attocode 0.1.4 → 0.1.6
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/CHANGELOG.md +36 -1
- package/dist/src/agent.d.ts +40 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +492 -37
- package/dist/src/agent.js.map +1 -1
- package/dist/src/core/index.d.ts +1 -6
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +4 -7
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/defaults.d.ts +1 -1
- package/dist/src/defaults.d.ts.map +1 -1
- package/dist/src/integrations/agent-registry.d.ts.map +1 -1
- package/dist/src/integrations/agent-registry.js +8 -1
- package/dist/src/integrations/agent-registry.js.map +1 -1
- package/dist/src/integrations/codebase-context.d.ts +163 -0
- package/dist/src/integrations/codebase-context.d.ts.map +1 -1
- package/dist/src/integrations/codebase-context.js +462 -0
- package/dist/src/integrations/codebase-context.js.map +1 -1
- package/dist/src/integrations/economics.d.ts +94 -2
- package/dist/src/integrations/economics.d.ts.map +1 -1
- package/dist/src/integrations/economics.js +265 -12
- package/dist/src/integrations/economics.js.map +1 -1
- package/dist/src/integrations/file-change-tracker.d.ts +1 -0
- package/dist/src/integrations/file-change-tracker.d.ts.map +1 -1
- package/dist/src/integrations/file-change-tracker.js +30 -12
- package/dist/src/integrations/file-change-tracker.js.map +1 -1
- package/dist/src/integrations/graph-visualization.d.ts +72 -0
- package/dist/src/integrations/graph-visualization.d.ts.map +1 -0
- package/dist/src/integrations/graph-visualization.js +383 -0
- package/dist/src/integrations/graph-visualization.js.map +1 -0
- package/dist/src/integrations/index.d.ts +2 -1
- package/dist/src/integrations/index.d.ts.map +1 -1
- package/dist/src/integrations/index.js +2 -0
- package/dist/src/integrations/index.js.map +1 -1
- package/dist/src/integrations/memory.d.ts +8 -0
- package/dist/src/integrations/memory.d.ts.map +1 -1
- package/dist/src/integrations/memory.js +23 -0
- package/dist/src/integrations/memory.js.map +1 -1
- package/dist/src/integrations/pending-plan.d.ts +26 -1
- package/dist/src/integrations/pending-plan.d.ts.map +1 -1
- package/dist/src/integrations/pending-plan.js +131 -3
- package/dist/src/integrations/pending-plan.js.map +1 -1
- package/dist/src/integrations/planning.d.ts +19 -0
- package/dist/src/integrations/planning.d.ts.map +1 -1
- package/dist/src/integrations/planning.js +78 -4
- package/dist/src/integrations/planning.js.map +1 -1
- package/dist/src/integrations/safety.d.ts +4 -0
- package/dist/src/integrations/safety.d.ts.map +1 -1
- package/dist/src/integrations/safety.js +46 -7
- package/dist/src/integrations/safety.js.map +1 -1
- package/dist/src/integrations/sqlite-store.d.ts.map +1 -1
- package/dist/src/integrations/sqlite-store.js +7 -1
- package/dist/src/integrations/sqlite-store.js.map +1 -1
- package/dist/src/main.js +0 -0
- package/dist/src/modes.d.ts +7 -0
- package/dist/src/modes.d.ts.map +1 -1
- package/dist/src/modes.js +69 -2
- package/dist/src/modes.js.map +1 -1
- package/dist/src/providers/llm-resilience.d.ts +8 -0
- package/dist/src/providers/llm-resilience.d.ts.map +1 -1
- package/dist/src/providers/llm-resilience.js +36 -0
- package/dist/src/providers/llm-resilience.js.map +1 -1
- package/dist/src/tools/agent.d.ts +20 -0
- package/dist/src/tools/agent.d.ts.map +1 -1
- package/dist/src/tools/agent.js +114 -0
- package/dist/src/tools/agent.js.map +1 -1
- package/dist/src/tools/file.d.ts.map +1 -1
- package/dist/src/tools/file.js +17 -3
- package/dist/src/tools/file.js.map +1 -1
- package/dist/src/tracing/trace-collector.d.ts +11 -1
- package/dist/src/tracing/trace-collector.d.ts.map +1 -1
- package/dist/src/tracing/trace-collector.js +92 -12
- package/dist/src/tracing/trace-collector.js.map +1 -1
- package/dist/src/tracing/types.d.ts +6 -0
- package/dist/src/tracing/types.d.ts.map +1 -1
- package/dist/src/tracing/types.js.map +1 -1
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +244 -66
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/components/CollapsibleDiffView.d.ts +49 -0
- package/dist/src/tui/components/CollapsibleDiffView.d.ts.map +1 -0
- package/dist/src/tui/components/CollapsibleDiffView.js +302 -0
- package/dist/src/tui/components/CollapsibleDiffView.js.map +1 -0
- package/dist/src/tui/components/DiffView.d.ts +55 -0
- package/dist/src/tui/components/DiffView.d.ts.map +1 -0
- package/dist/src/tui/components/DiffView.js +356 -0
- package/dist/src/tui/components/DiffView.js.map +1 -0
- package/dist/src/tui/components/FileChangeSummary.d.ts +48 -0
- package/dist/src/tui/components/FileChangeSummary.d.ts.map +1 -0
- package/dist/src/tui/components/FileChangeSummary.js +152 -0
- package/dist/src/tui/components/FileChangeSummary.js.map +1 -0
- package/dist/src/tui/components/SideBySideDiff.d.ts +62 -0
- package/dist/src/tui/components/SideBySideDiff.d.ts.map +1 -0
- package/dist/src/tui/components/SideBySideDiff.js +320 -0
- package/dist/src/tui/components/SideBySideDiff.js.map +1 -0
- package/dist/src/tui/components/SyntaxText.d.ts +47 -0
- package/dist/src/tui/components/SyntaxText.d.ts.map +1 -0
- package/dist/src/tui/components/SyntaxText.js +43 -0
- package/dist/src/tui/components/SyntaxText.js.map +1 -0
- package/dist/src/tui/components/index.d.ts +5 -0
- package/dist/src/tui/components/index.d.ts.map +1 -1
- package/dist/src/tui/components/index.js +7 -0
- package/dist/src/tui/components/index.js.map +1 -1
- package/dist/src/tui/syntax/index.d.ts +12 -0
- package/dist/src/tui/syntax/index.d.ts.map +1 -0
- package/dist/src/tui/syntax/index.js +14 -0
- package/dist/src/tui/syntax/index.js.map +1 -0
- package/dist/src/tui/syntax/languages/bash.d.ts +8 -0
- package/dist/src/tui/syntax/languages/bash.d.ts.map +1 -0
- package/dist/src/tui/syntax/languages/bash.js +296 -0
- package/dist/src/tui/syntax/languages/bash.js.map +1 -0
- package/dist/src/tui/syntax/languages/javascript.d.ts +8 -0
- package/dist/src/tui/syntax/languages/javascript.d.ts.map +1 -0
- package/dist/src/tui/syntax/languages/javascript.js +253 -0
- package/dist/src/tui/syntax/languages/javascript.js.map +1 -0
- package/dist/src/tui/syntax/languages/json.d.ts +8 -0
- package/dist/src/tui/syntax/languages/json.d.ts.map +1 -0
- package/dist/src/tui/syntax/languages/json.js +112 -0
- package/dist/src/tui/syntax/languages/json.js.map +1 -0
- package/dist/src/tui/syntax/languages/python.d.ts +8 -0
- package/dist/src/tui/syntax/languages/python.d.ts.map +1 -0
- package/dist/src/tui/syntax/languages/python.js +232 -0
- package/dist/src/tui/syntax/languages/python.js.map +1 -0
- package/dist/src/tui/syntax/lexer.d.ts +51 -0
- package/dist/src/tui/syntax/lexer.d.ts.map +1 -0
- package/dist/src/tui/syntax/lexer.js +131 -0
- package/dist/src/tui/syntax/lexer.js.map +1 -0
- package/dist/src/types.d.ts +56 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +4 -1
package/dist/src/tui/app.js
CHANGED
|
@@ -10,6 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
10
10
|
*/
|
|
11
11
|
import { useState, useCallback, useEffect, memo, useRef, useMemo } from 'react';
|
|
12
12
|
import { Box, Text, useApp, useInput, Static } from 'ink';
|
|
13
|
+
import { DiffView } from './components/DiffView.js';
|
|
13
14
|
import { getTheme, getThemeNames } from './theme/index.js';
|
|
14
15
|
import { ControlledCommandPalette } from './input/CommandPalette.js';
|
|
15
16
|
import { ApprovalDialog } from './components/ApprovalDialog.js';
|
|
@@ -114,9 +115,18 @@ const ToolCallItem = memo(function ToolCallItem({ tc, expanded, colors }) {
|
|
|
114
115
|
const argsStr = formatToolArgsCompact(tc.args);
|
|
115
116
|
if (expanded) {
|
|
116
117
|
const expandedArgs = formatToolArgsExpanded(tc.args);
|
|
117
|
-
return (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: statusColor, children: icon }), _jsx(Text, { color: "#DDA0DD", bold: true, children: tc.name }), tc.duration ? _jsxs(Text, { color: colors.textMuted, dimColor: true, children: ["(", tc.duration, "ms)"] }) : null] }), expandedArgs.map((argLine, i) => (_jsx(Box, { marginLeft: 3, children: _jsx(Text, { color: "#87CEEB", dimColor: true, children: argLine }) }, i))), tc.status === 'success' && tc.result !== undefined && tc.result !== null ? (_jsx(Box, { marginLeft: 3,
|
|
118
|
+
return (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: statusColor, children: icon }), _jsx(Text, { color: "#DDA0DD", bold: true, children: tc.name }), tc.duration ? _jsxs(Text, { color: colors.textMuted, dimColor: true, children: ["(", tc.duration, "ms)"] }) : null] }), expandedArgs.map((argLine, i) => (_jsx(Box, { marginLeft: 3, children: _jsx(Text, { color: "#87CEEB", dimColor: true, children: argLine }) }, i))), tc.status === 'success' && tc.result !== undefined && tc.result !== null ? (_jsx(Box, { marginLeft: 3, flexDirection: "column", children: (tc.name === 'edit_file' || tc.name === 'write_file') &&
|
|
119
|
+
typeof tc.result === 'object' && tc.result !== null &&
|
|
120
|
+
'metadata' in tc.result &&
|
|
121
|
+
typeof tc.result.metadata?.diff === 'string' ? (_jsx(DiffView, { diff: tc.result.metadata.diff, expanded: true, maxLines: 15 })) : (_jsx(Text, { color: "#98FB98", dimColor: true, children: `-> ${String(tc.result).slice(0, 150)}${String(tc.result).length > 150 ? '...' : ''}` })) })) : null, tc.status === 'error' && tc.error && (_jsx(Box, { marginLeft: 3, children: _jsx(Text, { color: "#FF6B6B", children: `x ${tc.error}` }) }))] }));
|
|
118
122
|
}
|
|
119
|
-
|
|
123
|
+
// Check if result has diff metadata for collapsed summary
|
|
124
|
+
const hasDiff = tc.status === 'success' &&
|
|
125
|
+
(tc.name === 'edit_file' || tc.name === 'write_file') &&
|
|
126
|
+
typeof tc.result === 'object' && tc.result !== null &&
|
|
127
|
+
'metadata' in tc.result &&
|
|
128
|
+
typeof tc.result.metadata?.diff === 'string';
|
|
129
|
+
return (_jsxs(Box, { marginLeft: 2, gap: 1, children: [_jsx(Text, { color: statusColor, children: icon }), _jsx(Text, { color: "#DDA0DD", bold: true, children: tc.name }), argsStr ? _jsx(Text, { color: colors.textMuted, dimColor: true, children: argsStr }) : null, hasDiff && (_jsx(DiffView, { diff: tc.result.metadata.diff, expanded: false })), tc.duration ? _jsxs(Text, { color: colors.textMuted, dimColor: true, children: ["(", tc.duration, "ms)"] }) : null] }));
|
|
120
130
|
});
|
|
121
131
|
const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled, borderColor, textColor, cursorColor, onCtrlC, onCtrlL, onCtrlP, onEscape, onToggleToolExpand, onToggleThinking, onToggleTransparency, onPageUp, onPageDown, onHome, onEnd, commandPaletteOpen, onCommandPaletteInput, approvalDialogOpen, approvalDenyReasonMode, onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason, onApprovalCancelDenyReason, onApprovalDenyReasonInput, }) {
|
|
122
132
|
const [value, setValue] = useState('');
|
|
@@ -304,6 +314,8 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
304
314
|
const [contextTokens, setContextTokens] = useState(0);
|
|
305
315
|
const [elapsedTime, setElapsedTime] = useState(0);
|
|
306
316
|
const processingStartRef = useRef(null);
|
|
317
|
+
const [executionMode, setExecutionMode] = useState('idle');
|
|
318
|
+
const executionModeRef = useRef('idle');
|
|
307
319
|
// Display toggles
|
|
308
320
|
const [toolCallsExpanded, setToolCallsExpanded] = useState(false);
|
|
309
321
|
const [showThinking, setShowThinking] = useState(true);
|
|
@@ -400,6 +412,203 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
400
412
|
});
|
|
401
413
|
}
|
|
402
414
|
}, [approvalBridge, handleApprovalRequest]);
|
|
415
|
+
// =========================================================================
|
|
416
|
+
// UNIFIED EVENT HANDLER
|
|
417
|
+
// Consolidated handler for all agent events - prevents duplicate messages
|
|
418
|
+
// =========================================================================
|
|
419
|
+
const handleAgentEvent = useCallback((event) => {
|
|
420
|
+
const mode = executionModeRef.current;
|
|
421
|
+
if (mode === 'idle')
|
|
422
|
+
return; // No active execution, ignore events
|
|
423
|
+
// Extract subagent from event if present (not all events have it)
|
|
424
|
+
const eventWithSubagent = event;
|
|
425
|
+
const subagentPrefix = eventWithSubagent.subagent ? `[${eventWithSubagent.subagent}] ` : '';
|
|
426
|
+
// -------------------------------------------------------------------------
|
|
427
|
+
// Approving-only events (plan execution)
|
|
428
|
+
// -------------------------------------------------------------------------
|
|
429
|
+
if (mode === 'approving') {
|
|
430
|
+
if (event.type === 'plan.approved') {
|
|
431
|
+
const e = event;
|
|
432
|
+
addMessage('system', `[PLAN] Executing ${e.changeCount} change(s)...`);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
if (event.type === 'plan.executing') {
|
|
436
|
+
const e = event;
|
|
437
|
+
setStatus(s => ({ ...s, mode: `executing ${e.changeIndex + 1}/${e.totalChanges}` }));
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
// -------------------------------------------------------------------------
|
|
442
|
+
// Shared events (both processing and approving modes)
|
|
443
|
+
// -------------------------------------------------------------------------
|
|
444
|
+
// Subagent lifecycle events
|
|
445
|
+
if (event.type === 'agent.spawn') {
|
|
446
|
+
const e = event;
|
|
447
|
+
addMessage('system', `[AGENT] Spawning ${e.name}: ${e.task.slice(0, 100)}${e.task.length > 100 ? '...' : ''}`);
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
if (event.type === 'agent.complete') {
|
|
451
|
+
const e = event;
|
|
452
|
+
const statusText = e.success ? 'completed' : 'failed';
|
|
453
|
+
addMessage('system', `[AGENT] ${e.agentId} ${statusText}`);
|
|
454
|
+
// Show output preview if substantive
|
|
455
|
+
if (e.output && e.output.length > 50) {
|
|
456
|
+
const preview = e.output.slice(0, 300);
|
|
457
|
+
addMessage('system', `[AGENT OUTPUT]\n${preview}${e.output.length > 300 ? '\n...(truncated)' : ''}`);
|
|
458
|
+
}
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (event.type === 'agent.error') {
|
|
462
|
+
const e = event;
|
|
463
|
+
addMessage('system', `[AGENT] ${e.agentId} error: ${e.error}`);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (event.type === 'agent.pending_plan') {
|
|
467
|
+
const e = event;
|
|
468
|
+
addMessage('system', `[AGENT] ${e.agentId} queued ${e.changes.length} change(s) to pending plan`);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
// Tool events
|
|
472
|
+
if (event.type === 'tool.start') {
|
|
473
|
+
const e = event;
|
|
474
|
+
const displayName = e.subagent ? `${e.subagent}:${e.tool}` : e.tool;
|
|
475
|
+
setStatus(s => ({ ...s, mode: `calling ${displayName}` }));
|
|
476
|
+
setToolCalls(prev => [...prev.slice(-4), {
|
|
477
|
+
id: `${displayName}-${Date.now()}`,
|
|
478
|
+
name: displayName,
|
|
479
|
+
args: e.args || {},
|
|
480
|
+
status: 'running',
|
|
481
|
+
startTime: new Date(),
|
|
482
|
+
}]);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
if (event.type === 'tool.complete') {
|
|
486
|
+
const e = event;
|
|
487
|
+
const displayName = e.subagent ? `${e.subagent}:${e.tool}` : e.tool;
|
|
488
|
+
const modeText = e.subagent ? `${e.subagent} thinking` : (mode === 'approving' ? 'executing plan' : 'thinking');
|
|
489
|
+
setStatus(s => ({ ...s, mode: modeText }));
|
|
490
|
+
setToolCalls(prev => prev.map(t => t.name === displayName ? {
|
|
491
|
+
...t,
|
|
492
|
+
status: 'success',
|
|
493
|
+
result: e.result,
|
|
494
|
+
duration: t.startTime ? Date.now() - t.startTime.getTime() : undefined,
|
|
495
|
+
} : t));
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (event.type === 'tool.blocked') {
|
|
499
|
+
const e = event;
|
|
500
|
+
const displayName = e.subagent ? `${e.subagent}:${e.tool}` : e.tool;
|
|
501
|
+
setToolCalls(prev => prev.map(t => t.name === displayName ? {
|
|
502
|
+
...t,
|
|
503
|
+
status: 'error',
|
|
504
|
+
error: e.reason || 'Blocked',
|
|
505
|
+
} : t));
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
// LLM events
|
|
509
|
+
if (event.type === 'llm.start') {
|
|
510
|
+
const e = event;
|
|
511
|
+
const modeText = e.subagent ? `${e.subagent} thinking` : (mode === 'approving' ? 'executing plan' : 'thinking');
|
|
512
|
+
setStatus(s => ({ ...s, mode: modeText, iter: s.iter + 1 }));
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (event.type === 'llm.complete' && eventWithSubagent.subagent && showThinking) {
|
|
516
|
+
const e = event;
|
|
517
|
+
const thinking = e.response?.thinking;
|
|
518
|
+
if (thinking) {
|
|
519
|
+
const preview = thinking.length > 500 ? thinking.slice(0, 500) + '...' : thinking;
|
|
520
|
+
addMessage('system', `[${eventWithSubagent.subagent}] ${preview}`);
|
|
521
|
+
}
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
// Error events
|
|
525
|
+
if (event.type === 'error') {
|
|
526
|
+
const e = event;
|
|
527
|
+
const prefix = e.subagent ? `[${e.subagent} ERROR]` : '[ERROR]';
|
|
528
|
+
const errorMsg = typeof e.error === 'string' ? e.error : e.error?.message || 'Unknown error';
|
|
529
|
+
addMessage('error', `${prefix} ${errorMsg}`);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
// Insight events
|
|
533
|
+
if (event.type === 'insight.tokens' && showThinking) {
|
|
534
|
+
const e = event;
|
|
535
|
+
addMessage('system', `${subagentPrefix}* ${e.inputTokens.toLocaleString()} in, ${e.outputTokens.toLocaleString()} out${e.cost ? ` $${e.cost.toFixed(6)}` : ''}`);
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
// Resilience events
|
|
539
|
+
if (event.type === 'resilience.retry') {
|
|
540
|
+
const e = event;
|
|
541
|
+
addMessage('system', `[RETRY] ${e.reason} (${e.attempt}/${e.maxAttempts})`);
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (event.type === 'resilience.recovered') {
|
|
545
|
+
const e = event;
|
|
546
|
+
addMessage('system', `[RECOVERED] ${e.reason} after ${e.attempts} attempt(s)`);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
// Subagent visibility events
|
|
550
|
+
if (event.type === 'subagent.iteration') {
|
|
551
|
+
const e = event;
|
|
552
|
+
setStatus(s => ({ ...s, mode: `${e.agentId} iter ${e.iteration}/${e.maxIterations}` }));
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (event.type === 'subagent.phase') {
|
|
556
|
+
const e = event;
|
|
557
|
+
setStatus(s => ({ ...s, mode: `${e.agentId} ${e.phase}` }));
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
// -------------------------------------------------------------------------
|
|
561
|
+
// Processing-only events (normal message submission)
|
|
562
|
+
// -------------------------------------------------------------------------
|
|
563
|
+
if (mode === 'processing') {
|
|
564
|
+
if (event.type === 'plan.change.queued') {
|
|
565
|
+
const e = event;
|
|
566
|
+
const summary = e.summary ? `: ${e.summary}` : '';
|
|
567
|
+
const prefix = e.subagent ? `[${e.subagent} PLAN]` : '[PLAN]';
|
|
568
|
+
addMessage('system', `${prefix} Queued ${e.tool}${summary}`);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
if (event.type === 'plan.change.complete') {
|
|
572
|
+
const e = event;
|
|
573
|
+
if (e.error) {
|
|
574
|
+
addMessage('system', `[PLAN ${e.changeIndex + 1}] ${e.tool} FAILED: ${e.error}`);
|
|
575
|
+
}
|
|
576
|
+
else if (e.tool === 'spawn_agent' && e.result) {
|
|
577
|
+
const output = typeof e.result === 'object' && e.result !== null && 'output' in e.result
|
|
578
|
+
? String(e.result.output)
|
|
579
|
+
: String(e.result);
|
|
580
|
+
const preview = output.length > 800 ? output.slice(0, 800) + '\n... (truncated)' : output;
|
|
581
|
+
addMessage('system', `[PLAN ${e.changeIndex + 1}] ${e.tool} result:\n${preview}`);
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
addMessage('system', `[PLAN ${e.changeIndex + 1}] ${e.tool} completed`);
|
|
585
|
+
}
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (event.type === 'cache.hit' && showThinking) {
|
|
589
|
+
const e = event;
|
|
590
|
+
addMessage('system', `[CACHE HIT] similarity: ${(e.similarity * 100).toFixed(0)}%`);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
if (event.type === 'cache.miss' && showThinking) {
|
|
594
|
+
addMessage('system', `[CACHE MISS]`);
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
if (event.type === 'compaction.auto') {
|
|
598
|
+
const e = event;
|
|
599
|
+
const before = (e.tokensBefore / 1000).toFixed(1);
|
|
600
|
+
const after = (e.tokensAfter / 1000).toFixed(1);
|
|
601
|
+
addMessage('system', `[COMPACT] ${before}k -> ${after}k tokens (${e.messagesCompacted} messages)`);
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (event.type === 'compaction.warning' && showThinking) {
|
|
605
|
+
const e = event;
|
|
606
|
+
const pct = Math.round((e.currentTokens / e.threshold) * 100);
|
|
607
|
+
addMessage('system', `[!] Context at ${pct}% of threshold`);
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}, [addMessage, showThinking]);
|
|
403
612
|
// Set up transparency aggregator and subscribe to agent events
|
|
404
613
|
useEffect(() => {
|
|
405
614
|
const aggregator = new TransparencyAggregator();
|
|
@@ -411,12 +620,13 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
411
620
|
// Subscribe to agent events
|
|
412
621
|
const unsubscribeAgent = agent.subscribe((event) => {
|
|
413
622
|
aggregator.processEvent(event);
|
|
623
|
+
handleAgentEvent(event); // Unified event handler for TUI display
|
|
414
624
|
});
|
|
415
625
|
return () => {
|
|
416
626
|
unsubscribeAggregator();
|
|
417
627
|
unsubscribeAgent();
|
|
418
628
|
};
|
|
419
|
-
}, [agent]);
|
|
629
|
+
}, [agent, handleAgentEvent]);
|
|
420
630
|
// =========================================================================
|
|
421
631
|
// COMMAND HANDLER
|
|
422
632
|
// =========================================================================
|
|
@@ -809,16 +1019,32 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
809
1019
|
addMessage('system', 'No plan to approve.');
|
|
810
1020
|
return;
|
|
811
1021
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1022
|
+
// Set execution mode - unified event handler will display events
|
|
1023
|
+
setIsProcessing(true);
|
|
1024
|
+
executionModeRef.current = 'approving';
|
|
1025
|
+
setExecutionMode('approving');
|
|
1026
|
+
setStatus(s => ({ ...s, mode: 'executing plan' }));
|
|
1027
|
+
try {
|
|
1028
|
+
const count = args[0] ? parseInt(args[0], 10) : undefined;
|
|
1029
|
+
const result = await agent.approvePlan(count);
|
|
1030
|
+
if (result.success) {
|
|
1031
|
+
addMessage('system', `[OK] Executed ${result.executed} change(s)`);
|
|
1032
|
+
}
|
|
1033
|
+
else {
|
|
1034
|
+
addMessage('system', `[!] ${result.executed} done, ${result.errors.length} errors:\n${result.errors.join('\n')}`);
|
|
1035
|
+
}
|
|
816
1036
|
}
|
|
817
|
-
|
|
818
|
-
addMessage('
|
|
1037
|
+
catch (e) {
|
|
1038
|
+
addMessage('error', `Plan execution failed: ${e.message}`);
|
|
819
1039
|
}
|
|
820
|
-
|
|
821
|
-
|
|
1040
|
+
finally {
|
|
1041
|
+
executionModeRef.current = 'idle';
|
|
1042
|
+
setExecutionMode('idle');
|
|
1043
|
+
setIsProcessing(false);
|
|
1044
|
+
setToolCalls([]);
|
|
1045
|
+
if (agent.getMode() === 'plan') {
|
|
1046
|
+
agent.setMode('build');
|
|
1047
|
+
}
|
|
822
1048
|
setStatus(s => ({ ...s, mode: 'ready' }));
|
|
823
1049
|
}
|
|
824
1050
|
return;
|
|
@@ -1111,7 +1337,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1111
1337
|
default:
|
|
1112
1338
|
addMessage('system', `Unknown: /${cmd}. Try /help`);
|
|
1113
1339
|
}
|
|
1114
|
-
}, [addMessage, exit, agent, mcpClient, lspManager, sessionStore, compactor, model, currentThemeName, currentSessionId, formatSessionsTable, saveCheckpointToStore]);
|
|
1340
|
+
}, [addMessage, exit, agent, mcpClient, lspManager, sessionStore, compactor, model, currentThemeName, currentSessionId, formatSessionsTable, saveCheckpointToStore, showThinking]);
|
|
1115
1341
|
// =========================================================================
|
|
1116
1342
|
// SUBMIT HANDLER
|
|
1117
1343
|
// =========================================================================
|
|
@@ -1125,60 +1351,11 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1125
1351
|
await handleCommand(parts[0], parts.slice(1));
|
|
1126
1352
|
return;
|
|
1127
1353
|
}
|
|
1354
|
+
// Set execution mode - unified event handler will display events
|
|
1128
1355
|
setIsProcessing(true);
|
|
1356
|
+
executionModeRef.current = 'processing';
|
|
1357
|
+
setExecutionMode('processing');
|
|
1129
1358
|
setStatus(s => ({ ...s, mode: 'thinking' }));
|
|
1130
|
-
const unsub = agent.subscribe((event) => {
|
|
1131
|
-
// Check if event is from a subagent
|
|
1132
|
-
const subagentPrefix = event.subagent ? `[${event.subagent}] ` : '';
|
|
1133
|
-
if (event.type === 'agent.spawn') {
|
|
1134
|
-
// A subagent is starting
|
|
1135
|
-
addMessage('system', `[AGENT] Spawning ${event.name}: ${event.task.slice(0, 100)}${event.task.length > 100 ? '...' : ''}`);
|
|
1136
|
-
}
|
|
1137
|
-
else if (event.type === 'agent.complete') {
|
|
1138
|
-
// A subagent finished
|
|
1139
|
-
addMessage('system', `[AGENT] ${event.agentId} ${event.success ? 'completed' : 'failed'}`);
|
|
1140
|
-
}
|
|
1141
|
-
else if (event.type === 'tool.start') {
|
|
1142
|
-
const displayName = event.subagent ? `${event.subagent}:${event.tool}` : event.tool;
|
|
1143
|
-
setStatus(s => ({ ...s, mode: `calling ${displayName}` }));
|
|
1144
|
-
setToolCalls(prev => [...prev.slice(-4), {
|
|
1145
|
-
id: `${displayName}-${Date.now()}`,
|
|
1146
|
-
name: displayName,
|
|
1147
|
-
args: event.args || {},
|
|
1148
|
-
status: 'running',
|
|
1149
|
-
startTime: new Date(),
|
|
1150
|
-
}]);
|
|
1151
|
-
}
|
|
1152
|
-
else if (event.type === 'tool.complete') {
|
|
1153
|
-
const displayName = event.subagent ? `${event.subagent}:${event.tool}` : event.tool;
|
|
1154
|
-
setStatus(s => ({ ...s, mode: event.subagent ? `${event.subagent} thinking` : 'thinking' }));
|
|
1155
|
-
setToolCalls(prev => prev.map(t => t.name === displayName ? {
|
|
1156
|
-
...t,
|
|
1157
|
-
status: 'success',
|
|
1158
|
-
result: event.result,
|
|
1159
|
-
duration: t.startTime ? Date.now() - t.startTime.getTime() : undefined,
|
|
1160
|
-
} : t));
|
|
1161
|
-
}
|
|
1162
|
-
else if (event.type === 'tool.blocked') {
|
|
1163
|
-
const displayName = event.subagent ? `${event.subagent}:${event.tool}` : event.tool;
|
|
1164
|
-
setToolCalls(prev => prev.map(t => t.name === displayName ? {
|
|
1165
|
-
...t,
|
|
1166
|
-
status: 'error',
|
|
1167
|
-
error: event.reason || 'Blocked',
|
|
1168
|
-
} : t));
|
|
1169
|
-
}
|
|
1170
|
-
else if (event.type === 'llm.start') {
|
|
1171
|
-
setStatus(s => ({ ...s, mode: event.subagent ? `${event.subagent} thinking` : 'thinking', iter: s.iter + 1 }));
|
|
1172
|
-
}
|
|
1173
|
-
else if (event.type === 'insight.tokens' && showThinking) {
|
|
1174
|
-
const e = event;
|
|
1175
|
-
addMessage('system', `${subagentPrefix}* ${e.inputTokens.toLocaleString()} in, ${e.outputTokens.toLocaleString()} out${e.cost ? ` $${e.cost.toFixed(6)}` : ''}`);
|
|
1176
|
-
}
|
|
1177
|
-
else if (event.type === 'plan.change.queued') {
|
|
1178
|
-
const summary = event.summary ? `: ${event.summary}` : '';
|
|
1179
|
-
addMessage('system', `[PLAN] Queued ${event.tool}${summary}`);
|
|
1180
|
-
}
|
|
1181
|
-
});
|
|
1182
1359
|
try {
|
|
1183
1360
|
const result = await agent.run(trimmed);
|
|
1184
1361
|
const metrics = agent.getMetrics();
|
|
@@ -1231,11 +1408,12 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1231
1408
|
addMessage('error', e.message);
|
|
1232
1409
|
}
|
|
1233
1410
|
finally {
|
|
1234
|
-
|
|
1411
|
+
executionModeRef.current = 'idle';
|
|
1412
|
+
setExecutionMode('idle');
|
|
1235
1413
|
setIsProcessing(false);
|
|
1236
1414
|
setToolCalls([]);
|
|
1237
1415
|
}
|
|
1238
|
-
}, [addMessage, handleCommand, agent, sessionStore, saveCheckpointToStore, persistenceDebug
|
|
1416
|
+
}, [addMessage, handleCommand, agent, sessionStore, saveCheckpointToStore, persistenceDebug]);
|
|
1239
1417
|
// =========================================================================
|
|
1240
1418
|
// COMMAND PALETTE ITEMS
|
|
1241
1419
|
// =========================================================================
|