copilot-api-plus 1.0.52 → 1.0.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.md CHANGED
@@ -42,7 +42,7 @@
42
42
  | 🌐 **代理支持** | 支持 HTTP/HTTPS 代理,配置持久化 |
43
43
  | 🐳 **Docker 支持** | 提供完整的 Docker 部署方案 |
44
44
  | 🔑 **API Key 认证** | 可选的 API Key 鉴权,保护公开部署的服务 |
45
- | ✂️ **智能上下文压缩** | Prompt 超过模型 Token 限制时自动截断,保留系统消息和最近对话 |
45
+ | ✂️ **上下文透传** | 全量透传上下文至上游 API,由客户端(如 Claude Code)自行管理压缩 |
46
46
  | 🔍 **智能模型匹配** | 自动处理模型名格式差异(日期后缀、dash/dot 版本号等) |
47
47
  | 🔁 **Antigravity 端点容错** | 双端点自动切换,按模型族追踪速率限制,指数退避重试 |
48
48
 
@@ -648,14 +648,12 @@ curl http://localhost:4141/v1/messages \
648
648
 
649
649
  ## 🔧 技术细节
650
650
 
651
- ### 智能上下文压缩
651
+ ### 上下文管理
652
652
 
653
- Prompt Token 数量超过模型的上下文窗口限制时,代理层会自动截断消息以避免上游 API 返回 400 错误:
653
+ 代理层不做上下文截断,全量透传消息至上游 API。上下文压缩由客户端负责:
654
654
 
655
- - **保留系统/开发者消息**:system developer 角色的消息始终保留
656
- - **保留最近对话**:优先丢弃最早的消息,保留最近的上下文
657
- - **工具调用分组**:assistant 的 tool_calls 和对应的 tool result 消息作为一组,不会被拆散
658
- - **5% 安全余量**:实际限制为模型上下文窗口的 95%,避免边界情况
655
+ - **Claude Code**:通过 `/count_tokens` 端点获取当前 token 数,接近上限时自动触发 `/compact` 压缩
656
+ - **其他客户端**:如果上游 API 返回 400(token 超限),客户端自行处理重试
659
657
 
660
658
  ### 智能模型名匹配
661
659
 
@@ -680,20 +678,11 @@ Google Antigravity 模式内置了可靠性保障:
680
678
 
681
679
  ### 请求日志
682
680
 
683
- 每次 API 请求会输出一行日志,包含模型名、耗时和 token 用量:
681
+ 每次 API 请求会输出一行日志,包含模型名、状态码和耗时:
684
682
 
