@jeffreycao/copilot-api 2.2.10 → 2.2.12
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 +36 -0
- package/README.zh-CN.md +36 -0
- package/dist/main.js +1 -1
- package/dist/{server-DEEWMydw.js → server-C3DnUZoh.js} +102 -43
- package/dist/server-C3DnUZoh.js.map +1 -0
- package/dist/{start-tknmnmUA.js → start-CJ6z_8Pn.js} +2 -2
- package/dist/{start-tknmnmUA.js.map → start-CJ6z_8Pn.js.map} +1 -1
- package/package.json +1 -1
- package/dist/server-DEEWMydw.js.map +0 -1
package/README.md
CHANGED
|
@@ -264,6 +264,42 @@ enabled = false
|
|
|
264
264
|
>
|
|
265
265
|
> For third-party models that do not support `tool_search`, we recommend disabling features.apps. Otherwise, each prompt may consume an additional 20,000 or more tokens.
|
|
266
266
|
|
|
267
|
+
### If Codex Is Not Signed In to a GPT Account
|
|
268
|
+
|
|
269
|
+
```toml
|
|
270
|
+
[model_providers.copilot_api]
|
|
271
|
+
name = "OpenAI"
|
|
272
|
+
base_url = "http://localhost:4141"
|
|
273
|
+
requires_openai_auth = false
|
|
274
|
+
supports_websockets = false
|
|
275
|
+
wire_api = "responses"
|
|
276
|
+
request_max_retries = 3
|
|
277
|
+
stream_max_retries = 3
|
|
278
|
+
stream_idle_timeout_ms = 300000
|
|
279
|
+
|
|
280
|
+
[model_providers.copilot_api.auth]
|
|
281
|
+
command = "powershell.exe"
|
|
282
|
+
args = [
|
|
283
|
+
"-NoProfile",
|
|
284
|
+
"-NonInteractive",
|
|
285
|
+
"-Command",
|
|
286
|
+
"[Console]::Out.Write($env:GITHUB_COPILOT_API_KEY)"
|
|
287
|
+
]
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
macOS, replace the `auth` block with:
|
|
291
|
+
|
|
292
|
+
```toml
|
|
293
|
+
[model_providers.copilot_api.auth]
|
|
294
|
+
command = "/bin/zsh"
|
|
295
|
+
args = [
|
|
296
|
+
"-c",
|
|
297
|
+
"printf '%s' \"$GITHUB_COPILOT_API_KEY\""
|
|
298
|
+
]
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Without this configuration, Codex cannot fetch `/v1/models` while not signed in to a GPT account, so custom models are unavailable in the model picker.
|
|
302
|
+
|
|
267
303
|
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.
|
|
268
304
|
|
|
269
305
|
The merged catalog is what Codex shows in its model picker, including the models exposed by your configured providers:
|
package/README.zh-CN.md
CHANGED
|
@@ -280,6 +280,42 @@ enabled = false
|
|
|
280
280
|
>
|
|
281
281
|
> 对于不支持 `tool_search` 的第三方模型,我们建议禁用 features.apps。否则,每个提示可能会额外消耗 20,000 多个 token。
|
|
282
282
|
|
|
283
|
+
### Codex 未登录 GPT 账号时
|
|
284
|
+
|
|
285
|
+
```toml
|
|
286
|
+
[model_providers.copilot_api]
|
|
287
|
+
name = "OpenAI"
|
|
288
|
+
base_url = "http://localhost:4141"
|
|
289
|
+
requires_openai_auth = false
|
|
290
|
+
supports_websockets = false
|
|
291
|
+
wire_api = "responses"
|
|
292
|
+
request_max_retries = 3
|
|
293
|
+
stream_max_retries = 3
|
|
294
|
+
stream_idle_timeout_ms = 300000
|
|
295
|
+
|
|
296
|
+
[model_providers.copilot_api.auth]
|
|
297
|
+
command = "powershell.exe"
|
|
298
|
+
args = [
|
|
299
|
+
"-NoProfile",
|
|
300
|
+
"-NonInteractive",
|
|
301
|
+
"-Command",
|
|
302
|
+
"[Console]::Out.Write($env:GITHUB_COPILOT_API_KEY)"
|
|
303
|
+
]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
macOS 将 `auth` 段替换为:
|
|
307
|
+
|
|
308
|
+
```toml
|
|
309
|
+
[model_providers.copilot_api.auth]
|
|
310
|
+
command = "/bin/zsh"
|
|
311
|
+
args = [
|
|
312
|
+
"-c",
|
|
313
|
+
"printf '%s' \"$GITHUB_COPILOT_API_KEY\""
|
|
314
|
+
]
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
未按上述方式配置时,Codex 未登录 GPT 账号拉不到 `/v1/models`,无法选择自定义模型。
|
|
318
|
+
|
|
283
319
|
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(包括流式事件)。
|
|
284
320
|
|
|
285
321
|
合并后的模型列表会直接展示在 Codex 的模型选择界面中,包含各 provider 暴露的模型:
|
package/dist/main.js
CHANGED
|
@@ -30,7 +30,7 @@ if (isMcpFastPath(process.argv)) {
|
|
|
30
30
|
const { auth } = await import("./auth-C-RWNXGU.js");
|
|
31
31
|
const { debug } = await import("./debug-41w6Whae.js");
|
|
32
32
|
const { mcp } = await import("./mcp-fpSlKZxK.js");
|
|
33
|
-
const { start } = await import("./start-
|
|
33
|
+
const { start } = await import("./start-CJ6z_8Pn.js");
|
|
34
34
|
await runMain(defineCommand({
|
|
35
35
|
meta: {
|
|
36
36
|
name: "copilot-api",
|
|
@@ -576,9 +576,19 @@ const builtinProviderModelRegistry = new class BuiltinProviderModelRegistry {
|
|
|
576
576
|
inputModalities: ["text"],
|
|
577
577
|
maxOutputTokens: 64e3,
|
|
578
578
|
pricing: {
|
|
579
|
-
cachedInput: .
|
|
580
|
-
input:
|
|
581
|
-
output:
|
|
579
|
+
cachedInput: .1,
|
|
580
|
+
input: 3,
|
|
581
|
+
output: 9
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
"deepseek-v4-flash-vision-exp": {
|
|
585
|
+
contextWindow: 1e6,
|
|
586
|
+
inputModalities: ["text", "image"],
|
|
587
|
+
maxOutputTokens: 64e3,
|
|
588
|
+
pricing: {
|
|
589
|
+
cachedInput: .1,
|
|
590
|
+
input: 3,
|
|
591
|
+
output: 9
|
|
582
592
|
}
|
|
583
593
|
},
|
|
584
594
|
"deepseek-v4-pro": {
|
|
@@ -586,9 +596,9 @@ const builtinProviderModelRegistry = new class BuiltinProviderModelRegistry {
|
|
|
586
596
|
inputModalities: ["text"],
|
|
587
597
|
maxOutputTokens: 64e3,
|
|
588
598
|
pricing: {
|
|
589
|
-
cachedInput: .
|
|
590
|
-
input:
|
|
591
|
-
output:
|
|
599
|
+
cachedInput: .3,
|
|
600
|
+
input: 9,
|
|
601
|
+
output: 27
|
|
592
602
|
}
|
|
593
603
|
}
|
|
594
604
|
},
|
|
@@ -661,19 +671,34 @@ const builtinProviderModelRegistry = new class BuiltinProviderModelRegistry {
|
|
|
661
671
|
inputModalities: ["text"],
|
|
662
672
|
maxOutputTokens: 64e3,
|
|
663
673
|
pricing: {
|
|
664
|
-
cachedInput: .
|
|
665
|
-
input: .
|
|
666
|
-
output: .
|
|
674
|
+
cachedInput: .007,
|
|
675
|
+
input: .22,
|
|
676
|
+
output: .66
|
|
667
677
|
}
|
|
668
678
|
},
|
|
679
|
+
"deepseek-v4-flash-vision-exp": {
|
|
680
|
+
contextWindow: 1e6,
|
|
681
|
+
inputModalities: ["text", "image"],
|
|
682
|
+
maxOutputTokens: 384e3,
|
|
683
|
+
pricing: {
|
|
684
|
+
cachedInput: .007,
|
|
685
|
+
input: .22,
|
|
686
|
+
output: .66
|
|
687
|
+
},
|
|
688
|
+
reasoningEfforts: [
|
|
689
|
+
"low",
|
|
690
|
+
"high",
|
|
691
|
+
"max"
|
|
692
|
+
]
|
|
693
|
+
},
|
|
669
694
|
"deepseek-v4-pro": {
|
|
670
695
|
contextWindow: 1e6,
|
|
671
696
|
inputModalities: ["text"],
|
|
672
697
|
maxOutputTokens: 64e3,
|
|
673
698
|
pricing: {
|
|
674
|
-
cachedInput: .
|
|
675
|
-
input:
|
|
676
|
-
output:
|
|
699
|
+
cachedInput: .022,
|
|
700
|
+
input: .66,
|
|
701
|
+
output: 1.98
|
|
677
702
|
}
|
|
678
703
|
},
|
|
679
704
|
"kimi-k2.7-code": {
|
|
@@ -781,6 +806,21 @@ const builtinProviderModelRegistry = new class BuiltinProviderModelRegistry {
|
|
|
781
806
|
maxInputTokens: 512e3,
|
|
782
807
|
output: 2.4
|
|
783
808
|
}] }
|
|
809
|
+
},
|
|
810
|
+
"ox-alpha-free": {
|
|
811
|
+
contextWindow: 1e6,
|
|
812
|
+
inputModalities: ["text", "image"],
|
|
813
|
+
maxOutputTokens: 131072,
|
|
814
|
+
pricing: {
|
|
815
|
+
cachedInput: 0,
|
|
816
|
+
input: 0,
|
|
817
|
+
output: 0
|
|
818
|
+
},
|
|
819
|
+
reasoningEfforts: [
|
|
820
|
+
"low",
|
|
821
|
+
"high",
|
|
822
|
+
"max"
|
|
823
|
+
]
|
|
784
824
|
}
|
|
785
825
|
},
|
|
786
826
|
kimi: {
|
|
@@ -8440,6 +8480,14 @@ const MESSAGES_COMPACTION_PROMPT = [
|
|
|
8440
8480
|
"",
|
|
8441
8481
|
compactTextOnlyGuard
|
|
8442
8482
|
].join("\n");
|
|
8483
|
+
const MESSAGES_TOOL_CALL_TIPS = [
|
|
8484
|
+
"# Tool Call Tips",
|
|
8485
|
+
"- Do NOT call `exec_command` directly; that tool does not exist. Use `functions__exec` to run commands instead.",
|
|
8486
|
+
"- The functions__exec tool accepts parameters only as {\"input\":\"...\"}; put the complete executable code inside input, including properly constructed tools.exec_command(...) calls and text(...) output handling.",
|
|
8487
|
+
"- Construct all tools.exec_command(...) arguments strictly according to its tool definition, and use OS/shell-compatible commands for Windows, Linux, and macOS.",
|
|
8488
|
+
"- Always assign the awaited tools.exec_command(...) call to a variable, then forward its output with text(result.output) and inspect result.exit_code; unforwarded output is silently dropped and makes results look empty.",
|
|
8489
|
+
"- Read files with the OS-native command (Get-Content/Test-Path on Windows PowerShell, cat/ls on POSIX), quote paths containing spaces, and verify the forwarded output is non-empty before concluding a file was read."
|
|
8490
|
+
].join("\n");
|
|
8443
8491
|
const COMPACTION_REPLAY_PROMPT = "The previous conversation was compacted. Continue from this handoff summary:\n\n";
|
|
8444
8492
|
const MAX_DEVELOPER_PROMPTS = 5;
|
|
8445
8493
|
const TOOL_NAME_PATTERN = /^[A-Za-z0-9_-]{1,64}$/u;
|
|
@@ -8460,7 +8508,7 @@ var ResponsesMessagesTranslationError = class extends Error {
|
|
|
8460
8508
|
function translateResponsesToMessages(payload, options) {
|
|
8461
8509
|
const registry = createToolRegistry(payload);
|
|
8462
8510
|
const normalized = normalizeResponsesInput(payload.input);
|
|
8463
|
-
const { messages, system } = translateInputToAnthropic(normalized.input, registry, payload.instructions, payload.input);
|
|
8511
|
+
const { messages, system } = translateInputToAnthropic(normalized.input, registry, payload.instructions, payload.input, options.toolCallTips ?? false);
|
|
8464
8512
|
if (normalized.compaction) messages.push({
|
|
8465
8513
|
role: "user",
|
|
8466
8514
|
content: MESSAGES_COMPACTION_PROMPT
|
|
@@ -8649,17 +8697,11 @@ function registerMessagesTool(registration, registry) {
|
|
|
8649
8697
|
const originalKey = createOriginalToolKey(registration);
|
|
8650
8698
|
const existing = registry.byOriginal.get(originalKey);
|
|
8651
8699
|
if (existing) return existing;
|
|
8652
|
-
const
|
|
8653
|
-
|
|
8654
|
-
alias,
|
|
8655
|
-
kind: registration.kind,
|
|
8656
|
-
name: registration.name,
|
|
8657
|
-
...registration.namespace ? { namespace: registration.namespace } : {}
|
|
8658
|
-
};
|
|
8659
|
-
registry.byAlias.set(alias, descriptor);
|
|
8700
|
+
const descriptor = createMessagesToolDescriptor(registration, registry);
|
|
8701
|
+
registry.byAlias.set(descriptor.alias, descriptor);
|
|
8660
8702
|
registry.byOriginal.set(originalKey, descriptor);
|
|
8661
8703
|
registry.tools.push({
|
|
8662
|
-
name: alias,
|
|
8704
|
+
name: descriptor.alias,
|
|
8663
8705
|
...registration.description ? { description: registration.description } : {},
|
|
8664
8706
|
input_schema: registration.kind === "custom" ? CUSTOM_TOOL_INPUT_SCHEMA : registration.parameters ?? {
|
|
8665
8707
|
type: "object",
|
|
@@ -8669,7 +8711,16 @@ function registerMessagesTool(registration, registry) {
|
|
|
8669
8711
|
});
|
|
8670
8712
|
return descriptor;
|
|
8671
8713
|
}
|
|
8672
|
-
function
|
|
8714
|
+
function createMessagesToolDescriptor(registration, registry) {
|
|
8715
|
+
const originalKey = createOriginalToolKey(registration);
|
|
8716
|
+
return {
|
|
8717
|
+
alias: createToolAlias(registration.namespace ? `${registration.namespace.replaceAll(".", "_")}__${registration.name}` : registration.name, originalKey, registry),
|
|
8718
|
+
kind: registration.kind,
|
|
8719
|
+
name: registration.name,
|
|
8720
|
+
...registration.namespace ? { namespace: registration.namespace } : {}
|
|
8721
|
+
};
|
|
8722
|
+
}
|
|
8723
|
+
function translateInputToAnthropic(input, registry, instructions, originalInput, toolCallTips) {
|
|
8673
8724
|
const messages = [];
|
|
8674
8725
|
const system = [];
|
|
8675
8726
|
if (instructions?.trim()) system.push({
|
|
@@ -8677,20 +8728,29 @@ function translateInputToAnthropic(input, registry, instructions, originalInput)
|
|
|
8677
8728
|
text: instructions
|
|
8678
8729
|
});
|
|
8679
8730
|
appendDeveloperPrompts(system, originalInput);
|
|
8680
|
-
if (typeof input === "string") {
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
system
|
|
8688
|
-
};
|
|
8689
|
-
}
|
|
8690
|
-
if (!Array.isArray(input)) return {
|
|
8731
|
+
if (typeof input === "string") messages.push({
|
|
8732
|
+
role: "user",
|
|
8733
|
+
content: input
|
|
8734
|
+
});
|
|
8735
|
+
else if (Array.isArray(input)) translateInputItems(input, messages, system, registry);
|
|
8736
|
+
if (toolCallTips) appendToolCallTips(system);
|
|
8737
|
+
return {
|
|
8691
8738
|
messages,
|
|
8692
8739
|
system
|
|
8693
8740
|
};
|
|
8741
|
+
}
|
|
8742
|
+
function appendToolCallTips(system) {
|
|
8743
|
+
const lastSystemBlock = system.at(-1);
|
|
8744
|
+
if (!lastSystemBlock) {
|
|
8745
|
+
system.push({
|
|
8746
|
+
type: "text",
|
|
8747
|
+
text: MESSAGES_TOOL_CALL_TIPS
|
|
8748
|
+
});
|
|
8749
|
+
return;
|
|
8750
|
+
}
|
|
8751
|
+
lastSystemBlock.text = `${lastSystemBlock.text}\n\n${MESSAGES_TOOL_CALL_TIPS}`;
|
|
8752
|
+
}
|
|
8753
|
+
function translateInputItems(input, messages, system, registry) {
|
|
8694
8754
|
let userMessageSeen = false;
|
|
8695
8755
|
for (const item of input) {
|
|
8696
8756
|
const type = getItemType(item);
|
|
@@ -8726,10 +8786,6 @@ function translateInputToAnthropic(input, registry, instructions, originalInput)
|
|
|
8726
8786
|
default: throw new ResponsesMessagesTranslationError(`Responses Messages fallback does not support input item type '${type}'`);
|
|
8727
8787
|
}
|
|
8728
8788
|
}
|
|
8729
|
-
return {
|
|
8730
|
-
messages,
|
|
8731
|
-
system
|
|
8732
|
-
};
|
|
8733
8789
|
}
|
|
8734
8790
|
function translateInputMessage(item, messages, system, userMessageSeen) {
|
|
8735
8791
|
if (!isRecord(item)) throw new ResponsesMessagesTranslationError("Invalid Responses message item");
|
|
@@ -8794,11 +8850,12 @@ function translateInputReasoning(item, messages) {
|
|
|
8794
8850
|
}
|
|
8795
8851
|
function translateInputToolCall(item, kind, messages, registry) {
|
|
8796
8852
|
if (!isRecord(item)) throw new ResponsesMessagesTranslationError("Invalid Responses tool call item");
|
|
8797
|
-
const
|
|
8853
|
+
const toolIdentity = {
|
|
8798
8854
|
kind,
|
|
8799
8855
|
name: requireStringField(item, "name", `${kind}_tool_call`),
|
|
8800
8856
|
namespace: getOptionalStringField(item, "namespace") ?? void 0
|
|
8801
|
-
}
|
|
8857
|
+
};
|
|
8858
|
+
const descriptor = registry.byOriginal.get(createOriginalToolKey(toolIdentity)) ?? createMessagesToolDescriptor(toolIdentity, registry);
|
|
8802
8859
|
const input = kind === "custom" ? { input: getStringField(item, "input") ?? "" } : parseFunctionArguments(getStringField(item, "arguments") ?? "{}", `${kind}_tool_call.arguments`);
|
|
8803
8860
|
appendAssistantBlock(messages, {
|
|
8804
8861
|
type: "tool_use",
|
|
@@ -9938,13 +9995,15 @@ async function handleResponsesViaMessages(c, options) {
|
|
|
9938
9995
|
model: options.publicModel
|
|
9939
9996
|
}, {
|
|
9940
9997
|
model: options.targetModel,
|
|
9941
|
-
publicModel: options.publicModel
|
|
9998
|
+
publicModel: options.publicModel,
|
|
9999
|
+
toolCallTips: isCodexUserAgent(c.req.header("user-agent"))
|
|
9942
10000
|
});
|
|
9943
10001
|
const context = translation;
|
|
9944
10002
|
debugJson(logger$3, "Translated Messages request:", {
|
|
9945
10003
|
payload: translation.messagesPayload,
|
|
9946
10004
|
publicModel: options.publicModel,
|
|
9947
|
-
targetModel: options.targetModel
|
|
10005
|
+
targetModel: options.targetModel,
|
|
10006
|
+
userAgent: c.req.header("user-agent") ?? ""
|
|
9948
10007
|
});
|
|
9949
10008
|
const messagesResponse = await responsesMessagesDependencies.handleCompletionPayload(c, translation.messagesPayload, {
|
|
9950
10009
|
compactType: translation.compaction ? 1 : void 0,
|
|
@@ -10514,4 +10573,4 @@ server.route("/:provider/images", providerImageRoutes);
|
|
|
10514
10573
|
//#endregion
|
|
10515
10574
|
export { server };
|
|
10516
10575
|
|
|
10517
|
-
//# sourceMappingURL=server-
|
|
10576
|
+
//# sourceMappingURL=server-C3DnUZoh.js.map
|