@miphamai/cli 0.32.2 → 0.32.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ui/agent-footer.tsx +37 -10
- package/src/ui/app.tsx +41 -12
package/package.json
CHANGED
package/src/ui/agent-footer.tsx
CHANGED
|
@@ -48,11 +48,25 @@ function formatTokens(n: number): string {
|
|
|
48
48
|
/** Map tool name to Ink color for the [Tool ...] indicator. */
|
|
49
49
|
function toolIndicatorColor(name: string): string {
|
|
50
50
|
switch (name) {
|
|
51
|
-
case 'Bash':
|
|
52
|
-
case '
|
|
53
|
-
case '
|
|
54
|
-
case '
|
|
55
|
-
|
|
51
|
+
case 'Bash':
|
|
52
|
+
case 'Read':
|
|
53
|
+
case 'Glob':
|
|
54
|
+
case 'Grep':
|
|
55
|
+
return 'white'
|
|
56
|
+
case 'Write':
|
|
57
|
+
case 'Edit':
|
|
58
|
+
case 'Update':
|
|
59
|
+
return 'red'
|
|
60
|
+
case 'Agent':
|
|
61
|
+
case 'Task':
|
|
62
|
+
case 'Skill':
|
|
63
|
+
case 'Workflow':
|
|
64
|
+
return 'magenta'
|
|
65
|
+
case 'WebSearch':
|
|
66
|
+
case 'WebFetch':
|
|
67
|
+
return 'blue'
|
|
68
|
+
default:
|
|
69
|
+
return 'white'
|
|
56
70
|
}
|
|
57
71
|
}
|
|
58
72
|
|
|
@@ -64,10 +78,22 @@ function animatedDots(tick: number): string {
|
|
|
64
78
|
|
|
65
79
|
/** Gerund verbs for agent progress — rotated every 2 seconds for visual liveliness. */
|
|
66
80
|
const GERUNDS = [
|
|
67
|
-
'Pondering',
|
|
68
|
-
'
|
|
69
|
-
'
|
|
70
|
-
'
|
|
81
|
+
'Pondering',
|
|
82
|
+
'Contemplating',
|
|
83
|
+
'Cerebrating',
|
|
84
|
+
'Ruminating',
|
|
85
|
+
'Deliberating',
|
|
86
|
+
'Cogitating',
|
|
87
|
+
'Perambulating',
|
|
88
|
+
'Computing',
|
|
89
|
+
'Processing',
|
|
90
|
+
'Analyzing',
|
|
91
|
+
'Synthesizing',
|
|
92
|
+
'Orchestrating',
|
|
93
|
+
'Forging',
|
|
94
|
+
'Illuminating',
|
|
95
|
+
'Manifesting',
|
|
96
|
+
'Transmogrifying',
|
|
71
97
|
]
|
|
72
98
|
|
|
73
99
|
/** Pick a gerund that changes every 2 seconds (driven by tick). */
|
|
@@ -89,7 +115,8 @@ export function AgentFooter({ agents, tick, activeTool, agentProgress }: AgentFo
|
|
|
89
115
|
{hasTool && (
|
|
90
116
|
<Box>
|
|
91
117
|
<Text color={toolIndicatorColor(activeTool!.name)}>
|
|
92
|
-
{' '}[{activeTool!.name} {activeTool!.detail.slice(0, 60)}
|
|
118
|
+
{' '}[{activeTool!.name} {activeTool!.detail.slice(0, 60)}
|
|
119
|
+
{animatedDots(tick)}]
|
|
93
120
|
</Text>
|
|
94
121
|
</Box>
|
|
95
122
|
)}
|
package/src/ui/app.tsx
CHANGED
|
@@ -185,11 +185,17 @@ export function App({
|
|
|
185
185
|
const [agentTick, setAgentTick] = useState(0)
|
|
186
186
|
/** Active foreground tool indicator: [Bash command...], [Update file.ts...], etc. */
|
|
187
187
|
const [activeTool, setActiveTool] = useState<{ name: string; detail: string } | null>(null)
|
|
188
|
+
// Refs for immediate state (bypasses React batching so footer renders between rapid chunks)
|
|
189
|
+
const activeToolRef = useRef<{ name: string; detail: string } | null>(null)
|
|
190
|
+
const agentProgressRef = useRef<AgentProgress | null>(null)
|
|
188
191
|
|
|
189
|
-
// Tick timer for agent elapsed displays (re-renders every second while agents are running)
|
|
192
|
+
// Tick timer for agent elapsed displays (re-renders every second while agents are running).
|
|
193
|
+
// Uses refs so the timer doesn't stop between state batches.
|
|
190
194
|
useEffect(() => {
|
|
191
195
|
const hasRunning =
|
|
192
|
-
Object.values(runningAgents).some((a) => a.status === 'running') ||
|
|
196
|
+
Object.values(runningAgents).some((a) => a.status === 'running') ||
|
|
197
|
+
agentProgressRef.current !== null ||
|
|
198
|
+
activeToolRef.current !== null
|
|
193
199
|
if (!hasRunning) return
|
|
194
200
|
const i = setInterval(() => setAgentTick((t) => t + 1), 1000)
|
|
195
201
|
return () => clearInterval(i)
|
|
@@ -436,6 +442,13 @@ export function App({
|
|
|
436
442
|
setMessages((prev) => [...prev, { role: 'user', content: input }])
|
|
437
443
|
setIsLoading(true)
|
|
438
444
|
|
|
445
|
+
// Start agent progress indicator immediately for ALL processing
|
|
446
|
+
const progressStart = Date.now()
|
|
447
|
+
const progress: AgentProgress = { name: '', description: '', startTime: progressStart, tokensUsed: 0 }
|
|
448
|
+
agentProgressRef.current = progress
|
|
449
|
+
setAgentProgress(progress)
|
|
450
|
+
setAgentTick((t) => t + 1)
|
|
451
|
+
|
|
439
452
|
const controller = new AbortController()
|
|
440
453
|
abortRef.current = controller
|
|
441
454
|
|
|
@@ -509,18 +522,24 @@ export function App({
|
|
|
509
522
|
const isAgent = toolName === 'Agent' || toolName === 'Task'
|
|
510
523
|
const detail = formatToolDetail(toolName, chunk.toolUse.input)
|
|
511
524
|
|
|
512
|
-
// Show [ToolName detail...] activity indicator for ALL tools
|
|
513
|
-
|
|
525
|
+
// Show [ToolName detail...] activity indicator for ALL tools (via ref for immediate render)
|
|
526
|
+
const toolEntry = { name: toolDisplayName(toolName), detail }
|
|
527
|
+
activeToolRef.current = toolEntry
|
|
528
|
+
setActiveTool(toolEntry)
|
|
529
|
+
setAgentTick((t) => t + 1)
|
|
514
530
|
|
|
515
531
|
if (isAgent) {
|
|
516
|
-
|
|
532
|
+
const ap: AgentProgress = {
|
|
517
533
|
name: detail || (chunk.toolUse.input.subagent_type as string) || 'General-purpose',
|
|
518
534
|
description:
|
|
519
535
|
(chunk.toolUse.input.description as string) ||
|
|
520
536
|
(chunk.toolUse.input.prompt as string) ||
|
|
521
537
|
'',
|
|
522
538
|
startTime: Date.now(),
|
|
523
|
-
}
|
|
539
|
+
}
|
|
540
|
+
agentProgressRef.current = ap
|
|
541
|
+
setAgentProgress(ap)
|
|
542
|
+
setAgentTick((t) => t + 1)
|
|
524
543
|
}
|
|
525
544
|
|
|
526
545
|
// Show tool call as a visible, collapsed message
|
|
@@ -544,8 +563,10 @@ export function App({
|
|
|
544
563
|
}
|
|
545
564
|
|
|
546
565
|
if (chunk.type === 'tool_result') {
|
|
547
|
-
|
|
566
|
+
// Clear tool indicator but keep agent progress (AI is still processing)
|
|
567
|
+
activeToolRef.current = null
|
|
548
568
|
setActiveTool(null)
|
|
569
|
+
setAgentTick((t) => t + 1)
|
|
549
570
|
// Sync background agents (e.g. Agent tool may have spawned them)
|
|
550
571
|
syncBgAgents()
|
|
551
572
|
const output = chunk.content ? String(chunk.content).trim() : ''
|
|
@@ -582,12 +603,14 @@ export function App({
|
|
|
582
603
|
}
|
|
583
604
|
}
|
|
584
605
|
|
|
585
|
-
if (chunk.type === 'usage'
|
|
606
|
+
if (chunk.type === 'usage') {
|
|
586
607
|
const totalTokens = (chunk.inputTokens || 0) + (chunk.outputTokens || 0)
|
|
587
|
-
if (totalTokens > 0) {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
608
|
+
if (totalTokens > 0 && agentProgressRef.current) {
|
|
609
|
+
agentProgressRef.current = {
|
|
610
|
+
...agentProgressRef.current,
|
|
611
|
+
tokensUsed: (agentProgressRef.current.tokensUsed || 0) + totalTokens,
|
|
612
|
+
}
|
|
613
|
+
setAgentProgress({ ...agentProgressRef.current })
|
|
591
614
|
}
|
|
592
615
|
}
|
|
593
616
|
|
|
@@ -631,6 +654,12 @@ export function App({
|
|
|
631
654
|
flushStreamBuffer()
|
|
632
655
|
setIsLoading(false)
|
|
633
656
|
abortRef.current = null
|
|
657
|
+
// Clear all progress/tool indicators
|
|
658
|
+
agentProgressRef.current = null
|
|
659
|
+
setAgentProgress(null)
|
|
660
|
+
activeToolRef.current = null
|
|
661
|
+
setActiveTool(null)
|
|
662
|
+
setAgentTick((t) => t + 1)
|
|
634
663
|
// Auto-save checkpoint after each AI response
|
|
635
664
|
if (assistantContent) {
|
|
636
665
|
engine.getContext().saveCheckpoint('post-turn')
|