removeIncompleteToolCalls 移除所有不完整的 tool_call 序列 策略:找到第一个不完整的 tool_call,截断到该位置之前
(messages []types.Message)
| 1669 | // removeIncompleteToolCalls 移除所有不完整的 tool_call 序列 |
| 1670 | // 策略:找到第一个不完整的 tool_call,截断到该位置之前 |
| 1671 | func (a *Agent) removeIncompleteToolCalls(messages []types.Message) []types.Message { |
| 1672 | if len(messages) == 0 { |
| 1673 | return messages |
| 1674 | } |
| 1675 | |
| 1676 | // 从前往后扫描,找到第一个不完整的 tool_call |
| 1677 | for i, msg := range messages { |
| 1678 | // 检查是否有 tool_calls |
| 1679 | var toolCallIDs []string |
| 1680 | hasToolCalls := false |
| 1681 | for _, block := range msg.ContentBlocks { |
| 1682 | if toolUse, ok := block.(*types.ToolUseBlock); ok { |
| 1683 | hasToolCalls = true |
| 1684 | toolCallIDs = append(toolCallIDs, toolUse.ID) |
| 1685 | } |
| 1686 | } |
| 1687 | |
| 1688 | if hasToolCalls { |
| 1689 | // 如果是最后一条消息,截断 |
| 1690 | if i+1 >= len(messages) { |
| 1691 | return messages[:i] |
| 1692 | } |
| 1693 | |
| 1694 | // 检查下一条消息 |
| 1695 | nextMsg := messages[i+1] |
| 1696 | var toolResultIDs []string |
| 1697 | hasToolResult := false |
| 1698 | for _, block := range nextMsg.ContentBlocks { |
| 1699 | if toolResult, ok := block.(*types.ToolResultBlock); ok { |
| 1700 | hasToolResult = true |
| 1701 | toolResultIDs = append(toolResultIDs, toolResult.ToolUseID) |
| 1702 | } |
| 1703 | } |
| 1704 | |
| 1705 | if !hasToolResult { |
| 1706 | // 下一条消息不是 tool_result,截断到这里 |
| 1707 | return messages[:i] |
| 1708 | } |
| 1709 | |
| 1710 | // 验证所有 tool_call 都有对应的 tool_result |
| 1711 | allMatched := true |
| 1712 | for _, toolCallID := range toolCallIDs { |
| 1713 | found := slices.Contains(toolResultIDs, toolCallID) |
| 1714 | if !found { |
| 1715 | allMatched = false |
| 1716 | break |
| 1717 | } |
| 1718 | } |
| 1719 | |
| 1720 | if !allMatched { |
| 1721 | return messages[:i] |
| 1722 | } |
| 1723 | } |
| 1724 | } |
| 1725 | |
| 1726 | // 所有消息都是完整的 |
| 1727 | return messages |
| 1728 | } |