@jeffreycao/copilot-api 2.1.5 → 2.1.7
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 +3 -1
- package/README.zh-CN.md +3 -1
- package/dist/main.js +1 -1
- package/dist/{server-DyVtfan1.js → server-s6RzK7Oo.js} +27 -16
- package/dist/server-s6RzK7Oo.js.map +1 -0
- package/dist/{start-DzKOeRTn.js → start-D5W3xtWv.js} +2 -2
- package/dist/{start-DzKOeRTn.js.map → start-D5W3xtWv.js.map} +1 -1
- package/package.json +1 -1
- package/dist/server-DyVtfan1.js.map +0 -1
package/README.md
CHANGED
|
@@ -398,7 +398,7 @@ requires_openai_auth = true
|
|
|
398
398
|
supports_websockets = false
|
|
399
399
|
wire_api = "responses"
|
|
400
400
|
request_max_retries = 3
|
|
401
|
-
stream_max_retries =
|
|
401
|
+
stream_max_retries = 3
|
|
402
402
|
stream_idle_timeout_ms = 300000
|
|
403
403
|
|
|
404
404
|
[features]
|
|
@@ -417,6 +417,8 @@ enabled = false
|
|
|
417
417
|
|
|
418
418
|
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.
|
|
419
419
|
|
|
420
|
+
For Codex clients, only `gpt-*` Copilot models use the native Responses API; non-GPT Copilot models always go through the adapter, even when they advertise native `/responses` support.
|
|
421
|
+
|
|
420
422
|
Responses Lite tool definitions are read from `input.additional_tools`, without relying on top-level `tools`. Function, `namespace`, and custom tools are supported; clients must declare `apply_patch` as `type: "custom"`, and it is not handled as a standalone special tool type. Returned calls recover their original `name` and `namespace`. Tools are collected before old history is trimmed, so compaction requests retain them. The Messages fallback does not support Responses `tool_search` mode. Anthropic `output_config.effort` keeps the project's existing valid levels; Responses `minimal` maps to `low`, while `none` omits Anthropic effort.
|
|
421
423
|
|
|
422
424
|
When Codex uses the top-level GitHub Copilot route with `approvals_reviewer = "auto_review"`, map its internal review model to a Responses-capable Copilot model in the gateway's `config.json`:
|
package/README.zh-CN.md
CHANGED
|
@@ -426,7 +426,7 @@ requires_openai_auth = true
|
|
|
426
426
|
supports_websockets = false
|
|
427
427
|
wire_api = "responses"
|
|
428
428
|
request_max_retries = 3
|
|
429
|
-
stream_max_retries =
|
|
429
|
+
stream_max_retries = 3
|
|
430
430
|
stream_idle_timeout_ms = 300000
|
|
431
431
|
|
|
432
432
|
[features]
|
|
@@ -445,6 +445,8 @@ enabled = false
|
|
|
445
445
|
|
|
446
446
|
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(包括流式事件)。
|
|
447
447
|
|
|
448
|
+
对 Codex 客户端而言,只有 `gpt-*` Copilot 模型走原生 Responses API;非 GPT Copilot 模型一律走适配路径,即使声明支持原生 `/responses` 也不例外。
|
|
449
|
+
|
|
448
450
|
Responses Lite 的工具定义从 `input` 中的 `additional_tools` 读取,而不是依赖顶层 `tools`。该适配支持 function、`namespace` 和 custom tool;`apply_patch` 需要由客户端声明为 `type: "custom"`,不会作为独立工具类型特殊处理。工具调用返回时会恢复原始 `name` 与 `namespace`;压缩请求在裁剪旧历史前先保存工具定义,因此压缩期间也不会丢失工具。Messages 回退路径不支持 Responses `tool_search` 模式。Anthropic 的 `output_config.effort` 仍只使用项目既有的合法档位;Responses 的 `minimal` 会降级为 `low`,`none` 则不向 Anthropic 发送 effort。
|
|
449
451
|
|
|
450
452
|
当 Codex 通过顶层 GitHub Copilot 路由并设置 `approvals_reviewer = "auto_review"` 时,可在网关的 `config.json` 中将内部审核模型映射到一个支持 Responses API 的 Copilot 模型:
|
package/dist/main.js
CHANGED
|
@@ -25,7 +25,7 @@ bindElectronFetch();
|
|
|
25
25
|
const { auth } = await import("./auth-t5Gi1JB9.js");
|
|
26
26
|
const { debug } = await import("./debug-2GkXJBt5.js");
|
|
27
27
|
const { mcp } = await import("./mcp-BG6fpi6q.js");
|
|
28
|
-
const { start } = await import("./start-
|
|
28
|
+
const { start } = await import("./start-D5W3xtWv.js");
|
|
29
29
|
await runMain(defineCommand({
|
|
30
30
|
meta: {
|
|
31
31
|
name: "copilot-api",
|
|
@@ -3458,6 +3458,7 @@ function translateToOpenAI(payload, options = {}) {
|
|
|
3458
3458
|
const model = state.models?.data.find((m) => m.id === modelId);
|
|
3459
3459
|
const thinkingBudget = getThinkingBudget(payload, model);
|
|
3460
3460
|
const reasoningEffort = getReasoningEffort(payload, options);
|
|
3461
|
+
const promptCacheKey = requestContext.getStore()?.sessionAffinity?.trim();
|
|
3461
3462
|
return {
|
|
3462
3463
|
model: modelId,
|
|
3463
3464
|
messages: translateAnthropicMessagesToOpenAI(payload, modelId, {
|
|
@@ -3473,7 +3474,8 @@ function translateToOpenAI(payload, options = {}) {
|
|
|
3473
3474
|
tools: translateAnthropicToolsToOpenAI(payload.tools),
|
|
3474
3475
|
tool_choice: translateAnthropicToolChoiceToOpenAI(payload.tool_choice),
|
|
3475
3476
|
thinking_budget: thinkingBudget,
|
|
3476
|
-
...reasoningEffort ? { reasoning_effort: reasoningEffort } : {}
|
|
3477
|
+
...reasoningEffort ? { reasoning_effort: reasoningEffort } : {},
|
|
3478
|
+
...promptCacheKey ? { prompt_cache_key: promptCacheKey } : {}
|
|
3477
3479
|
};
|
|
3478
3480
|
}
|
|
3479
3481
|
function getReasoningEffort(payload, options) {
|
|
@@ -6355,7 +6357,7 @@ const CODEX_MODELS = [
|
|
|
6355
6357
|
]
|
|
6356
6358
|
},
|
|
6357
6359
|
{
|
|
6358
|
-
contextWindow:
|
|
6360
|
+
contextWindow: 272e3,
|
|
6359
6361
|
id: "gpt-5.6-sol",
|
|
6360
6362
|
input: ["text", "image"],
|
|
6361
6363
|
maxTokens: 128e3,
|
|
@@ -6370,7 +6372,7 @@ const CODEX_MODELS = [
|
|
|
6370
6372
|
]
|
|
6371
6373
|
},
|
|
6372
6374
|
{
|
|
6373
|
-
contextWindow:
|
|
6375
|
+
contextWindow: 272e3,
|
|
6374
6376
|
id: "gpt-5.6-terra",
|
|
6375
6377
|
input: ["text", "image"],
|
|
6376
6378
|
maxTokens: 128e3,
|
|
@@ -6385,7 +6387,7 @@ const CODEX_MODELS = [
|
|
|
6385
6387
|
]
|
|
6386
6388
|
},
|
|
6387
6389
|
{
|
|
6388
|
-
contextWindow:
|
|
6390
|
+
contextWindow: 272e3,
|
|
6389
6391
|
id: "gpt-5.6-luna",
|
|
6390
6392
|
input: ["text", "image"],
|
|
6391
6393
|
maxTokens: 128e3,
|
|
@@ -8090,15 +8092,20 @@ function getCopilotCodexCandidates() {
|
|
|
8090
8092
|
function isCopilotCodexCandidate(model) {
|
|
8091
8093
|
return (model.supported_endpoints ?? []).some((endpoint) => endpoint === MESSAGES_ENDPOINT || endpoint === CHAT_COMPLETIONS_ENDPOINT || RESPONSES_ENDPOINTS.has(endpoint)) && model.capabilities.supports.tool_calls !== false;
|
|
8092
8094
|
}
|
|
8095
|
+
function describeCopilotAdapter(model) {
|
|
8096
|
+
const supportsResponses = model.supported_endpoints?.some((endpoint) => RESPONSES_ENDPOINTS.has(endpoint));
|
|
8097
|
+
if (model.id.startsWith("gpt") && supportsResponses) return `${model.name} through the Copilot Responses API.`;
|
|
8098
|
+
if (model.supported_endpoints?.includes(MESSAGES_ENDPOINT)) return `${model.name} through the Copilot Messages adapter.`;
|
|
8099
|
+
if (supportsResponses) return `${model.name} through the Copilot Messages-to-Responses adapter.`;
|
|
8100
|
+
return `${model.name} through the Copilot Messages-to-Chat adapter.`;
|
|
8101
|
+
}
|
|
8093
8102
|
function createCopilotCodexCandidate(model) {
|
|
8094
8103
|
const reasoningEfforts = normalizeReasoningEfforts(model.capabilities.supports.reasoning_effort);
|
|
8095
|
-
const usesNativeResponses = model.supported_endpoints?.some((endpoint) => RESPONSES_ENDPOINTS.has(endpoint));
|
|
8096
|
-
const usesNativeMessages = model.supported_endpoints?.includes(MESSAGES_ENDPOINT);
|
|
8097
8104
|
return {
|
|
8098
8105
|
slug: toClientModelId(model.id),
|
|
8099
8106
|
displayName: model.name,
|
|
8100
|
-
description:
|
|
8101
|
-
contextWindow: positiveNumber(model.capabilities.limits.
|
|
8107
|
+
description: describeCopilotAdapter(model),
|
|
8108
|
+
contextWindow: positiveNumber(model.capabilities.limits.max_prompt_tokens, 256e3),
|
|
8102
8109
|
maxOutputTokens: positiveNumber(model.capabilities.limits.max_output_tokens, 32e3),
|
|
8103
8110
|
inputModalities: model.capabilities.supports.vision ? ["text", "image"] : ["text"],
|
|
8104
8111
|
reasoningEfforts,
|
|
@@ -8177,15 +8184,16 @@ function normalizeInputModalities(value) {
|
|
|
8177
8184
|
if (!Array.isArray(value)) return [];
|
|
8178
8185
|
return [...new Set(value.filter((modality) => modality === "text" || modality === "image"))];
|
|
8179
8186
|
}
|
|
8180
|
-
function
|
|
8181
|
-
if (configuredModalities.length > 0) return configuredModalities;
|
|
8182
|
-
if (providerName === "kimi") {
|
|
8183
|
-
const modalities = remoteModalities.length > 0 ? remoteModalities : builtinModalities.length > 0 ? builtinModalities : ["text"];
|
|
8184
|
-
return [...new Set([...modalities, "image"])];
|
|
8185
|
-
}
|
|
8187
|
+
function fallbackModalities(remoteModalities, builtinModalities) {
|
|
8186
8188
|
if (remoteModalities.length > 0) return remoteModalities;
|
|
8187
8189
|
return builtinModalities.length > 0 ? builtinModalities : ["text"];
|
|
8188
8190
|
}
|
|
8191
|
+
function resolveInputModalities(providerName, configuredModalities, remoteModalities, builtinModalities) {
|
|
8192
|
+
if (configuredModalities.length > 0) return configuredModalities;
|
|
8193
|
+
const modalities = fallbackModalities(remoteModalities, builtinModalities);
|
|
8194
|
+
if (providerName === "kimi") return [...new Set([...modalities, "image"])];
|
|
8195
|
+
return modalities;
|
|
8196
|
+
}
|
|
8189
8197
|
function selectDefaultReasoningEffort(efforts, configured) {
|
|
8190
8198
|
if (configured && efforts.includes(configured)) return configured;
|
|
8191
8199
|
if (efforts.includes("max")) return "max";
|
|
@@ -8400,6 +8408,7 @@ function translateResponsesToMessages(payload, options) {
|
|
|
8400
8408
|
if (messages.length === 0) throw new ResponsesMessagesTranslationError("Responses input must contain at least one translatable message");
|
|
8401
8409
|
applyEphemeralCacheControl(messages, system);
|
|
8402
8410
|
const reasoningEffort = translateReasoningEffort(payload.reasoning?.effort);
|
|
8411
|
+
const metadataUserId = resolveMetadataUserId(payload);
|
|
8403
8412
|
const messagesPayload = {
|
|
8404
8413
|
model: options.model,
|
|
8405
8414
|
messages,
|
|
@@ -8412,7 +8421,7 @@ function translateResponsesToMessages(payload, options) {
|
|
|
8412
8421
|
tool_choice: translateToolChoice(payload.tool_choice, registry),
|
|
8413
8422
|
...reasoningEffort ? { output_config: { effort: reasoningEffort } } : {},
|
|
8414
8423
|
...payload.service_tier === "auto" || payload.service_tier === "standard_only" ? { service_tier: payload.service_tier } : {},
|
|
8415
|
-
...
|
|
8424
|
+
...metadataUserId ? { metadata: { user_id: metadataUserId } } : {}
|
|
8416
8425
|
};
|
|
8417
8426
|
return {
|
|
8418
8427
|
compaction: normalized.compaction,
|
|
@@ -8920,6 +8929,8 @@ function translateReasoningEffort(effort) {
|
|
|
8920
8929
|
if (effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max") return effort;
|
|
8921
8930
|
}
|
|
8922
8931
|
function resolveMetadataUserId(payload) {
|
|
8932
|
+
const sessionAffinity = requestContext.getStore()?.sessionAffinity?.trim();
|
|
8933
|
+
if (sessionAffinity) return sessionAffinity;
|
|
8923
8934
|
const metadataUserId = payload.metadata?.user_id;
|
|
8924
8935
|
if (metadataUserId?.trim()) return metadataUserId;
|
|
8925
8936
|
if (payload.safety_identifier?.trim()) return payload.safety_identifier;
|
|
@@ -10422,4 +10433,4 @@ server.route("/:provider/images", providerImageRoutes);
|
|
|
10422
10433
|
//#endregion
|
|
10423
10434
|
export { server };
|
|
10424
10435
|
|
|
10425
|
-
//# sourceMappingURL=server-
|
|
10436
|
+
//# sourceMappingURL=server-s6RzK7Oo.js.map
|