diff --git a/src/client/SideChatView.module.css b/src/client/SideChatView.module.css
index 73d657f..fbae146 100644
--- a/src/client/SideChatView.module.css
+++ b/src/client/SideChatView.module.css
@@ -221,6 +221,18 @@
transform: rotate(90deg);
}
+/* Tool-kind leading glyph (the main conversation's 16px slot; the icon
+ * itself renders at 14). Failed rows pass a StateDot instead. */
+.sidechatRowIcon {
+ flex: none;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 16px;
+ height: 16px;
+ color: var(--dsw-alias-label-tertiary);
+}
+
.sidechatRowLabel {
flex: none;
max-width: 60%;
diff --git a/src/client/SideChatView.tsx b/src/client/SideChatView.tsx
index ccb4019..e409c1a 100644
--- a/src/client/SideChatView.tsx
+++ b/src/client/SideChatView.tsx
@@ -29,10 +29,15 @@ import clsx from 'clsx'
import {
ConnectionIndicator,
DiffBlock,
+ IconApiOutline14,
+ IconBrowseOutline16,
IconChevronRightOutline14,
+ IconEditOutline16,
IconNewChatOutline16,
IconPlusOutline16,
+ IconSearchOutline16,
IconSendOutline16,
+ IconSparkle16,
IconStopFill16,
MarkdownText,
Menu,
@@ -149,8 +154,13 @@ function CollapsibleRow(props: {
mono?: boolean
streaming?: boolean
failed?: boolean
+ /** 16px leading glyph (tool-kind icon, the main conversation's row head). */
+ icon?: React.ReactNode
children?: React.ReactNode
}): React.ReactNode {
+ const leading = props.icon === undefined ? null : (
+ {props.icon}
+ )
const label = (
+ {leading}
{label}
{meta}
@@ -185,6 +196,7 @@ function CollapsibleRow(props: {
+ {leading}
{label}
{meta}
@@ -215,6 +227,30 @@ function toolCardBody(card: SidechatToolCard, executing: boolean, labels: RowLab
return
}
+/** The tool row's 16px leading slot, the way the main conversation draws it
+ * (GenericToolCard's variant table): the tool-kind glyph at 14, replaced by
+ * an error StateDot on failed rows. */
+function toolLeading(name: string, failed: boolean): React.ReactNode {
+ if (failed) return
+ switch (name) {
+ case 'bash':
+ case 'pwsh':
+ return
+ case 'read':
+ case 'web_fetch':
+ return
+ case 'edit':
+ case 'write':
+ return
+ case 'grep':
+ case 'glob':
+ case 'web_search':
+ return
+ default:
+ return
+ }
+}
+
/** One row renderer (React keys ride the source event seq). */
function renderRow(row: SidechatTranscriptRow, labels: RowLabels): React.ReactNode {
switch (row.kind) {
@@ -275,6 +311,7 @@ function renderRow(row: SidechatTranscriptRow, labels: RowLabels): React.ReactNo
key={`${row.kind}:${row.seq}`}
label={row.name}
meta={toolArgsSummary(row.args)}
+ icon={toolLeading(row.name, row.failed)}
mono
streaming={row.executing === true}
failed={row.failed}