fix(acp): allow API-key based auth to bypass forced OAuth login - #2185
fix(acp): allow API-key based auth to bypass forced OAuth login#2185yogaxu wants to merge 1 commit into
Conversation
When using ACP with IDE clients (e.g., JetBrains), the server used to force OAuth login even when users had already configured providers with api_key in config.toml. This caused an unavoidable 'Login with Kimi account' dialog in the IDE. Changes: - initialize(): dynamically set auth_methods to empty when the user already has API-key based auth configured, preventing proactive auth UI popups from ACP clients. - _check_auth(): fallback to check config.providers for api_key when OAuth token is unavailable, instead of unconditionally raising AUTH_REQUIRED. Fixes the scenario where terminal-mode kimi works fine with api_key, but ACP mode (kimi acp) incorrectly demands OAuth login.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5d6e432fa1
ℹ️ 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".
| if has_api_key or self._check_token_usable() is None: | ||
| self._auth_methods = [] |
There was a problem hiding this comment.
Keep login method cached for future auth failures
Avoid clearing self._auth_methods in initialize when auth currently looks usable. _check_auth() later builds its AUTH_REQUIRED payload from this cached list, so if the token expires (or API-key config is removed) after initialization, the server will return AUTH_REQUIRED with an empty authMethods array and clients lose the terminal login action (kimi login) needed to recover.
Useful? React with 👍 / 👎.
| if has_api_key or self._check_token_usable() is None: | ||
| self._auth_methods = [] |
There was a problem hiding this comment.
🟡 AUTH_REQUIRED error raised with empty authMethods when token expires mid-session
When the OAuth token is valid at initialize time, self._auth_methods is set to [] (line 84). If the token later expires (no refresh token) and the user has no API key, _check_auth (line 137) falls through to building auth_methods_data from self._auth_methods which is [], and raises auth_required({"authMethods": []}) at line 166. The client receives an AUTH_REQUIRED error but with no auth methods to present to the user, leaving them stuck with no way to re-authenticate. Before this PR, self._auth_methods was always populated with the login method, so the client always received actionable auth instructions.
Prompt for agents
The problem is that `self._auth_methods` is conditionally cleared in `initialize()` based on point-in-time auth state, but `_check_auth()` later depends on `self._auth_methods` to construct a useful AUTH_REQUIRED error. When the token was valid at init but expires later (with no refresh token and no API key), the AUTH_REQUIRED error is raised with an empty authMethods list.
Two possible approaches:
1. Always populate `self._auth_methods` with the login method (as it was before), but only include it in the `InitializeResponse.auth_methods` conditionally. This way the cached data is always available for `_check_auth` error construction.
2. In `_check_auth`, construct the auth methods on-the-fly (using the same terminal-auth data) rather than relying on the cached `self._auth_methods` list.
Approach 1 is the simplest — decouple what's advertised in the InitializeResponse from what's used internally for error reporting. The relevant code is in `src/kimi_cli/acp/server.py`, specifically the `initialize` method (lines 76-105) and `_check_auth` method (lines 137-166).
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5d6e432fa1
ℹ️ 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".
| if has_api_key or self._check_token_usable() is None: | ||
| self._auth_methods = [] |
There was a problem hiding this comment.
Preserve login method for later AUTH_REQUIRED responses
initialize() clears self._auth_methods whenever the OAuth token is usable, but _check_auth() later derives the AUTH_REQUIRED payload from this cached list. If a long-lived ACP server starts while the token is valid and the token later expires without a refresh token, new_session/load_session will raise auth_required with an empty authMethods list, so clients lose the terminal-login metadata needed to guide re-authentication.
Useful? React with 👍 / 👎.
| has_api_key = any( | ||
| provider.api_key and provider.api_key.get_secret_value() | ||
| for provider in config.providers.values() |
There was a problem hiding this comment.
Restrict API-key bypass to active/default provider
_check_auth() currently treats the presence of any provider API key as authenticated, regardless of which provider the session will actually use. In multi-provider configs, an unrelated API key can bypass auth even when the default model is on an OAuth provider with no usable token, causing session creation to pass and then fail at prompt time with 401/internal errors instead of returning a clear AUTH_REQUIRED flow.
Useful? React with 👍 / 👎.
Problem
When using Kimi Code CLI via ACP (e.g., JetBrains IDE), the server forces OAuth authentication even when the user has already configured a provider with
api_keyinconfig.toml.In the terminal,
kimiworks fine because it directly uses the configured provider + API key. But through ACP (kimi acp), the IDE pops up a "Login with Kimi account" dialog with only a web/OAuth login option, leaving API-key users no way to proceed.Reproduction Steps
api_keyin~/.kimi/config.toml(do not runkimi login):kimi --prompt "hello"~/.jetbrains/acp.json):{ "agent_servers": { "Kimi Code CLI": { "command": "kimi", "args": ["acp"] } } }Root Cause
There are two places in
kimi_cli/acp/server.pythat together create this forced-login behavior:1.
_check_auth()only checks OAuth tokenIt completely ignores valid
api_keyconfigurations inconfig.providers.2.
initialize()unconditionally advertisesloginauth methodEven if the user has an API key, the ACP server tells the client during
initialize()that the only available auth method is OAuth login. Some ACP clients (e.g., JetBrains AI Assistant) proactively show an authentication UI whenauth_methodsis non-empty, before any session is created.Changes
initialize()— Dynamicauth_methodsauth_methodsis empty, preventing proactive auth UI popups._check_auth()— API-key fallbackapi_key.AUTH_REQUIRED.Relation to PR #1445
PR #1445 removes the
_check_auth()gate fromnew_sessionandload_session, which addresses part of this issue. However, it does not modifyinitialize(), so clients that react toauth_methodsmay still force a login prompt at connection time.This PR complements PR #1445 by also fixing the
initialize()side:auth_methodsadvertisement is accurate.Together they provide a complete fix for API-key-based ACP usage.
Compatibility
auth_methods=[]and_check_auth()passes.initialize()and session operations work seamlessly.loginauth method ininitialize()andAUTH_REQUIREDon session creation, preserving the existing onboarding flow.