Skip to content

fix(oauth): treat API-key providers as authed in ACP session gate#1331

Open
omnilyra wants to merge 3 commits into
MoonshotAI:mainfrom
omnilyra:fix/acp-api-key-auth-gate
Open

fix(oauth): treat API-key providers as authed in ACP session gate#1331
omnilyra wants to merge 3 commits into
MoonshotAI:mainfrom
omnilyra:fix/acp-api-key-auth-gate

Conversation

@omnilyra

@omnilyra omnilyra commented Jul 3, 2026

Copy link
Copy Markdown

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 (and session/load / session/resume) always returns auth_required (-32000), even though the API key is valid and works in the TUI. initialize still 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) writes apiKey into 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 gate harnessIsAuthed() checks harness.auth.status().providers.some(e => e.hasToken), but status() / hasToken() only inspect the OAuth token file (~/.kimi-code/credentials/kimi-code.json). So for API-key users hasToken is always false and the gate rejects every session.

What changed

KimiOAuthToolkit.status() now also enumerates providers from the config (via the existing configAdapter) and surfaces any provider with a non-empty apiKey as hasToken: true. The gate already treats any provider with hasToken as authed, so API-key users now pass.

This is a small, contained fix:

  • packages/oauth/src/toolkit.tsstatus() scans config.providers for non-empty apiKey entries and appends them to the returned providers[]. 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 as hasToken: true with no OAuth token present; (2) an empty apiKey (what the managed OAuth path writes) is not treated as an API-key provider.

Why this approach fits: the toolkit already holds configAdapter and resolveManagedAuth() already reads config.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, which applyManagedKimiCodeConfig provisions with apiKey: "".

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

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

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-bot

changeset-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 67247e0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/oauth/src/toolkit.ts Outdated
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.
@omnilyra

omnilyra commented Jul 3, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/oauth/src/toolkit.ts Outdated
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.
@omnilyra

omnilyra commented Jul 3, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread .changeset/acp-api-key-auth-gate.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ACP] API-key login does not satisfy the session auth gate — session/new always returns auth_required (-32000)

1 participant