copilot-api-plus 1.0.40 → 1.0.41

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.
@@ -15,7 +15,7 @@ function getZenAuthPath() {
15
15
  async function saveZenAuth(auth) {
16
16
  await ensurePaths();
17
17
  const authPath = getZenAuthPath();
18
- await (await import("node:fs/promises")).writeFile(authPath, JSON.stringify(auth, null, 2), "utf-8");
18
+ await (await import("node:fs/promises")).writeFile(authPath, JSON.stringify(auth, null, 2), "utf8");
19
19
  consola.success("Zen API key saved to", authPath);
20
20
  }
21
21
  /**
@@ -30,7 +30,7 @@ async function loadZenAuth() {
30
30
  } catch {
31
31
  return null;
32
32
  }
33
- const content = await fs.readFile(authPath, "utf-8");
33
+ const content = await fs.readFile(authPath);
34
34
  return JSON.parse(content);
35
35
  } catch {
36
36
  return null;
@@ -74,4 +74,4 @@ async function setupZenApiKey(force = false) {
74
74
 
75
75
  //#endregion
76
76
  export { clearZenAuth, getZenAuthPath, loadZenAuth, saveZenAuth, setupZenApiKey };
77
- //# sourceMappingURL=auth-T55-Bhoo.js.map
77
+ //# sourceMappingURL=auth-BrdL89xk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-BrdL89xk.js","names":[],"sources":["../src/services/zen/auth.ts"],"sourcesContent":["/**\n * OpenCode Zen Authentication\n *\n * Handles API key authentication for OpenCode Zen.\n * API keys are created at https://opencode.ai/zen\n */\n\nimport consola from \"consola\"\n\nimport { PATHS, ensurePaths } from \"~/lib/paths\"\n\nexport interface ZenAuth {\n apiKey: string\n}\n\nconst ZEN_AUTH_FILENAME = \"zen-auth.json\"\n\n/**\n * Get the path to the Zen auth file\n */\nexport function getZenAuthPath(): string {\n return `${PATHS.DATA_DIR}/${ZEN_AUTH_FILENAME}`\n}\n\n/**\n * Save Zen API key to file\n */\nexport async function saveZenAuth(auth: ZenAuth): Promise<void> {\n await ensurePaths()\n const authPath = getZenAuthPath()\n const fs = await import(\"node:fs/promises\")\n await fs.writeFile(authPath, JSON.stringify(auth, null, 2), \"utf8\")\n consola.success(\"Zen API key saved to\", authPath)\n}\n\n/**\n * Load Zen API key from file\n */\nexport async function loadZenAuth(): Promise<ZenAuth | null> {\n try {\n const authPath = getZenAuthPath()\n const fs = await import(\"node:fs/promises\")\n\n // Check if file exists\n try {\n await fs.access(authPath)\n } catch {\n return null\n }\n\n const content = await fs.readFile(authPath)\n return JSON.parse(content) as ZenAuth\n } catch {\n return null\n }\n}\n\n/**\n * Clear Zen API key\n */\nexport async function clearZenAuth(): Promise<void> {\n try {\n const authPath = getZenAuthPath()\n const fs = await import(\"node:fs/promises\")\n await fs.unlink(authPath)\n consola.success(\"Zen API key cleared\")\n } catch {\n // File might not exist, ignore\n }\n}\n\n/**\n * Setup Zen API key interactively\n */\nexport async function setupZenApiKey(force = false): Promise<string> {\n const existingAuth = await loadZenAuth()\n\n if (existingAuth && !force) {\n consola.info(\"Using existing Zen API key\")\n return existingAuth.apiKey\n }\n\n consola.info(\"OpenCode Zen gives you access to all the best coding models\")\n consola.info(\"Get your API key at: https://opencode.ai/zen\")\n consola.info(\"\")\n\n const apiKey = await consola.prompt(\"Enter your OpenCode Zen API key:\", {\n type: \"text\",\n })\n\n if (!apiKey || typeof apiKey !== \"string\") {\n throw new Error(\"API key is required\")\n }\n\n // Validate the API key by fetching models\n try {\n const response = await fetch(\"https://opencode.ai/zen/v1/models\", {\n headers: {\n Authorization: `Bearer ${apiKey}`,\n },\n })\n\n if (!response.ok) {\n throw new Error(\n `Invalid API key: ${response.status} ${response.statusText}`,\n )\n }\n\n consola.success(\"API key validated successfully\")\n } catch (error) {\n consola.error(\"Failed to validate API key:\", error)\n throw error\n }\n\n await saveZenAuth({ apiKey })\n return apiKey\n}\n"],"mappings":";;;;AAeA,MAAM,oBAAoB;;;;AAK1B,SAAgB,iBAAyB;AACvC,QAAO,GAAG,MAAM,SAAS,GAAG;;;;;AAM9B,eAAsB,YAAY,MAA8B;AAC9D,OAAM,aAAa;CACnB,MAAM,WAAW,gBAAgB;AAEjC,QADW,MAAM,OAAO,qBACf,UAAU,UAAU,KAAK,UAAU,MAAM,MAAM,EAAE,EAAE,OAAO;AACnE,SAAQ,QAAQ,wBAAwB,SAAS;;;;;AAMnD,eAAsB,cAAuC;AAC3D,KAAI;EACF,MAAM,WAAW,gBAAgB;EACjC,MAAM,KAAK,MAAM,OAAO;AAGxB,MAAI;AACF,SAAM,GAAG,OAAO,SAAS;UACnB;AACN,UAAO;;EAGT,MAAM,UAAU,MAAM,GAAG,SAAS,SAAS;AAC3C,SAAO,KAAK,MAAM,QAAQ;SACpB;AACN,SAAO;;;;;;AAOX,eAAsB,eAA8B;AAClD,KAAI;EACF,MAAM,WAAW,gBAAgB;AAEjC,SADW,MAAM,OAAO,qBACf,OAAO,SAAS;AACzB,UAAQ,QAAQ,sBAAsB;SAChC;;;;;AAQV,eAAsB,eAAe,QAAQ,OAAwB;CACnE,MAAM,eAAe,MAAM,aAAa;AAExC,KAAI,gBAAgB,CAAC,OAAO;AAC1B,UAAQ,KAAK,6BAA6B;AAC1C,SAAO,aAAa;;AAGtB,SAAQ,KAAK,8DAA8D;AAC3E,SAAQ,KAAK,+CAA+C;AAC5D,SAAQ,KAAK,GAAG;CAEhB,MAAM,SAAS,MAAM,QAAQ,OAAO,oCAAoC,EACtE,MAAM,QACP,CAAC;AAEF,KAAI,CAAC,UAAU,OAAO,WAAW,SAC/B,OAAM,IAAI,MAAM,sBAAsB;AAIxC,KAAI;EACF,MAAM,WAAW,MAAM,MAAM,qCAAqC,EAChE,SAAS,EACP,eAAe,UAAU,UAC1B,EACF,CAAC;AAEF,MAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MACR,oBAAoB,SAAS,OAAO,GAAG,SAAS,aACjD;AAGH,UAAQ,QAAQ,iCAAiC;UAC1C,OAAO;AACd,UAAQ,MAAM,+BAA+B,MAAM;AACnD,QAAM;;AAGR,OAAM,YAAY,EAAE,QAAQ,CAAC;AAC7B,QAAO"}
@@ -1,4 +1,4 @@
1
1
  import "./paths-CVYLp61D.js";
