Skip to content

fix: 修复 OpenAI→Claude 流式转换在并行工具调用下的参数粘连 - #72

Open
housiliao wants to merge 1 commit into
aiprodcoder:mainfrom
housiliao:fix/stream-parallel-tool-calls
Open

fix: 修复 OpenAI→Claude 流式转换在并行工具调用下的参数粘连#72
housiliao wants to merge 1 commit into
aiprodcoder:mainfrom
housiliao:fix/stream-parallel-tool-calls

Conversation

@housiliao

Copy link
Copy Markdown

修复 issue #5483 场景:带 reasoning 的 OpenAI 模型(如 GPT-5.6)流式 /v1/messages + 多 content block(reasoning+text+并行 tool_use)时, Claude SDK 报 InputValidationError: Read was called with input that could not be parsed as JSON。

根因(StreamResponseOpenAI2Claude 为单 block 状态机):

  • 上游 tool_calls[].index 从未被读取:同 chunk 内第二个及以后的 tool call 增量直接丢弃
  • 第二个 tool call 的参数片段全部并入第一个 tool_use block, 生成 {}{}{} 非法 JSON
  • None→tools 切换时对未 start 的 block 发幽灵 content_block_stop
  • 首块即 tool_calls 时提前 return,首块增量丢失
  • usage-only 尾 chunk 导致收尾序列静默丢失

修复:

  • ClaudeConvertInfo 新增 ToolCallBlockIndex(上游 index→block index 映射)与 ActiveBlocks(活跃 block 跟踪)
  • tools 分支遍历全部增量并按上游 index 路由到各自 content block
  • Done 终结调用提前,所有活跃 block 统一补发 stop 后再收尾

测试:新增 service/convert_test.go(协议状态机校验器 + 6 用例,
含 2 个回归保护),全部通过;go vet / go build 通过。

修复 issue #5483 场景:带 reasoning 的 OpenAI 模型(如 GPT-5.6)流式
/v1/messages + 多 content block(reasoning+text+并行 tool_use)时,
Claude SDK 报 InputValidationError: Read was called with input that
could not be parsed as JSON。

根因(StreamResponseOpenAI2Claude 为单 block 状态机):
- 上游 tool_calls[].index 从未被读取:同 chunk 内第二个及以后的
  tool call 增量直接丢弃
- 第二个 tool call 的参数片段全部并入第一个 tool_use block,
  生成 {}{}{} 非法 JSON
- None→tools 切换时对未 start 的 block 发幽灵 content_block_stop
- 首块即 tool_calls 时提前 return,首块增量丢失
- usage-only 尾 chunk 导致收尾序列静默丢失

修复:
- ClaudeConvertInfo 新增 ToolCallBlockIndex(上游 index→block index
  映射)与 ActiveBlocks(活跃 block 跟踪)
- tools 分支遍历全部增量并按上游 index 路由到各自 content block
- Done 终结调用提前,所有活跃 block 统一补发 stop 后再收尾

测试:新增 service/convert_test.go(协议状态机校验器 + 6 用例,
含 2 个回归保护),全部通过;go vet / go build 通过。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant