Skip to content

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

Description

@omnilyra

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions