chore: prep 0.0.1a4 release#10
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Code Review
This pull request increments the project version to 0.0.1a4 across the CHANGELOG, README, and pyproject.toml files. It also introduces GitHub configuration files, including a CODEOWNERS file and issue templates for bug reports and feature requests. One review comment suggests updating the version example in the bug report template to align with the new release version.
| --- | ||
|
|
||
| **Adapter**: (e.g., Slack, Discord, Teams) | ||
| **Version**: (e.g., 0.0.1a3) |
Contributor
There was a problem hiding this comment.
This was referenced May 8, 2026
patrick-chinchill
added a commit
that referenced
this pull request
May 28, 2026
Ports vercel/chat#391 — adds chat.get_user(adapter, user_id) and per-adapter get_user implementations across all 8 platforms. - Chat.get_user(adapter: str | Adapter, user_id: str) -> User | None resolves string adapter names through registered adapters - Adapter Protocol gains async def get_user(user_id: str) -> User | None - User extended with optional email, display_name, avatar_url - Per-adapter implementations: Slack users.info, Discord GET /users/{id}, Google Chat users.get, GitHub GET /users/{login}, Linear GraphQL user(id:), Teams Graph /users/{aadObjectId} (uses #85's AAD cache), Telegram getChat (best-effort), WhatsApp (Cloud API has no separate lookup) - Slack get_user awaits _resolve_token_async() so it works under callable bot_token resolvers (#87) when called from background contexts (cron, etc.) - Lazy imports of platform SDKs inside each method (hazard #10) - Resolved merge conflicts with #85/#86/#87/#88/#89 — all surface areas coexist 26 new tests in test_get_user_adapters.py + 3 in test_chat_faithful.py.
patrick-chinchill
added a commit
that referenced
this pull request
Jun 18, 2026
* feat(slack): expose web_client property on SlackAdapter (#98) Port the Slack adapter's direct WebClient access from upstream vercel/chat (commits 8366b8b / fdebde7 / 2f108bd, PRs #471/#476/#478). - Add ``SlackAdapter.web_client``: a synchronous ``slack_sdk.WebClient`` bound to the current request-context token (multi-workspace) or the configured default token (single-workspace). Token resolution uses the existing 3-level resolver via ``_get_token()``: ContextVar token > static ``bot_token`` config > ``AuthenticationError`` (no ``or`` fallbacks). - Add ``_get_web_client_for_token`` mirroring upstream's ``getClientForToken`` — one cached ``WebClient`` per distinct token. Kept separate from the async ``_client_cache`` (``AsyncWebClient``). ``slack_sdk`` import stays deferred (optional dependency, hazard #10). - Add deprecated ``client`` property alias delegating to ``web_client`` (one-release deprecation; emits ``DeprecationWarning``). Tests (tests/test_slack_web_client.py) mirror upstream's "webClient getter" block: single-tenant binding + per-token caching identity, multi-tenant ContextVar resolution under ``with_bot_token``, no-context and unresolved-async-resolver -> ``AuthenticationError``, and the deprecated alias returning the same object plus emitting the warning. https://claude.ai/code/session_01FyMxQn2BEAzmwKS1GZczKj * fix(slack): evict web_client cache on invalidation + clarify caching test (review) Two review follow-ups on the web_client port: - Gemini: `_invalidate_client` cleared only the async `_client_cache`, leaving stale/revoked synchronous `WebClient` instances in `_web_client_cache` on token revocation / auth-error eviction. Pop the token from both caches. New `test_invalidate_client_clears_web_client_cache` is load-bearing. - github-code-quality: `assert adapter.web_client is adapter.web_client` tripped "comparison of identical values". The test is a genuine caching check (the property is invoked twice), but binding each access to a name makes that intent explicit and silences the false-positive. https://claude.ai/code/session_01FyMxQn2BEAzmwKS1GZczKj * fix(slack): invoke sync token resolvers in web_client / _get_token (codex review) The sync ``_get_token`` path only handled the static-string and primed cache cases — a sync ``bot_token`` callable (used e.g. for secret rotation or lazy load from a sync source) raised ``AuthenticationError`` from ``web_client`` outside any webhook / ContextVar scope until an async path had primed the cache. Proactive sends from single-workspace apps using a sync resolver therefore failed. Detect the sync-resolver case via ``inspect.iscoroutinefunction``, invoke the callable, validate the result, and prime ``_default_bot_token_cache`` with the same semantics the async ``_resolve_default_token`` path uses. Async resolvers still raise from the sync property (cannot be awaited). Defensive check for sync callables that *return* a coroutine (rare but real: ``lambda: some_async_fn()``) — refuse to cache the coroutine. The two existing tests that asserted the previous deficient behavior (sync resolver raising before resolution) are updated to assert the new correct behavior; the cache-refresh regression test switches to an async resolver so its sanity precondition still holds. * fix(slack): close orphan coroutine before raising awaitable-resolver error (audit) The defensive `inspect.isawaitable(resolved)` branch in `_get_token`'s sync-callable handler raised AuthenticationError but never closed the coroutine the resolver returned. Callers saw a noisy `RuntimeWarning: coroutine was never awaited` on every triggering call. Close the awaitable via its `close()` method (Coroutine protocol) before raising. The existing regression test `test_sync_callable_returning_coroutine_raises` is strengthened to capture warnings and assert none of "never awaited" kind leaked — confirmed load-bearing under `pytest -W error::RuntimeWarning`. https://claude.ai/code/session_01FyMxQn2BEAzmwKS1GZczKj * fix(slack): honor bot_token rotation contract in sync _get_token + invalidation Addresses two P2 review findings on PR #127: **Codex P2 — sync resolver rotation broken** The previous sync-callable branch in ``_get_token`` cached the first resolved value in ``_default_bot_token_cache`` and the cache-first early-return prevented re-invocation, freezing rotating resolvers (e.g., secret-manager-backed). The contract on ``SlackAdapterConfig.bot_token`` says callable resolvers are "called on each use to support rotation." Track ``_is_dynamic_bot_token`` at construction time. In ``_get_token``, sync dynamic resolvers now invoke fresh on every call and never write the process-wide cache. Static-string configs keep their cache fast path (nothing to rotate). Async resolvers still require a webhook / ``current_token_async`` entry to be awaited. The previously-added test ``test_sync_current_token_with_sync_resolver_invokes_resolver`` asserted the cache was primed — flipped to assert the inverse, with a cross-reference to the dedicated rotation pin in ``test_sync_callable_invoked_fresh_each_access``. **CodeRabbit P2 — _invalidate_client retained revoked tokens** ``_invalidate_client(token)`` evicted the WebClient and AsyncWebClient caches but left ``_default_bot_token_cache`` / ``_resolved_default_token`` holding the revoked value, so the next ``_get_token`` returned the same token and the adapter just rebuilt clients around it. Now clears the resolved-token caches for dynamic-resolver configs so the next access re-invokes the resolver. Guarded on ``_is_dynamic_bot_token`` so static-string configs retain their cache (no refresh path — clearing would only make subsequent sync access raise with no way to recover). Tests: rewrote the caching test to assert rotation (resolver invoked fresh on every access, cache stays None); added invalidation tests covering dynamic-resolver clearing, ContextVar clearing, static-string no-op, and token-mismatch no-op. Full suite green (4067 passed) under ``-W error::RuntimeWarning``. https://claude.ai/code/session_01FyMxQn2BEAzmwKS1GZczKj * chore(tests): address CodeRabbit duplicate-test + iter-StopIteration findings CodeRabbit review on the latest #127 HEAD surfaced two test-quality issues: 1. ``TestWebClientAsyncResolver.test_unresolved_async_resolver_raises`` duplicated ``TestWebClientSyncResolver.test_async_callable_in_sync_context_raises`` (same async-resolver-in-sync-context path, but the latter is stronger — it also validates the error message wording). Removed the redundant wrapper class to honor this repo's "no duplicate tests" CLAUDE.md rule. 2. Rotation pin used ``tokens = iter(["xoxb-sync-1", ...])`` which would ``StopIteration`` if the test grew to a 4th access. Switched to ``f"xoxb-sync-{calls['n']}"`` so the resolver scales with call count; existing assertions on the literal values still hold. 68 tests still pass under ``pytest -W error::RuntimeWarning``. https://claude.ai/code/session_01FyMxQn2BEAzmwKS1GZczKj --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Final cosmetic fixes before going public.