copilot-api-plus 1.2.52 → 1.2.53
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.en.md +0 -1
- package/README.md +0 -1
- package/dist/{account-manager-B219qKl8.js → account-manager-DUSOybLm.js} +23 -7
- package/dist/account-manager-DUSOybLm.js.map +1 -0
- package/dist/error-HsNBNEyW.js +3 -0
- package/dist/get-user-DiK-7IaC.js +3 -0
- package/dist/main.js +404 -317
- package/dist/main.js.map +1 -1
- package/dist/token-C8PZ2fm8.js +4 -0
- package/dist/{token-CeQ-m5dq.js → token-Dhk6Zi-n.js} +7 -4
- package/dist/token-Dhk6Zi-n.js.map +1 -0
- package/package.json +1 -1
- package/dist/account-manager-B219qKl8.js.map +0 -1
- package/dist/error-DgcYmDsR.js +0 -2
- package/dist/get-user-BBdg72U5.js +0 -2
- package/dist/token-BlWK_LuB.js +0 -3
- package/dist/token-CeQ-m5dq.js.map +0 -1
package/dist/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { GITHUB_BASE_URL, GITHUB_CLIENT_ID, HTTPError, PATHS, accountManager, cacheModels, cacheVSCodeVersion, copilotBaseUrl, copilotHeaders, ensurePaths, findModel, forwardError, getAccountDispatcher, getCopilotUsage, initProxyFromEnv, isAccountProxied, isNullish, isProxyActive, notifyStreamEnd, notifyStreamStart, resetAccountConnections, resetConnections, rootCause, sleep, standardHeaders, state } from "./account-manager-DUSOybLm.js";
|
|
3
|
+
import { clearGithubToken, getDeviceCode, pollAccessToken, refreshCopilotToken, setupCopilotToken, setupGitHubToken, stopCopilotTokenRefresh } from "./token-Dhk6Zi-n.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
6
6
|
import consola from "consola";
|
|
@@ -19,15 +19,16 @@ import { cors } from "hono/cors";
|
|
|
19
19
|
import { HTTPException } from "hono/http-exception";
|
|
20
20
|
import { streamSSE } from "hono/streaming";
|
|
21
21
|
import { events } from "fetch-event-stream";
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
|
|
23
|
+
//#region rolldown:runtime
|
|
24
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
25
|
+
var __commonJS = (cb, mod) => function() {
|
|
26
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
27
|
+
};
|
|
24
28
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
29
|
+
|
|
25
30
|
//#endregion
|
|
26
31
|
//#region src/lib/config.ts
|
|
27
|
-
/**
|
|
28
|
-
* Configuration file management
|
|
29
|
-
* Handles persistent configuration storage for proxy settings and other options
|
|
30
|
-
*/
|
|
31
32
|
const CONFIG_FILENAME = "config.json";
|
|
32
33
|
/**
|
|
33
34
|
* Get the path to the config file
|
|
@@ -50,9 +51,9 @@ async function loadConfig() {
|
|
|
50
51
|
/**
|
|
51
52
|
* Save configuration to file
|
|
52
53
|
*/
|
|
53
|
-
async function saveConfig(config) {
|
|
54
|
+
async function saveConfig(config$1) {
|
|
54
55
|
const configPath = getConfigPath();
|
|
55
|
-
await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf8");
|
|
56
|
+
await fs.writeFile(configPath, JSON.stringify(config$1, null, 2), "utf8");
|
|
56
57
|
consola.debug(`Configuration saved to ${configPath}`);
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
@@ -65,17 +66,17 @@ async function getProxyConfig() {
|
|
|
65
66
|
* Save proxy configuration
|
|
66
67
|
*/
|
|
67
68
|
async function saveProxyConfig(proxyConfig) {
|
|
68
|
-
const config = await loadConfig();
|
|
69
|
-
config.proxy = proxyConfig;
|
|
70
|
-
await saveConfig(config);
|
|
69
|
+
const config$1 = await loadConfig();
|
|
70
|
+
config$1.proxy = proxyConfig;
|
|
71
|
+
await saveConfig(config$1);
|
|
71
72
|
}
|
|
72
73
|
/**
|
|
73
74
|
* Clear proxy configuration
|
|
74
75
|
*/
|
|
75
76
|
async function clearProxyConfig() {
|
|
76
|
-
const config = await loadConfig();
|
|
77
|
-
delete config.proxy;
|
|
78
|
-
await saveConfig(config);
|
|
77
|
+
const config$1 = await loadConfig();
|
|
78
|
+
delete config$1.proxy;
|
|
79
|
+
await saveConfig(config$1);
|
|
79
80
|
}
|
|
80
81
|
/**
|
|
81
82
|
* Get model mapping configuration
|
|
@@ -87,9 +88,9 @@ async function getModelMappingConfig() {
|
|
|
87
88
|
* Save model mapping configuration
|
|
88
89
|
*/
|
|
89
90
|
async function saveModelMappingConfig(modelMapping) {
|
|
90
|
-
const config = await loadConfig();
|
|
91
|
-
config.modelMapping = modelMapping;
|
|
92
|
-
await saveConfig(config);
|
|
91
|
+
const config$1 = await loadConfig();
|
|
92
|
+
config$1.modelMapping = modelMapping;
|
|
93
|
+
await saveConfig(config$1);
|
|
93
94
|
}
|
|
94
95
|
/**
|
|
95
96
|
* Apply saved proxy configuration to environment variables
|
|
@@ -116,6 +117,7 @@ async function applyProxyConfig() {
|
|
|
116
117
|
if (proxyConfig.noProxy) consola.info(` NO_PROXY: ${proxyConfig.noProxy}`);
|
|
117
118
|
return true;
|
|
118
119
|
}
|
|
120
|
+
|
|
119
121
|
//#endregion
|
|
120
122
|
//#region src/account.ts
|
|
121
123
|
const addAccount = defineCommand({
|
|
@@ -305,14 +307,15 @@ const removeAccount = defineCommand({
|
|
|
305
307
|
}
|
|
306
308
|
}
|
|
307
309
|
});
|
|
310
|
+
|
|
308
311
|
//#endregion
|
|
309
312
|
//#region src/auth.ts
|
|
310
|
-
async function runAuth(options) {
|
|
311
|
-
if (options.verbose) {
|
|
313
|
+
async function runAuth(options$1) {
|
|
314
|
+
if (options$1.verbose) {
|
|
312
315
|
consola.level = 5;
|
|
313
316
|
consola.info("Verbose logging enabled");
|
|
314
317
|
}
|
|
315
|
-
state.showToken = options.showToken;
|
|
318
|
+
state.showToken = options$1.showToken;
|
|
316
319
|
await ensurePaths();
|
|
317
320
|
await setupGitHubToken({ force: true });
|
|
318
321
|
consola.success("GitHub token written to", PATHS.GITHUB_TOKEN_PATH);
|
|
@@ -342,6 +345,7 @@ const auth = defineCommand({
|
|
|
342
345
|
});
|
|
343
346
|
}
|
|
344
347
|
});
|
|
348
|
+
|
|
345
349
|
//#endregion
|
|
346
350
|
//#region src/check-usage.ts
|
|
347
351
|
const checkUsage = defineCommand({
|
|
@@ -378,6 +382,7 @@ const checkUsage = defineCommand({
|
|
|
378
382
|
}
|
|
379
383
|
}
|
|
380
384
|
});
|
|
385
|
+
|
|
381
386
|
//#endregion
|
|
382
387
|
//#region src/debug.ts
|
|
383
388
|
async function getPackageVersion() {
|
|
@@ -406,13 +411,13 @@ async function checkTokenExists() {
|
|
|
406
411
|
}
|
|
407
412
|
}
|
|
408
413
|
async function getDebugInfo() {
|
|
409
|
-
const [version, githubExists, proxyConfig] = await Promise.all([
|
|
414
|
+
const [version$1, githubExists, proxyConfig] = await Promise.all([
|
|
410
415
|
getPackageVersion(),
|
|
411
416
|
checkTokenExists(),
|
|
412
417
|
getProxyConfig()
|
|
413
418
|
]);
|
|
414
419
|
return {
|
|
415
|
-
version,
|
|
420
|
+
version: version$1,
|
|
416
421
|
runtime: getRuntimeInfo(),
|
|
417
422
|
paths: {
|
|
418
423
|
APP_DIR: PATHS.APP_DIR,
|
|
@@ -442,9 +447,9 @@ Proxy: ${proxyStatus}`);
|
|
|
442
447
|
function printDebugInfoJson(info) {
|
|
443
448
|
console.log(JSON.stringify(info, null, 2));
|
|
444
449
|
}
|
|
445
|
-
async function runDebug(options) {
|
|
450
|
+
async function runDebug(options$1) {
|
|
446
451
|
const debugInfo = await getDebugInfo();
|
|
447
|
-
if (options.json) printDebugInfoJson(debugInfo);
|
|
452
|
+
if (options$1.json) printDebugInfoJson(debugInfo);
|
|
448
453
|
else printDebugInfoPlain(debugInfo);
|
|
449
454
|
}
|
|
450
455
|
const debug = defineCommand({
|
|
@@ -461,11 +466,12 @@ const debug = defineCommand({
|
|
|
461
466
|
return runDebug({ json: args.json });
|
|
462
467
|
}
|
|
463
468
|
});
|
|
469
|
+
|
|
464
470
|
//#endregion
|
|
465
471
|
//#region src/logout.ts
|
|
466
|
-
async function runLogout(options) {
|
|
472
|
+
async function runLogout(options$1) {
|
|
467
473
|
await ensurePaths();
|
|
468
|
-
if (options.all || options.github) {
|
|
474
|
+
if (options$1.all || options$1.github) {
|
|
469
475
|
await clearGithubToken();
|
|
470
476
|
consola.success("Logged out from GitHub Copilot");
|
|
471
477
|
consola.info(`Token file location: ${PATHS.GITHUB_TOKEN_PATH}`);
|
|
@@ -501,12 +507,9 @@ const logout = defineCommand({
|
|
|
501
507
|
});
|
|
502
508
|
}
|
|
503
509
|
});
|
|
510
|
+
|
|
504
511
|
//#endregion
|
|
505
512
|
//#region src/proxy-config.ts
|
|
506
|
-
/**
|
|
507
|
-
* Proxy configuration command
|
|
508
|
-
* Allows users to configure, enable, disable, and view proxy settings
|
|
509
|
-
*/
|
|
510
513
|
const proxy = defineCommand({
|
|
511
514
|
meta: {
|
|
512
515
|
name: "proxy",
|
|
@@ -554,8 +557,8 @@ const proxy = defineCommand({
|
|
|
554
557
|
async run({ args }) {
|
|
555
558
|
await ensurePaths();
|
|
556
559
|
if (args.show || !args.set && !args.enable && !args.disable && !args.clear && !args["http-proxy"] && !args["https-proxy"]) {
|
|
557
|
-
const config = await getProxyConfig();
|
|
558
|
-
if (!config) {
|
|
560
|
+
const config$1 = await getProxyConfig();
|
|
561
|
+
if (!config$1) {
|
|
559
562
|
consola.info("No proxy configuration saved.");
|
|
560
563
|
consola.info("");
|
|
561
564
|
consola.info("To configure proxy, use one of:");
|
|
@@ -564,10 +567,10 @@ const proxy = defineCommand({
|
|
|
564
567
|
return;
|
|
565
568
|
}
|
|
566
569
|
consola.info("Current proxy configuration:");
|
|
567
|
-
consola.info(` Status: ${config.enabled ? "✅ Enabled" : "❌ Disabled"}`);
|
|
568
|
-
if (config.httpProxy) consola.info(` HTTP_PROXY: ${config.httpProxy}`);
|
|
569
|
-
if (config.httpsProxy) consola.info(` HTTPS_PROXY: ${config.httpsProxy}`);
|
|
570
|
-
if (config.noProxy) consola.info(` NO_PROXY: ${config.noProxy}`);
|
|
570
|
+
consola.info(` Status: ${config$1.enabled ? "✅ Enabled" : "❌ Disabled"}`);
|
|
571
|
+
if (config$1.httpProxy) consola.info(` HTTP_PROXY: ${config$1.httpProxy}`);
|
|
572
|
+
if (config$1.httpsProxy) consola.info(` HTTPS_PROXY: ${config$1.httpsProxy}`);
|
|
573
|
+
if (config$1.noProxy) consola.info(` NO_PROXY: ${config$1.noProxy}`);
|
|
571
574
|
return;
|
|
572
575
|
}
|
|
573
576
|
if (args.clear) {
|
|
@@ -576,24 +579,24 @@ const proxy = defineCommand({
|
|
|
576
579
|
return;
|
|
577
580
|
}
|
|
578
581
|
if (args.enable) {
|
|
579
|
-
const config = await getProxyConfig();
|
|
580
|
-
if (!config) {
|
|
582
|
+
const config$1 = await getProxyConfig();
|
|
583
|
+
if (!config$1) {
|
|
581
584
|
consola.error("No proxy configuration saved. Use --set to configure first.");
|
|
582
585
|
return;
|
|
583
586
|
}
|
|
584
|
-
config.enabled = true;
|
|
585
|
-
await saveProxyConfig(config);
|
|
587
|
+
config$1.enabled = true;
|
|
588
|
+
await saveProxyConfig(config$1);
|
|
586
589
|
consola.success("Proxy enabled. It will be used on next server start.");
|
|
587
590
|
return;
|
|
588
591
|
}
|
|
589
592
|
if (args.disable) {
|
|
590
|
-
const config = await getProxyConfig();
|
|
591
|
-
if (!config) {
|
|
593
|
+
const config$1 = await getProxyConfig();
|
|
594
|
+
if (!config$1) {
|
|
592
595
|
consola.info("No proxy configuration to disable.");
|
|
593
596
|
return;
|
|
594
597
|
}
|
|
595
|
-
config.enabled = false;
|
|
596
|
-
await saveProxyConfig(config);
|
|
598
|
+
config$1.enabled = false;
|
|
599
|
+
await saveProxyConfig(config$1);
|
|
597
600
|
consola.success("Proxy disabled. Settings are preserved.");
|
|
598
601
|
return;
|
|
599
602
|
}
|
|
@@ -659,9 +662,10 @@ const proxy = defineCommand({
|
|
|
659
662
|
}
|
|
660
663
|
}
|
|
661
664
|
});
|
|
665
|
+
|
|
662
666
|
//#endregion
|
|
663
667
|
//#region node_modules/dotenv/package.json
|
|
664
|
-
var require_package = /* @__PURE__ */
|
|
668
|
+
var require_package = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/package.json": ((exports, module) => {
|
|
665
669
|
module.exports = {
|
|
666
670
|
"name": "dotenv",
|
|
667
671
|
"version": "17.2.3",
|
|
@@ -720,10 +724,11 @@ var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
720
724
|
"engines": { "node": ">=12" },
|
|
721
725
|
"browser": { "fs": false }
|
|
722
726
|
};
|
|
723
|
-
}));
|
|
727
|
+
}) });
|
|
728
|
+
|
|
724
729
|
//#endregion
|
|
725
730
|
//#region node_modules/dotenv/lib/main.js
|
|
726
|
-
var require_main = /* @__PURE__ */
|
|
731
|
+
var require_main = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/main.js": ((exports, module) => {
|
|
727
732
|
const fs$1 = __require("fs");
|
|
728
733
|
const path$1 = __require("path");
|
|
729
734
|
const os$1 = __require("os");
|
|
@@ -786,21 +791,22 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
786
791
|
}
|
|
787
792
|
return obj;
|
|
788
793
|
}
|
|
789
|
-
function _parseVault(options) {
|
|
790
|
-
options = options || {};
|
|
791
|
-
const vaultPath = _vaultPath(options);
|
|
792
|
-
options.path = vaultPath;
|
|
793
|
-
const result = DotenvModule.configDotenv(options);
|
|
794
|
+
function _parseVault(options$1) {
|
|
795
|
+
options$1 = options$1 || {};
|
|
796
|
+
const vaultPath = _vaultPath(options$1);
|
|
797
|
+
options$1.path = vaultPath;
|
|
798
|
+
const result = DotenvModule.configDotenv(options$1);
|
|
794
799
|
if (!result.parsed) {
|
|
795
800
|
const err = /* @__PURE__ */ new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
796
801
|
err.code = "MISSING_DATA";
|
|
797
802
|
throw err;
|
|
798
803
|
}
|
|
799
|
-
const keys = _dotenvKey(options).split(",");
|
|
804
|
+
const keys = _dotenvKey(options$1).split(",");
|
|
800
805
|
const length = keys.length;
|
|
801
806
|
let decrypted;
|
|
802
807
|
for (let i = 0; i < length; i++) try {
|
|
803
|
-
const
|
|
808
|
+
const key = keys[i].trim();
|
|
809
|
+
const attrs = _instructions(result, key);
|
|
804
810
|
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
805
811
|
break;
|
|
806
812
|
} catch (error) {
|
|
@@ -817,8 +823,8 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
817
823
|
function _log(message) {
|
|
818
824
|
console.log(`[dotenv@${version}] ${message}`);
|
|
819
825
|
}
|
|
820
|
-
function _dotenvKey(options) {
|
|
821
|
-
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) return options.DOTENV_KEY;
|
|
826
|
+
function _dotenvKey(options$1) {
|
|
827
|
+
if (options$1 && options$1.DOTENV_KEY && options$1.DOTENV_KEY.length > 0) return options$1.DOTENV_KEY;
|
|
822
828
|
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) return process.env.DOTENV_KEY;
|
|
823
829
|
return "";
|
|
824
830
|
}
|
|
@@ -858,11 +864,11 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
858
864
|
key
|
|
859
865
|
};
|
|
860
866
|
}
|
|
861
|
-
function _vaultPath(options) {
|
|
867
|
+
function _vaultPath(options$1) {
|
|
862
868
|
let possibleVaultPath = null;
|
|
863
|
-
if (options && options.path && options.path.length > 0) if (Array.isArray(options.path)) {
|
|
864
|
-
for (const filepath of options.path) if (fs$1.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
865
|
-
} else possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
869
|
+
if (options$1 && options$1.path && options$1.path.length > 0) if (Array.isArray(options$1.path)) {
|
|
870
|
+
for (const filepath of options$1.path) if (fs$1.existsSync(filepath)) possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
871
|
+
} else possibleVaultPath = options$1.path.endsWith(".vault") ? options$1.path : `${options$1.path}.vault`;
|
|
866
872
|
else possibleVaultPath = path$1.resolve(process.cwd(), ".env.vault");
|
|
867
873
|
if (fs$1.existsSync(possibleVaultPath)) return possibleVaultPath;
|
|
868
874
|
return null;
|
|
@@ -870,51 +876,51 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
870
876
|
function _resolveHome(envPath) {
|
|
871
877
|
return envPath[0] === "~" ? path$1.join(os$1.homedir(), envPath.slice(1)) : envPath;
|
|
872
878
|
}
|
|
873
|
-
function _configVault(options) {
|
|
874
|
-
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
875
|
-
const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
876
|
-
if (debug || !quiet) _log("Loading env from encrypted .env.vault");
|
|
877
|
-
const parsed = DotenvModule._parseVault(options);
|
|
879
|
+
function _configVault(options$1) {
|
|
880
|
+
const debug$1 = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options$1 && options$1.debug);
|
|
881
|
+
const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options$1 && options$1.quiet);
|
|
882
|
+
if (debug$1 || !quiet) _log("Loading env from encrypted .env.vault");
|
|
883
|
+
const parsed = DotenvModule._parseVault(options$1);
|
|
878
884
|
let processEnv = process.env;
|
|
879
|
-
if (options && options.processEnv != null) processEnv = options.processEnv;
|
|
880
|
-
DotenvModule.populate(processEnv, parsed, options);
|
|
885
|
+
if (options$1 && options$1.processEnv != null) processEnv = options$1.processEnv;
|
|
886
|
+
DotenvModule.populate(processEnv, parsed, options$1);
|
|
881
887
|
return { parsed };
|
|
882
888
|
}
|
|
883
|
-
function configDotenv(options) {
|
|
889
|
+
function configDotenv(options$1) {
|
|
884
890
|
const dotenvPath = path$1.resolve(process.cwd(), ".env");
|
|
885
891
|
let encoding = "utf8";
|
|
886
892
|
let processEnv = process.env;
|
|
887
|
-
if (options && options.processEnv != null) processEnv = options.processEnv;
|
|
888
|
-
let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
889
|
-
let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
890
|
-
if (options && options.encoding) encoding = options.encoding;
|
|
891
|
-
else if (debug) _debug("No encoding is specified. UTF-8 is used by default");
|
|
893
|
+
if (options$1 && options$1.processEnv != null) processEnv = options$1.processEnv;
|
|
894
|
+
let debug$1 = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options$1 && options$1.debug);
|
|
895
|
+
let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options$1 && options$1.quiet);
|
|
896
|
+
if (options$1 && options$1.encoding) encoding = options$1.encoding;
|
|
897
|
+
else if (debug$1) _debug("No encoding is specified. UTF-8 is used by default");
|
|
892
898
|
let optionPaths = [dotenvPath];
|
|
893
|
-
if (options && options.path) if (!Array.isArray(options.path)) optionPaths = [_resolveHome(options.path)];
|
|
899
|
+
if (options$1 && options$1.path) if (!Array.isArray(options$1.path)) optionPaths = [_resolveHome(options$1.path)];
|
|
894
900
|
else {
|
|
895
901
|
optionPaths = [];
|
|
896
|
-
for (const filepath of options.path) optionPaths.push(_resolveHome(filepath));
|
|
902
|
+
for (const filepath of options$1.path) optionPaths.push(_resolveHome(filepath));
|
|
897
903
|
}
|
|
898
904
|
let lastError;
|
|
899
905
|
const parsedAll = {};
|
|
900
|
-
for (const path of optionPaths) try {
|
|
901
|
-
const parsed = DotenvModule.parse(fs$1.readFileSync(path, { encoding }));
|
|
902
|
-
DotenvModule.populate(parsedAll, parsed, options);
|
|
906
|
+
for (const path$2 of optionPaths) try {
|
|
907
|
+
const parsed = DotenvModule.parse(fs$1.readFileSync(path$2, { encoding }));
|
|
908
|
+
DotenvModule.populate(parsedAll, parsed, options$1);
|
|
903
909
|
} catch (e) {
|
|
904
|
-
if (debug) _debug(`Failed to load ${path} ${e.message}`);
|
|
910
|
+
if (debug$1) _debug(`Failed to load ${path$2} ${e.message}`);
|
|
905
911
|
lastError = e;
|
|
906
912
|
}
|
|
907
|
-
const populated = DotenvModule.populate(processEnv, parsedAll, options);
|
|
908
|
-
debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
|
|
913
|
+
const populated = DotenvModule.populate(processEnv, parsedAll, options$1);
|
|
914
|
+
debug$1 = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug$1);
|
|
909
915
|
quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
|
|
910
|
-
if (debug || !quiet) {
|
|
916
|
+
if (debug$1 || !quiet) {
|
|
911
917
|
const keysCount = Object.keys(populated).length;
|
|
912
918
|
const shortPaths = [];
|
|
913
919
|
for (const filePath of optionPaths) try {
|
|
914
920
|
const relative = path$1.relative(process.cwd(), filePath);
|
|
915
921
|
shortPaths.push(relative);
|
|
916
922
|
} catch (e) {
|
|
917
|
-
if (debug) _debug(`Failed to load ${filePath} ${e.message}`);
|
|
923
|
+
if (debug$1) _debug(`Failed to load ${filePath} ${e.message}`);
|
|
918
924
|
lastError = e;
|
|
919
925
|
}
|
|
920
926
|
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
|
|
@@ -925,14 +931,14 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
925
931
|
};
|
|
926
932
|
else return { parsed: parsedAll };
|
|
927
933
|
}
|
|
928
|
-
function config(options) {
|
|
929
|
-
if (_dotenvKey(options).length === 0) return DotenvModule.configDotenv(options);
|
|
930
|
-
const vaultPath = _vaultPath(options);
|
|
934
|
+
function config(options$1) {
|
|
935
|
+
if (_dotenvKey(options$1).length === 0) return DotenvModule.configDotenv(options$1);
|
|
936
|
+
const vaultPath = _vaultPath(options$1);
|
|
931
937
|
if (!vaultPath) {
|
|
932
938
|
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
933
|
-
return DotenvModule.configDotenv(options);
|
|
939
|
+
return DotenvModule.configDotenv(options$1);
|
|
934
940
|
}
|
|
935
|
-
return DotenvModule._configVault(options);
|
|
941
|
+
return DotenvModule._configVault(options$1);
|
|
936
942
|
}
|
|
937
943
|
function decrypt(encrypted, keyStr) {
|
|
938
944
|
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
@@ -959,9 +965,9 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
959
965
|
} else throw error;
|
|
960
966
|
}
|
|
961
967
|
}
|
|
962
|
-
function populate(processEnv, parsed, options = {}) {
|
|
963
|
-
const debug = Boolean(options && options.debug);
|
|
964
|
-
const override = Boolean(options && options.override);
|
|
968
|
+
function populate(processEnv, parsed, options$1 = {}) {
|
|
969
|
+
const debug$1 = Boolean(options$1 && options$1.debug);
|
|
970
|
+
const override = Boolean(options$1 && options$1.override);
|
|
965
971
|
const populated = {};
|
|
966
972
|
if (typeof parsed !== "object") {
|
|
967
973
|
const err = /* @__PURE__ */ new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
@@ -973,7 +979,7 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
973
979
|
processEnv[key] = parsed[key];
|
|
974
980
|
populated[key] = parsed[key];
|
|
975
981
|
}
|
|
976
|
-
if (debug) if (override === true) _debug(`"${key}" is already defined and WAS overwritten`);
|
|
982
|
+
if (debug$1) if (override === true) _debug(`"${key}" is already defined and WAS overwritten`);
|
|
977
983
|
else _debug(`"${key}" is already defined and was NOT overwritten`);
|
|
978
984
|
} else {
|
|
979
985
|
processEnv[key] = parsed[key];
|
|
@@ -998,10 +1004,11 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
998
1004
|
module.exports.parse = DotenvModule.parse;
|
|
999
1005
|
module.exports.populate = DotenvModule.populate;
|
|
1000
1006
|
module.exports = DotenvModule;
|
|
1001
|
-
}));
|
|
1007
|
+
}) });
|
|
1008
|
+
|
|
1002
1009
|
//#endregion
|
|
1003
1010
|
//#region node_modules/dotenv/lib/env-options.js
|
|
1004
|
-
var require_env_options = /* @__PURE__ */
|
|
1011
|
+
var require_env_options = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/env-options.js": ((exports, module) => {
|
|
1005
1012
|
const options = {};
|
|
1006
1013
|
if (process.env.DOTENV_CONFIG_ENCODING != null) options.encoding = process.env.DOTENV_CONFIG_ENCODING;
|
|
1007
1014
|
if (process.env.DOTENV_CONFIG_PATH != null) options.path = process.env.DOTENV_CONFIG_PATH;
|
|
@@ -1010,34 +1017,31 @@ var require_env_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1010
1017
|
if (process.env.DOTENV_CONFIG_OVERRIDE != null) options.override = process.env.DOTENV_CONFIG_OVERRIDE;
|
|
1011
1018
|
if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY;
|
|
1012
1019
|
module.exports = options;
|
|
1013
|
-
}));
|
|
1020
|
+
}) });
|
|
1021
|
+
|
|
1014
1022
|
//#endregion
|
|
1015
1023
|
//#region node_modules/dotenv/lib/cli-options.js
|
|
1016
|
-
var require_cli_options = /* @__PURE__ */
|
|
1024
|
+
var require_cli_options = /* @__PURE__ */ __commonJS({ "node_modules/dotenv/lib/cli-options.js": ((exports, module) => {
|
|
1017
1025
|
const re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/;
|
|
1018
1026
|
module.exports = function optionMatcher(args) {
|
|
1019
|
-
const options = args.reduce(function(acc, cur) {
|
|
1027
|
+
const options$1 = args.reduce(function(acc, cur) {
|
|
1020
1028
|
const matches = cur.match(re);
|
|
1021
1029
|
if (matches) acc[matches[1]] = matches[2];
|
|
1022
1030
|
return acc;
|
|
1023
1031
|
}, {});
|
|
1024
|
-
if (!("quiet" in options)) options.quiet = "true";
|
|
1025
|
-
return options;
|
|
1032
|
+
if (!("quiet" in options$1)) options$1.quiet = "true";
|
|
1033
|
+
return options$1;
|
|
1026
1034
|
};
|
|
1027
|
-
}));
|
|
1035
|
+
}) });
|
|
1036
|
+
|
|
1028
1037
|
//#endregion
|
|
1029
1038
|
//#region node_modules/dotenv/config.js
|
|
1030
1039
|
(function() {
|
|
1031
1040
|
require_main().config(Object.assign({}, require_env_options(), require_cli_options()(process.argv)));
|
|
1032
1041
|
})();
|
|
1042
|
+
|
|
1033
1043
|
//#endregion
|
|
1034
1044
|
//#region src/lib/model-router.ts
|
|
1035
|
-
/**
|
|
1036
|
-
* Model Router - Model mapping and per-model concurrency control
|
|
1037
|
-
*
|
|
1038
|
-
* Provides flexible model name mapping (requested → actual) and
|
|
1039
|
-
* per-model concurrency limits using a semaphore pattern.
|
|
1040
|
-
*/
|
|
1041
1045
|
const DEFAULT_CONFIG = {
|
|
1042
1046
|
mapping: {},
|
|
1043
1047
|
concurrency: { default: 10 }
|
|
@@ -1047,8 +1051,8 @@ var ModelRouter = class {
|
|
|
1047
1051
|
config;
|
|
1048
1052
|
queues = /* @__PURE__ */ new Map();
|
|
1049
1053
|
requestCounts = /* @__PURE__ */ new Map();
|
|
1050
|
-
constructor(config) {
|
|
1051
|
-
this.config = config ? { ...config } : {
|
|
1054
|
+
constructor(config$1) {
|
|
1055
|
+
this.config = config$1 ? { ...config$1 } : {
|
|
1052
1056
|
...DEFAULT_CONFIG,
|
|
1053
1057
|
mapping: {},
|
|
1054
1058
|
concurrency: { default: 10 }
|
|
@@ -1170,13 +1174,15 @@ var ModelRouter = class {
|
|
|
1170
1174
|
}
|
|
1171
1175
|
};
|
|
1172
1176
|
const modelRouter = new ModelRouter();
|
|
1177
|
+
|
|
1173
1178
|
//#endregion
|
|
1174
1179
|
//#region src/lib/shell.ts
|
|
1175
1180
|
function getShell() {
|
|
1176
1181
|
const { platform, ppid, env } = process$1;
|
|
1177
1182
|
if (platform === "win32") {
|
|
1178
1183
|
try {
|
|
1179
|
-
|
|
1184
|
+
const command = `wmic process get ParentProcessId,Name | findstr "${ppid}"`;
|
|
1185
|
+
if (execSync(command, { stdio: "pipe" }).toString().toLowerCase().includes("powershell.exe")) return "powershell";
|
|
1180
1186
|
} catch {
|
|
1181
1187
|
return "cmd";
|
|
1182
1188
|
}
|
|
@@ -1221,6 +1227,7 @@ function generateEnvScript(envVars, commandToRun = "") {
|
|
|
1221
1227
|
if (commandBlock && commandToRun) return `${commandBlock}${shell === "cmd" ? " & " : " && "}${commandToRun}`;
|
|
1222
1228
|
return commandBlock || commandToRun;
|
|
1223
1229
|
}
|
|
1230
|
+
|
|
1224
1231
|
//#endregion
|
|
1225
1232
|
//#region src/lib/api-key-auth.ts
|
|
1226
1233
|
/**
|
|
@@ -1259,6 +1266,7 @@ const apiKeyAuthMiddleware = async (c, next) => {
|
|
|
1259
1266
|
})) throw new HTTPException(401, { message: "Invalid API key. Please provide a valid API key." });
|
|
1260
1267
|
await next();
|
|
1261
1268
|
};
|
|
1269
|
+
|
|
1262
1270
|
//#endregion
|
|
1263
1271
|
//#region src/lib/model-logger.ts
|
|
1264
1272
|
/**
|
|
@@ -1307,7 +1315,9 @@ async function extractModelInfo(c) {
|
|
|
1307
1315
|
function modelLogger() {
|
|
1308
1316
|
return async (c, next) => {
|
|
1309
1317
|
const method = c.req.method;
|
|
1310
|
-
const
|
|
1318
|
+
const path$2 = c.req.path;
|
|
1319
|
+
const queryString = c.req.raw.url.includes("?") ? `?${c.req.raw.url.split("?")[1]}` : "";
|
|
1320
|
+
const fullPath = `${path$2}${queryString}`;
|
|
1311
1321
|
let model;
|
|
1312
1322
|
let thinking = false;
|
|
1313
1323
|
if (method === "POST" && c.req.header("content-type")?.includes("json")) {
|
|
@@ -1318,13 +1328,14 @@ function modelLogger() {
|
|
|
1318
1328
|
const modelPrefix = model ? `[${model}${thinking ? " thinking" : ""}] ` : "";
|
|
1319
1329
|
const startTime = getTime();
|
|
1320
1330
|
console.log(`${modelPrefix}${startTime} <-- ${method} ${fullPath}`);
|
|
1321
|
-
const start = Date.now();
|
|
1331
|
+
const start$1 = Date.now();
|
|
1322
1332
|
await next();
|
|
1323
|
-
const duration = Date.now() - start;
|
|
1333
|
+
const duration = Date.now() - start$1;
|
|
1324
1334
|
const endTime = getTime();
|
|
1325
1335
|
console.log(`${modelPrefix}${endTime} --> ${method} ${fullPath} ${c.res.status} ${formatDuration(duration)}`);
|
|
1326
1336
|
};
|
|
1327
1337
|
}
|
|
1338
|
+
|
|
1328
1339
|
//#endregion
|
|
1329
1340
|
//#region src/routes/admin/accounts.ts
|
|
1330
1341
|
const accountRoutes = new Hono();
|
|
@@ -1341,7 +1352,7 @@ function maskToken(token) {
|
|
|
1341
1352
|
* - `copilotToken` is fully excluded.
|
|
1342
1353
|
*/
|
|
1343
1354
|
function sanitiseAccount(account) {
|
|
1344
|
-
const { copilotToken: _dropped, githubToken
|
|
1355
|
+
const { copilotToken: _dropped, githubToken,...rest } = account;
|
|
1345
1356
|
return {
|
|
1346
1357
|
...rest,
|
|
1347
1358
|
githubToken: maskToken(githubToken)
|
|
@@ -1596,6 +1607,7 @@ accountRoutes.get("/usage", (c) => {
|
|
|
1596
1607
|
return c.json({ error: "Failed to fetch aggregated usage" }, 500);
|
|
1597
1608
|
}
|
|
1598
1609
|
});
|
|
1610
|
+
|
|
1599
1611
|
//#endregion
|
|
1600
1612
|
//#region src/routes/admin/models.ts
|
|
1601
1613
|
const modelAdminRoutes = new Hono();
|
|
@@ -1655,6 +1667,7 @@ modelAdminRoutes.put("/concurrency", async (c) => {
|
|
|
1655
1667
|
return c.json({ error: "Failed to update concurrency config" }, 500);
|
|
1656
1668
|
}
|
|
1657
1669
|
});
|
|
1670
|
+
|
|
1658
1671
|
//#endregion
|
|
1659
1672
|
//#region src/routes/admin/stats.ts
|
|
1660
1673
|
const statsRoute = new Hono();
|
|
@@ -1672,6 +1685,7 @@ statsRoute.delete("/", (c) => {
|
|
|
1672
1685
|
modelRouter.resetStats();
|
|
1673
1686
|
return c.json({ success: true });
|
|
1674
1687
|
});
|
|
1688
|
+
|
|
1675
1689
|
//#endregion
|
|
1676
1690
|
//#region src/routes/admin/route.ts
|
|
1677
1691
|
const adminRoutes = new Hono();
|
|
@@ -1685,17 +1699,19 @@ adminRoutes.get("/config", (c) => {
|
|
|
1685
1699
|
apiKey: state.apiKeys?.[0] ?? "dummy"
|
|
1686
1700
|
});
|
|
1687
1701
|
});
|
|
1702
|
+
|
|
1688
1703
|
//#endregion
|
|
1689
1704
|
//#region src/lib/approval.ts
|
|
1690
1705
|
const awaitApproval = async () => {
|
|
1691
1706
|
if (!await consola.prompt(`Accept incoming request?`, { type: "confirm" })) throw new HTTPError("Request rejected", Response.json({ message: "Request rejected" }, { status: 403 }));
|
|
1692
1707
|
};
|
|
1708
|
+
|
|
1693
1709
|
//#endregion
|
|
1694
1710
|
//#region src/lib/rate-limit.ts
|
|
1695
1711
|
/** Serialize concurrent rate-limit checks so only one request passes at a time. */
|
|
1696
1712
|
let rateLimitLock = Promise.resolve();
|
|
1697
|
-
async function checkRateLimit(state) {
|
|
1698
|
-
if (state.rateLimitSeconds === void 0) return;
|
|
1713
|
+
async function checkRateLimit(state$1) {
|
|
1714
|
+
if (state$1.rateLimitSeconds === void 0) return;
|
|
1699
1715
|
const previous = rateLimitLock;
|
|
1700
1716
|
let resolve;
|
|
1701
1717
|
rateLimitLock = new Promise((r) => {
|
|
@@ -1704,29 +1720,30 @@ async function checkRateLimit(state) {
|
|
|
1704
1720
|
try {
|
|
1705
1721
|
await previous;
|
|
1706
1722
|
const now = Date.now();
|
|
1707
|
-
if (!state.lastRequestTimestamp) {
|
|
1708
|
-
state.lastRequestTimestamp = now;
|
|
1723
|
+
if (!state$1.lastRequestTimestamp) {
|
|
1724
|
+
state$1.lastRequestTimestamp = now;
|
|
1709
1725
|
return;
|
|
1710
1726
|
}
|
|
1711
|
-
const elapsedSeconds = (now - state.lastRequestTimestamp) / 1e3;
|
|
1712
|
-
if (elapsedSeconds > state.rateLimitSeconds) {
|
|
1713
|
-
state.lastRequestTimestamp = now;
|
|
1727
|
+
const elapsedSeconds = (now - state$1.lastRequestTimestamp) / 1e3;
|
|
1728
|
+
if (elapsedSeconds > state$1.rateLimitSeconds) {
|
|
1729
|
+
state$1.lastRequestTimestamp = now;
|
|
1714
1730
|
return;
|
|
1715
1731
|
}
|
|
1716
|
-
const waitTimeSeconds = Math.ceil(state.rateLimitSeconds - elapsedSeconds);
|
|
1717
|
-
if (!state.rateLimitWait) {
|
|
1732
|
+
const waitTimeSeconds = Math.ceil(state$1.rateLimitSeconds - elapsedSeconds);
|
|
1733
|
+
if (!state$1.rateLimitWait) {
|
|
1718
1734
|
consola.warn(`Rate limit exceeded. Need to wait ${waitTimeSeconds} more seconds.`);
|
|
1719
1735
|
throw new HTTPError("Rate limit exceeded", Response.json({ message: "Rate limit exceeded" }, { status: 429 }));
|
|
1720
1736
|
}
|
|
1721
1737
|
const waitTimeMs = waitTimeSeconds * 1e3;
|
|
1722
1738
|
consola.warn(`Rate limit reached. Waiting ${waitTimeSeconds} seconds before proceeding...`);
|
|
1723
1739
|
await sleep(waitTimeMs);
|
|
1724
|
-
state.lastRequestTimestamp = Date.now();
|
|
1740
|
+
state$1.lastRequestTimestamp = Date.now();
|
|
1725
1741
|
consola.debug("Rate limit wait completed, proceeding with request");
|
|
1726
1742
|
} finally {
|
|
1727
1743
|
resolve();
|
|
1728
1744
|
}
|
|
1729
1745
|
}
|
|
1746
|
+
|
|
1730
1747
|
//#endregion
|
|
1731
1748
|
//#region src/routes/messages/strip-reminders.ts
|
|
1732
1749
|
/** Matches `<system-reminder>…</system-reminder>` non-greedy, across lines. */
|
|
@@ -1786,11 +1803,11 @@ function stripBlocks(content) {
|
|
|
1786
1803
|
*/
|
|
1787
1804
|
function stripMessage(message) {
|
|
1788
1805
|
if (typeof message.content === "string") {
|
|
1789
|
-
const next = stripText(message.content);
|
|
1790
|
-
if (next === message.content) return message;
|
|
1806
|
+
const next$1 = stripText(message.content);
|
|
1807
|
+
if (next$1 === message.content) return message;
|
|
1791
1808
|
return {
|
|
1792
1809
|
...message,
|
|
1793
|
-
content: next
|
|
1810
|
+
content: next$1
|
|
1794
1811
|
};
|
|
1795
1812
|
}
|
|
1796
1813
|
const next = stripBlocks(message.content);
|
|
@@ -1863,17 +1880,17 @@ function stripOpenAIReminders(payload) {
|
|
|
1863
1880
|
content: next
|
|
1864
1881
|
};
|
|
1865
1882
|
}
|
|
1866
|
-
if (!m.content.some((p) => p.type === "text" && typeof p.text === "string" && p.text.includes(REMINDER_OPEN_TAG))) return m;
|
|
1883
|
+
if (!m.content.some((p$1) => p$1.type === "text" && typeof p$1.text === "string" && p$1.text.includes(REMINDER_OPEN_TAG))) return m;
|
|
1867
1884
|
const out = [];
|
|
1868
|
-
for (const p of m.content) {
|
|
1869
|
-
if (p.type !== "text" || typeof p.text !== "string") {
|
|
1870
|
-
out.push(p);
|
|
1885
|
+
for (const p$1 of m.content) {
|
|
1886
|
+
if (p$1.type !== "text" || typeof p$1.text !== "string") {
|
|
1887
|
+
out.push(p$1);
|
|
1871
1888
|
continue;
|
|
1872
1889
|
}
|
|
1873
|
-
const t = stripText(p.text);
|
|
1890
|
+
const t = stripText(p$1.text);
|
|
1874
1891
|
if (t.length === 0) continue;
|
|
1875
|
-
out.push(t === p.text ? p : {
|
|
1876
|
-
...p,
|
|
1892
|
+
out.push(t === p$1.text ? p$1 : {
|
|
1893
|
+
...p$1,
|
|
1877
1894
|
text: t
|
|
1878
1895
|
});
|
|
1879
1896
|
}
|
|
@@ -1889,6 +1906,7 @@ function stripOpenAIReminders(payload) {
|
|
|
1889
1906
|
messages: newMessages
|
|
1890
1907
|
};
|
|
1891
1908
|
}
|
|
1909
|
+
|
|
1892
1910
|
//#endregion
|
|
1893
1911
|
//#region src/services/copilot/create-chat-completions.ts
|
|
1894
1912
|
/**
|
|
@@ -1972,6 +1990,27 @@ async function* wrapGeneratorWithRelease(gen, releaseSlot, accountInfo) {
|
|
|
1972
1990
|
}
|
|
1973
1991
|
}
|
|
1974
1992
|
/**
|
|
1993
|
+
* Models known to require `max_completion_tokens` instead of `max_tokens`.
|
|
1994
|
+
* Populated at runtime: when a model returns 400 with a message containing
|
|
1995
|
+
* "max_completion_tokens", that model is added here and all subsequent
|
|
1996
|
+
* requests use the correct field name automatically.
|
|
1997
|
+
*/
|
|
1998
|
+
const maxCompletionTokensModels = /* @__PURE__ */ new Set();
|
|
1999
|
+
/**
|
|
2000
|
+
* Normalize the payload for models that use `max_completion_tokens`
|
|
2001
|
+
* instead of `max_tokens`. Only applied when the model has been seen
|
|
2002
|
+
* to reject `max_tokens` at runtime.
|
|
2003
|
+
*/
|
|
2004
|
+
function normalizeMaxTokens(payload) {
|
|
2005
|
+
if (!maxCompletionTokensModels.has(payload.model)) return payload;
|
|
2006
|
+
if (!payload.max_tokens) return payload;
|
|
2007
|
+
const { max_tokens,...rest } = payload;
|
|
2008
|
+
return {
|
|
2009
|
+
...rest,
|
|
2010
|
+
max_completion_tokens: max_tokens
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
1975
2014
|
* Models that are known NOT to support the `reasoning_effort` parameter.
|
|
1976
2015
|
* Populated at runtime: the first time a model returns 400 with
|
|
1977
2016
|
* "Unrecognized request argument", it is added here and all future
|
|
@@ -2043,7 +2082,8 @@ function injectThinking(payload, resolvedModel) {
|
|
|
2043
2082
|
}
|
|
2044
2083
|
return payload;
|
|
2045
2084
|
}
|
|
2046
|
-
const
|
|
2085
|
+
const model = findModel(resolvedModel);
|
|
2086
|
+
const budget = getThinkingBudget(model);
|
|
2047
2087
|
if (budget) return {
|
|
2048
2088
|
...payload,
|
|
2049
2089
|
thinking_budget: budget
|
|
@@ -2083,6 +2123,11 @@ const createChatCompletions = async (payload) => {
|
|
|
2083
2123
|
releaseSlot();
|
|
2084
2124
|
return result;
|
|
2085
2125
|
} catch (error) {
|
|
2126
|
+
const maxTokensRetry = handle400MaxTokensError(error, {
|
|
2127
|
+
resolvedModel,
|
|
2128
|
+
routedPayload: thinkingPayload
|
|
2129
|
+
}, releaseSlot);
|
|
2130
|
+
if (maxTokensRetry !== void 0) return maxTokensRetry;
|
|
2086
2131
|
const retryResult = handle400ReasoningError(error, {
|
|
2087
2132
|
resolvedModel,
|
|
2088
2133
|
thinkingPayload,
|
|
@@ -2095,6 +2140,25 @@ const createChatCompletions = async (payload) => {
|
|
|
2095
2140
|
}
|
|
2096
2141
|
};
|
|
2097
2142
|
/**
|
|
2143
|
+
* Handle 400 errors caused by `max_tokens` being rejected — o-series and
|
|
2144
|
+
* GPT-5.x require `max_completion_tokens` instead. Learns at runtime:
|
|
2145
|
+
* adds the model to `maxCompletionTokensModels` and retries once with the
|
|
2146
|
+
* field renamed so all future requests skip the 400 entirely.
|
|
2147
|
+
*/
|
|
2148
|
+
function handle400MaxTokensError(error, ctx, releaseSlot) {
|
|
2149
|
+
if (!(error instanceof HTTPError) || error.response.status !== 400) return void 0;
|
|
2150
|
+
const errMsg = error.message;
|
|
2151
|
+
if (!errMsg.includes("max_tokens") || !errMsg.includes("max_completion_tokens")) return void 0;
|
|
2152
|
+
maxCompletionTokensModels.add(ctx.resolvedModel);
|
|
2153
|
+
consola.debug(`Model "${ctx.resolvedModel}" requires max_completion_tokens — switching for future requests`);
|
|
2154
|
+
if (ctx.routedPayload.max_tokens === null || ctx.routedPayload.max_tokens === void 0) return retryWithModifiedPayload(ctx.routedPayload, releaseSlot);
|
|
2155
|
+
const { max_tokens,...rest } = ctx.routedPayload;
|
|
2156
|
+
return retryWithModifiedPayload({
|
|
2157
|
+
...rest,
|
|
2158
|
+
max_completion_tokens: max_tokens
|
|
2159
|
+
}, releaseSlot);
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2098
2162
|
* Handle 400 reasoning_effort errors in the outer createChatCompletions catch.
|
|
2099
2163
|
* Returns a Promise (retry result) if handled, or undefined to re-throw.
|
|
2100
2164
|
*/
|
|
@@ -2159,9 +2223,9 @@ async function createWithSingleAccount(payload) {
|
|
|
2159
2223
|
});
|
|
2160
2224
|
const url = `${copilotBaseUrl(state)}/chat/completions`;
|
|
2161
2225
|
const body = payload.stream ? {
|
|
2162
|
-
...payload,
|
|
2226
|
+
...normalizeMaxTokens(payload),
|
|
2163
2227
|
stream_options: { include_usage: true }
|
|
2164
|
-
} : payload;
|
|
2228
|
+
} : normalizeMaxTokens(payload);
|
|
2165
2229
|
const bodyString = JSON.stringify(body);
|
|
2166
2230
|
let response = await fetchWithRetry(url, () => ({
|
|
2167
2231
|
method: "POST",
|
|
@@ -2187,7 +2251,8 @@ async function createWithSingleAccount(payload) {
|
|
|
2187
2251
|
if (response.status === 400) {
|
|
2188
2252
|
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2189
2253
|
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2190
|
-
|
|
2254
|
+
const isMaxTokensError = errorBody.includes("max_tokens") && errorBody.includes("max_completion_tokens");
|
|
2255
|
+
if (isExpectedReasoningError || isModelNotSupported || isMaxTokensError) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2191
2256
|
else consola.warn(`400: ${errorBody}`);
|
|
2192
2257
|
} else consola.error("Failed to create chat completions", {
|
|
2193
2258
|
status: response.status,
|
|
@@ -2415,9 +2480,9 @@ async function doFetch(payload, source, accountId) {
|
|
|
2415
2480
|
endpoint: url
|
|
2416
2481
|
});
|
|
2417
2482
|
const body = payload.stream ? {
|
|
2418
|
-
...payload,
|
|
2483
|
+
...normalizeMaxTokens(payload),
|
|
2419
2484
|
stream_options: { include_usage: true }
|
|
2420
|
-
} : payload;
|
|
2485
|
+
} : normalizeMaxTokens(payload);
|
|
2421
2486
|
const bodyString = JSON.stringify(body);
|
|
2422
2487
|
const response = await fetchWithRetry(url, () => ({
|
|
2423
2488
|
method: "POST",
|
|
@@ -2432,7 +2497,8 @@ async function doFetch(payload, source, accountId) {
|
|
|
2432
2497
|
if (response.status === 400) {
|
|
2433
2498
|
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2434
2499
|
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2435
|
-
|
|
2500
|
+
const isMaxTokensError = errorBody.includes("max_tokens") && errorBody.includes("max_completion_tokens");
|
|
2501
|
+
if (isExpectedReasoningError || isModelNotSupported || isMaxTokensError) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2436
2502
|
else consola.warn(`400: ${errorBody}`);
|
|
2437
2503
|
} else consola.error("Failed to create chat completions", {
|
|
2438
2504
|
status: response.status,
|
|
@@ -2444,6 +2510,7 @@ async function doFetch(payload, source, accountId) {
|
|
|
2444
2510
|
if (payload.stream) return events(response);
|
|
2445
2511
|
return await response.json();
|
|
2446
2512
|
}
|
|
2513
|
+
|
|
2447
2514
|
//#endregion
|
|
2448
2515
|
//#region src/routes/chat-completions/handler.ts
|
|
2449
2516
|
/**
|
|
@@ -2511,6 +2578,7 @@ function mapReasoningFields(response) {
|
|
|
2511
2578
|
})
|
|
2512
2579
|
};
|
|
2513
2580
|
}
|
|
2581
|
+
|
|
2514
2582
|
//#endregion
|
|
2515
2583
|
//#region src/routes/chat-completions/route.ts
|
|
2516
2584
|
const completionRoutes = new Hono();
|
|
@@ -2521,6 +2589,7 @@ completionRoutes.post("/", async (c) => {
|
|
|
2521
2589
|
return await forwardError(c, error);
|
|
2522
2590
|
}
|
|
2523
2591
|
});
|
|
2592
|
+
|
|
2524
2593
|
//#endregion
|
|
2525
2594
|
//#region src/services/copilot/create-embeddings.ts
|
|
2526
2595
|
const createEmbeddings = async (payload) => {
|
|
@@ -2544,17 +2613,20 @@ const createEmbeddings = async (payload) => {
|
|
|
2544
2613
|
if (!response.ok) throw new HTTPError("Failed to create embeddings", response);
|
|
2545
2614
|
return await response.json();
|
|
2546
2615
|
};
|
|
2616
|
+
|
|
2547
2617
|
//#endregion
|
|
2548
2618
|
//#region src/routes/embeddings/route.ts
|
|
2549
2619
|
const embeddingRoutes = new Hono();
|
|
2550
2620
|
embeddingRoutes.post("/", async (c) => {
|
|
2551
2621
|
try {
|
|
2552
|
-
const
|
|
2622
|
+
const paylod = await c.req.json();
|
|
2623
|
+
const response = await createEmbeddings(paylod);
|
|
2553
2624
|
return c.json(response);
|
|
2554
2625
|
} catch (error) {
|
|
2555
2626
|
return await forwardError(c, error);
|
|
2556
2627
|
}
|
|
2557
2628
|
});
|
|
2629
|
+
|
|
2558
2630
|
//#endregion
|
|
2559
2631
|
//#region src/lib/tokenizer.ts
|
|
2560
2632
|
const ENCODING_MAP = {
|
|
@@ -2737,7 +2809,8 @@ const numTokensForTools = (tools, encoder, constants) => {
|
|
|
2737
2809
|
* Calculate the token count of messages, supporting multiple GPT encoders
|
|
2738
2810
|
*/
|
|
2739
2811
|
const getTokenCount = async (payload, model) => {
|
|
2740
|
-
const
|
|
2812
|
+
const tokenizer = getTokenizerFromModel(model);
|
|
2813
|
+
const encoder = await getEncodeChatFunction(tokenizer);
|
|
2741
2814
|
const constants = getModelConstants(model);
|
|
2742
2815
|
let inputTokens = calculateTokens(payload.messages, encoder, constants);
|
|
2743
2816
|
if (payload.tools && payload.tools.length > 0) inputTokens += numTokensForTools(payload.tools, encoder, constants);
|
|
@@ -2746,6 +2819,7 @@ const getTokenCount = async (payload, model) => {
|
|
|
2746
2819
|
output: 0
|
|
2747
2820
|
};
|
|
2748
2821
|
};
|
|
2822
|
+
|
|
2749
2823
|
//#endregion
|
|
2750
2824
|
//#region src/routes/messages/utils.ts
|
|
2751
2825
|
function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
@@ -2757,6 +2831,7 @@ function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
|
2757
2831
|
content_filter: "end_turn"
|
|
2758
2832
|
}[finishReason];
|
|
2759
2833
|
}
|
|
2834
|
+
|
|
2760
2835
|
//#endregion
|
|
2761
2836
|
//#region src/routes/messages/non-stream-translation.ts
|
|
2762
2837
|
function translateToOpenAI(payload) {
|
|
@@ -2990,6 +3065,7 @@ function getAnthropicToolUseBlocks(toolCalls) {
|
|
|
2990
3065
|
})()
|
|
2991
3066
|
}));
|
|
2992
3067
|
}
|
|
3068
|
+
|
|
2993
3069
|
//#endregion
|
|
2994
3070
|
//#region src/routes/messages/count-tokens-handler.ts
|
|
2995
3071
|
/**
|
|
@@ -3030,19 +3106,20 @@ async function handleCountTokens(c) {
|
|
|
3030
3106
|
return c.json({ input_tokens: 1 });
|
|
3031
3107
|
}
|
|
3032
3108
|
}
|
|
3109
|
+
|
|
3033
3110
|
//#endregion
|
|
3034
3111
|
//#region src/routes/messages/stream-translation.ts
|
|
3035
|
-
function isToolBlockOpen(state) {
|
|
3036
|
-
if (!state.contentBlockOpen) return false;
|
|
3037
|
-
return Object.values(state.toolCalls).some((tc) => tc.anthropicBlockIndex === state.contentBlockIndex);
|
|
3112
|
+
function isToolBlockOpen(state$1) {
|
|
3113
|
+
if (!state$1.contentBlockOpen) return false;
|
|
3114
|
+
return Object.values(state$1.toolCalls).some((tc) => tc.anthropicBlockIndex === state$1.contentBlockIndex);
|
|
3038
3115
|
}
|
|
3039
|
-
function translateChunkToAnthropicEvents(chunk, state) {
|
|
3040
|
-
const events = [];
|
|
3041
|
-
if (chunk.choices.length === 0) return events;
|
|
3116
|
+
function translateChunkToAnthropicEvents(chunk, state$1) {
|
|
3117
|
+
const events$1 = [];
|
|
3118
|
+
if (chunk.choices.length === 0) return events$1;
|
|
3042
3119
|
const choice = chunk.choices[0];
|
|
3043
3120
|
const { delta } = choice;
|
|
3044
|
-
if (!state.messageStartSent) {
|
|
3045
|
-
events.push({
|
|
3121
|
+
if (!state$1.messageStartSent) {
|
|
3122
|
+
events$1.push({
|
|
3046
3123
|
type: "message_start",
|
|
3047
3124
|
message: {
|
|
3048
3125
|
id: chunk.id,
|
|
@@ -3059,33 +3136,33 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3059
3136
|
}
|
|
3060
3137
|
}
|
|
3061
3138
|
});
|
|
3062
|
-
state.messageStartSent = true;
|
|
3139
|
+
state$1.messageStartSent = true;
|
|
3063
3140
|
}
|
|
3064
3141
|
const reasoningContent = delta.reasoning_content ?? delta.reasoning_text;
|
|
3065
3142
|
if (reasoningContent) {
|
|
3066
|
-
if (state.contentBlockOpen && !state.thinkingBlockOpen) {
|
|
3067
|
-
events.push({
|
|
3143
|
+
if (state$1.contentBlockOpen && !state$1.thinkingBlockOpen) {
|
|
3144
|
+
events$1.push({
|
|
3068
3145
|
type: "content_block_stop",
|
|
3069
|
-
index: state.contentBlockIndex
|
|
3146
|
+
index: state$1.contentBlockIndex
|
|
3070
3147
|
});
|
|
3071
|
-
state.contentBlockIndex++;
|
|
3072
|
-
state.contentBlockOpen = false;
|
|
3148
|
+
state$1.contentBlockIndex++;
|
|
3149
|
+
state$1.contentBlockOpen = false;
|
|
3073
3150
|
}
|
|
3074
|
-
if (!state.thinkingBlockOpen) {
|
|
3075
|
-
events.push({
|
|
3151
|
+
if (!state$1.thinkingBlockOpen) {
|
|
3152
|
+
events$1.push({
|
|
3076
3153
|
type: "content_block_start",
|
|
3077
|
-
index: state.contentBlockIndex,
|
|
3154
|
+
index: state$1.contentBlockIndex,
|
|
3078
3155
|
content_block: {
|
|
3079
3156
|
type: "thinking",
|
|
3080
3157
|
thinking: ""
|
|
3081
3158
|
}
|
|
3082
3159
|
});
|
|
3083
|
-
state.contentBlockOpen = true;
|
|
3084
|
-
state.thinkingBlockOpen = true;
|
|
3160
|
+
state$1.contentBlockOpen = true;
|
|
3161
|
+
state$1.thinkingBlockOpen = true;
|
|
3085
3162
|
}
|
|
3086
|
-
events.push({
|
|
3163
|
+
events$1.push({
|
|
3087
3164
|
type: "content_block_delta",
|
|
3088
|
-
index: state.contentBlockIndex,
|
|
3165
|
+
index: state$1.contentBlockIndex,
|
|
3089
3166
|
delta: {
|
|
3090
3167
|
type: "thinking_delta",
|
|
3091
3168
|
thinking: reasoningContent
|
|
@@ -3093,37 +3170,37 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3093
3170
|
});
|
|
3094
3171
|
}
|
|
3095
3172
|
if (delta.content) {
|
|
3096
|
-
if (state.thinkingBlockOpen) {
|
|
3097
|
-
events.push({
|
|
3173
|
+
if (state$1.thinkingBlockOpen) {
|
|
3174
|
+
events$1.push({
|
|
3098
3175
|
type: "content_block_stop",
|
|
3099
|
-
index: state.contentBlockIndex
|
|
3176
|
+
index: state$1.contentBlockIndex
|
|
3100
3177
|
});
|
|
3101
|
-
state.contentBlockIndex++;
|
|
3102
|
-
state.contentBlockOpen = false;
|
|
3103
|
-
state.thinkingBlockOpen = false;
|
|
3178
|
+
state$1.contentBlockIndex++;
|
|
3179
|
+
state$1.contentBlockOpen = false;
|
|
3180
|
+
state$1.thinkingBlockOpen = false;
|
|
3104
3181
|
}
|
|
3105
|
-
if (isToolBlockOpen(state)) {
|
|
3106
|
-
events.push({
|
|
3182
|
+
if (isToolBlockOpen(state$1)) {
|
|
3183
|
+
events$1.push({
|
|
3107
3184
|
type: "content_block_stop",
|
|
3108
|
-
index: state.contentBlockIndex
|
|
3185
|
+
index: state$1.contentBlockIndex
|
|
3109
3186
|
});
|
|
3110
|
-
state.contentBlockIndex++;
|
|
3111
|
-
state.contentBlockOpen = false;
|
|
3187
|
+
state$1.contentBlockIndex++;
|
|
3188
|
+
state$1.contentBlockOpen = false;
|
|
3112
3189
|
}
|
|
3113
|
-
if (!state.contentBlockOpen) {
|
|
3114
|
-
events.push({
|
|
3190
|
+
if (!state$1.contentBlockOpen) {
|
|
3191
|
+
events$1.push({
|
|
3115
3192
|
type: "content_block_start",
|
|
3116
|
-
index: state.contentBlockIndex,
|
|
3193
|
+
index: state$1.contentBlockIndex,
|
|
3117
3194
|
content_block: {
|
|
3118
3195
|
type: "text",
|
|
3119
3196
|
text: ""
|
|
3120
3197
|
}
|
|
3121
3198
|
});
|
|
3122
|
-
state.contentBlockOpen = true;
|
|
3199
|
+
state$1.contentBlockOpen = true;
|
|
3123
3200
|
}
|
|
3124
|
-
events.push({
|
|
3201
|
+
events$1.push({
|
|
3125
3202
|
type: "content_block_delta",
|
|
3126
|
-
index: state.contentBlockIndex,
|
|
3203
|
+
index: state$1.contentBlockIndex,
|
|
3127
3204
|
delta: {
|
|
3128
3205
|
type: "text_delta",
|
|
3129
3206
|
text: delta.content
|
|
@@ -3131,32 +3208,32 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3131
3208
|
});
|
|
3132
3209
|
}
|
|
3133
3210
|
if (delta.tool_calls) {
|
|
3134
|
-
if (state.thinkingBlockOpen) {
|
|
3135
|
-
events.push({
|
|
3211
|
+
if (state$1.thinkingBlockOpen) {
|
|
3212
|
+
events$1.push({
|
|
3136
3213
|
type: "content_block_stop",
|
|
3137
|
-
index: state.contentBlockIndex
|
|
3214
|
+
index: state$1.contentBlockIndex
|
|
3138
3215
|
});
|
|
3139
|
-
state.contentBlockIndex++;
|
|
3140
|
-
state.contentBlockOpen = false;
|
|
3141
|
-
state.thinkingBlockOpen = false;
|
|
3216
|
+
state$1.contentBlockIndex++;
|
|
3217
|
+
state$1.contentBlockOpen = false;
|
|
3218
|
+
state$1.thinkingBlockOpen = false;
|
|
3142
3219
|
}
|
|
3143
3220
|
for (const toolCall of delta.tool_calls) {
|
|
3144
3221
|
if (toolCall.id && toolCall.function?.name) {
|
|
3145
|
-
if (state.contentBlockOpen) {
|
|
3146
|
-
events.push({
|
|
3222
|
+
if (state$1.contentBlockOpen) {
|
|
3223
|
+
events$1.push({
|
|
3147
3224
|
type: "content_block_stop",
|
|
3148
|
-
index: state.contentBlockIndex
|
|
3225
|
+
index: state$1.contentBlockIndex
|
|
3149
3226
|
});
|
|
3150
|
-
state.contentBlockIndex++;
|
|
3151
|
-
state.contentBlockOpen = false;
|
|
3227
|
+
state$1.contentBlockIndex++;
|
|
3228
|
+
state$1.contentBlockOpen = false;
|
|
3152
3229
|
}
|
|
3153
|
-
const anthropicBlockIndex = state.contentBlockIndex;
|
|
3154
|
-
state.toolCalls[toolCall.index] = {
|
|
3230
|
+
const anthropicBlockIndex = state$1.contentBlockIndex;
|
|
3231
|
+
state$1.toolCalls[toolCall.index] = {
|
|
3155
3232
|
id: toolCall.id,
|
|
3156
3233
|
name: toolCall.function.name,
|
|
3157
3234
|
anthropicBlockIndex
|
|
3158
3235
|
};
|
|
3159
|
-
events.push({
|
|
3236
|
+
events$1.push({
|
|
3160
3237
|
type: "content_block_start",
|
|
3161
3238
|
index: anthropicBlockIndex,
|
|
3162
3239
|
content_block: {
|
|
@@ -3166,11 +3243,11 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3166
3243
|
input: {}
|
|
3167
3244
|
}
|
|
3168
3245
|
});
|
|
3169
|
-
state.contentBlockOpen = true;
|
|
3246
|
+
state$1.contentBlockOpen = true;
|
|
3170
3247
|
}
|
|
3171
3248
|
if (toolCall.function?.arguments) {
|
|
3172
|
-
const toolCallInfo = state.toolCalls[toolCall.index];
|
|
3173
|
-
if (toolCallInfo) events.push({
|
|
3249
|
+
const toolCallInfo = state$1.toolCalls[toolCall.index];
|
|
3250
|
+
if (toolCallInfo) events$1.push({
|
|
3174
3251
|
type: "content_block_delta",
|
|
3175
3252
|
index: toolCallInfo.anthropicBlockIndex,
|
|
3176
3253
|
delta: {
|
|
@@ -3182,14 +3259,14 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3182
3259
|
}
|
|
3183
3260
|
}
|
|
3184
3261
|
if (choice.finish_reason) {
|
|
3185
|
-
if (state.contentBlockOpen) {
|
|
3186
|
-
events.push({
|
|
3262
|
+
if (state$1.contentBlockOpen) {
|
|
3263
|
+
events$1.push({
|
|
3187
3264
|
type: "content_block_stop",
|
|
3188
|
-
index: state.contentBlockIndex
|
|
3265
|
+
index: state$1.contentBlockIndex
|
|
3189
3266
|
});
|
|
3190
|
-
state.contentBlockOpen = false;
|
|
3267
|
+
state$1.contentBlockOpen = false;
|
|
3191
3268
|
}
|
|
3192
|
-
events.push({
|
|
3269
|
+
events$1.push({
|
|
3193
3270
|
type: "message_delta",
|
|
3194
3271
|
delta: {
|
|
3195
3272
|
stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),
|
|
@@ -3202,7 +3279,7 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3202
3279
|
}
|
|
3203
3280
|
}, { type: "message_stop" });
|
|
3204
3281
|
}
|
|
3205
|
-
return events;
|
|
3282
|
+
return events$1;
|
|
3206
3283
|
}
|
|
3207
3284
|
function translateErrorToAnthropicErrorEvent() {
|
|
3208
3285
|
return {
|
|
@@ -3213,6 +3290,7 @@ function translateErrorToAnthropicErrorEvent() {
|
|
|
3213
3290
|
}
|
|
3214
3291
|
};
|
|
3215
3292
|
}
|
|
3293
|
+
|
|
3216
3294
|
//#endregion
|
|
3217
3295
|
//#region src/routes/messages/handler.ts
|
|
3218
3296
|
/** Heartbeat interval — keeps the downstream connection alive. */
|
|
@@ -3357,6 +3435,7 @@ async function handleCompletion(c) {
|
|
|
3357
3435
|
});
|
|
3358
3436
|
}
|
|
3359
3437
|
const isNonStreaming = (response) => Object.hasOwn(response, "choices");
|
|
3438
|
+
|
|
3360
3439
|
//#endregion
|
|
3361
3440
|
//#region src/routes/messages/route.ts
|
|
3362
3441
|
const messageRoutes = new Hono();
|
|
@@ -3374,6 +3453,7 @@ messageRoutes.post("/count_tokens", async (c) => {
|
|
|
3374
3453
|
return await forwardError(c, error);
|
|
3375
3454
|
}
|
|
3376
3455
|
});
|
|
3456
|
+
|
|
3377
3457
|
//#endregion
|
|
3378
3458
|
//#region src/routes/models/route.ts
|
|
3379
3459
|
const modelRoutes = new Hono();
|
|
@@ -3398,6 +3478,7 @@ modelRoutes.get("/", async (c) => {
|
|
|
3398
3478
|
return await forwardError(c, error);
|
|
3399
3479
|
}
|
|
3400
3480
|
});
|
|
3481
|
+
|
|
3401
3482
|
//#endregion
|
|
3402
3483
|
//#region src/routes/token/route.ts
|
|
3403
3484
|
const tokenRoute = new Hono();
|
|
@@ -3413,6 +3494,7 @@ tokenRoute.get("/", (c) => {
|
|
|
3413
3494
|
}, 500);
|
|
3414
3495
|
}
|
|
3415
3496
|
});
|
|
3497
|
+
|
|
3416
3498
|
//#endregion
|
|
3417
3499
|
//#region src/routes/usage/route.ts
|
|
3418
3500
|
const usageRoute = new Hono();
|
|
@@ -3421,8 +3503,8 @@ usageRoute.get("/", async (c) => {
|
|
|
3421
3503
|
if (state.multiAccountEnabled && accountManager.hasAccounts()) {
|
|
3422
3504
|
const account = accountManager.getActiveAccount();
|
|
3423
3505
|
if (account) {
|
|
3424
|
-
const usage = await getCopilotUsage(account.githubToken);
|
|
3425
|
-
return c.json(usage);
|
|
3506
|
+
const usage$1 = await getCopilotUsage(account.githubToken);
|
|
3507
|
+
return c.json(usage$1);
|
|
3426
3508
|
}
|
|
3427
3509
|
}
|
|
3428
3510
|
const usage = await getCopilotUsage();
|
|
@@ -3433,6 +3515,7 @@ usageRoute.get("/", async (c) => {
|
|
|
3433
3515
|
return c.json({ error: "Failed to fetch Copilot usage" }, 500);
|
|
3434
3516
|
}
|
|
3435
3517
|
});
|
|
3518
|
+
|
|
3436
3519
|
//#endregion
|
|
3437
3520
|
//#region src/server.ts
|
|
3438
3521
|
const server = new Hono();
|
|
@@ -3450,6 +3533,7 @@ server.route("/v1/models", modelRoutes);
|
|
|
3450
3533
|
server.route("/v1/embeddings", embeddingRoutes);
|
|
3451
3534
|
server.route("/v1/messages", messageRoutes);
|
|
3452
3535
|
server.route("/api", adminRoutes);
|
|
3536
|
+
|
|
3453
3537
|
//#endregion
|
|
3454
3538
|
//#region src/start.ts
|
|
3455
3539
|
/**
|
|
@@ -3546,7 +3630,7 @@ async function validateGitHubToken(token) {
|
|
|
3546
3630
|
state.githubToken = token;
|
|
3547
3631
|
consola.info("Using provided GitHub token");
|
|
3548
3632
|
try {
|
|
3549
|
-
const { getGitHubUser } = await import("./get-user-
|
|
3633
|
+
const { getGitHubUser } = await import("./get-user-DiK-7IaC.js");
|
|
3550
3634
|
const user = await getGitHubUser();
|
|
3551
3635
|
consola.info(`Logged in as ${user.login}`);
|
|
3552
3636
|
} catch (error) {
|
|
@@ -3570,26 +3654,26 @@ async function validateGitHubToken(token) {
|
|
|
3570
3654
|
* - proxyEnv: Initialize proxy settings from environment variables
|
|
3571
3655
|
* - apiKeys: Optional list of API keys to enable API key authentication
|
|
3572
3656
|
*/
|
|
3573
|
-
async function runServer(options) {
|
|
3657
|
+
async function runServer(options$1) {
|
|
3574
3658
|
const savedProxyApplied = await applyProxyConfig();
|
|
3575
|
-
if (options.proxyEnv) initProxyFromEnv();
|
|
3659
|
+
if (options$1.proxyEnv) initProxyFromEnv();
|
|
3576
3660
|
else if (savedProxyApplied) initProxyFromEnv();
|
|
3577
|
-
if (options.verbose) {
|
|
3661
|
+
if (options$1.verbose) {
|
|
3578
3662
|
consola.level = 5;
|
|
3579
3663
|
consola.info("Verbose logging enabled");
|
|
3580
3664
|
}
|
|
3581
|
-
state.accountType = options.accountType;
|
|
3582
|
-
if (options.accountType !== "individual") consola.info(`Using ${options.accountType} plan GitHub account`);
|
|
3583
|
-
state.manualApprove = options.manual;
|
|
3584
|
-
state.rateLimitSeconds = options.rateLimit;
|
|
3585
|
-
state.rateLimitWait = options.rateLimitWait;
|
|
3586
|
-
state.showToken = options.showToken;
|
|
3587
|
-
state.apiKeys = options.apiKeys;
|
|
3665
|
+
state.accountType = options$1.accountType;
|
|
3666
|
+
if (options$1.accountType !== "individual") consola.info(`Using ${options$1.accountType} plan GitHub account`);
|
|
3667
|
+
state.manualApprove = options$1.manual;
|
|
3668
|
+
state.rateLimitSeconds = options$1.rateLimit;
|
|
3669
|
+
state.rateLimitWait = options$1.rateLimitWait;
|
|
3670
|
+
state.showToken = options$1.showToken;
|
|
3671
|
+
state.apiKeys = options$1.apiKeys;
|
|
3588
3672
|
if (state.apiKeys && state.apiKeys.length > 0) consola.info(`API key authentication enabled with ${state.apiKeys.length} key(s)`);
|
|
3589
3673
|
await ensurePaths();
|
|
3590
3674
|
await cacheVSCodeVersion();
|
|
3591
3675
|
try {
|
|
3592
|
-
await (options.githubToken ? validateGitHubToken(options.githubToken) : setupGitHubToken());
|
|
3676
|
+
await (options$1.githubToken ? validateGitHubToken(options$1.githubToken) : setupGitHubToken());
|
|
3593
3677
|
} catch (error) {
|
|
3594
3678
|
consola.error(`GitHub authentication failed: ${rootCause(error)}`);
|
|
3595
3679
|
consola.info("The server will start, but requests may fail until connectivity is restored");
|
|
@@ -3597,11 +3681,11 @@ async function runServer(options) {
|
|
|
3597
3681
|
try {
|
|
3598
3682
|
await setupCopilotToken();
|
|
3599
3683
|
} catch (error) {
|
|
3600
|
-
const { HTTPError } = await import("./error-
|
|
3601
|
-
if (error instanceof HTTPError && error.response.status === 401) {
|
|
3684
|
+
const { HTTPError: HTTPError$1 } = await import("./error-HsNBNEyW.js");
|
|
3685
|
+
if (error instanceof HTTPError$1 && error.response.status === 401) {
|
|
3602
3686
|
consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
|
|
3603
|
-
const { clearGithubToken } = await import("./token-
|
|
3604
|
-
await clearGithubToken();
|
|
3687
|
+
const { clearGithubToken: clearGithubToken$1 } = await import("./token-C8PZ2fm8.js");
|
|
3688
|
+
await clearGithubToken$1();
|
|
3605
3689
|
consola.info("Please restart to re-authenticate");
|
|
3606
3690
|
}
|
|
3607
3691
|
throw error;
|
|
@@ -3610,111 +3694,113 @@ async function runServer(options) {
|
|
|
3610
3694
|
await initMultiAccount();
|
|
3611
3695
|
await initModelRouting();
|
|
3612
3696
|
consola.info(`Available models: \n${state.models?.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
3613
|
-
const serverUrl = `http://localhost:${options.port}`;
|
|
3614
|
-
if (options.claudeCode) await setupClaudeCodeEnv(serverUrl);
|
|
3697
|
+
const serverUrl = `http://localhost:${options$1.port}`;
|
|
3698
|
+
if (options$1.claudeCode) await setupClaudeCodeEnv(serverUrl);
|
|
3615
3699
|
const multiAccountInfo = state.multiAccountEnabled ? `\n👥 Multi-account: ${accountManager.activeAccountCount}/${accountManager.accountCount} active` : "";
|
|
3616
3700
|
consola.box(`🌐 Usage Viewer: https://imbuxiangnan-cyber.github.io/copilot-api-plus?endpoint=${serverUrl}/usage${multiAccountInfo}`);
|
|
3617
3701
|
serve({
|
|
3618
3702
|
fetch: server.fetch,
|
|
3619
|
-
port: options.port
|
|
3703
|
+
port: options$1.port
|
|
3620
3704
|
});
|
|
3621
3705
|
}
|
|
3706
|
+
const start = defineCommand({
|
|
3707
|
+
meta: {
|
|
3708
|
+
name: "start",
|
|
3709
|
+
description: "Start the Copilot API server"
|
|
3710
|
+
},
|
|
3711
|
+
args: {
|
|
3712
|
+
port: {
|
|
3713
|
+
alias: "p",
|
|
3714
|
+
type: "string",
|
|
3715
|
+
default: "4141",
|
|
3716
|
+
description: "Port to listen on"
|
|
3717
|
+
},
|
|
3718
|
+
verbose: {
|
|
3719
|
+
alias: "v",
|
|
3720
|
+
type: "boolean",
|
|
3721
|
+
default: false,
|
|
3722
|
+
description: "Enable verbose logging"
|
|
3723
|
+
},
|
|
3724
|
+
"account-type": {
|
|
3725
|
+
alias: "a",
|
|
3726
|
+
type: "string",
|
|
3727
|
+
default: "individual",
|
|
3728
|
+
description: "Account type to use (individual, business, enterprise)"
|
|
3729
|
+
},
|
|
3730
|
+
manual: {
|
|
3731
|
+
type: "boolean",
|
|
3732
|
+
default: false,
|
|
3733
|
+
description: "Enable manual request approval"
|
|
3734
|
+
},
|
|
3735
|
+
"rate-limit": {
|
|
3736
|
+
alias: "r",
|
|
3737
|
+
type: "string",
|
|
3738
|
+
description: "Rate limit in seconds between requests"
|
|
3739
|
+
},
|
|
3740
|
+
wait: {
|
|
3741
|
+
alias: "w",
|
|
3742
|
+
type: "boolean",
|
|
3743
|
+
default: false,
|
|
3744
|
+
description: "Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"
|
|
3745
|
+
},
|
|
3746
|
+
"github-token": {
|
|
3747
|
+
alias: "g",
|
|
3748
|
+
type: "string",
|
|
3749
|
+
description: "Provide GitHub token directly (must be generated using the `auth` subcommand)"
|
|
3750
|
+
},
|
|
3751
|
+
"claude-code": {
|
|
3752
|
+
alias: "c",
|
|
3753
|
+
type: "boolean",
|
|
3754
|
+
default: false,
|
|
3755
|
+
description: "Generate a command to launch Claude Code with Copilot API config"
|
|
3756
|
+
},
|
|
3757
|
+
"show-token": {
|
|
3758
|
+
type: "boolean",
|
|
3759
|
+
default: false,
|
|
3760
|
+
description: "Show GitHub and Copilot tokens on fetch and refresh"
|
|
3761
|
+
},
|
|
3762
|
+
"proxy-env": {
|
|
3763
|
+
type: "boolean",
|
|
3764
|
+
default: false,
|
|
3765
|
+
description: "Initialize proxy from environment variables"
|
|
3766
|
+
},
|
|
3767
|
+
"api-key": {
|
|
3768
|
+
type: "string",
|
|
3769
|
+
description: "API keys for authentication"
|
|
3770
|
+
}
|
|
3771
|
+
},
|
|
3772
|
+
run({ args }) {
|
|
3773
|
+
const rateLimitRaw = args["rate-limit"];
|
|
3774
|
+
const rateLimit = rateLimitRaw === void 0 ? void 0 : Number.parseInt(rateLimitRaw, 10);
|
|
3775
|
+
const apiKeyRaw = args["api-key"];
|
|
3776
|
+
let apiKeys;
|
|
3777
|
+
if (apiKeyRaw) apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw];
|
|
3778
|
+
return runServer({
|
|
3779
|
+
port: Number.parseInt(args.port, 10),
|
|
3780
|
+
verbose: args.verbose,
|
|
3781
|
+
accountType: args["account-type"],
|
|
3782
|
+
manual: args.manual,
|
|
3783
|
+
rateLimit,
|
|
3784
|
+
rateLimitWait: args.wait,
|
|
3785
|
+
githubToken: args["github-token"],
|
|
3786
|
+
claudeCode: args["claude-code"],
|
|
3787
|
+
showToken: args["show-token"],
|
|
3788
|
+
proxyEnv: args["proxy-env"],
|
|
3789
|
+
apiKeys
|
|
3790
|
+
});
|
|
3791
|
+
}
|
|
3792
|
+
});
|
|
3793
|
+
|
|
3622
3794
|
//#endregion
|
|
3623
3795
|
//#region src/main.ts
|
|
3624
|
-
|
|
3796
|
+
const main = defineCommand({
|
|
3625
3797
|
meta: {
|
|
3626
3798
|
name: "copilot-api-plus",
|
|
3627
3799
|
description: "A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements."
|
|
3628
3800
|
},
|
|
3629
3801
|
subCommands: {
|
|
3630
3802
|
auth,
|
|
3631
|
-
start
|
|
3632
|
-
meta: {
|
|
3633
|
-
name: "start",
|
|
3634
|
-
description: "Start the Copilot API server"
|
|
3635
|
-
},
|
|
3636
|
-
args: {
|
|
3637
|
-
port: {
|
|
3638
|
-
alias: "p",
|
|
3639
|
-
type: "string",
|
|
3640
|
-
default: "4141",
|
|
3641
|
-
description: "Port to listen on"
|
|
3642
|
-
},
|
|
3643
|
-
verbose: {
|
|
3644
|
-
alias: "v",
|
|
3645
|
-
type: "boolean",
|
|
3646
|
-
default: false,
|
|
3647
|
-
description: "Enable verbose logging"
|
|
3648
|
-
},
|
|
3649
|
-
"account-type": {
|
|
3650
|
-
alias: "a",
|
|
3651
|
-
type: "string",
|
|
3652
|
-
default: "individual",
|
|
3653
|
-
description: "Account type to use (individual, business, enterprise)"
|
|
3654
|
-
},
|
|
3655
|
-
manual: {
|
|
3656
|
-
type: "boolean",
|
|
3657
|
-
default: false,
|
|
3658
|
-
description: "Enable manual request approval"
|
|
3659
|
-
},
|
|
3660
|
-
"rate-limit": {
|
|
3661
|
-
alias: "r",
|
|
3662
|
-
type: "string",
|
|
3663
|
-
description: "Rate limit in seconds between requests"
|
|
3664
|
-
},
|
|
3665
|
-
wait: {
|
|
3666
|
-
alias: "w",
|
|
3667
|
-
type: "boolean",
|
|
3668
|
-
default: false,
|
|
3669
|
-
description: "Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"
|
|
3670
|
-
},
|
|
3671
|
-
"github-token": {
|
|
3672
|
-
alias: "g",
|
|
3673
|
-
type: "string",
|
|
3674
|
-
description: "Provide GitHub token directly (must be generated using the `auth` subcommand)"
|
|
3675
|
-
},
|
|
3676
|
-
"claude-code": {
|
|
3677
|
-
alias: "c",
|
|
3678
|
-
type: "boolean",
|
|
3679
|
-
default: false,
|
|
3680
|
-
description: "Generate a command to launch Claude Code with Copilot API config"
|
|
3681
|
-
},
|
|
3682
|
-
"show-token": {
|
|
3683
|
-
type: "boolean",
|
|
3684
|
-
default: false,
|
|
3685
|
-
description: "Show GitHub and Copilot tokens on fetch and refresh"
|
|
3686
|
-
},
|
|
3687
|
-
"proxy-env": {
|
|
3688
|
-
type: "boolean",
|
|
3689
|
-
default: false,
|
|
3690
|
-
description: "Initialize proxy from environment variables"
|
|
3691
|
-
},
|
|
3692
|
-
"api-key": {
|
|
3693
|
-
type: "string",
|
|
3694
|
-
description: "API keys for authentication"
|
|
3695
|
-
}
|
|
3696
|
-
},
|
|
3697
|
-
run({ args }) {
|
|
3698
|
-
const rateLimitRaw = args["rate-limit"];
|
|
3699
|
-
const rateLimit = rateLimitRaw === void 0 ? void 0 : Number.parseInt(rateLimitRaw, 10);
|
|
3700
|
-
const apiKeyRaw = args["api-key"];
|
|
3701
|
-
let apiKeys;
|
|
3702
|
-
if (apiKeyRaw) apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw];
|
|
3703
|
-
return runServer({
|
|
3704
|
-
port: Number.parseInt(args.port, 10),
|
|
3705
|
-
verbose: args.verbose,
|
|
3706
|
-
accountType: args["account-type"],
|
|
3707
|
-
manual: args.manual,
|
|
3708
|
-
rateLimit,
|
|
3709
|
-
rateLimitWait: args.wait,
|
|
3710
|
-
githubToken: args["github-token"],
|
|
3711
|
-
claudeCode: args["claude-code"],
|
|
3712
|
-
showToken: args["show-token"],
|
|
3713
|
-
proxyEnv: args["proxy-env"],
|
|
3714
|
-
apiKeys
|
|
3715
|
-
});
|
|
3716
|
-
}
|
|
3717
|
-
}),
|
|
3803
|
+
start,
|
|
3718
3804
|
"check-usage": checkUsage,
|
|
3719
3805
|
"add-account": addAccount,
|
|
3720
3806
|
"list-accounts": listAccounts,
|
|
@@ -3723,8 +3809,9 @@ await runMain(defineCommand({
|
|
|
3723
3809
|
logout,
|
|
3724
3810
|
proxy
|
|
3725
3811
|
}
|
|
3726
|
-
})
|
|
3727
|
-
|
|
3728
|
-
export {};
|
|
3812
|
+
});
|
|
3813
|
+
await runMain(main);
|
|
3729
3814
|
|
|
3815
|
+
//#endregion
|
|
3816
|
+
export { };
|
|
3730
3817
|
//# sourceMappingURL=main.js.map
|