copilot-api-plus 1.2.52 → 1.2.54
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 +422 -319
- 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
|
|
@@ -1986,6 +2025,13 @@ const reasoningUnsupportedModels = /* @__PURE__ */ new Set();
|
|
|
1986
2025
|
*/
|
|
1987
2026
|
const reasoningEffortCap = /* @__PURE__ */ new Map();
|
|
1988
2027
|
/**
|
|
2028
|
+
* Models that reject `reasoning_effort` when function tools are present.
|
|
2029
|
+
* e.g. gpt-5.4 returns "Function tools with reasoning_effort are not
|
|
2030
|
+
* supported ... Please use /v1/responses instead."
|
|
2031
|
+
* Populated at runtime on first 400.
|
|
2032
|
+
*/
|
|
2033
|
+
const reasoningWithToolsUnsupported = /* @__PURE__ */ new Set();
|
|
2034
|
+
/**
|
|
1989
2035
|
* Compute an appropriate thinking_budget from model capabilities.
|
|
1990
2036
|
* Returns undefined if the model does not support thinking.
|
|
1991
2037
|
*/
|
|
@@ -2023,12 +2069,13 @@ function isToolChoiceForced(toolChoice) {
|
|
|
2023
2069
|
* /models endpoint doesn't expose thinking budget fields.
|
|
2024
2070
|
*/
|
|
2025
2071
|
function injectThinking(payload, resolvedModel) {
|
|
2026
|
-
|
|
2072
|
+
const hasTools = payload.tools && payload.tools.length > 0;
|
|
2073
|
+
if (isToolChoiceForced(payload.tool_choice) || hasTools && reasoningWithToolsUnsupported.has(resolvedModel)) {
|
|
2027
2074
|
if (payload.reasoning_effort || payload.thinking_budget) {
|
|
2028
2075
|
const stripped = { ...payload };
|
|
2029
2076
|
delete stripped.reasoning_effort;
|
|
2030
2077
|
delete stripped.thinking_budget;
|
|
2031
|
-
consola.debug(`Thinking: stripped reasoning params for "${resolvedModel}"
|
|
2078
|
+
consola.debug(`Thinking: stripped reasoning params for "${resolvedModel}" (tool conflict)`);
|
|
2032
2079
|
return stripped;
|
|
2033
2080
|
}
|
|
2034
2081
|
return payload;
|
|
@@ -2043,7 +2090,8 @@ function injectThinking(payload, resolvedModel) {
|
|
|
2043
2090
|
}
|
|
2044
2091
|
return payload;
|
|
2045
2092
|
}
|
|
2046
|
-
const
|
|
2093
|
+
const model = findModel(resolvedModel);
|
|
2094
|
+
const budget = getThinkingBudget(model);
|
|
2047
2095
|
if (budget) return {
|
|
2048
2096
|
...payload,
|
|
2049
2097
|
thinking_budget: budget
|
|
@@ -2083,6 +2131,11 @@ const createChatCompletions = async (payload) => {
|
|
|
2083
2131
|
releaseSlot();
|
|
2084
2132
|
return result;
|
|
2085
2133
|
} catch (error) {
|
|
2134
|
+
const maxTokensRetry = handle400MaxTokensError(error, {
|
|
2135
|
+
resolvedModel,
|
|
2136
|
+
routedPayload: thinkingPayload
|
|
2137
|
+
}, releaseSlot);
|
|
2138
|
+
if (maxTokensRetry !== void 0) return maxTokensRetry;
|
|
2086
2139
|
const retryResult = handle400ReasoningError(error, {
|
|
2087
2140
|
resolvedModel,
|
|
2088
2141
|
thinkingPayload,
|
|
@@ -2095,6 +2148,25 @@ const createChatCompletions = async (payload) => {
|
|
|
2095
2148
|
}
|
|
2096
2149
|
};
|
|
2097
2150
|
/**
|
|
2151
|
+
* Handle 400 errors caused by `max_tokens` being rejected — o-series and
|
|
2152
|
+
* GPT-5.x require `max_completion_tokens` instead. Learns at runtime:
|
|
2153
|
+
* adds the model to `maxCompletionTokensModels` and retries once with the
|
|
2154
|
+
* field renamed so all future requests skip the 400 entirely.
|
|
2155
|
+
*/
|
|
2156
|
+
function handle400MaxTokensError(error, ctx, releaseSlot) {
|
|
2157
|
+
if (!(error instanceof HTTPError) || error.response.status !== 400) return void 0;
|
|
2158
|
+
const errMsg = error.message;
|
|
2159
|
+
if (!errMsg.includes("max_tokens") || !errMsg.includes("max_completion_tokens")) return void 0;
|
|
2160
|
+
maxCompletionTokensModels.add(ctx.resolvedModel);
|
|
2161
|
+
consola.debug(`Model "${ctx.resolvedModel}" requires max_completion_tokens — switching for future requests`);
|
|
2162
|
+
if (ctx.routedPayload.max_tokens === null || ctx.routedPayload.max_tokens === void 0) return retryWithModifiedPayload(ctx.routedPayload, releaseSlot);
|
|
2163
|
+
const { max_tokens,...rest } = ctx.routedPayload;
|
|
2164
|
+
return retryWithModifiedPayload({
|
|
2165
|
+
...rest,
|
|
2166
|
+
max_completion_tokens: max_tokens
|
|
2167
|
+
}, releaseSlot);
|
|
2168
|
+
}
|
|
2169
|
+
/**
|
|
2098
2170
|
* Handle 400 reasoning_effort errors in the outer createChatCompletions catch.
|
|
2099
2171
|
* Returns a Promise (retry result) if handled, or undefined to re-throw.
|
|
2100
2172
|
*/
|
|
@@ -2117,6 +2189,14 @@ function handle400ReasoningError(error, ctx, releaseSlot) {
|
|
|
2117
2189
|
consola.debug(`Model "${ctx.resolvedModel}" does not support reasoning_effort — disabled for future requests`);
|
|
2118
2190
|
return retryWithModifiedPayload(ctx.routedPayload, releaseSlot);
|
|
2119
2191
|
}
|
|
2192
|
+
if (errMsg.includes("Function tools") && errMsg.includes("reasoning_effort")) {
|
|
2193
|
+
reasoningWithToolsUnsupported.add(ctx.resolvedModel);
|
|
2194
|
+
consola.debug(`Model "${ctx.resolvedModel}" does not support tools + reasoning_effort — stripped for future requests`);
|
|
2195
|
+
const stripped = { ...ctx.routedPayload };
|
|
2196
|
+
delete stripped.reasoning_effort;
|
|
2197
|
+
delete stripped.thinking_budget;
|
|
2198
|
+
return retryWithModifiedPayload(stripped, releaseSlot);
|
|
2199
|
+
}
|
|
2120
2200
|
}
|
|
2121
2201
|
/**
|
|
2122
2202
|
* Retry a request after modifying the payload (e.g. stripping or
|
|
@@ -2159,9 +2239,9 @@ async function createWithSingleAccount(payload) {
|
|
|
2159
2239
|
});
|
|
2160
2240
|
const url = `${copilotBaseUrl(state)}/chat/completions`;
|
|
2161
2241
|
const body = payload.stream ? {
|
|
2162
|
-
...payload,
|
|
2242
|
+
...normalizeMaxTokens(payload),
|
|
2163
2243
|
stream_options: { include_usage: true }
|
|
2164
|
-
} : payload;
|
|
2244
|
+
} : normalizeMaxTokens(payload);
|
|
2165
2245
|
const bodyString = JSON.stringify(body);
|
|
2166
2246
|
let response = await fetchWithRetry(url, () => ({
|
|
2167
2247
|
method: "POST",
|
|
@@ -2187,7 +2267,8 @@ async function createWithSingleAccount(payload) {
|
|
|
2187
2267
|
if (response.status === 400) {
|
|
2188
2268
|
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2189
2269
|
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2190
|
-
|
|
2270
|
+
const isMaxTokensError = errorBody.includes("max_tokens") && errorBody.includes("max_completion_tokens");
|
|
2271
|
+
if (isExpectedReasoningError || isModelNotSupported || isMaxTokensError) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2191
2272
|
else consola.warn(`400: ${errorBody}`);
|
|
2192
2273
|
} else consola.error("Failed to create chat completions", {
|
|
2193
2274
|
status: response.status,
|
|
@@ -2415,9 +2496,9 @@ async function doFetch(payload, source, accountId) {
|
|
|
2415
2496
|
endpoint: url
|
|
2416
2497
|
});
|
|
2417
2498
|
const body = payload.stream ? {
|
|
2418
|
-
...payload,
|
|
2499
|
+
...normalizeMaxTokens(payload),
|
|
2419
2500
|
stream_options: { include_usage: true }
|
|
2420
|
-
} : payload;
|
|
2501
|
+
} : normalizeMaxTokens(payload);
|
|
2421
2502
|
const bodyString = JSON.stringify(body);
|
|
2422
2503
|
const response = await fetchWithRetry(url, () => ({
|
|
2423
2504
|
method: "POST",
|
|
@@ -2432,7 +2513,8 @@ async function doFetch(payload, source, accountId) {
|
|
|
2432
2513
|
if (response.status === 400) {
|
|
2433
2514
|
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2434
2515
|
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2435
|
-
|
|
2516
|
+
const isMaxTokensError = errorBody.includes("max_tokens") && errorBody.includes("max_completion_tokens");
|
|
2517
|
+
if (isExpectedReasoningError || isModelNotSupported || isMaxTokensError) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2436
2518
|
else consola.warn(`400: ${errorBody}`);
|
|
2437
2519
|
} else consola.error("Failed to create chat completions", {
|
|
2438
2520
|
status: response.status,
|
|
@@ -2444,6 +2526,7 @@ async function doFetch(payload, source, accountId) {
|
|
|
2444
2526
|
if (payload.stream) return events(response);
|
|
2445
2527
|
return await response.json();
|
|
2446
2528
|
}
|
|
2529
|
+
|
|
2447
2530
|
//#endregion
|
|
2448
2531
|
//#region src/routes/chat-completions/handler.ts
|
|
2449
2532
|
/**
|
|
@@ -2511,6 +2594,7 @@ function mapReasoningFields(response) {
|
|
|
2511
2594
|
})
|
|
2512
2595
|
};
|
|
2513
2596
|
}
|
|
2597
|
+
|
|
2514
2598
|
//#endregion
|
|
2515
2599
|
//#region src/routes/chat-completions/route.ts
|
|
2516
2600
|
const completionRoutes = new Hono();
|
|
@@ -2521,6 +2605,7 @@ completionRoutes.post("/", async (c) => {
|
|
|
2521
2605
|
return await forwardError(c, error);
|
|
2522
2606
|
}
|
|
2523
2607
|
});
|
|
2608
|
+
|
|
2524
2609
|
//#endregion
|
|
2525
2610
|
//#region src/services/copilot/create-embeddings.ts
|
|
2526
2611
|
const createEmbeddings = async (payload) => {
|
|
@@ -2544,17 +2629,20 @@ const createEmbeddings = async (payload) => {
|
|
|
2544
2629
|
if (!response.ok) throw new HTTPError("Failed to create embeddings", response);
|
|
2545
2630
|
return await response.json();
|
|
2546
2631
|
};
|
|
2632
|
+
|
|
2547
2633
|
//#endregion
|
|
2548
2634
|
//#region src/routes/embeddings/route.ts
|
|
2549
2635
|
const embeddingRoutes = new Hono();
|
|
2550
2636
|
embeddingRoutes.post("/", async (c) => {
|
|
2551
2637
|
try {
|
|
2552
|
-
const
|
|
2638
|
+
const paylod = await c.req.json();
|
|
2639
|
+
const response = await createEmbeddings(paylod);
|
|
2553
2640
|
return c.json(response);
|
|
2554
2641
|
} catch (error) {
|
|
2555
2642
|
return await forwardError(c, error);
|
|
2556
2643
|
}
|
|
2557
2644
|
});
|
|
2645
|
+
|
|
2558
2646
|
//#endregion
|
|
2559
2647
|
//#region src/lib/tokenizer.ts
|
|
2560
2648
|
const ENCODING_MAP = {
|
|
@@ -2737,7 +2825,8 @@ const numTokensForTools = (tools, encoder, constants) => {
|
|
|
2737
2825
|
* Calculate the token count of messages, supporting multiple GPT encoders
|
|
2738
2826
|
*/
|
|
2739
2827
|
const getTokenCount = async (payload, model) => {
|
|
2740
|
-
const
|
|
2828
|
+
const tokenizer = getTokenizerFromModel(model);
|
|
2829
|
+
const encoder = await getEncodeChatFunction(tokenizer);
|
|
2741
2830
|
const constants = getModelConstants(model);
|
|
2742
2831
|
let inputTokens = calculateTokens(payload.messages, encoder, constants);
|
|
2743
2832
|
if (payload.tools && payload.tools.length > 0) inputTokens += numTokensForTools(payload.tools, encoder, constants);
|
|
@@ -2746,6 +2835,7 @@ const getTokenCount = async (payload, model) => {
|
|
|
2746
2835
|
output: 0
|
|
2747
2836
|
};
|
|
2748
2837
|
};
|
|
2838
|
+
|
|
2749
2839
|
//#endregion
|
|
2750
2840
|
//#region src/routes/messages/utils.ts
|
|
2751
2841
|
function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
@@ -2757,6 +2847,7 @@ function mapOpenAIStopReasonToAnthropic(finishReason) {
|
|
|
2757
2847
|
content_filter: "end_turn"
|
|
2758
2848
|
}[finishReason];
|
|
2759
2849
|
}
|
|
2850
|
+
|
|
2760
2851
|
//#endregion
|
|
2761
2852
|
//#region src/routes/messages/non-stream-translation.ts
|
|
2762
2853
|
function translateToOpenAI(payload) {
|
|
@@ -2990,6 +3081,7 @@ function getAnthropicToolUseBlocks(toolCalls) {
|
|
|
2990
3081
|
})()
|
|
2991
3082
|
}));
|
|
2992
3083
|
}
|
|
3084
|
+
|
|
2993
3085
|
//#endregion
|
|
2994
3086
|
//#region src/routes/messages/count-tokens-handler.ts
|
|
2995
3087
|
/**
|
|
@@ -3030,19 +3122,20 @@ async function handleCountTokens(c) {
|
|
|
3030
3122
|
return c.json({ input_tokens: 1 });
|
|
3031
3123
|
}
|
|
3032
3124
|
}
|
|
3125
|
+
|
|
3033
3126
|
//#endregion
|
|
3034
3127
|
//#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);
|
|
3128
|
+
function isToolBlockOpen(state$1) {
|
|
3129
|
+
if (!state$1.contentBlockOpen) return false;
|
|
3130
|
+
return Object.values(state$1.toolCalls).some((tc) => tc.anthropicBlockIndex === state$1.contentBlockIndex);
|
|
3038
3131
|
}
|
|
3039
|
-
function translateChunkToAnthropicEvents(chunk, state) {
|
|
3040
|
-
const events = [];
|
|
3041
|
-
if (chunk.choices.length === 0) return events;
|
|
3132
|
+
function translateChunkToAnthropicEvents(chunk, state$1) {
|
|
3133
|
+
const events$1 = [];
|
|
3134
|
+
if (chunk.choices.length === 0) return events$1;
|
|
3042
3135
|
const choice = chunk.choices[0];
|
|
3043
3136
|
const { delta } = choice;
|
|
3044
|
-
if (!state.messageStartSent) {
|
|
3045
|
-
events.push({
|
|
3137
|
+
if (!state$1.messageStartSent) {
|
|
3138
|
+
events$1.push({
|
|
3046
3139
|
type: "message_start",
|
|
3047
3140
|
message: {
|
|
3048
3141
|
id: chunk.id,
|
|
@@ -3059,33 +3152,33 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3059
3152
|
}
|
|
3060
3153
|
}
|
|
3061
3154
|
});
|
|
3062
|
-
state.messageStartSent = true;
|
|
3155
|
+
state$1.messageStartSent = true;
|
|
3063
3156
|
}
|
|
3064
3157
|
const reasoningContent = delta.reasoning_content ?? delta.reasoning_text;
|
|
3065
3158
|
if (reasoningContent) {
|
|
3066
|
-
if (state.contentBlockOpen && !state.thinkingBlockOpen) {
|
|
3067
|
-
events.push({
|
|
3159
|
+
if (state$1.contentBlockOpen && !state$1.thinkingBlockOpen) {
|
|
3160
|
+
events$1.push({
|
|
3068
3161
|
type: "content_block_stop",
|
|
3069
|
-
index: state.contentBlockIndex
|
|
3162
|
+
index: state$1.contentBlockIndex
|
|
3070
3163
|
});
|
|
3071
|
-
state.contentBlockIndex++;
|
|
3072
|
-
state.contentBlockOpen = false;
|
|
3164
|
+
state$1.contentBlockIndex++;
|
|
3165
|
+
state$1.contentBlockOpen = false;
|
|
3073
3166
|
}
|
|
3074
|
-
if (!state.thinkingBlockOpen) {
|
|
3075
|
-
events.push({
|
|
3167
|
+
if (!state$1.thinkingBlockOpen) {
|
|
3168
|
+
events$1.push({
|
|
3076
3169
|
type: "content_block_start",
|
|
3077
|
-
index: state.contentBlockIndex,
|
|
3170
|
+
index: state$1.contentBlockIndex,
|
|
3078
3171
|
content_block: {
|
|
3079
3172
|
type: "thinking",
|
|
3080
3173
|
thinking: ""
|
|
3081
3174
|
}
|
|
3082
3175
|
});
|
|
3083
|
-
state.contentBlockOpen = true;
|
|
3084
|
-
state.thinkingBlockOpen = true;
|
|
3176
|
+
state$1.contentBlockOpen = true;
|
|
3177
|
+
state$1.thinkingBlockOpen = true;
|
|
3085
3178
|
}
|
|
3086
|
-
events.push({
|
|
3179
|
+
events$1.push({
|
|
3087
3180
|
type: "content_block_delta",
|
|
3088
|
-
index: state.contentBlockIndex,
|
|
3181
|
+
index: state$1.contentBlockIndex,
|
|
3089
3182
|
delta: {
|
|
3090
3183
|
type: "thinking_delta",
|
|
3091
3184
|
thinking: reasoningContent
|
|
@@ -3093,37 +3186,37 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3093
3186
|
});
|
|
3094
3187
|
}
|
|
3095
3188
|
if (delta.content) {
|
|
3096
|
-
if (state.thinkingBlockOpen) {
|
|
3097
|
-
events.push({
|
|
3189
|
+
if (state$1.thinkingBlockOpen) {
|
|
3190
|
+
events$1.push({
|
|
3098
3191
|
type: "content_block_stop",
|
|
3099
|
-
index: state.contentBlockIndex
|
|
3192
|
+
index: state$1.contentBlockIndex
|
|
3100
3193
|
});
|
|
3101
|
-
state.contentBlockIndex++;
|
|
3102
|
-
state.contentBlockOpen = false;
|
|
3103
|
-
state.thinkingBlockOpen = false;
|
|
3194
|
+
state$1.contentBlockIndex++;
|
|
3195
|
+
state$1.contentBlockOpen = false;
|
|
3196
|
+
state$1.thinkingBlockOpen = false;
|
|
3104
3197
|
}
|
|
3105
|
-
if (isToolBlockOpen(state)) {
|
|
3106
|
-
events.push({
|
|
3198
|
+
if (isToolBlockOpen(state$1)) {
|
|
3199
|
+
events$1.push({
|
|
3107
3200
|
type: "content_block_stop",
|
|
3108
|
-
index: state.contentBlockIndex
|
|
3201
|
+
index: state$1.contentBlockIndex
|
|
3109
3202
|
});
|
|
3110
|
-
state.contentBlockIndex++;
|
|
3111
|
-
state.contentBlockOpen = false;
|
|
3203
|
+
state$1.contentBlockIndex++;
|
|
3204
|
+
state$1.contentBlockOpen = false;
|
|
3112
3205
|
}
|
|
3113
|
-
if (!state.contentBlockOpen) {
|
|
3114
|
-
events.push({
|
|
3206
|
+
if (!state$1.contentBlockOpen) {
|
|
3207
|
+
events$1.push({
|
|
3115
3208
|
type: "content_block_start",
|
|
3116
|
-
index: state.contentBlockIndex,
|
|
3209
|
+
index: state$1.contentBlockIndex,
|
|
3117
3210
|
content_block: {
|
|
3118
3211
|
type: "text",
|
|
3119
3212
|
text: ""
|
|
3120
3213
|
}
|
|
3121
3214
|
});
|
|
3122
|
-
state.contentBlockOpen = true;
|
|
3215
|
+
state$1.contentBlockOpen = true;
|
|
3123
3216
|
}
|
|
3124
|
-
events.push({
|
|
3217
|
+
events$1.push({
|
|
3125
3218
|
type: "content_block_delta",
|
|
3126
|
-
index: state.contentBlockIndex,
|
|
3219
|
+
index: state$1.contentBlockIndex,
|
|
3127
3220
|
delta: {
|
|
3128
3221
|
type: "text_delta",
|
|
3129
3222
|
text: delta.content
|
|
@@ -3131,32 +3224,32 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3131
3224
|
});
|
|
3132
3225
|
}
|
|
3133
3226
|
if (delta.tool_calls) {
|
|
3134
|
-
if (state.thinkingBlockOpen) {
|
|
3135
|
-
events.push({
|
|
3227
|
+
if (state$1.thinkingBlockOpen) {
|
|
3228
|
+
events$1.push({
|
|
3136
3229
|
type: "content_block_stop",
|
|
3137
|
-
index: state.contentBlockIndex
|
|
3230
|
+
index: state$1.contentBlockIndex
|
|
3138
3231
|
});
|
|
3139
|
-
state.contentBlockIndex++;
|
|
3140
|
-
state.contentBlockOpen = false;
|
|
3141
|
-
state.thinkingBlockOpen = false;
|
|
3232
|
+
state$1.contentBlockIndex++;
|
|
3233
|
+
state$1.contentBlockOpen = false;
|
|
3234
|
+
state$1.thinkingBlockOpen = false;
|
|
3142
3235
|
}
|
|
3143
3236
|
for (const toolCall of delta.tool_calls) {
|
|
3144
3237
|
if (toolCall.id && toolCall.function?.name) {
|
|
3145
|
-
if (state.contentBlockOpen) {
|
|
3146
|
-
events.push({
|
|
3238
|
+
if (state$1.contentBlockOpen) {
|
|
3239
|
+
events$1.push({
|
|
3147
3240
|
type: "content_block_stop",
|
|
3148
|
-
index: state.contentBlockIndex
|
|
3241
|
+
index: state$1.contentBlockIndex
|
|
3149
3242
|
});
|
|
3150
|
-
state.contentBlockIndex++;
|
|
3151
|
-
state.contentBlockOpen = false;
|
|
3243
|
+
state$1.contentBlockIndex++;
|
|
3244
|
+
state$1.contentBlockOpen = false;
|
|
3152
3245
|
}
|
|
3153
|
-
const anthropicBlockIndex = state.contentBlockIndex;
|
|
3154
|
-
state.toolCalls[toolCall.index] = {
|
|
3246
|
+
const anthropicBlockIndex = state$1.contentBlockIndex;
|
|
3247
|
+
state$1.toolCalls[toolCall.index] = {
|
|
3155
3248
|
id: toolCall.id,
|
|
3156
3249
|
name: toolCall.function.name,
|
|
3157
3250
|
anthropicBlockIndex
|
|
3158
3251
|
};
|
|
3159
|
-
events.push({
|
|
3252
|
+
events$1.push({
|
|
3160
3253
|
type: "content_block_start",
|
|
3161
3254
|
index: anthropicBlockIndex,
|
|
3162
3255
|
content_block: {
|
|
@@ -3166,11 +3259,11 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3166
3259
|
input: {}
|
|
3167
3260
|
}
|
|
3168
3261
|
});
|
|
3169
|
-
state.contentBlockOpen = true;
|
|
3262
|
+
state$1.contentBlockOpen = true;
|
|
3170
3263
|
}
|
|
3171
3264
|
if (toolCall.function?.arguments) {
|
|
3172
|
-
const toolCallInfo = state.toolCalls[toolCall.index];
|
|
3173
|
-
if (toolCallInfo) events.push({
|
|
3265
|
+
const toolCallInfo = state$1.toolCalls[toolCall.index];
|
|
3266
|
+
if (toolCallInfo) events$1.push({
|
|
3174
3267
|
type: "content_block_delta",
|
|
3175
3268
|
index: toolCallInfo.anthropicBlockIndex,
|
|
3176
3269
|
delta: {
|
|
@@ -3182,14 +3275,14 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3182
3275
|
}
|
|
3183
3276
|
}
|
|
3184
3277
|
if (choice.finish_reason) {
|
|
3185
|
-
if (state.contentBlockOpen) {
|
|
3186
|
-
events.push({
|
|
3278
|
+
if (state$1.contentBlockOpen) {
|
|
3279
|
+
events$1.push({
|
|
3187
3280
|
type: "content_block_stop",
|
|
3188
|
-
index: state.contentBlockIndex
|
|
3281
|
+
index: state$1.contentBlockIndex
|
|
3189
3282
|
});
|
|
3190
|
-
state.contentBlockOpen = false;
|
|
3283
|
+
state$1.contentBlockOpen = false;
|
|
3191
3284
|
}
|
|
3192
|
-
events.push({
|
|
3285
|
+
events$1.push({
|
|
3193
3286
|
type: "message_delta",
|
|
3194
3287
|
delta: {
|
|
3195
3288
|
stop_reason: mapOpenAIStopReasonToAnthropic(choice.finish_reason),
|
|
@@ -3202,7 +3295,7 @@ function translateChunkToAnthropicEvents(chunk, state) {
|
|
|
3202
3295
|
}
|
|
3203
3296
|
}, { type: "message_stop" });
|
|
3204
3297
|
}
|
|
3205
|
-
return events;
|
|
3298
|
+
return events$1;
|
|
3206
3299
|
}
|
|
3207
3300
|
function translateErrorToAnthropicErrorEvent() {
|
|
3208
3301
|
return {
|
|
@@ -3213,6 +3306,7 @@ function translateErrorToAnthropicErrorEvent() {
|
|
|
3213
3306
|
}
|
|
3214
3307
|
};
|
|
3215
3308
|
}
|
|
3309
|
+
|
|
3216
3310
|
//#endregion
|
|
3217
3311
|
//#region src/routes/messages/handler.ts
|
|
3218
3312
|
/** Heartbeat interval — keeps the downstream connection alive. */
|
|
@@ -3357,6 +3451,7 @@ async function handleCompletion(c) {
|
|
|
3357
3451
|
});
|
|
3358
3452
|
}
|
|
3359
3453
|
const isNonStreaming = (response) => Object.hasOwn(response, "choices");
|
|
3454
|
+
|
|
3360
3455
|
//#endregion
|
|
3361
3456
|
//#region src/routes/messages/route.ts
|
|
3362
3457
|
const messageRoutes = new Hono();
|
|
@@ -3374,6 +3469,7 @@ messageRoutes.post("/count_tokens", async (c) => {
|
|
|
3374
3469
|
return await forwardError(c, error);
|
|
3375
3470
|
}
|
|
3376
3471
|
});
|
|
3472
|
+
|
|
3377
3473
|
//#endregion
|
|
3378
3474
|
//#region src/routes/models/route.ts
|
|
3379
3475
|
const modelRoutes = new Hono();
|
|
@@ -3398,6 +3494,7 @@ modelRoutes.get("/", async (c) => {
|
|
|
3398
3494
|
return await forwardError(c, error);
|
|
3399
3495
|
}
|
|
3400
3496
|
});
|
|
3497
|
+
|
|
3401
3498
|
//#endregion
|
|
3402
3499
|
//#region src/routes/token/route.ts
|
|
3403
3500
|
const tokenRoute = new Hono();
|
|
@@ -3413,6 +3510,7 @@ tokenRoute.get("/", (c) => {
|
|
|
3413
3510
|
}, 500);
|
|
3414
3511
|
}
|
|
3415
3512
|
});
|
|
3513
|
+
|
|
3416
3514
|
//#endregion
|
|
3417
3515
|
//#region src/routes/usage/route.ts
|
|
3418
3516
|
const usageRoute = new Hono();
|
|
@@ -3421,8 +3519,8 @@ usageRoute.get("/", async (c) => {
|
|
|
3421
3519
|
if (state.multiAccountEnabled && accountManager.hasAccounts()) {
|
|
3422
3520
|
const account = accountManager.getActiveAccount();
|
|
3423
3521
|
if (account) {
|
|
3424
|
-
const usage = await getCopilotUsage(account.githubToken);
|
|
3425
|
-
return c.json(usage);
|
|
3522
|
+
const usage$1 = await getCopilotUsage(account.githubToken);
|
|
3523
|
+
return c.json(usage$1);
|
|
3426
3524
|
}
|
|
3427
3525
|
}
|
|
3428
3526
|
const usage = await getCopilotUsage();
|
|
@@ -3433,6 +3531,7 @@ usageRoute.get("/", async (c) => {
|
|
|
3433
3531
|
return c.json({ error: "Failed to fetch Copilot usage" }, 500);
|
|
3434
3532
|
}
|
|
3435
3533
|
});
|
|
3534
|
+
|
|
3436
3535
|
//#endregion
|
|
3437
3536
|
//#region src/server.ts
|
|
3438
3537
|
const server = new Hono();
|
|
@@ -3450,6 +3549,7 @@ server.route("/v1/models", modelRoutes);
|
|
|
3450
3549
|
server.route("/v1/embeddings", embeddingRoutes);
|
|
3451
3550
|
server.route("/v1/messages", messageRoutes);
|
|
3452
3551
|
server.route("/api", adminRoutes);
|
|
3552
|
+
|
|
3453
3553
|
//#endregion
|
|
3454
3554
|
//#region src/start.ts
|
|
3455
3555
|
/**
|
|
@@ -3546,7 +3646,7 @@ async function validateGitHubToken(token) {
|
|
|
3546
3646
|
state.githubToken = token;
|
|
3547
3647
|
consola.info("Using provided GitHub token");
|
|
3548
3648
|
try {
|
|
3549
|
-
const { getGitHubUser } = await import("./get-user-
|
|
3649
|
+
const { getGitHubUser } = await import("./get-user-DiK-7IaC.js");
|
|
3550
3650
|
const user = await getGitHubUser();
|
|
3551
3651
|
consola.info(`Logged in as ${user.login}`);
|
|
3552
3652
|
} catch (error) {
|
|
@@ -3570,26 +3670,26 @@ async function validateGitHubToken(token) {
|
|
|
3570
3670
|
* - proxyEnv: Initialize proxy settings from environment variables
|
|
3571
3671
|
* - apiKeys: Optional list of API keys to enable API key authentication
|
|
3572
3672
|
*/
|
|
3573
|
-
async function runServer(options) {
|
|
3673
|
+
async function runServer(options$1) {
|
|
3574
3674
|
const savedProxyApplied = await applyProxyConfig();
|
|
3575
|
-
if (options.proxyEnv) initProxyFromEnv();
|
|
3675
|
+
if (options$1.proxyEnv) initProxyFromEnv();
|
|
3576
3676
|
else if (savedProxyApplied) initProxyFromEnv();
|
|
3577
|
-
if (options.verbose) {
|
|
3677
|
+
if (options$1.verbose) {
|
|
3578
3678
|
consola.level = 5;
|
|
3579
3679
|
consola.info("Verbose logging enabled");
|
|
3580
3680
|
}
|
|
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;
|
|
3681
|
+
state.accountType = options$1.accountType;
|
|
3682
|
+
if (options$1.accountType !== "individual") consola.info(`Using ${options$1.accountType} plan GitHub account`);
|
|
3683
|
+
state.manualApprove = options$1.manual;
|
|
3684
|
+
state.rateLimitSeconds = options$1.rateLimit;
|
|
3685
|
+
state.rateLimitWait = options$1.rateLimitWait;
|
|
3686
|
+
state.showToken = options$1.showToken;
|
|
3687
|
+
state.apiKeys = options$1.apiKeys;
|
|
3588
3688
|
if (state.apiKeys && state.apiKeys.length > 0) consola.info(`API key authentication enabled with ${state.apiKeys.length} key(s)`);
|
|
3589
3689
|
await ensurePaths();
|
|
3590
3690
|
await cacheVSCodeVersion();
|
|
3591
3691
|
try {
|
|
3592
|
-
await (options.githubToken ? validateGitHubToken(options.githubToken) : setupGitHubToken());
|
|
3692
|
+
await (options$1.githubToken ? validateGitHubToken(options$1.githubToken) : setupGitHubToken());
|
|
3593
3693
|
} catch (error) {
|
|
3594
3694
|
consola.error(`GitHub authentication failed: ${rootCause(error)}`);
|
|
3595
3695
|
consola.info("The server will start, but requests may fail until connectivity is restored");
|
|
@@ -3597,11 +3697,11 @@ async function runServer(options) {
|
|
|
3597
3697
|
try {
|
|
3598
3698
|
await setupCopilotToken();
|
|
3599
3699
|
} catch (error) {
|
|
3600
|
-
const { HTTPError } = await import("./error-
|
|
3601
|
-
if (error instanceof HTTPError && error.response.status === 401) {
|
|
3700
|
+
const { HTTPError: HTTPError$1 } = await import("./error-HsNBNEyW.js");
|
|
3701
|
+
if (error instanceof HTTPError$1 && error.response.status === 401) {
|
|
3602
3702
|
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();
|
|
3703
|
+
const { clearGithubToken: clearGithubToken$1 } = await import("./token-C8PZ2fm8.js");
|
|
3704
|
+
await clearGithubToken$1();
|
|
3605
3705
|
consola.info("Please restart to re-authenticate");
|
|
3606
3706
|
}
|
|
3607
3707
|
throw error;
|
|
@@ -3610,111 +3710,113 @@ async function runServer(options) {
|
|
|
3610
3710
|
await initMultiAccount();
|
|
3611
3711
|
await initModelRouting();
|
|
3612
3712
|
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);
|
|
3713
|
+
const serverUrl = `http://localhost:${options$1.port}`;
|
|
3714
|
+
if (options$1.claudeCode) await setupClaudeCodeEnv(serverUrl);
|
|
3615
3715
|
const multiAccountInfo = state.multiAccountEnabled ? `\n👥 Multi-account: ${accountManager.activeAccountCount}/${accountManager.accountCount} active` : "";
|
|
3616
3716
|
consola.box(`🌐 Usage Viewer: https://imbuxiangnan-cyber.github.io/copilot-api-plus?endpoint=${serverUrl}/usage${multiAccountInfo}`);
|
|
3617
3717
|
serve({
|
|
3618
3718
|
fetch: server.fetch,
|
|
3619
|
-
port: options.port
|
|
3719
|
+
port: options$1.port
|
|
3620
3720
|
});
|
|
3621
3721
|
}
|
|
3722
|
+
const start = defineCommand({
|
|
3723
|
+
meta: {
|
|
3724
|
+
name: "start",
|
|
3725
|
+
description: "Start the Copilot API server"
|
|
3726
|
+
},
|
|
3727
|
+
args: {
|
|
3728
|
+
port: {
|
|
3729
|
+
alias: "p",
|
|
3730
|
+
type: "string",
|
|
3731
|
+
default: "4141",
|
|
3732
|
+
description: "Port to listen on"
|
|
3733
|
+
},
|
|
3734
|
+
verbose: {
|
|
3735
|
+
alias: "v",
|
|
3736
|
+
type: "boolean",
|
|
3737
|
+
default: false,
|
|
3738
|
+
description: "Enable verbose logging"
|
|
3739
|
+
},
|
|
3740
|
+
"account-type": {
|
|
3741
|
+
alias: "a",
|
|
3742
|
+
type: "string",
|
|
3743
|
+
default: "individual",
|
|
3744
|
+
description: "Account type to use (individual, business, enterprise)"
|
|
3745
|
+
},
|
|
3746
|
+
manual: {
|
|
3747
|
+
type: "boolean",
|
|
3748
|
+
default: false,
|
|
3749
|
+
description: "Enable manual request approval"
|
|
3750
|
+
},
|
|
3751
|
+
"rate-limit": {
|
|
3752
|
+
alias: "r",
|
|
3753
|
+
type: "string",
|
|
3754
|
+
description: "Rate limit in seconds between requests"
|
|
3755
|
+
},
|
|
3756
|
+
wait: {
|
|
3757
|
+
alias: "w",
|
|
3758
|
+
type: "boolean",
|
|
3759
|
+
default: false,
|
|
3760
|
+
description: "Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"
|
|
3761
|
+
},
|
|
3762
|
+
"github-token": {
|
|
3763
|
+
alias: "g",
|
|
3764
|
+
type: "string",
|
|
3765
|
+
description: "Provide GitHub token directly (must be generated using the `auth` subcommand)"
|
|
3766
|
+
},
|
|
3767
|
+
"claude-code": {
|
|
3768
|
+
alias: "c",
|
|
3769
|
+
type: "boolean",
|
|
3770
|
+
default: false,
|
|
3771
|
+
description: "Generate a command to launch Claude Code with Copilot API config"
|
|
3772
|
+
},
|
|
3773
|
+
"show-token": {
|
|
3774
|
+
type: "boolean",
|
|
3775
|
+
default: false,
|
|
3776
|
+
description: "Show GitHub and Copilot tokens on fetch and refresh"
|
|
3777
|
+
},
|
|
3778
|
+
"proxy-env": {
|
|
3779
|
+
type: "boolean",
|
|
3780
|
+
default: false,
|
|
3781
|
+
description: "Initialize proxy from environment variables"
|
|
3782
|
+
},
|
|
3783
|
+
"api-key": {
|
|
3784
|
+
type: "string",
|
|
3785
|
+
description: "API keys for authentication"
|
|
3786
|
+
}
|
|
3787
|
+
},
|
|
3788
|
+
run({ args }) {
|
|
3789
|
+
const rateLimitRaw = args["rate-limit"];
|
|
3790
|
+
const rateLimit = rateLimitRaw === void 0 ? void 0 : Number.parseInt(rateLimitRaw, 10);
|
|
3791
|
+
const apiKeyRaw = args["api-key"];
|
|
3792
|
+
let apiKeys;
|
|
3793
|
+
if (apiKeyRaw) apiKeys = Array.isArray(apiKeyRaw) ? apiKeyRaw : [apiKeyRaw];
|
|
3794
|
+
return runServer({
|
|
3795
|
+
port: Number.parseInt(args.port, 10),
|
|
3796
|
+
verbose: args.verbose,
|
|
3797
|
+
accountType: args["account-type"],
|
|
3798
|
+
manual: args.manual,
|
|
3799
|
+
rateLimit,
|
|
3800
|
+
rateLimitWait: args.wait,
|
|
3801
|
+
githubToken: args["github-token"],
|
|
3802
|
+
claudeCode: args["claude-code"],
|
|
3803
|
+
showToken: args["show-token"],
|
|
3804
|
+
proxyEnv: args["proxy-env"],
|
|
3805
|
+
apiKeys
|
|
3806
|
+
});
|
|
3807
|
+
}
|
|
3808
|
+
});
|
|
3809
|
+
|
|
3622
3810
|
//#endregion
|
|
3623
3811
|
//#region src/main.ts
|
|
3624
|
-
|
|
3812
|
+
const main = defineCommand({
|
|
3625
3813
|
meta: {
|
|
3626
3814
|
name: "copilot-api-plus",
|
|
3627
3815
|
description: "A wrapper around GitHub Copilot API to make it OpenAI/Anthropic compatible. Fork with bug fixes and improvements."
|
|
3628
3816
|
},
|
|
3629
3817
|
subCommands: {
|
|
3630
3818
|
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
|
-
}),
|
|
3819
|
+
start,
|
|
3718
3820
|
"check-usage": checkUsage,
|
|
3719
3821
|
"add-account": addAccount,
|
|
3720
3822
|
"list-accounts": listAccounts,
|
|
@@ -3723,8 +3825,9 @@ await runMain(defineCommand({
|
|
|
3723
3825
|
logout,
|
|
3724
3826
|
proxy
|
|
3725
3827
|
}
|
|
3726
|
-
})
|
|
3727
|
-
|
|
3728
|
-
export {};
|
|
3828
|
+
});
|
|
3829
|
+
await runMain(main);
|
|
3729
3830
|
|
|
3831
|
+
//#endregion
|
|
3832
|
+
export { };
|
|
3730
3833
|
//# sourceMappingURL=main.js.map
|