@jeffreycao/copilot-api 1.10.6 → 1.10.8

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
@@ -363,7 +363,6 @@ The following command line options are available for the `start` command:
363
363
  "gpt-5.4-mini": "xhigh",
364
364
  "gpt-5.4": "xhigh"
365
365
  },
366
- "useFunctionApplyPatch": true,
367
366
  "useMessagesApi": true,
368
367
  "useResponsesApiWebSocket": true,
369
368
  "useResponsesApiWebSearch": true
@@ -390,7 +389,6 @@ The following command line options are available for the `start` command:
390
389
  - **smallModel:** Fallback model used for tool-less warmup messages (e.g., Claude Code probe requests) to avoid spending premium requests; defaults to gpt-5-mini.
391
390
  - **responsesApiContextManagementModels:** List of GPT model IDs that should receive Responses API `context_management` compaction instructions. This defaults to `[]`, so you need to opt in explicitly. A good starting point is `["gpt-5-mini", "gpt-5.3-codex", "gpt-5.4-mini", "gpt-5.4"]`. When enabled, the request includes `context_management` in the body and keeps only the latest compaction carrier on follow-up turns. The actual compaction is handled server-side and appears to begin when usage approaches roughly 90% of the model's `maxPromptTokens`, which makes it especially useful for long-running tasks without consuming additional premium requests. In practice, the effective `compact_threshold` also appears to be fixed on the server side, so changing it in this project does not currently alter compaction behavior. At the moment, this optimization is intended for GPT-family models only.
392
391
  - **modelReasoningEfforts:** Per-model `reasoning.effort` sent to the Copilot Responses API. Allowed values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. If a model isn’t listed, `high` is used by default.
393
- - **useFunctionApplyPatch:** When `true`, the server will convert any custom tool named `apply_patch` in Responses payloads into an OpenAI-style function tool (`type: "function"`) with a parameter schema so assistants can call it using function-calling semantics to edit files. Set to `false` to leave tools unchanged. Defaults to `true`.
394
392
  - **useMessagesApi:** When `true`, Claude-family models that support Copilot's native `/v1/messages` endpoint will use the Messages API; otherwise they fall back to `/chat/completions`. Set to `false` to disable Messages API routing and always use `/chat/completions`. Defaults to `true`.
395
393
  - **useResponsesApiWebSocket:** When `true`, Responses API requests use Copilot's websocket transport for models that advertise `ws:/responses`; models that only advertise `/responses` continue to use HTTP. Set to `false` to disable websocket routing and use HTTP `/responses` whenever the selected model supports it. Defaults to `true`.
396
394
  - **useResponsesApiWebSearch:** When `true`, the server keeps Responses API tools with `type: "web_search"` and forwards them upstream. Set to `false` to strip those tools from `/responses` payloads. Defaults to `true`.
@@ -609,7 +607,7 @@ Add the tool search bridge to the MCP config used by Claude Code:
609
607
  "tool_search": {
610
608
  "type": "stdio",
611
609
  "command": "npx",
612
- "args": ["@jeffreycao/copilot-api@latest", "mcp"]
610
+ "args": ["-y", "@jeffreycao/copilot-api@latest", "mcp"]
613
611
  }
614
612
  }
615
613
  }
@@ -622,7 +620,7 @@ Add the tool search bridge to the MCP config used by opencode:
622
620
  "mcp": {
623
621
  "tool_search": {
624
622
  "type": "local",
625
- "command": ["npx", "@jeffreycao/copilot-api@latest", "mcp"]
623
+ "command": ["npx", "-y", "@jeffreycao/copilot-api@latest", "mcp"]
626
624
  }
627
625
  }
628
626
  }
package/README.zh-CN.md CHANGED
@@ -367,7 +367,6 @@ Copilot API 现在使用子命令结构,主要命令包括:
367
367
  "gpt-5.4-mini": "xhigh",
368
368
  "gpt-5.4": "xhigh"
369
369
  },
370
- "useFunctionApplyPatch": true,
371
370
  "useMessagesApi": true,
372
371
  "useResponsesApiWebSocket": true,
373
372
  "useResponsesApiWebSearch": true
@@ -394,7 +393,6 @@ Copilot API 现在使用子命令结构,主要命令包括:
394
393
  - **smallModel:** 无工具预热消息的回退模型(例如 Claude Code 的探测请求),用于避免消耗 premium requests;默认是 `gpt-5-mini`。
395
394
  - **responsesApiContextManagementModels:** 需要启用 Responses API `context_management` 压缩指令的 GPT 模型 ID 列表。默认是 `[]`,需要你显式开启。一个不错的起点是 `["gpt-5-mini", "gpt-5.3-codex", "gpt-5.4-mini", "gpt-5.4"]`。启用后,请求体会带上 `context_management`,并在后续轮次中仅保留最新的压缩承载内容。实际压缩由服务端完成,看起来会在 usage 接近模型 `maxPromptTokens` 的约 90% 时开始,因此特别适合长任务场景,同时不会额外消耗 premium requests。实践中 `compact_threshold` 似乎也是服务端固定的,所以在本项目中修改它目前不会改变压缩行为。当前该优化仅面向 GPT 系模型。
