mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Fix Kimi usage credential lookup
This commit is contained in:
@@ -67,6 +67,8 @@ To add plan usage for a provider, add `packages/server/src/services/quota-fetche
|
||||
|
||||
Keep the protocol shape provider-agnostic. Do not add provider-specific renderers for new limit windows; labels and generic bars should carry the UI. API responses should be parsed and normalized with Zod inside the fetcher, while the protocol boundary stays strict so old/new client compatibility is explicit.
|
||||
|
||||
Kimi Code usage follows the CLI-managed credential file at `KIMI_CODE_HOME` or `~/.kimi-code/credentials/kimi-code.json`; do not probe the legacy `~/.kimi` path as the primary source for current Kimi Code installs.
|
||||
|
||||
---
|
||||
|
||||
## ACP Provider Checklist
|
||||
|
||||
@@ -88,13 +88,24 @@ export class KimiQuotaProvider implements ProviderUsageFetcher {
|
||||
}
|
||||
|
||||
private async readKimiToken(): Promise<string | null> {
|
||||
const path = join(homedir(), ".kimi", "credentials", "kimi-code.json");
|
||||
if (!existsSync(path)) return null;
|
||||
try {
|
||||
const credentials = KimiAuthSchema.parse(JSON.parse(await fs.readFile(path, "utf8")));
|
||||
return credentials.access_token ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
const paths = [
|
||||
join(
|
||||
process.env["KIMI_CODE_HOME"] || join(homedir(), ".kimi-code"),
|
||||
"credentials",
|
||||
"kimi-code.json",
|
||||
),
|
||||
join(homedir(), ".kimi", "credentials", "kimi-code.json"),
|
||||
];
|
||||
|
||||
for (const path of paths) {
|
||||
if (!existsSync(path)) continue;
|
||||
try {
|
||||
const credentials = KimiAuthSchema.parse(JSON.parse(await fs.readFile(path, "utf8")));
|
||||
if (credentials.access_token) return credentials.access_token;
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
@@ -36,6 +36,20 @@ function writeCodexAuth(dir: string, accessToken: string, refreshToken = "rt_cod
|
||||
);
|
||||
}
|
||||
|
||||
function writeKimiCredentials(dir: string, accessToken: string): void {
|
||||
mkdirSync(join(dir, "credentials"), { recursive: true });
|
||||
writeFileSync(
|
||||
join(dir, "credentials", "kimi-code.json"),
|
||||
JSON.stringify({
|
||||
access_token: accessToken,
|
||||
refresh_token: "rt_kimi",
|
||||
expires_at: 1_798_812_800,
|
||||
scope: "kimi-code",
|
||||
token_type: "Bearer",
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function makeClaudeResponse(
|
||||
overrides: Partial<{
|
||||
five_hour: { utilization: number | string; resets_at: string };
|
||||
@@ -299,6 +313,7 @@ describe("real provider usage fetchers", () => {
|
||||
"GROK_TOKEN",
|
||||
"KIMI_TOKEN",
|
||||
"KIMI_API_KEY",
|
||||
"KIMI_CODE_HOME",
|
||||
"CODEX_HOME",
|
||||
]) {
|
||||
delete process.env[key];
|
||||
@@ -694,4 +709,35 @@ describe("real provider usage fetchers", () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("fetches Kimi usage from the CLI credential home", async () => {
|
||||
writeKimiCredentials(join(homeDir, ".kimi-code"), "kimi_cli_token");
|
||||
fetchApi = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {
|
||||
expect(url.toString()).toBe("https://api.kimi.com/coding/v1/usages");
|
||||
expect((init?.headers as Record<string, string> | undefined)?.Authorization).toBe(
|
||||
"Bearer kimi_cli_token",
|
||||
);
|
||||
return jsonResponse({
|
||||
usage: {
|
||||
limit: "200",
|
||||
remaining: "150",
|
||||
resetTime: "2026-06-23T05:12:17Z",
|
||||
},
|
||||
});
|
||||
}) as unknown as typeof fetch;
|
||||
|
||||
const kimi = findProvider(await service().listUsage(), "kimi");
|
||||
|
||||
expect(kimi).toMatchObject({
|
||||
status: "available",
|
||||
windows: [
|
||||
expect.objectContaining({
|
||||
id: "coding_usage",
|
||||
usedPct: 25,
|
||||
remainingPct: 75,
|
||||
resetsAt: "2026-06-23T05:12:17Z",
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user