@jeffreycao/copilot-api 2.0.1 → 2.1.0

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
@@ -401,6 +401,11 @@ request_max_retries = 3
401
401
  stream_max_retries = 1
402
402
  stream_idle_timeout_ms = 300000
403
403
 
404
+ [features.code_mode]
405
+ excluded_tool_namespaces = [
406
+ "mcp__codex_apps__sites"
407
+ ]
408
+
404
409
  [features]
405
410
  remote_compaction_v2 = true
406
411
 
@@ -410,6 +415,8 @@ enabled = false
410
415
 
411
416
  > [!NOTE]
412
417
  > `name` must be set to `"OpenAI"`.
418
+ >
419
+ > For models that do not support `tool_search`, we recommend disabling `mcp__codex_apps__sites` by adding it to `features.code_mode.excluded_tool_namespaces` as shown above. Otherwise, each prompt may consume more than 10,000 additional tokens.
413
420
 
414
421
  When a Codex client (`User-Agent` starts with `codex`) requests the top-level `GET /v1/models`, the gateway merges native Codex models with models available through the Messages adapter. The latter advertise `use_responses_lite: true`: `/v1/responses` uses **Responses → Messages** for Anthropic providers, while OpenAI-compatible providers and Chat-only Copilot models reuse the existing Messages route for **Responses → Messages → Chat Completions**, then translate streaming or JSON results back to Responses.
415
422
 
package/README.zh-CN.md CHANGED
@@ -429,6 +429,11 @@ request_max_retries = 3
429
429
  stream_max_retries = 1
430
430
  stream_idle_timeout_ms = 300000
431
431
 
432
+ [features.code_mode]
433
+ excluded_tool_namespaces = [
434
+ "mcp__codex_apps__sites"
435
+ ]
436
+
432
437
  [features]
433
438
  remote_compaction_v2 = true
434
439
 
@@ -438,6 +443,8 @@ enabled = false
438
443
 
439
444
  > [!NOTE]
440
445
  > `name` 一定要配置为 `"OpenAI"`。
446
+ >
447
+ > 对于不支持 `tool_search` 的模型,建议按上面的配置将 `mcp__codex_apps__sites` 添加到 `features.code_mode.excluded_tool_namespaces` 中。否则每次提问可能会额外消耗 1 万多个 tokens。
441
448
 
442
449
  Codex 客户端(`User-Agent` 以 `codex` 开头)请求顶层 `GET /v1/models` 时,网关会把原生 Codex 模型与可通过 Messages 适配的模型合并返回。后者会声明 `use_responses_lite: true`:调用 `/v1/responses` 后,Anthropic provider 走 **Responses → Messages**,OpenAI 兼容 provider 以及只支持 Chat 的 Copilot 模型则复用现有 Messages 路由继续走 **Responses → Messages → Chat Completions**,最终统一翻译回 Responses(包括流式事件)。
443
450
 
package/dist/main.js CHANGED
@@ -25,7 +25,7 @@ bindElectronFetch();
25
25
  const { auth } = await import("./auth-DH-ThnhJ.js");
26
26
  const { debug } = await import("./debug-D2giR-Kj.js");
27
27
  const { mcp } = await import("./mcp-BG6fpi6q.js");
