fix(oauth): treat API-key providers as authed in ACP session gate#1331
fix(oauth): treat API-key providers as authed in ACP session gate#1331omnilyra wants to merge 3 commits into
Conversation
API-key login (open-platform path) writes apiKey into the config file but not the OAuth credentials file, so the ACP session auth gate only checked for an OAuth token and returned auth_required (-32000) for every session/new, session/load, and session/resume even with a valid key. initialize still succeeded (no credentials), so clients saw init OK followed by an auth failure. KimiOAuthToolkit.status() now also surfaces providers configured with a non-empty apiKey, so the gate treats API-key users as authed.
🦋 Changeset detectedLatest commit: 67247e0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 298388dead
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Move the API-key provider scan out of KimiOAuthToolkit.status() (which was wired to the strict readConfigFileForUpdate read path) and into KimiAuthFacade, which resolves the provider names via loadRuntimeConfigSafe —the same lenient loader resolveManagedAuth already uses for token/status resolution. status() now receives the resolved names as an apiKeyProviders option. This preserves the degraded-config contract: a broken unrelated section (e.g. an invalid [loop_control]) must not abort status resolution and regress OAuth-backed sessions that previously worked.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c787d70e55
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
When the requested provider is itself an API-key provider (e.g.
status('moonshot-cn') after an open-platform login), the OAuth probe
reports hasToken:false because no token file exists. Previously a second
duplicate entry with hasToken:true was appended, so callers reading
providers[0] or find() by name still saw the stale false.
Now the API-key check is folded into the primary entry: if the requested
name is in apiKeyProviders, hasToken is true without a duplicate. Other
API-key providers are still appended as before.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 67247e0e4d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Related Issue
Resolve #1330
Problem
API-key-only users cannot use ACP mode. When a user authenticates with an API key (open-platform path),
session/new(andsession/load/session/resume) always returnsauth_required(-32000), even though the API key is valid and works in the TUI.initializestill succeeds (it carries no credentials), so ACP clients see init OK followed by an auth failure. This reproduces against any ACP-compliant client (Zed, JetBrains, Paseo, raw JSON-RPC).Root cause: API-key login (
applyOpenPlatformConfig) writesapiKeyinto the config file under a platform-specific provider key (e.g.moonshot-cn), but writes no OAuth token to the credentials file. The ACP session gateharnessIsAuthed()checksharness.auth.status().providers.some(e => e.hasToken), butstatus()/hasToken()only inspect the OAuth token file (~/.kimi-code/credentials/kimi-code.json). So for API-key usershasTokenis alwaysfalseand the gate rejects every session.What changed
KimiOAuthToolkit.status()now also enumerates providers from the config (via the existingconfigAdapter) and surfaces any provider with a non-emptyapiKeyashasToken: true. The gate already treats any provider withhasTokenas authed, so API-key users now pass.This is a small, contained fix:
packages/oauth/src/toolkit.ts—status()scansconfig.providersfor non-emptyapiKeyentries and appends them to the returnedproviders[]. The OAuth slot check is unchanged; API-key entries are additive.packages/oauth/test/toolkit.test.ts— two cases added to the existing file: (1) an API-key provider is reported ashasToken: truewith no OAuth token present; (2) an emptyapiKey(what the managed OAuth path writes) is not treated as an API-key provider.Why this approach fits: the toolkit already holds
configAdapterandresolveManagedAuth()already readsconfig.providers, so no new plumbing is needed —status()just reuses the existing config access. A non-empty-string check correctly excludes the managed OAuth slot, whichapplyManagedKimiCodeConfigprovisions withapiKey: "".Note: a stale/invalid API key will pass the gate and the real failure surfaces at LLM call time — but this matches the existing OAuth behavior (an expired token also passes the gate and fails on use), so it is not a new failure mode.
Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.