@nick3/copilot-api 1.10.8 → 1.10.9

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
@@ -435,7 +435,7 @@ The `<target>` can be either the account ID (GitHub login) or a 1-based index.
435
435
  - `temperature` (optional): Default temperature value used when the request does not specify one.
436
436
  - `topP` (optional): Default top_p value used when the request does not specify one.
437
437
  - `topK` (optional): Default top_k value used when the request does not specify one.
438
- - `extraBody` (optional): Dynamic fields merged into the upstream request body for that model. Request body fields with the same name take precedence. OpenAI-compatible providers can use this for fields such as `enable_thinking`, `preserve_thinking`, `reasoning_effort`.
438
+ - `extraBody` (optional): Dynamic fields merged into the upstream request body for that model. Request body fields with the same name take precedence. OpenAI-compatible providers can use this for fields such as `enable_thinking`, `preserve_thinking`, `reasoning_effort`. `thinking_budget` is a special OpenAI-compatible provider override: when configured in `extraBody`, it is forced after Anthropic `thinking.budget_tokens` translation and overrides the request-derived budget.
439
439
  - `contextCache` (optional): Defaults to `true` for OpenAI-compatible providers. This enables Alibaba Cloud Model Studio/DashScope explicit context cache by injecting `cache_control: { "type": "ephemeral" }` on up to 4 content blocks using the Context Cache format. The cache breakpoint strategy matches opencode's main provider flow: the first 2 system messages plus the last 2 non-system messages. Marked string content is converted to text content part arrays for `system` / `user` / `assistant` / `tool` messages; existing array content is marked on the last part. Set this to `false` when the model already supports implicit caching, or when the upstream does not accept this explicit-cache extension field.
440
440
  - `supportPdf` (optional): Controls whether the model supports PDF/document content. Defaults to `false`; unsupported PDFs are converted to a text notice. Set it to `true` to send PDF/document blocks as OpenAI Chat Completions file parts.
441
441
  - `toolContentSupportType` (optional): Tool result content capabilities for that model, as an array of `array`, `image`, and `pdf`. Provider routes default to string-only tool content when omitted. If `supportPdf` is `true` but this list does not include `pdf`, file parts in tool results are moved to user role messages. This provider default does not change the Copilot main flow, which continues to support array + image and not PDF.
package/README.zh-CN.md CHANGED
@@ -444,7 +444,7 @@ Copilot API 现在使用子命令结构,主要命令包括:
444
444
  - `temperature`:可选,当请求未指定时使用的默认温度。
445
445
  - `topP`:可选,当请求未指定时使用的默认 `top_p`。
446
446
  - `topK`:可选,当请求未指定时使用的默认 `top_k`。
447
- - `extraBody`:可选,按模型合入上游请求体的动态字段;请求体显式同名字段优先。OpenAI 兼容 provider 可用它配置 `enable_thinking`、`preserve_thinking`、`reasoning_effort` 等字段。
447
+ - `extraBody`:可选,按模型合入上游请求体的动态字段;请求体显式同名字段优先。OpenAI 兼容 provider 可用它配置 `enable_thinking`、`preserve_thinking`、`reasoning_effort` 等字段。`thinking_budget` 是 OpenAI 兼容 provider 的特殊覆盖项:配置在 `extraBody` 后,会在 Anthropic `thinking.budget_tokens` 翻译之后强制写入,并覆盖请求派生出的预算值。
448
448
  - `contextCache`:可选,OpenAI 兼容 provider 默认 `true`,用于启用阿里云百炼/DashScope 的显式缓存(explicit context cache),会按其 Context Cache 格式在最多 4 个 content block 上注入 `cache_control: { "type": "ephemeral" }`。缓存断点策略与 opencode 主链路保持一致:前 2 条 system 消息 + 最后 2 条非 system 消息。标记字符串 content 时会把 `system` / `user` / `assistant` / `tool` 消息转换为 text content part 数组;已有数组 content 则标记最后一个 part。如果模型本身已经支持隐式缓存,或上游不支持该显式缓存扩展字段,可在模型配置中设为 `false`。
449
449
  - `supportPdf`:可选,控制该模型是否支持 PDF/document content。默认 `false`,不支持时会把 PDF 转成提示文本;设为 `true` 时会把 PDF/document 转成 OpenAI Chat Completions 的 file part。
450
450
  - `toolContentSupportType`:可选,配置该模型的 tool result content 支持能力,值为 `array`、`image`、`pdf` 的数组。provider 侧未配置时默认只发送 string tool content。若 `supportPdf` 为 `true` 但这里不包含 `pdf`,tool result 里的 file part 会被转成 user role 消息。Copilot 主链路不使用这个 provider 默认,仍按 array + image 且不支持 PDF 的能力处理。
package/dist/main.js CHANGED
@@ -23,7 +23,7 @@ const { auth } = await import("./auth-B0y-2njL.js");
23
23
  const { checkUsage } = await import("./check-usage-DdevqHE5.js");
24
24
  const { debug } = await import("./debug-BMo6ltbp.js");
25
25
  const { mcp } = await import("./mcp-9Hgepkc5.js");
