What version of Kimi Code is running?
0.22.0
Which open platform/subscription were you using?
open platform
Which model were you using?
kimi-k2.7-code
What platform is your computer?
Darwin 25.3.0 arm64 arm
What issue are you seeing?
When a user authenticates with an API key (open-platform path) instead of OAuth, the ACP adapter rejects every session/new (and session/load / session/resume / authenticate) with auth_required (-32000), even though the API key is valid and usable in the TUI. The initialize handshake succeeds (it carries no credentials), so a client sees: init OK → session/new auth failure.
What steps can reproduce the bug?
- Log in with an API key via the open-platform path (so config.providers[] = { type: "kimi", baseUrl, apiKey } is written, but no token is written to ~/.kimi-code/credentials/kimi-code.json).
- Start the ACP server: kimi acp.
- As a client, send initialize → succeeds, returns authMethods: [{ id: "login", type: "terminal", ... }].
- Send session/new → fails with JSON-RPC error code: -32000 ("Authentication required").
This reproduces against any ACP-compliant client (Zed, JetBrains, a raw JSON-RPC client). It is not client-specific.
What is the expected behavior?
If the user has a valid, non-empty apiKey configured for any provider, harnessIsAuthed() should report hasToken: true (or the gate should be skipped for API-key providers), so session/new succeeds.
Additional information
The session gate harnessIsAuthed() only inspects the OAuth token file; it has no awareness of API-key providers.
packages/acp-adapter/src/server.ts:
async function harnessIsAuthed(harness: KimiHarness): Promise<boolean> {
const status = await harness.auth.status();
return status.providers.some((entry) => entry.hasToken === true);
}
async newSession(params) {
if (!(await harnessIsAuthed(this.harness))) {
throw RequestError.authRequired(); // -32000
}
// ...
}
The chain KimiAuthFacade.status() → KimiOAuthToolkit.status() → managerFor(...).hasToken() → OAuthManager.loadState() → FileTokenStorage.load() reads only ~/.kimi-code/credentials/.json (default name kimi-code). managerFor unconditionally constructs an OAuthManager — there is no branch for API-key providers, and status() always resolves the managed:kimi-code slot.
Meanwhile, API-key login (applyOpenPlatformConfig in packages/oauth/src/open-platform.ts) writes:
config.providers[providerKey] = { type: "kimi", baseUrl: ..., apiKey: ... };
under a different provider key (e.g. moonshot-cn), to the config file only. It does not write a credentials file and does not set an oauth ref. Therefore hasToken() returns false, the gate fails, and session/new throws auth_required.
What version of Kimi Code is running?
0.22.0
Which open platform/subscription were you using?
open platform
Which model were you using?
kimi-k2.7-code
What platform is your computer?
Darwin 25.3.0 arm64 arm
What issue are you seeing?
When a user authenticates with an API key (open-platform path) instead of OAuth, the ACP adapter rejects every session/new (and session/load / session/resume / authenticate) with auth_required (-32000), even though the API key is valid and usable in the TUI. The initialize handshake succeeds (it carries no credentials), so a client sees: init OK → session/new auth failure.
What steps can reproduce the bug?
This reproduces against any ACP-compliant client (Zed, JetBrains, a raw JSON-RPC client). It is not client-specific.
What is the expected behavior?
If the user has a valid, non-empty apiKey configured for any provider, harnessIsAuthed() should report hasToken: true (or the gate should be skipped for API-key providers), so session/new succeeds.
Additional information
The session gate harnessIsAuthed() only inspects the OAuth token file; it has no awareness of API-key providers.
packages/acp-adapter/src/server.ts:
The chain KimiAuthFacade.status() → KimiOAuthToolkit.status() → managerFor(...).hasToken() → OAuthManager.loadState() → FileTokenStorage.load() reads only ~/.kimi-code/credentials/.json (default name kimi-code). managerFor unconditionally constructs an OAuthManager — there is no branch for API-key providers, and status() always resolves the managed:kimi-code slot.
Meanwhile, API-key login (applyOpenPlatformConfig in packages/oauth/src/open-platform.ts) writes:
under a different provider key (e.g. moonshot-cn), to the config file only. It does not write a credentials file and does not set an oauth ref. Therefore hasToken() returns false, the gate fails, and session/new throws auth_required.