396
395
  - **modelReasoningEfforts:** 按模型配置发送到 Copilot Responses API 的 `reasoning.effort`。可选值包括 `none`、`minimal`、`low`、`medium`、`high` 和 `xhigh`。若某模型未配置,则默认使用 `high`。
397
- - **useFunctionApplyPatch:** 当为 `true` 时,服务端会把 Responses payload 中任何名为 `apply_patch` 的自定义工具转换为 OpenAI 风格的函数工具(`type: "function"`),并附带参数 schema,从而让 assistant 可以通过 function-calling 语义调用它来编辑文件。若设为 `false`,则保持工具原样。默认值为 `true`。
398
396
  - **useMessagesApi:** 当为 `true` 时,支持 Copilot 原生 `/v1/messages` 的 Claude 系模型会走 Messages API;否则回退到 `/chat/completions`。设为 `false` 可禁用 Messages API 路由,始终使用 `/chat/completions`。默认值为 `true`。
399
397
  - **useResponsesApiWebSocket:** 当为 `true` 时,Responses API 请求会优先对声明了 `ws:/responses` 的模型使用 Copilot websocket transport;仅声明 `/responses` 的模型仍走 HTTP。设为 `false` 可禁用 websocket 路由,并在模型支持 `/responses` 时使用 HTTP `/responses`。默认值为 `true`。
400
398
  - **useResponsesApiWebSearch:** 当为 `true` 时,服务端会保留 Responses API 中 `type: "web_search"` 的工具并透传到上游。设为 `false` 则会从 `/responses` payload 中移除这些工具。默认值为 `true`。
@@ -615,7 +613,7 @@ GPT 模型不要设置 Claude Code 原生的 `ENABLE_TOOL_SEARCH`。这个开关
615
613
  "tool_search": {
616
614
  "type": "stdio",
617
615
  "command": "npx",
618
- "args": ["@jeffreycao/copilot-api@latest", "mcp"]
616
+ "args": ["-y", "@jeffreycao/copilot-api@latest", "mcp"]
619
617
  }
620
618
  }
621
619
  }
@@ -628,7 +626,7 @@ GPT 模型不要设置 Claude Code 原生的 `ENABLE_TOOL_SEARCH`。这个开关
628
626
  "mcp": {
629
627
  "tool_search": {
630
628
  "type": "local",
631
- "command": ["npx", "@jeffreycao/copilot-api@latest", "mcp"]
629
+ "command": ["npx", "-y", "@jeffreycao/copilot-api@latest", "mcp"]
632
630
  }
633
631
  }
634
632
  }
package/dist/main.js CHANGED
@@ -43,7 +43,7 @@ const { auth } = await import("./auth-BHa2OHXf.js");
43
43
  const { checkUsage } = await import("./check-usage-BdXGp1Wr.js");
44
44
  const { debug } = await import("./debug-C_TBkyUw.js");
45
45
  const { mcp } = await import("./mcp-CTb-DbQH.js");
