fix(claude-sdk-oauth): resolve request auth from ambient Claude credentials - #836
Open
ismetanin wants to merge 1 commit into
Open
fix(claude-sdk-oauth): resolve request auth from ambient Claude credentials#836ismetanin wants to merge 1 commit into
ismetanin wants to merge 1 commit into
Conversation
…ntials
The provider registers only `oauth`, so `composeApiKeyAuth` gives it no
api-key auth. `resolveProviderAuth` reads ambient credentials exclusively
through `apiKey.resolve()`, so with nothing in auth.json it returns
undefined and every request fails with:
Provider is not configured: claude-sdk-oauth
Availability disagreed with resolution: `check()` accepts an environment
token or a logged-in Claude CLI, so the models are offered and selected —
including for session_title_generation, which fires on session start.
Users with a working `claude` login hit the error before typing anything,
and no amount of configuration helped, since only a stored credential was
ever consulted. The stream layer already supports this: `queryWithAuthLane`
has an "ambient" lane and `managedPool` defaults to it.
Let an extension OAuth config expose `resolveAmbient`. When a provider has
no key, headers or base but supplies one, compose ambient-only api-key auth
from it — no `login`, so the OAuth flow still owns login, and a stored
credential still wins. In claude-sdk-oauth this shares one predicate with
`check()`, so availability and resolution can no longer disagree.
Memoise the ambient probe (30s TTL, shared in-flight, errors uncached): it
spawns the Claude binary at ~200-650ms and now sits on the per-request path.
ismetanin
force-pushed
the
fix/claude-sdk-oauth-ambient-auth
branch
from
August 12, 2026 10:12
db436e9 to
17fa0ec
Compare
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.
Problem
On a machine with a logged-in Claude CLI but no
claude-sdk-oauthentry inauth.json, every request to the provider fails:session_title_generationfires on session start, so the error appears before the user types anything. No configuration helps, because only a stored credential is ever consulted.Reproduce with an empty
~/.senpi/auth.json,claude auth statusexiting 0, and anyclaude-sdk-oauthmodel selected.Root cause
A regression from 2acbb6e ("Require a real OAuth login for runtime availability"), which removed one line from the provider registration:
- apiKey: "claude-sdk-oauth-managed",That placeholder was the provider's only route to api-key auth.
resolveProviderAuth()reads ambient credentials exclusively throughprovider.auth.apiKey.resolve():With the placeholder gone the provider registers
oauthalone, andcomposeApiKeyAuthrefuses to give it api-key auth:Availability still passed, so the models stayed selectable:
Models.checkProviderAuth()falls back tooauth.check()with no credential, and that check accepts an env token or a logged-in CLI. Availability and resolution disagreed — the provider advertised models it could not authenticate.The stream layer was never the problem:
queryWithAuthLanehas always had anambientlane, andmanagedPoolselects it by default (settings.tokenInjection ?? "ambient").Fix
Give the extension a way to declare that it accepts ambient credentials, rather than reinstating a literal sentinel.
ExtensionOAuthConfiggains an additive optionalresolveAmbient().composeApiKeyAuthcomposes ambient-only api-key auth from it instead of returningundefined. It omitslogin, so the OAuth flow keeps ownership of login, and declines whenever a credential is passed, so a stored credential still wins.createOAuthConfigimplementsresolveAmbient(), sharing a singleambientAvailable()predicate withcheck()so the two cannot drift apart again.This does not restore the false availability 2acbb6e fixed. The removed literal reported configured unconditionally;
resolveAmbient()is gated on the same real probe ascheck(), so a logged-out machine still resolves toundefined. The test added by that commit (test/suite/claude-sdk-oauth-extension.test.ts) passes unchanged.availability.tsalso memoises the ambient probe (30s TTL, shared in-flight read, rejections uncached). It spawns the Claude binary at ~200-650ms and now sits on the per-request auth path rather than only on catalog refresh.changes.mdentries added undersrc/core/and the extension directory per the fork strategy.Tests
test/claude-sdk-oauth-ambient-resolve.test.tsdrives the real registration throughcomposeModelProvider()andresolveProviderAuth()against an empty credential store — it fails onmainwithundefinedand passes here:CLAUDE_CODE_OAUTH_TOKENwith nothing storedtest/claude-sdk-oauth-ambient-cache.test.tscovers the probe cache: TTL reuse, re-probe after expiry, concurrent in-flight sharing, and no caching of rejections.Verification
npm run checkpasses (biome, pinned-deps, ts-imports, shrinkwrap, install-lock, tsc, browser-smoke).claude-sdk-oauth/ auth-storage / provider / model-registry test files pass (435 tests).packages/coding-agentsuite shows no change againstmain: the same 14 files / 55 tests fail before and after, all from workspacedistnot being built in this environment (ERR_MODULE_NOT_FOUND: pi-ai/dist/index.js).🤖 Generated with Claude Code
Summary by cubic
Fixes failed requests for
claude-sdk-oauthwhen the Claude CLI is logged in but no credential is stored. Requests now use ambient credentials (env token or CLI) and no longer error on session start.resolveAmbient()to the OAuth config and updatedcomposeApiKeyAuthto build ambient-only API key auth when the provider supplies it. Stored credentials still win; login stays on OAuth.claude-sdk-oauth”.Written for commit 17fa0ec. Summary will update on new commits.