@miphamai/cli 0.32.3 → 0.32.5
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/app.tsx +6 -18
- package/src/ui/chat.tsx +9 -11
- package/src/ui/input.tsx +31 -3
package/package.json
CHANGED
package/src/ui/app.tsx
CHANGED
|
@@ -444,7 +444,12 @@ export function App({
|
|
|
444
444
|
|
|
445
445
|
// Start agent progress indicator immediately for ALL processing
|
|
446
446
|
const progressStart = Date.now()
|
|
447
|
-
const progress: AgentProgress = {
|
|
447
|
+
const progress: AgentProgress = {
|
|
448
|
+
name: '',
|
|
449
|
+
description: '',
|
|
450
|
+
startTime: progressStart,
|
|
451
|
+
tokensUsed: 0,
|
|
452
|
+
}
|
|
448
453
|
agentProgressRef.current = progress
|
|
449
454
|
setAgentProgress(progress)
|
|
450
455
|
setAgentTick((t) => t + 1)
|
|
@@ -700,14 +705,6 @@ export function App({
|
|
|
700
705
|
if (apiKeyPrompt) {
|
|
701
706
|
return (
|
|
702
707
|
<Box flexDirection="column" padding={1} height="100%">
|
|
703
|
-
{/* Header */}
|
|
704
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
705
|
-
<Text color="#FFD700" bold>
|
|
706
|
-
Mipham Code
|
|
707
|
-
</Text>
|
|
708
|
-
<Text dimColor>v{version || '0.0.0'}</Text>
|
|
709
|
-
</Box>
|
|
710
|
-
|
|
711
708
|
{/* Chat panel — show existing messages */}
|
|
712
709
|
<ChatPanel messages={messages} focusMode={false} />
|
|
713
710
|
|
|
@@ -747,15 +744,6 @@ export function App({
|
|
|
747
744
|
|
|
748
745
|
return (
|
|
749
746
|
<Box flexDirection="column" padding={1} height="100%">
|
|
750
|
-
{/* Header — left-aligned */}
|
|
751
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
752
|
-
<Text color="#FFD700" bold>
|
|
753
|
-
Mipham Code
|
|
754
|
-
</Text>
|
|
755
|
-
<Text dimColor>v{version || '0.0.0'}</Text>
|
|
756
|
-
<Text dimColor>{modelId}</Text>
|
|
757
|
-
</Box>
|
|
758
|
-
|
|
759
747
|
{/* Workflow progress — auto-detects active workflows, renders nothing when idle */}
|
|
760
748
|
<WorkflowProgress />
|
|
761
749
|
|
package/src/ui/chat.tsx
CHANGED
|
@@ -79,17 +79,15 @@ const MessageRow = React.memo(
|
|
|
79
79
|
</Box>
|
|
80
80
|
) : (
|
|
81
81
|
<>
|
|
82
|
-
|
|
83
|
-
bold
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
:
|
|
92
|
-
</Text>
|
|
82
|
+
{msg.role === 'user' ? (
|
|
83
|
+
<Text bold color="green">
|
|
84
|
+
▸ {displayCwd()}:
|
|
85
|
+
</Text>
|
|
86
|
+
) : msg.role === 'system' ? (
|
|
87
|
+
<Text bold color="yellow">
|
|
88
|
+
⚠ {t('ui.system.role_label')}:
|
|
89
|
+
</Text>
|
|
90
|
+
) : null}
|
|
93
91
|
<Text>{msg.content}</Text>
|
|
94
92
|
</>
|
|
95
93
|
)}
|
package/src/ui/input.tsx
CHANGED
|
@@ -79,6 +79,11 @@ export function InputBar({
|
|
|
79
79
|
}: InputBarProps) {
|
|
80
80
|
const { t } = useI18n()
|
|
81
81
|
const [value, setValue] = useState('')
|
|
82
|
+
// Ref mirror of value — used by useInput to read latest without stale closure.
|
|
83
|
+
// Also used by throttled onChange to hold the latest pending value.
|
|
84
|
+
const valueRef = useRef(value)
|
|
85
|
+
// Throttle timer for onChange — prevents React render floods during paste.
|
|
86
|
+
const onChangeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
82
87
|
const [verb, setVerb] = useState(() => t(pick(LOADING_KEYS)))
|
|
83
88
|
const [completionVerb, setCompletionVerb] = useState<string | null>(null)
|
|
84
89
|
const prevLoading = useRef(isLoading)
|
|
@@ -330,14 +335,27 @@ export function InputBar({
|
|
|
330
335
|
prevValueRef.current = value
|
|
331
336
|
}, [value, vimMode])
|
|
332
337
|
|
|
338
|
+
// Keep valueRef in sync with state (so useInput handlers read latest value)
|
|
339
|
+
useEffect(() => {
|
|
340
|
+
valueRef.current = value
|
|
341
|
+
}, [value])
|
|
342
|
+
|
|
333
343
|
const handleSubmit = (val: string) => {
|
|
334
|
-
|
|
344
|
+
// Flush any pending throttled onChange before submitting
|
|
345
|
+
if (onChangeTimerRef.current) {
|
|
346
|
+
clearTimeout(onChangeTimerRef.current)
|
|
347
|
+
onChangeTimerRef.current = null
|
|
348
|
+
}
|
|
349
|
+
// Use latest value from ref (may be ahead of state during throttle)
|
|
350
|
+
const finalValue = val || valueRef.current
|
|
351
|
+
if (!finalValue.trim() || isLoading) return
|
|
335
352
|
// Save to message history for arrow-key navigation
|
|
336
|
-
setSubmittedHistory((prev) => [...prev,
|
|
353
|
+
setSubmittedHistory((prev) => [...prev, finalValue])
|
|
337
354
|
historyIndexRef.current = -1
|
|
338
355
|
savedDraftRef.current = ''
|
|
339
|
-
onSubmit(
|
|
356
|
+
onSubmit(finalValue)
|
|
340
357
|
setValue('')
|
|
358
|
+
valueRef.current = ''
|
|
341
359
|
setPickerActive(false)
|
|
342
360
|
}
|
|
343
361
|
|
|
@@ -380,7 +398,17 @@ export function InputBar({
|
|
|
380
398
|
historyIndexRef.current = -1
|
|
381
399
|
savedDraftRef.current = ''
|
|
382
400
|
}
|
|
401
|
+
// Throttle: first keystroke renders immediately, then batch at ~30fps.
|
|
402
|
+
// During paste, the terminal may send hundreds of characters in rapid
|
|
403
|
+
// succession — without throttling, each triggers a React render+Ink write
|
|
404
|
+
// cycle that starves the event loop and freezes the UI.
|
|
405
|
+
valueRef.current = val
|
|
406
|
+
if (onChangeTimerRef.current) return // timer pending, latest value in ref
|
|
383
407
|
setValue(val)
|
|
408
|
+
onChangeTimerRef.current = setTimeout(() => {
|
|
409
|
+
onChangeTimerRef.current = null
|
|
410
|
+
setValue(valueRef.current)
|
|
411
|
+
}, 33) // ~30fps
|
|
384
412
|
}}
|
|
385
413
|
onSubmit={handleSubmit}
|
|
386
414
|
placeholder={
|