diff --git a/plugins/kimi-usage-source/server/usage.test.ts b/plugins/kimi-usage-source/server/usage.test.ts index 5c5783a4d5..9ed76b0493 100644 --- a/plugins/kimi-usage-source/server/usage.test.ts +++ b/plugins/kimi-usage-source/server/usage.test.ts @@ -215,6 +215,52 @@ describe("kimi usage source", () => { ]); }); + it("fetches global usage when an expired default-deployment login remains", async () => { + const kimiHome = join(homeDir, ".kimi-code"); + writeKimiCredentials(kimiHome, "expired_default", { expires_at: 1_700_000_000 }); + writeKimiCredentials(kimiHome, "live_global", { expires_at: 2_000_000_000 }, GLOBAL_SLOT); + const [account] = await discover(); + if (!account) throw new Error("No configured Kimi account"); + const requests: string[] = []; + + const report = await fetchUsage( + account.input as Parameters[0], + async (url, init) => { + requests.push(url.toString()); + expect(new Headers(init?.headers).get("Authorization")).toBe("Bearer live_global"); + return jsonResponse({ usage: { limit: "100", remaining: "60" } }); + }, + ); + + expect(requests).toEqual(["https://api.kimi.ai/coding/v1/usages"]); + expect(report).toMatchObject({ status: "available", windows: [{ usedPct: 40 }] }); + }); + + it("keeps KIMI_CODE_HOME ahead of a newer legacy-home login", async () => { + const selectedHome = join(homeDir, "selected-kimi"); + process.env.KIMI_CODE_HOME = selectedHome; + writeKimiCredentials( + selectedHome, + "selected_global_token", + { expires_at: 2_000_000_000 }, + GLOBAL_SLOT, + ); + writeKimiCredentials(join(homeDir, ".kimi"), "legacy_token", { expires_at: 2_000_000_100 }); + + const accounts = await discover(); + + expect(accounts).toEqual([ + { + key: "default", + input: { + store: "file", + locator: kimiCredentialPath(selectedHome, GLOBAL_SLOT), + baseUrl: "https://api.kimi.ai/coding/v1", + }, + }, + ]); + }); + it("asks the user to run kimi when the CLI token has expired", async () => { writeKimiCredentials(join(homeDir, ".kimi-code"), "kimi_cli_token", { expires_at: 1_700_000_000, diff --git a/plugins/kimi-usage-source/server/usage.ts b/plugins/kimi-usage-source/server/usage.ts index f002d032a9..3e2a07f914 100644 --- a/plugins/kimi-usage-source/server/usage.ts +++ b/plugins/kimi-usage-source/server/usage.ts @@ -331,9 +331,10 @@ export async function discover(): Promise { join(homedir(), ".kimi"), ]; // A login to another deployment leaves the old slot behind with a dead token. - // The CLI keeps refreshing the slot it uses, so the latest expiry wins. - let found: { input: UsageInput; expiresAt: number } | undefined; + // Within each home, prefer the latest expiry. Keep the configured home ahead + // of the legacy fallback, even if that fallback holds a newer token. for (const home of homes) { + let found: { input: UsageInput; expiresAt: number } | undefined; for (const deployment of KIMI_CODE_DEPLOYMENTS) { const input: UsageInput = { store: "file", @@ -345,6 +346,7 @@ export async function discover(): Promise { const expiresAt = credentials.expires_at ?? Number.POSITIVE_INFINITY; if (!found || expiresAt > found.expiresAt) found = { input, expiresAt }; } + if (found) return [{ key: "default", input: found.input }]; } - return found ? [{ key: "default", input: found.input }] : []; + return []; }