(r: ExecutableToolResult)
| 637 | } |
| 638 | |
| 639 | function normalizeToolResult(r: ExecutableToolResult): ExecutableToolResult { |
| 640 | let output: ExecutableToolResult['output']; |
| 641 | if (typeof r.output === 'string') { |
| 642 | output = r.output.length > 0 ? r.output : TOOL_OUTPUT_EMPTY; |
| 643 | } else if (r.output.length === 0) { |
| 644 | output = TOOL_OUTPUT_EMPTY; |
| 645 | } else { |
| 646 | const hasMediaBlock = r.output.some(isMediaContentPart); |
| 647 | if (hasMediaBlock) { |
| 648 | const hasNonEmptyText = r.output.some((c) => c.type === 'text' && c.text.length > 0); |
| 649 | output = hasNonEmptyText |
| 650 | ? r.output |
| 651 | : [{ type: 'text', text: TOOL_OUTPUT_NON_TEXT }, ...r.output]; |
| 652 | } else { |
| 653 | const textJoined = r.output |
| 654 | .filter((c): c is Extract<typeof c, { type: 'text' }> => c.type === 'text') |
| 655 | .map((c) => c.text) |
| 656 | .join(''); |
| 657 | output = textJoined.length > 0 ? textJoined : TOOL_OUTPUT_EMPTY; |
| 658 | } |
| 659 | } |
| 660 | if (r.isError === true) { |
| 661 | return r.truncated === true |
| 662 | ? { output, isError: true, truncated: true } |
| 663 | : { output, isError: true }; |
| 664 | } |
| 665 | return r.truncated === true ? { output, truncated: true } : { output }; |
| 666 | } |
| 667 | |
| 668 | function makeToolResult( |
| 669 | call: PreflightedToolCall, |
no outgoing calls
no test coverage detected