2
- import { clearZenAuth, getZenAuthPath, loadZenAuth, saveZenAuth, setupZenApiKey } from "./auth-T55-Bhoo.js";
2
+ import { clearZenAuth, getZenAuthPath, loadZenAuth, saveZenAuth, setupZenApiKey } from "./auth-BrdL89xk.js";
3
3
 
4
4
  export { loadZenAuth, setupZenApiKey };
package/dist/main.js CHANGED
@@ -3,9 +3,9 @@ import { PATHS, ensurePaths } from "./paths-CVYLp61D.js";
3
3
  import { state } from "./state-CcLGr8VN.js";
4
4
  import { GITHUB_API_BASE_URL, copilotBaseUrl, copilotHeaders, githubHeaders } from "./get-user-BzIEATcF.js";
5
5
  import { HTTPError, forwardError } from "./error-CvU5otz-.js";
6
- import { cacheModels, cacheVSCodeVersion, clearGithubToken, isNullish, setupCopilotToken, setupGitHubToken, sleep } from "./token-ClgudjZm.js";
6
+ import { cacheModels, cacheVSCodeVersion, clearGithubToken, findModel, isNullish, setupCopilotToken, setupGitHubToken, sleep } from "./token-B777vbx8.js";
7
7
  import { clearAntigravityAuth, disableCurrentAccount, getAntigravityAuthPath, getApiKey, getCurrentProjectId, getValidAccessToken, rotateAccount } from "./auth-CWGl6kMf.js";
