( messages: ReadonlyArray<Message>, lastUserMessage: Message, )
| 2470 | * resolve after. |
| 2471 | */ |
| 2472 | export function collectRecentSuccessfulTools( |
| 2473 | messages: ReadonlyArray<Message>, |
| 2474 | lastUserMessage: Message, |
| 2475 | ): readonly string[] { |
| 2476 | const useIdToName = new Map<string, string>() |
| 2477 | const resultByUseId = new Map<string, boolean>() |
| 2478 | for (let i = messages.length - 1; i >= 0; i--) { |
| 2479 | const m = messages[i] |
| 2480 | if (!m) continue |
| 2481 | if (isHumanTurn(m) && m !== lastUserMessage) break |
| 2482 | if (m.type === 'assistant' && typeof m.message.content !== 'string') { |
| 2483 | for (const block of m.message.content) { |
| 2484 | if (block.type === 'tool_use') useIdToName.set(block.id, block.name) |
| 2485 | } |
| 2486 | } else if ( |
| 2487 | m.type === 'user' && |
| 2488 | 'message' in m && |
| 2489 | Array.isArray(m.message.content) |
| 2490 | ) { |
| 2491 | for (const block of m.message.content) { |
| 2492 | if (isToolResultBlock(block)) { |
| 2493 | resultByUseId.set(block.tool_use_id, block.is_error === true) |
| 2494 | } |
| 2495 | } |
| 2496 | } |
| 2497 | } |
| 2498 | const failed = new Set<string>() |
| 2499 | const succeeded = new Set<string>() |
| 2500 | for (const [id, name] of useIdToName) { |
| 2501 | const errored = resultByUseId.get(id) |
| 2502 | if (errored === undefined) continue |
| 2503 | if (errored) { |
| 2504 | failed.add(name) |
| 2505 | } else { |
| 2506 | succeeded.add(name) |
| 2507 | } |
| 2508 | } |
| 2509 | return [...succeeded].filter(t => !failed.has(t)) |
| 2510 | } |
| 2511 | |
| 2512 | |
| 2513 | /** |
no test coverage detected