MoonshotAI / MoonshotAI/kimi-code
[ACP] API-key login does not satisfy the session auth gate — session/new always returns auth_required (-32000)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/acp-adapter/src/server.ts at harnessIsAuthed() and trace KimiAuthFacade.status() through packages/oauth to managerFor() and FileTokenStorage.load(). Compare that path with applyOpenPlatformConfig in packages/oauth/src/open-platform.ts, which stores API keys in config.providers. Done means a configured non-empty API key allows session/new and related session operations while OAuth authentication continues to work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, authentication, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100