[GH-ISSUE #309] 防止 Claude 协议流式响应中重复发送 message_stop 事件 #220

Closed
opened 2026-02-27 07:18:32 +03:00 by kerem · 3 comments
Owner

Originally created by @oktj on GitHub (Feb 6, 2026).
Original GitHub issue: https://github.com/justlovemaki/AIClient-2-API/issues/309

问题描述

在 Claude 协议的流式响应中,message_stop 事件可能会被重复发送,导致客户端接收到冗余的结束信号。

问题场景

  • 当使用 Claude 协议进行流式请求时
  • 如果上游服务已经在流中发送了 message_stop 事件
  • finally 块中会再次补充发送 message_stop 事件
  • 导致客户端收到重复的结束标记

修复内容

文件变更

  • 文件路径: src/utils/common.js
  • 修改位置: handleStreamRequest 函数(第 276-607 行)

具体修改

  1. 新增状态跟踪变量(第 325 行)

    let hasMessageStop = false; // 跟踪是否已经发送过 message_stop
    
  2. 检测流中的 message_stop 事件(第 386-389 行)

    // 检测是否已经发送过 message_stop
    if (chunk.type === 'message_stop') {
        hasMessageStop = true;
    }
    
  3. 条件性发送结束标记(第 587-591 行)

    // 只有在流中没有发送过 message_stop 时才补充发送
    if (!hasMessageStop) {
        res.write('event: message_stop\n');
        res.write('data: {"type":"message_stop"}\n\n');
    }
    

技术细节

修复逻辑

  1. 在流处理开始时初始化 hasMessageStop 标志为 false
  2. 在遍历流数据块时,检测每个 chunk 的 type 属性
  3. 如果检测到 type === 'message_stop',将标志设置为 true
  4. finally 块中发送结束标记前,检查标志状态
  5. 只有当标志为 false 时才补充发送 message_stop 事件

影响范围

  • 协议: 仅影响 Claude 协议(MODEL_PROTOCOL_PREFIX.CLAUDE
  • 请求类型: 仅影响流式请求(stream requests)
  • 兼容性: 不影响其他协议(OpenAI、Gemini 等)的行为

测试建议

测试场景 1: 上游已发送 message_stop

预期行为: 不再重复发送 message_stop 事件
验证方法: 检查客户端接收到的事件流,确认只有一个 message_stop

测试场景 2: 上游未发送 message_stop

预期行为: 在 finally 块中补充发送 message_stop 事件
验证方法: 检查客户端接收到的事件流,确认有且仅有一个 message_stop

测试场景 3: 其他协议不受影响

预期行为: OpenAI、Gemini 等协议的流式响应正常工作
验证方法: 测试各协议的流式请求,确认结束标记正常

提交信息

fix: 防止 Claude 协议流式响应中重复发送 message_stop 事件

- 添加 hasMessageStop 标志跟踪 message_stop 事件状态
- 在流处理过程中检测 message_stop 事件
- 只在未发送过 message_stop 时才补充发送
- 避免客户端接收到重复的结束信号

相关代码位置

  • 主要函数: handleStreamRequest (src/utils/common.js:276-607)
  • 相关协议: MODEL_PROTOCOL_PREFIX.CLAUDE (src/utils/common.js:57)
  • 结束标记处理: finally 块 (src/utils/common.js:567-

备注

此修复确保了 Claude 协议流式响应的规范性,避免了重复事件可能导致的客户端解析问题或状态混乱。

Originally created by @oktj on GitHub (Feb 6, 2026). Original GitHub issue: https://github.com/justlovemaki/AIClient-2-API/issues/309 ## 问题描述 在 Claude 协议的流式响应中,`message_stop` 事件可能会被重复发送,导致客户端接收到冗余的结束信号。 ### 问题场景 - 当使用 Claude 协议进行流式请求时 - 如果上游服务已经在流中发送了 `message_stop` 事件 - 在 `finally` 块中会再次补充发送 `message_stop` 事件 - 导致客户端收到重复的结束标记 ## 修复内容 ### 文件变更 - **文件路径**: `src/utils/common.js` - **修改位置**: `handleStreamRequest` 函数(第 276-607 行) ### 具体修改 1. **新增状态跟踪变量**(第 325 行) ```javascript let hasMessageStop = false; // 跟踪是否已经发送过 message_stop ``` 2. **检测流中的 message_stop 事件**(第 386-389 行) ```javascript // 检测是否已经发送过 message_stop if (chunk.type === 'message_stop') { hasMessageStop = true; } ``` 3. **条件性发送结束标记**(第 587-591 行) ```javascript // 只有在流中没有发送过 message_stop 时才补充发送 if (!hasMessageStop) { res.write('event: message_stop\n'); res.write('data: {"type":"message_stop"}\n\n'); } ``` ## 技术细节 ### 修复逻辑 1. 在流处理开始时初始化 `hasMessageStop` 标志为 `false` 2. 在遍历流数据块时,检测每个 chunk 的 `type` 属性 3. 如果检测到 `type === 'message_stop'`,将标志设置为 `true` 4. 在 `finally` 块中发送结束标记前,检查标志状态 5. 只有当标志为 `false` 时才补充发送 `message_stop` 事件 ### 影响范围 - **协议**: 仅影响 Claude 协议(`MODEL_PROTOCOL_PREFIX.CLAUDE`) - **请求类型**: 仅影响流式请求(stream requests) - **兼容性**: 不影响其他协议(OpenAI、Gemini 等)的行为 ## 测试建议 ### 测试场景 1: 上游已发送 message_stop ``` 预期行为: 不再重复发送 message_stop 事件 验证方法: 检查客户端接收到的事件流,确认只有一个 message_stop ``` ### 测试场景 2: 上游未发送 message_stop ``` 预期行为: 在 finally 块中补充发送 message_stop 事件 验证方法: 检查客户端接收到的事件流,确认有且仅有一个 message_stop ``` ### 测试场景 3: 其他协议不受影响 ``` 预期行为: OpenAI、Gemini 等协议的流式响应正常工作 验证方法: 测试各协议的流式请求,确认结束标记正常 ``` ## 提交信息 ``` fix: 防止 Claude 协议流式响应中重复发送 message_stop 事件 - 添加 hasMessageStop 标志跟踪 message_stop 事件状态 - 在流处理过程中检测 message_stop 事件 - 只在未发送过 message_stop 时才补充发送 - 避免客户端接收到重复的结束信号 ``` ## 相关代码位置 - **主要函数**: `handleStreamRequest` (src/utils/common.js:276-607) - **相关协议**: `MODEL_PROTOCOL_PREFIX.CLAUDE` (src/utils/common.js:57) - **结束标记处理**: finally 块 (src/utils/common.js:567- ## 备注 此修复确保了 Claude 协议流式响应的规范性,避免了重复事件可能导致的客户端解析问题或状态混乱。
kerem closed this issue 2026-02-27 07:18:32 +03:00
Author
Owner

@feimi8 commented on GitHub (Feb 6, 2026):

这个修改提交了吗

<!-- gh-comment-id:3858520274 --> @feimi8 commented on GitHub (Feb 6, 2026): 这个修改提交了吗
Author
Owner

@liangbaikaia commented on GitHub (Feb 7, 2026):

+1

<!-- gh-comment-id:3863669799 --> @liangbaikaia commented on GitHub (Feb 7, 2026): +1
Author
Owner

@justlovemaki commented on GitHub (Feb 8, 2026):

已更新

<!-- gh-comment-id:3866541277 --> @justlovemaki commented on GitHub (Feb 8, 2026): 已更新
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/AIClient-2-API-justlovemaki#220
No description provided.