luoxk 4bb25f0d53 fix: reorder assistant tool_use blocks before sending history
When the model streams `tool_use ... text ... tool_use` interleaved blocks
within one turn (e.g. parallel TaskCreate calls plus a mid-stream
explanation), the previous merge logic preserved the literal stream order
and persisted it to history. On the next request, Bedrock's stricter
history validator inspects the trailing run of `tool_use` blocks: text
between tool_uses makes the earlier tool_uses no longer count as
"trailing", so they are reported as missing tool_result and the API 400s
even though all tool_results were actually returned. See
CLIENT_TOOL_USE_BUG_REPORT.md from the worldRouter proxy team for the
captured request body and Bedrock error.

This fix:
- Adds `reorderAssistantToolUseBlocks` that moves non-tool_use blocks out
  of the tool_use cluster (preserving tool_use id order, thinking/
  redacted_thinking positions, and dropping no blocks). No-op when zero
  or one tool_use, or when tool_uses are already contiguous.
- Applies it in `mergeAssistantMessages` so live stream-merge produces
  clean history.
- Applies it as a pass in `normalizeMessagesForAPI` so sessions resumed
  from disk that were persisted before this fix also get cleaned up.
- Adds 9 bun:test cases covering the no-op, hoist, head/tail
  preservation, idempotence, and merge cases (including the exact
  pattern from the upstream bug report).
2026-05-23 15:36:32 +08:00
..