import { Text } from 'ink' import { memo, useEffect, useState } from 'react' import spinners, { type BrailleSpinnerName } from 'unicode-animations' import { FACES, TOOL_VERBS, VERBS } from '../constants.js' import type { Theme } from '../theme.js' import type { ActiveTool } from '../types.js' const THINK_POOL: BrailleSpinnerName[] = ['helix', 'breathe', 'orbit', 'dna', 'waverows', 'snake', 'pulse'] const TOOL_POOL: BrailleSpinnerName[] = ['cascade', 'scan', 'diagswipe', 'fillsweep', 'rain', 'columns', 'sparkle'] const pick = (arr: T[]) => arr[Math.floor(Math.random() * arr.length)]! function Spinner({ color, variant = 'think' }: { color: string; variant?: 'think' | 'tool' }) { const [spin] = useState(() => spinners[pick(variant === 'tool' ? TOOL_POOL : THINK_POOL)]) const [i, setI] = useState(0) useEffect(() => { const id = setInterval(() => setI(p => (p + 1) % spin.frames.length), spin.interval) return () => clearInterval(id) }, [spin]) return {spin.frames[i]} } export const Thinking = memo(function Thinking({ reasoning, t, tools }: { reasoning: string t: Theme tools: ActiveTool[] }) { const [tick, setTick] = useState(0) useEffect(() => { const id = setInterval(() => { setTick(v => v + 1) }, 1100) return () => clearInterval(id) }, []) const verb = VERBS[tick % VERBS.length] ?? 'thinking' const face = FACES[tick % FACES.length] ?? '(•_•)' const tail = reasoning.slice(-160).replace(/\n/g, ' ') return ( <> {tools.map(tool => ( {TOOL_VERBS[tool.name] ?? tool.name} {tool.context ? `: ${tool.context}` : ''} ))} {!tools.length && ( {face} {verb}… )} {tail && ( 💭 {tail} )} ) })