copilot-api-plus 1.2.51 → 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 +431 -325
- 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",
|
|
@@ -2184,9 +2248,13 @@ async function createWithSingleAccount(payload) {
|
|
|
2184
2248
|
}
|
|
2185
2249
|
if (!response.ok) {
|
|
2186
2250
|
const errorBody = await response.text();
|
|
2187
|
-
if (response.status === 400)
|
|
2188
|
-
|
|
2189
|
-
|
|
2251
|
+
if (response.status === 400) {
|
|
2252
|
+
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2253
|
+
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2254
|
+
const isMaxTokensError = errorBody.includes("max_tokens") && errorBody.includes("max_completion_tokens");
|
|
2255
|
+
if (isExpectedReasoningError || isModelNotSupported || isMaxTokensError) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2256
|
+
else consola.warn(`400: ${errorBody}`);
|
|
2257
|
+
} else consola.error("Failed to create chat completions", {
|
|
2190
2258
|
status: response.status,
|
|
2191
2259
|
statusText: response.statusText,
|
|
2192
2260
|
body: errorBody
|
|
@@ -2412,9 +2480,9 @@ async function doFetch(payload, source, accountId) {
|
|
|
2412
2480
|
endpoint: url
|
|
2413
2481
|
});
|
|
2414
2482
|
const body = payload.stream ? {
|
|
2415
|
-
...payload,
|
|
2483
|
+
...normalizeMaxTokens(payload),
|
|
2416
2484
|
stream_options: { include_usage: true }
|
|
2417
|
-
} : payload;
|
|
2485
|
+
} : normalizeMaxTokens(payload);
|
|
2418
2486
|
const bodyString = JSON.stringify(body);
|
|
2419
2487
|
const response = await fetchWithRetry(url, () => ({
|
|
2420
2488
|
method: "POST",
|
|
@@ -2426,9 +2494,13 @@ async function doFetch(payload, source, accountId) {
|
|
|
2426
2494
|
});
|
|
2427
2495
|
if (!response.ok) {
|
|
2428
2496
|
const errorBody = await response.text();
|
|
2429
|
-
if (response.status === 400)
|
|
2430
|
-
|
|
2431
|
-
|
|
2497
|
+
if (response.status === 400) {
|
|
2498
|
+
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2499
|
+
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2500
|
+
const isMaxTokensError = errorBody.includes("max_tokens") && errorBody.includes("max_completion_tokens");
|
|
2501
|
+
if (isExpectedReasoningError || isModelNotSupported || isMaxTokensError) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2502
|
+
else consola.warn(`400: ${errorBody}`);
|
|
2503
|
+
} else consola.error("Failed to create chat completions", {
|
|
2432
2504
|
status: response.status,
|
|
2433
2505
|
statusText: response.statusText,
|
|
2434
2506
|
body: errorBody
|
|
@@ -2438,6 +2510,7 @@ async function doFetch(payload, source, accountId) {
|
|
|
2438
2510
|
if (payload.stream) return events(response);
|
|
2439
2511
|
return await response.json();
|
|
2440
2512
|
}
|
|
2513
|
+
|
|
2441
2514
|
//#endregion
|
|
2442
2515
|
//#region src/routes/chat-completions/handler.ts
|
|
2443
2516
|
/**
|
|
@@ -2505,6 +2578,7 @@ function mapReasoningFields(response) {
|
|
|
2505
2578
|
})
|
|
2506
2579
|
};
|
|
2507
2580
|
}
|
|
2581
|
+
|
|
2508
2582
|
//#endregion
|
|
2509
2583
|
//#region src/routes/chat-completions/route.ts
|
|
2510
2584
|
const completionRoutes = new Hono();
|
|
@@ -2515,6 +2589,7 @@ completionRoutes.post("/", async (c) => {
|
|
|
2515
2589
|
return await forwardError(c, error);
|
|
2516
2590
|
}
|
|
2517
2591
|
});
|
|
2592
|
+
|
|
2518
2593
|
//#endregion
|
|
2519
2594
|
//#region src/services/copilot/create-embeddings.ts
|
|
2520
2595
|
const createEmbeddings = async (payload) => {
|
|
@@ -2538,17 +2613,20 @@ const createEmbeddings = async (payload) => {
|
|
|
2538
2613
|
if (!response.ok) throw new HTTPError("Failed to create embeddings", response);
|
|
2539
2614
|
return await response.json();
|
|
2540
2615
|
};
|
|
2616
|
+
|
|
2541
2617
|
//#endregion
|
|
2542
2618
|
//#region src/routes/embeddings/route.ts
|
|
2543
2619
|
const embeddingRoutes = new Hono();
|
|
2544
2620
|
embeddingRoutes.post("/", async (c) => {
|
|
2545
2621
|
try {
|
|
2546
|
-
const
|
|
2622
|
+
const paylod = await c.req.json();
|
|
2623
|
+
const response = await createEmbeddings(paylod);
|
|
2547
2624
|
return c.json(response);
|
|
2548
2625
|
} catch (error) {
|
|
2549
2626
|
return await forwardError(c, error);
|
|
2550
2627
|
}
|
|
2551
2628
|
});
|
|
2629
|
+
|
|
2552
2630
|
//#endregion
|
|
2553
2631
|
//#region src/lib/tokenizer.ts
|
|
2554
2632
|
const ENCODING_MAP = {
|
|
@@ -2731,7 +2809,8 @@ const numTokensForTools = (tools, encoder, constants) => {
|
|
|
2731
2809
|
* Calculate the token count of messages, supporting multiple GPT encoders
|
|
2732
2810
|
*/
|
|
2733
2811
|
const getTokenCount = async (payload, model) => {
|
|
2734
|
-
const
|
|
2812
|
+
const tokenizer = getTokenizerFromModel(model);
|
|
2813
|
+
const encoder = await getEncodeChatFunction(tokenizer);
|
|
2735
2814
|
const constants = getModelConstants(model);
|
|
2736
2815
|
let inputTokens = calculateTokens(payload.messages, encoder, constants);
|
|
2737
2816
|
if (payload.tools && payload.tools.length > 0) inputTokens += numTokensForTools(payload.tools, encoder, constants);
|
|
@@ -2740,6 +2819,7 @@ const getTokenCount = async (payload, model) => {
|
|
|
2740
2819
|
output: 0
|
|
2741
2820
|
};
|
|
2742
2821
|
};
|
|
2822
|
+
|
|
2743
2823
|
//#endregion
|
|
2744
2824
|
//#region src/routes/messages/utils.ts
|
|
2745
2825
|
function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
@@ -2751,6 +2831,7 @@ function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
|
2751
2831
|
content_filter: "end_turn"
|
|
2752
2832
|
}[finishReason];
|
|
2753
2833
|
}
|
|
2834
|
+
|
|
2754
2835
|
//#endregion
|
|
2755
2836
|
//#region src/routes/messages/non-stream-translation.ts
|
|
2756
2837
|
function translateToOpenAI(payload) {
|
|
@@ -2775,11 +2856,20 @@ function translateModelName(model) {
|
|
|
2775
2856
|
const supportedModels = state.models?.data.map((m) => m.id) ?? [];
|
|
2776
2857
|
if (supportedModels.includes(model)) return model;
|
|
2777
2858
|
const modelBase = model.replace(/-\d{8}$/, "");
|
|
2778
|
-
if (supportedModels.includes(modelBase))
|
|
2859
|
+
if (supportedModels.includes(modelBase)) {
|
|
2860
|
+
consola.debug(`Model name: "${model}" → "${modelBase}" (stripped date suffix)`);
|
|
2861
|
+
return modelBase;
|
|
2862
|
+
}
|
|
2779
2863
|
const modelWithDot = modelBase.replace(/-(\d+)-(\d+)$/, "-$1.$2");
|
|
2780
|
-
if (supportedModels.includes(modelWithDot))
|
|
2864
|
+
if (supportedModels.includes(modelWithDot)) {
|
|
2865
|
+
consola.debug(`Model name: "${model}" → "${modelWithDot}" (dash→dot)`);
|
|
2866
|
+
return modelWithDot;
|
|
2867
|
+
}
|
|
2781
2868
|
const modelWithDash = model.replace(/(\d+)\.(\d+)/, "$1-$2");
|
|
2782
|
-
if (supportedModels.includes(modelWithDash))
|
|
2869
|
+
if (supportedModels.includes(modelWithDash)) {
|
|
2870
|
+
consola.debug(`Model name: "${model}" → "${modelWithDash}" (dot→dash)`);
|
|
2871
|
+
return modelWithDash;
|
|
2872
|
+
}
|
|
2783
2873
|
for (const [oldFormat, newFormat] of Object.entries({
|
|
2784
2874
|
"claude-3-5-sonnet": "claude-sonnet-4.5",
|
|
2785
2875
|
"claude-3-sonnet": "claude-sonnet-4",
|
|
@@ -2787,7 +2877,11 @@ function translateModelName(model) {
|
|
|
2787
2877
|
"claude-3-opus": "claude-opus-4.5",
|
|
2788
2878
|
"claude-3-5-haiku": "claude-haiku-4.5",
|
|
2789
2879
|
"claude-3-haiku": "claude-haiku-4.5"
|
|
2790
|
-
})) if (modelBase.startsWith(oldFormat) && supportedModels.includes(newFormat))
|
|
2880
|
+
})) if (modelBase.startsWith(oldFormat) && supportedModels.includes(newFormat)) {
|
|
2881
|
+
consola.debug(`Model name: "${model}" → "${newFormat}" (legacy mapping)`);
|
|
2882
|
+
return newFormat;
|
|
2883
|
+
}
|
|
2884
|
+
consola.warn(`Model name: "${model}" not found in supported models list, passing as-is`);
|
|
2791
2885
|
return model;
|
|
2792
2886
|
}
|
|
2793
2887
|
function translateAnthropicMessagesToOpenAI(anthropicMessages, system) {
|
|
@@ -2971,6 +3065,7 @@ function getAnthropicToolUseBlocks(toolCalls) {
|
|
|
2971
3065
|
})()
|
|
2972
3066
|
}));
|
|
2973
3067
|
}
|
|
3068
|
+
|
|
2974
3069
|
//#endregion
|
|
2975
3070
|
//#region src/routes/messages/count-tokens-handler.ts
|
|
2976
3071
|
/**
|
|
@@ -3011,19 +3106,20 @@ async function handleCountTokens(c) {
|
|
|
3011
3106
|
return c.json({ input_tokens: 1 });
|
|
3012
3107
|
}
|
|
3013
3108
|
}
|
|
3109
|
+
|
|
3014
3110
|
//#endregion
|
|
3015
3111
|
//#region src/routes/messages/stream-translation.ts
|
|
3016
|
-
function isToolBlockOpen(state) {
|
|
3017
|
-
if (!state.contentBlockOpen) return false;
|
|
3018
|
-
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);
|
|
3019
3115
|
}
|
|
3020
|
-
function translateChunkToAnthropicEvents(chunk, state) {
|
|
3021
|
-
const events = [];
|
|
3022
|
-
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;
|
|
3023
3119
|
const choice = chunk.choices[0];
|
|
3024
3120
|
const { delta } = choice;
|
|
3025
|
-
if (!state.messageStartSent) {
|
|
3026
|
-
events.push({
|
|
3121
|
+
if (!state$1.messageStartSent) {
|
|
3122
|
+
events$1.push({
|
|
3027
3123
|
type: "message_start",
|
|
3028
3124
|
message: {
|
|
3029
3125
|
id: chunk.id,
|
|
@@ -3040,33 +3136,33 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3040
3136
|
}
|
|
3041
3137
|
}
|
|
3042
3138
|
});
|
|
3043
|
-
state.messageStartSent = true;
|
|
3139
|
+
state$1.messageStartSent = true;
|
|
3044
3140
|
}
|
|
3045
3141
|
const reasoningContent = delta.reasoning_content ?? delta.reasoning_text;
|
|
3046
3142
|
if (reasoningContent) {
|
|
3047
|
-
if (state.contentBlockOpen && !state.thinkingBlockOpen) {
|
|
3048
|
-
events.push({
|
|
3143
|
+
if (state$1.contentBlockOpen && !state$1.thinkingBlockOpen) {
|
|
3144
|
+
events$1.push({
|
|
3049
3145
|
type: "content_block_stop",
|
|
3050
|
-
index: state.contentBlockIndex
|
|
3146
|
+
index: state$1.contentBlockIndex
|
|
3051
3147
|
});
|
|
3052
|
-
state.contentBlockIndex++;
|
|
3053
|
-
state.contentBlockOpen = false;
|
|
3148
|
+
state$1.contentBlockIndex++;
|
|
3149
|
+
state$1.contentBlockOpen = false;
|
|
3054
3150
|
}
|
|
3055
|
-
if (!state.thinkingBlockOpen) {
|
|
3056
|
-
events.push({
|
|
3151
|
+
if (!state$1.thinkingBlockOpen) {
|
|
3152
|
+
events$1.push({
|
|
3057
3153
|
type: "content_block_start",
|
|
3058
|
-
index: state.contentBlockIndex,
|
|
3154
|
+
index: state$1.contentBlockIndex,
|
|
3059
3155
|
content_block: {
|
|
3060
3156
|
type: "thinking",
|
|
3061
3157
|
thinking: ""
|
|
3062
3158
|
}
|
|
3063
3159
|
});
|
|
3064
|
-
state.contentBlockOpen = true;
|
|
3065
|
-
state.thinkingBlockOpen = true;
|
|
3160
|
+
state$1.contentBlockOpen = true;
|
|
3161
|
+
state$1.thinkingBlockOpen = true;
|
|
3066
3162
|
}
|
|
3067
|
-
events.push({
|
|
3163
|
+
events$1.push({
|
|
3068
3164
|
type: "content_block_delta",
|
|
3069
|
-
index: state.contentBlockIndex,
|
|
3165
|
+
index: state$1.contentBlockIndex,
|
|
3070
3166
|
delta: {
|
|
3071
3167
|
type: "thinking_delta",
|
|
3072
3168
|
thinking: reasoningContent
|
|
@@ -3074,37 +3170,37 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3074
3170
|
});
|
|
3075
3171
|
}
|
|
3076
3172
|
if (delta.content) {
|
|
3077
|
-
if (state.thinkingBlockOpen) {
|
|
3078
|
-
events.push({
|
|
3173
|
+
if (state$1.thinkingBlockOpen) {
|
|
3174
|
+
events$1.push({
|
|
3079
3175
|
type: "content_block_stop",
|
|
3080
|
-
index: state.contentBlockIndex
|
|
3176
|
+
index: state$1.contentBlockIndex
|
|
3081
3177
|
});
|
|
3082
|
-
state.contentBlockIndex++;
|
|
3083
|
-
state.contentBlockOpen = false;
|
|
3084
|
-
state.thinkingBlockOpen = false;
|
|
3178
|
+
state$1.contentBlockIndex++;
|
|
3179
|
+
state$1.contentBlockOpen = false;
|
|
3180
|
+
state$1.thinkingBlockOpen = false;
|
|
3085
3181
|
}
|
|
3086
|
-
if (isToolBlockOpen(state)) {
|
|
3087
|
-
events.push({
|
|
3182
|
+
if (isToolBlockOpen(state$1)) {
|
|
3183
|
+
events$1.push({
|
|
3088
3184
|
type: "content_block_stop",
|
|
3089
|
-
index: state.contentBlockIndex
|
|
3185
|
+
index: state$1.contentBlockIndex
|
|
3090
3186
|
});
|
|
3091
|
-
state.contentBlockIndex++;
|
|
3092
|
-
state.contentBlockOpen = false;
|
|
3187
|
+
state$1.contentBlockIndex++;
|
|
3188
|
+
state$1.contentBlockOpen = false;
|
|
3093
3189
|
}
|
|
3094
|
-
if (!state.contentBlockOpen) {
|
|
3095
|
-
events.push({
|
|
3190
|
+
if (!state$1.contentBlockOpen) {
|
|
3191
|
+
events$1.push({
|
|
3096
3192
|
type: "content_block_start",
|
|
3097
|
-
index: state.contentBlockIndex,
|
|
3193
|
+
index: state$1.contentBlockIndex,
|
|
3098
3194
|
content_block: {
|
|
3099
3195
|
type: "text",
|
|
3100
3196
|
text: ""
|
|
3101
3197
|
}
|
|
3102
3198
|
});
|
|
3103
|
-
state.contentBlockOpen = true;
|
|
3199
|
+
state$1.contentBlockOpen = true;
|
|
3104
3200
|
}
|
|
3105
|
-
events.push({
|
|
3201
|
+
events$1.push({
|
|
3106
3202
|
type: "content_block_delta",
|
|
3107
|
-
index: state.contentBlockIndex,
|
|
3203
|
+
index: state$1.contentBlockIndex,
|
|
3108
3204
|
delta: {
|
|
3109
3205
|
type: "text_delta",
|
|
3110
3206
|
text: delta.content
|
|
@@ -3112,32 +3208,32 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3112
3208
|
});
|
|
3113
3209
|
}
|
|
3114
3210
|
if (delta.tool_calls) {
|
|
3115
|
-
if (state.thinkingBlockOpen) {
|
|
3116
|
-
events.push({
|
|
3211
|
+
if (state$1.thinkingBlockOpen) {
|
|
3212
|
+
events$1.push({
|
|
3117
3213
|
type: "content_block_stop",
|
|
3118
|
-
index: state.contentBlockIndex
|
|
3214
|
+
index: state$1.contentBlockIndex
|
|
3119
3215
|
});
|
|
3120
|
-
state.contentBlockIndex++;
|
|
3121
|
-
state.contentBlockOpen = false;
|
|
3122
|
-
state.thinkingBlockOpen = false;
|
|
3216
|
+
state$1.contentBlockIndex++;
|
|
3217
|
+
state$1.contentBlockOpen = false;
|
|
3218
|
+
state$1.thinkingBlockOpen = false;
|
|
3123
3219
|
}
|
|
3124
3220
|
for (const toolCall of delta.tool_calls) {
|
|
3125
3221
|
if (toolCall.id && toolCall.function?.name) {
|
|
3126
|
-
if (state.contentBlockOpen) {
|
|
3127
|
-
events.push({
|
|
3222
|
+
if (state$1.contentBlockOpen) {
|
|
3223
|
+
events$1.push({
|
|
3128
3224
|
type: "content_block_stop",
|
|
3129
|
-
index: state.contentBlockIndex
|
|
3225
|
+
index: state$1.contentBlockIndex
|
|
3130
3226
|
});
|
|
3131
|
-
state.contentBlockIndex++;
|
|
3132
|
-
state.contentBlockOpen = false;
|
|
3227
|
+
state$1.contentBlockIndex++;
|
|
3228
|
+
state$1.contentBlockOpen = false;
|
|
3133
3229
|
}
|
|
3134
|
-
const anthropicBlockIndex = state.contentBlockIndex;
|
|
3135
|
-
state.toolCalls[toolCall.index] = {
|
|
3230
|
+
const anthropicBlockIndex = state$1.contentBlockIndex;
|
|
3231
|
+
state$1.toolCalls[toolCall.index] = {
|
|
3136
3232
|
id: toolCall.id,
|
|
3137
3233
|
name: toolCall.function.name,
|
|
3138
3234
|
anthropicBlockIndex
|
|
3139
3235
|
};
|
|
3140
|
-
events.push({
|
|
3236
|
+
events$1.push({
|
|
3141
3237
|
type: "content_block_start",
|
|
3142
3238
|
index: anthropicBlockIndex,
|
|
3143
3239
|
content_block: {
|
|
@@ -3147,11 +3243,11 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3147
3243
|
input: {}
|
|
3148
3244
|
}
|
|
3149
3245
|
});
|
|
3150
|
-
state.contentBlockOpen = true;
|
|
3246
|
+
state$1.contentBlockOpen = true;
|
|
3151
3247
|
}
|
|
3152
3248
|
if (toolCall.function?.arguments) {
|
|
3153
|
-
const toolCallInfo = state.toolCalls[toolCall.index];
|
|
3154
|
-
if (toolCallInfo) events.push({
|
|
3249
|
+
const toolCallInfo = state$1.toolCalls[toolCall.index];
|
|
3250
|
+
if (toolCallInfo) events$1.push({
|
|
3155
3251
|
type: "content_block_delta",
|
|
3156
3252
|
index: toolCallInfo.anthropicBlockIndex,
|
|
3157
3253
|
delta: {
|
|
@@ -3163,14 +3259,14 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3163
3259
|
}
|
|
3164
3260
|
}
|
|
3165
3261
|
if (choice.finish_reason) {
|
|
3166
|
-
if (state.contentBlockOpen) {
|
|
3167
|
-
events.push({
|
|
3262
|
+
if (state$1.contentBlockOpen) {
|
|
3263
|
+
events$1.push({
|
|
3168
3264
|
type: "content_block_stop",
|
|
3169
|
-
index: state.contentBlockIndex
|
|
3265
|
+
index: state$1.contentBlockIndex
|
|
3170
3266
|
});
|
|
3171
|
-
state.contentBlockOpen = false;
|
|
3267
|
+
state$1.contentBlockOpen = false;
|
|
3172
3268
|
}
|
|
3173
|
-
events.push({
|
|
3269
|
+
events$1.push({
|
|
3174
3270
|
type: "message_delta",
|
|
3175
3271
|
delta: {
|
|
3176
3272
|
stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),
|
|
@@ -3183,7 +3279,7 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3183
3279
|
}
|
|
3184
3280
|
}, { type: "message_stop" });
|
|
3185
3281
|
}
|
|
3186
|
-
return events;
|
|
3282
|
+
return events$1;
|
|
3187
3283
|
}
|
|
3188
3284
|
function translateErrorToAnthropicErrorEvent() {
|
|
3189
3285
|
return {
|
|
@@ -3194,6 +3290,7 @@ function translateErrorToAnthropicErrorEvent() {
|
|
|
3194
3290
|
}
|
|
3195
3291
|
};
|
|
3196
3292
|
}
|
|
3293
|
+
|
|
3197
3294
|
//#endregion
|
|
3198
3295
|
//#region src/routes/messages/handler.ts
|
|
3199
3296
|
/** Heartbeat interval — keeps the downstream connection alive. */
|
|
@@ -3338,6 +3435,7 @@ async function handleCompletion(c) {
|
|
|
3338
3435
|
});
|
|
3339
3436
|
}
|
|
3340
3437
|
const isNonStreaming = (response) => Object.hasOwn(response, "choices");
|
|
3438
|
+
|
|
3341
3439
|
//#endregion
|
|
3342
3440
|
//#region src/routes/messages/route.ts
|
|
3343
3441
|
const messageRoutes = new Hono();
|
|
@@ -3355,6 +3453,7 @@ messageRoutes.post("/count_tokens", async (c) => {
|
|
|
3355
3453
|
return await forwardError(c, error);
|
|
3356
3454
|
}
|
|
3357
3455
|
});
|
|
3456
|
+
|
|
3358
3457
|
//#endregion
|
|
3359
3458
|
//#region src/routes/models/route.ts
|
|
3360
3459
|
const modelRoutes = new Hono();
|
|
@@ -3379,6 +3478,7 @@ modelRoutes.get("/", async (c) => {
|
|
|
3379
3478
|
return await forwardError(c, error);
|
|
3380
3479
|
}
|
|
3381
3480
|
});
|
|
3481
|
+
|
|
3382
3482
|
//#endregion
|
|
3383
3483
|
//#region src/routes/token/route.ts
|
|
3384
3484
|
const tokenRoute = new Hono();
|
|
@@ -3394,6 +3494,7 @@ tokenRoute.get("/", (c) => {
|
|
|
3394
3494
|
}, 500);
|
|
3395
3495
|
}
|
|
3396
3496
|
});
|
|
3497
|
+
|
|
3397
3498
|
//#endregion
|
|
3398
3499
|
//#region src/routes/usage/route.ts
|
|
3399
3500
|
const usageRoute = new Hono();
|
|
@@ -3402,8 +3503,8 @@ usageRoute.get("/", async (c) => {
|
|
|
3402
3503
|
if (state.multiAccountEnabled && accountManager.hasAccounts()) {
|
|
3403
3504
|
const account = accountManager.getActiveAccount();
|
|
3404
3505
|
if (account) {
|
|
3405
|
-
const usage = await getCopilotUsage(account.githubToken);
|
|
3406
|
-
return c.json(usage);
|
|
3506
|
+
const usage$1 = await getCopilotUsage(account.githubToken);
|
|
3507
|
+
return c.json(usage$1);
|
|
3407
3508
|
}
|
|
3408
3509
|
}
|
|
3409
3510
|
const usage = await getCopilotUsage();
|
|
@@ -3414,6 +3515,7 @@ usageRoute.get("/", async (c) => {
|
|
|
3414
3515
|
return c.json({ error: "Failed to fetch Copilot usage" }, 500);
|
|
3415
3516
|
}
|
|
3416
3517
|
});
|
|
3518
|
+
|
|
3417
3519
|
//#endregion
|
|
3418
3520
|
//#region src/server.ts
|
|
3419
3521
|
const server = new Hono();
|
|
@@ -3431,6 +3533,7 @@ server.route("/v1/models", modelRoutes);
|
|
|
3431
3533
|
server.route("/v1/embeddings", embeddingRoutes);
|
|
3432
3534
|
server.route("/v1/messages", messageRoutes);
|
|
3433
3535
|
server.route("/api", adminRoutes);
|
|
3536
|
+
|
|
3434
3537
|
//#endregion
|
|
3435
3538
|
//#region src/start.ts
|
|
3436
3539
|
/**
|
|
@@ -3527,7 +3630,7 @@ async function validateGitHubToken(token) {
|
|
|
3527
3630
|
state.githubToken = token;
|
|
3528
3631
|
consola.info("Using provided GitHub token");
|
|
3529
3632
|
try {
|
|
3530
|
-
const { getGitHubUser } = await import("./get-user-
|
|
3633
|
+
const { getGitHubUser } = await import("./get-user-DiK-7IaC.js");
|
|
3531
3634
|
const user = await getGitHubUser();
|
|
3532
3635
|
consola.info(`Logged in as ${user.login}`);
|
|
3533
3636
|
} catch (error) {
|
|
@@ -3551,26 +3654,26 @@ async function validateGitHubToken(token) {
|
|
|
3551
3654
|
* - proxyEnv: Initialize proxy settings from environment variables
|
|
3552
3655
|
* - apiKeys: Optional list of API keys to enable API key authentication
|
|
3553
3656
|
*/
|
|
3554
|
-
async function runServer(options) {
|
|
3657
|
+
async function runServer(options$1) {
|
|
3555
3658
|
const savedProxyApplied = await applyProxyConfig();
|
|
3556
|
-
if (options.proxyEnv) initProxyFromEnv();
|
|
3659
|
+
if (options$1.proxyEnv) initProxyFromEnv();
|
|
3557
3660
|
else if (savedProxyApplied) initProxyFromEnv();
|
|
3558
|
-
if (options.verbose) {
|
|
3661
|
+
if (options$1.verbose) {
|
|
3559
3662
|
consola.level = 5;
|
|
3560
3663
|
consola.info("Verbose logging enabled");
|
|
3561
3664
|
}
|
|
3562
|
-
state.accountType = options.accountType;
|
|
3563
|
-
if (options.accountType !== "individual") consola.info(`Using ${options.accountType} plan GitHub account`);
|
|
3564
|
-
state.manualApprove = options.manual;
|
|
3565
|
-
state.rateLimitSeconds = options.rateLimit;
|
|
3566
|
-
state.rateLimitWait = options.rateLimitWait;
|
|
3567
|
-
state.showToken = options.showToken;
|
|
3568
|
-
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;
|
|
3569
3672
|
if (state.apiKeys && state.apiKeys.length > 0) consola.info(`API key authentication enabled with ${state.apiKeys.length} key(s)`);
|
|
3570
3673
|
await ensurePaths();
|
|
3571
3674
|
await cacheVSCodeVersion();
|
|
3572
3675
|
try {
|
|
3573
|
-
await (options.githubToken ? validateGitHubToken(options.githubToken) : setupGitHubToken());
|
|
3676
|
+
await (options$1.githubToken ? validateGitHubToken(options$1.githubToken) : setupGitHubToken());
|
|
3574
3677
|
} catch (error) {
|
|
3575
3678
|
consola.error(`GitHub authentication failed: ${rootCause(error)}`);
|
|
3576
3679
|
consola.info("The server will start, but requests may fail until connectivity is restored");
|
|
@@ -3578,11 +3681,11 @@ async function runServer(options) {
|
|
|
3578
3681
|
try {
|
|
3579
3682
|
await setupCopilotToken();
|
|
3580
3683
|
} catch (error) {
|
|
3581
|
-
const { HTTPError } = await import("./error-
|
|
3582
|
-
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) {
|
|
3583
3686
|
consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
|
|
3584
|
-
const { clearGithubToken } = await import("./token-
|
|
3585
|
-
await clearGithubToken();
|
|
3687
|
+
const { clearGithubToken: clearGithubToken$1 } = await import("./token-C8PZ2fm8.js");
|
|
3688
|
+
await clearGithubToken$1();
|
|
3586
3689
|
consola.info("Please restart to re-authenticate");
|
|
3587
3690
|
}
|
|
3588
3691
|
throw error;
|
|
@@ -3591,111 +3694,113 @@ async function runServer(options) {
|
|
|
3591
3694
|
await initMultiAccount();
|
|
3592
3695
|
await initModelRouting();
|
|
3593
3696
|
consola.info(`Available models: \n${state.models?.data.map((model) => `- ${model.id}`).join("\n")}`);
|
|
3594
|
-
const serverUrl = `http://localhost:${options.port}`;
|
|
3595
|
-
if (options.claudeCode) await setupClaudeCodeEnv(serverUrl);
|
|
3697
|
+
const serverUrl = `http://localhost:${options$1.port}`;
|
|
3698
|
+
if (options$1.claudeCode) await setupClaudeCodeEnv(serverUrl);
|
|
3596
3699
|
const multiAccountInfo = state.multiAccountEnabled ? `\n👥 Multi-account: ${accountManager.activeAccountCount}/${accountManager.accountCount} active` : "";
|
|
3597
3700
|
consola.box(`🌐 Usage Viewer: https://imbuxiangnan-cyber.github.io/copilot-api-plus?endpoint=${serverUrl}/usage${multiAccountInfo}`);
|
|
3598
3701
|
serve({
|
|
3599
3702
|
fetch: server.fetch,
|
|
3600
|
-
port: options.port
|
|
3703
|
+
port: options$1.port
|
|
3601
3704
|
});
|
|
3602
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
|
+
|
|
3603
3794
|
//#endregion
|
|
3604
3795
|
//#region src/main.ts
|
|
3605
|
-
|
|
3796
|
+
const main = defineCommand({
|
|
3606
3797
|
meta: {
|
|
3607
3798
|
name: "copilot-api-plus",
|
|
3608
3799
|
description: "A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements."
|
|
3609
3800
|
},
|
|
3610
3801
|
subCommands: {
|
|
3611
3802
|
auth,
|
|
3612
|
-
start
|
|
3613
|
-
meta: {
|
|
3614
|
-
name: "start",
|
|
3615
|
-
description: "Start the Copilot API server"
|
|
3616
|
-
},
|
|
3617
|
-
args: {
|
|
3618
|
-
port: {
|
|
3619
|
-
alias: "p",
|
|
3620
|
-
type: "string",
|
|
3621
|
-
default: "4141",
|
|
3622
|
-
description: "Port to listen on"
|
|
3623
|
-
},
|
|
3624
|
-
verbose: {
|
|
3625
|
-
alias: "v",
|
|
3626
|
-
type: "boolean",
|
|
3627
|
-
default: false,
|
|
3628
|
-
description: "Enable verbose logging"
|
|
3629
|
-
},
|
|
3630
|
-
"account-type": {
|
|
3631
|
-
alias: "a",
|
|
3632
|
-
type: "string",
|
|
3633
|
-
default: "individual",
|
|
3634
|
-
description: "Account type to use (individual, business, enterprise)"
|
|
3635
|
-
},
|
|
3636
|
-
manual: {
|
|
3637
|
-
type: "boolean",
|
|
3638
|
-
default: false,
|
|
3639
|
-
description: "Enable manual request approval"
|
|
3640
|
-
},
|
|
3641
|
-
"rate-limit": {
|
|
3642
|
-
alias: "r",
|
|
3643
|
-
type: "string",
|
|
3644
|
-
description: "Rate limit in seconds between requests"
|
|
3645
|
-
},
|
|
3646
|
-
wait: {
|
|
3647
|
-
alias: "w",
|
|
3648
|
-
type: "boolean",
|
|
3649
|
-
default: false,
|
|
3650
|
-
description: "Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"
|
|
3651
|
-
},
|
|
3652
|
-
"github-token": {
|
|
3653
|
-
alias: "g",
|
|
3654
|
-
type: "string",
|
|
3655
|
-
description: "Provide GitHub token directly (must be generated using the `auth` subcommand)"
|
|
3656
|
-
},
|
|
3657
|
-
"claude-code": {
|
|
3658
|
-
alias: "c",
|
|
3659
|
-
type: "boolean",
|
|
3660
|
-
default: false,
|
|
3661
|
-
description: "Generate a command to launch Claude Code with Copilot API config"
|
|
3662
|
-
},
|
|
3663
|
-
"show-token": {
|
|
3664
|
-
type: "boolean",
|
|
3665
|
-
default: false,
|
|
3666
|
-
description: "Show GitHub and Copilot tokens on fetch and refresh"
|
|
3667
|
-
},
|
|
3668
|
-
"proxy-env": {
|
|
3669
|
-
type: "boolean",
|
|
3670
|
-
default: false,
|
|
3671
|
-
description: "Initialize proxy from environment variables"
|
|
3672
|
-
},
|
|
3673
|
-
"api-key": {
|
|
3674
|
-
type: "string",
|
|
3675
|
-
description: "API keys for authentication"
|
|
3676
|
-
}
|
|
3677
|
-
},
|
|
3678
|
-
run({ args }) {
|
|
3679
|
-
const rateLimitRaw = args["rate-limit"];
|
|
3680
|
-
const rateLimit = rateLimitRaw === void 0 ? void 0 : Number.parseInt(rateLimitRaw, 10);
|
|
3681
|
-
const apiKeyRaw = args["api-key"];
|
|
3682
|
-
let apiKeys;
|
|
3683
|
-
if (apiKeyRaw) apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw];
|
|
3684
|
-
return runServer({
|
|
3685
|
-
port: Number.parseInt(args.port, 10),
|
|
3686
|
-
verbose: args.verbose,
|
|
3687
|
-
accountType: args["account-type"],
|
|
3688
|
-
manual: args.manual,
|
|
3689
|
-
rateLimit,
|
|
3690
|
-
rateLimitWait: args.wait,
|
|
3691
|
-
githubToken: args["github-token"],
|
|
3692
|
-
claudeCode: args["claude-code"],
|
|
3693
|
-
showToken: args["show-token"],
|
|
3694
|
-
proxyEnv: args["proxy-env"],
|
|
3695
|
-
apiKeys
|
|
3696
|
-
});
|
|
3697
|
-
}
|
|
3698
|
-
}),
|
|
3803
|
+
start,
|
|
3699
3804
|
"check-usage": checkUsage,
|
|
3700
3805
|
"add-account": addAccount,
|
|
3701
3806
|
"list-accounts": listAccounts,
|
|
@@ -3704,8 +3809,9 @@ await runMain(defineCommand({
|
|
|
3704
3809
|
logout,
|
|
3705
3810
|
proxy
|
|
3706
3811
|
}
|
|
3707
|
-
})
|
|
3708
|
-
|
|
3709
|
-
export {};
|
|
3812
|
+
});
|
|
3813
|
+
await runMain(main);
|
|
3710
3814
|
|
|
3815
|
+
//#endregion
|
|
3816
|
+
export { };
|
|
3711
3817
|
//# sourceMappingURL=main.js.map
|