@kenkaiiii/gg-core 5.20.5 → 5.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GMBEO4JX.js → chunk-TST5LJWL.js} +352 -275
- package/dist/chunk-TST5LJWL.js.map +1 -0
- package/dist/index.cjs +542 -371
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -4
- package/dist/index.d.ts +28 -4
- package/dist/index.js +97 -3
- package/dist/index.js.map +1 -1
- package/dist/model-registry.cjs +40 -20
- package/dist/model-registry.cjs.map +1 -1
- package/dist/model-registry.d.cts +14 -1
- package/dist/model-registry.d.ts +14 -1
- package/dist/model-registry.js +3 -1
- package/package.json +2 -2
- package/dist/chunk-GMBEO4JX.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
getClaudeCodeVersion: () => getClaudeCodeVersion,
|
|
52
52
|
getContextWindow: () => getContextWindow,
|
|
53
53
|
getDefaultModel: () => getDefaultModel,
|
|
54
|
+
getDefaultThinkingLevel: () => getDefaultThinkingLevel,
|
|
54
55
|
getFastModel: () => getFastModel,
|
|
55
56
|
getMaxThinkingLevel: () => getMaxThinkingLevel,
|
|
56
57
|
getModel: () => getModel,
|
|
@@ -73,6 +74,7 @@ __export(index_exports, {
|
|
|
73
74
|
loginKimi: () => loginKimi,
|
|
74
75
|
loginOpenAI: () => loginOpenAI,
|
|
75
76
|
openLog: () => openLog,
|
|
77
|
+
readStoredBaseUrlSync: () => readStoredBaseUrlSync,
|
|
76
78
|
refreshAnthropicToken: () => refreshAnthropicToken,
|
|
77
79
|
refreshGeminiToken: () => refreshGeminiToken,
|
|
78
80
|
refreshKimiToken: () => refreshKimiToken,
|
|
@@ -86,9 +88,12 @@ __export(index_exports, {
|
|
|
86
88
|
});
|
|
87
89
|
module.exports = __toCommonJS(index_exports);
|
|
88
90
|
|
|
89
|
-
// src/
|
|
90
|
-
var
|
|
91
|
-
var
|
|
91
|
+
// src/oauth/kimi.ts
|
|
92
|
+
var import_node_child_process = require("child_process");
|
|
93
|
+
var import_node_crypto = require("crypto");
|
|
94
|
+
var import_node_fs = require("fs");
|
|
95
|
+
var import_node_os2 = require("os");
|
|
96
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
92
97
|
|
|
93
98
|
// src/paths.ts
|
|
94
99
|
var import_node_path = __toESM(require("path"), 1);
|
|
@@ -115,8 +120,225 @@ function getAppPaths() {
|
|
|
115
120
|
};
|
|
116
121
|
}
|
|
117
122
|
|
|
123
|
+
// src/oauth/kimi.ts
|
|
124
|
+
var CLIENT_ID = "17e5f671-d194-4dfb-9706-5516cb48c098";
|
|
125
|
+
var DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
|
|
126
|
+
var DEFAULT_CODING_BASE_URL = "https://api.kimi.com/coding/v1";
|
|
127
|
+
var KIMI_PLATFORM = "kimi_code_cli";
|
|
128
|
+
var DEFAULT_KIMI_VERSION = "1.0.11";
|
|
129
|
+
var DEVICE_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
130
|
+
function oauthHost() {
|
|
131
|
+
const host = process.env.KIMI_CODE_OAUTH_HOST ?? process.env.KIMI_OAUTH_HOST ?? DEFAULT_OAUTH_HOST;
|
|
132
|
+
return host.replace(/\/+$/, "");
|
|
133
|
+
}
|
|
134
|
+
function kimiCodeBaseUrl() {
|
|
135
|
+
return (process.env.KIMI_CODE_BASE_URL ?? DEFAULT_CODING_BASE_URL).replace(/\/+$/, "");
|
|
136
|
+
}
|
|
137
|
+
function kimiVersion() {
|
|
138
|
+
const v = process.env.KIMI_CODE_VERSION ?? DEFAULT_KIMI_VERSION;
|
|
139
|
+
return asciiHeader(v, DEFAULT_KIMI_VERSION);
|
|
140
|
+
}
|
|
141
|
+
function asciiHeader(value, fallback = "unknown") {
|
|
142
|
+
const cleaned = value.replace(/[^\u0020-\u007E]/g, "").trim();
|
|
143
|
+
return cleaned.length > 0 ? cleaned : fallback;
|
|
144
|
+
}
|
|
145
|
+
function macOsProductVersion() {
|
|
146
|
+
try {
|
|
147
|
+
const version = (0, import_node_child_process.execFileSync)("/usr/bin/sw_vers", ["-productVersion"], {
|
|
148
|
+
encoding: "utf-8",
|
|
149
|
+
timeout: 1e3
|
|
150
|
+
}).trim();
|
|
151
|
+
return version.length > 0 ? version : void 0;
|
|
152
|
+
} catch {
|
|
153
|
+
return void 0;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function deviceModel() {
|
|
157
|
+
const os2 = (0, import_node_os2.type)();
|
|
158
|
+
const version = (0, import_node_os2.release)();
|
|
159
|
+
const osArch = (0, import_node_os2.arch)();
|
|
160
|
+
if (os2 === "Darwin") return `macOS ${macOsProductVersion() ?? version} ${osArch}`;
|
|
161
|
+
if (os2 === "Windows_NT") return `Windows ${version} ${osArch}`;
|
|
162
|
+
return `${os2} ${version} ${osArch}`.trim();
|
|
163
|
+
}
|
|
164
|
+
function deviceId() {
|
|
165
|
+
const idPath = import_node_path2.default.join(getAppPaths().agentDir, "kimi_device_id");
|
|
166
|
+
if ((0, import_node_fs.existsSync)(idPath)) {
|
|
167
|
+
try {
|
|
168
|
+
const text = (0, import_node_fs.readFileSync)(idPath, "utf-8").trim();
|
|
169
|
+
if (text.length > 0) return text;
|
|
170
|
+
} catch {
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const id = (0, import_node_crypto.randomUUID)();
|
|
174
|
+
try {
|
|
175
|
+
(0, import_node_fs.mkdirSync)(getAppPaths().agentDir, { recursive: true, mode: 448 });
|
|
176
|
+
(0, import_node_fs.writeFileSync)(idPath, id, { encoding: "utf-8", mode: 384 });
|
|
177
|
+
} catch {
|
|
178
|
+
}
|
|
179
|
+
return id;
|
|
180
|
+
}
|
|
181
|
+
function deviceHeaders() {
|
|
182
|
+
return {
|
|
183
|
+
"X-Msh-Platform": KIMI_PLATFORM,
|
|
184
|
+
"X-Msh-Version": kimiVersion(),
|
|
185
|
+
"X-Msh-Device-Name": asciiHeader((0, import_node_os2.hostname)()),
|
|
186
|
+
"X-Msh-Device-Model": asciiHeader(deviceModel()),
|
|
187
|
+
"X-Msh-Os-Version": asciiHeader((0, import_node_os2.release)()),
|
|
188
|
+
"X-Msh-Device-Id": deviceId()
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function kimiCodingHeaders() {
|
|
192
|
+
return {
|
|
193
|
+
"User-Agent": `kimi-code-cli/${kimiVersion()}`,
|
|
194
|
+
...deviceHeaders()
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function isKimiCodingEndpoint(baseUrl) {
|
|
198
|
+
if (typeof baseUrl !== "string" || baseUrl.length === 0) return false;
|
|
199
|
+
const normalized = baseUrl.replace(/\/+$/, "");
|
|
200
|
+
return normalized === kimiCodeBaseUrl() || /(^|\.)kimi\.com/i.test(normalized);
|
|
201
|
+
}
|
|
202
|
+
async function postForm(endpoint, params) {
|
|
203
|
+
const response = await fetch(`${oauthHost()}${endpoint}`, {
|
|
204
|
+
method: "POST",
|
|
205
|
+
headers: {
|
|
206
|
+
...deviceHeaders(),
|
|
207
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
208
|
+
Accept: "application/json"
|
|
209
|
+
},
|
|
210
|
+
body: new URLSearchParams(params).toString()
|
|
211
|
+
});
|
|
212
|
+
let data = {};
|
|
213
|
+
try {
|
|
214
|
+
const parsed = await response.json();
|
|
215
|
+
if (parsed && typeof parsed === "object") data = parsed;
|
|
216
|
+
} catch {
|
|
217
|
+
}
|
|
218
|
+
return { status: response.status, data };
|
|
219
|
+
}
|
|
220
|
+
function errorDetail(data) {
|
|
221
|
+
const desc = data.error_description ?? data.message ?? data.error;
|
|
222
|
+
return typeof desc === "string" && desc.length > 0 ? desc : "unknown error";
|
|
223
|
+
}
|
|
224
|
+
function credsFromTokenResponse(data, opts) {
|
|
225
|
+
const accessToken = data.access_token;
|
|
226
|
+
const responseRefreshToken = data.refresh_token;
|
|
227
|
+
const expiresIn = Number(data.expires_in);
|
|
228
|
+
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
229
|
+
throw new Error("Kimi OAuth response missing access_token.");
|
|
230
|
+
}
|
|
231
|
+
const refreshToken = typeof responseRefreshToken === "string" && responseRefreshToken.length > 0 ? responseRefreshToken : opts?.fallbackRefreshToken ?? "";
|
|
232
|
+
if (refreshToken.length === 0) {
|
|
233
|
+
throw new Error("Kimi OAuth response missing refresh_token.");
|
|
234
|
+
}
|
|
235
|
+
if (!Number.isFinite(expiresIn) || expiresIn <= 0) {
|
|
236
|
+
throw new Error("Kimi OAuth response missing or invalid expires_in.");
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
accessToken,
|
|
240
|
+
refreshToken,
|
|
241
|
+
expiresAt: Date.now() + expiresIn * 1e3,
|
|
242
|
+
baseUrl: kimiCodeBaseUrl()
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async function requestDeviceAuthorization() {
|
|
246
|
+
const { status, data } = await postForm("/api/oauth/device_authorization", {
|
|
247
|
+
client_id: CLIENT_ID
|
|
248
|
+
});
|
|
249
|
+
if (status !== 200) {
|
|
250
|
+
throw new Error(`Kimi device authorization failed (${status}): ${errorDetail(data)}`);
|
|
251
|
+
}
|
|
252
|
+
const userCode = data.user_code;
|
|
253
|
+
const deviceCode = data.device_code;
|
|
254
|
+
const verificationUriComplete = data.verification_uri_complete;
|
|
255
|
+
if (typeof userCode !== "string" || typeof deviceCode !== "string") {
|
|
256
|
+
throw new Error("Kimi device authorization response missing user_code/device_code.");
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
userCode,
|
|
260
|
+
deviceCode,
|
|
261
|
+
verificationUri: typeof data.verification_uri === "string" ? data.verification_uri : "",
|
|
262
|
+
verificationUriComplete: typeof verificationUriComplete === "string" ? verificationUriComplete : "",
|
|
263
|
+
interval: Number(data.interval ?? 5) || 5
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
async function pollDeviceToken(deviceCode) {
|
|
267
|
+
const { status, data } = await postForm("/api/oauth/token", {
|
|
268
|
+
client_id: CLIENT_ID,
|
|
269
|
+
device_code: deviceCode,
|
|
270
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
271
|
+
});
|
|
272
|
+
if (status === 200 && typeof data.access_token === "string") {
|
|
273
|
+
return { kind: "success", creds: credsFromTokenResponse(data) };
|
|
274
|
+
}
|
|
275
|
+
if (status >= 500) {
|
|
276
|
+
throw new Error(`Kimi token polling server error (${status}): ${errorDetail(data)}`);
|
|
277
|
+
}
|
|
278
|
+
const errorCode = typeof data.error === "string" ? data.error : "unknown_error";
|
|
279
|
+
switch (errorCode) {
|
|
280
|
+
case "authorization_pending":
|
|
281
|
+
return { kind: "pending" };
|
|
282
|
+
case "slow_down":
|
|
283
|
+
return { kind: "slow_down" };
|
|
284
|
+
case "expired_token":
|
|
285
|
+
return { kind: "expired" };
|
|
286
|
+
case "access_denied":
|
|
287
|
+
return { kind: "denied" };
|
|
288
|
+
default:
|
|
289
|
+
throw new Error(`Kimi token polling failed (${status}): ${errorDetail(data)}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function sleep(ms) {
|
|
293
|
+
return new Promise((resolve) => {
|
|
294
|
+
setTimeout(resolve, ms);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
async function loginKimi(callbacks) {
|
|
298
|
+
const auth = await requestDeviceAuthorization();
|
|
299
|
+
callbacks.onStatus(
|
|
300
|
+
`Visit ${auth.verificationUri || auth.verificationUriComplete} and enter code: ${auth.userCode}`
|
|
301
|
+
);
|
|
302
|
+
callbacks.onOpenUrl(auth.verificationUriComplete || auth.verificationUri);
|
|
303
|
+
callbacks.onStatus("Waiting for you to authorize in the browser...");
|
|
304
|
+
const deadline = Date.now() + DEVICE_TIMEOUT_MS;
|
|
305
|
+
let interval = Math.max(auth.interval, 1);
|
|
306
|
+
while (Date.now() < deadline) {
|
|
307
|
+
await sleep(interval * 1e3);
|
|
308
|
+
const result = await pollDeviceToken(auth.deviceCode);
|
|
309
|
+
if (result.kind === "success") return result.creds;
|
|
310
|
+
if (result.kind === "denied") {
|
|
311
|
+
throw new Error("Kimi authorization was denied.");
|
|
312
|
+
}
|
|
313
|
+
if (result.kind === "expired") {
|
|
314
|
+
throw new Error("Kimi device code expired. Please run login again.");
|
|
315
|
+
}
|
|
316
|
+
if (result.kind === "slow_down") {
|
|
317
|
+
interval += 5;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
throw new Error("Kimi login timed out. Please run login again.");
|
|
321
|
+
}
|
|
322
|
+
async function refreshKimiToken(refreshToken) {
|
|
323
|
+
const { status, data } = await postForm("/api/oauth/token", {
|
|
324
|
+
client_id: CLIENT_ID,
|
|
325
|
+
grant_type: "refresh_token",
|
|
326
|
+
refresh_token: refreshToken
|
|
327
|
+
});
|
|
328
|
+
if (status === 200 && typeof data.access_token === "string") {
|
|
329
|
+
return credsFromTokenResponse(data, { fallbackRefreshToken: refreshToken });
|
|
330
|
+
}
|
|
331
|
+
const errorCode = typeof data.error === "string" ? data.error : "";
|
|
332
|
+
throw new Error(`Kimi token refresh failed (${status}): ${errorCode || errorDetail(data)}`);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// src/auth-storage.ts
|
|
336
|
+
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
337
|
+
var import_node_fs3 = require("fs");
|
|
338
|
+
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
339
|
+
|
|
118
340
|
// src/oauth/anthropic.ts
|
|
119
|
-
var
|
|
341
|
+
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
120
342
|
|
|
121
343
|
// src/oauth/pkce.ts
|
|
122
344
|
function base64urlEncode(bytes) {
|
|
@@ -138,12 +360,12 @@ async function generatePKCE() {
|
|
|
138
360
|
|
|
139
361
|
// src/claude-code-version.ts
|
|
140
362
|
var import_promises = __toESM(require("fs/promises"), 1);
|
|
141
|
-
var
|
|
363
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
142
364
|
|
|
143
365
|
// src/logger.ts
|
|
144
|
-
var
|
|
145
|
-
var
|
|
146
|
-
var
|
|
366
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
367
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
368
|
+
var import_node_crypto2 = require("crypto");
|
|
147
369
|
var import_gg_ai = require("@kenkaiiii/gg-ai");
|
|
148
370
|
var MAX_BYTES = 10 * 1024 * 1024;
|
|
149
371
|
var fd = null;
|
|
@@ -155,14 +377,14 @@ var cleanups = [];
|
|
|
155
377
|
var exactSecrets = [];
|
|
156
378
|
function rotateIfNeeded(filePath) {
|
|
157
379
|
try {
|
|
158
|
-
const st =
|
|
380
|
+
const st = import_node_fs2.default.statSync(filePath);
|
|
159
381
|
if (st.size < MAX_BYTES) return;
|
|
160
382
|
const rotated = `${filePath}.1`;
|
|
161
383
|
try {
|
|
162
|
-
|
|
384
|
+
import_node_fs2.default.unlinkSync(rotated);
|
|
163
385
|
} catch {
|
|
164
386
|
}
|
|
165
|
-
|
|
387
|
+
import_node_fs2.default.renameSync(filePath, rotated);
|
|
166
388
|
} catch {
|
|
167
389
|
}
|
|
168
390
|
}
|
|
@@ -171,32 +393,32 @@ function openLog(filePath, name) {
|
|
|
171
393
|
appName = name;
|
|
172
394
|
exactSecrets = (0, import_gg_ai.environmentSecrets)(process.env);
|
|
173
395
|
try {
|
|
174
|
-
|
|
396
|
+
import_node_fs2.default.mkdirSync(import_node_path3.default.dirname(filePath), { recursive: true, mode: 448 });
|
|
175
397
|
} catch {
|
|
176
398
|
}
|
|
177
399
|
rotateIfNeeded(filePath);
|
|
178
400
|
try {
|
|
179
|
-
fd =
|
|
401
|
+
fd = import_node_fs2.default.openSync(filePath, "a");
|
|
180
402
|
} catch {
|
|
181
403
|
fd = null;
|
|
182
404
|
bytesWritten = 0;
|
|
183
405
|
return false;
|
|
184
406
|
}
|
|
185
407
|
try {
|
|
186
|
-
bytesWritten =
|
|
408
|
+
bytesWritten = import_node_fs2.default.fstatSync(fd).size;
|
|
187
409
|
} catch {
|
|
188
410
|
try {
|
|
189
|
-
|
|
411
|
+
import_node_fs2.default.closeSync(fd);
|
|
190
412
|
} catch {
|
|
191
413
|
}
|
|
192
414
|
fd = null;
|
|
193
415
|
bytesWritten = 0;
|
|
194
416
|
return false;
|
|
195
417
|
}
|
|
196
|
-
sessionId = (0,
|
|
418
|
+
sessionId = (0, import_node_crypto2.randomBytes)(4).toString("hex");
|
|
197
419
|
try {
|
|
198
420
|
if (bytesWritten < MAX_BYTES) {
|
|
199
|
-
bytesWritten +=
|
|
421
|
+
bytesWritten += import_node_fs2.default.writeSync(fd, "\n");
|
|
200
422
|
}
|
|
201
423
|
} catch {
|
|
202
424
|
}
|
|
@@ -229,9 +451,9 @@ function log(level, category, message, data) {
|
|
|
229
451
|
`;
|
|
230
452
|
try {
|
|
231
453
|
if (bytesWritten + Buffer.byteLength(capLine) <= MAX_BYTES) {
|
|
232
|
-
bytesWritten +=
|
|
454
|
+
bytesWritten += import_node_fs2.default.writeSync(fd, capLine);
|
|
233
455
|
}
|
|
234
|
-
|
|
456
|
+
import_node_fs2.default.closeSync(fd);
|
|
235
457
|
} catch {
|
|
236
458
|
}
|
|
237
459
|
fd = null;
|
|
@@ -239,7 +461,7 @@ function log(level, category, message, data) {
|
|
|
239
461
|
return;
|
|
240
462
|
}
|
|
241
463
|
try {
|
|
242
|
-
bytesWritten +=
|
|
464
|
+
bytesWritten += import_node_fs2.default.writeSync(fd, line);
|
|
243
465
|
} catch {
|
|
244
466
|
}
|
|
245
467
|
}
|
|
@@ -250,7 +472,7 @@ function closeLogger(opts) {
|
|
|
250
472
|
if (fd !== null) {
|
|
251
473
|
if (opts?.shutdownLine !== false) log("INFO", "shutdown", `${appName} shutting down`);
|
|
252
474
|
try {
|
|
253
|
-
if (fd !== null)
|
|
475
|
+
if (fd !== null) import_node_fs2.default.closeSync(fd);
|
|
254
476
|
} catch {
|
|
255
477
|
}
|
|
256
478
|
}
|
|
@@ -270,7 +492,7 @@ var FALLBACK_VERSION = "2.1.88";
|
|
|
270
492
|
var memoryCache = null;
|
|
271
493
|
var inflight = null;
|
|
272
494
|
function cachePath() {
|
|
273
|
-
return
|
|
495
|
+
return import_node_path4.default.join(getAppPaths().agentDir, "claude-code-version.json");
|
|
274
496
|
}
|
|
275
497
|
async function readDiskCache() {
|
|
276
498
|
try {
|
|
@@ -352,7 +574,7 @@ async function getClaudeCliUserAgent() {
|
|
|
352
574
|
}
|
|
353
575
|
|
|
354
576
|
// src/oauth/anthropic.ts
|
|
355
|
-
var
|
|
577
|
+
var CLIENT_ID2 = atob("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
|
|
356
578
|
var AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
|
|
357
579
|
var TOKEN_URLS = [
|
|
358
580
|
"https://platform.claude.com/v1/oauth/token",
|
|
@@ -396,10 +618,10 @@ function toCredentials(data) {
|
|
|
396
618
|
}
|
|
397
619
|
async function loginAnthropic(callbacks) {
|
|
398
620
|
const { verifier, challenge } = await generatePKCE();
|
|
399
|
-
const state =
|
|
621
|
+
const state = import_node_crypto3.default.randomBytes(16).toString("hex");
|
|
400
622
|
const params = new URLSearchParams({
|
|
401
623
|
code: "true",
|
|
402
|
-
client_id:
|
|
624
|
+
client_id: CLIENT_ID2,
|
|
403
625
|
response_type: "code",
|
|
404
626
|
redirect_uri: REDIRECT_URI,
|
|
405
627
|
scope: SCOPES,
|
|
@@ -420,7 +642,7 @@ async function exchangeAnthropicCode(code, state, verifier) {
|
|
|
420
642
|
const data = await postTokenRequest(
|
|
421
643
|
{
|
|
422
644
|
grant_type: "authorization_code",
|
|
423
|
-
client_id:
|
|
645
|
+
client_id: CLIENT_ID2,
|
|
424
646
|
code,
|
|
425
647
|
state,
|
|
426
648
|
redirect_uri: REDIRECT_URI,
|
|
@@ -434,7 +656,7 @@ async function refreshAnthropicToken(refreshToken) {
|
|
|
434
656
|
const data = await postTokenRequest(
|
|
435
657
|
{
|
|
436
658
|
grant_type: "refresh_token",
|
|
437
|
-
client_id:
|
|
659
|
+
client_id: CLIENT_ID2,
|
|
438
660
|
refresh_token: refreshToken
|
|
439
661
|
},
|
|
440
662
|
"token refresh"
|
|
@@ -444,8 +666,8 @@ async function refreshAnthropicToken(refreshToken) {
|
|
|
444
666
|
|
|
445
667
|
// src/oauth/openai.ts
|
|
446
668
|
var import_node_http = __toESM(require("http"), 1);
|
|
447
|
-
var
|
|
448
|
-
var
|
|
669
|
+
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
670
|
+
var CLIENT_ID3 = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
449
671
|
var AUTHORIZE_URL2 = "https://auth.openai.com/oauth/authorize";
|
|
450
672
|
var TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
451
673
|
var REDIRECT_URI2 = "http://localhost:1455/auth/callback";
|
|
@@ -453,10 +675,10 @@ var SCOPE = "openid profile email offline_access api.connectors.read api.connect
|
|
|
453
675
|
var JWT_CLAIM_PATH = "https://api.openai.com/auth";
|
|
454
676
|
async function loginOpenAI(callbacks) {
|
|
455
677
|
const { verifier, challenge } = await generatePKCE();
|
|
456
|
-
const state =
|
|
678
|
+
const state = import_node_crypto4.default.randomBytes(16).toString("hex");
|
|
457
679
|
const url = new URL(AUTHORIZE_URL2);
|
|
458
680
|
url.searchParams.set("response_type", "code");
|
|
459
|
-
url.searchParams.set("client_id",
|
|
681
|
+
url.searchParams.set("client_id", CLIENT_ID3);
|
|
460
682
|
url.searchParams.set("redirect_uri", REDIRECT_URI2);
|
|
461
683
|
url.searchParams.set("scope", SCOPE);
|
|
462
684
|
url.searchParams.set("code_challenge", challenge);
|
|
@@ -577,7 +799,7 @@ async function exchangeOpenAICode(code, verifier) {
|
|
|
577
799
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
578
800
|
body: new URLSearchParams({
|
|
579
801
|
grant_type: "authorization_code",
|
|
580
|
-
client_id:
|
|
802
|
+
client_id: CLIENT_ID3,
|
|
581
803
|
code,
|
|
582
804
|
redirect_uri: REDIRECT_URI2,
|
|
583
805
|
code_verifier: verifier
|
|
@@ -601,7 +823,7 @@ async function refreshOpenAIToken(refreshToken) {
|
|
|
601
823
|
body: new URLSearchParams({
|
|
602
824
|
grant_type: "refresh_token",
|
|
603
825
|
refresh_token: refreshToken,
|
|
604
|
-
client_id:
|
|
826
|
+
client_id: CLIENT_ID3
|
|
605
827
|
})
|
|
606
828
|
});
|
|
607
829
|
if (!response.ok) {
|
|
@@ -623,7 +845,7 @@ async function refreshOpenAIToken(refreshToken) {
|
|
|
623
845
|
|
|
624
846
|
// src/oauth/gemini.ts
|
|
625
847
|
var import_node_http2 = __toESM(require("http"), 1);
|
|
626
|
-
var
|
|
848
|
+
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
627
849
|
var CLIENT_ID_ENV = "GGCODER_GEMINI_OAUTH_CLIENT_ID";
|
|
628
850
|
var CLIENT_SECRET_ENV = "GGCODER_GEMINI_OAUTH_CLIENT_SECRET";
|
|
629
851
|
var DEFAULT_CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com";
|
|
@@ -657,7 +879,7 @@ var CodeAssistHttpError = class extends Error {
|
|
|
657
879
|
async function loginGemini(callbacks) {
|
|
658
880
|
const { clientId, clientSecret } = getGeminiOAuthClientCredentials();
|
|
659
881
|
const { verifier, challenge } = await generatePKCE();
|
|
660
|
-
const state =
|
|
882
|
+
const state = import_node_crypto5.default.randomBytes(32).toString("hex");
|
|
661
883
|
const redirectUri = await getLoopbackRedirectUri();
|
|
662
884
|
const url = new URL(AUTHORIZE_URL3);
|
|
663
885
|
url.searchParams.set("response_type", "code");
|
|
@@ -897,308 +1119,91 @@ async function loadCodeAssist(accessToken, envProject, metadata) {
|
|
|
897
1119
|
throw err;
|
|
898
1120
|
}
|
|
899
1121
|
}
|
|
900
|
-
function getValidationRequiredTier(response) {
|
|
901
|
-
return response.ineligibleTiers?.find(
|
|
902
|
-
(tier) => tier.reasonCode === VALIDATION_REQUIRED_REASON && typeof tier.validationUrl === "string"
|
|
903
|
-
);
|
|
904
|
-
}
|
|
905
|
-
function getOnboardTier(response) {
|
|
906
|
-
const defaultTier = response.allowedTiers?.find((tier) => tier.isDefault);
|
|
907
|
-
return defaultTier ?? { id: USER_TIER_LEGACY, name: "" };
|
|
908
|
-
}
|
|
909
|
-
function throwProjectError(response) {
|
|
910
|
-
const reasons = response.ineligibleTiers?.map((tier) => tier.reasonMessage ?? tier.tierName).filter((reason) => Boolean(reason));
|
|
911
|
-
if (reasons && reasons.length > 0) {
|
|
912
|
-
throw new Error(`Gemini Code Assist setup failed: ${reasons.join(", ")}`);
|
|
913
|
-
}
|
|
914
|
-
throw new Error(
|
|
915
|
-
"Gemini requires a Google Cloud project for this account. Set GOOGLE_CLOUD_PROJECT and try again."
|
|
916
|
-
);
|
|
917
|
-
}
|
|
918
|
-
async function codeAssistPost(accessToken, method, body) {
|
|
919
|
-
let lastError;
|
|
920
|
-
for (let attempt = 0; attempt <= CODE_ASSIST_POST_RETRIES; attempt++) {
|
|
921
|
-
try {
|
|
922
|
-
return await codeAssistRequest(getCodeAssistMethodUrl(method), accessToken, method, {
|
|
923
|
-
method: "POST",
|
|
924
|
-
body: JSON.stringify(body)
|
|
925
|
-
});
|
|
926
|
-
} catch (err) {
|
|
927
|
-
if (!(err instanceof CodeAssistHttpError) || attempt === CODE_ASSIST_POST_RETRIES || !shouldRetryCodeAssistStatus(err.status)) {
|
|
928
|
-
throw err;
|
|
929
|
-
}
|
|
930
|
-
lastError = err;
|
|
931
|
-
}
|
|
932
|
-
await new Promise((resolve) => setTimeout(resolve, CODE_ASSIST_POST_RETRY_DELAY_MS));
|
|
933
|
-
}
|
|
934
|
-
throw lastError ?? new Error(`Gemini Code Assist ${method} failed.`);
|
|
935
|
-
}
|
|
936
|
-
async function codeAssistGet(accessToken, operationName) {
|
|
937
|
-
return codeAssistRequest(getCodeAssistOperationUrl(operationName), accessToken, "operation", {
|
|
938
|
-
method: "GET"
|
|
939
|
-
});
|
|
940
|
-
}
|
|
941
|
-
async function codeAssistRequest(url, accessToken, label, init) {
|
|
942
|
-
const response = await fetch(url, {
|
|
943
|
-
...init,
|
|
944
|
-
headers: codeAssistHeaders(accessToken)
|
|
945
|
-
});
|
|
946
|
-
if (!response.ok) {
|
|
947
|
-
const text = await response.text();
|
|
948
|
-
throw new CodeAssistHttpError(label, response.status, text);
|
|
949
|
-
}
|
|
950
|
-
return await response.json();
|
|
951
|
-
}
|
|
952
|
-
function getCodeAssistBaseUrl() {
|
|
953
|
-
const endpoint = process.env.CODE_ASSIST_ENDPOINT ?? CODE_ASSIST_BASE_URL;
|
|
954
|
-
const version = process.env.CODE_ASSIST_API_VERSION || CODE_ASSIST_API_VERSION;
|
|
955
|
-
return `${endpoint}/${version}`;
|
|
956
|
-
}
|
|
957
|
-
function getCodeAssistMethodUrl(method) {
|
|
958
|
-
return `${getCodeAssistBaseUrl()}:${method}`;
|
|
959
|
-
}
|
|
960
|
-
function getCodeAssistOperationUrl(operationName) {
|
|
961
|
-
return `${getCodeAssistBaseUrl()}/${operationName}`;
|
|
962
|
-
}
|
|
963
|
-
function shouldRetryCodeAssistStatus(status) {
|
|
964
|
-
return status === 429 || status === 499 || status >= 500 && status <= 599;
|
|
965
|
-
}
|
|
966
|
-
function isVpcScAffectedError(error) {
|
|
967
|
-
try {
|
|
968
|
-
const parsed = JSON.parse(error.body);
|
|
969
|
-
if (!parsed || typeof parsed !== "object" || !("error" in parsed)) return false;
|
|
970
|
-
const details = parsed.error?.details;
|
|
971
|
-
return Array.isArray(details) ? details.some(
|
|
972
|
-
(detail) => detail != null && typeof detail === "object" && "reason" in detail && detail.reason === VPC_SC_REASON
|
|
973
|
-
) : false;
|
|
974
|
-
} catch {
|
|
975
|
-
return false;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
function codeAssistHeaders(accessToken) {
|
|
979
|
-
return {
|
|
980
|
-
Authorization: `Bearer ${accessToken}`,
|
|
981
|
-
"Content-Type": "application/json",
|
|
982
|
-
"User-Agent": "google-gemini-cli",
|
|
983
|
-
"X-Goog-Api-Client": "gemini-cli/0.0.0"
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
// src/oauth/kimi.ts
|
|
988
|
-
var import_node_child_process = require("child_process");
|
|
989
|
-
var import_node_crypto5 = require("crypto");
|
|
990
|
-
var import_node_fs2 = require("fs");
|
|
991
|
-
var import_node_os2 = require("os");
|
|
992
|
-
var import_node_path4 = __toESM(require("path"), 1);
|
|
993
|
-
var CLIENT_ID3 = "17e5f671-d194-4dfb-9706-5516cb48c098";
|
|
994
|
-
var DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
|
|
995
|
-
var DEFAULT_CODING_BASE_URL = "https://api.kimi.com/coding/v1";
|
|
996
|
-
var KIMI_PLATFORM = "kimi_code_cli";
|
|
997
|
-
var DEFAULT_KIMI_VERSION = "1.0.11";
|
|
998
|
-
var DEVICE_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
999
|
-
function oauthHost() {
|
|
1000
|
-
const host = process.env.KIMI_CODE_OAUTH_HOST ?? process.env.KIMI_OAUTH_HOST ?? DEFAULT_OAUTH_HOST;
|
|
1001
|
-
return host.replace(/\/+$/, "");
|
|
1002
|
-
}
|
|
1003
|
-
function kimiCodeBaseUrl() {
|
|
1004
|
-
return (process.env.KIMI_CODE_BASE_URL ?? DEFAULT_CODING_BASE_URL).replace(/\/+$/, "");
|
|
1005
|
-
}
|
|
1006
|
-
function kimiVersion() {
|
|
1007
|
-
const v = process.env.KIMI_CODE_VERSION ?? DEFAULT_KIMI_VERSION;
|
|
1008
|
-
return asciiHeader(v, DEFAULT_KIMI_VERSION);
|
|
1009
|
-
}
|
|
1010
|
-
function asciiHeader(value, fallback = "unknown") {
|
|
1011
|
-
const cleaned = value.replace(/[^\u0020-\u007E]/g, "").trim();
|
|
1012
|
-
return cleaned.length > 0 ? cleaned : fallback;
|
|
1013
|
-
}
|
|
1014
|
-
function macOsProductVersion() {
|
|
1015
|
-
try {
|
|
1016
|
-
const version = (0, import_node_child_process.execFileSync)("/usr/bin/sw_vers", ["-productVersion"], {
|
|
1017
|
-
encoding: "utf-8",
|
|
1018
|
-
timeout: 1e3
|
|
1019
|
-
}).trim();
|
|
1020
|
-
return version.length > 0 ? version : void 0;
|
|
1021
|
-
} catch {
|
|
1022
|
-
return void 0;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
function deviceModel() {
|
|
1026
|
-
const os2 = (0, import_node_os2.type)();
|
|
1027
|
-
const version = (0, import_node_os2.release)();
|
|
1028
|
-
const osArch = (0, import_node_os2.arch)();
|
|
1029
|
-
if (os2 === "Darwin") return `macOS ${macOsProductVersion() ?? version} ${osArch}`;
|
|
1030
|
-
if (os2 === "Windows_NT") return `Windows ${version} ${osArch}`;
|
|
1031
|
-
return `${os2} ${version} ${osArch}`.trim();
|
|
1032
|
-
}
|
|
1033
|
-
function deviceId() {
|
|
1034
|
-
const idPath = import_node_path4.default.join(getAppPaths().agentDir, "kimi_device_id");
|
|
1035
|
-
if ((0, import_node_fs2.existsSync)(idPath)) {
|
|
1036
|
-
try {
|
|
1037
|
-
const text = (0, import_node_fs2.readFileSync)(idPath, "utf-8").trim();
|
|
1038
|
-
if (text.length > 0) return text;
|
|
1039
|
-
} catch {
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
const id = (0, import_node_crypto5.randomUUID)();
|
|
1043
|
-
try {
|
|
1044
|
-
(0, import_node_fs2.mkdirSync)(getAppPaths().agentDir, { recursive: true, mode: 448 });
|
|
1045
|
-
(0, import_node_fs2.writeFileSync)(idPath, id, { encoding: "utf-8", mode: 384 });
|
|
1046
|
-
} catch {
|
|
1047
|
-
}
|
|
1048
|
-
return id;
|
|
1049
|
-
}
|
|
1050
|
-
function deviceHeaders() {
|
|
1051
|
-
return {
|
|
1052
|
-
"X-Msh-Platform": KIMI_PLATFORM,
|
|
1053
|
-
"X-Msh-Version": kimiVersion(),
|
|
1054
|
-
"X-Msh-Device-Name": asciiHeader((0, import_node_os2.hostname)()),
|
|
1055
|
-
"X-Msh-Device-Model": asciiHeader(deviceModel()),
|
|
1056
|
-
"X-Msh-Os-Version": asciiHeader((0, import_node_os2.release)()),
|
|
1057
|
-
"X-Msh-Device-Id": deviceId()
|
|
1058
|
-
};
|
|
1059
|
-
}
|
|
1060
|
-
function kimiCodingHeaders() {
|
|
1061
|
-
return {
|
|
1062
|
-
"User-Agent": `kimi-code-cli/${kimiVersion()}`,
|
|
1063
|
-
...deviceHeaders()
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
function isKimiCodingEndpoint(baseUrl) {
|
|
1067
|
-
if (typeof baseUrl !== "string" || baseUrl.length === 0) return false;
|
|
1068
|
-
const normalized = baseUrl.replace(/\/+$/, "");
|
|
1069
|
-
return normalized === kimiCodeBaseUrl() || /(^|\.)kimi\.com/i.test(normalized);
|
|
1070
|
-
}
|
|
1071
|
-
async function postForm(endpoint, params) {
|
|
1072
|
-
const response = await fetch(`${oauthHost()}${endpoint}`, {
|
|
1073
|
-
method: "POST",
|
|
1074
|
-
headers: {
|
|
1075
|
-
...deviceHeaders(),
|
|
1076
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
1077
|
-
Accept: "application/json"
|
|
1078
|
-
},
|
|
1079
|
-
body: new URLSearchParams(params).toString()
|
|
1080
|
-
});
|
|
1081
|
-
let data = {};
|
|
1082
|
-
try {
|
|
1083
|
-
const parsed = await response.json();
|
|
1084
|
-
if (parsed && typeof parsed === "object") data = parsed;
|
|
1085
|
-
} catch {
|
|
1086
|
-
}
|
|
1087
|
-
return { status: response.status, data };
|
|
1088
|
-
}
|
|
1089
|
-
function errorDetail(data) {
|
|
1090
|
-
const desc = data.error_description ?? data.message ?? data.error;
|
|
1091
|
-
return typeof desc === "string" && desc.length > 0 ? desc : "unknown error";
|
|
1122
|
+
function getValidationRequiredTier(response) {
|
|
1123
|
+
return response.ineligibleTiers?.find(
|
|
1124
|
+
(tier) => tier.reasonCode === VALIDATION_REQUIRED_REASON && typeof tier.validationUrl === "string"
|
|
1125
|
+
);
|
|
1092
1126
|
}
|
|
1093
|
-
function
|
|
1094
|
-
const
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
if (refreshToken.length === 0) {
|
|
1102
|
-
throw new Error("Kimi OAuth response missing refresh_token.");
|
|
1127
|
+
function getOnboardTier(response) {
|
|
1128
|
+
const defaultTier = response.allowedTiers?.find((tier) => tier.isDefault);
|
|
1129
|
+
return defaultTier ?? { id: USER_TIER_LEGACY, name: "" };
|
|
1130
|
+
}
|
|
1131
|
+
function throwProjectError(response) {
|
|
1132
|
+
const reasons = response.ineligibleTiers?.map((tier) => tier.reasonMessage ?? tier.tierName).filter((reason) => Boolean(reason));
|
|
1133
|
+
if (reasons && reasons.length > 0) {
|
|
1134
|
+
throw new Error(`Gemini Code Assist setup failed: ${reasons.join(", ")}`);
|
|
1103
1135
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1136
|
+
throw new Error(
|
|
1137
|
+
"Gemini requires a Google Cloud project for this account. Set GOOGLE_CLOUD_PROJECT and try again."
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
async function codeAssistPost(accessToken, method, body) {
|
|
1141
|
+
let lastError;
|
|
1142
|
+
for (let attempt = 0; attempt <= CODE_ASSIST_POST_RETRIES; attempt++) {
|
|
1143
|
+
try {
|
|
1144
|
+
return await codeAssistRequest(getCodeAssistMethodUrl(method), accessToken, method, {
|
|
1145
|
+
method: "POST",
|
|
1146
|
+
body: JSON.stringify(body)
|
|
1147
|
+
});
|
|
1148
|
+
} catch (err) {
|
|
1149
|
+
if (!(err instanceof CodeAssistHttpError) || attempt === CODE_ASSIST_POST_RETRIES || !shouldRetryCodeAssistStatus(err.status)) {
|
|
1150
|
+
throw err;
|
|
1151
|
+
}
|
|
1152
|
+
lastError = err;
|
|
1153
|
+
}
|
|
1154
|
+
await new Promise((resolve) => setTimeout(resolve, CODE_ASSIST_POST_RETRY_DELAY_MS));
|
|
1106
1155
|
}
|
|
1107
|
-
|
|
1108
|
-
accessToken,
|
|
1109
|
-
refreshToken,
|
|
1110
|
-
expiresAt: Date.now() + expiresIn * 1e3,
|
|
1111
|
-
baseUrl: kimiCodeBaseUrl()
|
|
1112
|
-
};
|
|
1156
|
+
throw lastError ?? new Error(`Gemini Code Assist ${method} failed.`);
|
|
1113
1157
|
}
|
|
1114
|
-
async function
|
|
1115
|
-
|
|
1116
|
-
|
|
1158
|
+
async function codeAssistGet(accessToken, operationName) {
|
|
1159
|
+
return codeAssistRequest(getCodeAssistOperationUrl(operationName), accessToken, "operation", {
|
|
1160
|
+
method: "GET"
|
|
1117
1161
|
});
|
|
1118
|
-
if (status !== 200) {
|
|
1119
|
-
throw new Error(`Kimi device authorization failed (${status}): ${errorDetail(data)}`);
|
|
1120
|
-
}
|
|
1121
|
-
const userCode = data.user_code;
|
|
1122
|
-
const deviceCode = data.device_code;
|
|
1123
|
-
const verificationUriComplete = data.verification_uri_complete;
|
|
1124
|
-
if (typeof userCode !== "string" || typeof deviceCode !== "string") {
|
|
1125
|
-
throw new Error("Kimi device authorization response missing user_code/device_code.");
|
|
1126
|
-
}
|
|
1127
|
-
return {
|
|
1128
|
-
userCode,
|
|
1129
|
-
deviceCode,
|
|
1130
|
-
verificationUri: typeof data.verification_uri === "string" ? data.verification_uri : "",
|
|
1131
|
-
verificationUriComplete: typeof verificationUriComplete === "string" ? verificationUriComplete : "",
|
|
1132
|
-
interval: Number(data.interval ?? 5) || 5
|
|
1133
|
-
};
|
|
1134
1162
|
}
|
|
1135
|
-
async function
|
|
1136
|
-
const
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
1163
|
+
async function codeAssistRequest(url, accessToken, label, init) {
|
|
1164
|
+
const response = await fetch(url, {
|
|
1165
|
+
...init,
|
|
1166
|
+
headers: codeAssistHeaders(accessToken)
|
|
1140
1167
|
});
|
|
1141
|
-
if (
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
if (status >= 500) {
|
|
1145
|
-
throw new Error(`Kimi token polling server error (${status}): ${errorDetail(data)}`);
|
|
1146
|
-
}
|
|
1147
|
-
const errorCode = typeof data.error === "string" ? data.error : "unknown_error";
|
|
1148
|
-
switch (errorCode) {
|
|
1149
|
-
case "authorization_pending":
|
|
1150
|
-
return { kind: "pending" };
|
|
1151
|
-
case "slow_down":
|
|
1152
|
-
return { kind: "slow_down" };
|
|
1153
|
-
case "expired_token":
|
|
1154
|
-
return { kind: "expired" };
|
|
1155
|
-
case "access_denied":
|
|
1156
|
-
return { kind: "denied" };
|
|
1157
|
-
default:
|
|
1158
|
-
throw new Error(`Kimi token polling failed (${status}): ${errorDetail(data)}`);
|
|
1168
|
+
if (!response.ok) {
|
|
1169
|
+
const text = await response.text();
|
|
1170
|
+
throw new CodeAssistHttpError(label, response.status, text);
|
|
1159
1171
|
}
|
|
1172
|
+
return await response.json();
|
|
1160
1173
|
}
|
|
1161
|
-
function
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
}
|
|
1174
|
+
function getCodeAssistBaseUrl() {
|
|
1175
|
+
const endpoint = process.env.CODE_ASSIST_ENDPOINT ?? CODE_ASSIST_BASE_URL;
|
|
1176
|
+
const version = process.env.CODE_ASSIST_API_VERSION || CODE_ASSIST_API_VERSION;
|
|
1177
|
+
return `${endpoint}/${version}`;
|
|
1165
1178
|
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
callbacks.onStatus(
|
|
1169
|
-
`Visit ${auth.verificationUri || auth.verificationUriComplete} and enter code: ${auth.userCode}`
|
|
1170
|
-
);
|
|
1171
|
-
callbacks.onOpenUrl(auth.verificationUriComplete || auth.verificationUri);
|
|
1172
|
-
callbacks.onStatus("Waiting for you to authorize in the browser...");
|
|
1173
|
-
const deadline = Date.now() + DEVICE_TIMEOUT_MS;
|
|
1174
|
-
let interval = Math.max(auth.interval, 1);
|
|
1175
|
-
while (Date.now() < deadline) {
|
|
1176
|
-
await sleep(interval * 1e3);
|
|
1177
|
-
const result = await pollDeviceToken(auth.deviceCode);
|
|
1178
|
-
if (result.kind === "success") return result.creds;
|
|
1179
|
-
if (result.kind === "denied") {
|
|
1180
|
-
throw new Error("Kimi authorization was denied.");
|
|
1181
|
-
}
|
|
1182
|
-
if (result.kind === "expired") {
|
|
1183
|
-
throw new Error("Kimi device code expired. Please run login again.");
|
|
1184
|
-
}
|
|
1185
|
-
if (result.kind === "slow_down") {
|
|
1186
|
-
interval += 5;
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
throw new Error("Kimi login timed out. Please run login again.");
|
|
1179
|
+
function getCodeAssistMethodUrl(method) {
|
|
1180
|
+
return `${getCodeAssistBaseUrl()}:${method}`;
|
|
1190
1181
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1182
|
+
function getCodeAssistOperationUrl(operationName) {
|
|
1183
|
+
return `${getCodeAssistBaseUrl()}/${operationName}`;
|
|
1184
|
+
}
|
|
1185
|
+
function shouldRetryCodeAssistStatus(status) {
|
|
1186
|
+
return status === 429 || status === 499 || status >= 500 && status <= 599;
|
|
1187
|
+
}
|
|
1188
|
+
function isVpcScAffectedError(error) {
|
|
1189
|
+
try {
|
|
1190
|
+
const parsed = JSON.parse(error.body);
|
|
1191
|
+
if (!parsed || typeof parsed !== "object" || !("error" in parsed)) return false;
|
|
1192
|
+
const details = parsed.error?.details;
|
|
1193
|
+
return Array.isArray(details) ? details.some(
|
|
1194
|
+
(detail) => detail != null && typeof detail === "object" && "reason" in detail && detail.reason === VPC_SC_REASON
|
|
1195
|
+
) : false;
|
|
1196
|
+
} catch {
|
|
1197
|
+
return false;
|
|
1199
1198
|
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1199
|
+
}
|
|
1200
|
+
function codeAssistHeaders(accessToken) {
|
|
1201
|
+
return {
|
|
1202
|
+
Authorization: `Bearer ${accessToken}`,
|
|
1203
|
+
"Content-Type": "application/json",
|
|
1204
|
+
"User-Agent": "google-gemini-cli",
|
|
1205
|
+
"X-Goog-Api-Client": "gemini-cli/0.0.0"
|
|
1206
|
+
};
|
|
1202
1207
|
}
|
|
1203
1208
|
|
|
1204
1209
|
// src/file-lock.ts
|
|
@@ -1266,6 +1271,26 @@ function isAlive(pid) {
|
|
|
1266
1271
|
// src/auth-storage.ts
|
|
1267
1272
|
var MOONSHOT_OAUTH_KEY = "moonshot-oauth";
|
|
1268
1273
|
var XIAOMI_CREDITS_KEY = "xiaomi-credits";
|
|
1274
|
+
function activeBaseUrlEntry(data, provider) {
|
|
1275
|
+
if (provider === "moonshot") {
|
|
1276
|
+
const oauth = data[MOONSHOT_OAUTH_KEY];
|
|
1277
|
+
if (oauth) {
|
|
1278
|
+
const exhaustedUntil = oauth.usageExhaustedUntil ?? 0;
|
|
1279
|
+
if (Date.now() < exhaustedUntil && data["moonshot"]) return data["moonshot"];
|
|
1280
|
+
return oauth;
|
|
1281
|
+
}
|
|
1282
|
+
return data["moonshot"];
|
|
1283
|
+
}
|
|
1284
|
+
return data[provider];
|
|
1285
|
+
}
|
|
1286
|
+
function readStoredBaseUrlSync(authFile, provider) {
|
|
1287
|
+
try {
|
|
1288
|
+
const data = JSON.parse((0, import_node_fs3.readFileSync)(authFile, "utf-8"));
|
|
1289
|
+
return activeBaseUrlEntry(data, provider)?.baseUrl;
|
|
1290
|
+
} catch {
|
|
1291
|
+
return void 0;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1269
1294
|
var REFRESH_SKEW_MS = 6e4;
|
|
1270
1295
|
var USAGE_EXHAUSTED_DEFAULT_MS = 15 * 60 * 1e3;
|
|
1271
1296
|
var STATIC_API_KEY_PROVIDERS = /* @__PURE__ */ new Set([
|
|
@@ -1341,6 +1366,16 @@ var AuthStorage = class {
|
|
|
1341
1366
|
}
|
|
1342
1367
|
return STATIC_API_KEY_PROVIDERS.has(provider);
|
|
1343
1368
|
}
|
|
1369
|
+
/**
|
|
1370
|
+
* The base URL on the credential that is active right now, if any.
|
|
1371
|
+
* Synchronous — call only after load()/resolveCredentials() populated the
|
|
1372
|
+
* snapshot. For `moonshot` this is the Kimi For Coding URL whenever the
|
|
1373
|
+
* OAuth entry is the one resolveCredentials would serve (i.e. not currently
|
|
1374
|
+
* usage-exhausted with an API key configured).
|
|
1375
|
+
*/
|
|
1376
|
+
getStoredBaseUrl(provider) {
|
|
1377
|
+
return activeBaseUrlEntry(this.data, provider)?.baseUrl;
|
|
1378
|
+
}
|
|
1344
1379
|
async load() {
|
|
1345
1380
|
await withFileLock(this.filePath, async () => {
|
|
1346
1381
|
try {
|
|
@@ -1369,19 +1404,40 @@ var AuthStorage = class {
|
|
|
1369
1404
|
async ensureLoaded() {
|
|
1370
1405
|
if (!this.loaded) await this.load();
|
|
1371
1406
|
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Apply one provider-scoped mutation to the latest on-disk snapshot.
|
|
1409
|
+
* AuthStorage instances live in every app session/process, so writing this
|
|
1410
|
+
* instance's cached snapshot can erase credentials another instance just
|
|
1411
|
+
* added. The file lock only serializes writers; the re-read prevents stale
|
|
1412
|
+
* full-file overwrites.
|
|
1413
|
+
*/
|
|
1414
|
+
async mutateLatest(mutator) {
|
|
1415
|
+
await this.ensureLoaded();
|
|
1416
|
+
await withFileLock(this.filePath, async () => {
|
|
1417
|
+
const latest = await readAuthData(this.filePath);
|
|
1418
|
+
mutator(latest);
|
|
1419
|
+
await atomicWriteFile(this.filePath, JSON.stringify(latest, null, 2));
|
|
1420
|
+
this.data = latest;
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
async reloadLatest() {
|
|
1424
|
+
await withFileLock(this.filePath, async () => {
|
|
1425
|
+
this.data = await readAuthData(this.filePath);
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1372
1428
|
async getCredentials(provider) {
|
|
1373
1429
|
await this.ensureLoaded();
|
|
1374
1430
|
return this.data[provider];
|
|
1375
1431
|
}
|
|
1376
1432
|
async setCredentials(provider, creds) {
|
|
1377
|
-
await this.
|
|
1378
|
-
|
|
1379
|
-
|
|
1433
|
+
await this.mutateLatest((latest) => {
|
|
1434
|
+
latest[provider] = creds;
|
|
1435
|
+
});
|
|
1380
1436
|
}
|
|
1381
1437
|
async clearCredentials(provider) {
|
|
1382
|
-
await this.
|
|
1383
|
-
|
|
1384
|
-
|
|
1438
|
+
await this.mutateLatest((latest) => {
|
|
1439
|
+
delete latest[provider];
|
|
1440
|
+
});
|
|
1385
1441
|
}
|
|
1386
1442
|
/**
|
|
1387
1443
|
* Mark the credential stored under `storageKey` as usage-exhausted until
|
|
@@ -1395,12 +1451,15 @@ var AuthStorage = class {
|
|
|
1395
1451
|
* nothing is stored under `storageKey`.
|
|
1396
1452
|
*/
|
|
1397
1453
|
async markUsageExhausted(storageKey, resetsAt) {
|
|
1398
|
-
await this.ensureLoaded();
|
|
1399
|
-
const creds = this.data[storageKey];
|
|
1400
|
-
if (!creds) return;
|
|
1401
1454
|
const until = resetsAt !== void 0 && resetsAt * 1e3 > Date.now() ? resetsAt * 1e3 : Date.now() + USAGE_EXHAUSTED_DEFAULT_MS;
|
|
1402
|
-
|
|
1403
|
-
await this.
|
|
1455
|
+
let marked = false;
|
|
1456
|
+
await this.mutateLatest((latest) => {
|
|
1457
|
+
const creds = latest[storageKey];
|
|
1458
|
+
if (!creds) return;
|
|
1459
|
+
creds.usageExhaustedUntil = until;
|
|
1460
|
+
marked = true;
|
|
1461
|
+
});
|
|
1462
|
+
if (!marked) return;
|
|
1404
1463
|
log(
|
|
1405
1464
|
"WARN",
|
|
1406
1465
|
"auth",
|
|
@@ -1408,8 +1467,11 @@ var AuthStorage = class {
|
|
|
1408
1467
|
);
|
|
1409
1468
|
}
|
|
1410
1469
|
async clearAll() {
|
|
1411
|
-
this.
|
|
1412
|
-
await this.
|
|
1470
|
+
await this.ensureLoaded();
|
|
1471
|
+
await withFileLock(this.filePath, async () => {
|
|
1472
|
+
this.data = {};
|
|
1473
|
+
await atomicWriteFile(this.filePath, JSON.stringify(this.data, null, 2));
|
|
1474
|
+
});
|
|
1413
1475
|
}
|
|
1414
1476
|
/**
|
|
1415
1477
|
* Returns valid credentials, auto-refreshing if expired.
|
|
@@ -1419,6 +1481,10 @@ var AuthStorage = class {
|
|
|
1419
1481
|
*/
|
|
1420
1482
|
async resolveCredentials(provider, opts) {
|
|
1421
1483
|
await this.ensureLoaded();
|
|
1484
|
+
const directStorageKeys = opts?.storageKeys && !(opts.storageKeys.length === 1 && opts.storageKeys[0] === provider) ? opts.storageKeys : provider === "moonshot" ? [MOONSHOT_OAUTH_KEY, "moonshot"] : [provider];
|
|
1485
|
+
if (!directStorageKeys.some((key) => Boolean(this.data[key]))) {
|
|
1486
|
+
await this.reloadLatest();
|
|
1487
|
+
}
|
|
1422
1488
|
if (opts?.storageKeys && !(opts.storageKeys.length === 1 && opts.storageKeys[0] === provider)) {
|
|
1423
1489
|
for (const key of opts.storageKeys) {
|
|
1424
1490
|
const creds2 = this.data[key];
|
|
@@ -1465,41 +1531,44 @@ var AuthStorage = class {
|
|
|
1465
1531
|
const existing = this.refreshLocks.get(provider);
|
|
1466
1532
|
if (existing) return existing;
|
|
1467
1533
|
const refreshPromise = withFileLock(this.filePath, async () => {
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1534
|
+
const latest = await readAuthData(this.filePath);
|
|
1535
|
+
const latestCreds = latest[provider];
|
|
1536
|
+
if (!latestCreds) {
|
|
1537
|
+
this.data = latest;
|
|
1538
|
+
throw new NotLoggedInError(provider);
|
|
1539
|
+
}
|
|
1540
|
+
const credentialWasReplaced = latestCreds.accessToken !== creds.accessToken || latestCreds.refreshToken !== creds.refreshToken || latestCreds.expiresAt !== creds.expiresAt;
|
|
1541
|
+
if (credentialWasReplaced || !opts?.forceRefresh && Date.now() < latestCreds.expiresAt - REFRESH_SKEW_MS) {
|
|
1542
|
+
this.data = latest;
|
|
1543
|
+
return latestCreds;
|
|
1477
1544
|
}
|
|
1478
1545
|
const refreshFn = provider === "anthropic" ? refreshAnthropicToken : provider === "gemini" ? refreshGeminiToken : provider === MOONSHOT_OAUTH_KEY ? refreshKimiToken : refreshOpenAIToken;
|
|
1479
1546
|
let refreshed;
|
|
1480
1547
|
try {
|
|
1481
|
-
refreshed = await refreshFn(
|
|
1548
|
+
refreshed = await refreshFn(latestCreds.refreshToken);
|
|
1482
1549
|
} catch (err) {
|
|
1483
1550
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1484
1551
|
const isAuthFailure = /\((401|400)\)/.test(msg) || /invalid_grant|invalid_token|invalid.*refresh/i.test(msg) || /unauthorized/i.test(msg);
|
|
1485
1552
|
if (isAuthFailure) {
|
|
1486
|
-
delete
|
|
1487
|
-
|
|
1553
|
+
delete latest[provider];
|
|
1554
|
+
this.data = latest;
|
|
1555
|
+
await atomicWriteFile(this.filePath, JSON.stringify(latest, null, 2));
|
|
1488
1556
|
throw new NotLoggedInError(provider);
|
|
1489
1557
|
}
|
|
1490
1558
|
throw err;
|
|
1491
1559
|
}
|
|
1492
|
-
if (!refreshed.accountId &&
|
|
1493
|
-
refreshed.accountId =
|
|
1560
|
+
if (!refreshed.accountId && latestCreds.accountId) {
|
|
1561
|
+
refreshed.accountId = latestCreds.accountId;
|
|
1494
1562
|
}
|
|
1495
|
-
if (!refreshed.projectId &&
|
|
1496
|
-
refreshed.projectId =
|
|
1563
|
+
if (!refreshed.projectId && latestCreds.projectId) {
|
|
1564
|
+
refreshed.projectId = latestCreds.projectId;
|
|
1497
1565
|
}
|
|
1498
|
-
if (!refreshed.baseUrl &&
|
|
1499
|
-
refreshed.baseUrl =
|
|
1566
|
+
if (!refreshed.baseUrl && latestCreds.baseUrl) {
|
|
1567
|
+
refreshed.baseUrl = latestCreds.baseUrl;
|
|
1500
1568
|
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1569
|
+
latest[provider] = refreshed;
|
|
1570
|
+
this.data = latest;
|
|
1571
|
+
await atomicWriteFile(this.filePath, JSON.stringify(latest, null, 2));
|
|
1503
1572
|
return refreshed;
|
|
1504
1573
|
});
|
|
1505
1574
|
this.refreshLocks.set(provider, refreshPromise);
|
|
@@ -1517,12 +1586,16 @@ var AuthStorage = class {
|
|
|
1517
1586
|
const creds = await this.resolveCredentials(provider);
|
|
1518
1587
|
return creds.accessToken;
|
|
1519
1588
|
}
|
|
1520
|
-
async save() {
|
|
1521
|
-
await withFileLock(this.filePath, async () => {
|
|
1522
|
-
await atomicWriteFile(this.filePath, JSON.stringify(this.data, null, 2));
|
|
1523
|
-
});
|
|
1524
|
-
}
|
|
1525
1589
|
};
|
|
1590
|
+
async function readAuthData(filePath) {
|
|
1591
|
+
try {
|
|
1592
|
+
const content = await import_promises4.default.readFile(filePath, "utf-8");
|
|
1593
|
+
return JSON.parse(content);
|
|
1594
|
+
} catch (error) {
|
|
1595
|
+
if (error.code === "ENOENT") return {};
|
|
1596
|
+
throw error;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1526
1599
|
async function atomicWriteFile(filePath, content) {
|
|
1527
1600
|
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.${import_node_crypto6.default.randomUUID().slice(0, 8)}.tmp`;
|
|
1528
1601
|
try {
|
|
@@ -1777,8 +1850,9 @@ var MODELS = [
|
|
|
1777
1850
|
},
|
|
1778
1851
|
// ── Moonshot (Kimi) ────────────────────────────────────
|
|
1779
1852
|
// K3 is Kimi's 2.8T-parameter flagship for long-horizon coding, knowledge
|
|
1780
|
-
// work, and deep reasoning.
|
|
1781
|
-
//
|
|
1853
|
+
// work, and deep reasoning. Its effort ladder is server-declared as
|
|
1854
|
+
// low/high/max on both the public API (default max) and the Kimi For Coding
|
|
1855
|
+
// OAuth endpoint (default high); thinking can also be fully disabled.
|
|
1782
1856
|
{
|
|
1783
1857
|
id: "kimi-k3",
|
|
1784
1858
|
name: "Kimi K3",
|
|
@@ -2012,6 +2086,11 @@ function getContextWindow(modelId, options) {
|
|
|
2012
2086
|
function getMaxThinkingLevel(modelId) {
|
|
2013
2087
|
return getModel(modelId)?.maxThinkingLevel ?? "high";
|
|
2014
2088
|
}
|
|
2089
|
+
function getDefaultThinkingLevel(modelId, options) {
|
|
2090
|
+
const model = getModel(modelId);
|
|
2091
|
+
if (model?.id === "kimi-k3" && isKimiCodingEndpoint(options?.baseUrl)) return "high";
|
|
2092
|
+
return model?.maxThinkingLevel ?? "high";
|
|
2093
|
+
}
|
|
2015
2094
|
function getSummaryModel(provider, currentModelId) {
|
|
2016
2095
|
if (provider === "anthropic") {
|
|
2017
2096
|
return MODELS.find((m) => m.id === "claude-sonnet-5");
|
|
@@ -2052,6 +2131,7 @@ var ANTHROPIC_ADAPTIVE_THINKING_LEVELS = [
|
|
|
2052
2131
|
"high",
|
|
2053
2132
|
"max"
|
|
2054
2133
|
];
|
|
2134
|
+
var MOONSHOT_K3_THINKING_LEVELS = ["low", "high", "max"];
|
|
2055
2135
|
function isOpenAIGptModel(provider, model) {
|
|
2056
2136
|
return provider === "openai" && model.startsWith("gpt-");
|
|
2057
2137
|
}
|
|
@@ -2061,6 +2141,9 @@ function isSakanaModel(provider) {
|
|
|
2061
2141
|
function isXaiModel(provider) {
|
|
2062
2142
|
return provider === "xai";
|
|
2063
2143
|
}
|
|
2144
|
+
function isMoonshotK3Model(provider, model) {
|
|
2145
|
+
return provider === "moonshot" && model === "kimi-k3";
|
|
2146
|
+
}
|
|
2064
2147
|
function isAnthropicOpus48Or47Model(provider, model) {
|
|
2065
2148
|
return provider === "anthropic" && /opus-4-8|opus-4-7/.test(model);
|
|
2066
2149
|
}
|
|
@@ -2085,6 +2168,7 @@ function getSupportedThinkingLevels(provider, model) {
|
|
|
2085
2168
|
if (maxIndex2 === -1) return XAI_THINKING_LEVELS;
|
|
2086
2169
|
return XAI_THINKING_LEVELS.slice(0, maxIndex2 + 1);
|
|
2087
2170
|
}
|
|
2171
|
+
if (isMoonshotK3Model(provider, model)) return MOONSHOT_K3_THINKING_LEVELS;
|
|
2088
2172
|
if (!isOpenAIGptModel(provider, model)) return [maxLevel];
|
|
2089
2173
|
const levels = model.startsWith("gpt-5.6-") ? OPENAI_GPT_56_THINKING_LEVELS : OPENAI_GPT_THINKING_LEVELS;
|
|
2090
2174
|
const maxIndex = levels.indexOf(maxLevel);
|
|
@@ -2096,7 +2180,7 @@ function isThinkingLevelSupported(provider, model, level) {
|
|
|
2096
2180
|
}
|
|
2097
2181
|
function getNextThinkingLevel(provider, model, current) {
|
|
2098
2182
|
const supportedLevels = getSupportedThinkingLevels(provider, model);
|
|
2099
|
-
const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider);
|
|
2183
|
+
const shouldCycleLevels = isOpenAIGptModel(provider, model) || isAnthropicAdaptiveModel(provider, model) || isSakanaModel(provider) || isXaiModel(provider) || isMoonshotK3Model(provider, model);
|
|
2100
2184
|
if (!shouldCycleLevels) {
|
|
2101
2185
|
return current ? void 0 : supportedLevels[0];
|
|
2102
2186
|
}
|
|
@@ -2238,12 +2322,97 @@ async function fetchCodexUsage(credentials, fetchFn, signal, now) {
|
|
|
2238
2322
|
fetchedAt: now()
|
|
2239
2323
|
};
|
|
2240
2324
|
}
|
|
2325
|
+
function kimiNumber(value) {
|
|
2326
|
+
if (typeof value === "string" && value.trim()) {
|
|
2327
|
+
const parsed = Number(value);
|
|
2328
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
2329
|
+
}
|
|
2330
|
+
return finiteNumber(value);
|
|
2331
|
+
}
|
|
2332
|
+
function kimiUsagePercent(detail) {
|
|
2333
|
+
const used = kimiNumber(detail?.used);
|
|
2334
|
+
const limit = kimiNumber(detail?.limit);
|
|
2335
|
+
if (used === void 0 || limit === void 0 || limit <= 0) return void 0;
|
|
2336
|
+
return Math.min(100, Math.max(0, used / limit * 100));
|
|
2337
|
+
}
|
|
2338
|
+
function kimiWindowMinutes(window) {
|
|
2339
|
+
const duration = kimiNumber(window?.duration);
|
|
2340
|
+
if (duration === void 0 || duration <= 0) return void 0;
|
|
2341
|
+
switch (window?.timeUnit) {
|
|
2342
|
+
case "TIME_UNIT_SECOND":
|
|
2343
|
+
return duration / 60;
|
|
2344
|
+
case "TIME_UNIT_MINUTE":
|
|
2345
|
+
return duration;
|
|
2346
|
+
case "TIME_UNIT_HOUR":
|
|
2347
|
+
return duration * 60;
|
|
2348
|
+
case "TIME_UNIT_DAY":
|
|
2349
|
+
return duration * 24 * 60;
|
|
2350
|
+
default:
|
|
2351
|
+
return void 0;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
async function fetchKimiUsage(credentials, fetchFn, signal, now) {
|
|
2355
|
+
const response = await fetchFn(`${kimiCodeBaseUrl()}/usages`, {
|
|
2356
|
+
method: "GET",
|
|
2357
|
+
signal,
|
|
2358
|
+
headers: {
|
|
2359
|
+
Authorization: "Bearer " + credentials.accessToken,
|
|
2360
|
+
Accept: "application/json",
|
|
2361
|
+
// The managed coding endpoint gates on the kimi-code-cli client identity,
|
|
2362
|
+
// same as model requests.
|
|
2363
|
+
...kimiCodingHeaders()
|
|
2364
|
+
}
|
|
2365
|
+
});
|
|
2366
|
+
const data = await readUsageResponse(response);
|
|
2367
|
+
const windows = [];
|
|
2368
|
+
const weeklyPercent = kimiUsagePercent(data.usage);
|
|
2369
|
+
if (weeklyPercent !== void 0) {
|
|
2370
|
+
windows.push({
|
|
2371
|
+
kind: "weekly",
|
|
2372
|
+
label: "Weekly",
|
|
2373
|
+
usedPercent: weeklyPercent,
|
|
2374
|
+
resetsAt: isoTimestamp(data.usage?.resetTime)
|
|
2375
|
+
});
|
|
2376
|
+
}
|
|
2377
|
+
for (const limit of data.limits ?? []) {
|
|
2378
|
+
const minutes = kimiWindowMinutes(limit?.window);
|
|
2379
|
+
const percent = kimiUsagePercent(limit?.detail);
|
|
2380
|
+
if (minutes === void 0 || percent === void 0) continue;
|
|
2381
|
+
if (minutes >= 6 * 24 * 60) {
|
|
2382
|
+
if (!windows.some((window) => window.kind === "weekly")) {
|
|
2383
|
+
windows.push({
|
|
2384
|
+
kind: "weekly",
|
|
2385
|
+
label: "Weekly",
|
|
2386
|
+
usedPercent: percent,
|
|
2387
|
+
resetsAt: isoTimestamp(limit?.detail?.resetTime)
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
continue;
|
|
2391
|
+
}
|
|
2392
|
+
windows.push({
|
|
2393
|
+
kind: "current",
|
|
2394
|
+
label: `${Math.max(1, Math.round(minutes / 60))}-hour`,
|
|
2395
|
+
usedPercent: percent,
|
|
2396
|
+
resetsAt: isoTimestamp(limit?.detail?.resetTime)
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
windows.sort((left, right) => {
|
|
2400
|
+
if (left.kind === right.kind) return 0;
|
|
2401
|
+
return left.kind === "current" ? -1 : 1;
|
|
2402
|
+
});
|
|
2403
|
+
return {
|
|
2404
|
+
provider: "moonshot",
|
|
2405
|
+
displayName: "Kimi",
|
|
2406
|
+
windows,
|
|
2407
|
+
fetchedAt: now()
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2241
2410
|
async function fetchSubscriptionUsage(provider, credentials, options = {}) {
|
|
2242
2411
|
const fetchFn = options.fetchFn ?? fetch;
|
|
2243
2412
|
const now = options.now ?? Date.now;
|
|
2244
2413
|
const signal = AbortSignal.timeout(options.timeoutMs ?? 8e3);
|
|
2245
2414
|
try {
|
|
2246
|
-
return provider === "anthropic" ? await fetchAnthropicUsage(credentials, fetchFn, signal, now) : await fetchCodexUsage(credentials, fetchFn, signal, now);
|
|
2415
|
+
return provider === "anthropic" ? await fetchAnthropicUsage(credentials, fetchFn, signal, now) : provider === "openai" ? await fetchCodexUsage(credentials, fetchFn, signal, now) : await fetchKimiUsage(credentials, fetchFn, signal, now);
|
|
2247
2416
|
} catch (error) {
|
|
2248
2417
|
if (error instanceof SubscriptionUsageError) throw error;
|
|
2249
2418
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -2560,7 +2729,7 @@ async function transcribeVoice(fileUrl) {
|
|
|
2560
2729
|
|
|
2561
2730
|
// src/auto-update.ts
|
|
2562
2731
|
var import_node_child_process2 = require("child_process");
|
|
2563
|
-
var
|
|
2732
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
2564
2733
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
2565
2734
|
var CHECK_INTERVAL_MS = 60 * 60 * 1e3;
|
|
2566
2735
|
var FETCH_TIMEOUT_MS2 = 1e4;
|
|
@@ -2594,7 +2763,7 @@ function createAutoUpdater(config) {
|
|
|
2594
2763
|
}
|
|
2595
2764
|
function readState() {
|
|
2596
2765
|
try {
|
|
2597
|
-
const raw =
|
|
2766
|
+
const raw = import_node_fs4.default.readFileSync(stateFilePath(), "utf-8");
|
|
2598
2767
|
return JSON.parse(raw);
|
|
2599
2768
|
} catch {
|
|
2600
2769
|
return null;
|
|
@@ -2603,8 +2772,8 @@ function createAutoUpdater(config) {
|
|
|
2603
2772
|
function writeState(state) {
|
|
2604
2773
|
try {
|
|
2605
2774
|
const filePath = stateFilePath();
|
|
2606
|
-
|
|
2607
|
-
|
|
2775
|
+
import_node_fs4.default.mkdirSync(import_node_path5.default.dirname(filePath), { recursive: true, mode: 448 });
|
|
2776
|
+
import_node_fs4.default.writeFileSync(filePath, JSON.stringify(state));
|
|
2608
2777
|
} catch {
|
|
2609
2778
|
}
|
|
2610
2779
|
}
|
|
@@ -2749,6 +2918,7 @@ function createAutoUpdater(config) {
|
|
|
2749
2918
|
getClaudeCodeVersion,
|
|
2750
2919
|
getContextWindow,
|
|
2751
2920
|
getDefaultModel,
|
|
2921
|
+
getDefaultThinkingLevel,
|
|
2752
2922
|
getFastModel,
|
|
2753
2923
|
getMaxThinkingLevel,
|
|
2754
2924
|
getModel,
|
|
@@ -2771,6 +2941,7 @@ function createAutoUpdater(config) {
|
|
|
2771
2941
|
loginKimi,
|
|
2772
2942
|
loginOpenAI,
|
|
2773
2943
|
openLog,
|
|
2944
|
+
readStoredBaseUrlSync,
|
|
2774
2945
|
refreshAnthropicToken,
|
|
2775
2946
|
refreshGeminiToken,
|
|
2776
2947
|
refreshKimiToken,
|