( messages: Message[], toolName: string, )
| 4717 | * Searches backwards for efficiency. |
| 4718 | */ |
| 4719 | export function hasSuccessfulToolCall( |
| 4720 | messages: Message[], |
| 4721 | toolName: string, |
| 4722 | ): boolean { |
| 4723 | // Search backwards to find most recent tool_use for this tool |
| 4724 | let mostRecentToolUseId: string | undefined |
| 4725 | for (let i = messages.length - 1; i >= 0; i--) { |
| 4726 | const msg = messages[i] |
| 4727 | if (!msg) continue |
| 4728 | if (msg.type === 'assistant' && Array.isArray(msg.message.content)) { |
| 4729 | const toolUse = msg.message.content.find( |
| 4730 | (block): block is ToolUseBlock => |
| 4731 | block.type === 'tool_use' && block.name === toolName, |
| 4732 | ) |
| 4733 | if (toolUse) { |
| 4734 | mostRecentToolUseId = toolUse.id |
| 4735 | break |
| 4736 | } |
| 4737 | } |
| 4738 | } |
| 4739 | |
| 4740 | if (!mostRecentToolUseId) return false |
| 4741 | |
| 4742 | // Find the corresponding tool_result (search backwards) |
| 4743 | for (let i = messages.length - 1; i >= 0; i--) { |
| 4744 | const msg = messages[i] |
| 4745 | if (!msg) continue |
| 4746 | if (msg.type === 'user' && Array.isArray(msg.message.content)) { |
| 4747 | const toolResult = msg.message.content.find( |
| 4748 | (block): block is ToolResultBlockParam => |
| 4749 | block.type === 'tool_result' && |
| 4750 | block.tool_use_id === mostRecentToolUseId, |
| 4751 | ) |
| 4752 | if (toolResult) { |
| 4753 | // Success if is_error is false or undefined |
| 4754 | return toolResult.is_error !== true |
| 4755 | } |
| 4756 | } |
| 4757 | } |
| 4758 | |
| 4759 | // Tool called but no result yet (shouldn't happen in practice) |
| 4760 | return false |
| 4761 | } |
| 4762 | |
| 4763 | type ThinkingBlockType = |
| 4764 | | ThinkingBlock |
no outgoing calls
no test coverage detected