Add Codex Chat-to-Responses bridge

- Add Codex provider API format selection and model mapping for Chat-only upstreams.
- Convert Codex Responses requests to Chat Completions and rebuild Chat responses as Responses output.
- Preserve reasoning_content across non-streaming, streaming, tool calls, and previous_response_id follow-ups.
- Add a bounded Codex Chat history cache for restoring tool calls before tool outputs.
- Cover Chat bridge, compact routing, streaming, and history recovery with focused tests.
This commit is contained in:
Jason
2026-05-19 19:06:00 +08:00
parent 5315fa284b
commit 74acf1e387
16 changed files with 1796 additions and 163 deletions
@@ -90,6 +90,7 @@ export function CodexFormFields({
const [fetchedModels, setFetchedModels] = useState<FetchedModel[]>([]);
const [isFetchingModels, setIsFetchingModels] = useState(false);
const isChatApiFormat = apiFormat === "openai_chat";
const handleFetchModels = useCallback(() => {
if (!codexBaseUrl || !codexApiKey) {
@@ -202,7 +203,11 @@ export function CodexFormFields({
htmlFor="codexModelName"
className="block text-sm font-medium text-foreground"
>
{t("codexConfig.modelName", { defaultValue: "模型名称" })}
{isChatApiFormat
? t("codexConfig.upstreamModelName", {
defaultValue: "上游模型名称",
})
: t("codexConfig.modelName", { defaultValue: "模型名称" })}
</label>
<Button
type="button"
@@ -231,13 +236,18 @@ export function CodexFormFields({
isLoading={isFetchingModels}
/>
<p className="text-xs text-muted-foreground">
{modelName.trim()
? t("codexConfig.modelNameHint", {
defaultValue: "指定使用的模型,将自动更新到 config.toml 中",
{isChatApiFormat
? t("codexConfig.upstreamModelNameHint", {
defaultValue:
"Chat 格式下这里填写真实上游模型;接管时 Codex 本地会使用兼容模型,并由路由映射回该模型。",
})
: t("providerForm.modelHint", {
defaultValue: "💡 留空将使用供应商的默认模型",
})}
: modelName.trim()
? t("codexConfig.modelNameHint", {
defaultValue: "指定使用的模型,将自动更新到 config.toml 中",
})
: t("providerForm.modelHint", {
defaultValue: "💡 留空将使用供应商的默认模型",
})}
</p>
</div>
)}
+2
View File
@@ -1080,6 +1080,8 @@
"saveFailed": "Save failed: {{error}}",
"modelNameHint": "Specify the model to use, will be auto-updated in config.toml",
"modelName": "Model Name",
"upstreamModelName": "Upstream Model Name",
"upstreamModelNameHint": "For Chat format, enter the real upstream model here; takeover writes a Codex-compatible local model and routing maps it back to this model.",
"modelNamePlaceholder": "e.g., gpt-5-codex",
"contextWindow1M": "1M Context Window",
"autoCompactLimit": "Auto Compact Limit",
+2
View File
@@ -1080,6 +1080,8 @@
"saveFailed": "保存に失敗しました: {{error}}",
"modelNameHint": "使用するモデルを指定します。config.toml に自動更新されます",
"modelName": "モデル名",
"upstreamModelName": "上流モデル名",
"upstreamModelNameHint": "Chat 形式ではここに実際の上流モデルを入力します。接管時は Codex 互換のローカルモデルを書き込み、ルーティングでこのモデルに戻します。",
"modelNamePlaceholder": "例: gpt-5-codex",
"contextWindow1M": "1M コンテキストウィンドウ",
"autoCompactLimit": "自動圧縮しきい値",
+2
View File
@@ -1080,6 +1080,8 @@
"saveFailed": "保存失败: {{error}}",
"modelNameHint": "指定使用的模型,将自动更新到 config.toml 中",
"modelName": "模型名称",
"upstreamModelName": "上游模型名称",
"upstreamModelNameHint": "Chat 格式下这里填写真实上游模型;接管时 Codex 本地会使用兼容模型,并由路由映射回该模型。",
"modelNamePlaceholder": "例如: gpt-5-codex",
"contextWindow1M": "1M 上下文窗口",
"autoCompactLimit": "压缩阈值",