8
- import { clearZenAuth, getZenAuthPath } from "./auth-T55-Bhoo.js";
8
+ import { clearZenAuth, getZenAuthPath } from "./auth-BrdL89xk.js";
9
9
  import { getAntigravityModels, getAntigravityUsage, isThinkingModel } from "./get-models-uEbEgq0L.js";
10
10
  import { createRequire } from "node:module";
11
11
  import { defineCommand, runMain } from "citty";
@@ -2957,9 +2957,12 @@ const createChatCompletions = async (payload) => {
2957
2957
  //#region src/routes/chat-completions/handler.ts
2958
2958
  /**
2959
2959
  * Calculate token count, log it, and auto-truncate if needed.
2960
+ *
2961
+ * Uses multi-strategy exact matching via findModel() to handle
2962
+ * mismatches between requested and available model names.
2960
2963
  */
2961
2964
  async function processPayloadTokens(payload) {
2962
- const selectedModel = state.models?.data.find((model) => model.id === payload.model);
2965
+ const selectedModel = findModel(payload.model);
2963
2966
  if (!selectedModel) {
2964
2967
  consola.warn("No model selected, skipping token count calculation");
2965
2968
  return payload;
@@ -3085,14 +3088,6 @@ function translateModelName(model) {
3085
3088
  "claude-3-5-haiku": "claude-haiku-4.5",
3086
3089
  "claude-3-haiku": "claude-haiku-4.5"
3087
3090
  })) if (modelBase.startsWith(oldFormat) && supportedModels.includes(newFormat)) return newFormat;
3088
- let modelFamily = null;
3089
- if (model.includes("opus")) modelFamily = "opus";
3090
- else if (model.includes("sonnet")) modelFamily = "sonnet";
3091
- else if (model.includes("haiku")) modelFamily = "haiku";
3092
- if (modelFamily) {
3093
- const familyModel = supportedModels.find((m) => m.includes(modelFamily));
3094
- if (familyModel) return familyModel;
3095
- }
3096
3091
  return model;
3097
3092
  }