685
- ```
686
- [claude-opus-4-6] 13:13:39 --> POST /v1/messages?beta=true 200 20.1s [in:87356 out:171 cache_read:13016]
687
- ```
688
-
689
- - `in` — 输入 token 数(不含缓存命中部分)
690
- - `out` — 输出 token 数
691
- - `cache_read` — 缓存命中的 token 数(仅在有缓存时显示)
692
-
693
- 触发上下文压缩时会额外输出一行:
694
-
695
- ```
696
- Truncated: 190385 -> 117537 tokens (-59 msgs)
683
+ ```log
684
+ [claude-opus-4-6] 13:13:39 <-- POST /v1/messages?beta=true
685
+ [claude-opus-4-6] 13:13:59 --> POST /v1/messages?beta=true 200 20.1s
697
686
  ```
698
687
 
699
688
  ### 网络重试
@@ -0,0 +1,3 @@
1
+ import { HTTPError, forwardError } from "./error-CTmiDu8a.js";
2
+
3
+ export { HTTPError };
@@ -9,7 +9,6 @@ var HTTPError = class extends Error {
9
9
  }
10
10
  };
11
11
  async function forwardError(c, error) {
12
- consola.error("Error occurred:", error);
13
12
  if (error instanceof HTTPError) {
14
13
  let errorText;
15
14
  try {
@@ -17,18 +16,22 @@ async function forwardError(c, error) {
17
16
  } catch {
18
17
  errorText = error.message;
19
18
  }
20
- let errorJson;
21
- try {
22
- errorJson = JSON.parse(errorText);
23
- } catch {
24
- errorJson = errorText;
19
+ if (error.response.status === 400) {} else {
20
+ let errorJson;
21
+ try {
22
+ errorJson = JSON.parse(errorText);
23
+ } catch {
24
+ errorJson = errorText;
25
+ }
26
+ consola.error("Error occurred:", error);
27
+ consola.error("HTTP error:", errorJson);
25
28
  }
26
- consola.error("HTTP error:", errorJson);
27
29
  return c.json({ error: {
28
30
  message: errorText,
29
31
  type: "error"
30
32
  } }, error.response.status);
31
33
  }
34
+ consola.error("Error occurred:", error);
32
35
  return c.json({ error: {
33
36
  message: error.message,
34
37
  type: "error"
@@ -37,4 +40,4 @@ async function forwardError(c, error) {
37
40
 
38
41
  //#endregion
39
42
  export { HTTPError, forwardError };
40
- //# sourceMappingURL=error-SzJ4KHd8.js.map
43
+ //# sourceMappingURL=error-CTmiDu8a.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-CTmiDu8a.js","names":["errorText: string","errorJson: unknown"],"sources":["../src/lib/error.ts"],"sourcesContent":["import type { Context } from \"hono\"\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\"\n\nimport consola from \"consola\"\n\nexport class HTTPError extends Error {\n response: Response\n\n constructor(message: string, response: Response) {\n super(message)\n this.response = response\n }\n}\n\nexport async function forwardError(c: Context, error: unknown) {\n if (error instanceof HTTPError) {\n // Try to read error body, but it may already be consumed by the caller\n let errorText: string\n try {\n errorText = await error.response.text()\n } catch {\n // Body already read — fall back to the error message\n errorText = error.message\n }\n\n // 400 errors: concise log, already detailed upstream\n if (error.response.status === 400) {\n // no extra logging, upstream already printed details\n } else {\n let errorJson: unknown\n try {\n errorJson = JSON.parse(errorText)\n } catch {\n errorJson = errorText\n }\n consola.error(\"Error occurred:\", error)\n consola.error(\"HTTP error:\", errorJson)\n }\n\n return c.json(\n {\n error: {\n message: errorText,\n type: \"error\",\n },\n },\n error.response.status as ContentfulStatusCode,\n )\n }\n\n consola.error(\"Error occurred:\", error)\n return c.json(\n {\n error: {\n message: (error as Error).message,\n type: \"error\",\n },\n },\n 500,\n )\n}\n"],"mappings":";;;AAKA,IAAa,YAAb,cAA+B,MAAM;CACnC;CAEA,YAAY,SAAiB,UAAoB;AAC/C,QAAM,QAAQ;AACd,OAAK,WAAW;;;AAIpB,eAAsB,aAAa,GAAY,OAAgB;AAC7D,KAAI,iBAAiB,WAAW;EAE9B,IAAIA;AACJ,MAAI;AACF,eAAY,MAAM,MAAM,SAAS,MAAM;UACjC;AAEN,eAAY,MAAM;;AAIpB,MAAI,MAAM,SAAS,WAAW,KAAK,QAE5B;GACL,IAAIC;AACJ,OAAI;AACF,gBAAY,KAAK,MAAM,UAAU;WAC3B;AACN,gBAAY;;AAEd,WAAQ,MAAM,mBAAmB,MAAM;AACvC,WAAQ,MAAM,eAAe,UAAU;;AAGzC,SAAO,EAAE,KACP,EACE,OAAO;GACL,SAAS;GACT,MAAM;GACP,EACF,EACD,MAAM,SAAS,OAChB;;AAGH,SAAQ,MAAM,mBAAmB,MAAM;AACvC,QAAO,EAAE,KACP,EACE,OAAO;EACL,SAAU,MAAgB;EAC1B,MAAM;EACP,EACF,EACD,IACD"}
@@ -0,0 +1,5 @@
1
+ import "./state-CcLGr8VN.js";
2
+ import { getGitHubUser } from "./get-user-DOjM9pn9.js";
3
+ import "./error-CTmiDu8a.js";
4
+
5
+ export { getGitHubUser };
@@ -1,5 +1,5 @@
1
1
  import { state } from "./state-CcLGr8VN.js";
2
- import { HTTPError } from "./error-SzJ4KHd8.js";
2
+ import { HTTPError } from "./error-CTmiDu8a.js";
3
3
  import { randomUUID } from "node:crypto";
4
4
 
5
5
  //#region src/lib/api-config.ts
@@ -58,4 +58,4 @@ async function getGitHubUser() {
58
58
 
59
59
  //#endregion
60
60
  export { GITHUB_API_BASE_URL, GITHUB_APP_SCOPES, GITHUB_BASE_URL, GITHUB_CLIENT_ID, copilotBaseUrl, copilotHeaders, getGitHubUser, githubHeaders, standardHeaders };
61
- //# sourceMappingURL=get-user-DEDD9jIs.js.map
61
+ //# sourceMappingURL=get-user-DOjM9pn9.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-user-DEDD9jIs.js","names":["state","headers: Record<string, string>"],"sources":["../src/lib/api-config.ts","../src/services/github/get-user.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\n// Updated to match latest Zed implementation - 2025-05-01 returns Claude models\nconst API_VERSION = \"2025-05-01\"\n\n// Use the API endpoint from token response if available, otherwise fall back to default\nexport const copilotBaseUrl = (state: State) => {\n if (state.copilotApiEndpoint) {\n return state.copilotApiEndpoint\n }\n return state.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${state.accountType}.githubcopilot.com`\n}\nexport const copilotHeaders = (state: State, vision: boolean = false) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-panel\",\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 = (state: State) => ({\n ...standardHeaders(),\n authorization: `token ${state.githubToken}`,\n \"editor-version\": `vscode/${state.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 { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\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":";;;;;AAIA,MAAa,yBAAyB;CACpC,gBAAgB;CAChB,QAAQ;CACT;AAED,MAAM,kBAAkB;AACxB,MAAM,wBAAwB,gBAAgB;AAC9C,MAAM,aAAa,qBAAqB;AAGxC,MAAM,cAAc;AAGpB,MAAa,kBAAkB,YAAiB;AAC9C,KAAIA,QAAM,mBACR,QAAOA,QAAM;AAEf,QAAOA,QAAM,gBAAgB,eACzB,kCACA,eAAeA,QAAM,YAAY;;AAEvC,MAAa,kBAAkB,SAAc,SAAkB,UAAU;CACvE,MAAMC,UAAkC;EACtC,eAAe,UAAUD,QAAM;EAC/B,gBAAgB,iBAAiB,CAAC;EAClC,0BAA0B;EAC1B,kBAAkB,UAAUA,QAAM;EAClC,yBAAyB;EACzB,cAAc;EACd,iBAAiB;EACjB,wBAAwB;EACxB,gBAAgB,YAAY;EAC5B,uCAAuC;EACxC;AAED,KAAI,OAAQ,SAAQ,4BAA4B;AAEhD,QAAO;;AAGT,MAAa,sBAAsB;AACnC,MAAa,iBAAiB,aAAkB;CAC9C,GAAG,iBAAiB;CACpB,eAAe,SAASA,QAAM;CAC9B,kBAAkB,UAAUA,QAAM;CAClC,yBAAyB;CACzB,cAAc;CACd,wBAAwB;CACxB,uCAAuC;CACxC;AAED,MAAa,kBAAkB;AAC/B,MAAa,mBAAmB;AAChC,MAAa,oBAAoB,CAAC,YAAY,CAAC,KAAK,IAAI;;;;ACrDxD,eAAsB,gBAAgB;CACpC,MAAM,WAAW,MAAM,MAAM,GAAG,oBAAoB,QAAQ,EAC1D,SAAS;EACP,eAAe,SAAS,MAAM;EAC9B,GAAG,iBAAiB;EACrB,EACF,CAAC;AAEF,KAAI,CAAC,SAAS,GAAI,OAAM,IAAI,UAAU,6BAA6B,SAAS;AAE5E,QAAQ,MAAM,SAAS,MAAM"}
1
+ {"version":3,"file":"get-user-DOjM9pn9.js","names":["state","headers: Record<string, string>"],"sources":["../src/lib/api-config.ts","../src/services/github/get-user.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\"\n\nimport type { State } from \"./state\"\n\nexport const standardHeaders = () => ({\n \"content-type\": \"application/json\",\n accept: \"application/json\",\n})\n\nconst COPILOT_VERSION = \"0.26.7\"\nconst EDITOR_PLUGIN_VERSION = `copilot-chat/${COPILOT_VERSION}`\nconst USER_AGENT = `GitHubCopilotChat/${COPILOT_VERSION}`\n\n// Updated to match latest Zed implementation - 2025-05-01 returns Claude models\nconst API_VERSION = \"2025-05-01\"\n\n// Use the API endpoint from token response if available, otherwise fall back to default\nexport const copilotBaseUrl = (state: State) => {\n if (state.copilotApiEndpoint) {\n return state.copilotApiEndpoint\n }\n return state.accountType === \"individual\" ?\n \"https://api.githubcopilot.com\"\n : `https://api.${state.accountType}.githubcopilot.com`\n}\nexport const copilotHeaders = (state: State, vision: boolean = false) => {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${state.copilotToken}`,\n \"content-type\": standardHeaders()[\"content-type\"],\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-version\": `vscode/${state.vsCodeVersion}`,\n \"editor-plugin-version\": EDITOR_PLUGIN_VERSION,\n \"user-agent\": USER_AGENT,\n \"openai-intent\": \"conversation-panel\",\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 = (state: State) => ({\n ...standardHeaders(),\n authorization: `token ${state.githubToken}`,\n \"editor-version\": `vscode/${state.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 { GITHUB_API_BASE_URL, standardHeaders } from \"~/lib/api-config\"\nimport { HTTPError } from \"~/lib/error\"\nimport { state } from \"~/lib/state\"\n\nexport async function getGitHubUser() {\n const response = await fetch(`${GITHUB_API_BASE_URL}/user`, {\n headers: {\n authorization: `token ${state.githubToken}`,\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":";;;;;AAIA,MAAa,yBAAyB;CACpC,gBAAgB;CAChB,QAAQ;CACT;AAED,MAAM,kBAAkB;AACxB,MAAM,wBAAwB,gBAAgB;AAC9C,MAAM,aAAa,qBAAqB;AAGxC,MAAM,cAAc;AAGpB,MAAa,kBAAkB,YAAiB;AAC9C,KAAIA,QAAM,mBACR,QAAOA,QAAM;AAEf,QAAOA,QAAM,gBAAgB,eACzB,kCACA,eAAeA,QAAM,YAAY;;AAEvC,MAAa,kBAAkB,SAAc,SAAkB,UAAU;CACvE,MAAMC,UAAkC;EACtC,eAAe,UAAUD,QAAM;EAC/B,gBAAgB,iBAAiB,CAAC;EAClC,0BAA0B;EAC1B,kBAAkB,UAAUA,QAAM;EAClC,yBAAyB;EACzB,cAAc;EACd,iBAAiB;EACjB,wBAAwB;EACxB,gBAAgB,YAAY;EAC5B,uCAAuC;EACxC;AAED,KAAI,OAAQ,SAAQ,4BAA4B;AAEhD,QAAO;;AAGT,MAAa,sBAAsB;AACnC,MAAa,iBAAiB,aAAkB;CAC9C,GAAG,iBAAiB;CACpB,eAAe,SAASA,QAAM;CAC9B,kBAAkB,UAAUA,QAAM;CAClC,yBAAyB;CACzB,cAAc;CACd,wBAAwB;CACxB,uCAAuC;CACxC;AAED,MAAa,kBAAkB;AAC/B,MAAa,mBAAmB;AAChC,MAAa,oBAAoB,CAAC,YAAY,CAAC,KAAK,IAAI;;;;ACrDxD,eAAsB,gBAAgB;CACpC,MAAM,WAAW,MAAM,MAAM,GAAG,oBAAoB,QAAQ,EAC1D,SAAS;EACP,eAAe,SAAS,MAAM;EAC9B,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,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { PATHS, ensurePaths } from "./paths-CVYLp61D.js";
3
3
  import { state } from "./state-CcLGr8VN.js";
4
- import { GITHUB_API_BASE_URL, copilotBaseUrl, copilotHeaders, githubHeaders } from "./get-user-DEDD9jIs.js";
5
- import { HTTPError, forwardError } from "./error-SzJ4KHd8.js";
6
- import { cacheModels, cacheVSCodeVersion, clearGithubToken, findModel, isNullish, refreshCopilotToken, setupCopilotToken, setupGitHubToken, sleep } from "./token-CpxbiiIw.js";
4
+ import { GITHUB_API_BASE_URL, copilotBaseUrl, copilotHeaders, githubHeaders } from "./get-user-DOjM9pn9.js";
5
+ import { HTTPError, forwardError } from "./error-CTmiDu8a.js";
6
+ import { cacheModels, cacheVSCodeVersion, clearGithubToken, findModel, isNullish, refreshCopilotToken, setupCopilotToken, setupGitHubToken, sleep } from "./token-CnocHC_C.js";
7
7
  import { clearAntigravityAuth, disableCurrentAccount, getAntigravityAuthPath, getApiKey, getCurrentProjectId, getValidAccessToken, rotateAccount } from "./auth-CWGl6kMf.js";
8
8
  import { clearZenAuth, getZenAuthPath } from "./auth-BrdL89xk.js";
9
9
  import { getAntigravityModels, getAntigravityUsage, isThinkingModel } from "./get-models-uEbEgq0L.js";
@@ -1194,27 +1194,6 @@ const apiKeyAuthMiddleware = async (c, next) => {
1194
1194
  //#endregion
1195
1195
  //#region src/lib/model-logger.ts
1196
1196
  /**
1197
- * Global token usage store for passing usage info from handlers to logger.
1198
- * Handlers call setTokenUsage() when usage is available,
1199
- * logger reads and clears it after await next().
1200
- *
1201
- * For streaming responses, usage arrives after next() returns.
1202
- * In that case the handler calls signalStreamDone() when the stream ends,
1203
- * and the logger waits for it with a timeout.
1204
- */
1205
- let pendingTokenUsage;
1206
- let streamDoneResolve;
1207
- function setTokenUsage(usage) {
1208
- pendingTokenUsage = usage;
1209
- }
1210
- /**
1211
- * Notify the logger that a streaming response has finished sending.
1212
- * Must be called at the end of streamSSE callbacks.
1213
- */
1214
- function signalStreamDone() {
1215
- streamDoneResolve?.();
1216
- }
1217
- /**
1218
1197
  * Get timestamp string in format HH:mm:ss
1219
1198
  */
1220
1199
  function getTime() {
@@ -1228,15 +1207,6 @@ function formatDuration(ms) {
1228
1207
  return `${(ms / 1e3).toFixed(1)}s`;
1229
1208
  }
1230
1209
  /**
1231
- * Format token usage for log output
1232
- */
1233
- function formatTokenUsage(usage) {
1234
- const parts = [`in:${usage.inputTokens}`, `out:${usage.outputTokens}`];
1235
- if (usage.cacheReadTokens) parts.push(`cache_read:${usage.cacheReadTokens}`);
1236
- if (usage.cacheCreationTokens) parts.push(`cache_create:${usage.cacheCreationTokens}`);
1237
- return parts.join(" ");
1238
- }
1239
- /**
1240
1210
  * Extract model name from request body
1241
1211
  */
1242
1212
  async function extractModel(c) {
@@ -1251,7 +1221,7 @@ async function extractModel(c) {
1251
1221
  *
1252
1222
  * Output format:
1253
1223
  * [model] HH:mm:ss <-- METHOD /path
1254
- * [model] HH:mm:ss --> METHOD /path STATUS DURATION [in:N out:N]
1224
+ * [model] HH:mm:ss --> METHOD /path STATUS DURATION
1255
1225
  */
1256
1226
  function modelLogger() {
1257
1227
  return async (c, next) => {
@@ -1263,23 +1233,12 @@ function modelLogger() {
1263
1233
  if (method === "POST" && c.req.header("content-type")?.includes("json")) model = await extractModel(c);
1264
1234
  const modelPrefix = model ? `[${model}] ` : "";
1265
1235
  const startTime = getTime();
1266
- pendingTokenUsage = void 0;
1267
- const localStreamDone = new Promise((resolve) => {
1268
- streamDoneResolve = resolve;
1269
- });
1270
1236
  console.log(`${modelPrefix}${startTime} <-- ${method} ${fullPath}`);
1271
1237
  const start$1 = Date.now();
1272
1238
  await next();
1273
- if (c.res.headers.get("content-type")?.includes("text/event-stream") && !pendingTokenUsage) {
1274
- const timeout = new Promise((resolve) => setTimeout(resolve, 12e4));
1275
- await Promise.race([localStreamDone, timeout]);
1276
- }
1277
1239
  const duration = Date.now() - start$1;
1278
1240
  const endTime = getTime();
1279
- const usage = pendingTokenUsage;
1280
- pendingTokenUsage = void 0;
1281
- const usageSuffix = usage ? ` [${formatTokenUsage(usage)}]` : "";
1282
- console.log(`${modelPrefix}${endTime} --> ${method} ${fullPath} ${c.res.status} ${formatDuration(duration)}${usageSuffix}`);
1241
+ console.log(`${modelPrefix}${endTime} --> ${method} ${fullPath} ${c.res.status} ${formatDuration(duration)}`);
1283
1242
  };
1284
1243
  }
1285
1244
 
@@ -2688,7 +2647,8 @@ const createChatCompletions = async (payload) => {
2688
2647
  }
2689
2648
  if (!response.ok) {
2690
2649
  const errorBody = await response.text();
2691
- consola.error("Failed to create chat completions", {
2650
+ if (response.status === 400) consola.warn(`400: ${errorBody}`);
2651
+ else consola.error("Failed to create chat completions", {
2692
2652
  status: response.status,
2693
2653
  statusText: response.statusText,
2694
2654
  body: errorBody
@@ -2727,34 +2687,14 @@ async function handleCompletion$1(c) {
2727
2687
  const response = await createChatCompletions(payload);
2728
2688
  if (isNonStreaming$1(response)) {
2729
2689
  consola.debug("Non-streaming response:", JSON.stringify(response));
2730
- if (response.usage) setTokenUsage({
2731
- inputTokens: response.usage.prompt_tokens,
2732
- outputTokens: response.usage.completion_tokens,
2733
- cacheReadTokens: response.usage.prompt_tokens_details?.cached_tokens
2734
- });
2735
2690
  return c.json(response);
2736
2691
  }
2737
2692
  consola.debug("Streaming response");
2738
2693
  return streamSSE(c, async (stream) => {
2739
2694
  for await (const chunk of response) {
2740
2695
  consola.debug("Streaming chunk:", JSON.stringify(chunk));
2741
- try {
2742
- const sseChunk = chunk;
2743
- if (sseChunk.data && sseChunk.data !== "[DONE]") {
2744
- const parsed = JSON.parse(sseChunk.data);
2745
- if (parsed.usage) {
2746
- const usage = {
2747
- inputTokens: parsed.usage.prompt_tokens ?? 0,
2748
- outputTokens: parsed.usage.completion_tokens ?? 0,
2749
- cacheReadTokens: parsed.usage.prompt_tokens_details?.cached_tokens
2750
- };
2751
- setTokenUsage(usage);
2752
- }
2753
- }
2754
- } catch {}
2755
2696
  await stream.writeSSE(chunk);
2756
2697
  }
2757
- signalStreamDone();
2758
2698
  });
2759
2699
  }
2760
2700
  const isNonStreaming$1 = (response) => Object.hasOwn(response, "choices");
@@ -3372,12 +3312,6 @@ async function handleCompletion(c) {
3372
3312
  const response = await createChatCompletions(openAIPayload);
3373
3313
  if (isNonStreaming(response)) {
3374
3314
  const anthropicResponse = translateToAnthropic(response);
3375
- setTokenUsage({
3376
- inputTokens: anthropicResponse.usage.input_tokens,
3377
- outputTokens: anthropicResponse.usage.output_tokens,
3378
- cacheReadTokens: anthropicResponse.usage.cache_read_input_tokens,
3379
- cacheCreationTokens: anthropicResponse.usage.cache_creation_input_tokens
3380
- });
3381
3315
  return c.json(anthropicResponse);
3382
3316
  }
3383
3317
  return streamSSE(c, async (stream) => {
@@ -3392,20 +3326,11 @@ async function handleCompletion(c) {
3392
3326
  if (!rawEvent.data) continue;
3393
3327
  const chunk = JSON.parse(rawEvent.data);
3394
3328
  const events$1 = translateChunkToAnthropicEvents(chunk, streamState);
3395
- if (chunk.usage) {
3396
- const usage = {
3397
- inputTokens: chunk.usage.prompt_tokens - (chunk.usage.prompt_tokens_details?.cached_tokens ?? 0),
3398
- outputTokens: chunk.usage.completion_tokens,
3399
- cacheReadTokens: chunk.usage.prompt_tokens_details?.cached_tokens
3400
- };
3401
- setTokenUsage(usage);
3402
- }
3403
3329
  for (const event of events$1) await stream.writeSSE({
3404
3330
  event: event.type,
3405
3331
  data: JSON.stringify(event)
3406
3332
  });
3407
3333
  }
3408
- signalStreamDone();
3409
3334
  });
3410
3335
  }
3411
3336
  const isNonStreaming = (response) => Object.hasOwn(response, "choices");
@@ -3978,7 +3903,7 @@ async function runServer(options$1) {
3978
3903
  state.githubToken = options$1.githubToken;
3979
3904
  consola.info("Using provided GitHub token");
3980
3905
  try {
3981
- const { getGitHubUser } = await import("./get-user-HhhC3uQr.js");
3906
+ const { getGitHubUser } = await import("./get-user-D1SF4af1.js");
3982
3907
  const user = await getGitHubUser();
3983
3908
  consola.info(`Logged in as ${user.login}`);
3984
3909
  } catch (error) {
@@ -3989,10 +3914,10 @@ async function runServer(options$1) {
3989
3914
  try {
3990
3915
  await setupCopilotToken();
3991
3916
  } catch (error) {
3992
- const { HTTPError: HTTPError$1 } = await import("./error-DNWWcl_s.js");
3917
+ const { HTTPError: HTTPError$1 } = await import("./error-CBKWgD6B.js");
3993
3918
  if (error instanceof HTTPError$1 && error.response.status === 401) {
3994
3919
  consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
3995
- const { clearGithubToken: clearGithubToken$1 } = await import("./token-DkNaoDp7.js");
3920
+ const { clearGithubToken: clearGithubToken$1 } = await import("./token-2K-Nf49r.js");
3996
3921
  await clearGithubToken$1();
3997
3922
  consola.info("Please restart to re-authenticate");
3998
3923
  }