dexto 1.5.8 → 1.6.1
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/README.md +3 -3
- package/dist/agents/agent-template.yml +2 -2
- package/dist/agents/coding-agent/README.md +10 -10
- package/dist/agents/coding-agent/coding-agent.yml +84 -83
- package/dist/agents/default-agent.yml +32 -47
- package/dist/agents/explore-agent/explore-agent.yml +3 -6
- package/dist/agents/image-editor-agent/image-editor-agent.yml +1 -1
- package/dist/agents/nano-banana-agent/nano-banana-agent.yml +1 -1
- package/dist/agents/podcast-agent/podcast-agent.yml +1 -1
- package/dist/agents/product-name-researcher/product-name-researcher.yml +1 -1
- package/dist/agents/sora-video-agent/sora-video-agent.yml +4 -6
- package/dist/agents/triage-demo/triage-agent.yml +1 -1
- package/dist/analytics/events.d.ts +1 -1
- package/dist/analytics/events.d.ts.map +1 -1
- package/dist/api/mcp/tool-aggregation-handler.d.ts +2 -2
- package/dist/api/server-hono.d.ts +2 -2
- package/dist/api/server-hono.d.ts.map +1 -1
- package/dist/api/server-hono.js +37 -60
- package/dist/cli/approval/cli-approval-handler.d.ts +10 -3
- package/dist/cli/approval/cli-approval-handler.d.ts.map +1 -1
- package/dist/cli/approval/cli-approval-handler.js +1 -1
- package/dist/cli/assets/sounds/SOURCES.md +35 -0
- package/dist/cli/assets/sounds/boot.wav +0 -0
- package/dist/cli/assets/sounds/chime.wav +0 -0
- package/dist/cli/assets/sounds/coin.wav +0 -0
- package/dist/cli/assets/sounds/confirm.wav +0 -0
- package/dist/cli/assets/sounds/levelup.wav +0 -0
- package/dist/cli/assets/sounds/ping.wav +0 -0
- package/dist/cli/assets/sounds/powerup.wav +0 -0
- package/dist/cli/assets/sounds/startup.wav +0 -0
- package/dist/cli/assets/sounds/success.wav +0 -0
- package/dist/cli/assets/sounds/treasure.wav +0 -0
- package/dist/cli/assets/sounds/win.wav +0 -0
- package/dist/cli/commands/create-app.d.ts +1 -11
- package/dist/cli/commands/create-app.d.ts.map +1 -1
- package/dist/cli/commands/create-app.js +21 -545
- package/dist/cli/commands/create-image.d.ts.map +1 -1
- package/dist/cli/commands/create-image.js +54 -53
- package/dist/cli/commands/image.d.ts +52 -0
- package/dist/cli/commands/image.d.ts.map +1 -0
- package/dist/cli/commands/image.js +118 -0
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +3 -1
- package/dist/cli/commands/init-app.d.ts +4 -8
- package/dist/cli/commands/init-app.d.ts.map +1 -1
- package/dist/cli/commands/init-app.js +37 -161
- package/dist/cli/commands/interactive-commands/command-parser.d.ts +2 -0
- package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/commands.d.ts +1 -1
- package/dist/cli/commands/interactive-commands/commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/commands.js +2 -2
- package/dist/cli/commands/interactive-commands/exit-handler.d.ts +12 -0
- package/dist/cli/commands/interactive-commands/exit-handler.d.ts.map +1 -0
- package/dist/cli/commands/interactive-commands/exit-handler.js +20 -0
- package/dist/cli/commands/interactive-commands/exit-stats.d.ts +24 -0
- package/dist/cli/commands/interactive-commands/exit-stats.d.ts.map +1 -0
- package/dist/cli/commands/interactive-commands/exit-stats.js +17 -0
- package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/general-commands.js +55 -5
- package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/prompt-commands.js +14 -74
- package/dist/cli/commands/interactive-commands/session/index.d.ts +2 -1
- package/dist/cli/commands/interactive-commands/session/index.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/index.js +2 -1
- package/dist/cli/commands/interactive-commands/session/session-commands.d.ts +2 -2
- package/dist/cli/commands/interactive-commands/session/session-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/session-commands.js +2 -4
- package/dist/cli/commands/interactive-commands/system/system-commands.d.ts +1 -13
- package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/system/system-commands.js +52 -83
- package/dist/cli/commands/plugin.d.ts +4 -4
- package/dist/cli/commands/sync-agents.d.ts +2 -12
- package/dist/cli/commands/sync-agents.d.ts.map +1 -1
- package/dist/cli/commands/sync-agents.js +2 -50
- package/dist/cli/ink-cli/InkCLIRefactored.d.ts +7 -1
- package/dist/cli/ink-cli/InkCLIRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/InkCLIRefactored.js +138 -27
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts +2 -2
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ApprovalPrompt.js +85 -30
- package/dist/cli/ink-cli/components/BackgroundTasksPanel.js +1 -1
- package/dist/cli/ink-cli/components/ElicitationForm.d.ts +5 -3
- package/dist/cli/ink-cli/components/ElicitationForm.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ElicitationForm.js +414 -180
- package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/Footer.js +1 -2
- package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ResourceAutocomplete.js +20 -11
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.js +47 -67
- package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/StatusBar.js +20 -10
- package/dist/cli/ink-cli/components/TodoPanel.js +1 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.d.ts +2 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.js +37 -27
- package/dist/cli/ink-cli/components/chat/Header.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/Header.js +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.js +3 -1
- package/dist/cli/ink-cli/components/chat/ToolIcon.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/ToolIcon.js +5 -15
- package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.js +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +1 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts +3 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +5 -3
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts +3 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.js +10 -3
- package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts +13 -0
- package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.js +60 -0
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +213 -100
- package/dist/cli/ink-cli/components/overlays/PromptList.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/PromptList.js +12 -16
- package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts +21 -0
- package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/SoundsSelector.js +566 -0
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts +1 -1
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.js +100 -45
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.js +8 -13
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts +3 -3
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.js +6 -5
- package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts +3 -1
- package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/FileRenderer.js +18 -7
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.js +7 -17
- package/dist/cli/ink-cli/components/renderers/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/index.js +1 -1
- package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts +7 -0
- package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.js +8 -0
- package/dist/cli/ink-cli/components/shared/HintBar.d.ts +6 -0
- package/dist/cli/ink-cli/components/shared/HintBar.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/shared/HintBar.js +6 -0
- package/dist/cli/ink-cli/constants/spinnerFrames.d.ts +2 -0
- package/dist/cli/ink-cli/constants/spinnerFrames.d.ts.map +1 -0
- package/dist/cli/ink-cli/constants/spinnerFrames.js +1 -0
- package/dist/cli/ink-cli/constants/tips.d.ts.map +1 -1
- package/dist/cli/ink-cli/constants/tips.js +2 -1
- package/dist/cli/ink-cli/containers/InputContainer.d.ts +4 -0
- package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/InputContainer.js +47 -21
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts +2 -0
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/OverlayContainer.js +101 -40
- package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useAgentEvents.js +15 -16
- package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts +11 -0
- package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useAnimationTick.js +54 -0
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useCLIState.js +1 -0
- package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useTokenCounter.js +7 -4
- package/dist/cli/ink-cli/services/CommandService.d.ts +1 -1
- package/dist/cli/ink-cli/services/CommandService.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/CommandService.js +2 -2
- package/dist/cli/ink-cli/services/processStream.d.ts +2 -2
- package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/processStream.js +27 -19
- package/dist/cli/ink-cli/state/initialState.d.ts.map +1 -1
- package/dist/cli/ink-cli/state/initialState.js +1 -0
- package/dist/cli/ink-cli/state/types.d.ts +15 -3
- package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/commandOverlays.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/commandOverlays.js +1 -0
- package/dist/cli/ink-cli/utils/elicitationSchema.d.ts +11 -0
- package/dist/cli/ink-cli/utils/elicitationSchema.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/elicitationSchema.js +80 -0
- package/dist/cli/ink-cli/utils/index.d.ts +1 -1
- package/dist/cli/ink-cli/utils/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/index.js +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts +10 -19
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.js +43 -262
- package/dist/cli/ink-cli/utils/overlayPresentation.d.ts +19 -0
- package/dist/cli/ink-cli/utils/overlayPresentation.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/overlayPresentation.js +33 -0
- package/dist/cli/ink-cli/utils/overlaySizing.d.ts +19 -0
- package/dist/cli/ink-cli/utils/overlaySizing.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/overlaySizing.js +11 -0
- package/dist/cli/ink-cli/utils/soundNotification.d.ts +19 -13
- package/dist/cli/ink-cli/utils/soundNotification.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/soundNotification.js +120 -97
- package/dist/cli/ink-cli/utils/toolUtils.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/toolUtils.js +2 -9
- package/dist/cli/utils/config-validation.d.ts +11 -11
- package/dist/cli/utils/config-validation.d.ts.map +1 -1
- package/dist/cli/utils/config-validation.js +56 -290
- package/dist/cli/utils/image-store.d.ts +16 -0
- package/dist/cli/utils/image-store.d.ts.map +1 -0
- package/dist/cli/utils/image-store.js +289 -0
- package/dist/cli/utils/scaffolding-utils.d.ts +5 -0
- package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
- package/dist/cli/utils/scaffolding-utils.js +46 -4
- package/dist/cli/utils/template-engine.d.ts +28 -16
- package/dist/cli/utils/template-engine.d.ts.map +1 -1
- package/dist/cli/utils/template-engine.js +339 -479
- package/dist/config/cli-overrides.d.ts +4 -3
- package/dist/config/cli-overrides.d.ts.map +1 -1
- package/dist/config/cli-overrides.js +7 -9
- package/dist/index-main.d.ts +2 -0
- package/dist/index-main.d.ts.map +1 -0
- package/dist/index-main.js +1554 -0
- package/dist/index.js +2 -1589
- package/dist/utils/session-logger-factory.d.ts +3 -0
- package/dist/utils/session-logger-factory.d.ts.map +1 -0
- package/dist/utils/session-logger-factory.js +34 -0
- package/dist/webui/assets/{index-Cz2z7NQ8.js → index-CKhumsZA.js} +231 -231
- package/dist/webui/index.html +1 -1
- package/package.json +11 -8
- package/dist/cli/cli-subscriber.d.ts +0 -45
- package/dist/cli/cli-subscriber.d.ts.map +0 -1
- package/dist/cli/cli-subscriber.js +0 -204
|
@@ -25,10 +25,17 @@ import { getStartupInfo } from './utils/messageFormatting.js';
|
|
|
25
25
|
// Toggle this to switch between modes for testing
|
|
26
26
|
//const USE_ALTERNATE_BUFFER = true;
|
|
27
27
|
const USE_ALTERNATE_BUFFER = false;
|
|
28
|
+
function formatCost(c) {
|
|
29
|
+
if (c < 0.01)
|
|
30
|
+
return `$${c.toFixed(4)}`;
|
|
31
|
+
if (c < 1)
|
|
32
|
+
return `$${c.toFixed(3)}`;
|
|
33
|
+
return `$${c.toFixed(2)}`;
|
|
34
|
+
}
|
|
28
35
|
/**
|
|
29
36
|
* Inner component that wraps the mode-specific component with providers
|
|
30
37
|
*/
|
|
31
|
-
function InkCLIInner({ agent, initialSessionId, startupInfo, soundService }) {
|
|
38
|
+
function InkCLIInner({ agent, initialSessionId, initialPrompt, startupInfo, soundService, configFilePath, }) {
|
|
32
39
|
// Selection hint callback for alternate buffer mode
|
|
33
40
|
const [, setSelectionHintShown] = useState(false);
|
|
34
41
|
// Streaming mode - can be toggled via /stream command
|
|
@@ -37,10 +44,10 @@ function InkCLIInner({ agent, initialSessionId, startupInfo, soundService }) {
|
|
|
37
44
|
setSelectionHintShown(true);
|
|
38
45
|
}, []);
|
|
39
46
|
if (USE_ALTERNATE_BUFFER) {
|
|
40
|
-
return (_jsx(SoundProvider, { soundService: soundService, children: _jsx(ScrollProvider, { onSelectionAttempt: handleSelectionAttempt, children: _jsx(AlternateBufferCLI, { agent: agent, initialSessionId: initialSessionId, startupInfo: startupInfo, onSelectionAttempt: handleSelectionAttempt, useStreaming: streaming }) }) }));
|
|
47
|
+
return (_jsx(SoundProvider, { soundService: soundService, children: _jsx(ScrollProvider, { onSelectionAttempt: handleSelectionAttempt, children: _jsx(AlternateBufferCLI, { agent: agent, initialSessionId: initialSessionId, initialPrompt: initialPrompt, startupInfo: startupInfo, onSelectionAttempt: handleSelectionAttempt, useStreaming: streaming, configFilePath: configFilePath }) }) }));
|
|
41
48
|
}
|
|
42
49
|
// Static mode - no ScrollProvider needed
|
|
43
|
-
return (_jsx(SoundProvider, { soundService: soundService, children: _jsx(StaticCLI, { agent: agent, initialSessionId: initialSessionId, startupInfo: startupInfo, useStreaming: streaming }) }));
|
|
50
|
+
return (_jsx(SoundProvider, { soundService: soundService, children: _jsx(StaticCLI, { agent: agent, initialSessionId: initialSessionId, initialPrompt: initialPrompt, startupInfo: startupInfo, useStreaming: streaming, configFilePath: configFilePath }) }));
|
|
44
51
|
}
|
|
45
52
|
/**
|
|
46
53
|
* Modern CLI interface using React Ink
|
|
@@ -50,8 +57,8 @@ function InkCLIInner({ agent, initialSessionId, startupInfo, soundService }) {
|
|
|
50
57
|
* - KeypressProvider for unified keyboard input
|
|
51
58
|
* - MouseProvider (only in alternate buffer mode)
|
|
52
59
|
*/
|
|
53
|
-
export function InkCLIRefactored({ agent, initialSessionId, startupInfo, soundService, }) {
|
|
54
|
-
return (_jsx(ErrorBoundary, { children: _jsx(KeypressProvider, { children: _jsx(MouseProvider, { mouseEventsEnabled: USE_ALTERNATE_BUFFER, children: _jsx(InkCLIInner, { agent: agent, initialSessionId: initialSessionId, startupInfo: startupInfo, soundService: soundService }) }) }) }));
|
|
60
|
+
export function InkCLIRefactored({ agent, initialSessionId, initialPrompt, startupInfo, soundService, configFilePath, }) {
|
|
61
|
+
return (_jsx(ErrorBoundary, { children: _jsx(KeypressProvider, { children: _jsx(MouseProvider, { mouseEventsEnabled: USE_ALTERNATE_BUFFER, children: _jsx(InkCLIInner, { agent: agent, initialSessionId: initialSessionId, initialPrompt: initialPrompt, startupInfo: startupInfo, soundService: soundService, configFilePath: configFilePath }) }) }) }));
|
|
55
62
|
}
|
|
56
63
|
/**
|
|
57
64
|
* Start the modern Ink-based CLI
|
|
@@ -68,53 +75,157 @@ export async function startInkCliRefactored(agent, initialSessionId, options = {
|
|
|
68
75
|
updateInfo: options.updateInfo,
|
|
69
76
|
needsAgentSync: options.needsAgentSync,
|
|
70
77
|
};
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
// Load preferences helpers (non-fatal if unavailable)
|
|
79
|
+
let globalPreferencesExistFn = () => false;
|
|
80
|
+
let loadGlobalPreferencesFn = null;
|
|
81
|
+
let agentPreferencesExistFn = () => false;
|
|
82
|
+
let loadAgentPreferencesFn = null;
|
|
83
|
+
try {
|
|
84
|
+
const agentManagement = await import('@dexto/agent-management');
|
|
85
|
+
globalPreferencesExistFn = agentManagement.globalPreferencesExist;
|
|
86
|
+
loadGlobalPreferencesFn = agentManagement.loadGlobalPreferences;
|
|
87
|
+
agentPreferencesExistFn = agentManagement.agentPreferencesExist;
|
|
88
|
+
loadAgentPreferencesFn = agentManagement.loadAgentPreferences;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
agent.logger.debug(`Preferences module could not be loaded: ${error instanceof Error ? error.message : String(error)}`);
|
|
92
|
+
}
|
|
74
93
|
let soundService = null;
|
|
75
94
|
// Initialize sound config with defaults (enabled by default even without preferences file)
|
|
76
95
|
let soundConfig = {
|
|
77
96
|
enabled: true,
|
|
97
|
+
onStartup: false,
|
|
98
|
+
startupSoundFile: undefined,
|
|
78
99
|
onApprovalRequired: true,
|
|
100
|
+
approvalSoundFile: undefined,
|
|
79
101
|
onTaskComplete: true,
|
|
102
|
+
completeSoundFile: undefined,
|
|
80
103
|
};
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
// Initialize sound service from preferences (non-fatal)
|
|
105
|
+
try {
|
|
106
|
+
const { SoundNotificationService: SoundNotificationServiceImpl } = await import('./utils/soundNotification.js');
|
|
107
|
+
// Override with user preferences if they exist
|
|
108
|
+
if (globalPreferencesExistFn() && loadGlobalPreferencesFn) {
|
|
109
|
+
try {
|
|
110
|
+
const preferences = await loadGlobalPreferencesFn();
|
|
111
|
+
soundConfig = {
|
|
112
|
+
enabled: preferences.sounds?.enabled ?? soundConfig.enabled,
|
|
113
|
+
onStartup: preferences.sounds?.onStartup ?? soundConfig.onStartup,
|
|
114
|
+
startupSoundFile: preferences.sounds?.startupSoundFile ?? soundConfig.startupSoundFile,
|
|
115
|
+
onApprovalRequired: preferences.sounds?.onApprovalRequired ?? soundConfig.onApprovalRequired,
|
|
116
|
+
approvalSoundFile: preferences.sounds?.approvalSoundFile ?? soundConfig.approvalSoundFile,
|
|
117
|
+
onTaskComplete: preferences.sounds?.onTaskComplete ?? soundConfig.onTaskComplete,
|
|
118
|
+
completeSoundFile: preferences.sounds?.completeSoundFile ?? soundConfig.completeSoundFile,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
// Continue with default sounds - this is non-critical functionality
|
|
123
|
+
agent.logger.debug(`Sound preferences could not be loaded: ${error instanceof Error ? error.message : String(error)}`);
|
|
124
|
+
}
|
|
95
125
|
}
|
|
126
|
+
// Always create the service so sound settings can be toggled at runtime (service gates playback by config)
|
|
127
|
+
soundService = new SoundNotificationServiceImpl(soundConfig);
|
|
128
|
+
soundService.playStartupSound();
|
|
96
129
|
}
|
|
97
|
-
|
|
98
|
-
|
|
130
|
+
catch (error) {
|
|
131
|
+
agent.logger.debug(`Sound initialization failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
132
|
+
soundService = null;
|
|
99
133
|
}
|
|
100
134
|
// Initialize tool preferences (per-agent)
|
|
101
|
-
if (
|
|
135
|
+
if (agentPreferencesExistFn(agent.config.agentId) && loadAgentPreferencesFn) {
|
|
102
136
|
try {
|
|
103
|
-
const preferences = await
|
|
137
|
+
const preferences = await loadAgentPreferencesFn(agent.config.agentId);
|
|
104
138
|
agent.setGlobalDisabledTools(preferences.tools?.disabled ?? []);
|
|
105
139
|
}
|
|
106
140
|
catch (error) {
|
|
107
141
|
agent.logger.debug(`Agent tool preferences could not be loaded: ${error instanceof Error ? error.message : String(error)}`);
|
|
108
142
|
}
|
|
109
143
|
}
|
|
110
|
-
|
|
144
|
+
// Import exit handler before render to avoid race condition
|
|
145
|
+
const { registerExitHandler } = await import('../commands/interactive-commands/exit-handler.js');
|
|
146
|
+
const inkApp = render(_jsx(InkCLIRefactored, { agent: agent, initialSessionId: initialSessionId, initialPrompt: options.initialPrompt, startupInfo: startupInfo, soundService: soundService, configFilePath: options.configFilePath ?? null }), {
|
|
111
147
|
exitOnCtrlC: false,
|
|
112
148
|
alternateBuffer: USE_ALTERNATE_BUFFER,
|
|
113
149
|
// Incremental rendering works better with VirtualizedList
|
|
114
150
|
// Static pattern doesn't need it (and may work better without)
|
|
115
151
|
incrementalRendering: USE_ALTERNATE_BUFFER,
|
|
116
152
|
});
|
|
153
|
+
// Register exit handler immediately after render (synchronous, before any await)
|
|
154
|
+
registerExitHandler(() => inkApp.unmount());
|
|
117
155
|
await inkApp.waitUntilExit();
|
|
118
156
|
// Disable bracketed paste mode to restore normal terminal behavior
|
|
119
157
|
disableBracketedPaste();
|
|
158
|
+
// Display session stats if available (after Ink has unmounted)
|
|
159
|
+
const chalk = (await import('chalk')).default;
|
|
160
|
+
const { getExitStats, clearExitStats } = await import('../commands/interactive-commands/exit-stats.js');
|
|
161
|
+
const exitStats = getExitStats();
|
|
162
|
+
if (exitStats) {
|
|
163
|
+
// Add visual separation - clear space like Gemini CLI does
|
|
164
|
+
// This creates a clean slate showing only the exit command and summary
|
|
165
|
+
process.stdout.write('\n'.repeat(1));
|
|
166
|
+
process.stdout.write(chalk.bold.cyan('📊 Session Summary') + '\n');
|
|
167
|
+
process.stdout.write(chalk.dim('─'.repeat(50)) + '\n');
|
|
168
|
+
// Session ID
|
|
169
|
+
if (exitStats.sessionId) {
|
|
170
|
+
process.stdout.write(chalk.gray(` Session ID: ${exitStats.sessionId}`) + '\n');
|
|
171
|
+
}
|
|
172
|
+
// Duration
|
|
173
|
+
if (exitStats.duration) {
|
|
174
|
+
process.stdout.write(chalk.gray(` Duration: ${exitStats.duration}`) + '\n');
|
|
175
|
+
}
|
|
176
|
+
// Message count
|
|
177
|
+
if (exitStats.messageCount.total > 0) {
|
|
178
|
+
process.stdout.write(chalk.gray(` Messages: ${exitStats.messageCount.total} total (${exitStats.messageCount.user} user, ${exitStats.messageCount.assistant} assistant)`) + '\n');
|
|
179
|
+
}
|
|
180
|
+
// Multi-model breakdown (if multiple models were used)
|
|
181
|
+
if (exitStats.modelStats && exitStats.modelStats.length > 1) {
|
|
182
|
+
process.stdout.write(chalk.gray('\n Models Used:') + '\n');
|
|
183
|
+
for (const modelStat of exitStats.modelStats) {
|
|
184
|
+
const modelLabel = `${modelStat.model} (${modelStat.messageCount} msgs)`;
|
|
185
|
+
process.stdout.write(chalk.gray(` • ${modelLabel}`) + '\n');
|
|
186
|
+
// Detailed token breakdown per model
|
|
187
|
+
const tokens = modelStat.tokenUsage;
|
|
188
|
+
process.stdout.write(chalk.gray(` Input tokens: ${tokens.inputTokens.toLocaleString()}`) +
|
|
189
|
+
'\n');
|
|
190
|
+
process.stdout.write(chalk.gray(` Output tokens: ${tokens.outputTokens.toLocaleString()}`) + '\n');
|
|
191
|
+
process.stdout.write(chalk.gray(` Reasoning tokens: ${tokens.reasoningTokens.toLocaleString()}`) + '\n');
|
|
192
|
+
process.stdout.write(chalk.gray(` Cache read tokens: ${tokens.cacheReadTokens.toLocaleString()}`) + '\n');
|
|
193
|
+
process.stdout.write(chalk.gray(` Cache write tokens: ${tokens.cacheWriteTokens.toLocaleString()}`) + '\n');
|
|
194
|
+
process.stdout.write(chalk.gray(` Total tokens: ${tokens.totalTokens.toLocaleString()}`) +
|
|
195
|
+
'\n');
|
|
196
|
+
if (modelStat.estimatedCost !== undefined) {
|
|
197
|
+
process.stdout.write(chalk.gray(` Cost: ${formatCost(modelStat.estimatedCost)}`) + '\n');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Token usage - label depends on whether multi-model was shown
|
|
202
|
+
if (exitStats.tokenUsage) {
|
|
203
|
+
const { inputTokens, outputTokens, reasoningTokens, cacheReadTokens, cacheWriteTokens, totalTokens, } = exitStats.tokenUsage;
|
|
204
|
+
// Calculate cache savings percentage
|
|
205
|
+
const totalInputWithCache = inputTokens + cacheReadTokens;
|
|
206
|
+
const cacheSavingsPercent = totalInputWithCache > 0
|
|
207
|
+
? ((cacheReadTokens / totalInputWithCache) * 100).toFixed(1)
|
|
208
|
+
: '0.0';
|
|
209
|
+
const tokenSectionLabel = exitStats.modelStats && exitStats.modelStats.length > 1
|
|
210
|
+
? '\n Total Token Usage:'
|
|
211
|
+
: '\n Token Usage:';
|
|
212
|
+
process.stdout.write(chalk.gray(tokenSectionLabel) + '\n');
|
|
213
|
+
process.stdout.write(chalk.gray(` Input tokens: ${inputTokens.toLocaleString()}`) + '\n');
|
|
214
|
+
process.stdout.write(chalk.gray(` Output tokens: ${outputTokens.toLocaleString()}`) + '\n');
|
|
215
|
+
process.stdout.write(chalk.gray(` Reasoning tokens: ${reasoningTokens.toLocaleString()}`) + '\n');
|
|
216
|
+
const cacheReadLabel = cacheReadTokens > 0
|
|
217
|
+
? `${cacheReadTokens.toLocaleString()} (💰 ${cacheSavingsPercent}% savings)`
|
|
218
|
+
: cacheReadTokens.toLocaleString();
|
|
219
|
+
process.stdout.write(chalk.gray(` Cache read tokens: ${cacheReadLabel}`) + '\n');
|
|
220
|
+
process.stdout.write(chalk.gray(` Cache write tokens: ${cacheWriteTokens.toLocaleString()}`) + '\n');
|
|
221
|
+
process.stdout.write(chalk.gray(` Total tokens: ${totalTokens.toLocaleString()}`) + '\n');
|
|
222
|
+
}
|
|
223
|
+
// Estimated cost
|
|
224
|
+
if (exitStats.estimatedCost !== undefined) {
|
|
225
|
+
process.stdout.write(chalk.green(`\n Estimated Cost: ${formatCost(exitStats.estimatedCost)}`) + '\n');
|
|
226
|
+
}
|
|
227
|
+
clearExitStats();
|
|
228
|
+
}
|
|
229
|
+
process.stdout.write(chalk.dim('─'.repeat(50)) + '\n');
|
|
230
|
+
process.stdout.write('\n' + chalk.rgb(255, 165, 0)('Exiting Dexto CLI. Goodbye!') + '\n');
|
|
120
231
|
}
|
|
@@ -17,7 +17,7 @@ export interface ApprovalPromptHandle {
|
|
|
17
17
|
export interface ApprovalOptions {
|
|
18
18
|
/** Remember this tool for the entire session (approves ALL uses) */
|
|
19
19
|
rememberChoice?: boolean;
|
|
20
|
-
/** Remember
|
|
20
|
+
/** Remember an approval pattern (e.g., "git *") */
|
|
21
21
|
rememberPattern?: string;
|
|
22
22
|
/** Form data for elicitation requests */
|
|
23
23
|
formData?: Record<string, unknown>;
|
|
@@ -36,7 +36,7 @@ interface ApprovalPromptProps {
|
|
|
36
36
|
* Compact approval prompt component that displays above the input area
|
|
37
37
|
* Shows options based on approval type:
|
|
38
38
|
* - Tool confirmation: Yes, Yes (Session), No
|
|
39
|
-
* -
|
|
39
|
+
* - Tool with patterns: Yes (once), pattern options, Yes (session), No
|
|
40
40
|
* - Elicitation: Form with input fields
|
|
41
41
|
*/
|
|
42
42
|
export declare const ApprovalPrompt: React.ForwardRefExoticComponent<ApprovalPromptProps & React.RefAttributes<ApprovalPromptHandle>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApprovalPrompt.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/ApprovalPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAM5D,MAAM,WAAW,eAAe;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,oEAAoE;IACpE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,
|
|
1
|
+
{"version":3,"file":"ApprovalPrompt.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/ApprovalPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAM5D,MAAM,WAAW,eAAe;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,oEAAoE;IACpE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,gFAAgF;IAChF,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,UAAU,mBAAmB;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC9C,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAiBD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,kGAwe1B,CAAC"}
|
|
@@ -4,36 +4,71 @@ import { Box, Text } from 'ink';
|
|
|
4
4
|
import { ElicitationForm } from './ElicitationForm.js';
|
|
5
5
|
import { DiffPreview, CreateFilePreview } from './renderers/index.js';
|
|
6
6
|
import { isEditWriteTool } from '../utils/toolUtils.js';
|
|
7
|
-
import { formatToolHeader } from '../utils/messageFormatting.js';
|
|
7
|
+
import { formatPathForDisplay, formatToolHeader } from '../utils/messageFormatting.js';
|
|
8
8
|
/**
|
|
9
9
|
* Compact approval prompt component that displays above the input area
|
|
10
10
|
* Shows options based on approval type:
|
|
11
11
|
* - Tool confirmation: Yes, Yes (Session), No
|
|
12
|
-
* -
|
|
12
|
+
* - Tool with patterns: Yes (once), pattern options, Yes (session), No
|
|
13
13
|
* - Elicitation: Form with input fields
|
|
14
14
|
*/
|
|
15
15
|
export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCancel }, ref) => {
|
|
16
16
|
const isCommandConfirmation = approval.type === 'command_confirmation';
|
|
17
17
|
const isElicitation = approval.type === 'elicitation';
|
|
18
18
|
const isDirectoryAccess = approval.type === 'directory_access';
|
|
19
|
+
const directoryAccess = approval.metadata.directoryAccess;
|
|
20
|
+
const hasToolDirectoryAccess = approval.type === 'tool_confirmation' &&
|
|
21
|
+
directoryAccess !== undefined &&
|
|
22
|
+
typeof directoryAccess === 'object' &&
|
|
23
|
+
directoryAccess !== null;
|
|
24
|
+
const directoryAccessParentDir = hasToolDirectoryAccess && typeof directoryAccess.parentDir === 'string'
|
|
25
|
+
? directoryAccess.parentDir
|
|
26
|
+
: null;
|
|
19
27
|
// Extract tool metadata
|
|
20
28
|
const toolName = approval.metadata.toolName;
|
|
21
29
|
const toolArgs = approval.metadata.args || {};
|
|
30
|
+
const callDescriptionRaw = typeof approval.metadata.description === 'string'
|
|
31
|
+
? approval.metadata.description
|
|
32
|
+
: undefined;
|
|
33
|
+
const callDescription = useMemo(() => {
|
|
34
|
+
if (!callDescriptionRaw)
|
|
35
|
+
return null;
|
|
36
|
+
const singleLine = callDescriptionRaw.replace(/\s+/g, ' ').trim();
|
|
37
|
+
if (!singleLine)
|
|
38
|
+
return null;
|
|
39
|
+
const maxLength = 120;
|
|
40
|
+
if (singleLine.length <= maxLength)
|
|
41
|
+
return singleLine;
|
|
42
|
+
return `${singleLine.slice(0, Math.max(0, maxLength - 1))}…`;
|
|
43
|
+
}, [callDescriptionRaw]);
|
|
22
44
|
// Check if this is a plan_review tool (shows custom approval options)
|
|
23
|
-
const isPlanReview = toolName === '
|
|
24
|
-
|
|
25
|
-
toolName === 'plan_review';
|
|
26
|
-
// Extract suggested patterns for bash tools
|
|
45
|
+
const isPlanReview = toolName === 'plan_review';
|
|
46
|
+
// Extract suggested patterns for tools that support pattern-based approvals
|
|
27
47
|
const suggestedPatterns = approval.metadata.suggestedPatterns ?? [];
|
|
28
|
-
const
|
|
48
|
+
const hasSuggestedPatterns = suggestedPatterns.length > 0;
|
|
29
49
|
// Check if this is an edit/write file tool
|
|
30
50
|
const isEditOrWriteTool = isEditWriteTool(toolName);
|
|
31
51
|
// Format tool header using shared utility (same format as tool messages)
|
|
52
|
+
const presentationSnapshot = useMemo(() => {
|
|
53
|
+
const raw = approval.metadata
|
|
54
|
+
.presentationSnapshot;
|
|
55
|
+
if (typeof raw !== 'object' || raw === null) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
if (raw.version !== 1) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
return raw;
|
|
62
|
+
}, [approval.metadata]);
|
|
32
63
|
const formattedTool = useMemo(() => {
|
|
33
64
|
if (!toolName)
|
|
34
65
|
return null;
|
|
35
|
-
return formatToolHeader(
|
|
36
|
-
|
|
66
|
+
return formatToolHeader({
|
|
67
|
+
toolName,
|
|
68
|
+
args: toolArgs,
|
|
69
|
+
...(presentationSnapshot !== undefined && { presentationSnapshot }),
|
|
70
|
+
});
|
|
71
|
+
}, [toolName, toolArgs, presentationSnapshot]);
|
|
37
72
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
38
73
|
// State for plan review feedback input
|
|
39
74
|
const [showFeedbackInput, setShowFeedbackInput] = useState(false);
|
|
@@ -50,8 +85,17 @@ export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCance
|
|
|
50
85
|
options.push({ id: 'plan-approve-accept-edits', label: 'Approve + Accept All Edits' });
|
|
51
86
|
// Third "option" is the feedback input (handled specially in render)
|
|
52
87
|
}
|
|
53
|
-
else if (
|
|
54
|
-
//
|
|
88
|
+
else if (hasToolDirectoryAccess) {
|
|
89
|
+
// Tool approval that includes directory access - offer session-scoped dir allow
|
|
90
|
+
const dirLabel = directoryAccessParentDir
|
|
91
|
+
? ` ${formatPathForDisplay(directoryAccessParentDir)}`
|
|
92
|
+
: '';
|
|
93
|
+
options.push({ id: 'yes', label: 'Yes (once)' });
|
|
94
|
+
options.push({ id: 'yes-directory-session', label: `Yes, allow${dirLabel} (session)` });
|
|
95
|
+
options.push({ id: 'no', label: 'No' });
|
|
96
|
+
}
|
|
97
|
+
else if (hasSuggestedPatterns) {
|
|
98
|
+
// Tool with pattern suggestions
|
|
55
99
|
options.push({ id: 'yes', label: 'Yes (once)' });
|
|
56
100
|
suggestedPatterns.forEach((pattern, i) => {
|
|
57
101
|
options.push({
|
|
@@ -59,7 +103,7 @@ export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCance
|
|
|
59
103
|
label: `Yes, allow "${pattern}"`,
|
|
60
104
|
});
|
|
61
105
|
});
|
|
62
|
-
options.push({ id: 'yes-session', label: 'Yes, allow
|
|
106
|
+
options.push({ id: 'yes-session', label: 'Yes, allow this tool (session)' });
|
|
63
107
|
options.push({ id: 'no', label: 'No' });
|
|
64
108
|
}
|
|
65
109
|
else if (isCommandConfirmation) {
|
|
@@ -70,7 +114,7 @@ export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCance
|
|
|
70
114
|
else if (isDirectoryAccess) {
|
|
71
115
|
// Directory access - offer session-scoped access
|
|
72
116
|
const parentDir = approval.metadata.parentDir;
|
|
73
|
-
const dirLabel = parentDir ? `
|
|
117
|
+
const dirLabel = parentDir ? ` ${formatPathForDisplay(parentDir)}` : '';
|
|
74
118
|
options.push({ id: 'yes', label: 'Yes (once)' });
|
|
75
119
|
options.push({ id: 'yes-session', label: `Yes, allow${dirLabel} (session)` });
|
|
76
120
|
options.push({ id: 'no', label: 'No' });
|
|
@@ -166,6 +210,9 @@ export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCance
|
|
|
166
210
|
onApprove({ rememberChoice: true });
|
|
167
211
|
}
|
|
168
212
|
}
|
|
213
|
+
else if (option.id === 'yes-directory-session') {
|
|
214
|
+
onApprove({ rememberDirectory: true });
|
|
215
|
+
}
|
|
169
216
|
else if (option.id === 'yes-accept-edits') {
|
|
170
217
|
// Approve and enable "accept all edits" mode
|
|
171
218
|
onApprove({ enableAcceptEditsMode: true });
|
|
@@ -201,6 +248,7 @@ export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCance
|
|
|
201
248
|
isElicitation,
|
|
202
249
|
isEditOrWriteTool,
|
|
203
250
|
isDirectoryAccess,
|
|
251
|
+
hasToolDirectoryAccess,
|
|
204
252
|
isPlanReview,
|
|
205
253
|
options,
|
|
206
254
|
suggestedPatterns,
|
|
@@ -222,26 +270,16 @@ export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCance
|
|
|
222
270
|
if (!displayPreview)
|
|
223
271
|
return null;
|
|
224
272
|
switch (displayPreview.type) {
|
|
225
|
-
case 'diff':
|
|
226
|
-
|
|
227
|
-
toolName === 'internal--write_file' ||
|
|
228
|
-
toolName === 'write_file';
|
|
229
|
-
return (_jsx(DiffPreview, { data: displayPreview, headerType: isOverwrite ? 'overwrite' : 'edit' }));
|
|
230
|
-
}
|
|
273
|
+
case 'diff':
|
|
274
|
+
return _jsx(DiffPreview, { data: displayPreview });
|
|
231
275
|
case 'shell':
|
|
232
|
-
// For shell preview,
|
|
233
|
-
return (_jsxs(Box, { marginBottom: 1,
|
|
276
|
+
// For shell preview, show the command + optional description (no output yet)
|
|
277
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { color: "cyan", bold: true, children: displayPreview.title ?? 'Bash' }) }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [displayPreview.command.split('\n').map((line, i) => (_jsxs(Text, { color: "yellowBright", wrap: "wrap", children: [i === 0 ? '$ ' : ' ', line] }, i))), displayPreview.isBackground && (_jsx(Text, { color: "gray", children: "(background)" }))] }), callDescription && (_jsx(Box, { marginTop: 0, children: _jsx(Text, { color: "gray", children: callDescription }) }))] }));
|
|
234
278
|
case 'file':
|
|
235
|
-
//
|
|
236
|
-
if (displayPreview.
|
|
279
|
+
// If content is provided, show the full content (create/review flows)
|
|
280
|
+
if (displayPreview.content) {
|
|
237
281
|
return _jsx(CreateFilePreview, { data: displayPreview });
|
|
238
282
|
}
|
|
239
|
-
// For plan_review (read operation with content), show full content for review
|
|
240
|
-
if (displayPreview.operation === 'read' &&
|
|
241
|
-
displayPreview.content &&
|
|
242
|
-
isPlanReview) {
|
|
243
|
-
return _jsx(CreateFilePreview, { data: displayPreview, header: "Review plan" });
|
|
244
|
-
}
|
|
245
283
|
// Fallback for other file operations
|
|
246
284
|
return (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "gray", children: [displayPreview.operation === 'read' &&
|
|
247
285
|
`Read ${displayPreview.lineCount ?? 'file'} lines`, displayPreview.operation === 'write' &&
|
|
@@ -255,7 +293,24 @@ export const ApprovalPrompt = forwardRef(({ approval, onApprove, onDeny, onCance
|
|
|
255
293
|
const directoryPath = approval.metadata.path;
|
|
256
294
|
const parentDir = approval.metadata.parentDir;
|
|
257
295
|
const operation = approval.metadata.operation;
|
|
258
|
-
|
|
296
|
+
const directoryAccessTitle = !isDirectoryAccess
|
|
297
|
+
? null
|
|
298
|
+
: operation === 'read'
|
|
299
|
+
? 'Read file'
|
|
300
|
+
: operation === 'write'
|
|
301
|
+
? 'Write file'
|
|
302
|
+
: operation === 'edit'
|
|
303
|
+
? 'Edit file'
|
|
304
|
+
: 'Directory access';
|
|
305
|
+
const directoryAccessToolHeader = !isDirectoryAccess || !toolName
|
|
306
|
+
? null
|
|
307
|
+
: formatToolHeader({
|
|
308
|
+
toolName,
|
|
309
|
+
args: (directoryPath ?? parentDir) ? { path: directoryPath ?? parentDir } : {},
|
|
310
|
+
...(presentationSnapshot !== undefined && { presentationSnapshot }),
|
|
311
|
+
}).header;
|
|
312
|
+
const showHeaderBlock = isDirectoryAccess || isCommandConfirmation || !displayPreview;
|
|
313
|
+
return (_jsxs(Box, { paddingX: 0, paddingY: 0, flexDirection: "column", children: [showHeaderBlock && (_jsx(Box, { flexDirection: "column", marginBottom: 0, children: isDirectoryAccess ? (_jsxs(_Fragment, { children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { color: "cyan", bold: true, children: directoryAccessTitle ?? 'Directory access' }) }), directoryAccessToolHeader && (_jsx(Box, { marginBottom: 0, children: _jsx(Text, { wrap: "wrap", children: directoryAccessToolHeader }) }))] })) : isCommandConfirmation ? (_jsxs(_Fragment, { children: [_jsx(Box, { flexDirection: "row", children: _jsxs(Text, { color: "yellowBright", bold: true, children: ["Confirm command:", ' '] }) }), command && (_jsx(Box, { flexDirection: "column", marginTop: 0, children: _jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: command.split('\n').map((line, i) => (_jsx(Text, { color: "red", wrap: "wrap", children: line }, i))) }) }))] })) : (_jsxs(_Fragment, { children: [_jsxs(Box, { flexDirection: "row", children: [_jsxs(Text, { color: "yellowBright", bold: true, children: ["Confirm:", ' '] }), formattedTool && (_jsx(Text, { color: "cyan", children: formattedTool.header }))] }), callDescription && (_jsxs(Box, { flexDirection: "row", marginTop: 0, children: [_jsx(Text, { color: "gray", children: ' ' }), _jsx(Text, { color: "gray", children: callDescription })] }))] })) })), renderPreview(), _jsxs(Box, { flexDirection: "column", marginTop: 0, children: [options.map((option, index) => {
|
|
259
314
|
const isSelected = index === selectedIndex;
|
|
260
315
|
const isNo = option.id === 'no';
|
|
261
316
|
return (_jsx(Box, { children: isSelected ? (_jsxs(Text, { color: isNo ? 'red' : 'green', bold: true, children: [' ▶ ', option.label] })) : (_jsxs(Text, { color: "gray", children: [' ', option.label] })) }, option.id));
|
|
@@ -40,7 +40,7 @@ export function BackgroundTasksPanel({ tasks, isExpanded, isProcessing = false,
|
|
|
40
40
|
const statusWidth = 10;
|
|
41
41
|
const idWidth = 14;
|
|
42
42
|
const descWidth = 48;
|
|
43
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: isProcessing ? undefined : 'round', borderColor: "gray", paddingX: 1, marginX: 1, marginBottom: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: headerText }), _jsxs(Text, { color: "gray", dimColor: true, children: [' ', "\u00B7 ctrl+b to hide tasks"] })] }), _jsx(Box, { children: _jsxs(Text, { color: "gray", children: [padText('status', statusWidth), padText('task id', idWidth), padText('description', descWidth)] }) }), sortedTasks.map((task) => {
|
|
43
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: isProcessing ? undefined : 'round', borderColor: "gray", paddingX: 1, marginX: 1, marginBottom: 1, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: headerText }), _jsxs(Text, { color: "gray", dimColor: true, children: [' ', "\u00B7 ctrl+b to hide bg tasks"] })] }), _jsx(Box, { children: _jsxs(Text, { color: "gray", children: [padText('status', statusWidth), padText('task id', idWidth), padText('description', descWidth)] }) }), sortedTasks.map((task) => {
|
|
44
44
|
const status = formatStatus(task.status);
|
|
45
45
|
const desc = task.description ?? '';
|
|
46
46
|
return (_jsx(Box, { children: _jsxs(Text, { color: task.status === 'running' ? 'yellow' : 'gray', children: [padText(status, statusWidth), padText(task.taskId, idWidth), padText(desc, descWidth)] }) }, task.taskId));
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ElicitationForm Component
|
|
3
|
-
* Renders a form for ask_user/elicitation requests in the CLI
|
|
4
|
-
*
|
|
3
|
+
* Renders a form for ask_user/elicitation requests in the CLI.
|
|
4
|
+
*
|
|
5
|
+
* Uses a wizard flow (one question at a time) to avoid huge modals and improve
|
|
6
|
+
* usability on small terminals.
|
|
5
7
|
*/
|
|
6
8
|
import React from 'react';
|
|
7
|
-
import type { Key } from '../hooks/useInputOrchestrator.js';
|
|
8
9
|
import type { ElicitationMetadata } from '@dexto/core';
|
|
10
|
+
import type { Key } from '../hooks/useInputOrchestrator.js';
|
|
9
11
|
export interface ElicitationFormHandle {
|
|
10
12
|
handleInput: (input: string, key: Key) => boolean;
|
|
11
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElicitationForm.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/ElicitationForm.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ElicitationForm.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/ElicitationForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA0E,MAAM,OAAO,CAAC;AAG/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAI5D,MAAM,WAAW,qBAAqB;IAClC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,oBAAoB;IAC1B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAkBD;;GAEG;AACH,eAAO,MAAM,eAAe,oGA6uB3B,CAAC"}
|