The sparkle glyph gained a second consumer (GoalBar beside the Others tool-row variant), which the duplication gate correctly flags as a clone — the package-local-until-shared rule its comment recorded has run its course. Both copies collapse into the shared ic_ds_* family; the icon-set count test grows to 57.
46 lines
1.8 KiB
TypeScript
46 lines
1.8 KiB
TypeScript
// GenericToolCard: the default tool row — classifies the tool into one of
|
|
// the five figma row variants and renders the summary row. Supplied by the
|
|
// chat view as the keyed toolview slot's render-site fallback (an
|
|
// unregistered tool name lands here); registrants may also compose it as a
|
|
// base, feeding the same owner payload through.
|
|
|
|
import type { ReactNode } from 'react'
|
|
import {
|
|
IconApiOutline14, IconBrowseOutline16, IconCodeOutline16, IconEditOutline16, IconSearchOutline16, IconSparkle16,
|
|
IconThinkOutline14,
|
|
} from '@deepseek-ai/dsh-client-ui-primitives'
|
|
import type { ToolRowOwnerProps } from '../contract/slots.ts'
|
|
import { toolRowModel, type ToolRowVariant } from '../contract/tool-call-model.ts'
|
|
import { ToolRow } from './ToolRow.tsx'
|
|
|
|
/** Variant leading icons (figma table); all glyphs render at 14 inside the 16px leading box. */
|
|
const VARIANT_ICONS: Record<ToolRowVariant, ReactNode> = {
|
|
think: <IconThinkOutline14 size={14} />,
|
|
search: <IconSearchOutline16 size={14} />,
|
|
read: <IconBrowseOutline16 size={14} />,
|
|
bash: <IconApiOutline14 size={14} />,
|
|
write: <IconEditOutline16 size={14} />,
|
|
edit: <IconEditOutline16 size={14} />,
|
|
code: <IconCodeOutline16 size={14} />,
|
|
others: <IconSparkle16 size={14} />,
|
|
}
|
|
|
|
export function GenericToolCard({ toolName, block, cwd, openFile }: ToolRowOwnerProps) {
|
|
const model = toolRowModel(toolName, block, cwd)
|
|
const singleFile = model.filePath !== undefined
|
|
return (
|
|
<ToolRow
|
|
variant={model.variant}
|
|
toolName={toolName}
|
|
icon={VARIANT_ICONS[model.variant]}
|
|
title={model.title}
|
|
summary={model.summary}
|
|
// Single-file tools never expose an args body — the path link is the only action.
|
|
body={singleFile ? null : model.body}
|
|
state={model.state}
|
|
filePath={model.filePath}
|
|
onOpenFile={singleFile ? openFile : undefined}
|
|
/>
|
|
)
|
|
}
|