feat: support Responses to Chat (#5787)

* fix(openai): harden Chat-to-Responses compatibility

Add a shared Responses-to-Chat stream state machine and use it from the OpenAI relay path. Preserve assistant text alongside tool calls, bind tool argument deltas by output_index, map incomplete finish reasons, support reasoning/custom tool events, and buffer upstream SSE for non-stream Chat clients.

Add deterministic service tests and relay SSE tests for the conversion path.

Related to #5745.

* refactor: rename openaicompat to relayconvert for improved clarity

* feat(gemini): support responses request conversion

* feat: add responses to chat conversion support

* fix: harden responses chat conversion edge cases
This commit is contained in:
Calcium-Ion
2026-06-28 14:25:47 +08:00
committed by GitHub
parent 3a506f50f0
commit 2d5a041639
35 changed files with 2731 additions and 40 deletions
@@ -43,6 +43,10 @@ export const ADVANCED_CUSTOM_CONVERTER_OPTIONS: Array<{
value: 'openai_chat_completions_to_openai_responses',
label: 'OpenAI Chat to OpenAI Responses',
},
{
value: 'openai_responses_to_openai_chat_completions',
label: 'OpenAI Responses to OpenAI Chat',
},
{
value: 'gemini_generate_content_to_openai_chat_completions',
label: 'Gemini Generate Content to OpenAI Chat',
@@ -326,6 +330,9 @@ export function getAdvancedCustomUpstreamPathPlaceholder(
if (converter === 'openai_chat_completions_to_anthropic_messages') {
return '/v1/messages'
}
if (converter === 'openai_responses_to_openai_chat_completions') {
return '/v1/chat/completions'
}
return '/v1/chat/completions'
}
@@ -573,6 +580,9 @@ function isConverterPathAllowed(
) {
return incomingPath === '/v1/chat/completions'
}
if (converter === 'openai_responses_to_openai_chat_completions') {
return incomingPath === '/v1/responses'
}
return (
incomingPath.includes(':generateContent') ||
incomingPath.includes(':streamGenerateContent')
+1
View File
@@ -131,6 +131,7 @@ export type AdvancedCustomConverter =
| 'anthropic_messages_to_openai_chat_completions'
| 'openai_chat_completions_to_anthropic_messages'
| 'openai_chat_completions_to_openai_responses'
| 'openai_responses_to_openai_chat_completions'
| 'gemini_generate_content_to_openai_chat_completions'
| 'openai_chat_completions_to_gemini_generate_content'
+2 -1
View File
@@ -2995,6 +2995,7 @@
"OpenAI Rerank": "OpenAI Rerank",
"OpenAI Responses": "OpenAI Responses",
"OpenAI Responses Compact": "OpenAI Responses Compact",
"OpenAI Responses to OpenAI Chat": "OpenAI Responses to OpenAI Chat",
"OpenAI, Anthropic, etc.": "OpenAI, Anthropic, etc.",
"OpenAI, Anthropic, Google, etc.": "OpenAI, Anthropic, Google, etc.",
"OpenAIMax": "OpenAIMax",
@@ -3675,8 +3676,8 @@
"Resetting...": "Resetting...",
"Resolve Conflicts": "Resolve Conflicts",
"Resource Configuration": "Resource Configuration",
"Responding...": "Responding...",
"Resources": "Resources",
"Responding...": "Responding...",
"Response": "Response",
"Response Time": "Response Time",
"Response time: {{duration}}": "Response time: {{duration}}",
+2 -1
View File
@@ -2995,6 +2995,7 @@
"OpenAI Rerank": "OpenAI Rerank",
"OpenAI Responses": "OpenAI Responses",
"OpenAI Responses Compact": "OpenAI Responses Compact",
"OpenAI Responses to OpenAI Chat": "OpenAI Responses vers OpenAI Chat",
"OpenAI, Anthropic, etc.": "OpenAI, Anthropic, etc.",
"OpenAI, Anthropic, Google, etc.": "OpenAI, Anthropic, Google, etc.",
"OpenAIMax": "OpenAIMax",
@@ -3675,8 +3676,8 @@
"Resetting...": "Réinitialisation...",
"Resolve Conflicts": "Résoudre les conflits",
"Resource Configuration": "Configuration des ressources",
"Responding...": "Réponse en cours...",
"Resources": "Ressources",
"Responding...": "Réponse en cours...",
"Response": "Réponse",
"Response Time": "Temps de réponse",
"Response time: {{duration}}": "Temps de réponse : {{duration}}",
+2 -1
View File
@@ -2995,6 +2995,7 @@
"OpenAI Rerank": "OpenAI 再ランク付け",
"OpenAI Responses": "OpenAI レスポンス",
"OpenAI Responses Compact": "OpenAI レスポンス圧縮",
"OpenAI Responses to OpenAI Chat": "OpenAI Responses から OpenAI Chat",
"OpenAI, Anthropic, etc.": "OpenAI、Anthropicなど",
"OpenAI, Anthropic, Google, etc.": "OpenAI、Anthropic、Googleなど",
"OpenAIMax": "OpenAIMax",
@@ -3675,8 +3676,8 @@
"Resetting...": "リセット中...",
"Resolve Conflicts": "競合を解決",
"Resource Configuration": "リソース設定",
"Responding...": "応答中...",
"Resources": "リソース",
"Responding...": "応答中...",
"Response": "レスポンス",
"Response Time": "応答時間",
"Response time: {{duration}}": "応答時間: {{duration}}",
+2 -1
View File
@@ -2995,6 +2995,7 @@
"OpenAI Rerank": "Реранжирование OpenAI",
"OpenAI Responses": "Ответы OpenAI",
"OpenAI Responses Compact": "Компактные ответы OpenAI",
"OpenAI Responses to OpenAI Chat": "OpenAI Responses в OpenAI Chat",
"OpenAI, Anthropic, etc.": "OpenAI, Anthropic и т.д.",
"OpenAI, Anthropic, Google, etc.": "OpenAI, Anthropic, Google и т.д.",
"OpenAIMax": "OpenAIMax",
@@ -3675,8 +3676,8 @@
"Resetting...": "Сброс...",
"Resolve Conflicts": "Разрешить конфликты",
"Resource Configuration": "Конфигурация ресурсов",
"Responding...": "Отвечаем...",
"Resources": "Ресурсы",
"Responding...": "Отвечаем...",
"Response": "Ответ",
"Response Time": "Время ответа",
"Response time: {{duration}}": "Время ответа: {{duration}}",
+2 -1
View File
@@ -2995,6 +2995,7 @@
"OpenAI Rerank": "OpenAI Rerank",
"OpenAI Responses": "OpenAI Responses",
"OpenAI Responses Compact": "OpenAI Responses Compact",
"OpenAI Responses to OpenAI Chat": "OpenAI Responses sang OpenAI Chat",
"OpenAI, Anthropic, etc.": "OpenAI, Anthropic, v.v.",
"OpenAI, Anthropic, Google, etc.": "OpenAI, Anthropic, Google, v.v.",
"OpenAIMax": "OpenAIMax",
@@ -3675,8 +3676,8 @@
"Resetting...": "Đang đặt lại...",
"Resolve Conflicts": "Giải quyết Xung đột",
"Resource Configuration": "Cấu hình tài nguyên",
"Responding...": "Đang phản hồi...",
"Resources": "Tài nguyên",
"Responding...": "Đang phản hồi...",
"Response": "Phản hồi",
"Response Time": "Thời gian phản hồi",
"Response time: {{duration}}": "Thời gian phản hồi: {{duration}}",
+2 -1
View File
@@ -2995,6 +2995,7 @@
"OpenAI Rerank": "OpenAI 重排序",
"OpenAI Responses": "OpenAI 响应",
"OpenAI Responses Compact": "OpenAI 响应压缩",
"OpenAI Responses to OpenAI Chat": "OpenAI Responses 到 OpenAI Chat",
"OpenAI, Anthropic, etc.": "OpenAI、Anthropic 等",
"OpenAI, Anthropic, Google, etc.": "OpenAI、Anthropic、Google 等",
"OpenAIMax": "OpenAIMax",
@@ -3675,8 +3676,8 @@
"Resetting...": "重置中...",
"Resolve Conflicts": "解决冲突",
"Resource Configuration": "资源配置",
"Responding...": "正在回复...",
"Resources": "资源",
"Responding...": "正在回复...",
"Response": "响应",
"Response Time": "响应时间",
"Response time: {{duration}}": "响应时间:{{duration}}",