Skip to content

Commit 15c5c31

Browse files
committed
Fix CLI toggle rendering and update knowledge
1 parent 6b5b3f7 commit 15c5c31

File tree

3 files changed

+90
-36
lines changed

3 files changed

+90
-36
lines changed

cli/src/components/branch-item.tsx

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,65 @@ export const BranchItem = ({
2626
theme,
2727
onToggle,
2828
}: BranchItemProps) => {
29+
const isTextRenderable = (value: ReactNode): boolean => {
30+
if (
31+
value === null ||
32+
value === undefined ||
33+
typeof value === 'boolean'
34+
) {
35+
return false
36+
}
37+
38+
if (typeof value === 'string' || typeof value === 'number') {
39+
return true
40+
}
41+
42+
if (Array.isArray(value)) {
43+
return value.every((child) => isTextRenderable(child))
44+
}
45+
46+
if (React.isValidElement(value)) {
47+
if (value.type === React.Fragment) {
48+
return isTextRenderable(value.props.children)
49+
}
50+
51+
if (typeof value.type === 'string') {
52+
if (
53+
value.type === 'span' ||
54+
value.type === 'strong' ||
55+
value.type === 'em'
56+
) {
57+
return isTextRenderable(value.props.children)
58+
}
59+
60+
return false
61+
}
62+
}
63+
64+
return false
65+
}
66+
67+
const renderExpandedContent = (value: ReactNode): ReactNode => {
68+
if (
69+
value === null ||
70+
value === undefined ||
71+
value === false ||
72+
value === true
73+
) {
74+
return null
75+
}
76+
77+
if (isTextRenderable(value)) {
78+
return (
79+
<text wrap fg={theme.agentText}>
80+
{value}
81+
</text>
82+
)
83+
}
84+
85+
return value
86+
}
87+
2988
return (
3089
<box style={{ flexDirection: 'row', flexShrink: 0 }}>
3190
<text wrap={false}>
@@ -51,21 +110,17 @@ export const BranchItem = ({
51110
}}
52111
onMouseDown={onToggle}
53112
>
54-
<text wrap={false}>
113+
<text wrap>
55114
<span fg={theme.agentToggleText}>
56115
{isCollapsed ? '▸ ' : '▾ '}
57116
</span>
117+
<span
118+
fg={theme.agentToggleText}
119+
attributes={TextAttributes.BOLD}
120+
>
121+
{name}
122+
</span>
58123
</text>
59-
<box style={{ flexShrink: 1 }}>
60-
<text wrap>
61-
<span
62-
fg={theme.agentToggleText}
63-
attributes={TextAttributes.BOLD}
64-
>
65-
{name}
66-
</span>
67-
</text>
68-
</box>
69124
</box>
70125
<box style={{ flexShrink: 1, marginBottom: 0 }}>
71126
{isStreaming && isCollapsed && streamingPreview && (
@@ -86,11 +141,7 @@ export const BranchItem = ({
86141
{finishedPreview}
87142
</text>
88143
)}
89-
{!isCollapsed && content && (
90-
<text wrap fg={theme.agentText}>
91-
{content}
92-
</text>
93-
)}
144+
{!isCollapsed && content && renderExpandedContent(content)}
94145
</box>
95146
</box>
96147
</box>

cli/src/hooks/use-message-renderer.tsx

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -175,26 +175,22 @@ export const useMessageRenderer = (props: UseMessageRendererProps): ReactNode[]
175175
? theme.agentResponseCount
176176
: theme.agentPrefix,
177177
paddingLeft: 1,
178-
paddingRight: 1,
179-
}}
180-
onMouseDown={handleTitleClick}
181-
>
182-
<text wrap={false}>
183-
<span fg={theme.agentToggleText}>
184-
{isCollapsed ? '▸' : '▾'}{' '}
185-
</span>
186-
</text>
187-
<box style={{ flexShrink: 1 }}>
188-
<text wrap>
189-
<span
190-
fg={theme.agentToggleText}
191-
attributes={TextAttributes.BOLD}
192-
>
193-
{agentInfo.agentName}
194-
</span>
195-
</text>
196-
</box>
197-
</box>
178+
paddingRight: 1,
179+
}}
180+
onMouseDown={handleTitleClick}
181+
>
182+
<text wrap>
183+
<span fg={theme.agentToggleText}>
184+
{isCollapsed ? '▸ ' : '▾ '}
185+
</span>
186+
<span
187+
fg={theme.agentToggleText}
188+
attributes={TextAttributes.BOLD}
189+
>
190+
{agentInfo.agentName}
191+
</span>
192+
</text>
193+
</box>
198194
<box
199195
style={{ flexShrink: 1, marginBottom: isCollapsed ? 1 : 0 }}
200196
onMouseDown={handleContentClick}

knowledge.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ Codebuff is a tool for editing codebases via natural language instruction to Buf
5555
- ESC key to toggle menu or stop AI response
5656
- CTRL+C to exit the application
5757

58+
### CLI Toggle Rendering Notes
59+
60+
- The agent/tool toggles in the TUI render inside `<text>` components from OpenTUI. Any expanded content must resolve to plain strings or StyledText-compatible fragments (`<span>`, `<strong>`, `<em>`, etc.) so the reconciler can convert them into `TextNodeRenderable` instances.
61+
- Issue: When markdown-rendered content returned arbitrary React elements (e.g., nested `<box>` containers) under `<text>`, toggling a branch threw `Error: TextNodeRenderable only accepts strings, TextNodeRenderable instances, or StyledText instances`.
62+
- Fix (Oct 2025): `cli/src/components/branch-item.tsx` now inspects expanded content; if it is text-renderable, it stays inside `<text>`, otherwise the raw element tree is rendered directly. This prevents invalid children from reaching `TextNodeRenderable` while preserving formatted markdown.
63+
- Related adjustment: `cli/src/hooks/use-message-renderer.tsx` ensures the toggle header renders within a single `<text>` block so glyphs and names remain StyledText-safe.
64+
5865
### Shell Shims (Direct Commands)
5966

6067
Codebuff supports shell shims for direct command invocation without the `codebuff` prefix.

0 commit comments

Comments
 (0)