( messages: Message[], toolName: string, )
| 4817 | * Searches backwards for efficiency. |
| 4818 | */ |
| 4819 | export function hasSuccessfulToolCall( |
| 4820 | messages: Message[], |
| 4821 | toolName: string, |
| 4822 | ): boolean { |
| 4823 | // Search backwards to find most recent tool_use for this tool |
| 4824 | let mostRecentToolUseId: string | undefined |
| 4825 | for (let i = messages.length - 1; i >= 0; i--) { |
| 4826 | const msg = messages[i] |
| 4827 | if (!msg) continue |
| 4828 | if (msg.type === 'assistant' && Array.isArray(msg.message.content)) { |
| 4829 | const toolUse = msg.message.content.find( |
| 4830 | (block): block is ToolUseBlock => |
| 4831 | block.type === 'tool_use' && block.name === toolName, |
| 4832 | ) |
| 4833 | if (toolUse) { |
| 4834 | mostRecentToolUseId = toolUse.id |
| 4835 | break |
| 4836 | } |
| 4837 | } |
| 4838 | } |
| 4839 | |
| 4840 | if (!mostRecentToolUseId) return false |
| 4841 | |
| 4842 | // Find the corresponding tool_result (search backwards) |
| 4843 | for (let i = messages.length - 1; i >= 0; i--) { |
| 4844 | const msg = messages[i] |
| 4845 | if (!msg) continue |
| 4846 | if (msg.type === 'user' && Array.isArray(msg.message.content)) { |
| 4847 | const toolResult = msg.message.content.find( |
| 4848 | (block): block is ToolResultBlockParam => |
| 4849 | block.type === 'tool_result' && |
| 4850 | block.tool_use_id === mostRecentToolUseId, |
| 4851 | ) |
| 4852 | if (toolResult) { |
| 4853 | // Success if is_error is false or undefined |
| 4854 | return toolResult.is_error !== true |
| 4855 | } |
| 4856 | } |
| 4857 | } |
| 4858 | |
| 4859 | // Tool called but no result yet (shouldn't happen in practice) |
| 4860 | return false |
| 4861 | } |
| 4862 | |
| 4863 | type ThinkingBlockType = |
| 4864 | | ThinkingBlock |
no outgoing calls
no test coverage detected