fix(forms): reflect automatic Copilot protocol routing (#8196)

This commit is contained in:
Railgun authored and GitHub committed 2026-10-24 21:00:19 +08:00
1 parent 9decd60e80
commit bd50984e05
9 files changed
+62 -4

No files matched your search

+9 -1
View File
@@ -54,7 +54,7 @@
Claude Code 的预设最全,涵盖厂商官方、编程套餐、聚合和中转平台。其中:
- **Claude 官方**:使用 Anthropic 官方账号登录,在「账号登录」分类
- **GitHub Copilot / Codex(ChatGPT 账号)/ xAI (Grok)**:同样在「账号登录」,需要先在授权中心登录对应账号,见下文「Codex OAuth 反向代理」
- **GitHub Copilot / Codex(ChatGPT 账号)/ xAI (Grok)**:同样在「账号登录」,需要先在授权中心登录对应账号,见下文「Codex OAuth 反向代理」与「GitHub Copilot」
- 其余预设填 API Key 即可;预设里已写好的上游格式、模型映射不用手动改
#### Claude Desktop 预设
@@ -411,6 +411,14 @@ Codex OAuth 反向代理通过**逆向工程的 OAuth 流程**访问 ChatGPT 账
> 📖 完整免责声明及更多背景参见 [v3.13.0 Release Notes](../../../release-notes/v3.13.0-zh.md#️-风险提示)。
## GitHub Copilot(Claude Code / Codex)
通过授权中心登录 GitHub 账号后,可在 Claude Code 和 Codex 中添加 GitHub Copilot 供应商。
### 上游协议选择
Claude Code / Claude Desktop 的 Copilot 上游协议由路由按模型自动选择,手选格式不生效,表单会禁用格式选择并显示说明。Codex 可选择 `Auto`、`Chat Completions` 或 `Responses`,模型列表按所选协议过滤。普通供应商仍按手选格式转发。
## 高级选项
### 上游格式(Claude)
@@ -1119,12 +1119,17 @@ export function ClaudeDesktopProviderForm({
</Label>
<Select
value={apiFormat}
disabled={activeProviderType === "github_copilot"}
onValueChange={(value) =>
setApiFormat(value as ClaudeApiFormat)
}
>
<SelectTrigger className="w-full">
<SelectValue />
<SelectValue>
{activeProviderType === "github_copilot"
? t("copilot.automaticFormat")
: undefined}
</SelectValue>
</SelectTrigger>
<SelectContent>
<SelectItem value="anthropic">
@@ -1151,6 +1156,11 @@ export function ClaudeDesktopProviderForm({
</SelectItem>
</SelectContent>
</Select>
{activeProviderType === "github_copilot" && (
<p className="text-xs leading-relaxed text-fg-2">
{t("copilot.automaticFormatHint")}
</p>
)}
</div>
)}
@@ -833,6 +833,12 @@ export function ClaudeFormFields({
</>
);
const copilotRoutingNotice = isCopilotPreset && (
<p className="text-xs leading-relaxed text-fg-2">
{t("copilot.automaticFormatHint")}
</p>
);
// 上游格式、认证字段:经典布局放在高级选项里,Stack 布局放在连接区。
const apiFormatLabel = t("providerForm.apiFormat", {
defaultValue: "上游格式",
@@ -854,9 +860,15 @@ export function ClaudeFormFields({
})}
</HelpTip>
</div>
<Select value={apiFormat} onValueChange={onApiFormatChange}>
<Select
value={apiFormat}
onValueChange={onApiFormatChange}
disabled={isCopilotPreset}
>
<SelectTrigger id="apiFormat" className="w-full">
<SelectValue />
<SelectValue>
{isCopilotPreset ? t("copilot.automaticFormat") : undefined}
</SelectValue>
</SelectTrigger>
<SelectContent>
<SelectItem value="anthropic">
@@ -999,6 +1011,7 @@ export function ClaudeFormFields({
return (
<>
{oauthSections}
{copilotRoutingNotice}
{apiFormatField}
{apiKeySection}
{showAuthField && authFieldSelect}
@@ -1056,6 +1069,7 @@ export function ClaudeFormFields({
return (
<>
{oauthSections}
{copilotRoutingNotice}
{apiKeySection}
{templateSection}
{endpointSection}
+2
View File
@@ -1792,6 +1792,8 @@
"directModeFormatSwitch": "This format doesn't work in direct mode; switch to routing or Aggregation to use this card."
},
"copilot": {
"automaticFormat": "Selected automatically by routing",
"automaticFormatHint": "Routing selects the Copilot upstream format per model; manual format settings are ignored.",
"authSection": "GitHub Copilot Authentication",
"authStatus": "Authentication Status",
"authenticated": "Authenticated as {{username}}",
+2
View File
@@ -1792,6 +1792,8 @@
"directModeFormatSwitch": "この形式は直結モードでは使えません。ルーティングか集約に切り替えるとこのカードを使えます。"
},
"copilot": {
"automaticFormat": "モデルに応じてルーティングが自動選択",
"automaticFormatHint": "Copilot の上流形式はモデルに応じてルーティングが自動選択し、手動設定は適用されません。",
"authSection": "GitHub Copilot 認証",
"authStatus": "認証状態",
"authenticated": "認証済み: {{username}}",
+2
View File
@@ -1793,6 +1793,8 @@
"directModeFormatSwitch": "直連模式下用不了這種格式,切到路由或聚合後才能用這張卡。"
},
"copilot": {
"automaticFormat": "由路由依模型自動選擇",
"automaticFormatHint": "Copilot 的上游格式由路由依模型自動選擇,手選格式不生效。",
"authSection": "GitHub Copilot 驗證",
"authStatus": "驗證狀態",
"authenticated": "已驗證: {{username}}",
+2
View File
@@ -1792,6 +1792,8 @@
"directModeFormatSwitch": "直连模式下用不了这种格式,切到路由或聚合后才能用这张卡。"
},
"copilot": {
"automaticFormat": "由路由按模型自动选择",
"automaticFormatHint": "Copilot 的上游格式由路由按模型自动选择,手选格式不生效。",
"authSection": "GitHub Copilot 认证",
"authStatus": "认证状态",
"authenticated": "已认证: {{username}}",
@@ -185,6 +185,13 @@ describe("ClaudeDesktopProviderForm", () => {
});
expect(modelModePicker).toHaveTextContent("模型映射");
expect(modelModePicker).toBeDisabled();
if (providerType === "github_copilot") {
const formatControl = screen
.getByText("copilot.automaticFormat")
.closest("button");
expect(formatControl).toBeDisabled();
expect(screen.getByText(/copilot.automaticFormatHint/)).toBeVisible();
}
},
);
@@ -142,6 +142,17 @@ describe("ClaudeFormFields", () => {
expect(copilotApiMock.copilotGetModelsForAccount).not.toHaveBeenCalled();
});
it.each(["classic", "stack"] as const)(
"Copilot %s 布局显示自动协议并禁用无效的手选格式",
(variant) => {
renderCopilotForm({ variant, apiFormat: "openai_responses" });
const control = screen.getByRole("combobox", { name: "上游格式" });
expect(control).toBeDisabled();
expect(control).toHaveTextContent("copilot.automaticFormat");
expect(screen.getByText(/copilot.automaticFormatHint/)).toBeVisible();
},
);
it("点击获取模型列表后才请求当前 Copilot 账号的模型", async () => {
renderCopilotForm();