fix(tui): stabilize multiline input, persist tool traces, and port CLI-style context status bar

This commit is contained in:
Brooklyn Nicholson 2026-04-08 23:59:56 -05:00
parent c49bbbe8c2
commit b66550ed08
9 changed files with 262 additions and 129 deletions

View file

@ -53,6 +53,12 @@ export const MessageLine = memo(function MessageLine({
return (
<Box flexDirection="column" marginTop={msg.role === 'user' ? 1 : 0}>
{msg.thinking && (
<Text color={t.color.dim} dimColor wrap="truncate-end">
💭 {msg.thinking.replace(/\n/g, ' ').slice(0, 200)}
</Text>
)}
<Box>
<Box flexShrink={0} width={3}>
<Text bold={msg.role === 'user'} color={prefix}>
@ -62,6 +68,20 @@ export const MessageLine = memo(function MessageLine({
<Box width={Math.max(20, cols - 5)}>{content}</Box>
</Box>
{!!msg.tools?.length && (
<Box flexDirection="column">
{msg.tools.map((tool, i) => (
<Text
color={tool.endsWith(' ✗') ? t.color.error : t.color.dim}
dimColor={!tool.endsWith(' ✗')}
key={`${tool}-${i}`}
>
{t.brand.tool} {tool}
</Text>
))}
</Box>
)}
</Box>
)
})

View file

@ -117,7 +117,11 @@ export function TextInput({ value, onChange, onPaste, onSubmit, placeholder = ''
}
if (k.return) {
onSubmit?.(value)
if (k.shift || k.meta) {
commit(value.slice(0, cur) + '\n' + value.slice(cur), cur + 1)
} else {
onSubmit?.(value)
}
return
}
@ -163,6 +167,12 @@ export function TextInput({ value, onChange, onPaste, onSubmit, placeholder = ''
return
}
if (raw === '\n') {
commit(v.slice(0, c) + '\n' + v.slice(c), c + 1)
return
}
if (raw.length > 1 || raw.includes('\n')) {
if (!pasteBuf.current) {
pastePos.current = c

View file

@ -44,6 +44,7 @@ export const Thinking = memo(function Thinking({
const verb = VERBS[tick % VERBS.length] ?? 'thinking'
const face = FACES[tick % FACES.length] ?? '(•_•)'
const tail = reasoning.slice(-160).replace(/\n/g, ' ')
const hasReasoning = !!tail
return (
<>
@ -54,7 +55,7 @@ export const Thinking = memo(function Thinking({
</Text>
))}
{!tools.length && (
{!tools.length && !hasReasoning && (
<Text color={t.color.dim}>
<Spinner color={t.color.dim} /> {face} {verb}
</Text>