3098
3093
  function translateAnthropicMessagesToOpenAI(anthropicMessages, system) {
@@ -3260,16 +3255,21 @@ function getAnthropicToolUseBlocks(toolCalls) {
3260
3255
  //#endregion
3261
3256
  //#region src/routes/messages/count-tokens-handler.ts
3262
3257
  /**
3263
- * Handles token counting for Anthropic messages
3258
+ * Handles token counting for Anthropic messages.
3259
+ *
3260
+ * Uses multi-strategy model matching:
3261
+ * 1. findModel(translatedName) — translated Copilot name with format variants
3262
+ * 2. findModel(originalName) — original Anthropic name with format variants
3264
3263
  */
3265
3264
  async function handleCountTokens(c) {
3266
3265
  try {
3267
3266
  const anthropicBeta = c.req.header("anthropic-beta");
3268
3267
  const anthropicPayload = await c.req.json();
3269
3268
  const openAIPayload = translateToOpenAI(anthropicPayload);
3270
- const selectedModel = state.models?.data.find((model) => model.id === anthropicPayload.model);
3269
+ const translatedModelName = translateModelName(anthropicPayload.model);
3270
+ const selectedModel = findModel(translatedModelName) ?? findModel(anthropicPayload.model);
3271
3271
  if (!selectedModel) {
3272
- consola.warn("Model not found, returning default token count");
3272
+ consola.warn(`Model not found for "${anthropicPayload.model}" (translated: "${translatedModelName}"), returning default token count`);
3273
3273
  return c.json({ input_tokens: 1 });
3274
3274
  }
3275
3275
  const tokenCount = await getTokenCount(openAIPayload, selectedModel);
@@ -3420,9 +3420,12 @@ function translateChunkToAnthropicEvents(chunk, state$1) {
3420
3420
  //#region src/routes/messages/handler.ts
3421
3421
  /**
3422
3422
  * Auto-truncate OpenAI payload if prompt tokens exceed model limit.
3423
+ *
3424
+ * Uses multi-strategy exact matching via findModel() to handle
3425
+ * mismatches between Anthropic and Copilot model naming conventions.
3423
3426
  */
3424
3427
  async function autoTruncatePayload(payload) {
3425
- const selectedModel = state.models?.data.find((model) => model.id === payload.model);
3428
+ const selectedModel = findModel(payload.model);
3426
3429
  if (!selectedModel) {
3427
3430
  consola.warn("No model selected for Anthropic endpoint, skipping auto-truncation");
3428
3431
  return payload;
@@ -3982,7 +3985,7 @@ async function runServer(options$1) {
3982
3985
  state.zenApiKey = options$1.zenApiKey;
3983
3986
  consola.info("Using provided Zen API key");
3984
3987
  } else {
3985
- const { setupZenApiKey, loadZenAuth } = await import("./auth-CCwbOOQN.js");
3988
+ const { setupZenApiKey, loadZenAuth } = await import("./auth-pRwfByMF.js");
3986
3989
  const existingAuth = await loadZenAuth();
3987
3990
  if (existingAuth) {
3988
3991
  state.zenApiKey = existingAuth.apiKey;
@@ -4002,7 +4005,7 @@ async function runServer(options$1) {
4002
4005
  }
4003
4006
  if (hasApiKey()) {
4004
4007
  consola.info("Using Gemini API Key for authentication (from GEMINI_API_KEY)");
4005
- consola.info("API Key: " + getApiKey$1()?.slice(0, 10) + "...");
4008
+ consola.info(`API Key: ${getApiKey$1()?.slice(0, 10) ?? ""}...`);
4006
4009
  } else {
4007
4010
  const existingAuth = await loadAntigravityAuth();
4008
4011
  if (!existingAuth || existingAuth.accounts.length === 0) {
@@ -4048,7 +4051,7 @@ async function runServer(options$1) {
4048
4051
  const { HTTPError: HTTPError$1 } = await import("./error-CsShqJjE.js");
4049
4052
  if (error instanceof HTTPError$1 && error.response.status === 401) {
4050
4053
  consola.error("Failed to get Copilot token - GitHub token may be invalid or Copilot access revoked");
4051
- const { clearGithubToken: clearGithubToken$1 } = await import("./token-sYqHiHEd.js");
4054
+ const { clearGithubToken: clearGithubToken$1 } = await import("./token-CCg0yU7a.js");
4052
4055
  await clearGithubToken$1();
4053
4056
  consola.info("Please restart to re-authenticate");
4054
4057
  }