mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
feat: cute spinners
This commit is contained in:
@@ -1,21 +1,27 @@
|
||||
import { Text } from 'ink'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
import spinners, { type BrailleSpinnerName } from 'unicode-animations'
|
||||
|
||||
import { FACES, SPINNER, TOOL_VERBS, VERBS } from '../constants.js'
|
||||
import { pick } from '../lib/text.js'
|
||||
import { FACES, TOOL_VERBS, VERBS } from '../constants.js'
|
||||
import type { Theme } from '../theme.js'
|
||||
import type { ActiveTool } from '../types.js'
|
||||
|
||||
function Spinner({ color }: { color: string }) {
|
||||
const THINK_POOL: BrailleSpinnerName[] = ['helix', 'breathe', 'orbit', 'dna', 'waverows', 'snake', 'pulse']
|
||||
const TOOL_POOL: BrailleSpinnerName[] = ['cascade', 'scan', 'diagswipe', 'fillsweep', 'rain', 'columns', 'sparkle']
|
||||
|
||||
const pick = <T,>(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) % SPINNER.length), 80)
|
||||
const id = setInterval(() => setI(p => (p + 1) % spin.frames.length), spin.interval)
|
||||
|
||||
return () => clearInterval(id)
|
||||
}, [])
|
||||
}, [spin])
|
||||
|
||||
return <Text color={color}>{SPINNER[i]}</Text>
|
||||
return <Text color={color}>{spin.frames[i]}</Text>
|
||||
}
|
||||
|
||||
export const Thinking = memo(function Thinking({
|
||||
@@ -27,25 +33,25 @@ export const Thinking = memo(function Thinking({
|
||||
t: Theme
|
||||
tools: ActiveTool[]
|
||||
}) {
|
||||
const [verb, setVerb] = useState(() => pick(VERBS))
|
||||
const [face, setFace] = useState(() => pick(FACES))
|
||||
const [tick, setTick] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => {
|
||||
setVerb(pick(VERBS))
|
||||
setFace(pick(FACES))
|
||||
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 => (
|
||||
<Text color={t.color.dim} key={tool.id}>
|
||||
<Spinner color={t.color.amber} /> {TOOL_VERBS[tool.name] ?? tool.name}
|
||||
<Spinner color={t.color.amber} variant="tool" /> {TOOL_VERBS[tool.name] ?? tool.name}
|
||||
{tool.context ? `: ${tool.context}` : ''}
|
||||
</Text>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user