28
- const { start } = await import("./start-BZqWghY0.js");
28
+ const { start } = await import("./start-D3oRc7UM.js");
29
29
  await runMain(defineCommand({
30
30
  meta: {
31
31
  name: "copilot-api",
@@ -2562,9 +2562,11 @@ async function forwardCodexAlphaSearchRequest(request) {
2562
2562
  return createProviderProxyResponse(upstreamResponse);
2563
2563
  }
2564
2564
  function createAlphaSearchRequest(request, payload) {
2565
- return new Request(request, {
2565
+ return new Request(request.url, {
2566
2566
  body: JSON.stringify(payload),
2567
- method: "post"
2567
+ headers: request.headers,
2568
+ method: request.method,
2569
+ signal: request.signal
2568
2570
  });
2569
2571
  }
2570
2572
  async function handleCodexRequest(c, request, resolvedProviderConfig) {
@@ -2609,7 +2611,10 @@ async function handleAlphaSearchRequest(c, resolvedProviderConfig) {
2609
2611
  if (providerModelAlias.provider === "codex") return await handleCodexRequest(c, createAlphaSearchRequest(c.req.raw, payload));
2610
2612
  }
2611
2613
  if (isAlphaSearchCodexPriorityEnabled()) {
2612
- if (await resolveProviderConfig("codex")) return await forwardCodexAlphaSearchRequest(createAlphaSearchRequest(c.req.raw, payload));
2614
+ if (await resolveProviderConfig("codex")) {
2615
+ if (!payload.model.startsWith("gpt")) payload.model = "gpt-5.6-luna";
2616
+ return await forwardCodexAlphaSearchRequest(createAlphaSearchRequest(c.req.raw, payload));
2617
+ }
2613
2618
  }
2614
2619
  const messagesBackedModel = await isMessagesBackedModel(resolvedRequestedModel);
2615
2620
  if (messagesBackedModel) {
@@ -8134,6 +8139,7 @@ function translateResponsesToMessages(payload, options) {
8134
8139
  content: MESSAGES_COMPACTION_PROMPT
8135
8140
  });
8136
8141
  if (messages.length === 0) throw new ResponsesMessagesTranslationError("Responses input must contain at least one translatable message");
8142
+ applyEphemeralCacheControl(messages, system);
8137
8143
  const reasoningEffort = translateReasoningEffort(payload.reasoning?.effort);
8138
8144
  const messagesPayload = {
8139
8145
  model: options.model,
@@ -8660,6 +8666,24 @@ function resolveMetadataUserId(payload) {
8660
8666
  if (payload.safety_identifier?.trim()) return payload.safety_identifier;
8661
8667
  if (payload.prompt_cache_key?.trim()) return payload.prompt_cache_key;
8662
8668
  }
8669
+ const EPHEMERAL_CACHE_CONTROL = { type: "ephemeral" };
8670
+ function applyEphemeralCacheControl(messages, system) {
8671
+ const lastSystemBlock = system.at(-1);
8672
+ if (lastSystemBlock) lastSystemBlock.cache_control = { ...EPHEMERAL_CACHE_CONTROL };
8673
+ const lastMessage = messages.at(-1);
8674
+ if (!lastMessage) return;
8675
+ if (typeof lastMessage.content === "string") {
8676
+ lastMessage.content = [{
8677
+ type: "text",
8678
+ text: lastMessage.content,
8679
+ cache_control: { ...EPHEMERAL_CACHE_CONTROL }
8680
+ }];
8681
+ return;
8682
+ }
8683
+ const lastBlock = lastMessage.content.at(-1);
8684
+ if (!lastBlock || lastBlock.type === "thinking") return;
8685
+ lastBlock.cache_control = { ...EPHEMERAL_CACHE_CONTROL };
8686
+ }
8663
8687
  function appendAssistantBlock(messages, block) {
8664
8688
  const last = messages.at(-1);
8665
8689
  if (last?.role === "assistant" && Array.isArray(last.content)) {
@@ -8772,6 +8796,9 @@ var CustomToolInputStreamDecoder = class {
8772
8796
  prefixTokenOffset = 0;
8773
8797
  safeInputLength = 0;
8774
8798
  state = "prefix";
8799
+ trailingDepth = 0;
8800
+ trailingEscaped = false;
8801
+ trailingInString = false;
8775
8802
  unicodeDigitsRemaining = 0;
8776
8803
  append(partialJson) {
8777
8804
  if (this.failed) return this.fail("decoder is already in a failed state");
@@ -8807,8 +8834,42 @@ var CustomToolInputStreamDecoder = class {
8807
8834
  }
8808
8835
  if (this.state === "suffix") {
8809
8836
  if (isJsonWhitespace(char)) return;
8810
- if (char !== "}") return this.fail("expected \"}\" after the input string");
8811
- this.state = "done";
8837
+ if (char === "}") {
8838
+ this.state = "done";
8839
+ return;
8840
+ }
8841
+ if (char === ",") {
8842
+ this.state = "trailing";
8843
+ this.trailingDepth = 1;
8844
+ return;
8845
+ }
8846
+ return this.fail("expected \"}\" or \",\" after the input string");
8847
+ }
8848
+ if (this.state === "trailing") {
8849
+ if (this.trailingInString) {
8850
+ if (this.trailingEscaped) {
8851
+ this.trailingEscaped = false;
8852
+ return;
8853
+ }
8854
+ if (char === "\\") {
8855
+ this.trailingEscaped = true;
8856
+ return;
8857
+ }
8858
+ if (char === "\"") this.trailingInString = false;
8859
+ return;
8860
+ }
8861
+ if (char === "\"") {
8862
+ this.trailingInString = true;
8863
+ return;
8864
+ }
8865
+ if (char === "{" || char === "[") {
8866
+ this.trailingDepth += 1;
8867
+ return;
8868
+ }
8869
+ if (char === "}" || char === "]") {
8870
+ this.trailingDepth -= 1;
8871
+ if (this.trailingDepth === 0) this.state = "done";
8872
+ }
8812
8873
  return;
8813
8874
  }
8814
8875
  if (this.state === "done") {
@@ -8869,7 +8930,7 @@ function isJsonWhitespace(char) {
8869
8930
  }
8870
8931
  //#endregion
8871
8932
  //#region src/routes/responses/messages-stream-translation.ts
8872
- const EMPTY_SIGNATURE_ENCRYPTED_CONTENT = "Y29waWxvdC1hcGk6bWVzc2FnZXMtZW1wdHktc2lnbmF0dXJlOnYx";
8933
+ const EMPTY_SIGNATURE_ENCRYPTED_CONTENT = "";
8873
8934
  async function* translateMessagesStream(chunks, context) {
8874
8935
  const state = createTranslationState(context);
8875
8936
  try {
@@ -10062,4 +10123,4 @@ server.route("/:provider/images", providerImageRoutes);
10062
10123
  //#endregion
10063
10124
  export { server };
10064
10125
 
10065
- //# sourceMappingURL=server-BDdqK9ps.js.map
10126
+ //# sourceMappingURL=server-DcL9pgmS.js.map