557
}];
558
}
560
>
// Phase 10 — strip the SDK's `mcp__<server>__` prefix for
561
>
// our in-process client-tool MCP server. The SDK surfaces
562
>
// in-process MCP tools to the model with that prefix, but
563
>
// the workbench's registered client-tool list (and the
564
>
// MCP handler's closure) use the unprefixed name. Without
565
>
// normalizing at the seam, `ChatToolCallReady` /
566
>
// `ChatToolCallComplete` would carry the prefixed name
567
>
// and the workbench would never recognize them as client
568
>
// tools. SDK-owned tools (Read, Write, Bash, etc.) and
569
>
// subagent spawn tools pass through unchanged because
570
>
// they don't carry the prefix.
571
>
const toolName = stripClientToolNamePrefix(block.name);
572
>
const isClientTool = hasClientToolNamePrefix(block.name);
573
>
state.startToolBlock(event.index, block.id, toolName, turnId);
574
>
// Phase 12 — subagent correlation bookkeeping. Either this
575
>
// tool_use is at the top level and (if Task/Agent) spawns a
576
>
// new subagent, or it is inner and we record its edge to the
577
>
// parent. They are mutually exclusive (a Task call inside a
578
>
// subagent is itself an inner tool_use; the resolver chain
579
>
// handles nested spawns by following the parent chain).
580
>
// Gated on `!isClientTool` so a workbench tool named `Task` /
581
>
// `Agent` cannot impersonate the SDK's subagent-spawn tools.
582
>
const isSubagentSpawn = !isClientTool && SUBAGENT_SPAWNING_TOOL_NAMES.has(toolName);
583
>
if (parentToolUseId === null) {
584
>
if (isSubagentSpawn) {
585
registry.recordSpawn(block.id);
586
}
588
registry.noteInnerTool(block.id, parentToolUseId);
589
}
591
>
// search / subagent renderers. Single write at the tool-open
592
>
// seam; the reducer carries `_meta` forward to all subsequent
593
>
// state transitions (D6). Subagent meta from Phase 12 is now
594
>
// produced by `buildClaudeToolMeta` because
595
>
// `getClaudeToolKind('Task') === 'subagent'`.
596
>
const meta = buildClaudeToolMeta(toolName);
597
>
const toolClientId = isClientTool ? clientToolOwner?.(toolName) : undefined;
598
>
return [{
599
>
kind: 'action',
600
>
resource: chat,
601
>
action: {
602
>
type: ActionType.ChatToolCallStart,
603
>
turnId,
604
>
toolCallId: block.id,
605
>
toolName,
606
>
displayName: getClaudeToolDisplayName(toolName),
607
>
...(toolClientId ? { contributor: { kind: ToolCallContributorKind.Client, clientId: toolClientId } } : {}),
608
>
...(meta ? { _meta: meta } : {}),
609
>
},
610
>
}];
611
>
}
612
return [];
613
}