From 4d588f6c7d836250812b7a32496667bc5038a820 Mon Sep 17 00:00:00 2001 From: hex2077 Date: Sun, 8 Feb 2026 15:42:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=98=B2=E6=AD=A2=E6=B5=81=E5=BC=8F?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E4=B8=AD=E9=87=8D=E5=A4=8D=E5=8F=91=E9=80=81?= =?UTF-8?q?=E7=BB=93=E6=9D=9F=E6=A0=87=E5=BF=97=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=96=B0=E6=A8=A1=E5=9E=8B=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 handleStreamRequest 中可能重复发送流结束标志的问题,新增 hasMessageStop 状态跟踪。 在 provider-pool-manager 中修复临时配置缺少全局配置的问题。 为 Gemini 提供者添加新的模型支持:gemini-claude-opus-4-6-thinking。 --- src/providers/gemini/antigravity-core.js | 6 ++-- src/providers/provider-models.js | 3 +- src/providers/provider-pool-manager.js | 1 + src/utils/common.js | 39 +++++++++++++++++++++--- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/providers/gemini/antigravity-core.js b/src/providers/gemini/antigravity-core.js index db22bbb..07334c1 100644 --- a/src/providers/gemini/antigravity-core.js +++ b/src/providers/gemini/antigravity-core.js @@ -66,7 +66,8 @@ const MODEL_ALIAS_MAP = { 'gemini-2.5-flash-preview': 'gemini-2.5-flash', 'gemini-claude-sonnet-4-5': 'claude-sonnet-4-5', 'gemini-claude-sonnet-4-5-thinking': 'claude-sonnet-4-5-thinking', - 'gemini-claude-opus-4-5-thinking': 'claude-opus-4-5-thinking' + 'gemini-claude-opus-4-5-thinking': 'claude-opus-4-5-thinking', + 'gemini-claude-opus-4-6-thinking': 'claude-opus-4-6-thinking' }; // 真实模型名 -> 别名 @@ -78,7 +79,8 @@ const MODEL_NAME_MAP = { 'gemini-2.5-flash': 'gemini-2.5-flash-preview', 'claude-sonnet-4-5': 'gemini-claude-sonnet-4-5', 'claude-sonnet-4-5-thinking': 'gemini-claude-sonnet-4-5-thinking', - 'claude-opus-4-5-thinking': 'gemini-claude-opus-4-5-thinking' + 'claude-opus-4-5-thinking': 'gemini-claude-opus-4-5-thinking', + 'claude-opus-4-6-thinking': 'gemini-claude-opus-4-6-thinking' }; /** diff --git a/src/providers/provider-models.js b/src/providers/provider-models.js index 5c21ffc..7964f99 100644 --- a/src/providers/provider-models.js +++ b/src/providers/provider-models.js @@ -21,7 +21,8 @@ export const PROVIDER_MODELS = { 'gemini-2.5-flash-preview', 'gemini-claude-sonnet-4-5', 'gemini-claude-sonnet-4-5-thinking', - 'gemini-claude-opus-4-5-thinking' + 'gemini-claude-opus-4-5-thinking', + 'gemini-claude-opus-4-6-thinking' ], 'claude-custom': [], 'claude-kiro-oauth': [ diff --git a/src/providers/provider-pool-manager.js b/src/providers/provider-pool-manager.js index 7603a55..310d5bb 100644 --- a/src/providers/provider-pool-manager.js +++ b/src/providers/provider-pool-manager.js @@ -379,6 +379,7 @@ export class ProviderPoolManager { // 使用适配器进行刷新 const tempConfig = { + ...this.globalConfig, ...config, MODEL_PROVIDER: providerType }; diff --git a/src/utils/common.js b/src/utils/common.js index 863ad16..43eacc6 100644 --- a/src/utils/common.js +++ b/src/utils/common.js @@ -322,6 +322,7 @@ export async function handleStreamRequest(res, service, model, requestBody, from const addEvent = getProtocolPrefix(fromProvider) === MODEL_PROTOCOL_PREFIX.CLAUDE || getProtocolPrefix(fromProvider) === MODEL_PROTOCOL_PREFIX.OPENAI_RESPONSES; let hasToolCall = false; + let hasMessageStop = false; // 跟踪是否已经发送过结束标志(message_stop / done) try { for await (const nativeChunk of nativeStream) { @@ -399,6 +400,20 @@ export async function handleStreamRequest(res, service, model, requestBody, from } } + // 防止重复发送结束标志 + // OpenAI: choices[].finish_reason + // Claude: message_stop + // OpenAI Responses: done + // Gemini: candidates[].finishReason(如 STOP / MAX_TOKENS / SAFETY 等) + if ( + chunk?.choices?.some(choice => choice?.finish_reason) || + chunk?.type === 'message_stop' || + chunk?.type === 'done' || + chunk?.candidates?.some(candidate => candidate?.finishReason) + ) { + hasMessageStop = true; + } + if (addEvent) { // fullOldResponseJson += chunk.type+"\n"; // fullResponseJson += chunk.type+"\n"; @@ -574,13 +589,27 @@ export async function handleStreamRequest(res, service, model, requestBody, from if (!res.writableEnded) { try { if (clientProtocol === MODEL_PROTOCOL_PREFIX.OPENAI) { - res.write('data: [DONE]\n\n'); + if (!hasMessageStop) { + res.write('data: [DONE]\n\n'); + hasMessageStop = true; + } } else if (clientProtocol === MODEL_PROTOCOL_PREFIX.OPENAI_RESPONSES) { - res.write('event: done\n'); - res.write('data: {}\n\n'); + if (!hasMessageStop) { + res.write('event: done\n'); + res.write('data: {}\n\n'); + hasMessageStop = true; + } } else if (clientProtocol === MODEL_PROTOCOL_PREFIX.CLAUDE) { - res.write('event: message_stop\n'); - res.write('data: {"type":"message_stop"}\n\n'); + if (!hasMessageStop) { + res.write('event: message_stop\n'); + res.write('data: {"type":"message_stop"}\n\n'); + hasMessageStop = true; + } + } else if (clientProtocol === MODEL_PROTOCOL_PREFIX.GEMINI) { + if (!hasMessageStop) { + res.write('data: {"candidates":[{"finishReason":"STOP"}]}\n\n'); + hasMessageStop = true; + } } res.end(); } catch (writeErr) {