chore: uptick

This commit is contained in:
Brooklyn Nicholson 2026-04-13 10:22:44 -05:00
parent a27167fb30
commit 713a614ea8
2 changed files with 55 additions and 17 deletions

View file

@ -338,6 +338,7 @@ export function App({ gw }: { gw: GatewayClient }) {
const [secret, setSecret] = useState<SecretReq | null>(null)
const [picker, setPicker] = useState(false)
const [reasoning, setReasoning] = useState('')
const [reasoningActive, setReasoningActive] = useState(false)
const [reasoningStreaming, setReasoningStreaming] = useState(false)
const [statusBar, setStatusBar] = useState(true)
const [lastUserMsg, setLastUserMsg] = useState('')
@ -394,6 +395,7 @@ export function App({ gw }: { gw: GatewayClient }) {
clearTimeout(reasoningStreamingTimerRef.current)
}
setReasoningActive(true)
setReasoningStreaming(true)
reasoningStreamingTimerRef.current = setTimeout(() => {
reasoningStreamingTimerRef.current = null
@ -401,13 +403,14 @@ export function App({ gw }: { gw: GatewayClient }) {
}, REASONING_PULSE_MS)
}, [])
const clearReasoningStreaming = useCallback(() => {
const endReasoningPhase = useCallback(() => {
if (reasoningStreamingTimerRef.current) {
clearTimeout(reasoningStreamingTimerRef.current)
reasoningStreamingTimerRef.current = null
}
setReasoningStreaming(false)
setReasoningActive(false)
}, [])
useEffect(
@ -589,6 +592,7 @@ export function App({ gw }: { gw: GatewayClient }) {
}, [pushActivity, rpc, sid])
const idle = () => {
endReasoningPhase()
setTools([])
setTurnTrail([])
setBusy(false)
@ -1342,6 +1346,7 @@ export function App({ gw }: { gw: GatewayClient }) {
case 'message.start':
setBusy(true)
endReasoningPhase()
setReasoning('')
setActivity([])
setTurnTrail([])
@ -1416,7 +1421,7 @@ export function App({ gw }: { gw: GatewayClient }) {
case 'tool.start':
pruneTransient()
clearReasoningStreaming()
endReasoningPhase()
setTools(prev => [
...prev,
{ id: p.tool_id, name: p.name, context: (p.context as string) || '', startedAt: Date.now() }
@ -1507,7 +1512,7 @@ export function App({ gw }: { gw: GatewayClient }) {
case 'message.delta':
pruneTransient()
clearReasoningStreaming()
endReasoningPhase()
if (p?.text && !interruptedRef.current) {
buf.current = p.rendered ?? buf.current + p.text
@ -1528,7 +1533,6 @@ export function App({ gw }: { gw: GatewayClient }) {
idle()
setReasoning('')
clearReasoningStreaming()
setStreaming('')
if (inflightPasteIdsRef.current.length) {
@ -1586,7 +1590,20 @@ export function App({ gw }: { gw: GatewayClient }) {
break
}
},
[appendMessage, dequeue, newSession, pushActivity, pushTrail, send, sys]
[
appendMessage,
bellOnComplete,
dequeue,
endReasoningPhase,
newSession,
pruneTransient,
pulseReasoningStreaming,
pushActivity,
pushTrail,
send,
sys,
stdout
]
)
onEventRef.current = onEvent
@ -2484,6 +2501,7 @@ export function App({ gw }: { gw: GatewayClient }) {
activity={busy ? activity : []}
busy={busy && !streaming}
reasoning={reasoning}
reasoningActive={reasoningActive}
reasoningStreaming={reasoningStreaming}
t={theme}
thinkingMode={hasReasoning ? thinkingMode : 'truncated'}

View file

@ -58,7 +58,17 @@ function Detail({ color, content, dimColor }: DetailRow) {
// ── Streaming cursor ─────────────────────────────────────────────────
function StreamCursor({ active = false, color, dimColor }: { active?: boolean; color: string; dimColor?: boolean }) {
function StreamCursor({
color,
dimColor,
streaming = false,
visible = false
}: {
color: string
dimColor?: boolean
streaming?: boolean
visible?: boolean
}) {
const [on, setOn] = useState(true)
useEffect(() => {
@ -67,21 +77,23 @@ function StreamCursor({ active = false, color, dimColor }: { active?: boolean; c
return () => clearInterval(id)
}, [])
return (
return visible ? (
<Text color={color} dimColor={dimColor}>
{active && on ? '▍' : ' '}
{streaming && on ? '▍' : ' '}
</Text>
)
) : null
}
// ── Thinking (pre-tool fallback) ─────────────────────────────────────
export const Thinking = memo(function Thinking({
active = false,
mode = 'truncated',
reasoning,
streaming = false,
t
}: {
active?: boolean
mode?: ThinkingMode
reasoning: string
streaming?: boolean
@ -108,12 +120,12 @@ export const Thinking = memo(function Thinking({
<Text color={t.color.dim} dimColor {...(mode !== 'full' ? { wrap: 'truncate-end' as const } : {})}>
<Text dimColor> </Text>
{preview}
<StreamCursor active={streaming} color={t.color.dim} dimColor />
<StreamCursor color={t.color.dim} dimColor streaming={streaming} visible={active} />
</Text>
) : streaming ? (
) : active ? (
<Text color={t.color.dim} dimColor>
<Text dimColor> </Text>
<StreamCursor active={streaming} color={t.color.dim} dimColor />
<StreamCursor color={t.color.dim} dimColor streaming={streaming} visible={active} />
</Text>
) : null}
</Box>
@ -127,6 +139,7 @@ type Group = { color: string; content: ReactNode; details: DetailRow[]; key: str
export const ToolTrail = memo(function ToolTrail({
busy = false,
thinkingMode = 'truncated',
reasoningActive = false,
reasoning = '',
reasoningStreaming = false,
t,
@ -136,6 +149,7 @@ export const ToolTrail = memo(function ToolTrail({
}: {
busy?: boolean
thinkingMode?: ThinkingMode
reasoningActive?: boolean
reasoning?: string
reasoningStreaming?: boolean
t: Theme
@ -157,7 +171,7 @@ export const ToolTrail = memo(function ToolTrail({
const reasoningTail = thinkingPreview(reasoning, thinkingMode, THINKING_COT_MAX)
if (!busy && !trail.length && !tools.length && !activity.length && !reasoningTail) {
if (!busy && !trail.length && !tools.length && !activity.length && !reasoningTail && !reasoningActive) {
return null
}
@ -247,16 +261,16 @@ export const ToolTrail = memo(function ToolTrail({
content: (
<>
{reasoningTail}
<StreamCursor active={reasoningStreaming} color={t.color.dim} dimColor />
<StreamCursor color={t.color.dim} dimColor streaming={reasoningStreaming} visible={reasoningActive} />
</>
),
dimColor: true,
key: 'cot'
})
} else if (reasoningStreaming && groups.length && thinkingMode === 'collapsed') {
} else if (reasoningActive && groups.length && thinkingMode === 'collapsed') {
detail({
color: t.color.dim,
content: <StreamCursor active={reasoningStreaming} color={t.color.dim} dimColor />,
content: <StreamCursor color={t.color.dim} dimColor streaming={reasoningStreaming} visible={reasoningActive} />,
dimColor: true,
key: 'cot'
})
@ -276,7 +290,13 @@ export const ToolTrail = memo(function ToolTrail({
return (
<Box flexDirection="column">
{busy && !groups.length && (
<Thinking mode={thinkingMode} reasoning={reasoning} streaming={reasoningStreaming} t={t} />
<Thinking
active={reasoningActive}
mode={thinkingMode}
reasoning={reasoning}
streaming={reasoningStreaming}
t={t}
/>
)}
{!busy && !groups.length && reasoningTail && (
<Detail color={t.color.dim} content={reasoningTail} dimColor key="cot" />