mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-10-26 01:34:51 +08:00
refactor(codex): move field explanations into help tips
The Codex edit page carried a grey explanation under almost every field. Following the v7 help rules, explanations of what a field is and when to use it now sit behind a "?" after the field name, and only consequences stay on the page: restart Codex after changing the model list, a max output above the real limit returns 400, User-Agent and request overrides only apply in routing mode, and Copilot needs routing in every mode. The collapsed advanced-section summary and the reasoning group note are gone; the Chat and Anthropic options already say they need routing. The shared endpoint, User-Agent and request override fields take an optional help text, so the other provider forms are unchanged.
This commit is contained in:
1 parent
9f7ac1fa67
commit
36e2ce2c78
10 files changed
+314
-262
No files matched your search
@@ -1,4 +1,11 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
type ReactNode,
|
||||
} from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { HelpTip } from "@/components/ui/help-tip";
|
||||
@@ -1180,13 +1187,26 @@ export function CodexFormFields({
|
||||
|
||||
// 上游格式及 Anthropic 格式专有的几项:经典布局都在高级选项里;Stack 布局把上游格式和
|
||||
// 认证字段放进连接区,其余留在高级选项里。
|
||||
// 字段名后面的「?」:规则和术语解释收进去;后果(要开路由、会报错)仍写在页面上。
|
||||
const labelWithHelp = (label: string, help: ReactNode, htmlFor?: string) => (
|
||||
<div className="flex items-center gap-0.5">
|
||||
<FormLabel htmlFor={htmlFor}>{label}</FormLabel>
|
||||
<HelpTip title={label}>{help}</HelpTip>
|
||||
</div>
|
||||
);
|
||||
|
||||
const upstreamFormatSelect = (
|
||||
<div className="space-y-1.5">
|
||||
<FormLabel htmlFor="codex-upstream-format">
|
||||
{t("codexConfig.upstreamFormatLabel", {
|
||||
defaultValue: "上游格式",
|
||||
})}
|
||||
</FormLabel>
|
||||
{labelWithHelp(
|
||||
t("codexConfig.upstreamFormatLabel", { defaultValue: "上游格式" }),
|
||||
isCopilotPreset
|
||||
? t("codexConfig.upstreamFormatCopilotHint")
|
||||
: t("codexConfig.upstreamFormatHint", {
|
||||
defaultValue:
|
||||
"看供应商原生支持哪种协议:Responses 直连、不转换格式;Chat 或 Anthropic 由路由转成 Responses。",
|
||||
}),
|
||||
"codex-upstream-format",
|
||||
)}
|
||||
<Select
|
||||
value={isCopilotPreset ? copilotApiFormat : apiFormat}
|
||||
onValueChange={(value) => {
|
||||
@@ -1237,24 +1257,24 @@ export function CodexFormFields({
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{isCopilotPreset
|
||||
? t("codexConfig.upstreamFormatCopilotHint")
|
||||
: t("codexConfig.upstreamFormatHint", {
|
||||
defaultValue:
|
||||
"供应商原生是 Responses API 就选 Responses(直连,不转换格式);使用 Chat Completions 协议就选 Chat;供应商只提供原生 Anthropic Messages 协议就选 Anthropic Messages。Chat 与 Anthropic Messages 均需开启路由接管才能转换为 Responses。",
|
||||
})}
|
||||
</p>
|
||||
{/* Chat / Anthropic 的「需开启路由」已写在选项里;Copilot 的选项没写,单独提示。 */}
|
||||
{isCopilotPreset && (
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.upstreamFormatCopilotRouteHint")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
const anthropicAuthFieldSelect = (
|
||||
<div className="space-y-1.5">
|
||||
<FormLabel htmlFor="codex-anthropic-auth-field">
|
||||
{t("codexConfig.anthropicAuthFieldLabel", {
|
||||
defaultValue: "认证字段",
|
||||
})}
|
||||
</FormLabel>
|
||||
{labelWithHelp(
|
||||
t("codexConfig.anthropicAuthFieldLabel", { defaultValue: "认证字段" }),
|
||||
t("codexConfig.anthropicAuthFieldHint", {
|
||||
defaultValue: "按网关读取 API Key 的请求头选择,两者只发其一。",
|
||||
}),
|
||||
"codex-anthropic-auth-field",
|
||||
)}
|
||||
<Select
|
||||
value={anthropicAuthField}
|
||||
onValueChange={(value) =>
|
||||
@@ -1277,30 +1297,20 @@ export function CodexFormFields({
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.anthropicAuthFieldHint", {
|
||||
defaultValue:
|
||||
"选择网关接收 API Key 的请求头:ANTHROPIC_AUTH_TOKEN 发送 Authorization: Bearer;ANTHROPIC_API_KEY 发送 x-api-key。两者只发其一。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const impersonateClaudeCodeToggle = (
|
||||
<div className="flex items-center justify-between gap-4 border-t border-border pt-3">
|
||||
<div className="space-y-1">
|
||||
<FormLabel>
|
||||
{t("codexConfig.impersonateClaudeCodeLabel", {
|
||||
defaultValue: "模拟 Claude Code 客户端",
|
||||
})}
|
||||
</FormLabel>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.impersonateClaudeCodeHint", {
|
||||
defaultValue:
|
||||
"网关或其上游限制只能通过 Claude Code 使用时开启:伪装 User-Agent、anthropic-beta、x-app 请求头,并在系统提示首行注入 Claude Code 身份。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
{labelWithHelp(
|
||||
t("codexConfig.impersonateClaudeCodeLabel", {
|
||||
defaultValue: "模拟 Claude Code 客户端",
|
||||
}),
|
||||
t("codexConfig.impersonateClaudeCodeHint", {
|
||||
defaultValue:
|
||||
"网关只允许 Claude Code 使用时打开:伪装 Claude Code 的请求头,并在系统提示首行注入它的身份。",
|
||||
}),
|
||||
)}
|
||||
<Switch
|
||||
checked={impersonateClaudeCode}
|
||||
onCheckedChange={onImpersonateClaudeCodeChange}
|
||||
@@ -1313,11 +1323,21 @@ export function CodexFormFields({
|
||||
|
||||
const maxOutputTokensField = (
|
||||
<div className="space-y-1.5 border-t border-border pt-3">
|
||||
<FormLabel htmlFor="codex-anthropic-max-output-tokens">
|
||||
{t("codexConfig.maxOutputTokensLabel", {
|
||||
{labelWithHelp(
|
||||
t("codexConfig.maxOutputTokensLabel", {
|
||||
defaultValue: "最大输出 tokens",
|
||||
})}
|
||||
</FormLabel>
|
||||
}),
|
||||
isGrokBuild
|
||||
? t("grokBuild.maxOutputTokensHint", {
|
||||
defaultValue:
|
||||
"默认上限 8192,长回答或深度思考容易被截断。这里的值会作为 Anthropic 的 max_tokens 发出。",
|
||||
})
|
||||
: t("codexConfig.maxOutputTokensHint", {
|
||||
defaultValue:
|
||||
"Codex 不带输出上限,默认 8192,长回答或深度思考容易被截断。这里的值会作为 Anthropic 的 max_tokens 发出。",
|
||||
}),
|
||||
"codex-anthropic-max-output-tokens",
|
||||
)}
|
||||
<Input
|
||||
id="codex-anthropic-max-output-tokens"
|
||||
type="number"
|
||||
@@ -1332,15 +1352,9 @@ export function CodexFormFields({
|
||||
})}
|
||||
/>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{isGrokBuild
|
||||
? t("grokBuild.maxOutputTokensHint", {
|
||||
defaultValue:
|
||||
"默认上限 8192 容易在长回答或深度思考时被截断(stop_reason=max_tokens)。此处设置会作为 Anthropic 的 max_tokens 覆盖请求值。请勿超过该模型/网关的真实输出上限,否则可能 400。留空使用默认 8192。",
|
||||
})
|
||||
: t("codexConfig.maxOutputTokensHint", {
|
||||
defaultValue:
|
||||
"Codex 不会把 model_max_output_tokens 写进请求体,默认上限 8192 容易在长回答或深度思考时被截断(stop_reason=max_tokens)。此处设置会作为 Anthropic 的 max_tokens 覆盖请求值。请勿超过该模型/网关的真实输出上限,否则可能 400。留空使用默认 8192。",
|
||||
})}
|
||||
{t("codexConfig.maxOutputTokensWarning", {
|
||||
defaultValue: "不要超过模型或网关的真实输出上限,否则会返回 400。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
@@ -1348,11 +1362,15 @@ export function CodexFormFields({
|
||||
const reasoningFields = (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<FormLabel>
|
||||
{t("codexConfig.promptCacheRoutingLabel", {
|
||||
{labelWithHelp(
|
||||
t("codexConfig.promptCacheRoutingLabel", {
|
||||
defaultValue: "提示词缓存路由",
|
||||
})}
|
||||
</FormLabel>
|
||||
}),
|
||||
t("codexConfig.promptCacheRoutingHint", {
|
||||
defaultValue:
|
||||
"自动:只对确认兼容的上游发送 prompt_cache_key。开启:用于其他兼容网关。关闭:避免严格网关因未知字段返回 400。",
|
||||
}),
|
||||
)}
|
||||
<Select
|
||||
value={promptCacheRouting}
|
||||
onValueChange={(value) =>
|
||||
@@ -1380,42 +1398,24 @@ export function CodexFormFields({
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.promptCacheRoutingHint", {
|
||||
defaultValue:
|
||||
"自动模式仅对已确认兼容的上游发送 prompt_cache_key;开启可用于其他兼容网关,关闭可避免严格网关因未知字段返回 400。只使用客户端提供的稳定会话 ID。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<FormLabel>
|
||||
{t("codexConfig.reasoningGroupTitle", {
|
||||
defaultValue: "思考能力",
|
||||
})}
|
||||
</FormLabel>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.reasoningSectionHint", {
|
||||
defaultValue:
|
||||
"预设供应商已自动配置;自定义供应商会按名称/地址自动推断。仅当自动识别不准时才需手动覆盖。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
<FormLabel>
|
||||
{t("codexConfig.reasoningGroupTitle", {
|
||||
defaultValue: "思考能力",
|
||||
})}
|
||||
</FormLabel>
|
||||
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="space-y-1">
|
||||
<FormLabel>
|
||||
{t("codexConfig.reasoningModeToggle", {
|
||||
defaultValue: "支持思考模式",
|
||||
})}
|
||||
</FormLabel>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.reasoningModeHint", {
|
||||
defaultValue:
|
||||
"上游 Chat Completions 接口支持开启或关闭 thinking 时启用。Kimi、GLM、Qwen 等通常属于这一类。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
{labelWithHelp(
|
||||
t("codexConfig.reasoningModeToggle", {
|
||||
defaultValue: "支持思考模式",
|
||||
}),
|
||||
t("codexConfig.reasoningModeHint", {
|
||||
defaultValue:
|
||||
"上游 Chat 接口能开关 thinking 时打开,Kimi、GLM、Qwen 等通常属于这一类。",
|
||||
}),
|
||||
)}
|
||||
<Switch
|
||||
checked={supportsThinking}
|
||||
onCheckedChange={handleReasoningThinkingChange}
|
||||
@@ -1426,24 +1426,20 @@ export function CodexFormFields({
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between gap-4 border-t border-border pt-3">
|
||||
<div className="space-y-1">
|
||||
<FormLabel>
|
||||
{t("codexConfig.reasoningEffortToggle", {
|
||||
defaultValue: "支持思考等级",
|
||||
})}
|
||||
</FormLabel>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{isGrokBuild
|
||||
? t("grokBuild.reasoningEffortHint", {
|
||||
defaultValue:
|
||||
"上游支持 low/high/max 等思考深度控制时启用。启用后会自动启用思考模式,并把请求中的 reasoning effort 转成上游 Chat 参数。",
|
||||
})
|
||||
: t("codexConfig.reasoningEffortHint", {
|
||||
defaultValue:
|
||||
"上游支持 low/high/max 等思考深度控制时启用。启用后会自动启用思考模式,并把 Codex 的 reasoning.effort 转成上游 Chat 参数。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
{labelWithHelp(
|
||||
t("codexConfig.reasoningEffortToggle", {
|
||||
defaultValue: "支持思考等级",
|
||||
}),
|
||||
isGrokBuild
|
||||
? t("grokBuild.reasoningEffortHint", {
|
||||
defaultValue:
|
||||
"上游支持 low/high/max 等思考深度时打开。会同时打开思考模式,并把请求中的 reasoning effort 转成上游 Chat 参数。",
|
||||
})
|
||||
: t("codexConfig.reasoningEffortHint", {
|
||||
defaultValue:
|
||||
"上游支持 low/high/max 等思考深度时打开。会同时打开思考模式,并把 Codex 的 reasoning.effort 转成上游 Chat 参数。",
|
||||
}),
|
||||
)}
|
||||
<Switch
|
||||
checked={supportsEffort}
|
||||
onCheckedChange={handleReasoningEffortChange}
|
||||
@@ -1455,12 +1451,21 @@ export function CodexFormFields({
|
||||
</>
|
||||
);
|
||||
|
||||
// 两项都只在路由模式下生效:在分组开头说一次,各自的作用收进字段名后的「?」。
|
||||
const userAgentAndOverrides = (
|
||||
<>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.routeOnlySettingsHint", {
|
||||
defaultValue: "以下两项只在路由模式下生效。",
|
||||
})}
|
||||
</p>
|
||||
<CustomUserAgentField
|
||||
id="codex-custom-user-agent"
|
||||
value={customUserAgent}
|
||||
onChange={onCustomUserAgentChange}
|
||||
help={t("providerForm.customUserAgentHelp", {
|
||||
defaultValue: "替换转发到供应商的请求里的 User-Agent。",
|
||||
})}
|
||||
/>
|
||||
<div className="border-t border-border pt-3">
|
||||
<LocalProxyRequestOverridesField
|
||||
@@ -1468,6 +1473,9 @@ export function CodexFormFields({
|
||||
bodyJson={localProxyBodyOverride}
|
||||
onHeadersJsonChange={onLocalProxyHeadersOverrideChange}
|
||||
onBodyJsonChange={onLocalProxyBodyOverrideChange}
|
||||
help={t("providerForm.localProxyRequestOverridesHelp", {
|
||||
defaultValue: "作用于格式转换后发给上游的请求。",
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
@@ -1681,7 +1689,7 @@ export function CodexFormFields({
|
||||
value={codexBaseUrl}
|
||||
onChange={onBaseUrlChange}
|
||||
placeholder={t("providerForm.codexApiEndpointPlaceholder")}
|
||||
hint={t("providerForm.codexApiHint")}
|
||||
help={t("providerForm.codexApiHint")}
|
||||
showFullUrlToggle
|
||||
isFullUrl={isFullUrl}
|
||||
onFullUrlChange={onFullUrlChange}
|
||||
@@ -1883,13 +1891,13 @@ export function CodexFormFields({
|
||||
})}
|
||||
</FormLabel>
|
||||
<HelpTip
|
||||
title={t("providerForm.stackModelDefault", {
|
||||
defaultValue: "默认模型",
|
||||
title={t("codexConfig.modelListTitle", {
|
||||
defaultValue: "模型列表",
|
||||
})}
|
||||
>
|
||||
{t("codexConfig.modelListDefaultHelp", {
|
||||
defaultValue:
|
||||
"第一行是默认模型,Codex 启动时用它。列表为空时,可以在下方单独填写默认模型。",
|
||||
"这些模型会出现在 Codex 的 /model 里,带上各自的上下文窗口和思考等级。第一行是默认模型。",
|
||||
})}
|
||||
</HelpTip>
|
||||
</div>
|
||||
@@ -1902,8 +1910,7 @@ export function CodexFormFields({
|
||||
</div>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.modelListHint", {
|
||||
defaultValue:
|
||||
"这些模型会出现在 Codex 的 /model 里,带上各自的上下文窗口和思考等级。修改后需要重启 Codex。",
|
||||
defaultValue: "修改后需要重启 Codex。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
@@ -1926,9 +1933,18 @@ export function CodexFormFields({
|
||||
onModelChange &&
|
||||
(!firstRowIsDefault || catalogRows.length === 0) && (
|
||||
<div className="space-y-1.5">
|
||||
<FormLabel htmlFor="codexDefaultModel">
|
||||
{t("codexConfig.defaultModelLabel", { defaultValue: "默认模型" })}
|
||||
</FormLabel>
|
||||
{labelWithHelp(
|
||||
t("codexConfig.defaultModelLabel", { defaultValue: "默认模型" }),
|
||||
isGrokBuild
|
||||
? t("grokBuild.defaultModelHint", {
|
||||
defaultValue: "Grok Build 默认请求的模型,随时可改。",
|
||||
})
|
||||
: t("codexConfig.defaultModelHint", {
|
||||
defaultValue:
|
||||
"Codex 默认请求的模型。添加模型列表后,列表第一行就是默认模型。",
|
||||
}),
|
||||
"codexDefaultModel",
|
||||
)}
|
||||
<div className="flex gap-1">
|
||||
<Input
|
||||
id="codexDefaultModel"
|
||||
@@ -1972,17 +1988,6 @@ export function CodexFormFields({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{isGrokBuild
|
||||
? t("grokBuild.defaultModelHint", {
|
||||
defaultValue:
|
||||
"Grok Build 默认请求的模型,随时可改,无需等待预设更新。",
|
||||
})
|
||||
: t("codexConfig.defaultModelHint", {
|
||||
defaultValue:
|
||||
"Codex 默认请求的模型,随时可改,无需等待预设更新。添加模型列表后,列表第一行就是默认模型。",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1990,11 +1995,16 @@ export function CodexFormFields({
|
||||
留空删键,子代理跟随主模型;聚合模式下不写进 live。 */}
|
||||
{category !== "official" && onSubagentModelChange && (
|
||||
<div className="space-y-1.5">
|
||||
<FormLabel htmlFor="codexSubagentModel">
|
||||
{t("codexConfig.subagentModelLabel", {
|
||||
{labelWithHelp(
|
||||
t("codexConfig.subagentModelLabel", {
|
||||
defaultValue: "子代理模型",
|
||||
})}
|
||||
</FormLabel>
|
||||
}),
|
||||
t("codexConfig.subagentModelHint", {
|
||||
defaultValue:
|
||||
"Codex 派出的子代理默认用的模型和推理强度。留空时沿用主代理的;只填模型时用该模型自己的默认强度。聚合模式下不生效,子代理跟随主模型。",
|
||||
}),
|
||||
"codexSubagentModel",
|
||||
)}
|
||||
<div className="flex gap-1">
|
||||
<Input
|
||||
id="codexSubagentModel"
|
||||
@@ -2051,12 +2061,6 @@ export function CodexFormFields({
|
||||
</Select>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.subagentModelHint", {
|
||||
defaultValue:
|
||||
"Codex 派出的子代理默认用的模型和推理强度。留空时子代理沿用主代理的;只填模型时用该模型自己的默认强度。聚合模式下不生效,子代理跟随主模型。",
|
||||
})}
|
||||
</p>
|
||||
{isSubagentModelOutsideCatalog && (
|
||||
<p className="flex flex-wrap items-center gap-x-2 text-xs leading-relaxed text-fg-2">
|
||||
{t("codexConfig.subagentModelNotInCatalog", {
|
||||
@@ -2105,19 +2109,6 @@ export function CodexFormFields({
|
||||
})}
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
{!advancedExpanded && (
|
||||
<p className="mt-1 ml-1 text-xs text-fg-2">
|
||||
{isGrokBuild
|
||||
? t("grokBuild.advancedSectionHint", {
|
||||
defaultValue:
|
||||
"包含上游格式、思考能力与自定义 User-Agent。使用 Chat Completions / Anthropic Messages 协议的供应商需开启路由接管才能使用。",
|
||||
})
|
||||
: t("codexConfig.advancedSectionHint", {
|
||||
defaultValue:
|
||||
"包含上游格式、思考能力与自定义 User-Agent。使用 Chat Completions / Anthropic Messages 协议的供应商需开启路由才能使用。",
|
||||
})}
|
||||
</p>
|
||||
)}
|
||||
<CollapsibleContent className="space-y-3 pt-3">
|
||||
{/* Copilot supports automatic capability routing or an explicit protocol;
|
||||
other providers retain their existing format controls. */}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ChevronDown } from "lucide-react";
|
||||
import { FormLabel } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { HelpTip } from "@/components/ui/help-tip";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -17,6 +18,8 @@ interface CustomUserAgentFieldProps {
|
||||
id: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
/** 传了就把说明放进字段名后的「?」,替代下方的「仅在路由下生效」提示。 */
|
||||
help?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,17 +33,20 @@ export function CustomUserAgentField({
|
||||
id,
|
||||
value,
|
||||
onChange,
|
||||
help,
|
||||
}: CustomUserAgentFieldProps) {
|
||||
const { t } = useTranslation();
|
||||
const valid = isValidUserAgentHeader(value);
|
||||
const label = t("providerForm.customUserAgent", {
|
||||
defaultValue: "自定义 User-Agent",
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<FormLabel htmlFor={id}>
|
||||
{t("providerForm.customUserAgent", {
|
||||
defaultValue: "自定义 User-Agent",
|
||||
})}
|
||||
</FormLabel>
|
||||
<div className="flex items-center gap-0.5">
|
||||
<FormLabel htmlFor={id}>{label}</FormLabel>
|
||||
{help ? <HelpTip title={label}>{help}</HelpTip> : null}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
id={id}
|
||||
@@ -77,12 +83,14 @@ export function CustomUserAgentField({
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
{valid ? (
|
||||
<p className="text-xs text-fg-2">
|
||||
{t("providerForm.customUserAgentHint", {
|
||||
defaultValue:
|
||||
"仅在开启本地路由/代理接管后生效,会替换转发到供应商 API 请求中的 User-Agent。",
|
||||
})}
|
||||
</p>
|
||||
!help && (
|
||||
<p className="text-xs text-fg-2">
|
||||
{t("providerForm.customUserAgentHint", {
|
||||
defaultValue:
|
||||
"仅在开启本地路由/代理接管后生效,会替换转发到供应商 API 请求中的 User-Agent。",
|
||||
})}
|
||||
</p>
|
||||
)
|
||||
) : (
|
||||
<p className="text-xs text-destructive">
|
||||
{t("providerForm.customUserAgentInvalid", {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormLabel } from "@/components/ui/form";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { HelpTip } from "@/components/ui/help-tip";
|
||||
import {
|
||||
parseBodyOverrideJson,
|
||||
parseHeaderOverrideJson,
|
||||
@@ -11,6 +12,8 @@ interface LocalProxyRequestOverridesFieldProps {
|
||||
bodyJson: string;
|
||||
onHeadersJsonChange: (value: string) => void;
|
||||
onBodyJsonChange: (value: string) => void;
|
||||
/** 传了就把说明放进字段名后的「?」,替代下方的「仅在路由下生效」提示。 */
|
||||
help?: string;
|
||||
}
|
||||
|
||||
export function LocalProxyRequestOverridesField({
|
||||
@@ -18,25 +21,30 @@ export function LocalProxyRequestOverridesField({
|
||||
bodyJson,
|
||||
onHeadersJsonChange,
|
||||
onBodyJsonChange,
|
||||
help,
|
||||
}: LocalProxyRequestOverridesFieldProps) {
|
||||
const { t } = useTranslation();
|
||||
const label = t("providerForm.localProxyRequestOverrides", {
|
||||
defaultValue: "本地代理请求覆盖",
|
||||
});
|
||||
const headerError = parseHeaderOverrideJson(headersJson).error;
|
||||
const bodyError = parseBodyOverrideJson(bodyJson).error;
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="space-y-1">
|
||||
<FormLabel>
|
||||
{t("providerForm.localProxyRequestOverrides", {
|
||||
defaultValue: "本地代理请求覆盖",
|
||||
})}
|
||||
</FormLabel>
|
||||
<p className="text-xs text-fg-2">
|
||||
{t("providerForm.localProxyRequestOverridesHint", {
|
||||
defaultValue:
|
||||
"仅在本地路由/代理接管后生效,应用于协议转换后的上游请求。",
|
||||
})}
|
||||
</p>
|
||||
<div className="flex items-center gap-0.5">
|
||||
<FormLabel>{label}</FormLabel>
|
||||
{help ? <HelpTip title={label}>{help}</HelpTip> : null}
|
||||
</div>
|
||||
{!help && (
|
||||
<p className="text-xs text-fg-2">
|
||||
{t("providerForm.localProxyRequestOverridesHint", {
|
||||
defaultValue:
|
||||
"仅在本地路由/代理接管后生效,应用于协议转换后的上游请求。",
|
||||
})}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { FormLabel } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { HelpTip } from "@/components/ui/help-tip";
|
||||
import { Link2, Zap } from "lucide-react";
|
||||
import { REQUIRED_LABEL } from "../BasicFormFields";
|
||||
|
||||
@@ -12,6 +13,8 @@ interface EndpointFieldProps {
|
||||
onChange: (value: string) => void;
|
||||
placeholder: string;
|
||||
hint?: string;
|
||||
/** 填写说明放进字段名后的「?」,不占页面;和 `hint` 二选一。完整 URL 的提示照常显示。 */
|
||||
help?: string;
|
||||
fullUrlHint?: string;
|
||||
showManageButton?: boolean;
|
||||
onManageClick?: () => void;
|
||||
@@ -28,6 +31,7 @@ export function EndpointField({
|
||||
onChange,
|
||||
placeholder,
|
||||
hint,
|
||||
help,
|
||||
fullUrlHint,
|
||||
showManageButton = true,
|
||||
onManageClick,
|
||||
@@ -54,9 +58,14 @@ export function EndpointField({
|
||||
<div className="space-y-2">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<FormLabel htmlFor={id} className={REQUIRED_LABEL}>
|
||||
{label}
|
||||
</FormLabel>
|
||||
<div className="flex items-center gap-0.5">
|
||||
<FormLabel htmlFor={id} className={REQUIRED_LABEL}>
|
||||
{label}
|
||||
</FormLabel>
|
||||
{help ? (
|
||||
<HelpTip title={label}>{help.replace(/^💡\s*/u, "")}</HelpTip>
|
||||
) : null}
|
||||
</div>
|
||||
{showFullUrlToggle && onFullUrlChange ? (
|
||||
<div className="flex items-center gap-2 rounded-full border border-border px-2.5 py-1">
|
||||
<Link2
|
||||
|
||||
+22
-20
@@ -1212,10 +1212,9 @@
|
||||
"rawConfig": "config.toml",
|
||||
"invalidToml": "Invalid config.toml: {{error}}",
|
||||
"defaultModelPlaceholder": "e.g. grok-4.5",
|
||||
"defaultModelHint": "The model Grok Build requests by default; change it anytime without waiting for a preset update.",
|
||||
"advancedSectionHint": "Includes upstream format, reasoning overrides and custom User-Agent. Providers using the Chat Completions or Anthropic Messages protocol require routing takeover to be enabled.",
|
||||
"reasoningEffortHint": "Enable when the upstream supports thinking-depth control such as low/high/max. Enabling this also turns on thinking mode and converts the request's reasoning effort into the upstream Chat parameter.",
|
||||
"maxOutputTokensHint": "The default 8192 ceiling can truncate long or thinking-heavy responses (stop_reason=max_tokens). This value overrides the request's max_tokens on the Anthropic path. Do not exceed the real output ceiling of the model/gateway or it may 400. Leave empty to use the default 8192.",
|
||||
"defaultModelHint": "The model Grok Build requests by default; change it anytime.",
|
||||
"reasoningEffortHint": "Turn on when the upstream supports thinking depth such as low/high/max. Also turns on thinking mode and maps the request's reasoning effort to the upstream Chat parameter.",
|
||||
"maxOutputTokensHint": "The default limit of 8192 can cut off long answers or deep thinking. This value is sent as Anthropic's max_tokens.",
|
||||
"keyFieldsHint": "The default model (models.default) and the model table it points to follow the provider; everything else is Grok Build global settings and applies to every provider after saving.",
|
||||
"inactiveFieldsHint": "This provider still stores {{count}} settings that do not follow the provider. Click one to copy its TOML and paste it above if you need it; the value stored in the provider is kept.",
|
||||
"inactiveFieldCopied": "Copied"
|
||||
@@ -1712,7 +1711,9 @@
|
||||
"fetchModelsNotSupported": "This provider does not support fetching model list",
|
||||
"fetchModelsEndpointNotFound": "No reachable models endpoint found. Please check the Base URL or confirm whether the provider exposes this API.",
|
||||
"fetchModelsTimeout": "Request timed out, please check network connection",
|
||||
"requiredFields": "Please fill in provider name, API endpoint, API Key and model"
|
||||
"requiredFields": "Please fill in provider name, API endpoint, API Key and model",
|
||||
"customUserAgentHelp": "Replaces the User-Agent of requests forwarded to the provider.",
|
||||
"localProxyRequestOverridesHelp": "Applies to the upstream request after format conversion."
|
||||
},
|
||||
"copilot": {
|
||||
"authSection": "GitHub Copilot Authentication",
|
||||
@@ -1880,25 +1881,25 @@
|
||||
"upstreamFormatLabel": "Upstream Format",
|
||||
"upstreamFormatAuto": "Automatic (model capabilities)",
|
||||
"upstreamFormatCopilotResponses": "Responses (routing required)",
|
||||
"upstreamFormatCopilotHint": "Automatic mode prefers Responses when supported by the model, otherwise Chat Completions. You can also select a protocol explicitly; models that do not support it will return an error. All modes require Codex routing takeover to inject Copilot account credentials.",
|
||||
"upstreamFormatHint": "Pick Responses when your provider is natively a Responses API (direct, no format conversion); pick Chat when it uses the Chat Completions protocol; pick Anthropic Messages when it only offers the native Anthropic Messages protocol. Chat and Anthropic Messages both require routing takeover to convert to Responses.",
|
||||
"upstreamFormatCopilotHint": "Auto prefers Responses when the model supports it, otherwise Chat Completions. You can also pick a protocol explicitly.",
|
||||
"upstreamFormatHint": "Pick the protocol the provider supports natively: Responses connects directly without conversion; routing converts Chat or Anthropic to Responses.",
|
||||
"upstreamFormatChat": "Chat Completions (routing required)",
|
||||
"upstreamFormatResponses": "Responses (native)",
|
||||
"upstreamFormatAnthropic": "Anthropic Messages (routing required)",
|
||||
"anthropicAuthFieldLabel": "Auth field",
|
||||
"anthropicAuthFieldAuthToken": "ANTHROPIC_AUTH_TOKEN (Authorization)",
|
||||
"anthropicAuthFieldApiKey": "ANTHROPIC_API_KEY (x-api-key)",
|
||||
"anthropicAuthFieldHint": "Choose which header carries the API key to the gateway: ANTHROPIC_AUTH_TOKEN sends Authorization: Bearer; ANTHROPIC_API_KEY sends x-api-key. Only one is sent.",
|
||||
"anthropicAuthFieldHint": "Pick the header the gateway reads the API key from. Only one is sent.",
|
||||
"impersonateClaudeCodeLabel": "Emulate Claude Code client",
|
||||
"impersonateClaudeCodeHint": "Enable when the gateway (or its upstream) restricts usage to Claude Code: spoofs the User-Agent, anthropic-beta and x-app headers, and injects the Claude Code identity as the first system prompt line.",
|
||||
"impersonateClaudeCodeHint": "Turn on when the gateway only accepts Claude Code: sends Claude Code's request headers and puts its identity on the first line of the system prompt.",
|
||||
"maxOutputTokensLabel": "Max output tokens",
|
||||
"maxOutputTokensPlaceholder": "Leave empty to use the default 8192",
|
||||
"maxOutputTokensHint": "Codex does not forward model_max_output_tokens in the request body, so the default 8192 ceiling can truncate long or thinking-heavy responses (stop_reason=max_tokens). This value overrides the request's max_tokens on the Anthropic path. Do not exceed the real output ceiling of the model/gateway or it may 400. Leave empty to use the default 8192.",
|
||||
"maxOutputTokensHint": "Codex sends no output limit, so the default 8192 can cut off long answers or deep thinking. This value is sent as Anthropic's max_tokens.",
|
||||
"promptCacheRoutingLabel": "Prompt cache routing",
|
||||
"promptCacheRoutingAuto": "Auto (recommended)",
|
||||
"promptCacheRoutingEnabled": "Enabled",
|
||||
"promptCacheRoutingDisabled": "Disabled",
|
||||
"promptCacheRoutingHint": "Auto sends prompt_cache_key only to known-compatible upstreams. Enable it for other compatible gateways, or disable it if a strict gateway rejects unknown fields with HTTP 400. Only a stable client-provided session ID is used.",
|
||||
"promptCacheRoutingHint": "Auto: send prompt_cache_key only to known-compatible upstreams. On: for other compatible gateways. Off: avoid 400s from strict gateways that reject unknown fields.",
|
||||
"upstreamModelName": "Upstream Model Name",
|
||||
"upstreamModelNameHint": "For Chat format, enter the real upstream model here; routing converts Codex Responses requests to Chat Completions while keeping this model.",
|
||||
"modelNamePlaceholder": "e.g., gpt-5-codex",
|
||||
@@ -1912,15 +1913,15 @@
|
||||
"modelMetadataAdvancedHint": "Overrides Codex metadata for unknown models; clearing a field removes the matching config.toml entry.",
|
||||
"defaultModelLabel": "Default Model",
|
||||
"defaultModelPlaceholder": "e.g. gpt-5.6-sol",
|
||||
"defaultModelHint": "The model Codex requests by default; change it anytime without waiting for a preset update. Once you add a model list, its first row is the default model.",
|
||||
"defaultModelHint": "The model Codex requests by default. Once you add a model list, its first row is the default model.",
|
||||
"subagentModelLabel": "Sub-agent Model",
|
||||
"subagentModelPlaceholder": "Leave empty to follow the main model",
|
||||
"subagentReasoningEffortLabel": "Sub-agent reasoning effort",
|
||||
"subagentReasoningEffortDefault": "Default effort",
|
||||
"subagentModelHint": "The model and reasoning effort Codex sub-agents use by default. When empty, sub-agents use the main agent's; with only a model set, they use that model's default effort. Not applied in Aggregation mode, where sub-agents follow the main model.",
|
||||
"subagentModelHint": "The model and reasoning effort Codex sub-agents use by default. Empty follows the main agent; a model alone uses its own default effort. Ignored in Aggregation mode, where sub-agents follow the main model.",
|
||||
"subagentModelNotInCatalog": "This model is not in the model list: Codex can't get its context window, and when routing converts requests to Chat / Anthropic it is replaced by the default model.",
|
||||
"modelListHint": "These models appear in Codex's /model menu with their own context window and reasoning levels. Restart Codex after changes.",
|
||||
"modelListDefaultHelp": "The first row is the default model Codex uses at startup. With an empty list, you can set the default model separately below.",
|
||||
"modelListHint": "Restart Codex after changes.",
|
||||
"modelListDefaultHelp": "These models appear in Codex's /model menu with their own context window and reasoning levels. The first row is the default model.",
|
||||
"addCatalogModel": "Add manually",
|
||||
"modelListTitle": "Models",
|
||||
"stackModelListHint": "These models appear in Codex's /model menu; picking one sends requests straight to this provider. Restart Codex after changes.",
|
||||
@@ -1944,15 +1945,16 @@
|
||||
"defaultReasoningLevelPlaceholder": "Auto",
|
||||
"defaultReasoningLevelTip": "Default level: {{level}}",
|
||||
"reasoningModeToggle": "Supports Thinking Mode",
|
||||
"reasoningModeHint": "Enable when the upstream Chat Completions API supports toggling thinking on/off. Providers like Kimi, GLM and Qwen usually fall into this category.",
|
||||
"reasoningModeHint": "Turn on when the upstream Chat API can switch thinking on and off. Kimi, GLM and Qwen usually can.",
|
||||
"reasoningEffortToggle": "Supports Reasoning Effort",
|
||||
"reasoningEffortHint": "Enable when the upstream supports thinking-depth control such as low/high/max. Enabling this also turns on thinking mode and converts Codex's reasoning.effort into the upstream Chat parameter.",
|
||||
"reasoningEffortHint": "Turn on when the upstream supports thinking depth such as low/high/max. Also turns on thinking mode and maps Codex's reasoning.effort to the upstream Chat parameter.",
|
||||
"reasoningGroupTitle": "Reasoning Capability",
|
||||
"reasoningSectionHint": "Preset providers are configured automatically; custom providers are inferred from name/URL. Override manually only when auto-detection is wrong.",
|
||||
"advancedSectionHint": "Includes upstream format, reasoning overrides and custom User-Agent. Providers using the Chat Completions / Anthropic Messages protocol require routing to be enabled.",
|
||||
"keyFieldsHint": "The endpoint, key, model, reasoning effort, context window and compatibility switches follow the provider; everything else is a global Codex setting that applies to every provider once saved.",
|
||||
"inactiveFieldsHint": "This provider still stores {{count}} settings that are not applied when switching. Click one to copy its TOML and paste it above if you need it; the stored values are kept.",
|
||||
"inactiveFieldCopied": "Copied"
|
||||
"inactiveFieldCopied": "Copied",
|
||||
"upstreamFormatCopilotRouteHint": "Every mode requires routing, which injects the Copilot account credentials. A protocol you pick explicitly fails for models that don't support it.",
|
||||
"maxOutputTokensWarning": "Don't exceed the real output limit of the model or gateway, or requests return 400.",
|
||||
"routeOnlySettingsHint": "The two settings below only apply in routing mode."
|
||||
},
|
||||
"geminiConfig": {
|
||||
"envFile": "Environment Variables (.env)",
|
||||
|
||||
+22
-20
@@ -1212,10 +1212,9 @@
|
||||
"rawConfig": "config.toml",
|
||||
"invalidToml": "config.toml の形式が不正です: {{error}}",
|
||||
"defaultModelPlaceholder": "例: grok-4.5",
|
||||
"defaultModelHint": "Grok Build がデフォルトでリクエストするモデルです。プリセットの更新を待たずにいつでも変更できます。",
|
||||
"advancedSectionHint": "上流フォーマット、思考機能、カスタム User-Agent の設定を含みます。Chat Completions / Anthropic Messages プロトコルを使用するプロバイダーはルーティング引き継ぎの有効化が必要です。",
|
||||
"reasoningEffortHint": "上流が low/high/max などの思考の深さの制御に対応している場合に有効化します。有効にすると思考モードも自動的にオンになり、リクエストの reasoning effort を上流の Chat パラメータに変換します。",
|
||||
"maxOutputTokensHint": "デフォルト上限 8192 では長い回答や深い思考時に切り詰められることがあります(stop_reason=max_tokens)。この値は Anthropic 経路で max_tokens を上書きします。モデル/ゲートウェイの実際の出力上限を超えると 400 になる場合があります。空欄でデフォルトの 8192 を使用します。",
|
||||
"defaultModelHint": "Grok Build がデフォルトでリクエストするモデルです。いつでも変更できます。",
|
||||
"reasoningEffortHint": "上流が low/high/max などの思考深度に対応しているときにオンにします。思考モードも同時にオンになり、リクエストの reasoning effort を上流の Chat パラメーターに変換します。",
|
||||
"maxOutputTokensHint": "既定の上限 8192 では長い回答や深い思考が切れることがあります。この値が Anthropic の max_tokens として送られます。",
|
||||
"keyFieldsHint": "デフォルトモデル(models.default)とそれが指すモデルテーブルはプロバイダーに合わせて切り替わります。それ以外は Grok Build のグローバル設定で、保存するとすべてのプロバイダーに適用されます。",
|
||||
"inactiveFieldsHint": "このプロバイダーには切り替えで反映されない設定が {{count}} 件保存されています。クリックすると TOML がコピーされるので、必要に応じて上に貼り付けてください。プロバイダーに保存された元の値は削除されません。",
|
||||
"inactiveFieldCopied": "コピーしました"
|
||||
@@ -1712,7 +1711,9 @@
|
||||
"fetchModelsNotSupported": "このプロバイダーはモデル一覧の取得に対応していません",
|
||||
"fetchModelsEndpointNotFound": "利用可能なモデル一覧エンドポイントが見つかりません。Base URL を確認するか、プロバイダーが該当 API を公開しているかご確認ください",
|
||||
"fetchModelsTimeout": "リクエストがタイムアウトしました。ネットワーク接続を確認してください",
|
||||
"requiredFields": "プロバイダー名、API エンドポイント、API Key、モデルを入力してください"
|
||||
"requiredFields": "プロバイダー名、API エンドポイント、API Key、モデルを入力してください",
|
||||
"customUserAgentHelp": "プロバイダーへ転送するリクエストの User-Agent を置き換えます。",
|
||||
"localProxyRequestOverridesHelp": "形式変換後に上流へ送るリクエストに適用されます。"
|
||||
},
|
||||
"copilot": {
|
||||
"authSection": "GitHub Copilot 認証",
|
||||
@@ -1880,25 +1881,25 @@
|
||||
"upstreamFormatLabel": "上流フォーマット",
|
||||
"upstreamFormatAuto": "自動(モデルの対応状況)",
|
||||
"upstreamFormatCopilotResponses": "Responses(ルーティング必須)",
|
||||
"upstreamFormatCopilotHint": "自動モードでは、モデルが対応していれば Responses を優先し、それ以外は Chat Completions を使用します。プロトコルを指定することもできますが、非対応のモデルではエラーになります。すべてのモードで Copilot アカウントの認証情報を付与するために Codex のルーティング引き継ぎが必要です。",
|
||||
"upstreamFormatHint": "プロバイダーがネイティブ Responses API なら Responses を選択(直結、フォーマット変換なし)。Chat Completions プロトコルなら Chat を選択。ネイティブ Anthropic Messages プロトコルのみ提供する場合は Anthropic Messages を選択。Chat と Anthropic Messages はどちらも Responses への変換にルーティング引き継ぎの有効化が必要です。",
|
||||
"upstreamFormatCopilotHint": "自動モードはモデルが対応していれば Responses を優先し、そうでなければ Chat Completions を使います。プロトコルを手動で指定することもできます。",
|
||||
"upstreamFormatHint": "プロバイダーがネイティブ対応するプロトコルを選びます。Responses は直接接続で変換なし、Chat と Anthropic はルーティングが Responses に変換します。",
|
||||
"upstreamFormatChat": "Chat Completions(ルーティング必須)",
|
||||
"upstreamFormatResponses": "Responses(ネイティブ)",
|
||||
"upstreamFormatAnthropic": "Anthropic Messages(ルーティング必須)",
|
||||
"anthropicAuthFieldLabel": "認証フィールド",
|
||||
"anthropicAuthFieldAuthToken": "ANTHROPIC_AUTH_TOKEN(Authorization)",
|
||||
"anthropicAuthFieldApiKey": "ANTHROPIC_API_KEY(x-api-key)",
|
||||
"anthropicAuthFieldHint": "ゲートウェイに API キーを渡すヘッダーを選択します。ANTHROPIC_AUTH_TOKEN は Authorization: Bearer、ANTHROPIC_API_KEY は x-api-key を送信します。送信されるのはどちらか一方のみです。",
|
||||
"anthropicAuthFieldHint": "ゲートウェイが API キーを読むヘッダーを選びます。送るのはどちらか一方だけです。",
|
||||
"impersonateClaudeCodeLabel": "Claude Code クライアントを模倣",
|
||||
"impersonateClaudeCodeHint": "ゲートウェイ(またはその上流)が Claude Code のみに制限している場合に有効化します。User-Agent・anthropic-beta・x-app ヘッダーを偽装し、システムプロンプトの先頭行に Claude Code のアイデンティティを注入します。",
|
||||
"impersonateClaudeCodeHint": "ゲートウェイが Claude Code しか受け付けないときにオンにします。Claude Code のリクエストヘッダーを送り、システムプロンプトの先頭行にその身元を挿入します。",
|
||||
"maxOutputTokensLabel": "最大出力トークン",
|
||||
"maxOutputTokensPlaceholder": "空欄の場合はデフォルトの 8192 を使用",
|
||||
"maxOutputTokensHint": "Codex は model_max_output_tokens をリクエストボディに含めないため、デフォルト上限 8192 では長い回答や深い思考時に切り詰められることがあります(stop_reason=max_tokens)。この値は Anthropic 経路で max_tokens を上書きします。モデル/ゲートウェイの実際の出力上限を超えると 400 になる場合があります。空欄でデフォルトの 8192 を使用します。",
|
||||
"maxOutputTokensHint": "Codex は出力上限を送らないため、既定の 8192 では長い回答や深い思考が切れることがあります。この値が Anthropic の max_tokens として送られます。",
|
||||
"promptCacheRoutingLabel": "プロンプトキャッシュルーティング",
|
||||
"promptCacheRoutingAuto": "自動(推奨)",
|
||||
"promptCacheRoutingEnabled": "有効",
|
||||
"promptCacheRoutingDisabled": "無効",
|
||||
"promptCacheRoutingHint": "自動モードでは、互換性を確認済みの上流にのみ prompt_cache_key を送信します。他の互換ゲートウェイでは有効にし、未知のフィールドを 400 で拒否する厳格なゲートウェイでは無効にしてください。クライアントが提供した安定したセッション ID のみを使用します。",
|
||||
"promptCacheRoutingHint": "自動:互換性が確認済みの上流にだけ prompt_cache_key を送ります。オン:その他の互換ゲートウェイ向け。オフ:未知のフィールドで 400 を返す厳格なゲートウェイを避けます。",
|
||||
"upstreamModelName": "上流モデル名",
|
||||
"upstreamModelNameHint": "Chat 形式ではここに実際の上流モデルを入力します。ルーティングで Codex の Responses リクエストを Chat Completions に変換し、このモデルを維持します。",
|
||||
"modelNamePlaceholder": "例: gpt-5-codex",
|
||||
@@ -1912,15 +1913,15 @@
|
||||
"modelMetadataAdvancedHint": "未知のモデル向けに Codex メタデータを上書きします。空にすると対応する config.toml 設定を削除します。",
|
||||
"defaultModelLabel": "デフォルトモデル",
|
||||
"defaultModelPlaceholder": "例: gpt-5.6-sol",
|
||||
"defaultModelHint": "Codex がデフォルトでリクエストするモデルです。プリセットの更新を待たずにいつでも変更できます。モデル一覧を追加すると、その先頭行がデフォルトモデルになります。",
|
||||
"defaultModelHint": "Codex がデフォルトでリクエストするモデルです。モデル一覧を追加すると、その先頭行がデフォルトモデルになります。",
|
||||
"subagentModelLabel": "サブエージェントモデル",
|
||||
"subagentModelPlaceholder": "空欄ならメインモデルに従う",
|
||||
"subagentReasoningEffortLabel": "サブエージェントの推論強度",
|
||||
"subagentReasoningEffortDefault": "デフォルト強度",
|
||||
"subagentModelHint": "Codex が起動するサブエージェントのデフォルトのモデルと推論強度です。空欄ならメインエージェントと同じものを使い、モデルだけ指定するとそのモデルのデフォルト強度を使います。集約モードでは適用されず、サブエージェントはメインモデルに従います。",
|
||||
"subagentModelHint": "Codex が起動するサブエージェントの既定モデルと推論強度です。空欄ならメインエージェントに従い、モデルだけ指定するとそのモデルの既定強度になります。集約モードでは無効で、メインモデルに従います。",
|
||||
"subagentModelNotInCatalog": "このモデルはモデル一覧にありません。Codex はコンテキストウィンドウを取得できず、ルーティングで Chat / Anthropic 形式に変換する際はデフォルトモデルに置き換えられます。",
|
||||
"modelListHint": "これらのモデルは、それぞれのコンテキストウィンドウと思考レベル付きで Codex の /model に表示されます。変更後は Codex を再起動してください。",
|
||||
"modelListDefaultHelp": "先頭の行がデフォルトモデルで、Codex の起動時に使われます。一覧が空のときは、下でデフォルトモデルを個別に設定できます。",
|
||||
"modelListHint": "変更後は Codex を再起動してください。",
|
||||
"modelListDefaultHelp": "これらのモデルは、それぞれのコンテキストウィンドウと思考レベル付きで Codex の /model に表示されます。先頭の行がデフォルトモデルです。",
|
||||
"addCatalogModel": "手動で追加",
|
||||
"modelListTitle": "モデル一覧",
|
||||
"stackModelListHint": "これらのモデルは Codex の /model に表示され、選ぶとリクエストがこのプロバイダーへ直接送られます。変更後は Codex を再起動してください。",
|
||||
@@ -1944,15 +1945,16 @@
|
||||
"defaultReasoningLevelPlaceholder": "自動",
|
||||
"defaultReasoningLevelTip": "デフォルトレベル:{{level}}",
|
||||
"reasoningModeToggle": "思考モードに対応",
|
||||
"reasoningModeHint": "上流の Chat Completions API が思考(thinking)のオン/オフ切り替えに対応している場合に有効化します。Kimi、GLM、Qwen などが通常このタイプに該当します。",
|
||||
"reasoningModeHint": "上流の Chat API で thinking のオン・オフを切り替えられるときにオンにします。Kimi、GLM、Qwen などが該当します。",
|
||||
"reasoningEffortToggle": "思考レベルに対応",
|
||||
"reasoningEffortHint": "上流が low/high/max などの思考の深さの制御に対応している場合に有効化します。有効にすると思考モードも自動的にオンになり、Codex の reasoning.effort を上流の Chat パラメータに変換します。",
|
||||
"reasoningEffortHint": "上流が low/high/max などの思考深度に対応しているときにオンにします。思考モードも同時にオンになり、Codex の reasoning.effort を上流の Chat パラメーターに変換します。",
|
||||
"reasoningGroupTitle": "思考能力",
|
||||
"reasoningSectionHint": "プリセットの供給元は自動的に設定され、カスタム供給元は名前/URL から自動推論されます。自動識別が正しくない場合のみ手動で上書きしてください。",
|
||||
"advancedSectionHint": "上流フォーマット、思考能力、カスタム User-Agent の設定を含みます。Chat Completions / Anthropic Messages プロトコルを使用するプロバイダーはルーティングの有効化が必要です。",
|
||||
"keyFieldsHint": "エンドポイント、キー、モデル、推論レベル、コンテキストウィンドウ、互換スイッチはプロバイダーに合わせて切り替わります。それ以外は Codex のグローバル設定で、保存するとすべてのプロバイダーに適用されます。",
|
||||
"inactiveFieldsHint": "このプロバイダーには切り替え時に適用されない設定が {{count}} 件保存されています。クリックすると TOML をコピーできるので、必要なら上に貼り付けてください。保存済みの値は削除されません。",
|
||||
"inactiveFieldCopied": "コピーしました"
|
||||
"inactiveFieldCopied": "コピーしました",
|
||||
"upstreamFormatCopilotRouteHint": "どのモードでもルーティングが必要で、ルーティングが Copilot アカウントの認証情報を注入します。手動指定したプロトコルにモデルが対応していないとエラーになります。",
|
||||
"maxOutputTokensWarning": "モデルやゲートウェイの実際の出力上限を超えないでください。超えると 400 が返ります。",
|
||||
"routeOnlySettingsHint": "以下の二つはルーティングモードでのみ有効です。"
|
||||
},
|
||||
"geminiConfig": {
|
||||
"envFile": "環境変数 (.env)",
|
||||
|
||||
+22
-20
@@ -1213,10 +1213,9 @@
|
||||
"rawConfig": "config.toml",
|
||||
"invalidToml": "config.toml 格式錯誤:{{error}}",
|
||||
"defaultModelPlaceholder": "例如: grok-4.5",
|
||||
"defaultModelHint": "Grok Build 預設請求的模型,隨時可改,無需等待軟體更新供應商範本。",
|
||||
"advancedSectionHint": "包含上游格式、思考能力與自訂 User-Agent。使用 Chat Completions / Anthropic Messages 協定的供應商需開啟路由接管才能使用。",
|
||||
"reasoningEffortHint": "上游支援 low/high/max 等思考深度控制時啟用。啟用後會自動啟用思考模式,並把請求中的 reasoning effort 轉成上游 Chat 參數。",
|
||||
"maxOutputTokensHint": "預設上限 8192 容易在長回答或深度思考時被截斷(stop_reason=max_tokens)。此處設定會作為 Anthropic 的 max_tokens 覆蓋請求值。請勿超過該模型/閘道的真實輸出上限,否則可能 400。留空使用預設 8192。",
|
||||
"defaultModelHint": "Grok Build 預設請求的模型,隨時可改。",
|
||||
"reasoningEffortHint": "上游支援 low/high/max 等思考深度時開啟。會同時開啟思考模式,並把請求中的 reasoning effort 轉成上游 Chat 參數。",
|
||||
"maxOutputTokensHint": "預設上限 8192,長回答或深度思考容易被截斷。這裡的值會作為 Anthropic 的 max_tokens 發出。",
|
||||
"keyFieldsHint": "預設模型(models.default)和它指向的模型表隨供應商切換;其餘是 Grok Build 全域設定,儲存後對所有供應商生效。",
|
||||
"inactiveFieldsHint": "這個供應商還保存著 {{count}} 個不隨切換生效的設定。點擊複製它的 TOML,依需要貼到上方;供應商裡保存的原值不會刪除。",
|
||||
"inactiveFieldCopied": "已複製"
|
||||
@@ -1713,7 +1712,9 @@
|
||||
"fetchModelsNotSupported": "該供應商不支援取得模型清單",
|
||||
"fetchModelsEndpointNotFound": "未找到可用的模型清單端點,請檢查 Base URL 或確認供應商是否開放該 API",
|
||||
"fetchModelsTimeout": "請求逾時,請檢查網路連線",
|
||||
"requiredFields": "請填寫供應商名稱、API 位址、API Key 和模型"
|
||||
"requiredFields": "請填寫供應商名稱、API 位址、API Key 和模型",
|
||||
"customUserAgentHelp": "替換轉發到供應商的請求裡的 User-Agent。",
|
||||
"localProxyRequestOverridesHelp": "作用於格式轉換後發給上游的請求。"
|
||||
},
|
||||
"copilot": {
|
||||
"authSection": "GitHub Copilot 驗證",
|
||||
@@ -1886,36 +1887,36 @@
|
||||
"upstreamFormatLabel": "上游格式",
|
||||
"upstreamFormatAuto": "自動(依模型能力)",
|
||||
"upstreamFormatCopilotResponses": "Responses(需開啟路由)",
|
||||
"upstreamFormatCopilotHint": "自動模式依模型能力優先使用 Responses,否則使用 Chat Completions;也可手動指定協定,不支援該協定的模型將回報錯誤。所有模式都需要開啟 Codex 路由接管,以注入 Copilot 帳號憑證。",
|
||||
"upstreamFormatHint": "供應商原生為 Responses API 就選 Responses(直連,不轉換格式);使用 Chat Completions 協定就選 Chat;供應商只提供原生 Anthropic Messages 協定就選 Anthropic Messages。Chat 與 Anthropic Messages 均需開啟路由接管才能轉換為 Responses。",
|
||||
"upstreamFormatCopilotHint": "自動模式依模型能力優先使用 Responses,否則使用 Chat Completions;也可以手動指定協定。",
|
||||
"upstreamFormatHint": "看供應商原生支援哪種協定:Responses 直連、不轉換格式;Chat 或 Anthropic 由路由轉成 Responses。",
|
||||
"upstreamFormatChat": "Chat Completions(需開啟路由)",
|
||||
"upstreamFormatResponses": "Responses(原生)",
|
||||
"upstreamFormatAnthropic": "Anthropic Messages(需開啟路由)",
|
||||
"anthropicAuthFieldLabel": "認證欄位",
|
||||
"anthropicAuthFieldAuthToken": "ANTHROPIC_AUTH_TOKEN(Authorization)",
|
||||
"anthropicAuthFieldApiKey": "ANTHROPIC_API_KEY(x-api-key)",
|
||||
"anthropicAuthFieldHint": "選擇閘道接收 API Key 的請求標頭:ANTHROPIC_AUTH_TOKEN 傳送 Authorization: Bearer;ANTHROPIC_API_KEY 傳送 x-api-key。兩者只傳其一。",
|
||||
"anthropicAuthFieldHint": "依閘道讀取 API Key 的請求標頭選擇,兩者只發其一。",
|
||||
"impersonateClaudeCodeLabel": "模擬 Claude Code 用戶端",
|
||||
"impersonateClaudeCodeHint": "閘道或其上游限制只能透過 Claude Code 使用時開啟:偽裝 User-Agent、anthropic-beta、x-app 請求標頭,並在系統提示首行注入 Claude Code 身分。",
|
||||
"impersonateClaudeCodeHint": "閘道只允許 Claude Code 使用時開啟:偽裝 Claude Code 的請求標頭,並在系統提示首行注入它的身分。",
|
||||
"maxOutputTokensLabel": "最大輸出 tokens",
|
||||
"maxOutputTokensPlaceholder": "留空則使用預設 8192",
|
||||
"maxOutputTokensHint": "Codex 不會把 model_max_output_tokens 寫進請求體,預設上限 8192 容易在長回答或深度思考時被截斷(stop_reason=max_tokens)。此處設定會作為 Anthropic 的 max_tokens 覆蓋請求值。請勿超過該模型/閘道的真實輸出上限,否則可能 400。留空使用預設 8192。",
|
||||
"maxOutputTokensHint": "Codex 不帶輸出上限,預設 8192,長回答或深度思考容易被截斷。這裡的值會作為 Anthropic 的 max_tokens 發出。",
|
||||
"promptCacheRoutingLabel": "提示詞快取路由",
|
||||
"promptCacheRoutingAuto": "自動(建議)",
|
||||
"promptCacheRoutingEnabled": "開啟",
|
||||
"promptCacheRoutingDisabled": "關閉",
|
||||
"promptCacheRoutingHint": "自動模式僅對已確認相容的上游傳送 prompt_cache_key;開啟可用於其他相容閘道,關閉可避免嚴格閘道因未知欄位回傳 400。只使用客戶端提供的穩定工作階段 ID。",
|
||||
"promptCacheRoutingHint": "自動:只對確認相容的上游發送 prompt_cache_key。開啟:用於其他相容閘道。關閉:避免嚴格閘道因未知欄位回傳 400。",
|
||||
"defaultModelLabel": "預設模型",
|
||||
"defaultModelPlaceholder": "例如: gpt-5.6-sol",
|
||||
"defaultModelHint": "Codex 預設請求的模型,隨時可改,無需等待軟體更新供應商範本。加入模型列表後,列表第一行就是預設模型。",
|
||||
"defaultModelHint": "Codex 預設請求的模型。加入模型列表後,列表第一行就是預設模型。",
|
||||
"subagentModelLabel": "子代理模型",
|
||||
"subagentModelPlaceholder": "留空則跟隨主模型",
|
||||
"subagentReasoningEffortLabel": "子代理推理強度",
|
||||
"subagentReasoningEffortDefault": "預設強度",
|
||||
"subagentModelHint": "Codex 派出的子代理預設使用的模型和推理強度。留空時子代理沿用主代理的;只填模型時使用該模型自己的預設強度。聚合模式下不生效,子代理跟隨主模型。",
|
||||
"subagentModelHint": "Codex 派出的子代理預設使用的模型和推理強度。留空時沿用主代理的;只填模型時使用該模型自己的預設強度。聚合模式下不生效,子代理跟隨主模型。",
|
||||
"subagentModelNotInCatalog": "該模型不在模型列表中:Codex 取得不到它的上下文視窗;經路由轉成 Chat / Anthropic 協定時會被換成預設模型。",
|
||||
"modelListHint": "這些模型會出現在 Codex 的 /model 裡,帶上各自的上下文視窗和思考等級。修改後需要重新啟動 Codex。",
|
||||
"modelListDefaultHelp": "第一行是預設模型,Codex 啟動時使用它。列表為空時,可以在下方單獨填寫預設模型。",
|
||||
"modelListHint": "修改後需要重新啟動 Codex。",
|
||||
"modelListDefaultHelp": "這些模型會出現在 Codex 的 /model 裡,帶上各自的上下文視窗和思考等級。第一行是預設模型。",
|
||||
"addCatalogModel": "手動新增",
|
||||
"modelListTitle": "模型列表",
|
||||
"stackModelListHint": "這些模型會出現在 Codex 的 /model 裡,選中後請求直達這家。修改後需要重新啟動 Codex。",
|
||||
@@ -1945,15 +1946,16 @@
|
||||
"modelMetadataAdvanced": "模型中繼資料進階選項",
|
||||
"modelMetadataAdvancedHint": "用於未知模型的 Codex 中繼資料覆寫;清空欄位會從 config.toml 刪除對應設定。",
|
||||
"reasoningModeToggle": "支援思考模式",
|
||||
"reasoningModeHint": "上游 Chat Completions 介面支援開啟或關閉 thinking 時啟用。Kimi、GLM、Qwen 等通常屬於這一類。",
|
||||
"reasoningModeHint": "上游 Chat 介面能開關 thinking 時開啟,Kimi、GLM、Qwen 等通常屬於這一類。",
|
||||
"reasoningEffortToggle": "支援思考等級",
|
||||
"reasoningEffortHint": "上游支援 low/high/max 等思考深度控制時啟用。啟用後會自動啟用思考模式,並把 Codex 的 reasoning.effort 轉成上游 Chat 參數。",
|
||||
"reasoningEffortHint": "上游支援 low/high/max 等思考深度時開啟。會同時開啟思考模式,並把 Codex 的 reasoning.effort 轉成上游 Chat 參數。",
|
||||
"reasoningGroupTitle": "思考能力",
|
||||
"reasoningSectionHint": "預設供應商已自動設定;自訂供應商會按名稱/位址自動推斷。僅當自動識別不準時才需手動覆寫。",
|
||||
"advancedSectionHint": "包含上游格式、思考能力與自訂 User-Agent。使用 Chat Completions / Anthropic Messages 協定的供應商需開啟路由才能使用。",
|
||||
"keyFieldsHint": "位址、Key、模型、推理檔位、上下文視窗和相容開關隨供應商切換;其餘是 Codex 全域設定,儲存後對所有供應商生效。",
|
||||
"inactiveFieldsHint": "這個供應商還保存著 {{count}} 個不隨切換生效的設定。點擊可複製它的 TOML,依需要貼到上方;供應商裡保存的原值不會刪除。",
|
||||
"inactiveFieldCopied": "已複製"
|
||||
"inactiveFieldCopied": "已複製",
|
||||
"upstreamFormatCopilotRouteHint": "所有模式都需要開啟路由,由路由注入 Copilot 帳號憑證;手動指定的協定模型不支援時會報錯。",
|
||||
"maxOutputTokensWarning": "不要超過模型或閘道的真實輸出上限,否則會回傳 400。",
|
||||
"routeOnlySettingsHint": "以下兩項只在路由模式下生效。"
|
||||
},
|
||||
"geminiConfig": {
|
||||
"envFile": "環境變數 (.env)",
|
||||
|
||||
+22
-20
@@ -1212,10 +1212,9 @@
|
||||
"rawConfig": "config.toml",
|
||||
"invalidToml": "config.toml 格式错误:{{error}}",
|
||||
"defaultModelPlaceholder": "例如: grok-4.5",
|
||||
"defaultModelHint": "Grok Build 默认请求的模型,随时可改,无需等待预设更新。",
|
||||
"advancedSectionHint": "包含上游格式、思考能力与自定义 User-Agent。使用 Chat Completions / Anthropic Messages 协议的供应商需开启路由接管才能使用。",
|
||||
"reasoningEffortHint": "上游支持 low/high/max 等思考深度控制时启用。启用后会自动启用思考模式,并把请求中的 reasoning effort 转成上游 Chat 参数。",
|
||||
"maxOutputTokensHint": "默认上限 8192 容易在长回答或深度思考时被截断(stop_reason=max_tokens)。此处设置会作为 Anthropic 的 max_tokens 覆盖请求值。请勿超过该模型/网关的真实输出上限,否则可能 400。留空使用默认 8192。",
|
||||
"defaultModelHint": "Grok Build 默认请求的模型,随时可改。",
|
||||
"reasoningEffortHint": "上游支持 low/high/max 等思考深度时打开。会同时打开思考模式,并把请求中的 reasoning effort 转成上游 Chat 参数。",
|
||||
"maxOutputTokensHint": "默认上限 8192,长回答或深度思考容易被截断。这里的值会作为 Anthropic 的 max_tokens 发出。",
|
||||
"keyFieldsHint": "默认模型(models.default)和它指向的模型表随供应商切换;其余是 Grok Build 全局设置,保存后对所有供应商生效。",
|
||||
"inactiveFieldsHint": "这个供应商还保存着 {{count}} 个不随切换生效的设置。点击复制它的 TOML,按需粘贴到上方;供应商里保存的原值不会删除。",
|
||||
"inactiveFieldCopied": "已复制"
|
||||
@@ -1712,7 +1711,9 @@
|
||||
"fetchModelsNotSupported": "该供应商不支持获取模型列表",
|
||||
"fetchModelsEndpointNotFound": "未找到可用的模型列表端点,请检查 Base URL 或确认供应商是否开放该接口",
|
||||
"fetchModelsTimeout": "请求超时,请检查网络连接",
|
||||
"requiredFields": "请填写供应商名称、API 地址、API Key 和模型"
|
||||
"requiredFields": "请填写供应商名称、API 地址、API Key 和模型",
|
||||
"customUserAgentHelp": "替换转发到供应商的请求里的 User-Agent。",
|
||||
"localProxyRequestOverridesHelp": "作用于格式转换后发给上游的请求。"
|
||||
},
|
||||
"copilot": {
|
||||
"authSection": "GitHub Copilot 认证",
|
||||
@@ -1880,25 +1881,25 @@
|
||||
"upstreamFormatLabel": "上游格式",
|
||||
"upstreamFormatAuto": "自动(按模型能力)",
|
||||
"upstreamFormatCopilotResponses": "Responses(需开启路由)",
|
||||
"upstreamFormatCopilotHint": "自动模式根据模型能力优先使用 Responses,否则使用 Chat Completions;也可手动指定协议,不支持该协议的模型将报错。所有模式都需要开启 Codex 路由接管,以注入 Copilot 账号凭据。",
|
||||
"upstreamFormatHint": "供应商原生为 Responses API 就选 Responses(直连,不转换格式);使用 Chat Completions 协议就选 Chat;供应商只提供原生 Anthropic Messages 协议就选 Anthropic Messages。Chat 与 Anthropic Messages 均需开启路由接管才能转换为 Responses。",
|
||||
"upstreamFormatCopilotHint": "自动模式按模型能力优先用 Responses,否则用 Chat Completions;也可以手动指定协议。",
|
||||
"upstreamFormatHint": "看供应商原生支持哪种协议:Responses 直连、不转换格式;Chat 或 Anthropic 由路由转成 Responses。",
|
||||
"upstreamFormatChat": "Chat Completions(需开启路由)",
|
||||
"upstreamFormatResponses": "Responses(原生)",
|
||||
"upstreamFormatAnthropic": "Anthropic Messages(需开启路由)",
|
||||
"anthropicAuthFieldLabel": "认证字段",
|
||||
"anthropicAuthFieldAuthToken": "ANTHROPIC_AUTH_TOKEN(Authorization)",
|
||||
"anthropicAuthFieldApiKey": "ANTHROPIC_API_KEY(x-api-key)",
|
||||
"anthropicAuthFieldHint": "选择网关接收 API Key 的请求头:ANTHROPIC_AUTH_TOKEN 发送 Authorization: Bearer;ANTHROPIC_API_KEY 发送 x-api-key。两者只发其一。",
|
||||
"anthropicAuthFieldHint": "按网关读取 API Key 的请求头选择,两者只发其一。",
|
||||
"impersonateClaudeCodeLabel": "模拟 Claude Code 客户端",
|
||||
"impersonateClaudeCodeHint": "网关或其上游限制只能通过 Claude Code 使用时开启:伪装 User-Agent、anthropic-beta、x-app 请求头,并在系统提示首行注入 Claude Code 身份。",
|
||||
"impersonateClaudeCodeHint": "网关只允许 Claude Code 使用时打开:伪装 Claude Code 的请求头,并在系统提示首行注入它的身份。",
|
||||
"maxOutputTokensLabel": "最大输出 tokens",
|
||||
"maxOutputTokensPlaceholder": "留空则使用默认 8192",
|
||||
"maxOutputTokensHint": "Codex 不会把 model_max_output_tokens 写进请求体,默认上限 8192 容易在长回答或深度思考时被截断(stop_reason=max_tokens)。此处设置会作为 Anthropic 的 max_tokens 覆盖请求值。请勿超过该模型/网关的真实输出上限,否则可能 400。留空使用默认 8192。",
|
||||
"maxOutputTokensHint": "Codex 不带输出上限,默认 8192,长回答或深度思考容易被截断。这里的值会作为 Anthropic 的 max_tokens 发出。",
|
||||
"promptCacheRoutingLabel": "提示词缓存路由",
|
||||
"promptCacheRoutingAuto": "自动(推荐)",
|
||||
"promptCacheRoutingEnabled": "开启",
|
||||
"promptCacheRoutingDisabled": "关闭",
|
||||
"promptCacheRoutingHint": "自动模式仅对已确认兼容的上游发送 prompt_cache_key;开启可用于其他兼容网关,关闭可避免严格网关因未知字段返回 400。只使用客户端提供的稳定会话 ID。",
|
||||
"promptCacheRoutingHint": "自动:只对确认兼容的上游发送 prompt_cache_key。开启:用于其他兼容网关。关闭:避免严格网关因未知字段返回 400。",
|
||||
"upstreamModelName": "上游模型名称",
|
||||
"upstreamModelNameHint": "Chat 格式下这里填写真实上游模型;路由会把 Codex 的 Responses 请求转换为 Chat Completions 并保持该模型。",
|
||||
"modelNamePlaceholder": "例如: gpt-5-codex",
|
||||
@@ -1912,15 +1913,15 @@
|
||||
"modelMetadataAdvancedHint": "用于未知模型的 Codex 元数据覆盖;清空字段会从 config.toml 删除对应配置。",
|
||||
"defaultModelLabel": "默认模型",
|
||||
"defaultModelPlaceholder": "例如: gpt-5.6-sol",
|
||||
"defaultModelHint": "Codex 默认请求的模型,随时可改,无需等待预设更新。添加模型列表后,列表第一行就是默认模型。",
|
||||
"defaultModelHint": "Codex 默认请求的模型。添加模型列表后,列表第一行就是默认模型。",
|
||||
"subagentModelLabel": "子代理模型",
|
||||
"subagentModelPlaceholder": "留空则跟随主模型",
|
||||
"subagentReasoningEffortLabel": "子代理推理强度",
|
||||
"subagentReasoningEffortDefault": "默认强度",
|
||||
"subagentModelHint": "Codex 派出的子代理默认用的模型和推理强度。留空时子代理沿用主代理的;只填模型时用该模型自己的默认强度。聚合模式下不生效,子代理跟随主模型。",
|
||||
"subagentModelHint": "Codex 派出的子代理默认用的模型和推理强度。留空时沿用主代理的;只填模型时用该模型自己的默认强度。聚合模式下不生效,子代理跟随主模型。",
|
||||
"subagentModelNotInCatalog": "该模型不在模型列表中:Codex 拿不到它的上下文窗口;经路由转成 Chat / Anthropic 协议时会被换成默认模型。",
|
||||
"modelListHint": "这些模型会出现在 Codex 的 /model 里,带上各自的上下文窗口和思考等级。修改后需要重启 Codex。",
|
||||
"modelListDefaultHelp": "第一行是默认模型,Codex 启动时用它。列表为空时,可以在下方单独填写默认模型。",
|
||||
"modelListHint": "修改后需要重启 Codex。",
|
||||
"modelListDefaultHelp": "这些模型会出现在 Codex 的 /model 里,带上各自的上下文窗口和思考等级。第一行是默认模型。",
|
||||
"addCatalogModel": "手动添加",
|
||||
"modelListTitle": "模型列表",
|
||||
"stackModelListHint": "这些模型会出现在 Codex 的 /model 里,选中后请求直达这家。修改后需要重启 Codex。",
|
||||
@@ -1944,15 +1945,16 @@
|
||||
"defaultReasoningLevelPlaceholder": "自动",
|
||||
"defaultReasoningLevelTip": "默认等级:{{level}}",
|
||||
"reasoningModeToggle": "支持思考模式",
|
||||
"reasoningModeHint": "上游 Chat Completions 接口支持开启或关闭 thinking 时启用。Kimi、GLM、Qwen 等通常属于这一类。",
|
||||
"reasoningModeHint": "上游 Chat 接口能开关 thinking 时打开,Kimi、GLM、Qwen 等通常属于这一类。",
|
||||
"reasoningEffortToggle": "支持思考等级",
|
||||
"reasoningEffortHint": "上游支持 low/high/max 等思考深度控制时启用。启用后会自动启用思考模式,并把 Codex 的 reasoning.effort 转成上游 Chat 参数。",
|
||||
"reasoningEffortHint": "上游支持 low/high/max 等思考深度时打开。会同时打开思考模式,并把 Codex 的 reasoning.effort 转成上游 Chat 参数。",
|
||||
"reasoningGroupTitle": "思考能力",
|
||||
"reasoningSectionHint": "预设供应商已自动配置;自定义供应商会按名称/地址自动推断。仅当自动识别不准时才需手动覆盖。",
|
||||
"advancedSectionHint": "包含上游格式、思考能力与自定义 User-Agent。使用 Chat Completions / Anthropic Messages 协议的供应商需开启路由才能使用。",
|
||||
"keyFieldsHint": "地址、Key、模型、推理档位、上下文窗口和兼容开关随供应商切换;其余是 Codex 全局设置,保存后对所有供应商生效。",
|
||||
"inactiveFieldsHint": "这个供应商还保存着 {{count}} 个不随切换生效的设置。点击复制它的 TOML,按需粘贴到上方;供应商里保存的原值不会删除。",
|
||||
"inactiveFieldCopied": "已复制"
|
||||
"inactiveFieldCopied": "已复制",
|
||||
"upstreamFormatCopilotRouteHint": "所有模式都需要开启路由,由路由注入 Copilot 账号凭据;手动指定的协议模型不支持时会报错。",
|
||||
"maxOutputTokensWarning": "不要超过模型或网关的真实输出上限,否则会返回 400。",
|
||||
"routeOnlySettingsHint": "以下两项只在路由模式下生效。"
|
||||
},
|
||||
"geminiConfig": {
|
||||
"envFile": "环境变量 (.env)",
|
||||
|
||||
@@ -120,7 +120,8 @@ describe("CodexFormFields direct layout", () => {
|
||||
});
|
||||
|
||||
expect(screen.getByText("模型列表")).toBeVisible();
|
||||
expect(screen.getByRole("button", { name: "默认模型" })).toBeVisible();
|
||||
// 「第一行是默认模型」写在「模型列表」后面的「?」里。
|
||||
expect(screen.getByRole("button", { name: "模型列表" })).toBeVisible();
|
||||
expect(screen.queryByText("上游格式")).toBeNull();
|
||||
expect(document.getElementById("codexDefaultModel")).toBeNull();
|
||||
expect(
|
||||
@@ -170,3 +171,31 @@ describe("CodexFormFields direct layout", () => {
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("CodexFormFields help tips", () => {
|
||||
it("puts field explanations behind「?」and keeps consequences on the page", () => {
|
||||
renderCodexForm({
|
||||
apiFormat: "anthropic",
|
||||
// 有地址栏的卡才显示上游格式。
|
||||
shouldShowSpeedTest: true,
|
||||
catalogModels: [],
|
||||
onCatalogModelsChange: vi.fn(),
|
||||
});
|
||||
|
||||
for (const name of [
|
||||
"codexConfig.apiUrlLabel",
|
||||
"默认模型",
|
||||
"子代理模型",
|
||||
]) {
|
||||
expect(screen.getByRole("button", { name })).toBeInTheDocument();
|
||||
}
|
||||
// Anthropic 格式的高级区自动展开:后果提示仍在页面上,说明在字段名后的「?」里。
|
||||
for (const name of ["上游格式", "认证字段", "最大输出 tokens"]) {
|
||||
expect(screen.getByRole("button", { name })).toBeInTheDocument();
|
||||
}
|
||||
expect(
|
||||
screen.getByText("不要超过模型或网关的真实输出上限,否则会返回 400。"),
|
||||
).toBeVisible();
|
||||
expect(screen.getByText("以下两项只在路由模式下生效。")).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -280,11 +280,8 @@ context_window = 500000
|
||||
// Grok 没有模型映射目录,不应出现"映射第一行"条款
|
||||
expect(screen.queryByText(/映射第一行/)).toBeNull();
|
||||
|
||||
// Chat 格式且无已配置高级值时高级区默认折叠,折叠提示也应是 Grok 版本
|
||||
expect(
|
||||
screen.getByText(/Anthropic Messages 协议的供应商需开启路由接管/),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.queryByText(/模型映射、思考能力/)).toBeNull();
|
||||
// Chat 格式且无已配置高级值时高级区默认折叠,折叠时不再挂说明小字
|
||||
expect(screen.queryByText(/思考能力与自定义 User-Agent/)).toBeNull();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: /高级选项/ }));
|
||||
expect(
|
||||
@@ -320,9 +317,11 @@ context_window = 500000
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText(/^默认上限 8192 容易在长回答/)).toBeInTheDocument();
|
||||
// 说明在「?」里(读屏副本一直在页面上),页面上只留超限会 400 的提醒。
|
||||
expect(screen.getByText(/^默认上限 8192,长回答/)).toBeInTheDocument();
|
||||
expect(screen.queryByText(/^Codex 不带输出上限/)).toBeNull();
|
||||
expect(
|
||||
screen.queryByText(/Codex 不会把 model_max_output_tokens/),
|
||||
).toBeNull();
|
||||
screen.getByText("不要超过模型或网关的真实输出上限,否则会返回 400。"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user