MCPcopy Index your code
hub / github.com/codeaashu/claude-code / smooshIntoToolResult

Function smooshIntoToolResult

src/utils/messages.ts:2534–2598  ·  view source on GitHub ↗

* Fold content blocks into a tool_result's content. Returns the updated * tool_result, or `null` if smoosh is impossible (tool_reference constraint). * * Valid block types inside tool_result.content per SDK: text, image, * search_result, document. All of these smoosh. tool_reference (beta) canno

(
  tr: ToolResultBlockParam,
  blocks: ContentBlockParam[],
)

Source from the content-addressed store, hash-verified

2532 * - otherwise → array, with adjacent text merged (notebook.ts idiom)
2533 */
2534function smooshIntoToolResult(
2535 tr: ToolResultBlockParam,
2536 blocks: ContentBlockParam[],
2537): ToolResultBlockParam | null {
2538 if (blocks.length === 0) return tr
2539
2540 const existing = tr.content
2541 if (Array.isArray(existing) && existing.some(isToolReferenceBlock)) {
2542 return null
2543 }
2544
2545 // API constraint: is_error tool_results must contain only text blocks.
2546 // Queued-command siblings can carry images (pasted screenshot) — smooshing
2547 // those into an error result produces a transcript that 400s on every
2548 // subsequent call and can't be recovered by /fork. The image isn't lost:
2549 // it arrives as a proper user turn anyway.
2550 if (tr.is_error) {
2551 blocks = blocks.filter(b => b.type === 'text')
2552 if (blocks.length === 0) return tr
2553 }
2554
2555 const allText = blocks.every(b => b.type === 'text')
2556
2557 // Preserve string shape when existing was string/undefined and all incoming
2558 // blocks are text — this is the common case (hook reminders into Bash/Read
2559 // results) and matches the legacy smoosh output shape.
2560 if (allText && (existing === undefined || typeof existing === 'string')) {
2561 const joined = [
2562 (existing ?? '').trim(),
2563 ...blocks.map(b => (b as TextBlockParam).text.trim()),
2564 ]
2565 .filter(Boolean)
2566 .join('\n\n')
2567 return { ...tr, content: joined }
2568 }
2569
2570 // General case: normalize to array, concat, merge adjacent text
2571 const base: ToolResultContentItem[] =
2572 existing === undefined
2573 ? []
2574 : typeof existing === 'string'
2575 ? existing.trim()
2576 ? [{ type: 'text', text: existing.trim() }]
2577 : []
2578 : [...existing]
2579
2580 const merged: ToolResultContentItem[] = []
2581 for (const b of [...base, ...blocks]) {
2582 if (b.type === 'text') {
2583 const t = b.text.trim()
2584 if (!t) continue
2585 const prev = merged.at(-1)
2586 if (prev?.type === 'text') {
2587 merged[merged.length - 1] = { ...prev, text: `${prev.text}\n\n${t}` } // lvalue
2588 } else {
2589 merged.push({ type: 'text', text: t })
2590 }
2591 } else {

Callers 2

mergeUserContentBlocksFunction · 0.85

Calls 1

pushMethod · 0.45

Tested by

no test coverage detected