attocode 0.1.7 → 0.1.8
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 +13 -1
- package/dist/src/adapters.d.ts.map +1 -1
- package/dist/src/adapters.js +6 -0
- package/dist/src/adapters.js.map +1 -1
- package/dist/src/agent.d.ts +52 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +628 -82
- package/dist/src/agent.js.map +1 -1
- package/dist/src/commands/handler.d.ts.map +1 -1
- package/dist/src/commands/handler.js +6 -0
- package/dist/src/commands/handler.js.map +1 -1
- package/dist/src/defaults.d.ts +3 -1
- package/dist/src/defaults.d.ts.map +1 -1
- package/dist/src/defaults.js +9 -1
- package/dist/src/defaults.js.map +1 -1
- package/dist/src/integrations/agent-registry.d.ts +14 -0
- package/dist/src/integrations/agent-registry.d.ts.map +1 -1
- package/dist/src/integrations/agent-registry.js.map +1 -1
- package/dist/src/integrations/cancellation.d.ts +62 -0
- package/dist/src/integrations/cancellation.d.ts.map +1 -1
- package/dist/src/integrations/cancellation.js +174 -0
- package/dist/src/integrations/cancellation.js.map +1 -1
- package/dist/src/integrations/dead-letter-queue.js +1 -1
- package/dist/src/integrations/dead-letter-queue.js.map +1 -1
- package/dist/src/integrations/economics.d.ts +41 -0
- package/dist/src/integrations/economics.d.ts.map +1 -1
- package/dist/src/integrations/economics.js +114 -8
- package/dist/src/integrations/economics.js.map +1 -1
- package/dist/src/integrations/history.d.ts +72 -0
- package/dist/src/integrations/history.d.ts.map +1 -0
- package/dist/src/integrations/history.js +165 -0
- package/dist/src/integrations/history.js.map +1 -0
- package/dist/src/integrations/index.d.ts +4 -3
- package/dist/src/integrations/index.d.ts.map +1 -1
- package/dist/src/integrations/index.js +4 -2
- package/dist/src/integrations/index.js.map +1 -1
- package/dist/src/integrations/resources.d.ts +5 -0
- package/dist/src/integrations/resources.d.ts.map +1 -1
- package/dist/src/integrations/resources.js +7 -0
- package/dist/src/integrations/resources.js.map +1 -1
- package/dist/src/integrations/safety.d.ts +3 -1
- package/dist/src/integrations/safety.d.ts.map +1 -1
- package/dist/src/integrations/safety.js +22 -5
- package/dist/src/integrations/safety.js.map +1 -1
- package/dist/src/modes/tui.d.ts.map +1 -1
- package/dist/src/modes/tui.js +6 -0
- package/dist/src/modes/tui.js.map +1 -1
- package/dist/src/providers/adapters/openrouter.js +2 -2
- package/dist/src/providers/adapters/openrouter.js.map +1 -1
- package/dist/src/tools/agent.d.ts.map +1 -1
- package/dist/src/tools/agent.js +13 -1
- package/dist/src/tools/agent.js.map +1 -1
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +213 -103
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/components/DebugPanel.d.ts +41 -0
- package/dist/src/tui/components/DebugPanel.d.ts.map +1 -0
- package/dist/src/tui/components/DebugPanel.js +104 -0
- package/dist/src/tui/components/DebugPanel.js.map +1 -0
- package/dist/src/tui/components/ErrorDetailPanel.d.ts +49 -0
- package/dist/src/tui/components/ErrorDetailPanel.d.ts.map +1 -0
- package/dist/src/tui/components/ErrorDetailPanel.js +109 -0
- package/dist/src/tui/components/ErrorDetailPanel.js.map +1 -0
- package/dist/src/tui/components/ToolCallItem.d.ts +3 -4
- package/dist/src/tui/components/ToolCallItem.d.ts.map +1 -1
- package/dist/src/tui/components/ToolCallItem.js +51 -15
- package/dist/src/tui/components/ToolCallItem.js.map +1 -1
- package/dist/src/tui/components/index.d.ts +2 -0
- package/dist/src/tui/components/index.d.ts.map +1 -1
- package/dist/src/tui/components/index.js +4 -0
- package/dist/src/tui/components/index.js.map +1 -1
- package/dist/src/types.d.ts +77 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/src/tui/app.js
CHANGED
|
@@ -10,9 +10,10 @@ 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';
|
|
14
13
|
import { ActiveAgentsPanel } from './components/ActiveAgentsPanel.js';
|
|
15
14
|
import { TasksPanel } from './components/TasksPanel.js';
|
|
15
|
+
import { ToolCallItem } from './components/ToolCallItem.js';
|
|
16
|
+
import { DebugPanel, useDebugBuffer } from './components/DebugPanel.js';
|
|
16
17
|
import { getTheme, getThemeNames } from './theme/index.js';
|
|
17
18
|
import { ControlledCommandPalette } from './input/CommandPalette.js';
|
|
18
19
|
import { ApprovalDialog } from './components/ApprovalDialog.js';
|
|
@@ -20,6 +21,7 @@ import { TransparencyAggregator } from './transparency-aggregator.js';
|
|
|
20
21
|
import { handleSkillsCommand } from '../commands/skills-commands.js';
|
|
21
22
|
import { handleAgentsCommand } from '../commands/agents-commands.js';
|
|
22
23
|
import { handleInitCommand } from '../commands/init-commands.js';
|
|
24
|
+
import { createHistoryManager } from '../integrations/history.js';
|
|
23
25
|
// =============================================================================
|
|
24
26
|
// PATTERN GENERATION FOR ALWAYS-ALLOW
|
|
25
27
|
// =============================================================================
|
|
@@ -59,98 +61,34 @@ const MessageItem = memo(function MessageItem({ msg, colors }) {
|
|
|
59
61
|
const label = isUser ? 'You' : isAssistant ? 'Assistant' : isError ? 'Error' : 'System';
|
|
60
62
|
return (_jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: roleColor, bold: true, children: icon }), _jsx(Text, { color: roleColor, bold: true, children: label }), _jsx(Text, { color: colors.textMuted, dimColor: true, children: ` ${msg.ts.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })}` })] }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { wrap: "wrap", color: isError ? colors.error : colors.text, children: msg.content }) })] }));
|
|
61
63
|
});
|
|
62
|
-
const
|
|
63
|
-
const icon = tc.status === 'success' ? '[OK]' : tc.status === 'error' ? '[X]' : tc.status === 'running' ? '[~]' : '[ ]';
|
|
64
|
-
const statusColor = tc.status === 'success' ? '#98FB98' : tc.status === 'error' ? '#FF6B6B' : tc.status === 'running' ? '#87CEEB' : colors.textMuted;
|
|
65
|
-
// Compact formatting for collapsed view
|
|
66
|
-
const formatToolArgsCompact = (args) => {
|
|
67
|
-
const entries = Object.entries(args);
|
|
68
|
-
if (entries.length === 0)
|
|
69
|
-
return '';
|
|
70
|
-
if (entries.length === 1) {
|
|
71
|
-
const [key, val] = entries[0];
|
|
72
|
-
const valStr = typeof val === 'string' ? val : JSON.stringify(val);
|
|
73
|
-
return valStr.length > 50 ? `${key}: ${valStr.slice(0, 47)}...` : `${key}: ${valStr}`;
|
|
74
|
-
}
|
|
75
|
-
return `{${entries.length} args}`;
|
|
76
|
-
};
|
|
77
|
-
// Expanded formatting - each arg on its own line with proper handling
|
|
78
|
-
const formatToolArgsExpanded = (args) => {
|
|
79
|
-
const entries = Object.entries(args);
|
|
80
|
-
if (entries.length === 0)
|
|
81
|
-
return [];
|
|
82
|
-
return entries.map(([key, val]) => {
|
|
83
|
-
let valStr;
|
|
84
|
-
if (typeof val === 'string') {
|
|
85
|
-
// For strings, show with quotes, handle multiline
|
|
86
|
-
if (val.includes('\n')) {
|
|
87
|
-
const lines = val.split('\n');
|
|
88
|
-
if (lines.length > 3) {
|
|
89
|
-
valStr = `"${lines.slice(0, 3).join('\\n')}..." (${lines.length} lines)`;
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
valStr = `"${val.replace(/\n/g, '\\n')}"`;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
else if (val.length > 100) {
|
|
96
|
-
valStr = `"${val.slice(0, 97)}..."`;
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
valStr = `"${val}"`;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
else if (typeof val === 'object' && val !== null) {
|
|
103
|
-
const json = JSON.stringify(val, null, 2);
|
|
104
|
-
if (json.length > 200) {
|
|
105
|
-
valStr = JSON.stringify(val).slice(0, 197) + '...';
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
valStr = json;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
valStr = String(val);
|
|
113
|
-
}
|
|
114
|
-
return `${key}: ${valStr}`;
|
|
115
|
-
});
|
|
116
|
-
};
|
|
117
|
-
const argsStr = formatToolArgsCompact(tc.args);
|
|
118
|
-
if (expanded) {
|
|
119
|
-
const expandedArgs = formatToolArgsExpanded(tc.args);
|
|
120
|
-
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') &&
|
|
121
|
-
typeof tc.result === 'object' && tc.result !== null &&
|
|
122
|
-
'metadata' in tc.result &&
|
|
123
|
-
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}` }) }))] }));
|
|
124
|
-
}
|
|
125
|
-
// Check if result has diff metadata for collapsed summary
|
|
126
|
-
const hasDiff = tc.status === 'success' &&
|
|
127
|
-
(tc.name === 'edit_file' || tc.name === 'write_file') &&
|
|
128
|
-
typeof tc.result === 'object' && tc.result !== null &&
|
|
129
|
-
'metadata' in tc.result &&
|
|
130
|
-
typeof tc.result.metadata?.diff === 'string';
|
|
131
|
-
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] }));
|
|
132
|
-
});
|
|
133
|
-
const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled, borderColor, textColor, cursorColor, onCtrlC, onCtrlL, onCtrlP, onEscape, onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onPageUp, onPageDown, onHome, onEnd, commandPaletteOpen, onCommandPaletteInput, approvalDialogOpen, approvalDenyReasonMode, onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason, onApprovalCancelDenyReason, onApprovalDenyReasonInput, }) {
|
|
64
|
+
const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled, borderColor, textColor, cursorColor, onCtrlC, onCtrlL, onCtrlP, onEscape, onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onToggleDebug, onPageUp, onPageDown, onHome, onEnd, commandPaletteOpen, onCommandPaletteInput, approvalDialogOpen, approvalDenyReasonMode, onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason, onApprovalCancelDenyReason, onApprovalDenyReasonInput, history = [], onHistorySearch, }) {
|
|
134
65
|
const [value, setValue] = useState('');
|
|
135
66
|
const [cursorPos, setCursorPos] = useState(0);
|
|
67
|
+
// History navigation state
|
|
68
|
+
const [historyIndex, setHistoryIndex] = useState(-1); // -1 = current input (not browsing history)
|
|
69
|
+
const [savedInput, setSavedInput] = useState(''); // Preserve current input when browsing
|
|
70
|
+
const historyRef = useRef(history);
|
|
71
|
+
historyRef.current = history;
|
|
136
72
|
// Store callbacks in refs so useInput doesn't re-subscribe on prop changes
|
|
137
73
|
const callbacksRef = useRef({
|
|
138
74
|
onSubmit, onCtrlC, onCtrlL, onCtrlP, onEscape,
|
|
139
|
-
onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks,
|
|
75
|
+
onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onToggleDebug,
|
|
140
76
|
onPageUp, onPageDown, onHome, onEnd,
|
|
141
77
|
commandPaletteOpen, onCommandPaletteInput,
|
|
142
78
|
approvalDialogOpen, approvalDenyReasonMode,
|
|
143
79
|
onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason,
|
|
144
80
|
onApprovalCancelDenyReason, onApprovalDenyReasonInput,
|
|
81
|
+
onHistorySearch,
|
|
145
82
|
});
|
|
146
83
|
callbacksRef.current = {
|
|
147
84
|
onSubmit, onCtrlC, onCtrlL, onCtrlP, onEscape,
|
|
148
|
-
onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks,
|
|
85
|
+
onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onToggleDebug,
|
|
149
86
|
onPageUp, onPageDown, onHome, onEnd,
|
|
150
87
|
commandPaletteOpen, onCommandPaletteInput,
|
|
151
88
|
approvalDialogOpen, approvalDenyReasonMode,
|
|
152
89
|
onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason,
|
|
153
90
|
onApprovalCancelDenyReason, onApprovalDenyReasonInput,
|
|
91
|
+
onHistorySearch,
|
|
154
92
|
};
|
|
155
93
|
const disabledRef = useRef(disabled);
|
|
156
94
|
disabledRef.current = disabled;
|
|
@@ -198,6 +136,11 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
|
|
|
198
136
|
cb.onToggleTasks?.();
|
|
199
137
|
return;
|
|
200
138
|
}
|
|
139
|
+
// Alt+D / Option+D - Toggle debug panel
|
|
140
|
+
if (input === '\u2202' || (key.meta && input === 'd')) {
|
|
141
|
+
cb.onToggleDebug?.();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
201
144
|
// Command palette keyboard handling (when open)
|
|
202
145
|
if (cb.commandPaletteOpen && cb.onCommandPaletteInput) {
|
|
203
146
|
cb.onCommandPaletteInput(input, key);
|
|
@@ -261,10 +204,18 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
|
|
|
261
204
|
// Input handling (only when not disabled)
|
|
262
205
|
if (disabledRef.current)
|
|
263
206
|
return;
|
|
207
|
+
// Shift+Enter for multiline input (insert newline)
|
|
208
|
+
if (key.return && key.shift) {
|
|
209
|
+
setValue(v => v.slice(0, cursorPos) + '\n' + v.slice(cursorPos));
|
|
210
|
+
setCursorPos(p => p + 1);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
264
213
|
if (key.return && value.trim()) {
|
|
265
214
|
cb.onSubmit(value);
|
|
266
215
|
setValue('');
|
|
267
216
|
setCursorPos(0);
|
|
217
|
+
setHistoryIndex(-1); // Reset history navigation
|
|
218
|
+
setSavedInput('');
|
|
268
219
|
return;
|
|
269
220
|
}
|
|
270
221
|
if (key.backspace || key.delete) {
|
|
@@ -282,6 +233,54 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
|
|
|
282
233
|
setCursorPos(p => Math.min(value.length, p + 1));
|
|
283
234
|
return;
|
|
284
235
|
}
|
|
236
|
+
// History navigation with up/down arrows
|
|
237
|
+
if (key.upArrow && historyRef.current.length > 0) {
|
|
238
|
+
setHistoryIndex(prevIndex => {
|
|
239
|
+
const maxIndex = historyRef.current.length - 1;
|
|
240
|
+
if (prevIndex === -1) {
|
|
241
|
+
// First press - save current input and go to most recent history
|
|
242
|
+
setSavedInput(value);
|
|
243
|
+
const newValue = historyRef.current[maxIndex] || '';
|
|
244
|
+
setValue(newValue);
|
|
245
|
+
setCursorPos(newValue.length);
|
|
246
|
+
return maxIndex;
|
|
247
|
+
}
|
|
248
|
+
else if (prevIndex > 0) {
|
|
249
|
+
// Go to older entry
|
|
250
|
+
const newIndex = prevIndex - 1;
|
|
251
|
+
const newValue = historyRef.current[newIndex] || '';
|
|
252
|
+
setValue(newValue);
|
|
253
|
+
setCursorPos(newValue.length);
|
|
254
|
+
return newIndex;
|
|
255
|
+
}
|
|
256
|
+
return prevIndex; // Already at oldest
|
|
257
|
+
});
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (key.downArrow && historyRef.current.length > 0) {
|
|
261
|
+
setHistoryIndex(prevIndex => {
|
|
262
|
+
if (prevIndex === -1) {
|
|
263
|
+
// Not browsing history, do nothing
|
|
264
|
+
return -1;
|
|
265
|
+
}
|
|
266
|
+
else if (prevIndex < historyRef.current.length - 1) {
|
|
267
|
+
// Go to newer entry
|
|
268
|
+
const newIndex = prevIndex + 1;
|
|
269
|
+
const newValue = historyRef.current[newIndex] || '';
|
|
270
|
+
setValue(newValue);
|
|
271
|
+
setCursorPos(newValue.length);
|
|
272
|
+
return newIndex;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
// At most recent - restore saved input
|
|
276
|
+
setValue(savedInput);
|
|
277
|
+
setCursorPos(savedInput.length);
|
|
278
|
+
setSavedInput('');
|
|
279
|
+
return -1;
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
285
284
|
if (key.ctrl && input === 'a') {
|
|
286
285
|
setCursorPos(0);
|
|
287
286
|
return;
|
|
@@ -300,7 +299,10 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
|
|
|
300
299
|
setCursorPos(p => p + input.length);
|
|
301
300
|
}
|
|
302
301
|
});
|
|
303
|
-
|
|
302
|
+
// Check if multiline (for visual indicator)
|
|
303
|
+
const isMultiline = value.includes('\n');
|
|
304
|
+
const lineCount = value.split('\n').length;
|
|
305
|
+
return (_jsx(Box, { borderStyle: "round", borderColor: disabledRef.current ? '#666' : borderColor, paddingX: 1, flexDirection: "column", children: _jsxs(Box, { children: [_jsxs(Text, { color: textColor, bold: true, children: [isMultiline ? '»' : '>', " "] }), _jsx(Text, { children: value.slice(0, cursorPos).replace(/\n/g, '⏎') }), !disabled && (_jsx(Text, { backgroundColor: cursorColor, color: "#1a1a2e", children: value[cursorPos] === '\n' ? '⏎' : (value[cursorPos] ?? ' ') })), _jsx(Text, { children: value.slice(cursorPos + 1).replace(/\n/g, '⏎') }), isMultiline && (_jsxs(Text, { color: "#666", dimColor: true, children: [" (", lineCount, " lines)"] }))] }) }));
|
|
304
306
|
}, (prevProps, nextProps) => {
|
|
305
307
|
// Custom comparison: only re-render if visual props change
|
|
306
308
|
return prevProps.disabled === nextProps.disabled &&
|
|
@@ -326,6 +328,14 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
326
328
|
const [contextTokens, setContextTokens] = useState(0);
|
|
327
329
|
const [elapsedTime, setElapsedTime] = useState(0);
|
|
328
330
|
const processingStartRef = useRef(null);
|
|
331
|
+
// Command history manager (persistent)
|
|
332
|
+
const historyManagerRef = useRef(null);
|
|
333
|
+
if (!historyManagerRef.current) {
|
|
334
|
+
historyManagerRef.current = createHistoryManager();
|
|
335
|
+
}
|
|
336
|
+
const [historyEntries, setHistoryEntries] = useState(() => historyManagerRef.current?.getHistory() || []);
|
|
337
|
+
// Debug buffer for debug panel
|
|
338
|
+
const debugBuffer = useDebugBuffer(100);
|
|
329
339
|
const [executionMode, setExecutionMode] = useState('idle');
|
|
330
340
|
const executionModeRef = useRef('idle');
|
|
331
341
|
// Display toggles
|
|
@@ -334,6 +344,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
334
344
|
const [transparencyExpanded, setTransparencyExpanded] = useState(false);
|
|
335
345
|
const [activeAgentsExpanded, setActiveAgentsExpanded] = useState(true);
|
|
336
346
|
const [tasksExpanded, setTasksExpanded] = useState(true);
|
|
347
|
+
const [debugExpanded, setDebugExpanded] = useState(false);
|
|
337
348
|
// Active agents tracking (for Active Agents Panel)
|
|
338
349
|
const [activeAgents, setActiveAgents] = useState([]);
|
|
339
350
|
// Tasks tracking (for Tasks Panel)
|
|
@@ -351,6 +362,9 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
351
362
|
// Transparency state
|
|
352
363
|
const [transparencyState, setTransparencyState] = useState(null);
|
|
353
364
|
const transparencyAggregatorRef = useRef(null);
|
|
365
|
+
// Consecutive Ctrl+C tracking for force exit
|
|
366
|
+
const [ctrlCCount, setCtrlCCount] = useState(0);
|
|
367
|
+
const ctrlCTimerRef = useRef(null);
|
|
354
368
|
// Refs for stable callbacks
|
|
355
369
|
const isProcessingRef = useRef(isProcessing);
|
|
356
370
|
const messagesLengthRef = useRef(messages.length);
|
|
@@ -366,6 +380,22 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
366
380
|
const uniqueId = `${role}-${Date.now()}-${++messageIdCounter.current}`;
|
|
367
381
|
setMessages(prev => [...prev, { id: uniqueId, role, content, ts: new Date() }]);
|
|
368
382
|
}, []);
|
|
383
|
+
const persistPendingPlanToStore = useCallback(() => {
|
|
384
|
+
if (!agent.hasPendingPlan())
|
|
385
|
+
return;
|
|
386
|
+
if (!('savePendingPlan' in sessionStore) || typeof sessionStore.savePendingPlan !== 'function') {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const pendingPlan = agent.getPendingPlan();
|
|
390
|
+
if (!pendingPlan)
|
|
391
|
+
return;
|
|
392
|
+
sessionStore.savePendingPlan(pendingPlan, currentSessionId);
|
|
393
|
+
persistenceDebug.log('Pending plan saved', {
|
|
394
|
+
planId: pendingPlan.id,
|
|
395
|
+
changes: pendingPlan.proposedChanges.length,
|
|
396
|
+
sessionId: currentSessionId,
|
|
397
|
+
});
|
|
398
|
+
}, [agent, sessionStore, currentSessionId, persistenceDebug]);
|
|
369
399
|
// =========================================================================
|
|
370
400
|
// APPROVAL DIALOG HANDLERS
|
|
371
401
|
// =========================================================================
|
|
@@ -438,6 +468,10 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
438
468
|
const mode = executionModeRef.current;
|
|
439
469
|
if (mode === 'idle')
|
|
440
470
|
return; // No active execution, ignore events
|
|
471
|
+
// Log event to debug buffer
|
|
472
|
+
if (debugExpanded) {
|
|
473
|
+
debugBuffer.debug(`Event: ${event.type}`, event);
|
|
474
|
+
}
|
|
441
475
|
// Extract subagent from event if present (not all events have it)
|
|
442
476
|
const eventWithSubagent = event;
|
|
443
477
|
const subagentPrefix = eventWithSubagent.subagent ? `[${eventWithSubagent.subagent}] ` : '';
|
|
@@ -478,41 +512,44 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
478
512
|
if (event.type === 'agent.complete') {
|
|
479
513
|
const e = event;
|
|
480
514
|
const statusText = e.success ? 'completed' : 'failed';
|
|
481
|
-
|
|
482
|
-
|
|
515
|
+
const displayName = e.agentType || e.agentId;
|
|
516
|
+
addMessage('system', `[AGENT] ${displayName} ${statusText}`);
|
|
517
|
+
// Show output preview if substantive (increased from 300 to 1000 chars)
|
|
483
518
|
if (e.output && e.output.length > 50) {
|
|
484
|
-
const preview = e.output.slice(0,
|
|
485
|
-
|
|
519
|
+
const preview = e.output.slice(0, 1000);
|
|
520
|
+
const truncated = e.output.length > 1000;
|
|
521
|
+
addMessage('system', `[AGENT OUTPUT]\n${preview}${truncated ? `\n...(full output: ${e.output.length} chars)` : ''}`);
|
|
486
522
|
}
|
|
487
|
-
// Update active agents panel
|
|
488
|
-
setActiveAgents(prev => prev.map(a => a.
|
|
523
|
+
// Update active agents panel - use strict ID matching
|
|
524
|
+
setActiveAgents(prev => prev.map(a => a.id === e.agentId
|
|
489
525
|
? { ...a, status: e.success ? 'completed' : 'error' }
|
|
490
526
|
: a));
|
|
491
527
|
return;
|
|
492
528
|
}
|
|
493
529
|
if (event.type === 'agent.error') {
|
|
494
530
|
const e = event;
|
|
495
|
-
|
|
531
|
+
const displayName = e.agentType || e.agentId;
|
|
532
|
+
addMessage('system', `[AGENT] ${displayName} error: ${e.error}`);
|
|
496
533
|
// For timeout errors, use 'timing_out' status first to indicate the agent
|
|
497
534
|
// is in the process of stopping. Then transition to 'timeout' after a delay.
|
|
498
535
|
// This provides better UX than immediately showing "failed" while tokens accumulate.
|
|
499
536
|
const isTimeout = e.error.includes('timed out') || e.error.includes('Timed out');
|
|
500
537
|
if (isTimeout) {
|
|
501
|
-
// First, mark as timing_out
|
|
502
|
-
setActiveAgents(prev => prev.map(a => a.
|
|
538
|
+
// First, mark as timing_out - use strict ID matching
|
|
539
|
+
setActiveAgents(prev => prev.map(a => a.id === e.agentId
|
|
503
540
|
? { ...a, status: 'timing_out' }
|
|
504
541
|
: a));
|
|
505
542
|
// After 3 seconds, transition to final timeout status
|
|
506
543
|
// (agent should have stopped by then due to cancellation token check)
|
|
507
544
|
setTimeout(() => {
|
|
508
|
-
setActiveAgents(prev => prev.map(a =>
|
|
545
|
+
setActiveAgents(prev => prev.map(a => a.id === e.agentId && a.status === 'timing_out'
|
|
509
546
|
? { ...a, status: 'timeout' }
|
|
510
547
|
: a));
|
|
511
548
|
}, 3000);
|
|
512
549
|
}
|
|
513
550
|
else {
|
|
514
|
-
// Regular error - set immediately
|
|
515
|
-
setActiveAgents(prev => prev.map(a => a.
|
|
551
|
+
// Regular error - set immediately with strict ID matching
|
|
552
|
+
setActiveAgents(prev => prev.map(a => a.id === e.agentId
|
|
516
553
|
? { ...a, status: 'error' }
|
|
517
554
|
: a));
|
|
518
555
|
}
|
|
@@ -595,9 +632,14 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
595
632
|
// These agents should have stopped, and any lingering events are from
|
|
596
633
|
// zombie processes that we don't want to count.
|
|
597
634
|
if (e.subagent || eventWithSubagent.subagent) {
|
|
635
|
+
const subagentId = e.subagentId || eventWithSubagent.subagentId;
|
|
598
636
|
const agentName = e.subagent || eventWithSubagent.subagent;
|
|
599
637
|
setActiveAgents(prev => prev.map(a => {
|
|
600
|
-
|
|
638
|
+
// Use strict ID matching when subagentId is available (prevents duplicate counting
|
|
639
|
+
// when multiple agents of the same type run in parallel)
|
|
640
|
+
const matchesAgent = subagentId
|
|
641
|
+
? a.id === subagentId
|
|
642
|
+
: (a.type === agentName || a.id.includes(agentName || ''));
|
|
601
643
|
const isStillRunning = a.status === 'running';
|
|
602
644
|
// Only update tokens if agent is still running
|
|
603
645
|
if (matchesAgent && isStillRunning) {
|
|
@@ -624,18 +666,26 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
624
666
|
const e = event;
|
|
625
667
|
setStatus(s => ({ ...s, mode: `${e.agentId} iter ${e.iteration}/${e.maxIterations}` }));
|
|
626
668
|
// Update active agents panel with iteration info
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
669
|
+
// Use subagentId for strict matching when available (parallel same-type agents)
|
|
670
|
+
setActiveAgents(prev => prev.map(a => {
|
|
671
|
+
const matches = e.subagentId
|
|
672
|
+
? a.id === e.subagentId
|
|
673
|
+
: (a.type === e.agentId || a.id.includes(e.agentId));
|
|
674
|
+
return matches ? { ...a, iteration: e.iteration, maxIterations: e.maxIterations } : a;
|
|
675
|
+
}));
|
|
630
676
|
return;
|
|
631
677
|
}
|
|
632
678
|
if (event.type === 'subagent.phase') {
|
|
633
679
|
const e = event;
|
|
634
680
|
setStatus(s => ({ ...s, mode: `${e.agentId} ${e.phase}` }));
|
|
635
681
|
// Update active agents panel with phase info
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
682
|
+
// Use subagentId for strict matching when available (parallel same-type agents)
|
|
683
|
+
setActiveAgents(prev => prev.map(a => {
|
|
684
|
+
const matches = e.subagentId
|
|
685
|
+
? a.id === e.subagentId
|
|
686
|
+
: (a.type === e.agentId || a.id.includes(e.agentId));
|
|
687
|
+
return matches ? { ...a, currentPhase: e.phase } : a;
|
|
688
|
+
}));
|
|
639
689
|
return;
|
|
640
690
|
}
|
|
641
691
|
// Task events - update Tasks Panel
|
|
@@ -825,6 +875,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
825
875
|
' Alt+O Toggle thinking',
|
|
826
876
|
' Alt+I Toggle transparency panel',
|
|
827
877
|
' Alt+K Toggle tasks panel',
|
|
878
|
+
' Alt+D Toggle debug panel',
|
|
828
879
|
'========================',
|
|
829
880
|
].join('\n'));
|
|
830
881
|
return;
|
|
@@ -848,6 +899,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
848
899
|
plan: agentState.plan,
|
|
849
900
|
memoryContext: agentState.memoryContext,
|
|
850
901
|
});
|
|
902
|
+
persistPendingPlanToStore();
|
|
851
903
|
addMessage('system', `Session saved: ${currentSessionId} (checkpoint: ${ckptId})`);
|
|
852
904
|
}
|
|
853
905
|
catch (e) {
|
|
@@ -1559,7 +1611,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1559
1611
|
default:
|
|
1560
1612
|
addMessage('system', `Unknown: /${cmd}. Try /help`);
|
|
1561
1613
|
}
|
|
1562
|
-
}, [addMessage, exit, agent, mcpClient, lspManager, sessionStore, compactor, model, currentThemeName, currentSessionId, formatSessionsTable, saveCheckpointToStore, showThinking]);
|
|
1614
|
+
}, [addMessage, exit, agent, mcpClient, lspManager, sessionStore, compactor, model, currentThemeName, currentSessionId, formatSessionsTable, saveCheckpointToStore, showThinking, persistPendingPlanToStore]);
|
|
1563
1615
|
// =========================================================================
|
|
1564
1616
|
// SUBMIT HANDLER
|
|
1565
1617
|
// =========================================================================
|
|
@@ -1567,6 +1619,11 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1567
1619
|
const trimmed = input.trim();
|
|
1568
1620
|
if (!trimmed)
|
|
1569
1621
|
return;
|
|
1622
|
+
// Add to history (persistent)
|
|
1623
|
+
if (historyManagerRef.current) {
|
|
1624
|
+
historyManagerRef.current.addEntry(trimmed);
|
|
1625
|
+
setHistoryEntries(historyManagerRef.current.getHistory());
|
|
1626
|
+
}
|
|
1570
1627
|
addMessage('user', trimmed);
|
|
1571
1628
|
if (trimmed.startsWith('/')) {
|
|
1572
1629
|
const parts = trimmed.slice(1).split(/\s+/);
|
|
@@ -1578,6 +1635,8 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1578
1635
|
executionModeRef.current = 'processing';
|
|
1579
1636
|
setExecutionMode('processing');
|
|
1580
1637
|
setStatus(s => ({ ...s, mode: 'thinking' }));
|
|
1638
|
+
// Reset CPU time counter for per-prompt resource limits (prevents session-wide timeout)
|
|
1639
|
+
agent.resetResourceTimer();
|
|
1581
1640
|
try {
|
|
1582
1641
|
const result = await agent.run(trimmed);
|
|
1583
1642
|
const metrics = agent.getMetrics();
|
|
@@ -1620,6 +1679,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1620
1679
|
plan: checkpoint.state.plan,
|
|
1621
1680
|
memoryContext: checkpoint.state.memoryContext,
|
|
1622
1681
|
});
|
|
1682
|
+
persistPendingPlanToStore();
|
|
1623
1683
|
}
|
|
1624
1684
|
catch (e) {
|
|
1625
1685
|
persistenceDebug.error('[TUI] Checkpoint failed', e);
|
|
@@ -1635,7 +1695,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1635
1695
|
setIsProcessing(false);
|
|
1636
1696
|
setToolCalls([]);
|
|
1637
1697
|
}
|
|
1638
|
-
}, [addMessage, handleCommand, agent, sessionStore, saveCheckpointToStore, persistenceDebug]);
|
|
1698
|
+
}, [addMessage, handleCommand, agent, sessionStore, saveCheckpointToStore, persistenceDebug, persistPendingPlanToStore]);
|
|
1639
1699
|
// =========================================================================
|
|
1640
1700
|
// COMMAND PALETTE ITEMS
|
|
1641
1701
|
// =========================================================================
|
|
@@ -1729,8 +1789,33 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1729
1789
|
// KEYBOARD CALLBACKS
|
|
1730
1790
|
// =========================================================================
|
|
1731
1791
|
const handleCtrlC = useCallback(() => {
|
|
1732
|
-
|
|
1733
|
-
|
|
1792
|
+
// Clear any existing timer
|
|
1793
|
+
if (ctrlCTimerRef.current) {
|
|
1794
|
+
clearTimeout(ctrlCTimerRef.current);
|
|
1795
|
+
ctrlCTimerRef.current = null;
|
|
1796
|
+
}
|
|
1797
|
+
setCtrlCCount(prevCount => {
|
|
1798
|
+
const newCount = prevCount + 1;
|
|
1799
|
+
if (newCount >= 2) {
|
|
1800
|
+
// Second Ctrl+C within timeout window - force exit immediately
|
|
1801
|
+
process.exit(1);
|
|
1802
|
+
}
|
|
1803
|
+
// First Ctrl+C - show warning and start graceful cleanup
|
|
1804
|
+
addMessage('system', '[CTRL+C] Press again within 1s to force exit...');
|
|
1805
|
+
// Start graceful cleanup in background
|
|
1806
|
+
agent.cleanup()
|
|
1807
|
+
.then(() => mcpClient.cleanup())
|
|
1808
|
+
.then(() => lspManager.cleanup())
|
|
1809
|
+
.then(() => exit())
|
|
1810
|
+
.catch(() => exit()); // Exit even if cleanup fails
|
|
1811
|
+
// Reset counter after 1 second
|
|
1812
|
+
ctrlCTimerRef.current = setTimeout(() => {
|
|
1813
|
+
setCtrlCCount(0);
|
|
1814
|
+
ctrlCTimerRef.current = null;
|
|
1815
|
+
}, 1000);
|
|
1816
|
+
return newCount;
|
|
1817
|
+
});
|
|
1818
|
+
}, [agent, mcpClient, lspManager, exit, addMessage]);
|
|
1734
1819
|
const handleCtrlL = useCallback(() => {
|
|
1735
1820
|
setMessages([]);
|
|
1736
1821
|
setToolCalls([]);
|
|
@@ -1740,7 +1825,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1740
1825
|
setCommandPaletteQuery('');
|
|
1741
1826
|
setCommandPaletteIndex(0);
|
|
1742
1827
|
}, []);
|
|
1743
|
-
const handleEscape = useCallback(() => {
|
|
1828
|
+
const handleEscape = useCallback(async () => {
|
|
1744
1829
|
// Close command palette first if open
|
|
1745
1830
|
if (commandPaletteOpen) {
|
|
1746
1831
|
setCommandPaletteOpen(false);
|
|
@@ -1750,11 +1835,30 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1750
1835
|
}
|
|
1751
1836
|
// Otherwise cancel processing
|
|
1752
1837
|
if (isProcessingRef.current) {
|
|
1838
|
+
// Immediate visual feedback
|
|
1839
|
+
addMessage('system', '[ESC] Stopping agent...');
|
|
1840
|
+
// Autosave checkpoint before cancel (async, don't block)
|
|
1841
|
+
try {
|
|
1842
|
+
const agentState = agent.getState();
|
|
1843
|
+
saveCheckpointToStore(sessionStore, {
|
|
1844
|
+
sessionId: currentSessionId,
|
|
1845
|
+
reason: 'user_cancel',
|
|
1846
|
+
messages: agentState.messages,
|
|
1847
|
+
iteration: agentState.iteration,
|
|
1848
|
+
timestamp: Date.now(),
|
|
1849
|
+
});
|
|
1850
|
+
persistPendingPlanToStore();
|
|
1851
|
+
persistenceDebug.log('Checkpoint saved before cancel');
|
|
1852
|
+
}
|
|
1853
|
+
catch (e) {
|
|
1854
|
+
persistenceDebug.error('Failed to save checkpoint before cancel', e);
|
|
1855
|
+
}
|
|
1856
|
+
// Cancel the agent
|
|
1753
1857
|
agent.cancel('Cancelled by ESC');
|
|
1754
1858
|
setIsProcessing(false);
|
|
1755
|
-
addMessage('system', '[STOP] Cancelled');
|
|
1859
|
+
addMessage('system', '[STOP] Cancelled (checkpoint saved)');
|
|
1756
1860
|
}
|
|
1757
|
-
}, [agent, addMessage, commandPaletteOpen]);
|
|
1861
|
+
}, [agent, addMessage, commandPaletteOpen, sessionStore, currentSessionId, saveCheckpointToStore, persistenceDebug, persistPendingPlanToStore]);
|
|
1758
1862
|
const handleToggleToolExpand = useCallback(() => {
|
|
1759
1863
|
setToolCallsExpanded(prev => {
|
|
1760
1864
|
addMessage('system', !prev ? '[*] Tool details: expanded' : '[ ] Tool details: collapsed');
|
|
@@ -1785,6 +1889,12 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1785
1889
|
return !prev;
|
|
1786
1890
|
});
|
|
1787
1891
|
}, [addMessage]);
|
|
1892
|
+
const handleToggleDebug = useCallback(() => {
|
|
1893
|
+
setDebugExpanded(prev => {
|
|
1894
|
+
addMessage('system', !prev ? '[v] Debug panel: visible (Alt+D)' : '[^] Debug panel: hidden');
|
|
1895
|
+
return !prev;
|
|
1896
|
+
});
|
|
1897
|
+
}, [addMessage]);
|
|
1788
1898
|
// Update context tokens
|
|
1789
1899
|
useEffect(() => {
|
|
1790
1900
|
const agentState = agent.getState();
|
|
@@ -1826,7 +1936,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
|
|
|
1826
1936
|
args: pendingApproval.args || {},
|
|
1827
1937
|
risk: pendingApproval.risk,
|
|
1828
1938
|
context: pendingApproval.context,
|
|
1829
|
-
}, onApprove: handleApprove, onDeny: handleDeny, colors: colors, denyReasonMode: denyReasonMode, denyReason: denyReason })), _jsx(TasksPanel, { tasks: tasks, colors: colors, expanded: tasksExpanded }), _jsx(ActiveAgentsPanel, { agents: activeAgents, colors: colors, expanded: activeAgentsExpanded }), _jsx(MemoizedInputArea, { onSubmit: handleSubmit, disabled: isProcessing || !!pendingApproval, borderColor: pendingApproval ? '#FFD700' : '#87CEEB', textColor: "#98FB98", cursorColor: "#87CEEB", onCtrlC: handleCtrlC, onCtrlL: handleCtrlL, onCtrlP: handleCtrlP, onEscape: handleEscape, onToggleToolExpand: handleToggleToolExpand, onToggleThinking: handleToggleThinking, onToggleTransparency: handleToggleTransparency, onToggleActiveAgents: handleToggleActiveAgents, onToggleTasks: handleToggleTasks, commandPaletteOpen: commandPaletteOpen, onCommandPaletteInput: handleCommandPaletteInput, approvalDialogOpen: !!pendingApproval, approvalDenyReasonMode: denyReasonMode, onApprovalApprove: handleApprove, onApprovalAlwaysAllow: handleAlwaysAllow, onApprovalDeny: handleDeny, onApprovalDenyWithReason: handleDenyWithReason, onApprovalCancelDenyReason: handleCancelDenyReason, onApprovalDenyReasonInput: handleApprovalDenyReasonInput }), commandPaletteOpen && (_jsx(ControlledCommandPalette, { theme: selectedTheme, items: filteredCommandItems, visible: commandPaletteOpen, query: commandPaletteQuery, selectedIndex: commandPaletteIndex, onQueryChange: setCommandPaletteQuery, onSelectItem: (item) => {
|
|
1939
|
+
}, onApprove: handleApprove, onDeny: handleDeny, colors: colors, denyReasonMode: denyReasonMode, denyReason: denyReason })), _jsx(DebugPanel, { entries: debugBuffer.entries, expanded: debugExpanded, colors: colors }), _jsx(TasksPanel, { tasks: tasks, colors: colors, expanded: tasksExpanded }), _jsx(ActiveAgentsPanel, { agents: activeAgents, colors: colors, expanded: activeAgentsExpanded }), _jsx(MemoizedInputArea, { onSubmit: handleSubmit, disabled: isProcessing || !!pendingApproval, borderColor: pendingApproval ? '#FFD700' : '#87CEEB', textColor: "#98FB98", cursorColor: "#87CEEB", onCtrlC: handleCtrlC, onCtrlL: handleCtrlL, onCtrlP: handleCtrlP, onEscape: handleEscape, onToggleToolExpand: handleToggleToolExpand, onToggleThinking: handleToggleThinking, onToggleTransparency: handleToggleTransparency, onToggleActiveAgents: handleToggleActiveAgents, onToggleTasks: handleToggleTasks, onToggleDebug: handleToggleDebug, commandPaletteOpen: commandPaletteOpen, onCommandPaletteInput: handleCommandPaletteInput, approvalDialogOpen: !!pendingApproval, approvalDenyReasonMode: denyReasonMode, onApprovalApprove: handleApprove, onApprovalAlwaysAllow: handleAlwaysAllow, onApprovalDeny: handleDeny, onApprovalDenyWithReason: handleDenyWithReason, onApprovalCancelDenyReason: handleCancelDenyReason, onApprovalDenyReasonInput: handleApprovalDenyReasonInput, history: historyEntries }), commandPaletteOpen && (_jsx(ControlledCommandPalette, { theme: selectedTheme, items: filteredCommandItems, visible: commandPaletteOpen, query: commandPaletteQuery, selectedIndex: commandPaletteIndex, onQueryChange: setCommandPaletteQuery, onSelectItem: (item) => {
|
|
1830
1940
|
setCommandPaletteOpen(false);
|
|
1831
1941
|
setCommandPaletteQuery('');
|
|
1832
1942
|
setCommandPaletteIndex(0);
|