copilot-api-plus 1.2.1 → 1.2.3
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 +3 -2
- package/README.md +3 -2
- package/dist/{get-user-WQHD68Sz.js → get-user-BT7hEyDN.js} +6 -4
- package/dist/get-user-BT7hEyDN.js.map +1 -0
- package/dist/get-user-BTN_-eOk.js +3 -0
- package/dist/main.js +89 -24
- package/dist/main.js.map +1 -1
- package/dist/token-CxG7xLpI.js +4 -0
- package/dist/{token-BMHteyQY.js → token-D_wTNufW.js} +103 -89
- package/dist/token-D_wTNufW.js.map +1 -0
- package/package.json +1 -1
- package/dist/get-user-D5-qoD5J.js +0 -3
- package/dist/get-user-WQHD68Sz.js.map +0 -1
- package/dist/token-BMHteyQY.js.map +0 -1
- package/dist/token-Brc5l1C6.js +0 -4
package/README.en.md
CHANGED
|
@@ -49,6 +49,7 @@ English | [简体中文](README.md)
|
|
|
49
49
|
| 🛡️ **Network Resilience** | 120s connection timeout + exponential backoff retry (2s/5s/10s) |
|
|
50
50
|
| ✂️ **Context Passthrough** | Full context passthrough to upstream API; clients (e.g. Claude Code) manage compression |
|
|
51
51
|
| 🔍 **Smart Model Matching** | Handles model name format differences (date suffixes, dash/dot versions, etc.) |
|
|
52
|
+
| 🧠 **Thinking Chain** | Automatically enables deep thinking (thinking/reasoning) for supported models, improving code quality |
|
|
52
53
|
|
|
53
54
|
---
|
|
54
55
|
|
|
@@ -573,8 +574,8 @@ For Anthropic endpoints (`/v1/messages`), `translateModelName` also handles lega
|
|
|
573
574
|
Each API request outputs a log line with model name, status code, and duration:
|
|
574
575
|
|
|
575
576
|
```log
|
|
576
|
-
[claude-opus-4-6] 13:13:39 <-- POST /v1/messages?beta=true
|
|
577
|
-
[claude-opus-4-6] 13:13:59 --> POST /v1/messages?beta=true 200 20.1s
|
|
577
|
+
[claude-opus-4-6 thinking] 13:13:39 <-- POST /v1/messages?beta=true
|
|
578
|
+
[claude-opus-4-6 thinking] 13:13:59 --> POST /v1/messages?beta=true 200 20.1s
|
|
578
579
|
```
|
|
579
580
|
|
|
580
581
|
### Network Resilience
|
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
| 🛡️ **网络弹性** | 120s 连接超时 + 指数退避重试(2s/5s/10s) |
|
|
51
51
|
| ✂️ **上下文透传** | 全量透传上下文至上游 API,由客户端(如 Claude Code)自行管理压缩 |
|
|
52
52
|
| 🔍 **智能模型匹配** | 自动处理模型名格式差异(日期后缀、dash/dot 版本号等) |
|
|
53
|
+
| 🧠 **Thinking 思维链** | 自动为支持的模型启用深度思考(thinking/reasoning),提升代码质量 |
|
|
53
54
|
|
|
54
55
|
---
|
|
55
56
|
|
|
@@ -736,8 +737,8 @@ Anthropic 格式的模型名(如 `claude-opus-4-6`)和 Copilot 的模型列
|
|
|
736
737
|
每次 API 请求会输出一行日志,包含模型名、状态码和耗时:
|
|
737
738
|
|
|
738
739
|
```log
|
|
739
|
-
[claude-opus-4-6] 13:13:39 <-- POST /v1/messages?beta=true
|
|
740
|
-
[claude-opus-4-6] 13:13:59 --> POST /v1/messages?beta=true 200 20.1s
|
|
740
|
+
[claude-opus-4-6 thinking] 13:13:39 <-- POST /v1/messages?beta=true
|
|
741
|
+
[claude-opus-4-6 thinking] 13:13:59 --> POST /v1/messages?beta=true 200 20.1s
|
|
741
742
|
```
|
|
742
743
|
|
|
743
744
|
### 网络弹性
|
|
@@ -5,10 +5,10 @@ const standardHeaders = () => ({
|
|
|
5
5
|
"content-type": "application/json",
|
|
6
6
|
accept: "application/json"
|
|
7
7
|
});
|
|
8
|
-
const COPILOT_VERSION = "0.
|
|
8
|
+
const COPILOT_VERSION = "0.38.2";
|
|
9
9
|
const EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`;
|
|
10
10
|
const USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`;
|
|
11
|
-
const API_VERSION = "2025-
|
|
11
|
+
const API_VERSION = "2025-10-01";
|
|
12
12
|
const copilotBaseUrl = (source) => {
|
|
13
13
|
if (source.copilotApiEndpoint) return source.copilotApiEndpoint;
|
|
14
14
|
return source.accountType === "individual" ? "https://api.githubcopilot.com" : `https://api.${source.accountType}.githubcopilot.com`;
|
|
@@ -21,7 +21,9 @@ const copilotHeaders = (source, vision = false) => {
|
|
|
21
21
|
"editor-version": `vscode/${source.vsCodeVersion}`,
|
|
22
22
|
"editor-plugin-version": EDITOR_PLUGIN_VERSION,
|
|
23
23
|
"user-agent": USER_AGENT,
|
|
24
|
-
"openai-intent": "conversation-
|
|
24
|
+
"openai-intent": "conversation-agent",
|
|
25
|
+
"x-interaction-type": "conversation-agent",
|
|
26
|
+
"x-agent-task-id": randomUUID(),
|
|
25
27
|
"x-github-api-version": API_VERSION,
|
|
26
28
|
"x-request-id": randomUUID(),
|
|
27
29
|
"x-vscode-user-agent-library-version": "electron-fetch"
|
|
@@ -72,4 +74,4 @@ async function getGitHubUser(githubToken) {
|
|
|
72
74
|
//#endregion
|
|
73
75
|
export { GITHUB_BASE_URL as a, copilotHeaders as c, GITHUB_APP_SCOPES as i, githubHeaders as l, state as n, GITHUB_CLIENT_ID as o, GITHUB_API_BASE_URL as r, copilotBaseUrl as s, getGitHubUser as t, standardHeaders as u };
|
|
74
76
|
|
|
75
|
-
//# sourceMappingURL=get-user-
|
|
77
|
+
//# sourceMappingURL=get-user-BT7hEyDN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-user-BT7hEyDN.js","names":[],"sources":["../src/lib/api-config.ts","../src/lib/state.ts","../src/services/github/get-user.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.38.2\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\n// Updated to match latest Zed implementation - 2025-10-01 returns Claude models\nconst API_VERSION = \"2025-10-01\"\n\n/**\n * Common interface for anything that can supply Copilot/GitHub credentials.\n *\n * Both `State` and `Account` satisfy this interface, so all header/URL\n * helpers can accept either without an explicit overload.\n */\nexport interface TokenSource {\n copilotToken?: string\n copilotApiEndpoint?: string\n accountType: string\n githubToken?: string\n vsCodeVersion?: string\n}\n\n// Re-export constants used by other modules for building headers manually\nexport { API_VERSION, EDITOR_PLUGIN_VERSION, USER_AGENT }\n\n// Use the API endpoint from token response if available, otherwise fall back to default\nexport const copilotBaseUrl = (source: TokenSource) => {\n if (source.copilotApiEndpoint) {\n return source.copilotApiEndpoint\n }\n return source.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${source.accountType}.githubcopilot.com`\n}\nexport const copilotHeaders = (\n source: TokenSource,\n vision: boolean = false,\n) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${source.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-version\": `vscode/${source.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-agent\",\n \"x-interaction-type\": \"conversation-agent\",\n \"x-agent-task-id\": randomUUID(),\n \"x-github-api-version\": API_VERSION,\n \"x-request-id\": randomUUID(),\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n }\n\n if (vision) headers[\"copilot-vision-request\"] = \"true\"\n\n return headers\n}\n\nexport const GITHUB_API_BASE_URL = \"https://api.github.com\"\nexport const githubHeaders = (source: TokenSource) => ({\n ...standardHeaders(),\n authorization: `token ${source.githubToken}`,\n \"editor-version\": `vscode/${source.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"x-github-api-version\": API_VERSION,\n \"x-vscode-user-agent-library-version\": \"electron-fetch\",\n})\n\nexport const GITHUB_BASE_URL = \"https://github.com\"\nexport const GITHUB_CLIENT_ID = \"Iv1.b507a08c87ecfe98\"\nexport const GITHUB_APP_SCOPES = [\"read:user\"].join(\" \")\n","import type { ModelsResponse } from \"~/services/copilot/get-models\"\n\nexport interface State {\n githubToken?: string\n copilotToken?: string\n copilotApiEndpoint?: string // API endpoint returned by token response\n\n accountType: string\n models?: ModelsResponse\n vsCodeVersion?: string\n\n manualApprove: boolean\n rateLimitWait: boolean\n showToken: boolean\n\n // Rate limiting configuration\n rateLimitSeconds?: number\n lastRequestTimestamp?: number\n\n // API key authentication\n apiKeys?: Array<string>\n\n // Multi-account mode\n multiAccountEnabled: boolean\n\n // Selected models (from --claude-code setup)\n selectedModel?: string\n selectedSmallModel?: string\n}\n\nexport const state: State = {\n accountType: \"individual\",\n manualApprove: false,\n rateLimitWait: false,\n showToken: false,\n multiAccountEnabled: false,\n}\n","import { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\n/**\n * Fetch the GitHub user profile.\n *\n * @param githubToken Optional explicit token. When omitted, falls back to\n * the global `state.githubToken`. Prefer passing a token\n * explicitly to avoid race conditions in multi-account mode.\n */\nexport async function getGitHubUser(githubToken?: string) {\n const token = githubToken ?? state.githubToken\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${token}`,\n ...standardHeaders(),\n },\n })\n\n if (!response.ok) throw new HTTPError(\"Failed to get GitHub user\", response)\n\n return (await response.json()) as GithubUserResponse\n}\n\n// Trimmed for the sake of simplicity\ninterface GithubUserResponse {\n login: string\n}\n"],"mappings":";;;AAEA,MAAa,yBAAyB;CACpC,gBAAgB;CAChB,QAAQ;CACT;AAED,MAAM,kBAAkB;AACxB,MAAM,wBAAwB,gBAAgB;AAC9C,MAAM,aAAa,qBAAqB;AAGxC,MAAM,cAAc;AAoBpB,MAAa,kBAAkB,WAAwB;AACrD,KAAI,OAAO,mBACT,QAAO,OAAO;AAEhB,QAAO,OAAO,gBAAgB,eAC1B,kCACA,eAAe,OAAO,YAAY;;AAExC,MAAa,kBACX,QACA,SAAkB,UACf;CACH,MAAM,UAAkC;EACtC,eAAe,UAAU,OAAO;EAChC,gBAAgB,iBAAiB,CAAC;EAClC,0BAA0B;EAC1B,kBAAkB,UAAU,OAAO;EACnC,yBAAyB;EACzB,cAAc;EACd,iBAAiB;EACjB,sBAAsB;EACtB,mBAAmB,YAAY;EAC/B,wBAAwB;EACxB,gBAAgB,YAAY;EAC5B,uCAAuC;EACxC;AAED,KAAI,OAAQ,SAAQ,4BAA4B;AAEhD,QAAO;;AAGT,MAAa,sBAAsB;AACnC,MAAa,iBAAiB,YAAyB;CACrD,GAAG,iBAAiB;CACpB,eAAe,SAAS,OAAO;CAC/B,kBAAkB,UAAU,OAAO;CACnC,yBAAyB;CACzB,cAAc;CACd,wBAAwB;CACxB,uCAAuC;CACxC;AAED,MAAa,kBAAkB;AAC/B,MAAa,mBAAmB;AAChC,MAAa,oBAAoB,CAAC,YAAY,CAAC,KAAK,IAAI;;;AC/CxD,MAAa,QAAe;CAC1B,aAAa;CACb,eAAe;CACf,eAAe;CACf,WAAW;CACX,qBAAqB;CACtB;;;;;;;;;;ACzBD,eAAsB,cAAc,aAAsB;CACxD,MAAM,QAAQ,eAAe,MAAM;CACnC,MAAM,WAAW,MAAM,MAAM,GAAG,oBAAoB,QAAQ,EAC1D,SAAS;EACP,eAAe,SAAS;EACxB,GAAG,iBAAiB;EACrB,EACF,CAAC;AAEF,KAAI,CAAC,SAAS,GAAI,OAAM,IAAI,UAAU,6BAA6B,SAAS;AAE5E,QAAQ,MAAM,SAAS,MAAM"}
|
package/dist/main.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { n as forwardError, t as HTTPError } from "./error-CvwUkoEo.js";
|
|
3
|
-
import { a as stopCopilotTokenRefresh, c as
|
|
4
|
-
import { a as GITHUB_BASE_URL, c as copilotHeaders, n as state, o as GITHUB_CLIENT_ID, s as copilotBaseUrl, u as standardHeaders } from "./get-user-
|
|
3
|
+
import { _ as ensurePaths, a as stopCopilotTokenRefresh, c as accountManager, d as cacheVSCodeVersion, f as findModel, g as PATHS, h as sleep, i as setupGitHubToken, l as getCopilotUsage, m as rootCause, n as refreshCopilotToken, o as pollAccessToken, p as isNullish, r as setupCopilotToken, s as getDeviceCode, t as clearGithubToken, u as cacheModels } from "./token-D_wTNufW.js";
|
|
4
|
+
import { a as GITHUB_BASE_URL, c as copilotHeaders, n as state, o as GITHUB_CLIENT_ID, s as copilotBaseUrl, u as standardHeaders } from "./get-user-BT7hEyDN.js";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { defineCommand, runMain } from "citty";
|
|
7
7
|
import consola from "consola";
|
|
@@ -223,7 +223,8 @@ const addAccount = defineCommand({
|
|
|
223
223
|
consola.success(`Account added: ${account.githubLogin} (${account.label})`);
|
|
224
224
|
consola.info(`Total accounts: ${accountManager.accountCount}`);
|
|
225
225
|
} catch (err) {
|
|
226
|
-
consola.
|
|
226
|
+
consola.warn(`Failed to add account: ${rootCause(err)}`);
|
|
227
|
+
consola.debug("Failed to add account:", err);
|
|
227
228
|
process.exitCode = 1;
|
|
228
229
|
}
|
|
229
230
|
}
|
|
@@ -280,7 +281,8 @@ const listAccounts = defineCommand({
|
|
|
280
281
|
consola.log(botBorder);
|
|
281
282
|
consola.log("");
|
|
282
283
|
} catch (err) {
|
|
283
|
-
consola.
|
|
284
|
+
consola.warn(`Failed to list accounts: ${rootCause(err)}`);
|
|
285
|
+
consola.debug("Failed to list accounts:", err);
|
|
284
286
|
process.exitCode = 1;
|
|
285
287
|
}
|
|
286
288
|
}
|
|
@@ -355,7 +357,8 @@ const removeAccount = defineCommand({
|
|
|
355
357
|
process.exitCode = 1;
|
|
356
358
|
}
|
|
357
359
|
} catch (err) {
|
|
358
|
-
consola.
|
|
360
|
+
consola.warn(`Failed to remove account: ${rootCause(err)}`);
|
|
361
|
+
consola.debug("Failed to remove account:", err);
|
|
359
362
|
process.exitCode = 1;
|
|
360
363
|
}
|
|
361
364
|
}
|
|
@@ -427,7 +430,8 @@ const checkUsage = defineCommand({
|
|
|
427
430
|
const completionsLine = summarizeQuota("Completions", usage.quota_snapshots.completions);
|
|
428
431
|
consola.box(`Copilot Usage (plan: ${usage.copilot_plan})\nQuota resets: ${usage.quota_reset_date}\n\nQuotas:\n ${premiumLine}\n ${chatLine}\n ${completionsLine}`);
|
|
429
432
|
} catch (err) {
|
|
430
|
-
consola.
|
|
433
|
+
consola.warn(`Failed to fetch Copilot usage: ${rootCause(err)}`);
|
|
434
|
+
consola.debug("Failed to fetch Copilot usage:", err);
|
|
431
435
|
process.exit(1);
|
|
432
436
|
}
|
|
433
437
|
}
|
|
@@ -1320,29 +1324,47 @@ function formatDuration(ms) {
|
|
|
1320
1324
|
return `${(ms / 1e3).toFixed(1)}s`;
|
|
1321
1325
|
}
|
|
1322
1326
|
/**
|
|
1323
|
-
* Extract model name from request body
|
|
1327
|
+
* Extract model name and thinking status from request body.
|
|
1328
|
+
*
|
|
1329
|
+
* Thinking is considered active when:
|
|
1330
|
+
* - The client explicitly passes reasoning_effort / thinking_budget / thinking
|
|
1331
|
+
* - OR the backend will auto-inject thinking (default for all supported models)
|
|
1332
|
+
*
|
|
1333
|
+
* Since the proxy injects thinking for every model except those known to reject
|
|
1334
|
+
* it, we always mark thinking=true here. The `create-chat-completions` layer
|
|
1335
|
+
* will log the precise injection path separately.
|
|
1324
1336
|
*/
|
|
1325
|
-
async function
|
|
1337
|
+
async function extractModelInfo(c) {
|
|
1326
1338
|
try {
|
|
1327
|
-
|
|
1339
|
+
const body = await c.req.raw.clone().json();
|
|
1340
|
+
const clientThinking = Boolean(body.reasoning_effort) || Boolean(body.thinking_budget) || body.thinking?.type === "enabled";
|
|
1341
|
+
return {
|
|
1342
|
+
model: body.model,
|
|
1343
|
+
thinking: clientThinking || true
|
|
1344
|
+
};
|
|
1328
1345
|
} catch {
|
|
1329
|
-
return;
|
|
1346
|
+
return {};
|
|
1330
1347
|
}
|
|
1331
1348
|
}
|
|
1332
1349
|
/**
|
|
1333
|
-
* Custom logger middleware that shows model name before timestamp
|
|
1350
|
+
* Custom logger middleware that shows model name + thinking before timestamp
|
|
1334
1351
|
*
|
|
1335
1352
|
* Output format:
|
|
1336
|
-
* [model] HH:mm:ss <-- METHOD /path
|
|
1337
|
-
* [model] HH:mm:ss --> METHOD /path STATUS DURATION
|
|
1353
|
+
* [model thinking] HH:mm:ss <-- METHOD /path
|
|
1354
|
+
* [model thinking] HH:mm:ss --> METHOD /path STATUS DURATION
|
|
1338
1355
|
*/
|
|
1339
1356
|
function modelLogger() {
|
|
1340
1357
|
return async (c, next) => {
|
|
1341
1358
|
const method = c.req.method;
|
|
1342
1359
|
const fullPath = `${c.req.path}${c.req.raw.url.includes("?") ? `?${c.req.raw.url.split("?")[1]}` : ""}`;
|
|
1343
1360
|
let model;
|
|
1344
|
-
|
|
1345
|
-
|
|
1361
|
+
let thinking = false;
|
|
1362
|
+
if (method === "POST" && c.req.header("content-type")?.includes("json")) {
|
|
1363
|
+
const info = await extractModelInfo(c);
|
|
1364
|
+
model = info.model;
|
|
1365
|
+
thinking = info.thinking ?? false;
|
|
1366
|
+
}
|
|
1367
|
+
const modelPrefix = model ? `[${model}${thinking ? " thinking" : ""}] ` : "";
|
|
1346
1368
|
const startTime = getTime();
|
|
1347
1369
|
console.log(`${modelPrefix}${startTime} <-- ${method} ${fullPath}`);
|
|
1348
1370
|
const start = Date.now();
|
|
@@ -1719,6 +1741,50 @@ async function* wrapGeneratorWithRelease(gen, releaseSlot) {
|
|
|
1719
1741
|
* requests to that model skip the injection automatically.
|
|
1720
1742
|
*/
|
|
1721
1743
|
const reasoningUnsupportedModels = /* @__PURE__ */ new Set();
|
|
1744
|
+
/**
|
|
1745
|
+
* Compute an appropriate thinking_budget from model capabilities.
|
|
1746
|
+
* Returns undefined if the model does not support thinking.
|
|
1747
|
+
*/
|
|
1748
|
+
function getThinkingBudget(model) {
|
|
1749
|
+
if (!model) return void 0;
|
|
1750
|
+
const { supports, limits } = model.capabilities;
|
|
1751
|
+
const maxBudget = supports.max_thinking_budget;
|
|
1752
|
+
if (!maxBudget || maxBudget <= 0) return void 0;
|
|
1753
|
+
const maxOutput = limits.max_output_tokens ?? 0;
|
|
1754
|
+
const upperBound = Math.min(maxBudget, Math.max(maxOutput - 1, 0));
|
|
1755
|
+
const lowerBound = supports.min_thinking_budget ?? 1024;
|
|
1756
|
+
return Math.max(upperBound, lowerBound);
|
|
1757
|
+
}
|
|
1758
|
+
/**
|
|
1759
|
+
* Inject thinking parameters into the payload based on model capabilities.
|
|
1760
|
+
*
|
|
1761
|
+
* Strategy (in priority order):
|
|
1762
|
+
* 1. If the client already set reasoning_effort or thinking_budget → keep as-is
|
|
1763
|
+
* 2. If model capabilities declare max_thinking_budget → inject thinking_budget
|
|
1764
|
+
* 3. Otherwise → inject reasoning_effort="high" (works on claude-*-4.6)
|
|
1765
|
+
*
|
|
1766
|
+
* The fallback to reasoning_effort ensures thinking works even when the
|
|
1767
|
+
* /models endpoint doesn't expose thinking budget fields.
|
|
1768
|
+
*/
|
|
1769
|
+
function injectThinking(payload, resolvedModel) {
|
|
1770
|
+
if (payload.reasoning_effort || payload.thinking_budget) return payload;
|
|
1771
|
+
const budget = getThinkingBudget(findModel(resolvedModel));
|
|
1772
|
+
if (budget) return {
|
|
1773
|
+
...payload,
|
|
1774
|
+
thinking_budget: budget
|
|
1775
|
+
};
|
|
1776
|
+
if (!reasoningUnsupportedModels.has(resolvedModel)) return {
|
|
1777
|
+
...payload,
|
|
1778
|
+
reasoning_effort: "high"
|
|
1779
|
+
};
|
|
1780
|
+
return payload;
|
|
1781
|
+
}
|
|
1782
|
+
function logThinkingInjection(original, injected, resolvedModel) {
|
|
1783
|
+
if (original.reasoning_effort || original.thinking_budget) consola.debug(`Thinking: client-specified (reasoning_effort=${original.reasoning_effort ?? "none"} / thinking_budget=${original.thinking_budget ?? "none"})`);
|
|
1784
|
+
else if (injected.thinking_budget && injected.thinking_budget !== original.thinking_budget) consola.debug(`Thinking: injected thinking_budget=${injected.thinking_budget} for "${resolvedModel}"`);
|
|
1785
|
+
else if (injected.reasoning_effort === "high") consola.debug(`Thinking: injected reasoning_effort=high for "${resolvedModel}"`);
|
|
1786
|
+
else if (reasoningUnsupportedModels.has(resolvedModel)) consola.debug(`Thinking: skipped — "${resolvedModel}" does not support reasoning`);
|
|
1787
|
+
}
|
|
1722
1788
|
const createChatCompletions = async (payload) => {
|
|
1723
1789
|
const resolvedModel = modelRouter.resolveModel(payload.model);
|
|
1724
1790
|
const routedPayload = resolvedModel !== payload.model ? {
|
|
@@ -1726,11 +1792,9 @@ const createChatCompletions = async (payload) => {
|
|
|
1726
1792
|
model: resolvedModel
|
|
1727
1793
|
} : payload;
|
|
1728
1794
|
if (resolvedModel !== payload.model) consola.debug(`Model routed: ${payload.model} → ${resolvedModel}`);
|
|
1729
|
-
const
|
|
1730
|
-
const
|
|
1731
|
-
|
|
1732
|
-
...shouldInject && { reasoning_effort: "high" }
|
|
1733
|
-
};
|
|
1795
|
+
const thinkingPayload = injectThinking(routedPayload, resolvedModel);
|
|
1796
|
+
const wasInjected = thinkingPayload.reasoning_effort !== routedPayload.reasoning_effort || thinkingPayload.thinking_budget !== routedPayload.thinking_budget;
|
|
1797
|
+
logThinkingInjection(routedPayload, thinkingPayload, resolvedModel);
|
|
1734
1798
|
const releaseSlot = await modelRouter.acquireSlot(resolvedModel);
|
|
1735
1799
|
try {
|
|
1736
1800
|
const result = await dispatchRequest(thinkingPayload);
|
|
@@ -1738,7 +1802,7 @@ const createChatCompletions = async (payload) => {
|
|
|
1738
1802
|
releaseSlot();
|
|
1739
1803
|
return result;
|
|
1740
1804
|
} catch (error) {
|
|
1741
|
-
if (
|
|
1805
|
+
if (wasInjected && error instanceof HTTPError && error.response.status === 400 && error.message.includes("Unrecognized request argument")) {
|
|
1742
1806
|
reasoningUnsupportedModels.add(resolvedModel);
|
|
1743
1807
|
consola.info(`Model "${resolvedModel}" does not support reasoning_effort — disabled for future requests`);
|
|
1744
1808
|
return retryWithoutReasoning(routedPayload, releaseSlot);
|
|
@@ -2279,7 +2343,8 @@ function translateToOpenAI(payload) {
|
|
|
2279
2343
|
tools: translateAnthropicToolsToOpenAI(payload.tools),
|
|
2280
2344
|
tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),
|
|
2281
2345
|
...payload.thinking && { thinking: payload.thinking },
|
|
2282
|
-
...payload.thinking?.type === "enabled" && { reasoning_effort: "high" }
|
|
2346
|
+
...payload.thinking?.type === "enabled" && { reasoning_effort: "high" },
|
|
2347
|
+
...payload.thinking?.budget_tokens && { thinking_budget: payload.thinking.budget_tokens }
|
|
2283
2348
|
};
|
|
2284
2349
|
}
|
|
2285
2350
|
function translateModelName(model) {
|
|
@@ -2944,7 +3009,7 @@ async function validateGitHubToken(token) {
|
|
|
2944
3009
|
state.githubToken = token;
|
|
2945
3010
|
consola.info("Using provided GitHub token");
|
|
2946
3011
|
try {
|
|
2947
|
-
const { getGitHubUser } = await import("./get-user-
|
|
3012
|
+
const { getGitHubUser } = await import("./get-user-BTN_-eOk.js");
|
|
2948
3013
|
const user = await getGitHubUser();
|
|
2949
3014
|
consola.info(`Logged in as ${user.login}`);
|
|
2950
3015
|
} catch (error) {
|
|
@@ -2993,7 +3058,7 @@ async function runServer(options) {
|
|
|
2993
3058
|
const { HTTPError } = await import("./error-DLqcVQL_.js");
|
|
2994
3059
|
if (error instanceof HTTPError && error.response.status === 401) {
|
|
2995
3060
|
consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
|
|
2996
|
-
const { clearGithubToken } = await import("./token-
|
|
3061
|
+
const { clearGithubToken } = await import("./token-CxG7xLpI.js");
|
|
2997
3062
|
await clearGithubToken();
|
|
2998
3063
|
consola.info("Please restart to re-authenticate");
|
|
2999
3064
|
}
|