26
- const { start } = await import("./start-CtEoE2gt.js");
26
+ const { start } = await import("./start-DdrurmQ3.js");
27
27
  await runMain(defineCommand({
28
28
  meta: {
29
29
  name: "copilot-api",
@@ -6162,6 +6162,25 @@ const applyModelDefaults = (payload, modelConfig) => {
6162
6162
  const applyMissingExtraBody = (payload, options) => {
6163
6163
  for (const [key, value] of Object.entries(options.extraBody ?? {})) if (!Object.hasOwn(payload, key)) payload[key] = value;
6164
6164
  };
6165
+ const getRequestThinkingBudget = (payload) => {
6166
+ const budget = payload.thinking?.budget_tokens;
6167
+ if (typeof budget !== "number" || !Number.isFinite(budget)) return;
6168
+ return budget;
6169
+ };
6170
+ const applyOpenAICompatibleThinkingBudget = (payload, source) => {
6171
+ const thinkingBudget = getRequestThinkingBudget(source);
6172
+ if (thinkingBudget !== void 0) {
6173
+ payload.thinking_budget = thinkingBudget;
6174
+ return;
6175
+ }
6176
+ if (payload.thinking_budget === void 0) delete payload.thinking_budget;
6177
+ };
6178
+ const applyOpenAICompatibleExtraBodyThinkingBudget = (payload, options) => {
6179
+ const { extraBody } = options;
6180
+ if (!extraBody || !Object.hasOwn(extraBody, "thinking_budget")) return;
6181
+ const rawPayload = payload;
6182
+ rawPayload.thinking_budget = extraBody.thinking_budget;
6183
+ };
6165
6184
  const handleOpenAICompatibleProviderMessages = async (c, options) => {
6166
6185
  const { instrumentation, modelConfig, payload, provider, providerConfig } = options;
6167
6186
  const openAIPayload = createOpenAICompatiblePayload(payload, modelConfig);
@@ -6194,6 +6213,7 @@ const createOpenAICompatiblePayload = (payload, modelConfig) => {
6194
6213
  supportPdf: modelConfig?.supportPdf,
6195
6214
  toolContentSupportType: modelConfig?.toolContentSupportType ?? []
6196
6215
  });
6216
+ applyOpenAICompatibleThinkingBudget(openAIPayload, payload);
6197
6217
  if (payload.top_k !== void 0) openAIPayload.top_k = payload.top_k;
6198
6218
  if (openAIPayload.stream) openAIPayload.stream_options = { include_usage: true };
6199
6219
  normalizeOpenAICompatibleReasoningContent(openAIPayload);
@@ -6202,6 +6222,7 @@ const createOpenAICompatiblePayload = (payload, modelConfig) => {
6202
6222
  source: payload
6203
6223
  });
6204
6224
  applyMissingExtraBody(openAIPayload, { extraBody: modelConfig?.extraBody });
6225
+ applyOpenAICompatibleExtraBodyThinkingBudget(openAIPayload, { extraBody: modelConfig?.extraBody });
6205
6226
  if (!Object.hasOwn(openAIPayload, "parallel_tool_calls")) openAIPayload.parallel_tool_calls = true;
6206
6227
  if (modelConfig?.contextCache !== false) applyOpenAICompatibleContextCache(openAIPayload);
6207
6228
  return openAIPayload;
@@ -7370,6 +7391,8 @@ async function handleCompletion(c) {
7370
7391
  const upstreamRequestId = generateRequestIdFromPayload(anthropicPayload, sessionId);
7371
7392
  logger$3.debug("Generated request ID:", upstreamRequestId);
7372
7393
  const clientModel = anthropicPayload.model;
7394
+ anthropicPayload.model = resolveModelAlias(anthropicPayload.model);
7395
+ const routingModel = anthropicPayload.model;
7373
7396
  const streamRequested = Boolean(anthropicPayload.stream);
7374
7397
  const rawUserId = anthropicPayload.metadata?.user_id;
7375
7398
  const userId = typeof rawUserId === "string" ? rawUserId : void 0;
@@ -7401,9 +7424,9 @@ async function handleCompletion(c) {
7401
7424
  selectionReason: invalidSubagentMarkerSelectionReason
7402
7425
  });
7403
7426
  if (blockedResponse) return blockedResponse;
7404
- const endpointModel = findEndpointModel(clientModel);
7405
- const resolvedClientModel = endpointModel?.id ?? clientModel;
7406
- const affinityModelId = clientModel !== originalRequestModel ? findEndpointModel(originalRequestModel)?.id ?? originalRequestModel : void 0;
7427
+ const endpointModel = findEndpointModel(routingModel);
7428
+ const resolvedClientModel = endpointModel?.id ?? routingModel;
7429
+ const affinityModelId = routingModel !== originalRequestModel ? findEndpointModel(originalRequestModel)?.id ?? originalRequestModel : void 0;
7407
7430
  const useMessagesApi = isMessagesApiEnabled();
7408
7431
  const candidates = [];
7409
7432
  if (useMessagesApi) candidates.push({
@@ -8908,4 +8931,4 @@ server.route("/:provider/v1/models", providerModelRoutes);
8908
8931
  //#endregion
8909
8932
  export { server };
8910
8933
 
8911
- //# sourceMappingURL=server-DulP9mYd.js.map
8934
+ //# sourceMappingURL=server-GxNB5Syq.js.map