46
- const { start } = await import("./start-DrAsrFFq.js");
46
+ const { start } = await import("./start-Bzfnxzlh.js");
47
47
  await runMain(defineCommand({
48
48
  meta: {
49
49
  name: "copilot-api",
@@ -50,7 +50,6 @@ const defaultConfig = {
50
50
  "gpt-5.4": "xhigh",
51
51
  "gpt-5.5": "xhigh"
52
52
  },
53
- useFunctionApplyPatch: true,
54
53
  useMessagesApi: true,
55
54
  useResponsesApiWebSocket: true,
56
55
  useResponsesApiWebSearch: true
@@ -350,4 +349,4 @@ function initProxyFromEnv() {
350
349
  //#endregion
351
350
  export { setModelMappings as _, getConfig as a, getProviderConfig as c, isMessagesApiEnabled as d, isResponsesApiContextManagementModel as f, resolveMappedModel as g, mergeConfigWithDefaults as h, getClaudeTokenMultiplier as i, getReasoningEffortForModel as l, isResponsesApiWebSocketEnabled as m, initProxyFromEnv as n, getExtraPromptForModel as o, isResponsesApiWebSearchEnabled as p, getAnthropicApiKey as r, getModelMappings as s, getProxyEnvDispatcher as t, getSmallModel as u };
352
351
 
353
- //# sourceMappingURL=proxy-CSO5SLia.js.map
352
+ //# sourceMappingURL=proxy-DvlF9a-7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-DvlF9a-7.js","names":["get"],"sources":["../src/lib/config.ts","../src/lib/proxy.ts"],"sourcesContent":["import consola from \"consola\"\nimport { randomBytes } from \"node:crypto\"\nimport fs from \"node:fs\"\n\nimport { PATHS } from \"./paths\"\n\nexport interface AppConfig {\n auth?: {\n apiKeys?: Array<string>\n adminApiKey?: string\n }\n providers?: Record<string, ProviderConfig>\n modelMappings?: Record<string, string>\n extraPrompts?: Record<string, string>\n smallModel?: string\n responsesApiContextManagementModels?: Array<string>\n modelReasoningEfforts?: Record<\n string,\n \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\"\n >\n useMessagesApi?: boolean\n useResponsesApiWebSocket?: boolean\n anthropicApiKey?: string\n useResponsesApiWebSearch?: boolean\n claudeTokenMultiplier?: number\n}\n\nexport interface ModelConfig {\n temperature?: number\n topP?: number\n topK?: number\n extraBody?: Record<string, unknown>\n contextCache?: boolean\n supportPdf?: boolean\n toolContentSupportType?: Array<ToolContentSupportType>\n}\n\nexport type ProviderAuthType = \"authorization\" | \"x-api-key\"\nexport type ProviderType = \"anthropic\" | \"openai-compatible\"\nexport type ToolContentSupportType = \"array\" | \"image\" | \"pdf\"\n\nexport interface ProviderConfig {\n type?: string\n enabled?: boolean\n baseUrl?: string\n apiKey?: string\n authType?: ProviderAuthType\n models?: Record<string, ModelConfig>\n adjustInputTokens?: boolean\n}\n\nexport interface ResolvedProviderConfig {\n name: string\n type: ProviderType\n baseUrl: string\n apiKey: string\n authType: ProviderAuthType\n models?: Record<string, ModelConfig>\n adjustInputTokens?: boolean\n}\n\nconst gpt5ExplorationPrompt = `## Exploration and reading files\n- **Think first.** Before any tool call, decide ALL files/resources you will need.\n- **Batch everything.** If you need multiple files (even from different places), read them together.\n- **multi_tool_use.parallel** Use multi_tool_use.parallel to parallelize tool calls and only this.\n- **Only make sequential calls if you truly cannot know the next file without seeing a result first.**\n- **Workflow:** (a) plan all needed reads → (b) issue one parallel batch → (c) analyze results → (d) repeat if new, unpredictable reads arise.`\n\nconst gpt5CommentaryPrompt = `# Working with the user\n\nYou interact with the user through a terminal. You have 2 ways of communicating with the users: \n- Share intermediary updates in \\`commentary\\` channel. \n- After you have completed all your work, send a message to the \\`final\\` channel. \n\n## Intermediary updates\n\n- Intermediary updates go to the \\`commentary\\` channel.\n- User updates are short updates while you are working, they are NOT final answers.\n- You use 1-2 sentence user updates to communicate progress and new information to the user as you are doing work.\n- Do not begin responses with conversational interjections or meta commentary. Avoid openers such as acknowledgements (“Done —”, “Got it”, “Great question, ”) or framing phrases.\n- You provide user updates frequently, every 20s.\n- Before exploring or doing substantial work, you start with a user update acknowledging the request and explaining your first step. You should include your understanding of the user request and explain what you will do. Avoid commenting on the request or using starters such as \"Got it -\" or \"Understood -\" etc.\n- When exploring, e.g. searching, reading files, you provide user updates as you go, every 20s, explaining what context you are gathering and what you've learned. Vary your sentence structure when providing these updates to avoid sounding repetitive - in particular, don't start each sentence the same way.\n- After you have sufficient context, and the work is substantial, you provide a longer plan (this is the only user update that may be longer than 2 sentences and can contain formatting).\n- Before performing file edits of any kind, you provide updates explaining what edits you are making.\n- As you are thinking, you very frequently provide updates even if not taking any actions, informing the user of your progress. You interrupt your thinking and send multiple updates in a row if thinking for more than 100 words.\n- Tone of your updates MUST match your personality.`\n\nconst defaultConfig: AppConfig = {\n auth: {\n apiKeys: [],\n },\n providers: {},\n modelMappings: {},\n extraPrompts: {\n \"gpt-5-mini\": gpt5ExplorationPrompt,\n \"gpt-5.3-codex\": gpt5CommentaryPrompt,\n \"gpt-5.4-mini\": gpt5CommentaryPrompt,\n \"gpt-5.4\": gpt5CommentaryPrompt,\n \"gpt-5.5\": gpt5CommentaryPrompt,\n },\n smallModel: \"gpt-5-mini\",\n responsesApiContextManagementModels: [],\n modelReasoningEfforts: {\n \"gpt-5-mini\": \"low\",\n \"gpt-5.3-codex\": \"xhigh\",\n \"gpt-5.4-mini\": \"xhigh\",\n \"gpt-5.4\": \"xhigh\",\n \"gpt-5.5\": \"xhigh\",\n },\n useMessagesApi: true,\n useResponsesApiWebSocket: true,\n useResponsesApiWebSearch: true,\n}\n\nlet cachedConfig: AppConfig | null = null\n\nfunction normalizeAdminApiKey(adminApiKey: unknown): string | null {\n if (typeof adminApiKey !== \"string\") {\n if (adminApiKey !== undefined) {\n consola.warn(\n \"Invalid auth.adminApiKey config. Expected a non-empty string.\",\n )\n }\n return null\n }\n\n const normalizedAdminApiKey = adminApiKey.trim()\n if (!normalizedAdminApiKey) {\n consola.warn(\n \"Invalid auth.adminApiKey config. Expected a non-empty string.\",\n )\n return null\n }\n\n return normalizedAdminApiKey\n}\n\nfunction generateAdminApiKey(): string {\n return randomBytes(32).toString(\"hex\")\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error\n}\n\nfunction ensureConfigFile(): void {\n try {\n fs.accessSync(PATHS.CONFIG_PATH, fs.constants.R_OK | fs.constants.W_OK)\n } catch {\n fs.mkdirSync(PATHS.APP_DIR, { recursive: true })\n fs.writeFileSync(\n PATHS.CONFIG_PATH,\n `${JSON.stringify(defaultConfig, null, 2)}\\n`,\n \"utf8\",\n )\n try {\n fs.chmodSync(PATHS.CONFIG_PATH, 0o600)\n } catch {\n return\n }\n }\n}\n\nfunction readConfigFromDisk(): AppConfig {\n ensureConfigFile()\n try {\n const raw = fs.readFileSync(PATHS.CONFIG_PATH, \"utf8\")\n if (!raw.trim()) {\n fs.writeFileSync(\n PATHS.CONFIG_PATH,\n `${JSON.stringify(defaultConfig, null, 2)}\\n`,\n \"utf8\",\n )\n return defaultConfig\n }\n return JSON.parse(raw) as AppConfig\n } catch (error) {\n consola.error(\"Failed to read config file, using default config\", error)\n return defaultConfig\n }\n}\n\nfunction readEditableConfigFromDisk(): AppConfig {\n try {\n const raw = fs.readFileSync(PATHS.CONFIG_PATH, \"utf8\")\n if (!raw.trim()) {\n return {}\n }\n return JSON.parse(raw) as AppConfig\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return {}\n }\n if (error instanceof SyntaxError) {\n throw new Error(`Config file is not valid JSON: ${PATHS.CONFIG_PATH}`)\n }\n throw error\n }\n}\n\nfunction writeConfigToDisk(config: AppConfig): void {\n fs.mkdirSync(PATHS.APP_DIR, { recursive: true })\n fs.writeFileSync(\n PATHS.CONFIG_PATH,\n `${JSON.stringify(config, null, 2)}\\n`,\n \"utf8\",\n )\n}\n\nfunction mergeDefaultConfig(config: AppConfig): {\n mergedConfig: AppConfig\n changed: boolean\n} {\n const extraPrompts = config.extraPrompts ?? {}\n const defaultExtraPrompts = defaultConfig.extraPrompts ?? {}\n const modelReasoningEfforts = config.modelReasoningEfforts ?? {}\n const defaultModelReasoningEfforts = defaultConfig.modelReasoningEfforts ?? {}\n\n const missingExtraPromptModels = Object.keys(defaultExtraPrompts).filter(\n (model) => !Object.hasOwn(extraPrompts, model),\n )\n\n const missingReasoningEffortModels = Object.keys(\n defaultModelReasoningEfforts,\n ).filter((model) => !Object.hasOwn(modelReasoningEfforts, model))\n\n const hasExtraPromptChanges = missingExtraPromptModels.length > 0\n const hasReasoningEffortChanges = missingReasoningEffortModels.length > 0\n\n if (!hasExtraPromptChanges && !hasReasoningEffortChanges) {\n return { mergedConfig: config, changed: false }\n }\n\n return {\n mergedConfig: {\n ...config,\n extraPrompts: {\n ...defaultExtraPrompts,\n ...extraPrompts,\n },\n modelReasoningEfforts: {\n ...defaultModelReasoningEfforts,\n ...modelReasoningEfforts,\n },\n },\n changed: true,\n }\n}\n\nfunction ensureAdminApiKey(config: AppConfig): {\n mergedConfig: AppConfig\n changed: boolean\n} {\n const normalizedAdminApiKey = normalizeAdminApiKey(config.auth?.adminApiKey)\n if (normalizedAdminApiKey) {\n if (config.auth?.adminApiKey === normalizedAdminApiKey) {\n return { mergedConfig: config, changed: false }\n }\n\n return {\n mergedConfig: {\n ...config,\n auth: {\n ...(config.auth ?? {}),\n adminApiKey: normalizedAdminApiKey,\n },\n },\n changed: true,\n }\n }\n\n const editableConfig = readEditableConfigFromDisk()\n const { mergedConfig } = mergeDefaultConfig({\n ...editableConfig,\n auth: {\n ...(editableConfig.auth ?? {}),\n adminApiKey: generateAdminApiKey(),\n },\n })\n\n return { mergedConfig, changed: true }\n}\n\nexport function mergeConfigWithDefaults(): AppConfig {\n const config = readConfigFromDisk()\n const { mergedConfig, changed } = mergeDefaultConfig(config)\n const {\n mergedConfig: mergedConfigWithAdminApiKey,\n changed: adminApiKeyChanged,\n } = ensureAdminApiKey(mergedConfig)\n const shouldPersistConfig = changed || adminApiKeyChanged\n\n if (shouldPersistConfig) {\n try {\n writeConfigToDisk(mergedConfigWithAdminApiKey)\n } catch (writeError) {\n if (adminApiKeyChanged) {\n throw writeError\n }\n\n consola.warn(\n \"Failed to write merged extraPrompts to config file\",\n writeError,\n )\n }\n }\n\n cachedConfig = mergedConfigWithAdminApiKey\n return mergedConfigWithAdminApiKey\n}\n\nexport function getConfig(): AppConfig {\n cachedConfig ??= mergeDefaultConfig(readConfigFromDisk()).mergedConfig\n return cachedConfig\n}\n\nexport function reloadConfig(): AppConfig {\n return mergeConfigWithDefaults()\n}\n\nexport function getExtraPromptForModel(model: string): string {\n const config = getConfig()\n return config.extraPrompts?.[model] ?? \"\"\n}\n\nexport function getModelMappings(): Record<string, string> {\n const config = getConfig()\n const modelMappings = config.modelMappings\n if (!modelMappings) {\n return { ...(defaultConfig.modelMappings ?? {}) }\n }\n\n const validMappings: Record<string, string> = {}\n for (const [sourceModel, targetModel] of Object.entries(modelMappings)) {\n if (\n !sourceModel\n || typeof targetModel !== \"string\"\n || targetModel.length === 0\n ) {\n continue\n }\n validMappings[sourceModel] = targetModel\n }\n\n return validMappings\n}\n\nfunction validateModelMappings(\n modelMappings: Record<string, string>,\n): Record<string, string> {\n const validatedMappings: Record<string, string> = {}\n for (const [sourceModel, targetModel] of Object.entries(modelMappings)) {\n if (!sourceModel || !targetModel) {\n throw new Error(\n \"Each model mapping must use non-empty source and target values.\",\n )\n }\n validatedMappings[sourceModel] = targetModel\n }\n\n return validatedMappings\n}\n\nexport function setModelMappings(\n modelMappings: Record<string, string>,\n): Record<string, string> {\n const nextConfig = {\n ...readEditableConfigFromDisk(),\n modelMappings: validateModelMappings(modelMappings),\n }\n\n writeConfigToDisk(nextConfig)\n cachedConfig = reloadConfig()\n return getModelMappings()\n}\n\nexport function resolveMappedModel(model: string): string {\n return getModelMappings()[model] ?? model\n}\n\nexport function getSmallModel(): string {\n const config = getConfig()\n return config.smallModel ?? \"gpt-5-mini\"\n}\n\nexport function getResponsesApiContextManagementModels(): Array<string> {\n const config = getConfig()\n return (\n config.responsesApiContextManagementModels\n ?? defaultConfig.responsesApiContextManagementModels\n ?? []\n )\n}\n\nexport function isResponsesApiContextManagementModel(model: string): boolean {\n return getResponsesApiContextManagementModels().includes(model)\n}\n\nexport function getReasoningEffortForModel(\n model: string,\n): \"none\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" {\n const config = getConfig()\n return config.modelReasoningEfforts?.[model] ?? \"high\"\n}\n\nexport function normalizeProviderBaseUrl(url: string): string {\n return url.trim().replace(/\\/+$/u, \"\")\n}\n\nfunction getDefaultProviderAuthType(\n providerType: ProviderType,\n): ProviderAuthType {\n return providerType === \"openai-compatible\" ? \"authorization\" : \"x-api-key\"\n}\n\nexport function resolveProviderAuthType(\n providerName: string,\n authType: string | undefined,\n providerType: ProviderType,\n): ProviderAuthType {\n if (authType === undefined) {\n return getDefaultProviderAuthType(providerType)\n }\n\n if (authType === \"x-api-key\") {\n return \"x-api-key\"\n }\n\n if (authType === \"authorization\") {\n return authType\n }\n\n consola.warn(\n `Provider ${providerName} has invalid authType '${authType}', falling back to ${getDefaultProviderAuthType(providerType)}`,\n )\n return getDefaultProviderAuthType(providerType)\n}\n\nexport function getProviderConfig(name: string): ResolvedProviderConfig | null {\n const providerName = name.trim()\n if (!providerName) {\n return null\n }\n\n const config = getConfig()\n const provider = config.providers?.[providerName]\n if (!provider) {\n return null\n }\n\n if (provider.enabled === false) {\n return null\n }\n\n const type = provider.type ?? \"anthropic\"\n if (type !== \"anthropic\" && type !== \"openai-compatible\") {\n consola.warn(\n `Provider ${providerName} is ignored because type '${type}' is not supported`,\n )\n return null\n }\n\n const baseUrl = normalizeProviderBaseUrl(provider.baseUrl ?? \"\")\n const apiKey = (provider.apiKey ?? \"\").trim()\n const authType = resolveProviderAuthType(\n providerName,\n provider.authType,\n type,\n )\n if (!baseUrl || !apiKey) {\n consola.warn(\n `Provider ${providerName} is enabled but missing baseUrl or apiKey`,\n )\n return null\n }\n\n return {\n name: providerName,\n type,\n baseUrl,\n apiKey,\n authType,\n models: provider.models,\n adjustInputTokens: provider.adjustInputTokens,\n }\n}\n\nexport function listEnabledProviders(): Array<string> {\n const config = getConfig()\n const providerNames = Object.keys(config.providers ?? {})\n return providerNames.filter((name) => getProviderConfig(name) !== null)\n}\n\nexport function isMessagesApiEnabled(): boolean {\n const config = getConfig()\n return config.useMessagesApi ?? true\n}\n\nexport function isResponsesApiWebSocketEnabled(): boolean {\n const config = getConfig()\n return config.useResponsesApiWebSocket ?? true\n}\n\nexport function getAnthropicApiKey(): string | undefined {\n const config = getConfig()\n return config.anthropicApiKey ?? process.env.ANTHROPIC_API_KEY ?? undefined\n}\n\nexport function isResponsesApiWebSearchEnabled(): boolean {\n const config = getConfig()\n return config.useResponsesApiWebSearch ?? true\n}\n\nexport function getClaudeTokenMultiplier(): number {\n const config = getConfig()\n return config.claudeTokenMultiplier ?? 1.15\n}\n","import consola from \"consola\"\nimport { getProxyForUrl } from \"proxy-from-env\"\nimport { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from \"undici\"\n\nlet proxyEnvDispatcher: Dispatcher | undefined\n\nexport function getProxyEnvDispatcher(): Dispatcher | undefined {\n return proxyEnvDispatcher\n}\n\nexport function initProxyFromEnv(): void {\n try {\n const direct = new Agent()\n const proxies = new Map<string, ProxyAgent>()\n\n // We only need a minimal dispatcher that implements `dispatch` at runtime.\n // Typing the object as `Dispatcher` forces TypeScript to require many\n // additional methods. Instead, keep a plain object and cast when passing\n // to `setGlobalDispatcher`.\n const dispatcher = {\n dispatch(\n options: Dispatcher.DispatchOptions,\n handler: Dispatcher.DispatchHandler,\n ) {\n try {\n const origin =\n typeof options.origin === \"string\" ?\n new URL(options.origin)\n : (options.origin as URL)\n const get = getProxyForUrl as unknown as (\n u: string,\n ) => string | undefined\n const raw = get(origin.toString())\n const proxyUrl = raw && raw.length > 0 ? raw : undefined\n if (!proxyUrl) {\n consola.debug(`HTTP proxy bypass: ${origin.hostname}`)\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n let agent = proxies.get(proxyUrl)\n if (!agent) {\n agent = new ProxyAgent(proxyUrl)\n proxies.set(proxyUrl, agent)\n }\n let label = proxyUrl\n try {\n const u = new URL(proxyUrl)\n label = `${u.protocol}//${u.host}`\n } catch {\n /* noop */\n }\n consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)\n return (agent as unknown as Dispatcher).dispatch(options, handler)\n } catch {\n return (direct as unknown as Dispatcher).dispatch(options, handler)\n }\n },\n close() {\n return direct.close()\n },\n destroy() {\n return direct.destroy()\n },\n }\n\n proxyEnvDispatcher = dispatcher as unknown as Dispatcher\n\n if (typeof Bun !== \"undefined\") {\n consola.debug(\"WebSocket proxy configured from environment (per-URL)\")\n return\n }\n\n setGlobalDispatcher(proxyEnvDispatcher)\n consola.debug(\"HTTP proxy configured from environment (per-URL)\")\n } catch (err) {\n consola.debug(\"Proxy setup skipped:\", err)\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { t as PATHS } from "./paths-DC-mqCY3.js";
2
2
  import { D as generateTraceId, E as prepareMessageProxyHeaders, I as state, M as compactMessageSections, O as requestContext, P as compactSystemPromptStarts, T as prepareInteractionHeaders, _ as copilotWebSocketHeaders, c as getUUID, d as sleep, f as getCopilotUsage, g as copilotHeaders, h as copilotBaseUrl, j as compactAutoContinuePromptStarts, k as resolveTraceId$1, l as isNullish, m as forwardError, n as cacheModels, o as generateRequestIdFromPayload, p as HTTPError, s as getRootSessionId, u as parseUserIdMetadata, w as prepareForCompact } from "./utils-jHLgqAq2.js";
3
3
  import { a as isDeferredToolName, c as parseMcpToolSearchSentinel, d as shouldEnableResponsesToolSearch, i as isBridgeToolSearchName, l as resolveBridgeToolSearchName, o as listDeferredToolNames, r as formatToolSearchBridgeArguments, s as normalizeToolSearchBridgeArguments, t as BRIDGE_TOOL_SEARCH_NAME, u as selectDeferredToolsByNames } from "./tool-search-D3SN0jX-.js";
4
- import { _ as setModelMappings, a as getConfig, c as getProviderConfig, d as isMessagesApiEnabled, f as isResponsesApiContextManagementModel, g as resolveMappedModel, i as getClaudeTokenMultiplier, l as getReasoningEffortForModel, m as isResponsesApiWebSocketEnabled, o as getExtraPromptForModel, p as isResponsesApiWebSearchEnabled, r as getAnthropicApiKey, s as getModelMappings, t as getProxyEnvDispatcher, u as getSmallModel } from "./proxy-CSO5SLia.js";
4
+ import { _ as setModelMappings, a as getConfig, c as getProviderConfig, d as isMessagesApiEnabled, f as isResponsesApiContextManagementModel, g as resolveMappedModel, i as getClaudeTokenMultiplier, l as getReasoningEffortForModel, m as isResponsesApiWebSocketEnabled, o as getExtraPromptForModel, p as isResponsesApiWebSearchEnabled, r as getAnthropicApiKey, s as getModelMappings, t as getProxyEnvDispatcher, u as getSmallModel } from "./proxy-DvlF9a-7.js";
5
5
  import consola from "consola";
6
6
  import fs from "node:fs/promises";
7
7
  import path from "node:path";
@@ -4080,6 +4080,25 @@ const IDE_EXECUTE_CODE_TOOL = "mcp__ide__executeCode";
4080
4080
  const IDE_GET_DIAGNOSTICS_TOOL = "mcp__ide__getDiagnostics";
4081
4081
  const IDE_GET_DIAGNOSTICS_DESCRIPTION = "Get language diagnostics from VS Code. Returns errors, warnings, information, and hints for files in the workspace.";
4082
4082
  const PDF_FILE_READ_PREFIX = "PDF file read:";
4083
+ const getBlockCacheControl = (block) => {
4084
+ if (!block || block.type === "thinking") return;
4085
+ const cacheControl = block.cache_control;
4086
+ if (!cacheControl || typeof cacheControl !== "object") return;
4087
+ return cacheControl;
4088
+ };
4089
+ const getLastMessageContentCacheControl = (lastMessage) => {
4090
+ if (!lastMessage || !Array.isArray(lastMessage.content)) return;
4091
+ const cacheControl = getBlockCacheControl(lastMessage.content.at(-1));
4092
+ return cacheControl ? { ...cacheControl } : void 0;
4093
+ };
4094
+ const applyLastMessageCacheControl = (anthropicPayload, lastMessageCacheControl) => {
4095
+ const cacheControl = lastMessageCacheControl ?? { type: "ephemeral" };
4096
+ const lastMessage = anthropicPayload.messages.at(-1);
4097
+ if (!lastMessage || !Array.isArray(lastMessage.content)) return;
4098
+ const lastBlock = lastMessage.content.at(-1);
4099
+ if (!lastBlock || lastBlock.type === "thinking" || lastBlock.cache_control) return;
4100
+ lastBlock.cache_control = { ...cacheControl };
4101
+ };
4083
4102
  const getCompactCandidateText = (message) => {
4084
4103
  if (message.role !== "user") return "";
4085
4104
  if (typeof message.content === "string") return message.content;
@@ -4112,7 +4131,7 @@ const mergeContentWithText = (tr, textBlock) => {
4112
4131
  if (hasToolRef(tr)) return tr;
4113
4132
  return {
4114
4133
  ...tr,
4115
- content: [...tr.content, textBlock]
4134
+ content: [...tr.content, stripContentBlockCacheControl(textBlock)]
4116
4135
  };
4117
4136
  };
4118
4137
  const mergeContentWithTexts = (tr, textBlocks) => {
@@ -4126,22 +4145,29 @@ const mergeContentWithTexts = (tr, textBlocks) => {
4126
4145
  if (hasToolRef(tr)) return tr;
4127
4146
  return {
4128
4147
  ...tr,
4129
- content: [...tr.content, ...textBlocks]
4148
+ content: [...tr.content, ...textBlocks.map(stripContentBlockCacheControl)]
4130
4149
  };
4131
4150
  };
4132
4151
  const mergeContentWithAttachments = (tr, attachments) => {
4152
+ const cleanAttachments = attachments.map(stripContentBlockCacheControl);
4133
4153
  if (typeof tr.content === "string") return {
4134
4154
  ...tr,
4135
4155
  content: [{
4136
4156
  type: "text",
4137
4157
  text: tr.content
4138
- }, ...attachments]
4158
+ }, ...cleanAttachments]
4139
4159
  };
4140
4160
  return {
4141
4161
  ...tr,
4142
- content: [...tr.content, ...attachments]
4162
+ content: [...tr.content, ...cleanAttachments]
4143
4163
  };
4144
4164
  };
4165
+ const stripContentBlockCacheControl = (block) => {
4166
+ if (!Object.hasOwn(block, "cache_control")) return block;
4167
+ const copy = { ...block };
4168
+ delete copy.cache_control;
4169
+ return copy;
4170
+ };
4145
4171
  const isAttachmentBlock = (block) => {
4146
4172
  return block.type === "image" || block.type === "document";
4147
4173
  };
@@ -4284,11 +4310,10 @@ const hasToolRef = (block) => {
4284
4310
  };
4285
4311
  const stripCacheControl = (payload) => {
4286
4312
  if (Array.isArray(payload.system)) for (const block of payload.system) {
4287
- const systemBlock = block;
4288
- const cacheControl = systemBlock.cache_control;
4313
+ const cacheControl = block.cache_control;
4289
4314
  if (cacheControl && typeof cacheControl === "object") {
4290
4315
  const { scope, ...rest } = cacheControl;
4291
- systemBlock.cache_control = rest;
4316
+ block.cache_control = rest;
4292
4317
  }
4293
4318
  }
4294
4319
  };
@@ -4618,8 +4643,10 @@ async function handleCompletion(c) {
4618
4643
  const noTools = !anthropicPayload.tools || anthropicPayload.tools.length === 0;
4619
4644
  if (anthropicBeta && noTools && compactType === 0) anthropicPayload.model = getSmallModel();
4620
4645
  if (compactType) logger$3.debug("Compact request type:", compactType);
4646
+ const lastMessageCacheControl = getLastMessageContentCacheControl(anthropicPayload.messages.at(-1));
4621
4647
  stripToolReferenceTurnBoundary(anthropicPayload);
4622
4648
  mergeToolResultForClaude(anthropicPayload, { skipLastMessage: compactType === 1 });
4649
+ applyLastMessageCacheControl(anthropicPayload, lastMessageCacheControl);
4623
4650
  const requestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
4624
4651
  logger$3.debug("Generated request ID:", requestId);
4625
4652
  if (state.manualApprove) await awaitApproval();
@@ -4788,7 +4815,6 @@ const logger$1 = createHandlerLogger("responses-handler");
4788
4815
  const responsesHandlerDependencies = {
4789
4816
  checkRateLimit,
4790
4817
  createResponses,
4791
- getConfig,
4792
4818
  isResponsesApiWebSearchEnabled
4793
4819
  };
4794
4820
  const handleResponses = async (c) => {
@@ -4804,7 +4830,6 @@ const handleResponses = async (c) => {
4804
4830
  fallbackSessionId: sessionId,
4805
4831
  model: payload.model
4806
4832
  });
4807
- useFunctionApplyPatch(payload);
4808
4833
  removeUnsupportedTools(payload);
4809
4834
  if (!responsesHandlerDependencies.isResponsesApiWebSearchEnabled()) removeWebSearchTool(payload);
4810
4835
  compactInputByLatestCompaction(payload);
@@ -4862,31 +4887,6 @@ const parseResponsesStreamEvent = (chunk) => {
4862
4887
  return null;
4863
4888
  }
4864
4889
  };
4865
- const useFunctionApplyPatch = (payload) => {
4866
- if (responsesHandlerDependencies.getConfig().useFunctionApplyPatch ?? true) {
4867
- logger$1.debug("Using function tool apply_patch for responses");
4868
- if (Array.isArray(payload.tools)) {
4869
- const toolsArr = payload.tools;
4870
- for (let i = 0; i < toolsArr.length; i++) {
4871
- const t = toolsArr[i];
4872
- if (t.type === "custom" && t.name === "apply_patch") toolsArr[i] = {
4873
- type: "function",
4874
- name: t.name,
4875
- description: "Use the `apply_patch` tool to edit files",
4876
- parameters: {
4877
- type: "object",
4878
- properties: { input: {
4879
- type: "string",
4880
- description: "The entire contents of the apply_patch command"
4881
- } },
4882
- required: ["input"]
4883
- },
4884
- strict: false
4885
- };
4886
- }
4887
- }
4888
- }
4889
- };
4890
4890
  const removeWebSearchTool = (payload) => {
4891
4891
  if (!Array.isArray(payload.tools) || payload.tools.length === 0) return;
4892
4892
  payload.tools = payload.tools.filter((t) => {
@@ -5019,4 +5019,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
5019
5019
  //#endregion
5020
5020
  export { server };
5021
5021
 
5022
- //# sourceMappingURL=server-BdTBue-4.js.map
5022
+ //# sourceMappingURL=server-BRFLAT4z.js.map