Skip to content

Commit f54ef68

Browse files
committed
Rough truncated thinking component
1 parent cf4bab5 commit f54ef68

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

cli/src/components/thinking.tsx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { TextAttributes } from '@opentui/core'
2+
import React, { memo, type ReactNode } from 'react'
3+
4+
import { useTheme } from '../hooks/use-theme'
5+
import { useTerminalDimensions } from '../hooks/use-terminal-dimensions'
6+
import { getLastNVisualLines } from '../utils/text-layout'
7+
8+
interface ThinkingProps {
9+
content: string
10+
isCollapsed: boolean
11+
onToggle: () => void
12+
availableWidth?: number
13+
}
14+
15+
export const Thinking = memo(
16+
({ content, isCollapsed, onToggle, availableWidth }: ThinkingProps): ReactNode => {
17+
const theme = useTheme()
18+
const { contentMaxWidth } = useTerminalDimensions()
19+
20+
const width = Math.max(10, Math.min((availableWidth ?? contentMaxWidth), 120))
21+
const { lines: lastLines, hasMore } = getLastNVisualLines(content, width, 3)
22+
const collapsedText = (hasMore ? '...\n' : '') + lastLines.join('\n')
23+
24+
return (
25+
<box
26+
style={{
27+
flexDirection: 'column',
28+
gap: 0,
29+
marginTop: 1,
30+
marginBottom: 1,
31+
}}
32+
>
33+
<box
34+
style={{
35+
flexDirection: 'row',
36+
alignSelf: 'flex-start',
37+
backgroundColor: theme.muted,
38+
paddingLeft: 1,
39+
paddingRight: 1,
40+
}}
41+
onMouseDown={onToggle}
42+
>
43+
<text style={{ wrapMode: 'none' }}>
44+
<span fg={theme.foreground}>{isCollapsed ? '▸ ' : '▾ '}</span>
45+
<span fg={theme.foreground} attributes={TextAttributes.ITALIC}>
46+
Thinking
47+
</span>
48+
</text>
49+
</box>
50+
{isCollapsed && collapsedText && (
51+
<box style={{ flexShrink: 1, marginTop: 0 }}>
52+
<text
53+
style={{
54+
wrapMode: 'word',
55+
fg: theme.muted,
56+
}}
57+
attributes={TextAttributes.ITALIC}
58+
>
59+
{collapsedText}
60+
</text>
61+
</box>
62+
)}
63+
{!isCollapsed && (
64+
<box style={{ flexShrink: 1, marginTop: 0 }}>
65+
<text
66+
style={{
67+
wrapMode: 'word',
68+
fg: theme.muted,
69+
}}
70+
attributes={TextAttributes.ITALIC}
71+
>
72+
{content}
73+
</text>
74+
</box>
75+
)}
76+
</box>
77+
)
78+
},
79+
)

cli/src/hooks/use-send-message.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,13 @@ export const useSendMessage = ({
762762
rootStreamBufferRef.current =
763763
(rootStreamBufferRef.current ?? '') + eventObj.text
764764
}
765+
766+
// Auto-collapse thinking blocks by default
767+
if (eventObj.type === 'reasoning') {
768+
const thinkingId = `${aiMessageId}-thinking-0`
769+
setCollapsedAgents((prev) => new Set(prev).add(thinkingId))
770+
}
771+
765772
rootStreamSeenRef.current = true
766773
appendRootChunk(eventObj)
767774
} else if (event.type === 'subagent_chunk') {

0 commit comments

Comments
 (0)