@nick3/copilot-api 1.10.9 → 1.10.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -45
- package/README.zh-CN.md +140 -45
- package/dist/{account-COtMmvzU.js → account-DpW8RaT6.js} +3 -3
- package/dist/{account-COtMmvzU.js.map → account-DpW8RaT6.js.map} +1 -1
- package/dist/admin/AGENTS.md +19 -0
- package/dist/auth-nO-eHeO_.js +327 -0
- package/dist/auth-nO-eHeO_.js.map +1 -0
- package/dist/{check-usage-DdevqHE5.js → check-usage-ZifYvA3w.js} +4 -42
- package/dist/check-usage-ZifYvA3w.js.map +1 -0
- package/dist/config-CmhIPHn_.js +578 -0
- package/dist/config-CmhIPHn_.js.map +1 -0
- package/dist/{debug-BMo6ltbp.js → debug-DvpksqEL.js} +18 -7
- package/dist/debug-DvpksqEL.js.map +1 -0
- package/dist/main.js +5 -10
- package/dist/main.js.map +1 -1
- package/dist/mcp-http-BhELuvog.js +2 -0
- package/dist/mcp-http-DI4Vz01p.js +82 -0
- package/dist/mcp-http-DI4Vz01p.js.map +1 -0
- package/dist/mcp-http-config-DMdUDz1D.js +39 -0
- package/dist/mcp-http-config-DMdUDz1D.js.map +1 -0
- package/dist/mcp-pLTPS0tO.js +79 -0
- package/dist/mcp-pLTPS0tO.js.map +1 -0
- package/dist/{tool-search-BrN7M0Dd.js → mcp-server-DEqHrXFq.js} +25 -2
- package/dist/mcp-server-DEqHrXFq.js.map +1 -0
- package/dist/{paths-CclKwouX.js → paths-Bpsb62LK.js} +3 -1
- package/dist/paths-Bpsb62LK.js.map +1 -0
- package/dist/{poll-access-token-BAgM2-7k.js → poll-access-token-GzVkiTH8.js} +71 -4
- package/dist/poll-access-token-GzVkiTH8.js.map +1 -0
- package/dist/{request-outbound-BJjWS_jF.js → request-outbound-BkEA8Wgb.js} +1 -1
- package/dist/{request-outbound-Pu1kp2x8.js → request-outbound-DZTxxtcx.js} +3 -3
- package/dist/{request-outbound-Pu1kp2x8.js.map → request-outbound-DZTxxtcx.js.map} +1 -1
- package/dist/{proxy-_U-hgwIn.js → responses-bridge-registry-BJ5Sbh6-.js} +116 -577
- package/dist/responses-bridge-registry-BJ5Sbh6-.js.map +1 -0
- package/dist/{server-GxNB5Syq.js → server-DJ3_UGc4.js} +313 -165
- package/dist/server-DJ3_UGc4.js.map +1 -0
- package/dist/start-DaB0AcjZ.js +526 -0
- package/dist/start-DaB0AcjZ.js.map +1 -0
- package/dist/token-DrFDLVxa.js +365 -0
- package/dist/token-DrFDLVxa.js.map +1 -0
- package/package.json +1 -1
- package/dist/auth-B0y-2njL.js +0 -226
- package/dist/auth-B0y-2njL.js.map +0 -1
- package/dist/check-usage-DdevqHE5.js.map +0 -1
- package/dist/debug-BMo6ltbp.js.map +0 -1
- package/dist/get-copilot-token-8Rm-rVsp.js +0 -17
- package/dist/get-copilot-token-8Rm-rVsp.js.map +0 -1
- package/dist/mcp-9Hgepkc5.js +0 -37
- package/dist/mcp-9Hgepkc5.js.map +0 -1
- package/dist/paths-CclKwouX.js.map +0 -1
- package/dist/poll-access-token-BAgM2-7k.js.map +0 -1
- package/dist/proxy-_U-hgwIn.js.map +0 -1
- package/dist/server-GxNB5Syq.js.map +0 -1
- package/dist/start-DdrurmQ3.js +0 -274
- package/dist/start-DdrurmQ3.js.map +0 -1
- package/dist/tool-search-BrN7M0Dd.js.map +0 -1
|
@@ -1,538 +1,112 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { b as getCurrentIdentityEnvironment, c as isAccountEnabled, f as readLegacyToken, h as saveAccountToken, i as ensureAccountClientIdentity, l as listAccountsFromRegistry, o as hasLegacyToken, r as addAccountToRegistry, s as hasRegistry, u as loadAccountToken, v as buildIdentityKey, y as createAccountSessionId } from "./account-
|
|
3
|
-
import { t as PATHS } from "./paths-
|
|
4
|
-
import {
|
|
5
|
-
import { c as getAdminDbUserVersion, i as getRequestOutboundStore, o as getAdminDb, s as getAdminDbPath } from "./request-outbound-
|
|
1
|
+
import { A as accountFromState, N as consumeOutboundHeadersSnapshot, P as requestContext, S as copilotBaseUrl, _ as getCopilotToken, b as HTTPError, g as getCopilotUsage, m as getGitHubUser, w as copilotModelsHeaders } from "./poll-access-token-GzVkiTH8.js";
|
|
2
|
+
import { b as getCurrentIdentityEnvironment, c as isAccountEnabled, f as readLegacyToken, h as saveAccountToken, i as ensureAccountClientIdentity, l as listAccountsFromRegistry, o as hasLegacyToken, r as addAccountToRegistry, s as hasRegistry, u as loadAccountToken, v as buildIdentityKey, y as createAccountSessionId } from "./account-DpW8RaT6.js";
|
|
3
|
+
import { t as PATHS } from "./paths-Bpsb62LK.js";
|
|
4
|
+
import { E as resolveModelAlias, a as getConfig, f as getQuotaRefreshConfig, h as getSessionAffinityRetentionMs } from "./config-CmhIPHn_.js";
|
|
5
|
+
import { c as getAdminDbUserVersion, i as getRequestOutboundStore, o as getAdminDb, s as getAdminDbPath } from "./request-outbound-DZTxxtcx.js";
|
|
6
6
|
import consola, { consola as consola$1 } from "consola";
|
|
7
7
|
import fs from "node:fs/promises";
|
|
8
|
+
import { timingSafeEqual } from "node:crypto";
|
|
8
9
|
import fs$1 from "node:fs";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
compactUseSmallModel: true,
|
|
69
|
-
messageStartInputTokensFallback: false,
|
|
70
|
-
modelRefreshIntervalHours: 24,
|
|
71
|
-
sessionAffinityRetentionDays: 7,
|
|
72
|
-
useMessagesApi: true,
|
|
73
|
-
useResponsesApiWebSocket: true,
|
|
74
|
-
useResponsesApiWebSearch: true,
|
|
75
|
-
logLevel: "info",
|
|
76
|
-
devMode: {
|
|
77
|
-
enabled: false,
|
|
78
|
-
capture4xx: false,
|
|
79
|
-
capture5xx: false,
|
|
80
|
-
captureOther: false
|
|
81
|
-
},
|
|
82
|
-
quotaRefresh: DEFAULT_QUOTA_REFRESH_CONFIG
|
|
83
|
-
};
|
|
84
|
-
let cachedConfig = null;
|
|
85
|
-
function isPlainObject(value) {
|
|
86
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
87
|
-
}
|
|
88
|
-
function normalizeAuthApiKeys(value) {
|
|
89
|
-
if (!Array.isArray(value)) return [];
|
|
90
|
-
return [...new Set(value.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length > 0))];
|
|
91
|
-
}
|
|
92
|
-
function normalizeNonNegativeNumber(value) {
|
|
93
|
-
if (typeof value !== "number") return void 0;
|
|
94
|
-
if (!Number.isFinite(value)) return void 0;
|
|
95
|
-
if (value < 0) return void 0;
|
|
96
|
-
return value;
|
|
97
|
-
}
|
|
98
|
-
function normalizeQuotaRefreshIntervalMinutes(value) {
|
|
99
|
-
const minutes = normalizeNonNegativeNumber(value) ?? DEFAULT_QUOTA_REFRESH_CONFIG.intervalMinutes;
|
|
100
|
-
if (minutes > 0 && minutes < MIN_QUOTA_REFRESH_INTERVAL_MINUTES) return MIN_QUOTA_REFRESH_INTERVAL_MINUTES;
|
|
101
|
-
return minutes;
|
|
102
|
-
}
|
|
103
|
-
function normalizeQuotaRefreshConfig(value) {
|
|
104
|
-
const raw = isPlainObject(value) ? value : {};
|
|
105
|
-
const staggerMinSeconds = normalizeNonNegativeNumber(raw.staggerMinSeconds) ?? DEFAULT_QUOTA_REFRESH_CONFIG.staggerMinSeconds;
|
|
106
|
-
const rawStaggerMaxSeconds = normalizeNonNegativeNumber(raw.staggerMaxSeconds) ?? DEFAULT_QUOTA_REFRESH_CONFIG.staggerMaxSeconds;
|
|
107
|
-
return {
|
|
108
|
-
enabled: typeof raw.enabled === "boolean" ? raw.enabled : DEFAULT_QUOTA_REFRESH_CONFIG.enabled,
|
|
109
|
-
intervalMinutes: normalizeQuotaRefreshIntervalMinutes(raw.intervalMinutes),
|
|
110
|
-
startupDelaySeconds: normalizeNonNegativeNumber(raw.startupDelaySeconds) ?? DEFAULT_QUOTA_REFRESH_CONFIG.startupDelaySeconds,
|
|
111
|
-
staggerMinSeconds,
|
|
112
|
-
staggerMaxSeconds: Math.max(staggerMinSeconds, rawStaggerMaxSeconds)
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
const LOG_LEVELS = new Set([
|
|
116
|
-
"error",
|
|
117
|
-
"warn",
|
|
118
|
-
"info",
|
|
119
|
-
"debug"
|
|
120
|
-
]);
|
|
121
|
-
function normalizeLogLevel(value) {
|
|
122
|
-
if (typeof value !== "string") return void 0;
|
|
123
|
-
return LOG_LEVELS.has(value) ? value : void 0;
|
|
124
|
-
}
|
|
125
|
-
function ensureConfigFile() {
|
|
126
|
-
try {
|
|
127
|
-
fs$1.accessSync(PATHS.CONFIG_PATH, fs$1.constants.R_OK);
|
|
128
|
-
return;
|
|
129
|
-
} catch {}
|
|
130
|
-
try {
|
|
131
|
-
fs$1.mkdirSync(PATHS.APP_DIR, { recursive: true });
|
|
132
|
-
fs$1.writeFileSync(PATHS.CONFIG_PATH, `${JSON.stringify(defaultConfig, null, 2)}\n`, "utf8");
|
|
133
|
-
try {
|
|
134
|
-
fs$1.chmodSync(PATHS.CONFIG_PATH, 384);
|
|
135
|
-
} catch {}
|
|
136
|
-
} catch {}
|
|
137
|
-
}
|
|
138
|
-
function readConfigFromDisk() {
|
|
139
|
-
ensureConfigFile();
|
|
140
|
-
try {
|
|
141
|
-
const raw = fs$1.readFileSync(PATHS.CONFIG_PATH, "utf8");
|
|
142
|
-
if (!raw.trim()) {
|
|
143
|
-
fs$1.writeFileSync(PATHS.CONFIG_PATH, `${JSON.stringify(defaultConfig, null, 2)}\n`, "utf8");
|
|
144
|
-
return defaultConfig;
|
|
10
|
+
//#region src/lib/request-auth.ts
|
|
11
|
+
const LEGACY_API_KEY_ENV_VAR = "COPILOT_API_KEY";
|
|
12
|
+
let warnedLegacyEnvFallback = false;
|
|
13
|
+
let warnedLegacyConfigFallback = false;
|
|
14
|
+
function normalizeApiKeys(apiKeys) {
|
|
15
|
+
if (!Array.isArray(apiKeys)) {
|
|
16
|
+
if (apiKeys !== void 0) consola.warn("Invalid auth.apiKeys config. Expected an array of strings.");
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const normalizedKeys = apiKeys.filter((key) => typeof key === "string").map((key) => key.trim()).filter((key) => key.length > 0);
|
|
20
|
+
if (normalizedKeys.length !== apiKeys.length) consola.warn("Invalid auth.apiKeys entries found. Only non-empty strings are allowed.");
|
|
21
|
+
return [...new Set(normalizedKeys)];
|
|
22
|
+
}
|
|
23
|
+
function getConfiguredApiKeys() {
|
|
24
|
+
const config = getConfig();
|
|
25
|
+
const configuredApiKeys = normalizeApiKeys(config.auth?.apiKeys);
|
|
26
|
+
if (configuredApiKeys.length > 0) return configuredApiKeys;
|
|
27
|
+
const envApiKey = process.env[LEGACY_API_KEY_ENV_VAR]?.trim();
|
|
28
|
+
if (envApiKey) {
|
|
29
|
+
if (!warnedLegacyEnvFallback) {
|
|
30
|
+
warnedLegacyEnvFallback = true;
|
|
31
|
+
consola.warn(`Using legacy ${LEGACY_API_KEY_ENV_VAR}. Please migrate to config.auth.apiKeys.`);
|
|
32
|
+
}
|
|
33
|
+
return [envApiKey];
|
|
34
|
+
}
|
|
35
|
+
const legacyConfigApiKey = config.apiKey?.trim();
|
|
36
|
+
if (legacyConfigApiKey) {
|
|
37
|
+
if (!warnedLegacyConfigFallback) {
|
|
38
|
+
warnedLegacyConfigFallback = true;
|
|
39
|
+
consola.warn("Using deprecated config.apiKey. Please migrate to config.auth.apiKeys.");
|
|
40
|
+
}
|
|
41
|
+
return [legacyConfigApiKey];
|
|
42
|
+
}
|
|
43
|
+
return configuredApiKeys;
|
|
44
|
+
}
|
|
45
|
+
function extractHeadersApiKey(headers) {
|
|
46
|
+
const xApiKey = headers.get("x-api-key")?.trim();
|
|
47
|
+
if (xApiKey) return xApiKey;
|
|
48
|
+
const authorization = headers.get("authorization");
|
|
49
|
+
if (!authorization) return null;
|
|
50
|
+
const [scheme, ...rest] = authorization.trim().split(/\s+/);
|
|
51
|
+
if (scheme.toLowerCase() !== "bearer") return null;
|
|
52
|
+
return rest.join(" ").trim() || null;
|
|
53
|
+
}
|
|
54
|
+
function isAuthorizedHeaders(headers, getApiKeys = getConfiguredApiKeys) {
|
|
55
|
+
const apiKeys = getApiKeys();
|
|
56
|
+
if (apiKeys.length === 0) return true;
|
|
57
|
+
const requestApiKey = extractHeadersApiKey(headers);
|
|
58
|
+
return requestApiKey ? apiKeys.some((apiKey) => timingSafeKeyCompare(requestApiKey, apiKey)) : false;
|
|
59
|
+
}
|
|
60
|
+
function createUnauthorizedRawResponse() {
|
|
61
|
+
return new Response(JSON.stringify({ error: {
|
|
62
|
+
message: "Unauthorized. Provide Authorization: Bearer <key> or x-api-key.",
|
|
63
|
+
type: "unauthorized"
|
|
64
|
+
} }), {
|
|
65
|
+
status: 401,
|
|
66
|
+
headers: {
|
|
67
|
+
"content-type": "application/json",
|
|
68
|
+
"WWW-Authenticate": "Bearer realm=\"copilot-api\""
|
|
145
69
|
}
|
|
146
|
-
return JSON.parse(raw);
|
|
147
|
-
} catch (error) {
|
|
148
|
-
consola.error("Failed to read config file, using default config", error);
|
|
149
|
-
return defaultConfig;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
function mergeDefaultConfig(config) {
|
|
153
|
-
const extraPrompts = config.extraPrompts ?? {};
|
|
154
|
-
const defaultExtraPrompts = defaultConfig.extraPrompts ?? {};
|
|
155
|
-
const modelReasoningEfforts = config.modelReasoningEfforts ?? {};
|
|
156
|
-
const defaultModelReasoningEfforts = defaultConfig.modelReasoningEfforts ?? {};
|
|
157
|
-
const hasForceAgent = typeof config.forceAgent === "boolean";
|
|
158
|
-
const defaultForceAgent = defaultConfig.forceAgent ?? false;
|
|
159
|
-
const missingExtraPromptModels = Object.keys(defaultExtraPrompts).filter((model) => !Object.hasOwn(extraPrompts, model));
|
|
160
|
-
const missingReasoningEffortModels = Object.keys(defaultModelReasoningEfforts).filter((model) => !Object.hasOwn(modelReasoningEfforts, model));
|
|
161
|
-
const hasExtraPromptChanges = missingExtraPromptModels.length > 0;
|
|
162
|
-
const hasReasoningEffortChanges = missingReasoningEffortModels.length > 0;
|
|
163
|
-
if (!hasExtraPromptChanges && !hasReasoningEffortChanges && !!hasForceAgent) return {
|
|
164
|
-
mergedConfig: config,
|
|
165
|
-
changed: false
|
|
166
|
-
};
|
|
167
|
-
return {
|
|
168
|
-
mergedConfig: {
|
|
169
|
-
...config,
|
|
170
|
-
extraPrompts: {
|
|
171
|
-
...defaultExtraPrompts,
|
|
172
|
-
...extraPrompts
|
|
173
|
-
},
|
|
174
|
-
modelReasoningEfforts: {
|
|
175
|
-
...defaultModelReasoningEfforts,
|
|
176
|
-
...modelReasoningEfforts
|
|
177
|
-
},
|
|
178
|
-
forceAgent: hasForceAgent ? config.forceAgent : defaultForceAgent
|
|
179
|
-
},
|
|
180
|
-
changed: true
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
function mergeDefaultAuth(config) {
|
|
184
|
-
const authConfig = isPlainObject(config.auth) ? config.auth : void 0;
|
|
185
|
-
const nextAuth = { apiKeys: normalizeAuthApiKeys(Array.isArray(authConfig?.apiKeys) ? authConfig.apiKeys : void 0) };
|
|
186
|
-
if (authConfig && JSON.stringify(authConfig) === JSON.stringify(nextAuth)) return {
|
|
187
|
-
mergedConfig: config,
|
|
188
|
-
changed: false
|
|
189
|
-
};
|
|
190
|
-
return {
|
|
191
|
-
mergedConfig: {
|
|
192
|
-
...config,
|
|
193
|
-
auth: nextAuth
|
|
194
|
-
},
|
|
195
|
-
changed: true
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
function mergeDefaultAccountAffinity(config) {
|
|
199
|
-
const raw = config;
|
|
200
|
-
const hasOld = typeof raw.freeModelLoadBalancing === "boolean";
|
|
201
|
-
const hasNew = typeof config.accountAffinity === "boolean";
|
|
202
|
-
if (hasOld) {
|
|
203
|
-
const next = { ...config };
|
|
204
|
-
if (!hasNew) next.accountAffinity = raw.freeModelLoadBalancing;
|
|
205
|
-
delete next.freeModelLoadBalancing;
|
|
206
|
-
return {
|
|
207
|
-
mergedConfig: next,
|
|
208
|
-
changed: true
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
if (hasNew) return {
|
|
212
|
-
mergedConfig: config,
|
|
213
|
-
changed: false
|
|
214
|
-
};
|
|
215
|
-
return {
|
|
216
|
-
mergedConfig: {
|
|
217
|
-
...config,
|
|
218
|
-
accountAffinity: defaultConfig.accountAffinity ?? true
|
|
219
|
-
},
|
|
220
|
-
changed: true
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
function mergeDefaultModelRefreshInterval(config) {
|
|
224
|
-
if (normalizeNonNegativeNumber(config.modelRefreshIntervalHours) !== void 0) return {
|
|
225
|
-
mergedConfig: config,
|
|
226
|
-
changed: false
|
|
227
|
-
};
|
|
228
|
-
return {
|
|
229
|
-
mergedConfig: {
|
|
230
|
-
...config,
|
|
231
|
-
modelRefreshIntervalHours: defaultConfig.modelRefreshIntervalHours ?? 24
|
|
232
|
-
},
|
|
233
|
-
changed: true
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
function mergeDefaultSessionAffinityRetention(config) {
|
|
237
|
-
if (normalizeNonNegativeNumber(config.sessionAffinityRetentionDays) !== void 0) return {
|
|
238
|
-
mergedConfig: config,
|
|
239
|
-
changed: false
|
|
240
|
-
};
|
|
241
|
-
return {
|
|
242
|
-
mergedConfig: {
|
|
243
|
-
...config,
|
|
244
|
-
sessionAffinityRetentionDays: defaultConfig.sessionAffinityRetentionDays ?? 7
|
|
245
|
-
},
|
|
246
|
-
changed: true
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
function mergeDefaultLogLevel(config) {
|
|
250
|
-
if (normalizeLogLevel(config.logLevel) !== void 0) return {
|
|
251
|
-
mergedConfig: config,
|
|
252
|
-
changed: false
|
|
253
|
-
};
|
|
254
|
-
return {
|
|
255
|
-
mergedConfig: {
|
|
256
|
-
...config,
|
|
257
|
-
logLevel: defaultConfig.logLevel ?? "info"
|
|
258
|
-
},
|
|
259
|
-
changed: true
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
function mergeDefaultDevMode(config) {
|
|
263
|
-
const current = config.devMode;
|
|
264
|
-
if (current && typeof current.enabled === "boolean" && typeof current.capture4xx === "boolean" && typeof current.capture5xx === "boolean" && typeof current.captureOther === "boolean") return {
|
|
265
|
-
mergedConfig: config,
|
|
266
|
-
changed: false
|
|
267
|
-
};
|
|
268
|
-
return {
|
|
269
|
-
mergedConfig: {
|
|
270
|
-
...config,
|
|
271
|
-
devMode: {
|
|
272
|
-
enabled: current?.enabled === true,
|
|
273
|
-
capture4xx: current?.capture4xx === true,
|
|
274
|
-
capture5xx: current?.capture5xx === true,
|
|
275
|
-
captureOther: current?.captureOther === true
|
|
276
|
-
}
|
|
277
|
-
},
|
|
278
|
-
changed: true
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
function mergeDefaultQuotaRefresh(config) {
|
|
282
|
-
const quotaRefresh = normalizeQuotaRefreshConfig(config.quotaRefresh);
|
|
283
|
-
if (JSON.stringify(config.quotaRefresh) === JSON.stringify(quotaRefresh)) return {
|
|
284
|
-
mergedConfig: config,
|
|
285
|
-
changed: false
|
|
286
|
-
};
|
|
287
|
-
return {
|
|
288
|
-
mergedConfig: {
|
|
289
|
-
...config,
|
|
290
|
-
quotaRefresh
|
|
291
|
-
},
|
|
292
|
-
changed: true
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
function applyConfigMerges(config, mergeFns) {
|
|
296
|
-
return mergeFns.reduce((acc, mergeFn) => {
|
|
297
|
-
const result = mergeFn(acc.mergedConfig);
|
|
298
|
-
return {
|
|
299
|
-
mergedConfig: result.mergedConfig,
|
|
300
|
-
changed: acc.changed || result.changed
|
|
301
|
-
};
|
|
302
|
-
}, {
|
|
303
|
-
mergedConfig: config,
|
|
304
|
-
changed: false
|
|
305
70
|
});
|
|
306
71
|
}
|
|
307
|
-
function
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
mergeDefaultSessionAffinityRetention,
|
|
314
|
-
mergeDefaultLogLevel,
|
|
315
|
-
mergeDefaultDevMode,
|
|
316
|
-
mergeDefaultQuotaRefresh
|
|
317
|
-
]);
|
|
318
|
-
if (changed) try {
|
|
319
|
-
fs$1.writeFileSync(PATHS.CONFIG_PATH, `${JSON.stringify(mergedConfig, null, 2)}\n`, "utf8");
|
|
320
|
-
} catch (writeError) {
|
|
321
|
-
consola.warn("Failed to write merged config defaults", writeError);
|
|
322
|
-
}
|
|
323
|
-
cachedConfig = mergedConfig;
|
|
324
|
-
return mergedConfig;
|
|
325
|
-
}
|
|
326
|
-
function getConfig() {
|
|
327
|
-
cachedConfig ??= mergeDefaultConfig(readConfigFromDisk()).mergedConfig;
|
|
328
|
-
return cachedConfig;
|
|
329
|
-
}
|
|
330
|
-
function normalizeAliasKey(value) {
|
|
331
|
-
const trimmed = value.trim().toLowerCase();
|
|
332
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
333
|
-
}
|
|
334
|
-
function normalizeAliasTarget(value) {
|
|
335
|
-
const trimmed = value.trim();
|
|
336
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
337
|
-
}
|
|
338
|
-
function normalizeAliasSpec(value) {
|
|
339
|
-
if (typeof value === "string") {
|
|
340
|
-
const normalizedTarget = normalizeAliasTarget(value);
|
|
341
|
-
return normalizedTarget ? { target: normalizedTarget } : null;
|
|
342
|
-
}
|
|
343
|
-
if (!value || typeof value !== "object") return null;
|
|
344
|
-
const targetValue = value.target;
|
|
345
|
-
if (typeof targetValue !== "string") return null;
|
|
346
|
-
const normalizedTarget = normalizeAliasTarget(targetValue);
|
|
347
|
-
if (!normalizedTarget) return null;
|
|
348
|
-
const allowOriginalValue = value.allowOriginal;
|
|
349
|
-
return {
|
|
350
|
-
target: normalizedTarget,
|
|
351
|
-
allowOriginal: typeof allowOriginalValue === "boolean" ? allowOriginalValue : void 0
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
function getModelAliasesInfo() {
|
|
355
|
-
const raw = getConfig().modelAliases ?? {};
|
|
356
|
-
const normalized = {};
|
|
357
|
-
for (const [alias, rawSpec] of Object.entries(raw)) {
|
|
358
|
-
const normalizedAlias = normalizeAliasKey(alias);
|
|
359
|
-
const normalizedSpec = normalizeAliasSpec(rawSpec);
|
|
360
|
-
if (!normalizedAlias || !normalizedSpec) continue;
|
|
361
|
-
if (!Object.hasOwn(normalized, normalizedAlias)) normalized[normalizedAlias] = normalizedSpec;
|
|
362
|
-
}
|
|
363
|
-
return normalized;
|
|
364
|
-
}
|
|
365
|
-
function getModelAliases() {
|
|
366
|
-
const info = getModelAliasesInfo();
|
|
367
|
-
const normalized = {};
|
|
368
|
-
for (const [alias, spec] of Object.entries(info)) normalized[alias] = spec.target;
|
|
369
|
-
return normalized;
|
|
370
|
-
}
|
|
371
|
-
function resolveModelAlias(modelId) {
|
|
372
|
-
const normalized = normalizeAliasKey(modelId);
|
|
373
|
-
if (!normalized) return modelId;
|
|
374
|
-
return getModelAliases()[normalized] ?? modelId;
|
|
375
|
-
}
|
|
376
|
-
function isOriginalModelNameAllowedForAliases() {
|
|
377
|
-
return getConfig().allowOriginalModelNamesForAliases ?? false;
|
|
378
|
-
}
|
|
379
|
-
function getAliasTargetSet() {
|
|
380
|
-
const aliases = getModelAliasesInfo();
|
|
381
|
-
const allowOriginalDefault = isOriginalModelNameAllowedForAliases();
|
|
382
|
-
const targetAllowMap = /* @__PURE__ */ new Map();
|
|
383
|
-
for (const { target, allowOriginal } of Object.values(aliases)) {
|
|
384
|
-
const normalizedTarget = target.toLowerCase();
|
|
385
|
-
const effectiveAllow = allowOriginal ?? allowOriginalDefault;
|
|
386
|
-
const currentAllow = targetAllowMap.get(normalizedTarget);
|
|
387
|
-
if (currentAllow === true) continue;
|
|
388
|
-
if (effectiveAllow) targetAllowMap.set(normalizedTarget, true);
|
|
389
|
-
else if (currentAllow === void 0) targetAllowMap.set(normalizedTarget, false);
|
|
390
|
-
}
|
|
391
|
-
const blockedTargets = /* @__PURE__ */ new Set();
|
|
392
|
-
for (const [target, allowed] of targetAllowMap.entries()) if (!allowed) blockedTargets.add(target);
|
|
393
|
-
return blockedTargets;
|
|
394
|
-
}
|
|
395
|
-
function isOriginalModelNameAllowedForTarget(modelId) {
|
|
396
|
-
const normalized = normalizeAliasKey(modelId);
|
|
397
|
-
if (!normalized) return true;
|
|
398
|
-
return !getAliasTargetSet().has(normalized);
|
|
399
|
-
}
|
|
400
|
-
function getPreferredAliasForTarget(modelId) {
|
|
401
|
-
return getAliasKeysForTarget(modelId, getModelAliases())[0] ?? null;
|
|
402
|
-
}
|
|
403
|
-
function getAliasKeysForTarget(target, aliases) {
|
|
404
|
-
const normalizedTarget = target.toLowerCase();
|
|
405
|
-
return Object.entries(aliases).filter(([, model]) => model.toLowerCase() === normalizedTarget).map(([alias]) => alias).sort();
|
|
406
|
-
}
|
|
407
|
-
function getAliasFallbackValue(record, modelId, aliases) {
|
|
408
|
-
if (!record) return void 0;
|
|
409
|
-
const aliasKeys = getAliasKeysForTarget(modelId, aliases);
|
|
410
|
-
if (aliasKeys.length === 0) return void 0;
|
|
411
|
-
const recordByAlias = /* @__PURE__ */ new Map();
|
|
412
|
-
for (const [key, value] of Object.entries(record)) {
|
|
413
|
-
const normalized = normalizeAliasKey(key);
|
|
414
|
-
if (normalized) recordByAlias.set(normalized, value);
|
|
415
|
-
}
|
|
416
|
-
for (const alias of aliasKeys) {
|
|
417
|
-
const value = recordByAlias.get(alias);
|
|
418
|
-
if (value !== void 0) return value;
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
function getExtraPromptForModel(model) {
|
|
422
|
-
const config = getConfig();
|
|
423
|
-
const direct = config.extraPrompts?.[model];
|
|
424
|
-
if (direct !== void 0) return direct;
|
|
425
|
-
const aliases = getModelAliases();
|
|
426
|
-
return getAliasFallbackValue(config.extraPrompts, model, aliases) ?? "";
|
|
427
|
-
}
|
|
428
|
-
function getSmallModel() {
|
|
429
|
-
const model = getConfig().smallModel ?? "gpt-5-mini";
|
|
430
|
-
if (isOriginalModelNameAllowedForTarget(model)) return model;
|
|
431
|
-
return getPreferredAliasForTarget(model) ?? model;
|
|
432
|
-
}
|
|
433
|
-
function getLogLevel() {
|
|
434
|
-
return normalizeLogLevel(getConfig().logLevel) ?? defaultConfig.logLevel ?? "info";
|
|
435
|
-
}
|
|
436
|
-
function isAccountAffinityEnabled() {
|
|
437
|
-
return getConfig().accountAffinity ?? true;
|
|
438
|
-
}
|
|
439
|
-
function getModelRefreshIntervalHours() {
|
|
440
|
-
return normalizeNonNegativeNumber(getConfig().modelRefreshIntervalHours) ?? defaultConfig.modelRefreshIntervalHours ?? 24;
|
|
441
|
-
}
|
|
442
|
-
function getModelRefreshIntervalMs() {
|
|
443
|
-
const hours = getModelRefreshIntervalHours();
|
|
444
|
-
if (!Number.isFinite(hours) || hours <= 0) return 0;
|
|
445
|
-
return hours * 60 * 60 * 1e3;
|
|
446
|
-
}
|
|
447
|
-
function getQuotaRefreshConfig() {
|
|
448
|
-
return normalizeQuotaRefreshConfig(getConfig().quotaRefresh);
|
|
449
|
-
}
|
|
450
|
-
function getSessionAffinityRetentionDays() {
|
|
451
|
-
return normalizeNonNegativeNumber(getConfig().sessionAffinityRetentionDays) ?? defaultConfig.sessionAffinityRetentionDays ?? 7;
|
|
452
|
-
}
|
|
453
|
-
function getSessionAffinityRetentionMs() {
|
|
454
|
-
const days = getSessionAffinityRetentionDays();
|
|
455
|
-
if (!Number.isFinite(days) || days <= 0) return 0;
|
|
456
|
-
return days * 24 * 60 * 60 * 1e3;
|
|
457
|
-
}
|
|
458
|
-
function isMessageStartInputTokensFallbackEnabled() {
|
|
459
|
-
return getConfig().messageStartInputTokensFallback ?? false;
|
|
72
|
+
function createUnauthorizedResponse(c) {
|
|
73
|
+
c.header("WWW-Authenticate", "Bearer realm=\"copilot-api\"");
|
|
74
|
+
return c.json({ error: {
|
|
75
|
+
message: "Unauthorized. Provide Authorization: Bearer <key> or x-api-key.",
|
|
76
|
+
type: "unauthorized"
|
|
77
|
+
} }, 401);
|
|
460
78
|
}
|
|
461
|
-
function
|
|
462
|
-
|
|
79
|
+
function normalizePathname(pathname) {
|
|
80
|
+
if (pathname.length > 1 && pathname.endsWith("/")) return pathname.slice(0, -1);
|
|
81
|
+
return pathname;
|
|
463
82
|
}
|
|
464
|
-
function
|
|
465
|
-
return
|
|
83
|
+
function hasPrefixBoundary(pathname, prefix) {
|
|
84
|
+
return pathname === prefix || pathname.startsWith(`${prefix}/`);
|
|
466
85
|
}
|
|
467
|
-
function
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}
|
|
477
|
-
function
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if (authType === "authorization") return authType;
|
|
490
|
-
consola.warn(`Provider ${providerName} has invalid authType '${authType}', falling back to ${getDefaultProviderAuthType(providerType)}`);
|
|
491
|
-
return getDefaultProviderAuthType(providerType);
|
|
492
|
-
}
|
|
493
|
-
function getProviderConfig(name) {
|
|
494
|
-
const providerName = name.trim();
|
|
495
|
-
if (!providerName) return null;
|
|
496
|
-
const provider = getConfig().providers?.[providerName];
|
|
497
|
-
if (!provider) return null;
|
|
498
|
-
if (provider.enabled === false) return null;
|
|
499
|
-
const type = provider.type ?? "anthropic";
|
|
500
|
-
if (type !== "anthropic" && type !== "openai-compatible") {
|
|
501
|
-
consola.warn(`Provider ${providerName} is ignored because type '${type}' is not supported`);
|
|
502
|
-
return null;
|
|
503
|
-
}
|
|
504
|
-
const baseUrl = normalizeProviderBaseUrl(provider.baseUrl ?? "");
|
|
505
|
-
const apiKey = (provider.apiKey ?? "").trim();
|
|
506
|
-
const authType = resolveProviderAuthType(providerName, provider.authType, type);
|
|
507
|
-
if (!baseUrl || !apiKey) {
|
|
508
|
-
consola.warn(`Provider ${providerName} is enabled but missing baseUrl or apiKey`);
|
|
509
|
-
return null;
|
|
510
|
-
}
|
|
511
|
-
return {
|
|
512
|
-
name: providerName,
|
|
513
|
-
type,
|
|
514
|
-
baseUrl,
|
|
515
|
-
apiKey,
|
|
516
|
-
authType,
|
|
517
|
-
models: provider.models,
|
|
518
|
-
adjustInputTokens: provider.adjustInputTokens
|
|
86
|
+
function timingSafeKeyCompare(a, b) {
|
|
87
|
+
try {
|
|
88
|
+
const aBuf = Buffer.from(a);
|
|
89
|
+
const bBuf = Buffer.from(b);
|
|
90
|
+
if (aBuf.length !== bBuf.length) return false;
|
|
91
|
+
return timingSafeEqual(aBuf, bBuf);
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function createAuthMiddleware(options = {}) {
|
|
97
|
+
const getApiKeys = options.getApiKeys ?? getConfiguredApiKeys;
|
|
98
|
+
const allowUnauthenticatedPaths = new Set((options.allowUnauthenticatedPaths ?? ["/"]).map((path) => normalizePathname(path)));
|
|
99
|
+
const allowUnauthenticatedPathPrefixes = (options.allowUnauthenticatedPathPrefixes ?? []).map((path) => normalizePathname(path));
|
|
100
|
+
const allowOptionsBypass = options.allowOptionsBypass ?? true;
|
|
101
|
+
return async (c, next) => {
|
|
102
|
+
if (allowOptionsBypass && c.req.method === "OPTIONS") return next();
|
|
103
|
+
const pathname = normalizePathname(new URL(c.req.url, "http://local").pathname);
|
|
104
|
+
if (allowUnauthenticatedPaths.has(pathname)) return next();
|
|
105
|
+
if (allowUnauthenticatedPathPrefixes.some((prefix) => hasPrefixBoundary(pathname, prefix))) return next();
|
|
106
|
+
if (!isAuthorizedHeaders(c.req.raw.headers, getApiKeys)) return createUnauthorizedResponse(c);
|
|
107
|
+
return next();
|
|
519
108
|
};
|
|
520
109
|
}
|
|
521
|
-
function isMessagesApiEnabled() {
|
|
522
|
-
return getConfig().useMessagesApi ?? true;
|
|
523
|
-
}
|
|
524
|
-
function isResponsesApiWebSocketEnabled() {
|
|
525
|
-
return getConfig().useResponsesApiWebSocket ?? true;
|
|
526
|
-
}
|
|
527
|
-
function getAnthropicApiKey() {
|
|
528
|
-
return getConfig().anthropicApiKey ?? process.env.ANTHROPIC_API_KEY ?? void 0;
|
|
529
|
-
}
|
|
530
|
-
function isResponsesApiWebSearchEnabled() {
|
|
531
|
-
return getConfig().useResponsesApiWebSearch ?? true;
|
|
532
|
-
}
|
|
533
|
-
function getClaudeTokenMultiplier() {
|
|
534
|
-
return getConfig().claudeTokenMultiplier ?? 1.15;
|
|
535
|
-
}
|
|
536
110
|
//#endregion
|
|
537
111
|
//#region src/lib/account-affinity.ts
|
|
538
112
|
const DEFAULT_MAX_ENTRIES$1 = 1e4;
|
|
@@ -1629,7 +1203,7 @@ var RequestHistoryStore = class {
|
|
|
1629
1203
|
} catch (error) {
|
|
1630
1204
|
consola.debug("Failed to cleanup request_log retention", error);
|
|
1631
1205
|
}
|
|
1632
|
-
import("./request-outbound-
|
|
1206
|
+
import("./request-outbound-BkEA8Wgb.js").then((m) => m.getRequestOutboundStore().cleanupOrphans()).catch(() => {});
|
|
1633
1207
|
}
|
|
1634
1208
|
meta() {
|
|
1635
1209
|
return {
|
|
@@ -3257,59 +2831,24 @@ function updateQuotaRefreshSchedulerFromConfig() {
|
|
|
3257
2831
|
quotaRefreshScheduler.updateConfig(getQuotaRefreshConfig());
|
|
3258
2832
|
}
|
|
3259
2833
|
//#endregion
|
|
3260
|
-
//#region src/
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
}
|
|
3265
|
-
|
|
2834
|
+
//#region src/services/copilot/responses-bridge-registry.ts
|
|
2835
|
+
const bridgeClosers = /* @__PURE__ */ new Map();
|
|
2836
|
+
const registerResponsesBridge = (bridgeId, closer) => {
|
|
2837
|
+
bridgeClosers.set(bridgeId, closer);
|
|
2838
|
+
};
|
|
2839
|
+
const unregisterResponsesBridge = (bridgeId) => {
|
|
2840
|
+
bridgeClosers.delete(bridgeId);
|
|
2841
|
+
};
|
|
2842
|
+
const closeResponsesBridge = (bridgeId) => {
|
|
2843
|
+
const closer = bridgeClosers.get(bridgeId);
|
|
2844
|
+
if (!closer) return;
|
|
3266
2845
|
try {
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
dispatch(options, handler) {
|
|
3271
|
-
try {
|
|
3272
|
-
const origin = typeof options.origin === "string" ? new URL(options.origin) : options.origin;
|
|
3273
|
-
const raw = getProxyForUrl(origin.toString());
|
|
3274
|
-
const proxyUrl = raw && raw.length > 0 ? raw : void 0;
|
|
3275
|
-
if (!proxyUrl) {
|
|
3276
|
-
consola.debug(`HTTP proxy bypass: ${origin.hostname}`);
|
|
3277
|
-
return direct.dispatch(options, handler);
|
|
3278
|
-
}
|
|
3279
|
-
let agent = proxies.get(proxyUrl);
|
|
3280
|
-
if (!agent) {
|
|
3281
|
-
agent = new ProxyAgent(proxyUrl);
|
|
3282
|
-
proxies.set(proxyUrl, agent);
|
|
3283
|
-
}
|
|
3284
|
-
let label = proxyUrl;
|
|
3285
|
-
try {
|
|
3286
|
-
const u = new URL(proxyUrl);
|
|
3287
|
-
label = `${u.protocol}//${u.host}`;
|
|
3288
|
-
} catch {}
|
|
3289
|
-
consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`);
|
|
3290
|
-
return agent.dispatch(options, handler);
|
|
3291
|
-
} catch {
|
|
3292
|
-
return direct.dispatch(options, handler);
|
|
3293
|
-
}
|
|
3294
|
-
},
|
|
3295
|
-
close() {
|
|
3296
|
-
return direct.close();
|
|
3297
|
-
},
|
|
3298
|
-
destroy() {
|
|
3299
|
-
return direct.destroy();
|
|
3300
|
-
}
|
|
3301
|
-
};
|
|
3302
|
-
if (typeof Bun !== "undefined") {
|
|
3303
|
-
consola.debug("WebSocket proxy configured from environment (per-URL)");
|
|
3304
|
-
return;
|
|
3305
|
-
}
|
|
3306
|
-
setGlobalDispatcher(proxyEnvDispatcher);
|
|
3307
|
-
consola.debug("HTTP proxy configured from environment (per-URL)");
|
|
3308
|
-
} catch (err) {
|
|
3309
|
-
consola.debug("Proxy setup skipped:", err);
|
|
2846
|
+
closer();
|
|
2847
|
+
} catch (error) {
|
|
2848
|
+
consola.warn("Failed to close Responses websocket bridge:", error);
|
|
3310
2849
|
}
|
|
3311
|
-
}
|
|
2850
|
+
};
|
|
3312
2851
|
//#endregion
|
|
3313
|
-
export {
|
|
2852
|
+
export { createUnauthorizedRawResponse as C, createAuthMiddleware as S, normalizeMessagesUsage as _, startQuotaRefreshSchedulerFromConfig as a, flushPendingCapture as b, accountsManager as c, extractResponsesUsageFromStreamEvent as d, getClientIpInfo as f, normalizeEmbeddingsUsage as g, normalizeChatCompletionsUsage as h, registerQuotaRefreshSchedulerShutdownCleanup as i, applySharedSessionAffinityRetention as l, getStatsStore as m, registerResponsesBridge as n, stopQuotaRefreshScheduler as o, getRequestHistoryStore as p, unregisterResponsesBridge as r, updateQuotaRefreshSchedulerFromConfig as s, closeResponsesBridge as t, extractResponsesUsageFromResult as u, toLocalDateString as v, isAuthorizedHeaders as w, isDevModeEnabled as x, copilotFetch as y };
|
|
3314
2853
|
|
|
3315
|
-
//# sourceMappingURL=
|
|
2854
|
+
//# sourceMappingURL=responses-bridge-registry-BJ5Sbh6-.js.map
|