/** Root/subcall Tool composition with one keyed atomic dispatch path. */ import { memo, useMemo, type ReactNode } from 'react' import type { ToolCallBlock } from '@deepseek-ai/dsh-client-runtime/client' import type { ToolCallOwnerProps, ToolTreeProps } from '../contract/slots.ts' import { GenericToolCard } from './toolviews/GenericToolCard.tsx' import css from './ToolCallTree.module.css' /** Resolve a Tool call's wire name from either lifecycle form. */ function callName(node: ToolCallBlock): string { return 'kind' in node ? node.call?.name ?? '' : node.name } /** One atomic call dispatched through the Tool-owned keyed slot. */ const ToolCall = memo(function ToolCall({ renderSlot, callId, toolName, block, openFile, selected, cwd, inspectCall, t, children, }: Pick & { callId: string toolName: string block: ToolCallBlock selected: boolean children?: ReactNode }) { const owner: ToolCallOwnerProps = useMemo(() => ({ callId, toolName, block, openFile, cwd, inspect: () => { inspectCall(callId) }, }), [callId, toolName, block, openFile, cwd, inspectCall]) return (
{renderSlot('tool.call.toolview', owner, { entryKey: toolName, fallback: , })} {children}
) }) const ToolCallBranch = memo(function ToolCallBranch({ renderSlot, block, selectedCallId, cwd, openFile, inspectCall, t, }: Pick & { block: ToolCallBlock }) { return ( {block.subCalls.length > 0 ? (
{block.subCalls.map(child => ( ))}
) : null}
) }) /** * Render one root Tool call and its recursive children through the same * atomic keyed dispatch. * @param props - whole-Tool owner data and the Tool-owned child-slot share. * @returns the Tool call tree. */ export function ToolCallTree({ renderSlot, node, selectedCallId, cwd, openFile, inspectCall, t, }: ToolTreeProps) { const block = node.data.root return ( ) }