copilot-api-plus 1.0.53 → 1.0.55
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/README.md +4 -7
- package/dist/{auth-BrdL89xk.js → auth-DIDShcrD.js} +10 -5
- package/dist/{auth-BrdL89xk.js.map → auth-DIDShcrD.js.map} +1 -1
- package/dist/{auth-CWGl6kMf.js → auth-D_mymhYC.js} +10 -5
- package/dist/{auth-CWGl6kMf.js.map → auth-D_mymhYC.js.map} +1 -1
- package/dist/auth-DreFwlx2.js +3 -0
- package/dist/auth-g7psLP1B.js +3 -0
- package/dist/error-4DW6q2Mo.js +2 -0
- package/dist/{error-SzJ4KHd8.js → error-BYsVGb6T.js} +13 -11
- package/dist/error-BYsVGb6T.js.map +1 -0
- package/dist/{get-models-uEbEgq0L.js → get-models-DhYpjJVG.js} +11 -7
- package/dist/get-models-DhYpjJVG.js.map +1 -0
- package/dist/get-models-PKzVxQmq.js +4 -0
- package/dist/{get-models-DJfPj_Rg.js → get-models-onnSXkNI.js} +8 -4
- package/dist/{get-models-DJfPj_Rg.js.map → get-models-onnSXkNI.js.map} +1 -1
- package/dist/get-user-CtEiwKow.js +3 -0
- package/dist/{get-user-DEDD9jIs.js → get-user-wlP5uMaW.js} +14 -16
- package/dist/get-user-wlP5uMaW.js.map +1 -0
- package/dist/main.js +516 -584
- package/dist/main.js.map +1 -1
- package/dist/{paths-CVYLp61D.js → paths-BdbyVdad.js} +4 -6
- package/dist/{paths-CVYLp61D.js.map → paths-BdbyVdad.js.map} +1 -1
- package/dist/{state-CcLGr8VN.js → state-CRpaW-qc.js} +3 -3
- package/dist/state-CRpaW-qc.js.map +1 -0
- package/dist/token-B_0VZjlS.js +5 -0
- package/dist/{token-CpxbiiIw.js → token-Bg5qiNBd.js} +7 -14
- package/dist/token-Bg5qiNBd.js.map +1 -0
- package/package.json +2 -3
- package/dist/auth-BizgZEf2.js +0 -4
- package/dist/auth-pRwfByMF.js +0 -4
- package/dist/error-DNWWcl_s.js +0 -3
- package/dist/error-SzJ4KHd8.js.map +0 -1
- package/dist/get-models-COPf69Aa.js +0 -5
- package/dist/get-models-uEbEgq0L.js.map +0 -1
- package/dist/get-user-DEDD9jIs.js.map +0 -1
- package/dist/get-user-HhhC3uQr.js +0 -5
- package/dist/state-CcLGr8VN.js.map +0 -1
- package/dist/token-CpxbiiIw.js.map +0 -1
- package/dist/token-DkNaoDp7.js +0 -7
package/dist/main.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { state } from "./state-
|
|
4
|
-
import { GITHUB_API_BASE_URL, copilotBaseUrl, copilotHeaders
|
|
5
|
-
import {
|
|
6
|
-
import { cacheModels,
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
2
|
+
import { n as ensurePaths, t as PATHS } from "./paths-BdbyVdad.js";
|
|
3
|
+
import { t as state } from "./state-CRpaW-qc.js";
|
|
4
|
+
import { c as githubHeaders, n as GITHUB_API_BASE_URL, o as copilotBaseUrl, s as copilotHeaders } from "./get-user-wlP5uMaW.js";
|
|
5
|
+
import { n as forwardError, t as HTTPError } from "./error-BYsVGb6T.js";
|
|
6
|
+
import { a as cacheModels, c as isNullish, i as setupGitHubToken, l as sleep, n as refreshCopilotToken, o as cacheVSCodeVersion, r as setupCopilotToken, s as findModel, t as clearGithubToken } from "./token-Bg5qiNBd.js";
|
|
7
|
+
import { d as getValidAccessToken, g as rotateAccount, l as getCurrentProjectId, n as clearAntigravityAuth, o as getAntigravityAuthPath, r as disableCurrentAccount, s as getApiKey } from "./auth-D_mymhYC.js";
|
|
8
|
+
import { n as getZenAuthPath, t as clearZenAuth } from "./auth-DIDShcrD.js";
|
|
9
|
+
import { n as getAntigravityUsage, r as isThinkingModel, t as getAntigravityModels } from "./get-models-DhYpjJVG.js";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
11
|
import { defineCommand, runMain } from "citty";
|
|
12
12
|
import consola from "consola";
|
|
@@ -26,17 +26,12 @@ import { cors } from "hono/cors";
|
|
|
26
26
|
import { HTTPException } from "hono/http-exception";
|
|
27
27
|
import { streamSSE } from "hono/streaming";
|
|
28
28
|
import { events } from "fetch-event-stream";
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
32
|
-
var __commonJS = (cb, mod) => function() {
|
|
33
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
34
|
-
};
|
|
29
|
+
//#region \0rolldown/runtime.js
|
|
30
|
+
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
35
31
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
36
|
-
|
|
37
32
|
//#endregion
|
|
38
33
|
//#region node_modules/dotenv/package.json
|
|
39
|
-
var require_package = /* @__PURE__ */
|
|
34
|
+
var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
40
35
|
module.exports = {
|
|
41
36
|
"name": "dotenv",
|
|
42
37
|
"version": "17.2.3",
|
|
@@ -95,11 +90,10 @@ var require_package = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/package.
|
|
|
95
90
|
"engines": { "node": ">=12" },
|
|
96
91
|
"browser": { "fs": false }
|
|
97
92
|
};
|
|
98
|
-
})
|
|
99
|
-
|
|
93
|
+
}));
|
|
100
94
|
//#endregion
|
|
101
95
|
//#region node_modules/dotenv/lib/main.js
|
|
102
|
-
var require_main = /* @__PURE__ */
|
|
96
|
+
var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
103
97
|
const fs$1 = __require("fs");
|
|
104
98
|
const path$1 = __require("path");
|
|
105
99
|
const os$1 = __require("os");
|
|
@@ -162,22 +156,21 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
162
156
|
}
|
|
163
157
|
return obj;
|
|
164
158
|
}
|
|
165
|
-
function _parseVault(options
|
|
166
|
-
options
|
|
167
|
-
const vaultPath = _vaultPath(options
|
|
168
|
-
options
|
|
169
|
-
const result = DotenvModule.configDotenv(options
|
|
159
|
+
function _parseVault(options) {
|
|
160
|
+
options = options || {};
|
|
161
|
+
const vaultPath = _vaultPath(options);
|
|
162
|
+
options.path = vaultPath;
|
|
163
|
+
const result = DotenvModule.configDotenv(options);
|
|
170
164
|
if (!result.parsed) {
|
|
171
165
|
const err = /* @__PURE__ */ new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
172
166
|
err.code = "MISSING_DATA";
|
|
173
167
|
throw err;
|
|
174
168
|
}
|
|
175
|
-
const keys = _dotenvKey(options
|
|
169
|
+
const keys = _dotenvKey(options).split(",");
|
|
176
170
|
const length = keys.length;
|
|
177
171
|
let decrypted;
|
|
178
172
|
for (let i = 0; i < length; i++) try {
|
|
179
|
-
const
|
|
180
|
-
const attrs = _instructions(result, key);
|
|
173
|
+
const attrs = _instructions(result, keys[i].trim());
|
|
181
174
|
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
182
175
|
break;
|
|
183
176
|
} catch (error) {
|
|
@@ -194,8 +187,8 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
194
187
|
function _log(message) {
|
|
195
188
|
console.log(`[dotenv@${version}] ${message}`);
|
|
196
189
|
}
|
|
197
|
-
function _dotenvKey(options
|
|
198
|
-
if (options
|
|
190
|
+
function _dotenvKey(options) {
|
|
191
|
+
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) return options.DOTENV_KEY;
|
|
199
192
|
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) return process.env.DOTENV_KEY;
|
|
200
193
|
return "";
|
|
201
194
|
}
|
|
@@ -235,11 +228,11 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
235
228
|
key
|
|
236
229
|
};
|
|
237
230
|
}
|
|
238
|
-
function _vaultPath(options
|
|
231
|
+
function _vaultPath(options) {
|
|
239
232
|
let possibleVaultPath = null;
|
|
240
|
-
if (options
|
|
241
|
-
for (const filepath of options
|
|
242
|
-
} else possibleVaultPath = options
|
|
233
|
+
if (options && options.path && options.path.length > 0) if (Array.isArray(options.path)) {
|
|
234
|
+
for (const filepath of options.path) if (fs$1.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
235
|
+
} else possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
243
236
|
else possibleVaultPath = path$1.resolve(process.cwd(), ".env.vault");
|
|
244
237
|
if (fs$1.existsSync(possibleVaultPath)) return possibleVaultPath;
|
|
245
238
|
return null;
|
|
@@ -247,51 +240,51 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
247
240
|
function _resolveHome(envPath) {
|
|
248
241
|
return envPath[0] === "~" ? path$1.join(os$1.homedir(), envPath.slice(1)) : envPath;
|
|
249
242
|
}
|
|
250
|
-
function _configVault(options
|
|
251
|
-
const debug
|
|
252
|
-
const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options
|
|
253
|
-
if (debug
|
|
254
|
-
const parsed = DotenvModule._parseVault(options
|
|
243
|
+
function _configVault(options) {
|
|
244
|
+
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
245
|
+
const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
246
|
+
if (debug || !quiet) _log("Loading env from encrypted .env.vault");
|
|
247
|
+
const parsed = DotenvModule._parseVault(options);
|
|
255
248
|
let processEnv = process.env;
|
|
256
|
-
if (options
|
|
257
|
-
DotenvModule.populate(processEnv, parsed, options
|
|
249
|
+
if (options && options.processEnv != null) processEnv = options.processEnv;
|
|
250
|
+
DotenvModule.populate(processEnv, parsed, options);
|
|
258
251
|
return { parsed };
|
|
259
252
|
}
|
|
260
|
-
function configDotenv(options
|
|
253
|
+
function configDotenv(options) {
|
|
261
254
|
const dotenvPath = path$1.resolve(process.cwd(), ".env");
|
|
262
255
|
let encoding = "utf8";
|
|
263
256
|
let processEnv = process.env;
|
|
264
|
-
if (options
|
|
265
|
-
let debug
|
|
266
|
-
let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options
|
|
267
|
-
if (options
|
|
268
|
-
else if (debug
|
|
257
|
+
if (options && options.processEnv != null) processEnv = options.processEnv;
|
|
258
|
+
let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
259
|
+
let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
260
|
+
if (options && options.encoding) encoding = options.encoding;
|
|
261
|
+
else if (debug) _debug("No encoding is specified. UTF-8 is used by default");
|
|
269
262
|
let optionPaths = [dotenvPath];
|
|
270
|
-
if (options
|
|
263
|
+
if (options && options.path) if (!Array.isArray(options.path)) optionPaths = [_resolveHome(options.path)];
|
|
271
264
|
else {
|
|
272
265
|
optionPaths = [];
|
|
273
|
-
for (const filepath of options
|
|
266
|
+
for (const filepath of options.path) optionPaths.push(_resolveHome(filepath));
|
|
274
267
|
}
|
|
275
268
|
let lastError;
|
|
276
269
|
const parsedAll = {};
|
|
277
|
-
for (const path
|
|
278
|
-
const parsed = DotenvModule.parse(fs$1.readFileSync(path
|
|
279
|
-
DotenvModule.populate(parsedAll, parsed, options
|
|
270
|
+
for (const path of optionPaths) try {
|
|
271
|
+
const parsed = DotenvModule.parse(fs$1.readFileSync(path, { encoding }));
|
|
272
|
+
DotenvModule.populate(parsedAll, parsed, options);
|
|
280
273
|
} catch (e) {
|
|
281
|
-
if (debug
|
|
274
|
+
if (debug) _debug(`Failed to load ${path} ${e.message}`);
|
|
282
275
|
lastError = e;
|
|
283
276
|
}
|
|
284
|
-
const populated = DotenvModule.populate(processEnv, parsedAll, options
|
|
285
|
-
debug
|
|
277
|
+
const populated = DotenvModule.populate(processEnv, parsedAll, options);
|
|
278
|
+
debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
|
|
286
279
|
quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
|
|
287
|
-
if (debug
|
|
280
|
+
if (debug || !quiet) {
|
|
288
281
|
const keysCount = Object.keys(populated).length;
|
|
289
282
|
const shortPaths = [];
|
|
290
283
|
for (const filePath of optionPaths) try {
|
|
291
284
|
const relative = path$1.relative(process.cwd(), filePath);
|
|
292
285
|
shortPaths.push(relative);
|
|
293
286
|
} catch (e) {
|
|
294
|
-
if (debug
|
|
287
|
+
if (debug) _debug(`Failed to load ${filePath} ${e.message}`);
|
|
295
288
|
lastError = e;
|
|
296
289
|
}
|
|
297
290
|
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
|
|
@@ -302,14 +295,14 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
302
295
|
};
|
|
303
296
|
else return { parsed: parsedAll };
|
|
304
297
|
}
|
|
305
|
-
function config(options
|
|
306
|
-
if (_dotenvKey(options
|
|
307
|
-
const vaultPath = _vaultPath(options
|
|
298
|
+
function config(options) {
|
|
299
|
+
if (_dotenvKey(options).length === 0) return DotenvModule.configDotenv(options);
|
|
300
|
+
const vaultPath = _vaultPath(options);
|
|
308
301
|
if (!vaultPath) {
|
|
309
302
|
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
310
|
-
return DotenvModule.configDotenv(options
|
|
303
|
+
return DotenvModule.configDotenv(options);
|
|
311
304
|
}
|
|
312
|
-
return DotenvModule._configVault(options
|
|
305
|
+
return DotenvModule._configVault(options);
|
|
313
306
|
}
|
|
314
307
|
function decrypt(encrypted, keyStr) {
|
|
315
308
|
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
@@ -336,9 +329,9 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
336
329
|
} else throw error;
|
|
337
330
|
}
|
|
338
331
|
}
|
|
339
|
-
function populate(processEnv, parsed, options
|
|
340
|
-
const debug
|
|
341
|
-
const override = Boolean(options
|
|
332
|
+
function populate(processEnv, parsed, options = {}) {
|
|
333
|
+
const debug = Boolean(options && options.debug);
|
|
334
|
+
const override = Boolean(options && options.override);
|
|
342
335
|
const populated = {};
|
|
343
336
|
if (typeof parsed !== "object") {
|
|
344
337
|
const err = /* @__PURE__ */ new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
@@ -350,7 +343,7 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
350
343
|
processEnv[key] = parsed[key];
|
|
351
344
|
populated[key] = parsed[key];
|
|
352
345
|
}
|
|
353
|
-
if (debug
|
|
346
|
+
if (debug) if (override === true) _debug(`"${key}" is already defined and WAS overwritten`);
|
|
354
347
|
else _debug(`"${key}" is already defined and was NOT overwritten`);
|
|
355
348
|
} else {
|
|
356
349
|
processEnv[key] = parsed[key];
|
|
@@ -375,11 +368,10 @@ var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js
|
|
|
375
368
|
module.exports.parse = DotenvModule.parse;
|
|
376
369
|
module.exports.populate = DotenvModule.populate;
|
|
377
370
|
module.exports = DotenvModule;
|
|
378
|
-
})
|
|
379
|
-
|
|
371
|
+
}));
|
|
380
372
|
//#endregion
|
|
381
373
|
//#region node_modules/dotenv/lib/env-options.js
|
|
382
|
-
var require_env_options = /* @__PURE__ */
|
|
374
|
+
var require_env_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
383
375
|
const options = {};
|
|
384
376
|
if (process.env.DOTENV_CONFIG_ENCODING != null) options.encoding = process.env.DOTENV_CONFIG_ENCODING;
|
|
385
377
|
if (process.env.DOTENV_CONFIG_PATH != null) options.path = process.env.DOTENV_CONFIG_PATH;
|
|
@@ -388,31 +380,32 @@ var require_env_options = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/
|
|
|
388
380
|
if (process.env.DOTENV_CONFIG_OVERRIDE != null) options.override = process.env.DOTENV_CONFIG_OVERRIDE;
|
|
389
381
|
if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY;
|
|
390
382
|
module.exports = options;
|
|
391
|
-
})
|
|
392
|
-
|
|
383
|
+
}));
|
|
393
384
|
//#endregion
|
|
394
385
|
//#region node_modules/dotenv/lib/cli-options.js
|
|
395
|
-
var require_cli_options = /* @__PURE__ */
|
|
386
|
+
var require_cli_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
396
387
|
const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/;
|
|
397
388
|
module.exports = function optionMatcher(args) {
|
|
398
|
-
const options
|
|
389
|
+
const options = args.reduce(function(acc, cur) {
|
|
399
390
|
const matches = cur.match(re);
|
|
400
391
|
if (matches) acc[matches[1]] = matches[2];
|
|
401
392
|
return acc;
|
|
402
393
|
}, {});
|
|
403
|
-
if (!("quiet" in options
|
|
404
|
-
return options
|
|
394
|
+
if (!("quiet" in options)) options.quiet = "true";
|
|
395
|
+
return options;
|
|
405
396
|
};
|
|
406
|
-
})
|
|
407
|
-
|
|
397
|
+
}));
|
|
408
398
|
//#endregion
|
|
409
399
|
//#region node_modules/dotenv/config.js
|
|
410
400
|
(function() {
|
|
411
401
|
require_main().config(Object.assign({}, require_env_options(), require_cli_options()(process.argv)));
|
|
412
402
|
})();
|
|
413
|
-
|
|
414
403
|
//#endregion
|
|
415
404
|
//#region src/lib/config.ts
|
|
405
|
+
/**
|
|
406
|
+
* Configuration file management
|
|
407
|
+
* Handles persistent configuration storage for proxy settings and other options
|
|
408
|
+
*/
|
|
416
409
|
const CONFIG_FILENAME = "config.json";
|
|
417
410
|
/**
|
|
418
411
|
* Get the path to the config file
|
|
@@ -435,9 +428,9 @@ async function loadConfig() {
|
|
|
435
428
|
/**
|
|
436
429
|
* Save configuration to file
|
|
437
430
|
*/
|
|
438
|
-
async function saveConfig(config
|
|
431
|
+
async function saveConfig(config) {
|
|
439
432
|
const configPath = getConfigPath();
|
|
440
|
-
await fs.writeFile(configPath, JSON.stringify(config
|
|
433
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf8");
|
|
441
434
|
consola.debug(`Configuration saved to ${configPath}`);
|
|
442
435
|
}
|
|
443
436
|
/**
|
|
@@ -450,17 +443,17 @@ async function getProxyConfig() {
|
|
|
450
443
|
* Save proxy configuration
|
|
451
444
|
*/
|
|
452
445
|
async function saveProxyConfig(proxyConfig) {
|
|
453
|
-
const config
|
|
454
|
-
config
|
|
455
|
-
await saveConfig(config
|
|
446
|
+
const config = await loadConfig();
|
|
447
|
+
config.proxy = proxyConfig;
|
|
448
|
+
await saveConfig(config);
|
|
456
449
|
}
|
|
457
450
|
/**
|
|
458
451
|
* Clear proxy configuration
|
|
459
452
|
*/
|
|
460
453
|
async function clearProxyConfig() {
|
|
461
|
-
const config
|
|
462
|
-
delete config
|
|
463
|
-
await saveConfig(config
|
|
454
|
+
const config = await loadConfig();
|
|
455
|
+
delete config.proxy;
|
|
456
|
+
await saveConfig(config);
|
|
464
457
|
}
|
|
465
458
|
/**
|
|
466
459
|
* Apply saved proxy configuration to environment variables
|
|
@@ -487,7 +480,6 @@ async function applyProxyConfig() {
|
|
|
487
480
|
if (proxyConfig.noProxy) consola.info(` NO_PROXY: ${proxyConfig.noProxy}`);
|
|
488
481
|
return true;
|
|
489
482
|
}
|
|
490
|
-
|
|
491
483
|
//#endregion
|
|
492
484
|
//#region src/lib/proxy.ts
|
|
493
485
|
function initProxyFromEnv() {
|
|
@@ -496,14 +488,14 @@ function initProxyFromEnv() {
|
|
|
496
488
|
const direct = new Agent();
|
|
497
489
|
const proxies = /* @__PURE__ */ new Map();
|
|
498
490
|
setGlobalDispatcher({
|
|
499
|
-
dispatch(options
|
|
491
|
+
dispatch(options, handler) {
|
|
500
492
|
try {
|
|
501
|
-
const origin = typeof options
|
|
493
|
+
const origin = typeof options.origin === "string" ? new URL(options.origin) : options.origin;
|
|
502
494
|
const raw = getProxyForUrl(origin.toString());
|
|
503
495
|
const proxyUrl = raw && raw.length > 0 ? raw : void 0;
|
|
504
496
|
if (!proxyUrl) {
|
|
505
497
|
consola.debug(`HTTP proxy bypass: ${origin.hostname}`);
|
|
506
|
-
return direct.dispatch(options
|
|
498
|
+
return direct.dispatch(options, handler);
|
|
507
499
|
}
|
|
508
500
|
let agent = proxies.get(proxyUrl);
|
|
509
501
|
if (!agent) {
|
|
@@ -516,9 +508,9 @@ function initProxyFromEnv() {
|
|
|
516
508
|
label = `${u.protocol}//${u.host}`;
|
|
517
509
|
} catch {}
|
|
518
510
|
consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`);
|
|
519
|
-
return agent.dispatch(options
|
|
511
|
+
return agent.dispatch(options, handler);
|
|
520
512
|
} catch {
|
|
521
|
-
return direct.dispatch(options
|
|
513
|
+
return direct.dispatch(options, handler);
|
|
522
514
|
}
|
|
523
515
|
},
|
|
524
516
|
close() {
|
|
@@ -533,14 +525,13 @@ function initProxyFromEnv() {
|
|
|
533
525
|
consola.debug("Proxy setup skipped:", err);
|
|
534
526
|
}
|
|
535
527
|
}
|
|
536
|
-
|
|
537
528
|
//#endregion
|
|
538
529
|
//#region src/antigravity.ts
|
|
539
530
|
/**
|
|
540
531
|
* Add a new Antigravity account via OAuth
|
|
541
532
|
*/
|
|
542
533
|
async function addAccount() {
|
|
543
|
-
const { setupAntigravity, loadAntigravityAuth } = await import("./auth-
|
|
534
|
+
const { setupAntigravity, loadAntigravityAuth } = await import("./auth-DreFwlx2.js");
|
|
544
535
|
const existingAuth = await loadAntigravityAuth();
|
|
545
536
|
if (existingAuth && existingAuth.accounts.length > 0) {
|
|
546
537
|
const enabledCount = existingAuth.accounts.filter((a) => a.enable).length;
|
|
@@ -552,17 +543,17 @@ async function addAccount() {
|
|
|
552
543
|
* List all Antigravity accounts
|
|
553
544
|
*/
|
|
554
545
|
async function listAccounts() {
|
|
555
|
-
const { loadAntigravityAuth } = await import("./auth-
|
|
556
|
-
const auth
|
|
557
|
-
if (!auth
|
|
546
|
+
const { loadAntigravityAuth } = await import("./auth-DreFwlx2.js");
|
|
547
|
+
const auth = await loadAntigravityAuth();
|
|
548
|
+
if (!auth || auth.accounts.length === 0) {
|
|
558
549
|
consola.info("No Antigravity accounts configured");
|
|
559
550
|
return;
|
|
560
551
|
}
|
|
561
|
-
consola.info(`\nAntigravity Accounts (${auth
|
|
552
|
+
consola.info(`\nAntigravity Accounts (${auth.accounts.length} total):`);
|
|
562
553
|
consola.info("=".repeat(50));
|
|
563
|
-
for (let i = 0; i < auth
|
|
564
|
-
const account = auth
|
|
565
|
-
const isCurrent = i === auth
|
|
554
|
+
for (let i = 0; i < auth.accounts.length; i++) {
|
|
555
|
+
const account = auth.accounts[i];
|
|
556
|
+
const isCurrent = i === auth.currentIndex;
|
|
566
557
|
const status = account.enable ? "enabled" : "disabled";
|
|
567
558
|
const marker = isCurrent ? "→ " : " ";
|
|
568
559
|
const projectId = account.project_id || "unknown";
|
|
@@ -573,30 +564,30 @@ async function listAccounts() {
|
|
|
573
564
|
* Remove an Antigravity account by index
|
|
574
565
|
*/
|
|
575
566
|
async function removeAccount(index) {
|
|
576
|
-
const { loadAntigravityAuth, saveAntigravityAuth } = await import("./auth-
|
|
577
|
-
const auth
|
|
578
|
-
if (!auth
|
|
567
|
+
const { loadAntigravityAuth, saveAntigravityAuth } = await import("./auth-DreFwlx2.js");
|
|
568
|
+
const auth = await loadAntigravityAuth();
|
|
569
|
+
if (!auth || auth.accounts.length === 0) {
|
|
579
570
|
consola.error("No Antigravity accounts configured");
|
|
580
571
|
return;
|
|
581
572
|
}
|
|
582
|
-
if (index < 0 || index >= auth
|
|
583
|
-
consola.error(`Invalid index. Must be between 0 and ${auth
|
|
573
|
+
if (index < 0 || index >= auth.accounts.length) {
|
|
574
|
+
consola.error(`Invalid index. Must be between 0 and ${auth.accounts.length - 1}`);
|
|
584
575
|
return;
|
|
585
576
|
}
|
|
586
|
-
const removed = auth
|
|
587
|
-
if (auth
|
|
588
|
-
await saveAntigravityAuth(auth
|
|
577
|
+
const removed = auth.accounts.splice(index, 1)[0];
|
|
578
|
+
if (auth.currentIndex >= auth.accounts.length) auth.currentIndex = Math.max(0, auth.accounts.length - 1);
|
|
579
|
+
await saveAntigravityAuth(auth);
|
|
589
580
|
consola.success(`Removed account ${index} (Project: ${removed.project_id || "unknown"})`);
|
|
590
581
|
}
|
|
591
582
|
/**
|
|
592
583
|
* Clear all Antigravity accounts
|
|
593
584
|
*/
|
|
594
585
|
async function clearAccounts() {
|
|
595
|
-
const { clearAntigravityAuth
|
|
586
|
+
const { clearAntigravityAuth } = await import("./auth-DreFwlx2.js");
|
|
596
587
|
if (await consola.prompt("Are you sure you want to remove all Antigravity accounts?", {
|
|
597
588
|
type: "confirm",
|
|
598
589
|
initial: false
|
|
599
|
-
})) await clearAntigravityAuth
|
|
590
|
+
})) await clearAntigravityAuth();
|
|
600
591
|
}
|
|
601
592
|
const antigravity = defineCommand({
|
|
602
593
|
meta: {
|
|
@@ -658,15 +649,14 @@ const antigravity = defineCommand({
|
|
|
658
649
|
})
|
|
659
650
|
}
|
|
660
651
|
});
|
|
661
|
-
|
|
662
652
|
//#endregion
|
|
663
653
|
//#region src/auth.ts
|
|
664
|
-
async function runAuth(options
|
|
665
|
-
if (options
|
|
654
|
+
async function runAuth(options) {
|
|
655
|
+
if (options.verbose) {
|
|
666
656
|
consola.level = 5;
|
|
667
657
|
consola.info("Verbose logging enabled");
|
|
668
658
|
}
|
|
669
|
-
state.showToken = options
|
|
659
|
+
state.showToken = options.showToken;
|
|
670
660
|
await ensurePaths();
|
|
671
661
|
await setupGitHubToken({ force: true });
|
|
672
662
|
consola.success("GitHub token written to", PATHS.GITHUB_TOKEN_PATH);
|
|
@@ -696,7 +686,6 @@ const auth = defineCommand({
|
|
|
696
686
|
});
|
|
697
687
|
}
|
|
698
688
|
});
|
|
699
|
-
|
|
700
689
|
//#endregion
|
|
701
690
|
//#region src/services/github/get-copilot-usage.ts
|
|
702
691
|
const getCopilotUsage = async () => {
|
|
@@ -704,7 +693,6 @@ const getCopilotUsage = async () => {
|
|
|
704
693
|
if (!response.ok) throw new HTTPError("Failed to get Copilot usage", response);
|
|
705
694
|
return await response.json();
|
|
706
695
|
};
|
|
707
|
-
|
|
708
696
|
//#endregion
|
|
709
697
|
//#region src/check-usage.ts
|
|
710
698
|
const checkUsage = defineCommand({
|
|
@@ -740,7 +728,6 @@ const checkUsage = defineCommand({
|
|
|
740
728
|
}
|
|
741
729
|
}
|
|
742
730
|
});
|
|
743
|
-
|
|
744
731
|
//#endregion
|
|
745
732
|
//#region src/debug.ts
|
|
746
733
|
async function getPackageVersion() {
|
|
@@ -768,10 +755,10 @@ async function checkTokenExists() {
|
|
|
768
755
|
return false;
|
|
769
756
|
}
|
|
770
757
|
}
|
|
771
|
-
async function checkFileExists(path
|
|
758
|
+
async function checkFileExists(path) {
|
|
772
759
|
try {
|
|
773
|
-
if (!(await fs.stat(path
|
|
774
|
-
return (await fs.readFile(path
|
|
760
|
+
if (!(await fs.stat(path)).isFile()) return false;
|
|
761
|
+
return (await fs.readFile(path, "utf8")).trim().length > 0;
|
|
775
762
|
} catch {
|
|
776
763
|
return false;
|
|
777
764
|
}
|
|
@@ -779,7 +766,7 @@ async function checkFileExists(path$2) {
|
|
|
779
766
|
async function getDebugInfo() {
|
|
780
767
|
const zenAuthPath = getZenAuthPath();
|
|
781
768
|
const antigravityAuthPath = getAntigravityAuthPath();
|
|
782
|
-
const [version
|
|
769
|
+
const [version, githubExists, zenExists, antigravityExists, proxyConfig] = await Promise.all([
|
|
783
770
|
getPackageVersion(),
|
|
784
771
|
checkTokenExists(),
|
|
785
772
|
checkFileExists(zenAuthPath),
|
|
@@ -787,7 +774,7 @@ async function getDebugInfo() {
|
|
|
787
774
|
getProxyConfig()
|
|
788
775
|
]);
|
|
789
776
|
return {
|
|
790
|
-
version
|
|
777
|
+
version,
|
|
791
778
|
runtime: getRuntimeInfo(),
|
|
792
779
|
paths: {
|
|
793
780
|
APP_DIR: PATHS.APP_DIR,
|
|
@@ -827,9 +814,9 @@ Proxy: ${proxyStatus}`);
|
|
|
827
814
|
function printDebugInfoJson(info) {
|
|
828
815
|
console.log(JSON.stringify(info, null, 2));
|
|
829
816
|
}
|
|
830
|
-
async function runDebug(options
|
|
817
|
+
async function runDebug(options) {
|
|
831
818
|
const debugInfo = await getDebugInfo();
|
|
832
|
-
if (options
|
|
819
|
+
if (options.json) printDebugInfoJson(debugInfo);
|
|
833
820
|
else printDebugInfoPlain(debugInfo);
|
|
834
821
|
}
|
|
835
822
|
const debug = defineCommand({
|
|
@@ -846,12 +833,11 @@ const debug = defineCommand({
|
|
|
846
833
|
return runDebug({ json: args.json });
|
|
847
834
|
}
|
|
848
835
|
});
|
|
849
|
-
|
|
850
836
|
//#endregion
|
|
851
837
|
//#region src/logout.ts
|
|
852
|
-
async function runLogout(options
|
|
838
|
+
async function runLogout(options) {
|
|
853
839
|
await ensurePaths();
|
|
854
|
-
if (options
|
|
840
|
+
if (options.all) {
|
|
855
841
|
await clearGithubToken();
|
|
856
842
|
await clearZenAuth();
|
|
857
843
|
await clearAntigravityAuth();
|
|
@@ -861,19 +847,19 @@ async function runLogout(options$1) {
|
|
|
861
847
|
consola.info(`Antigravity accounts: ${getAntigravityAuthPath()}`);
|
|
862
848
|
return;
|
|
863
849
|
}
|
|
864
|
-
if (options
|
|
850
|
+
if (options.github) {
|
|
865
851
|
await clearGithubToken();
|
|
866
852
|
consola.success("Logged out from GitHub Copilot");
|
|
867
853
|
consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`);
|
|
868
854
|
return;
|
|
869
855
|
}
|
|
870
|
-
if (options
|
|
856
|
+
if (options.zen) {
|
|
871
857
|
await clearZenAuth();
|
|
872
858
|
consola.success("Logged out from OpenCode Zen");
|
|
873
859
|
consola.info(`Zen API key location: ${getZenAuthPath()}`);
|
|
874
860
|
return;
|
|
875
861
|
}
|
|
876
|
-
if (options
|
|
862
|
+
if (options.antigravity) {
|
|
877
863
|
await clearAntigravityAuth();
|
|
878
864
|
consola.success("Logged out from Google Antigravity");
|
|
879
865
|
consola.info(`Antigravity accounts location: ${getAntigravityAuthPath()}`);
|
|
@@ -950,9 +936,12 @@ const logout = defineCommand({
|
|
|
950
936
|
});
|
|
951
937
|
}
|
|
952
938
|
});
|
|
953
|
-
|
|
954
939
|
//#endregion
|
|
955
940
|
//#region src/proxy-config.ts
|
|
941
|
+
/**
|
|
942
|
+
* Proxy configuration command
|
|
943
|
+
* Allows users to configure, enable, disable, and view proxy settings
|
|
944
|
+
*/
|
|
956
945
|
const proxy = defineCommand({
|
|
957
946
|
meta: {
|
|
958
947
|
name: "proxy",
|
|
@@ -1000,8 +989,8 @@ const proxy = defineCommand({
|
|
|
1000
989
|
async run({ args }) {
|
|
1001
990
|
await ensurePaths();
|
|
1002
991
|
if (args.show || !args.set && !args.enable && !args.disable && !args.clear && !args["http-proxy"] && !args["https-proxy"]) {
|
|
1003
|
-
const config
|
|
1004
|
-
if (!config
|
|
992
|
+
const config = await getProxyConfig();
|
|
993
|
+
if (!config) {
|
|
1005
994
|
consola.info("No proxy configuration saved.");
|
|
1006
995
|
consola.info("");
|
|
1007
996
|
consola.info("To configure proxy, use one of:");
|
|
@@ -1010,10 +999,10 @@ const proxy = defineCommand({
|
|
|
1010
999
|
return;
|
|
1011
1000
|
}
|
|
1012
1001
|
consola.info("Current proxy configuration:");
|
|
1013
|
-
consola.info(` Status: ${config
|
|
1014
|
-
if (config
|
|
1015
|
-
if (config
|
|
1016
|
-
if (config
|
|
1002
|
+
consola.info(` Status: ${config.enabled ? "✅ Enabled" : "❌ Disabled"}`);
|
|
1003
|
+
if (config.httpProxy) consola.info(` HTTP_PROXY: ${config.httpProxy}`);
|
|
1004
|
+
if (config.httpsProxy) consola.info(` HTTPS_PROXY: ${config.httpsProxy}`);
|
|
1005
|
+
if (config.noProxy) consola.info(` NO_PROXY: ${config.noProxy}`);
|
|
1017
1006
|
return;
|
|
1018
1007
|
}
|
|
1019
1008
|
if (args.clear) {
|
|
@@ -1022,24 +1011,24 @@ const proxy = defineCommand({
|
|
|
1022
1011
|
return;
|
|
1023
1012
|
}
|
|
1024
1013
|
if (args.enable) {
|
|
1025
|
-
const config
|
|
1026
|
-
if (!config
|
|
1014
|
+
const config = await getProxyConfig();
|
|
1015
|
+
if (!config) {
|
|
1027
1016
|
consola.error("No proxy configuration saved. Use --set to configure first.");
|
|
1028
1017
|
return;
|
|
1029
1018
|
}
|
|
1030
|
-
config
|
|
1031
|
-
await saveProxyConfig(config
|
|
1019
|
+
config.enabled = true;
|
|
1020
|
+
await saveProxyConfig(config);
|
|
1032
1021
|
consola.success("Proxy enabled. It will be used on next server start.");
|
|
1033
1022
|
return;
|
|
1034
1023
|
}
|
|
1035
1024
|
if (args.disable) {
|
|
1036
|
-
const config
|
|
1037
|
-
if (!config
|
|
1025
|
+
const config = await getProxyConfig();
|
|
1026
|
+
if (!config) {
|
|
1038
1027
|
consola.info("No proxy configuration to disable.");
|
|
1039
1028
|
return;
|
|
1040
1029
|
}
|
|
1041
|
-
config
|
|
1042
|
-
await saveProxyConfig(config
|
|
1030
|
+
config.enabled = false;
|
|
1031
|
+
await saveProxyConfig(config);
|
|
1043
1032
|
consola.success("Proxy disabled. Settings are preserved.");
|
|
1044
1033
|
return;
|
|
1045
1034
|
}
|
|
@@ -1105,15 +1094,13 @@ const proxy = defineCommand({
|
|
|
1105
1094
|
}
|
|
1106
1095
|
}
|
|
1107
1096
|
});
|
|
1108
|
-
|
|
1109
1097
|
//#endregion
|
|
1110
1098
|
//#region src/lib/shell.ts
|
|
1111
1099
|
function getShell() {
|
|
1112
1100
|
const { platform, ppid, env } = process$1;
|
|
1113
1101
|
if (platform === "win32") {
|
|
1114
1102
|
try {
|
|
1115
|
-
|
|
1116
|
-
if (execSync(command, { stdio: "pipe" }).toString().toLowerCase().includes("powershell.exe")) return "powershell";
|
|
1103
|
+
if (execSync(`wmic process get ParentProcessId,Name | findstr "${ppid}"`, { stdio: "pipe" }).toString().toLowerCase().includes("powershell.exe")) return "powershell";
|
|
1117
1104
|
} catch {
|
|
1118
1105
|
return "cmd";
|
|
1119
1106
|
}
|
|
@@ -1158,7 +1145,6 @@ function generateEnvScript(envVars, commandToRun = "") {
|
|
|
1158
1145
|
if (commandBlock && commandToRun) return `${commandBlock}${shell === "cmd" ? " & " : " && "}${commandToRun}`;
|
|
1159
1146
|
return commandBlock || commandToRun;
|
|
1160
1147
|
}
|
|
1161
|
-
|
|
1162
1148
|
//#endregion
|
|
1163
1149
|
//#region src/lib/api-key-auth.ts
|
|
1164
1150
|
/**
|
|
@@ -1190,31 +1176,9 @@ const apiKeyAuthMiddleware = async (c, next) => {
|
|
|
1190
1176
|
if (!state.apiKeys.includes(providedKey)) throw new HTTPException(401, { message: "Invalid API key. Please provide a valid API key." });
|
|
1191
1177
|
await next();
|
|
1192
1178
|
};
|
|
1193
|
-
|
|
1194
1179
|
//#endregion
|
|
1195
1180
|
//#region src/lib/model-logger.ts
|
|
1196
1181
|
/**
|
|
1197
|
-
* Global token usage store for passing usage info from handlers to logger.
|
|
1198
|
-
* Handlers call setTokenUsage() when usage is available,
|
|
1199
|
-
* logger reads and clears it after await next().
|
|
1200
|
-
*
|
|
1201
|
-
* For streaming responses, usage arrives after next() returns.
|
|
1202
|
-
* In that case the handler calls signalStreamDone() when the stream ends,
|
|
1203
|
-
* and the logger waits for it with a timeout.
|
|
1204
|
-
*/
|
|
1205
|
-
let pendingTokenUsage;
|
|
1206
|
-
let streamDoneResolve;
|
|
1207
|
-
function setTokenUsage(usage) {
|
|
1208
|
-
pendingTokenUsage = usage;
|
|
1209
|
-
}
|
|
1210
|
-
/**
|
|
1211
|
-
* Notify the logger that a streaming response has finished sending.
|
|
1212
|
-
* Must be called at the end of streamSSE callbacks.
|
|
1213
|
-
*/
|
|
1214
|
-
function signalStreamDone() {
|
|
1215
|
-
streamDoneResolve?.();
|
|
1216
|
-
}
|
|
1217
|
-
/**
|
|
1218
1182
|
* Get timestamp string in format HH:mm:ss
|
|
1219
1183
|
*/
|
|
1220
1184
|
function getTime() {
|
|
@@ -1228,15 +1192,6 @@ function formatDuration(ms) {
|
|
|
1228
1192
|
return `${(ms / 1e3).toFixed(1)}s`;
|
|
1229
1193
|
}
|
|
1230
1194
|
/**
|
|
1231
|
-
* Format token usage for log output
|
|
1232
|
-
*/
|
|
1233
|
-
function formatTokenUsage(usage) {
|
|
1234
|
-
const parts = [`in:${usage.inputTokens}`, `out:${usage.outputTokens}`];
|
|
1235
|
-
if (usage.cacheReadTokens) parts.push(`cache_read:${usage.cacheReadTokens}`);
|
|
1236
|
-
if (usage.cacheCreationTokens) parts.push(`cache_create:${usage.cacheCreationTokens}`);
|
|
1237
|
-
return parts.join(" ");
|
|
1238
|
-
}
|
|
1239
|
-
/**
|
|
1240
1195
|
* Extract model name from request body
|
|
1241
1196
|
*/
|
|
1242
1197
|
async function extractModel(c) {
|
|
@@ -1251,38 +1206,24 @@ async function extractModel(c) {
|
|
|
1251
1206
|
*
|
|
1252
1207
|
* Output format:
|
|
1253
1208
|
* [model] HH:mm:ss <-- METHOD /path
|
|
1254
|
-
* [model] HH:mm:ss --> METHOD /path STATUS DURATION
|
|
1209
|
+
* [model] HH:mm:ss --> METHOD /path STATUS DURATION
|
|
1255
1210
|
*/
|
|
1256
1211
|
function modelLogger() {
|
|
1257
1212
|
return async (c, next) => {
|
|
1258
1213
|
const method = c.req.method;
|
|
1259
|
-
const path$
|
|
1260
|
-
const queryString = c.req.raw.url.includes("?") ? `?${c.req.raw.url.split("?")[1]}` : "";
|
|
1261
|
-
const fullPath = `${path$2}${queryString}`;
|
|
1214
|
+
const fullPath = `${c.req.path}${c.req.raw.url.includes("?") ? `?${c.req.raw.url.split("?")[1]}` : ""}`;
|
|
1262
1215
|
let model;
|
|
1263
1216
|
if (method === "POST" && c.req.header("content-type")?.includes("json")) model = await extractModel(c);
|
|
1264
1217
|
const modelPrefix = model ? `[${model}] ` : "";
|
|
1265
1218
|
const startTime = getTime();
|
|
1266
|
-
pendingTokenUsage = void 0;
|
|
1267
|
-
const localStreamDone = new Promise((resolve) => {
|
|
1268
|
-
streamDoneResolve = resolve;
|
|
1269
|
-
});
|
|
1270
1219
|
console.log(`${modelPrefix}${startTime} <-- ${method} ${fullPath}`);
|
|
1271
|
-
const start
|
|
1220
|
+
const start = Date.now();
|
|
1272
1221
|
await next();
|
|
1273
|
-
|
|
1274
|
-
const timeout = new Promise((resolve) => setTimeout(resolve, 12e4));
|
|
1275
|
-
await Promise.race([localStreamDone, timeout]);
|
|
1276
|
-
}
|
|
1277
|
-
const duration = Date.now() - start$1;
|
|
1222
|
+
const duration = Date.now() - start;
|
|
1278
1223
|
const endTime = getTime();
|
|
1279
|
-
|
|
1280
|
-
pendingTokenUsage = void 0;
|
|
1281
|
-
const usageSuffix = usage ? ` [${formatTokenUsage(usage)}]` : "";
|
|
1282
|
-
console.log(`${modelPrefix}${endTime} --> ${method} ${fullPath} ${c.res.status} ${formatDuration(duration)}${usageSuffix}`);
|
|
1224
|
+
console.log(`${modelPrefix}${endTime} --> ${method} ${fullPath} ${c.res.status} ${formatDuration(duration)}`);
|
|
1283
1225
|
};
|
|
1284
1226
|
}
|
|
1285
|
-
|
|
1286
1227
|
//#endregion
|
|
1287
1228
|
//#region src/services/antigravity/stream-parser.ts
|
|
1288
1229
|
/**
|
|
@@ -1315,117 +1256,115 @@ function parseSSELine(line) {
|
|
|
1315
1256
|
* Extract candidates and usage from parsed data
|
|
1316
1257
|
*/
|
|
1317
1258
|
function extractFromData(data) {
|
|
1318
|
-
const candidates = data.response?.candidates || data.candidates || [];
|
|
1319
|
-
const usage = data.response?.usageMetadata || data.usageMetadata;
|
|
1320
1259
|
return {
|
|
1321
|
-
candidates,
|
|
1322
|
-
usage
|
|
1260
|
+
candidates: data.response?.candidates || data.candidates || [],
|
|
1261
|
+
usage: data.response?.usageMetadata || data.usageMetadata
|
|
1323
1262
|
};
|
|
1324
1263
|
}
|
|
1325
1264
|
/**
|
|
1326
1265
|
* Process a single part and emit events
|
|
1327
1266
|
*/
|
|
1328
|
-
function processPart(part, state
|
|
1267
|
+
function processPart(part, state, emit) {
|
|
1329
1268
|
if (part.thought && part.text) {
|
|
1330
|
-
processThinkingPart(part.text, state
|
|
1269
|
+
processThinkingPart(part.text, state, emit);
|
|
1331
1270
|
return;
|
|
1332
1271
|
}
|
|
1333
1272
|
if (part.text && !part.thought) {
|
|
1334
|
-
processTextPart(part.text, state
|
|
1273
|
+
processTextPart(part.text, state, emit);
|
|
1335
1274
|
return;
|
|
1336
1275
|
}
|
|
1337
|
-
if (part.functionCall) processToolPart(part.functionCall, state
|
|
1276
|
+
if (part.functionCall) processToolPart(part.functionCall, state, emit);
|
|
1338
1277
|
}
|
|
1339
1278
|
/**
|
|
1340
1279
|
* Process thinking content
|
|
1341
1280
|
*/
|
|
1342
|
-
function processThinkingPart(text, state
|
|
1343
|
-
if (!state
|
|
1281
|
+
function processThinkingPart(text, state, emit) {
|
|
1282
|
+
if (!state.thinkingBlockStarted) {
|
|
1344
1283
|
emit({
|
|
1345
1284
|
type: "thinking_start",
|
|
1346
|
-
index: state
|
|
1285
|
+
index: state.contentBlockIndex
|
|
1347
1286
|
});
|
|
1348
|
-
state
|
|
1287
|
+
state.thinkingBlockStarted = true;
|
|
1349
1288
|
}
|
|
1350
1289
|
emit({
|
|
1351
1290
|
type: "thinking_delta",
|
|
1352
|
-
index: state
|
|
1291
|
+
index: state.contentBlockIndex,
|
|
1353
1292
|
text
|
|
1354
1293
|
});
|
|
1355
1294
|
}
|
|
1356
1295
|
/**
|
|
1357
1296
|
* Process text content
|
|
1358
1297
|
*/
|
|
1359
|
-
function processTextPart(text, state
|
|
1360
|
-
if (state
|
|
1298
|
+
function processTextPart(text, state, emit) {
|
|
1299
|
+
if (state.thinkingBlockStarted && !state.textBlockStarted) {
|
|
1361
1300
|
emit({
|
|
1362
1301
|
type: "thinking_stop",
|
|
1363
|
-
index: state
|
|
1302
|
+
index: state.contentBlockIndex
|
|
1364
1303
|
});
|
|
1365
|
-
state
|
|
1366
|
-
state
|
|
1304
|
+
state.contentBlockIndex++;
|
|
1305
|
+
state.thinkingBlockStarted = false;
|
|
1367
1306
|
}
|
|
1368
|
-
if (!state
|
|
1307
|
+
if (!state.textBlockStarted) {
|
|
1369
1308
|
emit({
|
|
1370
1309
|
type: "text_start",
|
|
1371
|
-
index: state
|
|
1310
|
+
index: state.contentBlockIndex
|
|
1372
1311
|
});
|
|
1373
|
-
state
|
|
1312
|
+
state.textBlockStarted = true;
|
|
1374
1313
|
}
|
|
1375
1314
|
emit({
|
|
1376
1315
|
type: "text_delta",
|
|
1377
|
-
index: state
|
|
1316
|
+
index: state.contentBlockIndex,
|
|
1378
1317
|
text
|
|
1379
1318
|
});
|
|
1380
1319
|
}
|
|
1381
1320
|
/**
|
|
1382
1321
|
* Process tool/function call
|
|
1383
1322
|
*/
|
|
1384
|
-
function processToolPart(functionCall, state
|
|
1385
|
-
if (state
|
|
1323
|
+
function processToolPart(functionCall, state, emit) {
|
|
1324
|
+
if (state.textBlockStarted) {
|
|
1386
1325
|
emit({
|
|
1387
1326
|
type: "text_stop",
|
|
1388
|
-
index: state
|
|
1327
|
+
index: state.contentBlockIndex
|
|
1389
1328
|
});
|
|
1390
|
-
state
|
|
1391
|
-
state
|
|
1392
|
-
} else if (state
|
|
1329
|
+
state.contentBlockIndex++;
|
|
1330
|
+
state.textBlockStarted = false;
|
|
1331
|
+
} else if (state.thinkingBlockStarted) {
|
|
1393
1332
|
emit({
|
|
1394
1333
|
type: "thinking_stop",
|
|
1395
|
-
index: state
|
|
1334
|
+
index: state.contentBlockIndex
|
|
1396
1335
|
});
|
|
1397
|
-
state
|
|
1398
|
-
state
|
|
1336
|
+
state.contentBlockIndex++;
|
|
1337
|
+
state.thinkingBlockStarted = false;
|
|
1399
1338
|
}
|
|
1400
1339
|
emit({
|
|
1401
1340
|
type: "tool_use",
|
|
1402
|
-
index: state
|
|
1341
|
+
index: state.contentBlockIndex,
|
|
1403
1342
|
name: functionCall.name,
|
|
1404
1343
|
args: functionCall.args
|
|
1405
1344
|
});
|
|
1406
|
-
state
|
|
1345
|
+
state.contentBlockIndex++;
|
|
1407
1346
|
}
|
|
1408
1347
|
/**
|
|
1409
1348
|
* Handle finish reason and close open blocks
|
|
1410
1349
|
*/
|
|
1411
|
-
function handleFinish(state
|
|
1412
|
-
if (state
|
|
1350
|
+
function handleFinish(state, emit) {
|
|
1351
|
+
if (state.textBlockStarted) {
|
|
1413
1352
|
emit({
|
|
1414
1353
|
type: "text_stop",
|
|
1415
|
-
index: state
|
|
1354
|
+
index: state.contentBlockIndex
|
|
1416
1355
|
});
|
|
1417
|
-
state
|
|
1418
|
-
} else if (state
|
|
1356
|
+
state.textBlockStarted = false;
|
|
1357
|
+
} else if (state.thinkingBlockStarted) {
|
|
1419
1358
|
emit({
|
|
1420
1359
|
type: "thinking_stop",
|
|
1421
|
-
index: state
|
|
1360
|
+
index: state.contentBlockIndex
|
|
1422
1361
|
});
|
|
1423
|
-
state
|
|
1362
|
+
state.thinkingBlockStarted = false;
|
|
1424
1363
|
}
|
|
1425
1364
|
emit({
|
|
1426
1365
|
type: "usage",
|
|
1427
|
-
inputTokens: state
|
|
1428
|
-
outputTokens: state
|
|
1366
|
+
inputTokens: state.inputTokens,
|
|
1367
|
+
outputTokens: state.outputTokens
|
|
1429
1368
|
});
|
|
1430
1369
|
emit({
|
|
1431
1370
|
type: "finish",
|
|
@@ -1435,15 +1374,24 @@ function handleFinish(state$1, emit) {
|
|
|
1435
1374
|
/**
|
|
1436
1375
|
* Process chunk and update buffer, returning complete lines
|
|
1437
1376
|
*/
|
|
1438
|
-
function processChunk(chunk, state
|
|
1439
|
-
state
|
|
1440
|
-
const lines = state
|
|
1441
|
-
state
|
|
1377
|
+
function processChunk(chunk, state) {
|
|
1378
|
+
state.buffer += chunk;
|
|
1379
|
+
const lines = state.buffer.split("\n");
|
|
1380
|
+
state.buffer = lines.pop() || "";
|
|
1442
1381
|
return lines;
|
|
1443
1382
|
}
|
|
1444
|
-
|
|
1445
1383
|
//#endregion
|
|
1446
1384
|
//#region src/services/antigravity/create-chat-completions.ts
|
|
1385
|
+
/**
|
|
1386
|
+
* Google Antigravity Chat Completions
|
|
1387
|
+
*
|
|
1388
|
+
* Proxy chat completion requests to Google Antigravity API or standard Gemini API.
|
|
1389
|
+
* Supports two authentication methods:
|
|
1390
|
+
* - API Key: Uses standard Gemini API (generativelanguage.googleapis.com)
|
|
1391
|
+
* - OAuth: Uses Antigravity private API (daily-cloudcode-pa.sandbox.googleapis.com)
|
|
1392
|
+
*
|
|
1393
|
+
* Based on: https://github.com/liuw1535/antigravity2api-nodejs
|
|
1394
|
+
*/
|
|
1447
1395
|
const ANTIGRAVITY_API_HOST = "daily-cloudcode-pa.sandbox.googleapis.com";
|
|
1448
1396
|
const ANTIGRAVITY_STREAM_URL = `https://${ANTIGRAVITY_API_HOST}/v1internal:streamGenerateContent?alt=sse`;
|
|
1449
1397
|
const ANTIGRAVITY_NO_STREAM_URL = `https://${ANTIGRAVITY_API_HOST}/v1internal:generateContent`;
|
|
@@ -1710,14 +1658,14 @@ function generateRequestId() {
|
|
|
1710
1658
|
function transformStreamResponse$1(response, model) {
|
|
1711
1659
|
const reader = response.body?.getReader();
|
|
1712
1660
|
if (!reader) return new Response("No response body", { status: 500 });
|
|
1713
|
-
const encoder
|
|
1661
|
+
const encoder = new TextEncoder();
|
|
1714
1662
|
const decoder = new TextDecoder();
|
|
1715
1663
|
const requestId = generateRequestId();
|
|
1716
1664
|
const stream = new ReadableStream({ async start(controller) {
|
|
1717
|
-
const state
|
|
1665
|
+
const state = createStreamState();
|
|
1718
1666
|
try {
|
|
1719
|
-
await processOpenAIStream(reader, decoder, state
|
|
1720
|
-
controller.enqueue(encoder
|
|
1667
|
+
await processOpenAIStream(reader, decoder, state, controller, encoder, requestId, model);
|
|
1668
|
+
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
|
|
1721
1669
|
controller.close();
|
|
1722
1670
|
} catch (error) {
|
|
1723
1671
|
consola.error("Stream transform error:", error);
|
|
@@ -1733,12 +1681,11 @@ function transformStreamResponse$1(response, model) {
|
|
|
1733
1681
|
/**
|
|
1734
1682
|
* Process stream and emit OpenAI format chunks
|
|
1735
1683
|
*/
|
|
1736
|
-
async function processOpenAIStream(reader, decoder, state
|
|
1684
|
+
async function processOpenAIStream(reader, decoder, state, controller, encoder, requestId, model) {
|
|
1737
1685
|
while (true) {
|
|
1738
1686
|
const { done, value } = await reader.read();
|
|
1739
1687
|
if (done) break;
|
|
1740
|
-
const
|
|
1741
|
-
const lines = processChunk(chunk, state$1);
|
|
1688
|
+
const lines = processChunk(decoder.decode(value, { stream: true }), state);
|
|
1742
1689
|
for (const line of lines) {
|
|
1743
1690
|
const data = parseSSELine(line);
|
|
1744
1691
|
if (!data) continue;
|
|
@@ -1747,7 +1694,7 @@ async function processOpenAIStream(reader, decoder, state$1, controller, encoder
|
|
|
1747
1694
|
const parts = candidate?.content?.parts ?? [];
|
|
1748
1695
|
for (const part of parts) {
|
|
1749
1696
|
const chunkData = buildOpenAIChunk(part, requestId, model, candidate?.finishReason);
|
|
1750
|
-
if (chunkData) controller.enqueue(encoder
|
|
1697
|
+
if (chunkData) controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunkData)}\n\n`));
|
|
1751
1698
|
}
|
|
1752
1699
|
}
|
|
1753
1700
|
}
|
|
@@ -1802,8 +1749,7 @@ function buildOpenAIChunk(part, requestId, model, finishReason) {
|
|
|
1802
1749
|
async function transformNonStreamResponse$1(response, model) {
|
|
1803
1750
|
const rawData = await response.json();
|
|
1804
1751
|
const data = rawData.response ?? rawData;
|
|
1805
|
-
const
|
|
1806
|
-
const { content, reasoningContent, toolCalls } = extractNonStreamContent(parts);
|
|
1752
|
+
const { content, reasoningContent, toolCalls } = extractNonStreamContent((data.candidates?.[0])?.content?.parts ?? []);
|
|
1807
1753
|
const message = {
|
|
1808
1754
|
role: "assistant",
|
|
1809
1755
|
content: content || null
|
|
@@ -1853,9 +1799,13 @@ function extractNonStreamContent(parts) {
|
|
|
1853
1799
|
toolCalls
|
|
1854
1800
|
};
|
|
1855
1801
|
}
|
|
1856
|
-
|
|
1857
1802
|
//#endregion
|
|
1858
1803
|
//#region src/routes/antigravity/chat-completions/route.ts
|
|
1804
|
+
/**
|
|
1805
|
+
* Antigravity Chat Completions Route
|
|
1806
|
+
*
|
|
1807
|
+
* OpenAI-compatible chat completions endpoint for Antigravity.
|
|
1808
|
+
*/
|
|
1859
1809
|
const app$1 = new Hono();
|
|
1860
1810
|
app$1.post("/", async (c) => {
|
|
1861
1811
|
const body = await c.req.json();
|
|
@@ -1871,7 +1821,6 @@ app$1.post("/", async (c) => {
|
|
|
1871
1821
|
});
|
|
1872
1822
|
});
|
|
1873
1823
|
const antigravityChatCompletionsRoute = app$1;
|
|
1874
|
-
|
|
1875
1824
|
//#endregion
|
|
1876
1825
|
//#region src/lib/request-queue.ts
|
|
1877
1826
|
var RequestQueue = class {
|
|
@@ -1914,7 +1863,6 @@ var RequestQueue = class {
|
|
|
1914
1863
|
}
|
|
1915
1864
|
};
|
|
1916
1865
|
const antigravityQueue = new RequestQueue(2, 500);
|
|
1917
|
-
|
|
1918
1866
|
//#endregion
|
|
1919
1867
|
//#region src/services/antigravity/anthropic-events.ts
|
|
1920
1868
|
/**
|
|
@@ -2074,9 +2022,16 @@ function generateMessageId() {
|
|
|
2074
2022
|
function generateToolId() {
|
|
2075
2023
|
return `toolu_${Date.now()}`;
|
|
2076
2024
|
}
|
|
2077
|
-
|
|
2078
2025
|
//#endregion
|
|
2079
2026
|
//#region src/services/antigravity/create-messages.ts
|
|
2027
|
+
/**
|
|
2028
|
+
* Google Antigravity Messages API
|
|
2029
|
+
*
|
|
2030
|
+
* Converts Anthropic Messages API format to Antigravity format.
|
|
2031
|
+
* This enables Claude Code to use Antigravity as backend.
|
|
2032
|
+
*
|
|
2033
|
+
* Based on: https://github.com/liuw1535/antigravity2api-nodejs
|
|
2034
|
+
*/
|
|
2080
2035
|
const ANTIGRAVITY_ENDPOINTS = ["daily-cloudcode-pa.sandbox.googleapis.com", "cloudcode-pa.googleapis.com"];
|
|
2081
2036
|
let currentEndpointIndex = 0;
|
|
2082
2037
|
function getStreamUrl(host) {
|
|
@@ -2114,8 +2069,7 @@ function clearRateLimitTracker(model) {
|
|
|
2114
2069
|
if (rateLimitTracker[family]) rateLimitTracker[family].consecutiveErrors = 0;
|
|
2115
2070
|
}
|
|
2116
2071
|
function getBackoffDelay(model, baseDelay) {
|
|
2117
|
-
const
|
|
2118
|
-
const info = rateLimitTracker[family];
|
|
2072
|
+
const info = rateLimitTracker[getModelFamily(model)];
|
|
2119
2073
|
if (!info) return baseDelay;
|
|
2120
2074
|
const multiplier = Math.min(Math.pow(2, info.consecutiveErrors - 1), 60);
|
|
2121
2075
|
return Math.min(baseDelay * multiplier, 3e4);
|
|
@@ -2296,8 +2250,7 @@ function createErrorResponse(type, message, status) {
|
|
|
2296
2250
|
const MAX_RETRIES$3 = 5;
|
|
2297
2251
|
const MAX_ENDPOINT_RETRIES = 2;
|
|
2298
2252
|
async function executeAntigravityRequest(request) {
|
|
2299
|
-
const
|
|
2300
|
-
const body = buildGeminiRequest(request, projectId);
|
|
2253
|
+
const body = buildGeminiRequest(request, await getCurrentProjectId());
|
|
2301
2254
|
let endpointRetries = 0;
|
|
2302
2255
|
for (let attempt = 0; attempt <= MAX_RETRIES$3; attempt++) {
|
|
2303
2256
|
const host = getCurrentHost();
|
|
@@ -2408,7 +2361,7 @@ async function handleApiError(response, _model) {
|
|
|
2408
2361
|
/**
|
|
2409
2362
|
* Emit SSE event to controller based on stream event type
|
|
2410
2363
|
*/
|
|
2411
|
-
function emitSSEEvent(event, controller, state
|
|
2364
|
+
function emitSSEEvent(event, controller, state) {
|
|
2412
2365
|
switch (event.type) {
|
|
2413
2366
|
case "thinking_start":
|
|
2414
2367
|
controller.enqueue(createThinkingBlockStart(event.index));
|
|
@@ -2432,11 +2385,11 @@ function emitSSEEvent(event, controller, state$1) {
|
|
|
2432
2385
|
emitToolUseEvents(event, controller);
|
|
2433
2386
|
break;
|
|
2434
2387
|
case "usage":
|
|
2435
|
-
state
|
|
2436
|
-
state
|
|
2388
|
+
state.inputTokens = event.inputTokens;
|
|
2389
|
+
state.outputTokens = event.outputTokens;
|
|
2437
2390
|
break;
|
|
2438
2391
|
case "finish":
|
|
2439
|
-
controller.enqueue(createMessageDelta(event.stopReason, state
|
|
2392
|
+
controller.enqueue(createMessageDelta(event.stopReason, state.outputTokens));
|
|
2440
2393
|
break;
|
|
2441
2394
|
}
|
|
2442
2395
|
}
|
|
@@ -2458,10 +2411,10 @@ function transformStreamResponse(response, model) {
|
|
|
2458
2411
|
const decoder = new TextDecoder();
|
|
2459
2412
|
const messageId = generateMessageId();
|
|
2460
2413
|
const stream = new ReadableStream({ async start(controller) {
|
|
2461
|
-
const state
|
|
2414
|
+
const state = createStreamState();
|
|
2462
2415
|
controller.enqueue(createMessageStart(messageId, model));
|
|
2463
2416
|
try {
|
|
2464
|
-
await processStream(reader, decoder, state
|
|
2417
|
+
await processStream(reader, decoder, state, controller);
|
|
2465
2418
|
controller.enqueue(createMessageStop());
|
|
2466
2419
|
controller.close();
|
|
2467
2420
|
} catch (error) {
|
|
@@ -2478,11 +2431,11 @@ function transformStreamResponse(response, model) {
|
|
|
2478
2431
|
/**
|
|
2479
2432
|
* Process candidate parts and handle finish
|
|
2480
2433
|
*/
|
|
2481
|
-
function processCandidate(candidate, state
|
|
2434
|
+
function processCandidate(candidate, state, emit) {
|
|
2482
2435
|
const parts = candidate?.content?.parts ?? [];
|
|
2483
|
-
for (const part of parts) processPart(part, state
|
|
2436
|
+
for (const part of parts) processPart(part, state, emit);
|
|
2484
2437
|
if (candidate?.finishReason === "STOP") {
|
|
2485
|
-
handleFinish(state
|
|
2438
|
+
handleFinish(state, emit);
|
|
2486
2439
|
return true;
|
|
2487
2440
|
}
|
|
2488
2441
|
return false;
|
|
@@ -2490,23 +2443,23 @@ function processCandidate(candidate, state$1, emit) {
|
|
|
2490
2443
|
/**
|
|
2491
2444
|
* Process the stream and emit events
|
|
2492
2445
|
*/
|
|
2493
|
-
async function processStream(reader, decoder, state
|
|
2494
|
-
const emit = (event) => emitSSEEvent(event, controller, state
|
|
2446
|
+
async function processStream(reader, decoder, state, controller) {
|
|
2447
|
+
const emit = (event) => emitSSEEvent(event, controller, state);
|
|
2495
2448
|
let finished = false;
|
|
2496
2449
|
while (!finished) {
|
|
2497
2450
|
const { done, value } = await reader.read();
|
|
2498
2451
|
if (done) break;
|
|
2499
|
-
const lines = processChunk(decoder.decode(value, { stream: true }), state
|
|
2452
|
+
const lines = processChunk(decoder.decode(value, { stream: true }), state);
|
|
2500
2453
|
for (const line of lines) {
|
|
2501
2454
|
if (finished) break;
|
|
2502
2455
|
const data = parseSSELine(line);
|
|
2503
2456
|
if (!data) continue;
|
|
2504
2457
|
const { candidates, usage } = extractFromData(data);
|
|
2505
2458
|
if (usage) {
|
|
2506
|
-
state
|
|
2507
|
-
state
|
|
2459
|
+
state.inputTokens = usage.promptTokenCount ?? state.inputTokens;
|
|
2460
|
+
state.outputTokens = usage.candidatesTokenCount ?? state.outputTokens;
|
|
2508
2461
|
}
|
|
2509
|
-
if (candidates[0] && processCandidate(candidates[0], state
|
|
2462
|
+
if (candidates[0] && processCandidate(candidates[0], state, emit)) {
|
|
2510
2463
|
finished = true;
|
|
2511
2464
|
break;
|
|
2512
2465
|
}
|
|
@@ -2519,8 +2472,7 @@ async function processStream(reader, decoder, state$1, controller) {
|
|
|
2519
2472
|
async function transformNonStreamResponse(response, model) {
|
|
2520
2473
|
const rawData = await response.json();
|
|
2521
2474
|
const data = rawData.response ?? rawData;
|
|
2522
|
-
const
|
|
2523
|
-
const content = buildNonStreamContent(parts);
|
|
2475
|
+
const content = buildNonStreamContent((data.candidates?.[0])?.content?.parts ?? []);
|
|
2524
2476
|
const anthropicResponse = {
|
|
2525
2477
|
id: generateMessageId(),
|
|
2526
2478
|
type: "message",
|
|
@@ -2559,9 +2511,14 @@ function buildNonStreamContent(parts) {
|
|
|
2559
2511
|
}
|
|
2560
2512
|
return content;
|
|
2561
2513
|
}
|
|
2562
|
-
|
|
2563
2514
|
//#endregion
|
|
2564
2515
|
//#region src/routes/antigravity/messages/route.ts
|
|
2516
|
+
/**
|
|
2517
|
+
* Antigravity Messages Route
|
|
2518
|
+
*
|
|
2519
|
+
* Anthropic-compatible messages endpoint for Antigravity.
|
|
2520
|
+
* This enables Claude Code to use Antigravity as backend.
|
|
2521
|
+
*/
|
|
2565
2522
|
const antigravityMessagesRoute = new Hono();
|
|
2566
2523
|
antigravityMessagesRoute.post("/", async (c) => {
|
|
2567
2524
|
if (!state.antigravityMode) return c.json({ error: "Antigravity mode is not enabled. Start with --antigravity flag." }, 400);
|
|
@@ -2592,53 +2549,54 @@ antigravityMessagesRoute.post("/", async (c) => {
|
|
|
2592
2549
|
}, 500);
|
|
2593
2550
|
}
|
|
2594
2551
|
});
|
|
2595
|
-
|
|
2596
2552
|
//#endregion
|
|
2597
2553
|
//#region src/routes/antigravity/models/route.ts
|
|
2554
|
+
/**
|
|
2555
|
+
* Antigravity Models Route
|
|
2556
|
+
*
|
|
2557
|
+
* OpenAI-compatible models endpoint for Antigravity.
|
|
2558
|
+
*/
|
|
2598
2559
|
const app = new Hono();
|
|
2599
2560
|
app.get("/", async (c) => {
|
|
2600
2561
|
const models = await getAntigravityModels();
|
|
2601
2562
|
return c.json(models);
|
|
2602
2563
|
});
|
|
2603
2564
|
const antigravityModelsRoute = app;
|
|
2604
|
-
|
|
2605
2565
|
//#endregion
|
|
2606
2566
|
//#region src/lib/approval.ts
|
|
2607
2567
|
const awaitApproval = async () => {
|
|
2608
2568
|
if (!await consola.prompt(`Accept incoming request?`, { type: "confirm" })) throw new HTTPError("Request rejected", Response.json({ message: "Request rejected" }, { status: 403 }));
|
|
2609
2569
|
};
|
|
2610
|
-
|
|
2611
2570
|
//#endregion
|
|
2612
2571
|
//#region src/lib/rate-limit.ts
|
|
2613
|
-
async function checkRateLimit(state
|
|
2614
|
-
if (state
|
|
2572
|
+
async function checkRateLimit(state) {
|
|
2573
|
+
if (state.rateLimitSeconds === void 0) return;
|
|
2615
2574
|
const now = Date.now();
|
|
2616
|
-
if (!state
|
|
2617
|
-
state
|
|
2575
|
+
if (!state.lastRequestTimestamp) {
|
|
2576
|
+
state.lastRequestTimestamp = now;
|
|
2618
2577
|
return;
|
|
2619
2578
|
}
|
|
2620
|
-
const elapsedSeconds = (now - state
|
|
2621
|
-
if (elapsedSeconds > state
|
|
2622
|
-
state
|
|
2579
|
+
const elapsedSeconds = (now - state.lastRequestTimestamp) / 1e3;
|
|
2580
|
+
if (elapsedSeconds > state.rateLimitSeconds) {
|
|
2581
|
+
state.lastRequestTimestamp = now;
|
|
2623
2582
|
return;
|
|
2624
2583
|
}
|
|
2625
|
-
const waitTimeSeconds = Math.ceil(state
|
|
2626
|
-
if (!state
|
|
2584
|
+
const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds);
|
|
2585
|
+
if (!state.rateLimitWait) {
|
|
2627
2586
|
consola.warn(`Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`);
|
|
2628
2587
|
throw new HTTPError("Rate limit exceeded", Response.json({ message: "Rate limit exceeded" }, { status: 429 }));
|
|
2629
2588
|
}
|
|
2630
2589
|
const waitTimeMs = waitTimeSeconds * 1e3;
|
|
2631
2590
|
consola.warn(`Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`);
|
|
2632
2591
|
await sleep(waitTimeMs);
|
|
2633
|
-
state
|
|
2592
|
+
state.lastRequestTimestamp = now;
|
|
2634
2593
|
consola.info("Rate limit wait completed, proceeding with request");
|
|
2635
2594
|
}
|
|
2636
|
-
|
|
2637
2595
|
//#endregion
|
|
2638
2596
|
//#region src/services/copilot/create-chat-completions.ts
|
|
2639
2597
|
const createChatCompletions = async (payload) => {
|
|
2640
2598
|
if (!state.copilotToken) throw new Error("Copilot token not found");
|
|
2641
|
-
const enableVision = payload.messages.some((x) => typeof x.content !== "string" && x.content?.some((x
|
|
2599
|
+
const enableVision = payload.messages.some((x) => typeof x.content !== "string" && x.content?.some((x) => x.type === "image_url"));
|
|
2642
2600
|
const isAgentCall = payload.messages.some((msg) => ["assistant", "tool"].includes(msg.role));
|
|
2643
2601
|
const buildHeaders = () => ({
|
|
2644
2602
|
...copilotHeaders(state, enableVision),
|
|
@@ -2688,7 +2646,8 @@ const createChatCompletions = async (payload) => {
|
|
|
2688
2646
|
}
|
|
2689
2647
|
if (!response.ok) {
|
|
2690
2648
|
const errorBody = await response.text();
|
|
2691
|
-
|
|
2649
|
+
if (response.status === 400) consola.warn(`400: ${errorBody}`);
|
|
2650
|
+
else consola.error("Failed to create chat completions", {
|
|
2692
2651
|
status: response.status,
|
|
2693
2652
|
statusText: response.statusText,
|
|
2694
2653
|
body: errorBody
|
|
@@ -2698,7 +2657,6 @@ const createChatCompletions = async (payload) => {
|
|
|
2698
2657
|
if (payload.stream) return events(response);
|
|
2699
2658
|
return await response.json();
|
|
2700
2659
|
};
|
|
2701
|
-
|
|
2702
2660
|
//#endregion
|
|
2703
2661
|
//#region src/routes/chat-completions/handler.ts
|
|
2704
2662
|
/**
|
|
@@ -2727,38 +2685,17 @@ async function handleCompletion$1(c) {
|
|
|
2727
2685
|
const response = await createChatCompletions(payload);
|
|
2728
2686
|
if (isNonStreaming$1(response)) {
|
|
2729
2687
|
consola.debug("Non-streaming response:", JSON.stringify(response));
|
|
2730
|
-
if (response.usage) setTokenUsage({
|
|
2731
|
-
inputTokens: response.usage.prompt_tokens,
|
|
2732
|
-
outputTokens: response.usage.completion_tokens,
|
|
2733
|
-
cacheReadTokens: response.usage.prompt_tokens_details?.cached_tokens
|
|
2734
|
-
});
|
|
2735
2688
|
return c.json(response);
|
|
2736
2689
|
}
|
|
2737
2690
|
consola.debug("Streaming response");
|
|
2738
2691
|
return streamSSE(c, async (stream) => {
|
|
2739
2692
|
for await (const chunk of response) {
|
|
2740
2693
|
consola.debug("Streaming chunk:", JSON.stringify(chunk));
|
|
2741
|
-
try {
|
|
2742
|
-
const sseChunk = chunk;
|
|
2743
|
-
if (sseChunk.data && sseChunk.data !== "[DONE]") {
|
|
2744
|
-
const parsed = JSON.parse(sseChunk.data);
|
|
2745
|
-
if (parsed.usage) {
|
|
2746
|
-
const usage = {
|
|
2747
|
-
inputTokens: parsed.usage.prompt_tokens ?? 0,
|
|
2748
|
-
outputTokens: parsed.usage.completion_tokens ?? 0,
|
|
2749
|
-
cacheReadTokens: parsed.usage.prompt_tokens_details?.cached_tokens
|
|
2750
|
-
};
|
|
2751
|
-
setTokenUsage(usage);
|
|
2752
|
-
}
|
|
2753
|
-
}
|
|
2754
|
-
} catch {}
|
|
2755
2694
|
await stream.writeSSE(chunk);
|
|
2756
2695
|
}
|
|
2757
|
-
signalStreamDone();
|
|
2758
2696
|
});
|
|
2759
2697
|
}
|
|
2760
2698
|
const isNonStreaming$1 = (response) => Object.hasOwn(response, "choices");
|
|
2761
|
-
|
|
2762
2699
|
//#endregion
|
|
2763
2700
|
//#region src/routes/chat-completions/route.ts
|
|
2764
2701
|
const completionRoutes = new Hono();
|
|
@@ -2769,7 +2706,6 @@ completionRoutes.post("/", async (c) => {
|
|
|
2769
2706
|
return await forwardError(c, error);
|
|
2770
2707
|
}
|
|
2771
2708
|
});
|
|
2772
|
-
|
|
2773
2709
|
//#endregion
|
|
2774
2710
|
//#region src/services/copilot/create-embeddings.ts
|
|
2775
2711
|
const createEmbeddings = async (payload) => {
|
|
@@ -2782,20 +2718,17 @@ const createEmbeddings = async (payload) => {
|
|
|
2782
2718
|
if (!response.ok) throw new HTTPError("Failed to create embeddings", response);
|
|
2783
2719
|
return await response.json();
|
|
2784
2720
|
};
|
|
2785
|
-
|
|
2786
2721
|
//#endregion
|
|
2787
2722
|
//#region src/routes/embeddings/route.ts
|
|
2788
2723
|
const embeddingRoutes = new Hono();
|
|
2789
2724
|
embeddingRoutes.post("/", async (c) => {
|
|
2790
2725
|
try {
|
|
2791
|
-
const
|
|
2792
|
-
const response = await createEmbeddings(paylod);
|
|
2726
|
+
const response = await createEmbeddings(await c.req.json());
|
|
2793
2727
|
return c.json(response);
|
|
2794
2728
|
} catch (error) {
|
|
2795
2729
|
return await forwardError(c, error);
|
|
2796
2730
|
}
|
|
2797
2731
|
});
|
|
2798
|
-
|
|
2799
2732
|
//#endregion
|
|
2800
2733
|
//#region src/lib/tokenizer.ts
|
|
2801
2734
|
const ENCODING_MAP = {
|
|
@@ -2809,11 +2742,11 @@ const encodingCache = /* @__PURE__ */ new Map();
|
|
|
2809
2742
|
/**
|
|
2810
2743
|
* Calculate tokens for tool calls
|
|
2811
2744
|
*/
|
|
2812
|
-
const calculateToolCallsTokens = (toolCalls, encoder
|
|
2745
|
+
const calculateToolCallsTokens = (toolCalls, encoder, constants) => {
|
|
2813
2746
|
let tokens = 0;
|
|
2814
2747
|
for (const toolCall of toolCalls) {
|
|
2815
2748
|
tokens += constants.funcInit;
|
|
2816
|
-
tokens += encoder
|
|
2749
|
+
tokens += encoder.encode(JSON.stringify(toolCall)).length;
|
|
2817
2750
|
}
|
|
2818
2751
|
tokens += constants.funcEnd;
|
|
2819
2752
|
return tokens;
|
|
@@ -2821,34 +2754,34 @@ const calculateToolCallsTokens = (toolCalls, encoder$1, constants) => {
|
|
|
2821
2754
|
/**
|
|
2822
2755
|
* Calculate tokens for content parts
|
|
2823
2756
|
*/
|
|
2824
|
-
const calculateContentPartsTokens = (contentParts, encoder
|
|
2757
|
+
const calculateContentPartsTokens = (contentParts, encoder) => {
|
|
2825
2758
|
let tokens = 0;
|
|
2826
|
-
for (const part of contentParts) if (part.type === "image_url") tokens += encoder
|
|
2827
|
-
else if (part.text) tokens += encoder
|
|
2759
|
+
for (const part of contentParts) if (part.type === "image_url") tokens += encoder.encode(part.image_url.url).length + 85;
|
|
2760
|
+
else if (part.text) tokens += encoder.encode(part.text).length;
|
|
2828
2761
|
return tokens;
|
|
2829
2762
|
};
|
|
2830
2763
|
/**
|
|
2831
2764
|
* Calculate tokens for a single message
|
|
2832
2765
|
*/
|
|
2833
|
-
const calculateMessageTokens = (message, encoder
|
|
2766
|
+
const calculateMessageTokens = (message, encoder, constants) => {
|
|
2834
2767
|
const tokensPerMessage = 3;
|
|
2835
2768
|
const tokensPerName = 1;
|
|
2836
2769
|
let tokens = tokensPerMessage;
|
|
2837
2770
|
for (const [key, value] of Object.entries(message)) {
|
|
2838
|
-
if (typeof value === "string") tokens += encoder
|
|
2771
|
+
if (typeof value === "string") tokens += encoder.encode(value).length;
|
|
2839
2772
|
if (key === "name") tokens += tokensPerName;
|
|
2840
|
-
if (key === "tool_calls") tokens += calculateToolCallsTokens(value, encoder
|
|
2841
|
-
if (key === "content" && Array.isArray(value)) tokens += calculateContentPartsTokens(value, encoder
|
|
2773
|
+
if (key === "tool_calls") tokens += calculateToolCallsTokens(value, encoder, constants);
|
|
2774
|
+
if (key === "content" && Array.isArray(value)) tokens += calculateContentPartsTokens(value, encoder);
|
|
2842
2775
|
}
|
|
2843
2776
|
return tokens;
|
|
2844
2777
|
};
|
|
2845
2778
|
/**
|
|
2846
2779
|
* Calculate tokens using custom algorithm
|
|
2847
2780
|
*/
|
|
2848
|
-
const calculateTokens = (messages, encoder
|
|
2781
|
+
const calculateTokens = (messages, encoder, constants) => {
|
|
2849
2782
|
if (messages.length === 0) return 0;
|
|
2850
2783
|
let numTokens = 0;
|
|
2851
|
-
for (const message of messages) numTokens += calculateMessageTokens(message, encoder
|
|
2784
|
+
for (const message of messages) numTokens += calculateMessageTokens(message, encoder, constants);
|
|
2852
2785
|
numTokens += 3;
|
|
2853
2786
|
return numTokens;
|
|
2854
2787
|
};
|
|
@@ -2900,7 +2833,7 @@ const getModelConstants = (model) => {
|
|
|
2900
2833
|
* Calculate tokens for a single parameter
|
|
2901
2834
|
*/
|
|
2902
2835
|
const calculateParameterTokens = (key, prop, context) => {
|
|
2903
|
-
const { encoder
|
|
2836
|
+
const { encoder, constants } = context;
|
|
2904
2837
|
let tokens = constants.propKey;
|
|
2905
2838
|
if (typeof prop !== "object" || prop === null) return tokens;
|
|
2906
2839
|
const param = prop;
|
|
@@ -2911,12 +2844,12 @@ const calculateParameterTokens = (key, prop, context) => {
|
|
|
2911
2844
|
tokens += constants.enumInit;
|
|
2912
2845
|
for (const item of param.enum) {
|
|
2913
2846
|
tokens += constants.enumItem;
|
|
2914
|
-
tokens += encoder
|
|
2847
|
+
tokens += encoder.encode(String(item)).length;
|
|
2915
2848
|
}
|
|
2916
2849
|
}
|
|
2917
2850
|
if (paramDesc.endsWith(".")) paramDesc = paramDesc.slice(0, -1);
|
|
2918
2851
|
const line = `${paramName}:${paramType}:${paramDesc}`;
|
|
2919
|
-
tokens += encoder
|
|
2852
|
+
tokens += encoder.encode(line).length;
|
|
2920
2853
|
const excludedKeys = new Set([
|
|
2921
2854
|
"type",
|
|
2922
2855
|
"description",
|
|
@@ -2925,14 +2858,14 @@ const calculateParameterTokens = (key, prop, context) => {
|
|
|
2925
2858
|
for (const propertyName of Object.keys(param)) if (!excludedKeys.has(propertyName)) {
|
|
2926
2859
|
const propertyValue = param[propertyName];
|
|
2927
2860
|
const propertyText = typeof propertyValue === "string" ? propertyValue : JSON.stringify(propertyValue);
|
|
2928
|
-
tokens += encoder
|
|
2861
|
+
tokens += encoder.encode(`${propertyName}:${propertyText}`).length;
|
|
2929
2862
|
}
|
|
2930
2863
|
return tokens;
|
|
2931
2864
|
};
|
|
2932
2865
|
/**
|
|
2933
2866
|
* Calculate tokens for function parameters
|
|
2934
2867
|
*/
|
|
2935
|
-
const calculateParametersTokens = (parameters, encoder
|
|
2868
|
+
const calculateParametersTokens = (parameters, encoder, constants) => {
|
|
2936
2869
|
if (!parameters || typeof parameters !== "object") return 0;
|
|
2937
2870
|
const params = parameters;
|
|
2938
2871
|
let tokens = 0;
|
|
@@ -2941,36 +2874,36 @@ const calculateParametersTokens = (parameters, encoder$1, constants) => {
|
|
|
2941
2874
|
if (Object.keys(properties).length > 0) {
|
|
2942
2875
|
tokens += constants.propInit;
|
|
2943
2876
|
for (const propKey of Object.keys(properties)) tokens += calculateParameterTokens(propKey, properties[propKey], {
|
|
2944
|
-
encoder
|
|
2877
|
+
encoder,
|
|
2945
2878
|
constants
|
|
2946
2879
|
});
|
|
2947
2880
|
}
|
|
2948
2881
|
} else {
|
|
2949
2882
|
const paramText = typeof value === "string" ? value : JSON.stringify(value);
|
|
2950
|
-
tokens += encoder
|
|
2883
|
+
tokens += encoder.encode(`${key}:${paramText}`).length;
|
|
2951
2884
|
}
|
|
2952
2885
|
return tokens;
|
|
2953
2886
|
};
|
|
2954
2887
|
/**
|
|
2955
2888
|
* Calculate tokens for a single tool
|
|
2956
2889
|
*/
|
|
2957
|
-
const calculateToolTokens = (tool, encoder
|
|
2890
|
+
const calculateToolTokens = (tool, encoder, constants) => {
|
|
2958
2891
|
let tokens = constants.funcInit;
|
|
2959
2892
|
const func = tool.function;
|
|
2960
2893
|
const fName = func.name;
|
|
2961
2894
|
let fDesc = func.description || "";
|
|
2962
2895
|
if (fDesc.endsWith(".")) fDesc = fDesc.slice(0, -1);
|
|
2963
2896
|
const line = fName + ":" + fDesc;
|
|
2964
|
-
tokens += encoder
|
|
2965
|
-
if (typeof func.parameters === "object" && func.parameters !== null) tokens += calculateParametersTokens(func.parameters, encoder
|
|
2897
|
+
tokens += encoder.encode(line).length;
|
|
2898
|
+
if (typeof func.parameters === "object" && func.parameters !== null) tokens += calculateParametersTokens(func.parameters, encoder, constants);
|
|
2966
2899
|
return tokens;
|
|
2967
2900
|
};
|
|
2968
2901
|
/**
|
|
2969
2902
|
* Calculate token count for tools based on model
|
|
2970
2903
|
*/
|
|
2971
|
-
const numTokensForTools = (tools, encoder
|
|
2904
|
+
const numTokensForTools = (tools, encoder, constants) => {
|
|
2972
2905
|
let funcTokenCount = 0;
|
|
2973
|
-
for (const tool of tools) funcTokenCount += calculateToolTokens(tool, encoder
|
|
2906
|
+
for (const tool of tools) funcTokenCount += calculateToolTokens(tool, encoder, constants);
|
|
2974
2907
|
funcTokenCount += constants.funcEnd;
|
|
2975
2908
|
return funcTokenCount;
|
|
2976
2909
|
};
|
|
@@ -2978,17 +2911,15 @@ const numTokensForTools = (tools, encoder$1, constants) => {
|
|
|
2978
2911
|
* Calculate the token count of messages, supporting multiple GPT encoders
|
|
2979
2912
|
*/
|
|
2980
2913
|
const getTokenCount = async (payload, model) => {
|
|
2981
|
-
const
|
|
2982
|
-
const encoder$1 = await getEncodeChatFunction(tokenizer);
|
|
2914
|
+
const encoder = await getEncodeChatFunction(getTokenizerFromModel(model));
|
|
2983
2915
|
const constants = getModelConstants(model);
|
|
2984
|
-
let inputTokens = calculateTokens(payload.messages, encoder
|
|
2985
|
-
if (payload.tools && payload.tools.length > 0) inputTokens += numTokensForTools(payload.tools, encoder
|
|
2916
|
+
let inputTokens = calculateTokens(payload.messages, encoder, constants);
|
|
2917
|
+
if (payload.tools && payload.tools.length > 0) inputTokens += numTokensForTools(payload.tools, encoder, constants);
|
|
2986
2918
|
return {
|
|
2987
2919
|
input: inputTokens,
|
|
2988
2920
|
output: 0
|
|
2989
2921
|
};
|
|
2990
2922
|
};
|
|
2991
|
-
|
|
2992
2923
|
//#endregion
|
|
2993
2924
|
//#region src/routes/messages/utils.ts
|
|
2994
2925
|
function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
@@ -3000,7 +2931,6 @@ function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
|
3000
2931
|
content_filter: "end_turn"
|
|
3001
2932
|
}[finishReason];
|
|
3002
2933
|
}
|
|
3003
|
-
|
|
3004
2934
|
//#endregion
|
|
3005
2935
|
//#region src/routes/messages/non-stream-translation.ts
|
|
3006
2936
|
function translateToOpenAI(payload) {
|
|
@@ -3197,7 +3127,6 @@ function getAnthropicToolUseBlocks(toolCalls) {
|
|
|
3197
3127
|
input: JSON.parse(toolCall.function.arguments)
|
|
3198
3128
|
}));
|
|
3199
3129
|
}
|
|
3200
|
-
|
|
3201
3130
|
//#endregion
|
|
3202
3131
|
//#region src/routes/messages/count-tokens-handler.ts
|
|
3203
3132
|
/**
|
|
@@ -3237,20 +3166,19 @@ async function handleCountTokens(c) {
|
|
|
3237
3166
|
return c.json({ input_tokens: 1 });
|
|
3238
3167
|
}
|
|
3239
3168
|
}
|
|
3240
|
-
|
|
3241
3169
|
//#endregion
|
|
3242
3170
|
//#region src/routes/messages/stream-translation.ts
|
|
3243
|
-
function isToolBlockOpen(state
|
|
3244
|
-
if (!state
|
|
3245
|
-
return Object.values(state
|
|
3171
|
+
function isToolBlockOpen(state) {
|
|
3172
|
+
if (!state.contentBlockOpen) return false;
|
|
3173
|
+
return Object.values(state.toolCalls).some((tc) => tc.anthropicBlockIndex === state.contentBlockIndex);
|
|
3246
3174
|
}
|
|
3247
|
-
function translateChunkToAnthropicEvents(chunk, state
|
|
3248
|
-
const events
|
|
3249
|
-
if (chunk.choices.length === 0) return events
|
|
3175
|
+
function translateChunkToAnthropicEvents(chunk, state) {
|
|
3176
|
+
const events = [];
|
|
3177
|
+
if (chunk.choices.length === 0) return events;
|
|
3250
3178
|
const choice = chunk.choices[0];
|
|
3251
3179
|
const { delta } = choice;
|
|
3252
|
-
if (!state
|
|
3253
|
-
events
|
|
3180
|
+
if (!state.messageStartSent) {
|
|
3181
|
+
events.push({
|
|
3254
3182
|
type: "message_start",
|
|
3255
3183
|
message: {
|
|
3256
3184
|
id: chunk.id,
|
|
@@ -3267,31 +3195,31 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
|
|
|
3267
3195
|
}
|
|
3268
3196
|
}
|
|
3269
3197
|
});
|
|
3270
|
-
state
|
|
3198
|
+
state.messageStartSent = true;
|
|
3271
3199
|
}
|
|
3272
3200
|
if (delta.content) {
|
|
3273
|
-
if (isToolBlockOpen(state
|
|
3274
|
-
events
|
|
3201
|
+
if (isToolBlockOpen(state)) {
|
|
3202
|
+
events.push({
|
|
3275
3203
|
type: "content_block_stop",
|
|
3276
|
-
index: state
|
|
3204
|
+
index: state.contentBlockIndex
|
|
3277
3205
|
});
|
|
3278
|
-
state
|
|
3279
|
-
state
|
|
3206
|
+
state.contentBlockIndex++;
|
|
3207
|
+
state.contentBlockOpen = false;
|
|
3280
3208
|
}
|
|
3281
|
-
if (!state
|
|
3282
|
-
events
|
|
3209
|
+
if (!state.contentBlockOpen) {
|
|
3210
|
+
events.push({
|
|
3283
3211
|
type: "content_block_start",
|
|
3284
|
-
index: state
|
|
3212
|
+
index: state.contentBlockIndex,
|
|
3285
3213
|
content_block: {
|
|
3286
3214
|
type: "text",
|
|
3287
3215
|
text: ""
|
|
3288
3216
|
}
|
|
3289
3217
|
});
|
|
3290
|
-
state
|
|
3218
|
+
state.contentBlockOpen = true;
|
|
3291
3219
|
}
|
|
3292
|
-
events
|
|
3220
|
+
events.push({
|
|
3293
3221
|
type: "content_block_delta",
|
|
3294
|
-
index: state
|
|
3222
|
+
index: state.contentBlockIndex,
|
|
3295
3223
|
delta: {
|
|
3296
3224
|
type: "text_delta",
|
|
3297
3225
|
text: delta.content
|
|
@@ -3300,21 +3228,21 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
|
|
|
3300
3228
|
}
|
|
3301
3229
|
if (delta.tool_calls) for (const toolCall of delta.tool_calls) {
|
|
3302
3230
|
if (toolCall.id && toolCall.function?.name) {
|
|
3303
|
-
if (state
|
|
3304
|
-
events
|
|
3231
|
+
if (state.contentBlockOpen) {
|
|
3232
|
+
events.push({
|
|
3305
3233
|
type: "content_block_stop",
|
|
3306
|
-
index: state
|
|
3234
|
+
index: state.contentBlockIndex
|
|
3307
3235
|
});
|
|
3308
|
-
state
|
|
3309
|
-
state
|
|
3236
|
+
state.contentBlockIndex++;
|
|
3237
|
+
state.contentBlockOpen = false;
|
|
3310
3238
|
}
|
|
3311
|
-
const anthropicBlockIndex = state
|
|
3312
|
-
state
|
|
3239
|
+
const anthropicBlockIndex = state.contentBlockIndex;
|
|
3240
|
+
state.toolCalls[toolCall.index] = {
|
|
3313
3241
|
id: toolCall.id,
|
|
3314
3242
|
name: toolCall.function.name,
|
|
3315
3243
|
anthropicBlockIndex
|
|
3316
3244
|
};
|
|
3317
|
-
events
|
|
3245
|
+
events.push({
|
|
3318
3246
|
type: "content_block_start",
|
|
3319
3247
|
index: anthropicBlockIndex,
|
|
3320
3248
|
content_block: {
|
|
@@ -3324,11 +3252,11 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
|
|
|
3324
3252
|
input: {}
|
|
3325
3253
|
}
|
|
3326
3254
|
});
|
|
3327
|
-
state
|
|
3255
|
+
state.contentBlockOpen = true;
|
|
3328
3256
|
}
|
|
3329
3257
|
if (toolCall.function?.arguments) {
|
|
3330
|
-
const toolCallInfo = state
|
|
3331
|
-
if (toolCallInfo) events
|
|
3258
|
+
const toolCallInfo = state.toolCalls[toolCall.index];
|
|
3259
|
+
if (toolCallInfo) events.push({
|
|
3332
3260
|
type: "content_block_delta",
|
|
3333
3261
|
index: toolCallInfo.anthropicBlockIndex,
|
|
3334
3262
|
delta: {
|
|
@@ -3339,14 +3267,14 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
|
|
|
3339
3267
|
}
|
|
3340
3268
|
}
|
|
3341
3269
|
if (choice.finish_reason) {
|
|
3342
|
-
if (state
|
|
3343
|
-
events
|
|
3270
|
+
if (state.contentBlockOpen) {
|
|
3271
|
+
events.push({
|
|
3344
3272
|
type: "content_block_stop",
|
|
3345
|
-
index: state
|
|
3273
|
+
index: state.contentBlockIndex
|
|
3346
3274
|
});
|
|
3347
|
-
state
|
|
3275
|
+
state.contentBlockOpen = false;
|
|
3348
3276
|
}
|
|
3349
|
-
events
|
|
3277
|
+
events.push({
|
|
3350
3278
|
type: "message_delta",
|
|
3351
3279
|
delta: {
|
|
3352
3280
|
stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),
|
|
@@ -3359,25 +3287,17 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
|
|
|
3359
3287
|
}
|
|
3360
3288
|
}, { type: "message_stop" });
|
|
3361
3289
|
}
|
|
3362
|
-
return events
|
|
3290
|
+
return events;
|
|
3363
3291
|
}
|
|
3364
|
-
|
|
3365
3292
|
//#endregion
|
|
3366
3293
|
//#region src/routes/messages/handler.ts
|
|
3367
3294
|
async function handleCompletion(c) {
|
|
3368
3295
|
await checkRateLimit(state);
|
|
3369
|
-
const
|
|
3370
|
-
const openAIPayload = translateToOpenAI(anthropicPayload);
|
|
3296
|
+
const openAIPayload = translateToOpenAI(await c.req.json());
|
|
3371
3297
|
if (state.manualApprove) await awaitApproval();
|
|
3372
3298
|
const response = await createChatCompletions(openAIPayload);
|
|
3373
3299
|
if (isNonStreaming(response)) {
|
|
3374
3300
|
const anthropicResponse = translateToAnthropic(response);
|
|
3375
|
-
setTokenUsage({
|
|
3376
|
-
inputTokens: anthropicResponse.usage.input_tokens,
|
|
3377
|
-
outputTokens: anthropicResponse.usage.output_tokens,
|
|
3378
|
-
cacheReadTokens: anthropicResponse.usage.cache_read_input_tokens,
|
|
3379
|
-
cacheCreationTokens: anthropicResponse.usage.cache_creation_input_tokens
|
|
3380
|
-
});
|
|
3381
3301
|
return c.json(anthropicResponse);
|
|
3382
3302
|
}
|
|
3383
3303
|
return streamSSE(c, async (stream) => {
|
|
@@ -3390,26 +3310,15 @@ async function handleCompletion(c) {
|
|
|
3390
3310
|
for await (const rawEvent of response) {
|
|
3391
3311
|
if (rawEvent.data === "[DONE]") break;
|
|
3392
3312
|
if (!rawEvent.data) continue;
|
|
3393
|
-
const
|
|
3394
|
-
const events
|
|
3395
|
-
if (chunk.usage) {
|
|
3396
|
-
const usage = {
|
|
3397
|
-
inputTokens: chunk.usage.prompt_tokens - (chunk.usage.prompt_tokens_details?.cached_tokens ?? 0),
|
|
3398
|
-
outputTokens: chunk.usage.completion_tokens,
|
|
3399
|
-
cacheReadTokens: chunk.usage.prompt_tokens_details?.cached_tokens
|
|
3400
|
-
};
|
|
3401
|
-
setTokenUsage(usage);
|
|
3402
|
-
}
|
|
3403
|
-
for (const event of events$1) await stream.writeSSE({
|
|
3313
|
+
const events = translateChunkToAnthropicEvents(JSON.parse(rawEvent.data), streamState);
|
|
3314
|
+
for (const event of events) await stream.writeSSE({
|
|
3404
3315
|
event: event.type,
|
|
3405
3316
|
data: JSON.stringify(event)
|
|
3406
3317
|
});
|
|
3407
3318
|
}
|
|
3408
|
-
signalStreamDone();
|
|
3409
3319
|
});
|
|
3410
3320
|
}
|
|
3411
3321
|
const isNonStreaming = (response) => Object.hasOwn(response, "choices");
|
|
3412
|
-
|
|
3413
3322
|
//#endregion
|
|
3414
3323
|
//#region src/routes/messages/route.ts
|
|
3415
3324
|
const messageRoutes = new Hono();
|
|
@@ -3427,7 +3336,6 @@ messageRoutes.post("/count_tokens", async (c) => {
|
|
|
3427
3336
|
return await forwardError(c, error);
|
|
3428
3337
|
}
|
|
3429
3338
|
});
|
|
3430
|
-
|
|
3431
3339
|
//#endregion
|
|
3432
3340
|
//#region src/routes/models/route.ts
|
|
3433
3341
|
const modelRoutes = new Hono();
|
|
@@ -3452,7 +3360,6 @@ modelRoutes.get("/", async (c) => {
|
|
|
3452
3360
|
return await forwardError(c, error);
|
|
3453
3361
|
}
|
|
3454
3362
|
});
|
|
3455
|
-
|
|
3456
3363
|
//#endregion
|
|
3457
3364
|
//#region src/routes/token/route.ts
|
|
3458
3365
|
const tokenRoute = new Hono();
|
|
@@ -3467,15 +3374,14 @@ tokenRoute.get("/", (c) => {
|
|
|
3467
3374
|
}, 500);
|
|
3468
3375
|
}
|
|
3469
3376
|
});
|
|
3470
|
-
|
|
3471
3377
|
//#endregion
|
|
3472
3378
|
//#region src/routes/usage/route.ts
|
|
3473
3379
|
const usageRoute = new Hono();
|
|
3474
3380
|
usageRoute.get("/", async (c) => {
|
|
3475
3381
|
try {
|
|
3476
3382
|
if (state.antigravityMode) {
|
|
3477
|
-
const usage
|
|
3478
|
-
return c.json(usage
|
|
3383
|
+
const usage = await getAntigravityUsage();
|
|
3384
|
+
return c.json(usage);
|
|
3479
3385
|
}
|
|
3480
3386
|
if (state.zenMode) return c.json({
|
|
3481
3387
|
error: "Usage statistics not available for Zen mode",
|
|
@@ -3491,9 +3397,13 @@ usageRoute.get("/", async (c) => {
|
|
|
3491
3397
|
return c.json({ error: "Failed to fetch Copilot usage" }, 500);
|
|
3492
3398
|
}
|
|
3493
3399
|
});
|
|
3494
|
-
|
|
3495
3400
|
//#endregion
|
|
3496
3401
|
//#region src/services/zen/create-chat-completions.ts
|
|
3402
|
+
/**
|
|
3403
|
+
* OpenCode Zen Chat Completions Proxy
|
|
3404
|
+
*
|
|
3405
|
+
* Proxies chat completion requests to OpenCode Zen API.
|
|
3406
|
+
*/
|
|
3497
3407
|
const MAX_RETRIES$2 = 5;
|
|
3498
3408
|
const DEFAULT_RETRY_DELAY$2 = 500;
|
|
3499
3409
|
/**
|
|
@@ -3549,9 +3459,13 @@ async function createZenChatCompletions(request, signal) {
|
|
|
3549
3459
|
}
|
|
3550
3460
|
throw new Error("Max retries exceeded");
|
|
3551
3461
|
}
|
|
3552
|
-
|
|
3553
3462
|
//#endregion
|
|
3554
3463
|
//#region src/routes/zen/chat-completions/route.ts
|
|
3464
|
+
/**
|
|
3465
|
+
* OpenCode Zen Chat Completions Route
|
|
3466
|
+
*
|
|
3467
|
+
* Proxies OpenAI-format chat completion requests to Zen.
|
|
3468
|
+
*/
|
|
3555
3469
|
const zenCompletionRoutes = new Hono();
|
|
3556
3470
|
zenCompletionRoutes.post("/", async (c) => {
|
|
3557
3471
|
if (!state.zenMode || !state.zenApiKey) return c.json({ error: "Zen mode is not enabled. Start with --zen flag." }, 400);
|
|
@@ -3579,9 +3493,13 @@ zenCompletionRoutes.post("/", async (c) => {
|
|
|
3579
3493
|
} }, 500);
|
|
3580
3494
|
}
|
|
3581
3495
|
});
|
|
3582
|
-
|
|
3583
3496
|
//#endregion
|
|
3584
3497
|
//#region src/services/zen/create-messages.ts
|
|
3498
|
+
/**
|
|
3499
|
+
* OpenCode Zen Messages Proxy
|
|
3500
|
+
*
|
|
3501
|
+
* Proxies Anthropic-format message requests to OpenCode Zen API.
|
|
3502
|
+
*/
|
|
3585
3503
|
const MAX_RETRIES$1 = 5;
|
|
3586
3504
|
const DEFAULT_RETRY_DELAY$1 = 500;
|
|
3587
3505
|
/**
|
|
@@ -3638,9 +3556,14 @@ async function createZenMessages(request, signal) {
|
|
|
3638
3556
|
}
|
|
3639
3557
|
throw new Error("Max retries exceeded");
|
|
3640
3558
|
}
|
|
3641
|
-
|
|
3642
3559
|
//#endregion
|
|
3643
3560
|
//#region src/routes/zen/messages/route.ts
|
|
3561
|
+
/**
|
|
3562
|
+
* OpenCode Zen Messages Route
|
|
3563
|
+
*
|
|
3564
|
+
* Proxies Anthropic-format message requests to Zen.
|
|
3565
|
+
* This enables Claude Code to use Zen as backend.
|
|
3566
|
+
*/
|
|
3644
3567
|
const zenMessageRoutes = new Hono();
|
|
3645
3568
|
zenMessageRoutes.post("/", async (c) => {
|
|
3646
3569
|
if (!state.zenMode || !state.zenApiKey) return c.json({ error: "Zen mode is not enabled. Start with --zen flag." }, 400);
|
|
@@ -3671,15 +3594,19 @@ zenMessageRoutes.post("/", async (c) => {
|
|
|
3671
3594
|
}, 500);
|
|
3672
3595
|
}
|
|
3673
3596
|
});
|
|
3674
|
-
|
|
3675
3597
|
//#endregion
|
|
3676
3598
|
//#region src/routes/zen/models/route.ts
|
|
3599
|
+
/**
|
|
3600
|
+
* OpenCode Zen Models Route
|
|
3601
|
+
*
|
|
3602
|
+
* Returns available models from Zen.
|
|
3603
|
+
*/
|
|
3677
3604
|
const zenModelRoutes = new Hono();
|
|
3678
3605
|
zenModelRoutes.get("/", async (c) => {
|
|
3679
3606
|
if (!state.zenMode || !state.zenApiKey) return c.json({ error: "Zen mode is not enabled. Start with --zen flag." }, 400);
|
|
3680
3607
|
try {
|
|
3681
3608
|
if (state.zenModels) return c.json(state.zenModels);
|
|
3682
|
-
const { getZenModels } = await import("./get-models-
|
|
3609
|
+
const { getZenModels } = await import("./get-models-onnSXkNI.js");
|
|
3683
3610
|
const models = await getZenModels();
|
|
3684
3611
|
state.zenModels = models;
|
|
3685
3612
|
return c.json(models);
|
|
@@ -3691,9 +3618,14 @@ zenModelRoutes.get("/", async (c) => {
|
|
|
3691
3618
|
} }, 500);
|
|
3692
3619
|
}
|
|
3693
3620
|
});
|
|
3694
|
-
|
|
3695
3621
|
//#endregion
|
|
3696
3622
|
//#region src/services/zen/create-responses.ts
|
|
3623
|
+
/**
|
|
3624
|
+
* OpenCode Zen Responses Proxy
|
|
3625
|
+
*
|
|
3626
|
+
* Proxies OpenAI Responses API requests to OpenCode Zen.
|
|
3627
|
+
* Used for GPT-5 series models with stateful, agentic tool-use.
|
|
3628
|
+
*/
|
|
3697
3629
|
const MAX_RETRIES = 5;
|
|
3698
3630
|
const DEFAULT_RETRY_DELAY = 500;
|
|
3699
3631
|
/**
|
|
@@ -3749,9 +3681,14 @@ async function createZenResponses(request, signal) {
|
|
|
3749
3681
|
}
|
|
3750
3682
|
throw new Error("Max retries exceeded");
|
|
3751
3683
|
}
|
|
3752
|
-
|
|
3753
3684
|
//#endregion
|
|
3754
3685
|
//#region src/routes/zen/responses/route.ts
|
|
3686
|
+
/**
|
|
3687
|
+
* OpenCode Zen Responses Route
|
|
3688
|
+
*
|
|
3689
|
+
* Proxies OpenAI Responses API requests to Zen.
|
|
3690
|
+
* Used for GPT-5 series models.
|
|
3691
|
+
*/
|
|
3755
3692
|
const zenResponsesRoutes = new Hono();
|
|
3756
3693
|
zenResponsesRoutes.post("/", async (c) => {
|
|
3757
3694
|
if (!state.zenMode || !state.zenApiKey) return c.json({ error: "Zen mode is not enabled. Start with --zen flag." }, 400);
|
|
@@ -3779,7 +3716,6 @@ zenResponsesRoutes.post("/", async (c) => {
|
|
|
3779
3716
|
} }, 500);
|
|
3780
3717
|
}
|
|
3781
3718
|
});
|
|
3782
|
-
|
|
3783
3719
|
//#endregion
|
|
3784
3720
|
//#region src/server.ts
|
|
3785
3721
|
const server = new Hono();
|
|
@@ -3873,7 +3809,6 @@ server.route("/zen/v1/responses", zenResponsesRoutes);
|
|
|
3873
3809
|
server.route("/antigravity/v1/chat/completions", antigravityChatCompletionsRoute);
|
|
3874
3810
|
server.route("/antigravity/v1/models", antigravityModelsRoute);
|
|
3875
3811
|
server.route("/antigravity/v1/messages", antigravityMessagesRoute);
|
|
3876
|
-
|
|
3877
3812
|
//#endregion
|
|
3878
3813
|
//#region src/start.ts
|
|
3879
3814
|
/**
|
|
@@ -3902,51 +3837,51 @@ server.route("/antigravity/v1/messages", antigravityMessagesRoute);
|
|
|
3902
3837
|
* - antigravityClientId: Google OAuth Client ID (optional; overrides env/default)
|
|
3903
3838
|
* - antigravityClientSecret: Google OAuth Client Secret (optional; overrides env/default)
|
|
3904
3839
|
*/
|
|
3905
|
-
async function runServer(options
|
|
3840
|
+
async function runServer(options) {
|
|
3906
3841
|
const savedProxyApplied = await applyProxyConfig();
|
|
3907
|
-
if (options
|
|
3842
|
+
if (options.proxyEnv) initProxyFromEnv();
|
|
3908
3843
|
else if (savedProxyApplied) initProxyFromEnv();
|
|
3909
|
-
if (options
|
|
3844
|
+
if (options.verbose) {
|
|
3910
3845
|
consola.level = 5;
|
|
3911
3846
|
consola.info("Verbose logging enabled");
|
|
3912
3847
|
}
|
|
3913
|
-
state.accountType = options
|
|
3914
|
-
if (options
|
|
3915
|
-
state.manualApprove = options
|
|
3916
|
-
state.rateLimitSeconds = options
|
|
3917
|
-
state.rateLimitWait = options
|
|
3918
|
-
state.showToken = options
|
|
3919
|
-
state.apiKeys = options
|
|
3848
|
+
state.accountType = options.accountType;
|
|
3849
|
+
if (options.accountType !== "individual") consola.info(`Using ${options.accountType} plan GitHub account`);
|
|
3850
|
+
state.manualApprove = options.manual;
|
|
3851
|
+
state.rateLimitSeconds = options.rateLimit;
|
|
3852
|
+
state.rateLimitWait = options.rateLimitWait;
|
|
3853
|
+
state.showToken = options.showToken;
|
|
3854
|
+
state.apiKeys = options.apiKeys;
|
|
3920
3855
|
if (state.apiKeys && state.apiKeys.length > 0) consola.info(`API key authentication enabled with ${state.apiKeys.length} key(s)`);
|
|
3921
3856
|
await ensurePaths();
|
|
3922
|
-
if (options
|
|
3857
|
+
if (options.zen) {
|
|
3923
3858
|
consola.info("OpenCode Zen mode enabled");
|
|
3924
3859
|
state.zenMode = true;
|
|
3925
|
-
if (options
|
|
3926
|
-
state.zenApiKey = options
|
|
3860
|
+
if (options.zenApiKey) {
|
|
3861
|
+
state.zenApiKey = options.zenApiKey;
|
|
3927
3862
|
consola.info("Using provided Zen API key");
|
|
3928
3863
|
} else {
|
|
3929
|
-
const { setupZenApiKey, loadZenAuth } = await import("./auth-
|
|
3864
|
+
const { setupZenApiKey, loadZenAuth } = await import("./auth-g7psLP1B.js");
|
|
3930
3865
|
const existingAuth = await loadZenAuth();
|
|
3931
3866
|
if (existingAuth) {
|
|
3932
3867
|
state.zenApiKey = existingAuth.apiKey;
|
|
3933
3868
|
consola.info("Using existing Zen API key");
|
|
3934
3869
|
} else state.zenApiKey = await setupZenApiKey();
|
|
3935
3870
|
}
|
|
3936
|
-
const { cacheZenModels } = await import("./get-models-
|
|
3871
|
+
const { cacheZenModels } = await import("./get-models-onnSXkNI.js");
|
|
3937
3872
|
await cacheZenModels();
|
|
3938
3873
|
consola.info(`Available Zen models: \n${state.zenModels?.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
3939
|
-
} else if (options
|
|
3874
|
+
} else if (options.antigravity) {
|
|
3940
3875
|
consola.info("Google Antigravity mode enabled");
|
|
3941
3876
|
state.antigravityMode = true;
|
|
3942
|
-
const { loadAntigravityAuth, setupAntigravity, getCurrentAccount, hasApiKey, getApiKey
|
|
3943
|
-
if (options
|
|
3944
|
-
setOAuthCredentials(options
|
|
3877
|
+
const { loadAntigravityAuth, setupAntigravity, getCurrentAccount, hasApiKey, getApiKey, setOAuthCredentials } = await import("./auth-DreFwlx2.js");
|
|
3878
|
+
if (options.antigravityClientId && options.antigravityClientSecret) {
|
|
3879
|
+
setOAuthCredentials(options.antigravityClientId, options.antigravityClientSecret);
|
|
3945
3880
|
consola.info("Using provided OAuth credentials from CLI");
|
|
3946
3881
|
}
|
|
3947
3882
|
if (hasApiKey()) {
|
|
3948
3883
|
consola.info("Using Gemini API Key for authentication (from GEMINI_API_KEY)");
|
|
3949
|
-
consola.info(`API Key: ${getApiKey
|
|
3884
|
+
consola.info(`API Key: ${getApiKey()?.slice(0, 10) ?? ""}...`);
|
|
3950
3885
|
} else {
|
|
3951
3886
|
const existingAuth = await loadAntigravityAuth();
|
|
3952
3887
|
if (!existingAuth || existingAuth.accounts.length === 0) {
|
|
@@ -3968,17 +3903,17 @@ async function runServer(options$1) {
|
|
|
3968
3903
|
}
|
|
3969
3904
|
if (!await getCurrentAccount() && !hasApiKey()) throw new Error("No enabled Antigravity accounts available");
|
|
3970
3905
|
}
|
|
3971
|
-
const { getAntigravityModels
|
|
3972
|
-
const models = await getAntigravityModels
|
|
3906
|
+
const { getAntigravityModels } = await import("./get-models-PKzVxQmq.js");
|
|
3907
|
+
const models = await getAntigravityModels();
|
|
3973
3908
|
state.antigravityModels = models;
|
|
3974
3909
|
consola.info(`Available Antigravity models: \n${models.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
3975
3910
|
} else {
|
|
3976
3911
|
await cacheVSCodeVersion();
|
|
3977
|
-
if (options
|
|
3978
|
-
state.githubToken = options
|
|
3912
|
+
if (options.githubToken) {
|
|
3913
|
+
state.githubToken = options.githubToken;
|
|
3979
3914
|
consola.info("Using provided GitHub token");
|
|
3980
3915
|
try {
|
|
3981
|
-
const { getGitHubUser } = await import("./get-user-
|
|
3916
|
+
const { getGitHubUser } = await import("./get-user-CtEiwKow.js");
|
|
3982
3917
|
const user = await getGitHubUser();
|
|
3983
3918
|
consola.info(`Logged in as ${user.login}`);
|
|
3984
3919
|
} catch (error) {
|
|
@@ -3989,11 +3924,11 @@ async function runServer(options$1) {
|
|
|
3989
3924
|
try {
|
|
3990
3925
|
await setupCopilotToken();
|
|
3991
3926
|
} catch (error) {
|
|
3992
|
-
const { HTTPError
|
|
3993
|
-
if (error instanceof HTTPError
|
|
3927
|
+
const { HTTPError } = await import("./error-4DW6q2Mo.js");
|
|
3928
|
+
if (error instanceof HTTPError && error.response.status === 401) {
|
|
3994
3929
|
consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
|
|
3995
|
-
const { clearGithubToken
|
|
3996
|
-
await clearGithubToken
|
|
3930
|
+
const { clearGithubToken } = await import("./token-B_0VZjlS.js");
|
|
3931
|
+
await clearGithubToken();
|
|
3997
3932
|
consola.info("Please restart to re-authenticate");
|
|
3998
3933
|
}
|
|
3999
3934
|
throw error;
|
|
@@ -4001,8 +3936,8 @@ async function runServer(options$1) {
|
|
|
4001
3936
|
await cacheModels();
|
|
4002
3937
|
consola.info(`Available models: \n${state.models?.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
4003
3938
|
}
|
|
4004
|
-
const serverUrl = `http://localhost:${options
|
|
4005
|
-
if (options
|
|
3939
|
+
const serverUrl = `http://localhost:${options.port}`;
|
|
3940
|
+
if (options.claudeCode) {
|
|
4006
3941
|
let modelList;
|
|
4007
3942
|
if (state.zenMode) modelList = state.zenModels?.data;
|
|
4008
3943
|
else if (state.antigravityMode) modelList = state.antigravityModels?.data;
|
|
@@ -4037,128 +3972,12 @@ async function runServer(options$1) {
|
|
|
4037
3972
|
consola.box(`🌐 Usage Viewer: https://imbuxiangnan-cyber.github.io/copilot-api-plus?endpoint=${serverUrl}/usage`);
|
|
4038
3973
|
serve({
|
|
4039
3974
|
fetch: server.fetch,
|
|
4040
|
-
port: options
|
|
3975
|
+
port: options.port
|
|
4041
3976
|
});
|
|
4042
3977
|
}
|
|
4043
|
-
const start = defineCommand({
|
|
4044
|
-
meta: {
|
|
4045
|
-
name: "start",
|
|
4046
|
-
description: "Start the Copilot API server"
|
|
4047
|
-
},
|
|
4048
|
-
args: {
|
|
4049
|
-
port: {
|
|
4050
|
-
alias: "p",
|
|
4051
|
-
type: "string",
|
|
4052
|
-
default: "4141",
|
|
4053
|
-
description: "Port to listen on"
|
|
4054
|
-
},
|
|
4055
|
-
verbose: {
|
|
4056
|
-
alias: "v",
|
|
4057
|
-
type: "boolean",
|
|
4058
|
-
default: false,
|
|
4059
|
-
description: "Enable verbose logging"
|
|
4060
|
-
},
|
|
4061
|
-
"account-type": {
|
|
4062
|
-
alias: "a",
|
|
4063
|
-
type: "string",
|
|
4064
|
-
default: "individual",
|
|
4065
|
-
description: "Account type to use (individual, business, enterprise)"
|
|
4066
|
-
},
|
|
4067
|
-
manual: {
|
|
4068
|
-
type: "boolean",
|
|
4069
|
-
default: false,
|
|
4070
|
-
description: "Enable manual request approval"
|
|
4071
|
-
},
|
|
4072
|
-
"rate-limit": {
|
|
4073
|
-
alias: "r",
|
|
4074
|
-
type: "string",
|
|
4075
|
-
description: "Rate limit in seconds between requests"
|
|
4076
|
-
},
|
|
4077
|
-
wait: {
|
|
4078
|
-
alias: "w",
|
|
4079
|
-
type: "boolean",
|
|
4080
|
-
default: false,
|
|
4081
|
-
description: "Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"
|
|
4082
|
-
},
|
|
4083
|
-
"github-token": {
|
|
4084
|
-
alias: "g",
|
|
4085
|
-
type: "string",
|
|
4086
|
-
description: "Provide GitHub token directly (must be generated using the `auth` subcommand)"
|
|
4087
|
-
},
|
|
4088
|
-
"claude-code": {
|
|
4089
|
-
alias: "c",
|
|
4090
|
-
type: "boolean",
|
|
4091
|
-
default: false,
|
|
4092
|
-
description: "Generate a command to launch Claude Code with Copilot API config"
|
|
4093
|
-
},
|
|
4094
|
-
"show-token": {
|
|
4095
|
-
type: "boolean",
|
|
4096
|
-
default: false,
|
|
4097
|
-
description: "Show GitHub and Copilot tokens on fetch and refresh"
|
|
4098
|
-
},
|
|
4099
|
-
"proxy-env": {
|
|
4100
|
-
type: "boolean",
|
|
4101
|
-
default: false,
|
|
4102
|
-
description: "Initialize proxy from environment variables"
|
|
4103
|
-
},
|
|
4104
|
-
"api-key": {
|
|
4105
|
-
type: "string",
|
|
4106
|
-
description: "API keys for authentication"
|
|
4107
|
-
},
|
|
4108
|
-
zen: {
|
|
4109
|
-
alias: "z",
|
|
4110
|
-
type: "boolean",
|
|
4111
|
-
default: false,
|
|
4112
|
-
description: "Enable OpenCode Zen mode (proxy to Zen instead of GitHub Copilot)"
|
|
4113
|
-
},
|
|
4114
|
-
"zen-api-key": {
|
|
4115
|
-
type: "string",
|
|
4116
|
-
description: "OpenCode Zen API key (get from https://opencode.ai/zen)"
|
|
4117
|
-
},
|
|
4118
|
-
antigravity: {
|
|
4119
|
-
type: "boolean",
|
|
4120
|
-
default: false,
|
|
4121
|
-
description: "Enable Google Antigravity mode (proxy to Antigravity instead of GitHub Copilot)"
|
|
4122
|
-
},
|
|
4123
|
-
"antigravity-client-id": {
|
|
4124
|
-
type: "string",
|
|
4125
|
-
description: "Google OAuth Client ID for Antigravity (create at https://console.cloud.google.com/apis/credentials)"
|
|
4126
|
-
},
|
|
4127
|
-
"antigravity-client-secret": {
|
|
4128
|
-
type: "string",
|
|
4129
|
-
description: "Google OAuth Client Secret for Antigravity"
|
|
4130
|
-
}
|
|
4131
|
-
},
|
|
4132
|
-
run({ args }) {
|
|
4133
|
-
const rateLimitRaw = args["rate-limit"];
|
|
4134
|
-
const rateLimit = rateLimitRaw === void 0 ? void 0 : Number.parseInt(rateLimitRaw, 10);
|
|
4135
|
-
const apiKeyRaw = args["api-key"];
|
|
4136
|
-
let apiKeys;
|
|
4137
|
-
if (apiKeyRaw) apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw];
|
|
4138
|
-
return runServer({
|
|
4139
|
-
port: Number.parseInt(args.port, 10),
|
|
4140
|
-
verbose: args.verbose,
|
|
4141
|
-
accountType: args["account-type"],
|
|
4142
|
-
manual: args.manual,
|
|
4143
|
-
rateLimit,
|
|
4144
|
-
rateLimitWait: args.wait,
|
|
4145
|
-
githubToken: args["github-token"],
|
|
4146
|
-
claudeCode: args["claude-code"],
|
|
4147
|
-
showToken: args["show-token"],
|
|
4148
|
-
proxyEnv: args["proxy-env"],
|
|
4149
|
-
apiKeys,
|
|
4150
|
-
zen: args.zen,
|
|
4151
|
-
zenApiKey: args["zen-api-key"],
|
|
4152
|
-
antigravity: args.antigravity,
|
|
4153
|
-
antigravityClientId: args["antigravity-client-id"],
|
|
4154
|
-
antigravityClientSecret: args["antigravity-client-secret"]
|
|
4155
|
-
});
|
|
4156
|
-
}
|
|
4157
|
-
});
|
|
4158
|
-
|
|
4159
3978
|
//#endregion
|
|
4160
3979
|
//#region src/main.ts
|
|
4161
|
-
|
|
3980
|
+
await runMain(defineCommand({
|
|
4162
3981
|
meta: {
|
|
4163
3982
|
name: "copilot-api-plus",
|
|
4164
3983
|
description: "A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements."
|
|
@@ -4166,15 +3985,128 @@ const main = defineCommand({
|
|
|
4166
3985
|
subCommands: {
|
|
4167
3986
|
antigravity,
|
|
4168
3987
|
auth,
|
|
4169
|
-
start
|
|
3988
|
+
start: defineCommand({
|
|
3989
|
+
meta: {
|
|
3990
|
+
name: "start",
|
|
3991
|
+
description: "Start the Copilot API server"
|
|
3992
|
+
},
|
|
3993
|
+
args: {
|
|
3994
|
+
port: {
|
|
3995
|
+
alias: "p",
|
|
3996
|
+
type: "string",
|
|
3997
|
+
default: "4141",
|
|
3998
|
+
description: "Port to listen on"
|
|
3999
|
+
},
|
|
4000
|
+
verbose: {
|
|
4001
|
+
alias: "v",
|
|
4002
|
+
type: "boolean",
|
|
4003
|
+
default: false,
|
|
4004
|
+
description: "Enable verbose logging"
|
|
4005
|
+
},
|
|
4006
|
+
"account-type": {
|
|
4007
|
+
alias: "a",
|
|
4008
|
+
type: "string",
|
|
4009
|
+
default: "individual",
|
|
4010
|
+
description: "Account type to use (individual, business, enterprise)"
|
|
4011
|
+
},
|
|
4012
|
+
manual: {
|
|
4013
|
+
type: "boolean",
|
|
4014
|
+
default: false,
|
|
4015
|
+
description: "Enable manual request approval"
|
|
4016
|
+
},
|
|
4017
|
+
"rate-limit": {
|
|
4018
|
+
alias: "r",
|
|
4019
|
+
type: "string",
|
|
4020
|
+
description: "Rate limit in seconds between requests"
|
|
4021
|
+
},
|
|
4022
|
+
wait: {
|
|
4023
|
+
alias: "w",
|
|
4024
|
+
type: "boolean",
|
|
4025
|
+
default: false,
|
|
4026
|
+
description: "Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"
|
|
4027
|
+
},
|
|
4028
|
+
"github-token": {
|
|
4029
|
+
alias: "g",
|
|
4030
|
+
type: "string",
|
|
4031
|
+
description: "Provide GitHub token directly (must be generated using the `auth` subcommand)"
|
|
4032
|
+
},
|
|
4033
|
+
"claude-code": {
|
|
4034
|
+
alias: "c",
|
|
4035
|
+
type: "boolean",
|
|
4036
|
+
default: false,
|
|
4037
|
+
description: "Generate a command to launch Claude Code with Copilot API config"
|
|
4038
|
+
},
|
|
4039
|
+
"show-token": {
|
|
4040
|
+
type: "boolean",
|
|
4041
|
+
default: false,
|
|
4042
|
+
description: "Show GitHub and Copilot tokens on fetch and refresh"
|
|
4043
|
+
},
|
|
4044
|
+
"proxy-env": {
|
|
4045
|
+
type: "boolean",
|
|
4046
|
+
default: false,
|
|
4047
|
+
description: "Initialize proxy from environment variables"
|
|
4048
|
+
},
|
|
4049
|
+
"api-key": {
|
|
4050
|
+
type: "string",
|
|
4051
|
+
description: "API keys for authentication"
|
|
4052
|
+
},
|
|
4053
|
+
zen: {
|
|
4054
|
+
alias: "z",
|
|
4055
|
+
type: "boolean",
|
|
4056
|
+
default: false,
|
|
4057
|
+
description: "Enable OpenCode Zen mode (proxy to Zen instead of GitHub Copilot)"
|
|
4058
|
+
},
|
|
4059
|
+
"zen-api-key": {
|
|
4060
|
+
type: "string",
|
|
4061
|
+
description: "OpenCode Zen API key (get from https://opencode.ai/zen)"
|
|
4062
|
+
},
|
|
4063
|
+
antigravity: {
|
|
4064
|
+
type: "boolean",
|
|
4065
|
+
default: false,
|
|
4066
|
+
description: "Enable Google Antigravity mode (proxy to Antigravity instead of GitHub Copilot)"
|
|
4067
|
+
},
|
|
4068
|
+
"antigravity-client-id": {
|
|
4069
|
+
type: "string",
|
|
4070
|
+
description: "Google OAuth Client ID for Antigravity (create at https://console.cloud.google.com/apis/credentials)"
|
|
4071
|
+
},
|
|
4072
|
+
"antigravity-client-secret": {
|
|
4073
|
+
type: "string",
|
|
4074
|
+
description: "Google OAuth Client Secret for Antigravity"
|
|
4075
|
+
}
|
|
4076
|
+
},
|
|
4077
|
+
run({ args }) {
|
|
4078
|
+
const rateLimitRaw = args["rate-limit"];
|
|
4079
|
+
const rateLimit = rateLimitRaw === void 0 ? void 0 : Number.parseInt(rateLimitRaw, 10);
|
|
4080
|
+
const apiKeyRaw = args["api-key"];
|
|
4081
|
+
let apiKeys;
|
|
4082
|
+
if (apiKeyRaw) apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw];
|
|
4083
|
+
return runServer({
|
|
4084
|
+
port: Number.parseInt(args.port, 10),
|
|
4085
|
+
verbose: args.verbose,
|
|
4086
|
+
accountType: args["account-type"],
|
|
4087
|
+
manual: args.manual,
|
|
4088
|
+
rateLimit,
|
|
4089
|
+
rateLimitWait: args.wait,
|
|
4090
|
+
githubToken: args["github-token"],
|
|
4091
|
+
claudeCode: args["claude-code"],
|
|
4092
|
+
showToken: args["show-token"],
|
|
4093
|
+
proxyEnv: args["proxy-env"],
|
|
4094
|
+
apiKeys,
|
|
4095
|
+
zen: args.zen,
|
|
4096
|
+
zenApiKey: args["zen-api-key"],
|
|
4097
|
+
antigravity: args.antigravity,
|
|
4098
|
+
antigravityClientId: args["antigravity-client-id"],
|
|
4099
|
+
antigravityClientSecret: args["antigravity-client-secret"]
|
|
4100
|
+
});
|
|
4101
|
+
}
|
|
4102
|
+
}),
|
|
4170
4103
|
"check-usage": checkUsage,
|
|
4171
4104
|
debug,
|
|
4172
4105
|
logout,
|
|
4173
4106
|
proxy
|
|
4174
4107
|
}
|
|
4175
|
-
});
|
|
4176
|
-
await runMain(main);
|
|
4177
|
-
|
|
4108
|
+
}));
|
|
4178
4109
|
//#endregion
|
|
4179
|
-
export {
|
|
4110
|
+
export {};
|
|
4111
|
+
|
|
4180
4112
|
//# sourceMappingURL=main.js.map
|