( tool: Tool<AnyObject, Output>, toolUseResult: Output, )
| 4286 | } |
| 4287 | |
| 4288 | function createToolResultMessage<Output>( |
| 4289 | tool: Tool<AnyObject, Output>, |
| 4290 | toolUseResult: Output, |
| 4291 | ): UserMessage { |
| 4292 | try { |
| 4293 | const result = tool.mapToolResultToToolResultBlockParam(toolUseResult, '1') |
| 4294 | |
| 4295 | // If the result contains image content blocks, preserve them as is |
| 4296 | if ( |
| 4297 | Array.isArray(result.content) && |
| 4298 | result.content.some(block => block.type === 'image') |
| 4299 | ) { |
| 4300 | return createUserMessage({ |
| 4301 | content: result.content as ContentBlockParam[], |
| 4302 | isMeta: true, |
| 4303 | }) |
| 4304 | } |
| 4305 | |
| 4306 | // For string content, use raw string — jsonStringify would escape \n→\\n, |
| 4307 | // wasting ~1 token per newline (a 2000-line @-file = ~1000 wasted tokens). |
| 4308 | // Keep jsonStringify for array/object content where structure matters. |
| 4309 | const contentStr = |
| 4310 | typeof result.content === 'string' |
| 4311 | ? result.content |
| 4312 | : jsonStringify(result.content) |
| 4313 | return createUserMessage({ |
| 4314 | content: `Result of calling the ${tool.name} tool:\n${contentStr}`, |
| 4315 | isMeta: true, |
| 4316 | }) |
| 4317 | } catch { |
| 4318 | return createUserMessage({ |
| 4319 | content: `Result of calling the ${tool.name} tool: Error`, |
| 4320 | isMeta: true, |
| 4321 | }) |
| 4322 | } |
| 4323 | } |
| 4324 | |
| 4325 | function createToolUseMessage( |
| 4326 | toolName: string, |
no test coverage detected