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
|
@@ -5,25 +5,32 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
5
5
|
* Features:
|
|
6
6
|
* - Search/filter tools by name
|
|
7
7
|
* - View tool details (description, schema)
|
|
8
|
-
* - Shows source (MCP server or
|
|
8
|
+
* - Shows source (MCP server or Local)
|
|
9
9
|
*/
|
|
10
10
|
import { useState, useEffect, forwardRef, useRef, useImperativeHandle, useMemo, } from 'react';
|
|
11
11
|
import { Box, Text } from 'ink';
|
|
12
12
|
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
|
|
13
13
|
import { writeToClipboard } from '../../utils/clipboardUtils.js';
|
|
14
|
-
|
|
14
|
+
import { getMaxVisibleItemsForTerminalRows } from '../../utils/overlaySizing.js';
|
|
15
|
+
import { HintBar } from '../shared/HintBar.js';
|
|
15
16
|
const LIST_ACTIONS = ['view', 'config', 'back'];
|
|
16
17
|
/**
|
|
17
18
|
* Tool browser with search and detail views
|
|
18
19
|
*/
|
|
19
20
|
const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent, sessionId }, ref) {
|
|
20
21
|
const { columns, rows } = useTerminalSize();
|
|
22
|
+
const maxVisibleTools = useMemo(() => {
|
|
23
|
+
return getMaxVisibleItemsForTerminalRows({
|
|
24
|
+
rows,
|
|
25
|
+
hardCap: 10,
|
|
26
|
+
reservedRows: 16,
|
|
27
|
+
});
|
|
28
|
+
}, [rows]);
|
|
21
29
|
const [tools, setTools] = useState([]);
|
|
22
30
|
const [isLoading, setIsLoading] = useState(false);
|
|
23
31
|
const [loadError, setLoadError] = useState(null);
|
|
24
|
-
const [
|
|
32
|
+
const [selection, setSelection] = useState({ index: 0, offset: 0 });
|
|
25
33
|
const [searchQuery, setSearchQuery] = useState('');
|
|
26
|
-
const [scrollOffset, setScrollOffset] = useState(0);
|
|
27
34
|
const [viewMode, setViewMode] = useState('list');
|
|
28
35
|
const [selectedTool, setSelectedTool] = useState(null);
|
|
29
36
|
const [detailScrollOffset, setDetailScrollOffset] = useState(0);
|
|
@@ -33,7 +40,7 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
33
40
|
const [scopeToolName, setScopeToolName] = useState(null);
|
|
34
41
|
const [scopeNextEnabled, setScopeNextEnabled] = useState(true);
|
|
35
42
|
const [scopeTarget, setScopeTarget] = useState('session');
|
|
36
|
-
const selectedIndexRef = useRef(
|
|
43
|
+
const selectedIndexRef = useRef(0);
|
|
37
44
|
const viewModeRef = useRef(viewMode);
|
|
38
45
|
const detailScrollOffsetRef = useRef(detailScrollOffset);
|
|
39
46
|
const detailMaxScrollOffsetRef = useRef(0);
|
|
@@ -45,7 +52,7 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
45
52
|
const scopeNextEnabledRef = useRef(scopeNextEnabled);
|
|
46
53
|
const scopeToolNameRef = useRef(scopeToolName);
|
|
47
54
|
// Keep refs in sync
|
|
48
|
-
selectedIndexRef.current =
|
|
55
|
+
selectedIndexRef.current = selection.index;
|
|
49
56
|
viewModeRef.current = viewMode;
|
|
50
57
|
detailScrollOffsetRef.current = detailScrollOffset;
|
|
51
58
|
selectedToolRef.current = selectedTool;
|
|
@@ -62,8 +69,7 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
62
69
|
let cancelled = false;
|
|
63
70
|
setIsLoading(true);
|
|
64
71
|
setSearchQuery('');
|
|
65
|
-
|
|
66
|
-
setScrollOffset(0);
|
|
72
|
+
setSelection({ index: 0, offset: 0 });
|
|
67
73
|
setViewMode('list');
|
|
68
74
|
setSelectedTool(null);
|
|
69
75
|
setListActionsIndex(0);
|
|
@@ -94,17 +100,17 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
94
100
|
toolList.push({
|
|
95
101
|
name: toolName,
|
|
96
102
|
description: toolInfo.description || 'No description available',
|
|
97
|
-
source: isMcpTool ? 'mcp' : '
|
|
103
|
+
source: isMcpTool ? 'mcp' : 'local',
|
|
98
104
|
serverName,
|
|
99
105
|
inputSchema: toolInfo.parameters,
|
|
100
106
|
isEnabled: enabledToolNames.has(toolName),
|
|
101
107
|
isAutoApproved: autoApprovedToolNames.has(toolName),
|
|
102
108
|
});
|
|
103
109
|
}
|
|
104
|
-
// Sort:
|
|
110
|
+
// Sort: local tools first, then MCP tools
|
|
105
111
|
toolList.sort((a, b) => {
|
|
106
112
|
if (a.source !== b.source) {
|
|
107
|
-
return a.source === '
|
|
113
|
+
return a.source === 'local' ? -1 : 1;
|
|
108
114
|
}
|
|
109
115
|
return a.name.localeCompare(b.name);
|
|
110
116
|
});
|
|
@@ -141,21 +147,27 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
141
147
|
return name.includes(query) || desc.includes(query) || server.includes(query);
|
|
142
148
|
});
|
|
143
149
|
}, [tools, searchQuery]);
|
|
144
|
-
//
|
|
145
|
-
useEffect(() => {
|
|
146
|
-
if (selectedIndex >= filteredTools.length) {
|
|
147
|
-
setSelectedIndex(Math.max(0, filteredTools.length - 1));
|
|
148
|
-
}
|
|
149
|
-
}, [filteredTools.length, selectedIndex]);
|
|
150
|
-
// Calculate scroll offset
|
|
150
|
+
// Keep selection valid and visible when filtering or terminal height changes.
|
|
151
151
|
useEffect(() => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
152
|
+
setSelection((prev) => {
|
|
153
|
+
const maxIndex = Math.max(0, filteredTools.length - 1);
|
|
154
|
+
const nextIndex = Math.min(prev.index, maxIndex);
|
|
155
|
+
let nextOffset = prev.offset;
|
|
156
|
+
if (nextIndex < nextOffset) {
|
|
157
|
+
nextOffset = nextIndex;
|
|
158
|
+
}
|
|
159
|
+
else if (nextIndex >= nextOffset + maxVisibleTools) {
|
|
160
|
+
nextOffset = Math.max(0, nextIndex - maxVisibleTools + 1);
|
|
161
|
+
}
|
|
162
|
+
const maxOffset = Math.max(0, filteredTools.length - maxVisibleTools);
|
|
163
|
+
nextOffset = Math.min(maxOffset, Math.max(0, nextOffset));
|
|
164
|
+
if (nextIndex === prev.index && nextOffset === prev.offset) {
|
|
165
|
+
return prev;
|
|
166
|
+
}
|
|
167
|
+
selectedIndexRef.current = nextIndex;
|
|
168
|
+
return { index: nextIndex, offset: nextOffset };
|
|
169
|
+
});
|
|
170
|
+
}, [filteredTools.length, maxVisibleTools]);
|
|
159
171
|
const openListActions = (tool) => {
|
|
160
172
|
setSelectedTool(tool);
|
|
161
173
|
setListActionsIndex(0);
|
|
@@ -276,6 +288,12 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
276
288
|
handleInput: (input, key) => {
|
|
277
289
|
if (!isVisible)
|
|
278
290
|
return false;
|
|
291
|
+
if (isLoading) {
|
|
292
|
+
if (key.escape) {
|
|
293
|
+
onClose();
|
|
294
|
+
}
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
279
297
|
// Scope selection view
|
|
280
298
|
if (viewModeRef.current === 'scope') {
|
|
281
299
|
if (key.escape || key.backspace || key.delete) {
|
|
@@ -429,8 +447,8 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
429
447
|
// Regular character - add to search
|
|
430
448
|
if (input.length === 1 && input.charCodeAt(0) >= 32) {
|
|
431
449
|
setSearchQuery((prev) => prev + input);
|
|
432
|
-
|
|
433
|
-
|
|
450
|
+
selectedIndexRef.current = 0;
|
|
451
|
+
setSelection({ index: 0, offset: 0 });
|
|
434
452
|
return true;
|
|
435
453
|
}
|
|
436
454
|
}
|
|
@@ -444,14 +462,36 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
444
462
|
return false;
|
|
445
463
|
if (key.upArrow) {
|
|
446
464
|
const nextIndex = (selectedIndexRef.current - 1 + itemsLength) % itemsLength;
|
|
447
|
-
setSelectedIndex(nextIndex);
|
|
448
465
|
selectedIndexRef.current = nextIndex;
|
|
466
|
+
setSelection((prev) => {
|
|
467
|
+
let nextOffset = prev.offset;
|
|
468
|
+
if (nextIndex < prev.offset) {
|
|
469
|
+
nextOffset = nextIndex;
|
|
470
|
+
}
|
|
471
|
+
else if (nextIndex >= prev.offset + maxVisibleTools) {
|
|
472
|
+
nextOffset = Math.max(0, nextIndex - maxVisibleTools + 1);
|
|
473
|
+
}
|
|
474
|
+
const maxOffset = Math.max(0, itemsLength - maxVisibleTools);
|
|
475
|
+
nextOffset = Math.min(maxOffset, Math.max(0, nextOffset));
|
|
476
|
+
return { index: nextIndex, offset: nextOffset };
|
|
477
|
+
});
|
|
449
478
|
return true;
|
|
450
479
|
}
|
|
451
480
|
if (key.downArrow) {
|
|
452
481
|
const nextIndex = (selectedIndexRef.current + 1) % itemsLength;
|
|
453
|
-
setSelectedIndex(nextIndex);
|
|
454
482
|
selectedIndexRef.current = nextIndex;
|
|
483
|
+
setSelection((prev) => {
|
|
484
|
+
let nextOffset = prev.offset;
|
|
485
|
+
if (nextIndex < prev.offset) {
|
|
486
|
+
nextOffset = nextIndex;
|
|
487
|
+
}
|
|
488
|
+
else if (nextIndex >= prev.offset + maxVisibleTools) {
|
|
489
|
+
nextOffset = Math.max(0, nextIndex - maxVisibleTools + 1);
|
|
490
|
+
}
|
|
491
|
+
const maxOffset = Math.max(0, itemsLength - maxVisibleTools);
|
|
492
|
+
nextOffset = Math.min(maxOffset, Math.max(0, nextOffset));
|
|
493
|
+
return { index: nextIndex, offset: nextOffset };
|
|
494
|
+
});
|
|
455
495
|
return true;
|
|
456
496
|
}
|
|
457
497
|
if (key.return && itemsLength > 0) {
|
|
@@ -463,12 +503,9 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
463
503
|
}
|
|
464
504
|
return false;
|
|
465
505
|
},
|
|
466
|
-
}), [isVisible, filteredTools, onClose, sessionId]);
|
|
506
|
+
}), [isVisible, isLoading, filteredTools, maxVisibleTools, onClose, sessionId]);
|
|
467
507
|
if (!isVisible)
|
|
468
508
|
return null;
|
|
469
|
-
if (isLoading) {
|
|
470
|
-
return (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "Loading tools..." }) }));
|
|
471
|
-
}
|
|
472
509
|
if (viewMode === 'list-actions' && selectedTool) {
|
|
473
510
|
return (_jsx(ToolActionsMenu, { tool: selectedTool, columns: columns, listActionsIndex: listActionsIndex }));
|
|
474
511
|
}
|
|
@@ -483,18 +520,36 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent,
|
|
|
483
520
|
return (_jsx(ToolScopeView, { tool: selectedTool, columns: columns, scopeTarget: scopeTarget, scopeNextEnabled: scopeNextEnabled, sessionAvailable: Boolean(sessionId) }));
|
|
484
521
|
}
|
|
485
522
|
// List view
|
|
486
|
-
const
|
|
487
|
-
const
|
|
523
|
+
const selectedIndex = selection.index;
|
|
524
|
+
const scrollOffset = selection.offset;
|
|
525
|
+
const visibleTools = filteredTools.slice(scrollOffset, scrollOffset + maxVisibleTools);
|
|
526
|
+
const filteredLocalCount = filteredTools.filter((t) => t.source === 'local').length;
|
|
488
527
|
const filteredMcpCount = filteredTools.filter((t) => t.source === 'mcp').length;
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
528
|
+
const selectedToolInList = filteredTools[selectedIndex];
|
|
529
|
+
let detailLine = '';
|
|
530
|
+
if (isLoading) {
|
|
531
|
+
detailLine = 'Loading tools…';
|
|
532
|
+
}
|
|
533
|
+
else if (loadError) {
|
|
534
|
+
detailLine = loadError;
|
|
535
|
+
}
|
|
536
|
+
else if (searchQuery.trim() && filteredTools.length === 0) {
|
|
537
|
+
detailLine = 'No tools match your search';
|
|
538
|
+
}
|
|
539
|
+
else if (selectedToolInList) {
|
|
540
|
+
detailLine = selectedToolInList.description;
|
|
541
|
+
}
|
|
542
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: "Tools" }), _jsxs(Text, { color: "gray", children: [' ', "(", filteredTools.length, " tools: ", filteredLocalCount, " local, ", filteredMcpCount, ' ', "MCP)"] })] }), _jsxs(Box, { paddingX: 0, paddingY: 0, marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Search: " }), _jsx(Text, { color: searchQuery ? 'white' : 'gray', wrap: "truncate-end", children: searchQuery || 'Type to filter tools…' })] }), _jsx(Box, { flexDirection: "column", height: maxVisibleTools, marginTop: 1, children: isLoading || filteredTools.length === 0
|
|
543
|
+
? Array.from({ length: maxVisibleTools }, (_, index) => (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { children: " " }) }, `tool-empty-${index}`)))
|
|
544
|
+
: Array.from({ length: maxVisibleTools }, (_, rowIndex) => {
|
|
545
|
+
const tool = visibleTools[rowIndex];
|
|
546
|
+
if (!tool) {
|
|
547
|
+
return (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { children: " " }) }, `tool-empty-${rowIndex}`));
|
|
548
|
+
}
|
|
549
|
+
const actualIndex = scrollOffset + rowIndex;
|
|
550
|
+
const isSelected = actualIndex === selectedIndex;
|
|
551
|
+
return (_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: isSelected ? 'cyan' : 'white', children: isSelected ? '▶ ' : ' ' }), _jsx(Text, { color: isSelected ? 'cyan' : 'white', bold: isSelected, children: truncateText(tool.name, 35) }), _jsxs(Text, { color: tool.source === 'local' ? 'magenta' : 'blue', children: [' ', "[", tool.source === 'local' ? 'Local' : 'MCP', "]"] }), tool.serverName && (_jsxs(Text, { color: "gray", children: [" (", tool.serverName, ")"] })), _jsxs(Text, { color: tool.isEnabled ? 'green' : 'red', children: [' ', tool.isEnabled ? 'Enabled' : 'Disabled'] }), tool.isAutoApproved && (_jsx(Text, { color: "yellow", children: " [auto-approved]" }))] }, tool.name));
|
|
552
|
+
}) }), _jsx(Box, { paddingX: 0, paddingY: 0, marginTop: 1, children: _jsx(Text, { color: loadError ? 'red' : 'gray', wrap: "truncate-end", children: detailLine }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(HintBar, { hints: ['↑↓ navigate', 'Enter options', 'Esc close'] }) })] }));
|
|
498
553
|
});
|
|
499
554
|
/**
|
|
500
555
|
* Build detail line data for a tool (plain data, not React elements)
|
|
@@ -560,7 +615,7 @@ function renderDetailLine(line, _index) {
|
|
|
560
615
|
case 'title':
|
|
561
616
|
return (_jsx(Text, { color: "cyan", bold: true, children: line.text }));
|
|
562
617
|
case 'source':
|
|
563
|
-
return (_jsxs(Text, { color: line.source === '
|
|
618
|
+
return (_jsxs(Text, { color: line.source === 'local' ? 'magenta' : 'blue', children: [line.source === 'local' ? 'Local Tool' : 'MCP Tool', line.serverName ? ` (${line.serverName})` : ''] }));
|
|
564
619
|
case 'empty':
|
|
565
620
|
return _jsx(Text, { children: " " });
|
|
566
621
|
case 'header':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalModelWizard.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA4E,MAAM,OAAO,CAAC;AAKjG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wCAAwC,CAAC;
|
|
1
|
+
{"version":3,"file":"LocalModelWizard.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA4E,MAAM,OAAO,CAAC;AAKjG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wCAAwC,CAAC;AAGlE,OAAO,EASH,KAAK,WAAW,EACnB,MAAM,yBAAyB,CAAC;AAqBjC,UAAU,qBAAqB;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAaD;;;GAGG;AACH,QAAA,MAAM,gBAAgB,sGAg/BrB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -11,6 +11,8 @@ import { Box, Text } from 'ink';
|
|
|
11
11
|
import * as fs from 'fs';
|
|
12
12
|
import * as path from 'path';
|
|
13
13
|
import { spawn } from 'child_process';
|
|
14
|
+
import { useAnimationTick } from '../../../hooks/useAnimationTick.js';
|
|
15
|
+
import { BRAILLE_SPINNER_FRAMES } from '../../../constants/spinnerFrames.js';
|
|
14
16
|
import { saveCustomModel, getAllInstalledModels, addInstalledModel, removeInstalledModel, getModelsDirectory, formatSize, getDextoGlobalPath, } from '@dexto/agent-management';
|
|
15
17
|
import { promises as fsPromises } from 'fs';
|
|
16
18
|
import { getAllLocalModels, getLocalModelById, getRecommendedLocalModels, downloadModel, isNodeLlamaCppInstalled, } from '@dexto/core';
|
|
@@ -33,8 +35,12 @@ const LocalModelWizard = forwardRef(function LocalModelWizard({ isVisible, onCom
|
|
|
33
35
|
const [nodeLlamaChecked, setNodeLlamaChecked] = useState(false); // Track if we've checked installation
|
|
34
36
|
const [isInstallingNodeLlama, setIsInstallingNodeLlama] = useState(false);
|
|
35
37
|
const [installConfirmIndex, setInstallConfirmIndex] = useState(0); // 0 = Yes, 1 = No
|
|
36
|
-
const [installSpinnerFrame, setInstallSpinnerFrame] = useState(0);
|
|
37
38
|
const [refreshTrigger, setRefreshTrigger] = useState(0); // Increment to trigger data reload
|
|
39
|
+
const installSpinnerTick = useAnimationTick({
|
|
40
|
+
enabled: isInstallingNodeLlama,
|
|
41
|
+
intervalMs: 80,
|
|
42
|
+
});
|
|
43
|
+
const installSpinnerFrame = installSpinnerTick % BRAILLE_SPINNER_FRAMES.length;
|
|
38
44
|
// Custom path input state
|
|
39
45
|
const [customPath, setCustomPath] = useState('');
|
|
40
46
|
// Display name input state
|
|
@@ -68,19 +74,8 @@ const LocalModelWizard = forwardRef(function LocalModelWizard({ isVisible, onCom
|
|
|
68
74
|
setError(null);
|
|
69
75
|
setIsInstallingNodeLlama(false);
|
|
70
76
|
setInstallConfirmIndex(0);
|
|
71
|
-
setInstallSpinnerFrame(0);
|
|
72
77
|
setNodeLlamaChecked(false);
|
|
73
78
|
}, [isVisible]);
|
|
74
|
-
// Spinner animation for installation
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
if (!isInstallingNodeLlama)
|
|
77
|
-
return;
|
|
78
|
-
const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
79
|
-
const interval = setInterval(() => {
|
|
80
|
-
setInstallSpinnerFrame((prev) => (prev + 1) % spinnerFrames.length);
|
|
81
|
-
}, 80);
|
|
82
|
-
return () => clearInterval(interval);
|
|
83
|
-
}, [isInstallingNodeLlama]);
|
|
84
79
|
// Load models when visible or when showAllModels changes
|
|
85
80
|
useEffect(() => {
|
|
86
81
|
if (!isVisible)
|
|
@@ -540,7 +535,7 @@ const LocalModelWizard = forwardRef(function LocalModelWizard({ isVisible, onCom
|
|
|
540
535
|
{ label: 'Yes', description: 'Install now (may take 1-2 minutes)' },
|
|
541
536
|
{ label: 'No', description: 'Go back' },
|
|
542
537
|
];
|
|
543
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "yellow", children: "Dependency Required" }) }), _jsx(Text, { children: "Local model execution requires node-llama-cpp." }), _jsx(Text, { color: "gray", children: "This will compile native bindings for your system." }), isInstallingNodeLlama ? (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", children: [[
|
|
538
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, marginTop: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "yellow", children: "Dependency Required" }) }), _jsx(Text, { children: "Local model execution requires node-llama-cpp." }), _jsx(Text, { color: "gray", children: "This will compile native bindings for your system." }), isInstallingNodeLlama ? (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Box, { children: _jsxs(Text, { color: "cyan", children: [BRAILLE_SPINNER_FRAMES[installSpinnerFrame], " Installing node-llama-cpp (compiling native bindings)..."] }) }), _jsx(Text, { color: "gray", children: "This may take 1-2 minutes." })] })) : (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, marginBottom: 1, children: _jsx(Text, { children: "Install node-llama-cpp now?" }) }), options.map((option, idx) => (_jsxs(Box, { children: [_jsxs(Text, { color: idx === installConfirmIndex ? 'cyan' : 'white', children: [idx === installConfirmIndex ? '❯ ' : ' ', option.label] }), idx === installConfirmIndex && (_jsxs(Text, { color: "gray", children: [" - ", option.description] }))] }, option.label)))] })), error && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "red", children: error }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: isInstallingNodeLlama
|
|
544
539
|
? 'Please wait...'
|
|
545
540
|
: '↑↓ navigate • Enter select • Esc cancel' }) })] }));
|
|
546
541
|
}
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
import type { DiffDisplayData, FileDisplayData } from '@dexto/core';
|
|
9
9
|
interface DiffPreviewProps {
|
|
10
10
|
data: DiffDisplayData;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/** Optional header override (useful for plan tools, etc.) */
|
|
12
|
+
header?: string;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Enhanced diff preview for edit_file and write_file (overwrite) approval
|
|
16
16
|
* Shows full diff with line backgrounds, hunk collapsing, and word-level highlighting
|
|
17
17
|
*/
|
|
18
|
-
export declare function DiffPreview({ data,
|
|
18
|
+
export declare function DiffPreview({ data, header }: DiffPreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
19
19
|
interface CreateFilePreviewProps {
|
|
20
20
|
data: FileDisplayData;
|
|
21
21
|
/** Custom header text (defaults to "Create file") */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreviewRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/FilePreviewRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgBpE,UAAU,gBAAgB;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,
|
|
1
|
+
{"version":3,"file":"FilePreviewRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/FilePreviewRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgBpE,UAAU,gBAAgB;IACtB,IAAI,EAAE,eAAe,CAAC;IACtB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAiG7D;AAMD,UAAU,sBAAsB;IAC5B,IAAI,EAAE,eAAe,CAAC;IACtB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,sBAAsB,2CAqDzE"}
|
|
@@ -14,7 +14,7 @@ import { parseUnifiedDiff, findLinePairs, computeWordDiff, getLineNumWidth, form
|
|
|
14
14
|
* Enhanced diff preview for edit_file and write_file (overwrite) approval
|
|
15
15
|
* Shows full diff with line backgrounds, hunk collapsing, and word-level highlighting
|
|
16
16
|
*/
|
|
17
|
-
export function DiffPreview({ data,
|
|
17
|
+
export function DiffPreview({ data, header }) {
|
|
18
18
|
const { unified, filename } = data;
|
|
19
19
|
const hunks = parseUnifiedDiff(unified);
|
|
20
20
|
// Calculate max line number for width
|
|
@@ -27,7 +27,7 @@ export function DiffPreview({ data, headerType }) {
|
|
|
27
27
|
const lineNumWidth = getLineNumWidth(maxLineNum);
|
|
28
28
|
// Find line pairs for word-level diff
|
|
29
29
|
const allLinePairs = hunks.map((hunk) => findLinePairs(hunk.lines));
|
|
30
|
-
const headerText =
|
|
30
|
+
const headerText = header ?? data.title ?? 'Update file';
|
|
31
31
|
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { color: "cyan", bold: true, children: headerText }) }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { children: makeRelativePath(filename) }) }), hunks.map((hunk, hunkIndex) => {
|
|
32
32
|
const linePairs = allLinePairs[hunkIndex];
|
|
33
33
|
const processedIndices = new Set();
|
|
@@ -54,13 +54,14 @@ export function DiffPreview({ data, headerType }) {
|
|
|
54
54
|
* Preview for write_file (new file creation) or plan review
|
|
55
55
|
* Shows full file content with line numbers, white text
|
|
56
56
|
*/
|
|
57
|
-
export function CreateFilePreview({ data, header
|
|
57
|
+
export function CreateFilePreview({ data, header }) {
|
|
58
58
|
const { path, content, lineCount } = data;
|
|
59
|
+
const headerText = header ?? data.title ?? 'Create file';
|
|
59
60
|
if (!content) {
|
|
60
61
|
// Fallback if content not provided
|
|
61
|
-
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { color: "cyan", bold: true, children:
|
|
62
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { color: "cyan", bold: true, children: headerText }) }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { children: makeRelativePath(path) }), lineCount && _jsxs(Text, { color: "gray", children: [lineCount, " lines"] })] })] }));
|
|
62
63
|
}
|
|
63
64
|
const lines = content.split('\n');
|
|
64
65
|
const lineNumWidth = getLineNumWidth(lines.length);
|
|
65
|
-
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { color: "cyan", bold: true, children:
|
|
66
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { color: "cyan", bold: true, children: headerText }) }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Box, { marginBottom: 0, children: _jsx(Text, { children: makeRelativePath(path) }) }), lines.map((line, index) => (_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: formatLineNum(index + 1, lineNumWidth) }), _jsxs(Text, { children: [' ', line] })] }, index)))] })] }));
|
|
66
67
|
}
|
|
@@ -9,11 +9,13 @@ import type { FileDisplayData } from '@dexto/core';
|
|
|
9
9
|
interface FileRendererProps {
|
|
10
10
|
/** File display data from tool result */
|
|
11
11
|
data: FileDisplayData;
|
|
12
|
+
/** Maximum lines of content to display (default: 20) */
|
|
13
|
+
maxLines?: number;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Renders file operation status.
|
|
15
17
|
* Uses ⎿ character for continuation lines.
|
|
16
18
|
*/
|
|
17
|
-
export declare function FileRenderer({ data }: FileRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function FileRenderer({ data, maxLines }: FileRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
18
20
|
export {};
|
|
19
21
|
//# sourceMappingURL=FileRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/FileRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"FileRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/FileRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,UAAU,iBAAiB;IACvB,yCAAyC;IACzC,IAAI,EAAE,eAAe,CAAC;IACtB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,QAAa,EAAE,EAAE,iBAAiB,2CA2EtE"}
|
|
@@ -1,25 +1,36 @@
|
|
|
1
|
-
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Text } from 'ink';
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { makeRelativePath } from '../../utils/messageFormatting.js';
|
|
4
|
+
import { formatLineNum, getLineNumWidth } from './diff-shared.js';
|
|
3
5
|
/**
|
|
4
6
|
* Renders file operation status.
|
|
5
7
|
* Uses ⎿ character for continuation lines.
|
|
6
8
|
*/
|
|
7
|
-
export function FileRenderer({ data }) {
|
|
8
|
-
const { operation, lineCount } = data;
|
|
9
|
+
export function FileRenderer({ data, maxLines = 20 }) {
|
|
10
|
+
const { operation, lineCount, path, content } = data;
|
|
11
|
+
const relativePath = makeRelativePath(path);
|
|
9
12
|
// Format based on operation type
|
|
10
13
|
if (operation === 'read') {
|
|
11
14
|
// Format: "Read N lines"
|
|
12
15
|
const lineText = lineCount !== undefined ? `${lineCount} lines` : 'file';
|
|
13
|
-
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', "Read ", lineText] }));
|
|
16
|
+
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', "Read ", lineText, " from ", relativePath] }));
|
|
14
17
|
}
|
|
15
18
|
// For write/create operations
|
|
16
19
|
if (operation === 'write' || operation === 'create') {
|
|
20
|
+
const verb = operation === 'create' ? 'Created' : 'Wrote';
|
|
21
|
+
if (operation === 'create' && content) {
|
|
22
|
+
const lines = content.split('\n');
|
|
23
|
+
const displayLines = lines.slice(0, maxLines);
|
|
24
|
+
const truncatedCount = lines.length - displayLines.length;
|
|
25
|
+
const lineNumWidth = getLineNumWidth(lines.length);
|
|
26
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: ' ⎿ ' }), _jsx(Text, { children: relativePath }), _jsx(Text, { color: "green", children: " (created)" })] }), _jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [displayLines.map((line, index) => (_jsxs(Box, { children: [_jsx(Text, { color: "gray", children: formatLineNum(index + 1, lineNumWidth) }), _jsxs(Text, { wrap: "wrap", children: [' ', line] })] }, index))), truncatedCount > 0 && (_jsxs(Text, { color: "gray", children: ["... +", truncatedCount, " lines"] }))] })] }));
|
|
27
|
+
}
|
|
17
28
|
const lineText = lineCount !== undefined ? `${lineCount} lines` : 'content';
|
|
18
|
-
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', "
|
|
29
|
+
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', verb, " ", lineText, " to ", relativePath] }));
|
|
19
30
|
}
|
|
20
31
|
// Delete operation
|
|
21
32
|
if (operation === 'delete') {
|
|
22
|
-
return _jsxs(Text, { color: "gray", children: [' ⎿ ', "Deleted
|
|
33
|
+
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', "Deleted ", relativePath] }));
|
|
23
34
|
}
|
|
24
35
|
// Fallback
|
|
25
36
|
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', operation] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShellRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/ShellRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,UAAU,kBAAkB;IACxB,0CAA0C;IAC1C,IAAI,EAAE,gBAAgB,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,QAAY,EAAE,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"ShellRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/ShellRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,UAAU,kBAAkB;IACxB,0CAA0C;IAC1C,IAAI,EAAE,gBAAgB,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,QAAY,EAAE,EAAE,kBAAkB,2CAqCvE"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
3
|
/**
|
|
4
4
|
* Renders shell command result with output.
|
|
@@ -6,20 +6,10 @@ import { Box, Text } from 'ink';
|
|
|
6
6
|
* Shows just the output, "(No content)" for empty results.
|
|
7
7
|
*/
|
|
8
8
|
export function ShellRenderer({ data, maxLines = 5 }) {
|
|
9
|
-
//
|
|
10
|
-
const output = data.stdout
|
|
11
|
-
const
|
|
12
|
-
const displayLines =
|
|
13
|
-
const truncatedCount =
|
|
14
|
-
|
|
15
|
-
if (lines.length === 0) {
|
|
16
|
-
return _jsxs(Text, { color: "gray", children: [' ⎿ ', "(No content)"] });
|
|
17
|
-
}
|
|
18
|
-
// Single line output - show inline
|
|
19
|
-
if (lines.length === 1 && lines[0]) {
|
|
20
|
-
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', lines[0]] }));
|
|
21
|
-
}
|
|
22
|
-
// Multi-line output
|
|
23
|
-
// TODO: Add ctrl+o expansion to show full output
|
|
24
|
-
return (_jsxs(Box, { flexDirection: "column", children: [displayLines.map((line, i) => (_jsxs(Text, { color: "gray", wrap: "truncate", children: [i === 0 ? ' ⎿ ' : ' ', line] }, i))), truncatedCount > 0 && (_jsxs(Text, { color: "gray", children: [' ', "+", truncatedCount, " lines"] }))] }));
|
|
9
|
+
// Prefer stdout; fall back to stderr if stdout is empty/undefined
|
|
10
|
+
const output = data.stdout && data.stdout.length > 0 ? data.stdout : data.stderr || '';
|
|
11
|
+
const outputLines = output.split('\n').filter((line) => line.length > 0);
|
|
12
|
+
const displayLines = outputLines.slice(0, maxLines);
|
|
13
|
+
const truncatedCount = outputLines.length - displayLines.length;
|
|
14
|
+
return (_jsxs(Box, { flexDirection: "column", children: [data.isBackground && _jsxs(Text, { color: "gray", children: [' ', "(background)"] }), outputLines.length === 0 ? (_jsxs(Text, { color: "gray", children: [' ', "(No output)"] })) : (_jsxs(_Fragment, { children: [displayLines.map((line, i) => (_jsxs(Text, { color: "gray", wrap: "truncate", children: [' ', line] }, i))), truncatedCount > 0 && (_jsxs(Text, { color: "gray", children: [' ', "+", truncatedCount, " lines"] }))] })), data.exitCode !== 0 && (_jsxs(Text, { color: "red", children: [' ', "exit code: ", data.exitCode] }))] }));
|
|
25
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/index.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAQhE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE1E,UAAU,uBAAuB;IAC7B,yDAAyD;IACzD,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,qDAAqD;IACrD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/renderers/index.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAQhE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE1E,UAAU,uBAAuB;IAC7B,yDAAyD;IACzD,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,qDAAqD;IACrD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,uBAAuB,2CAkCzF"}
|
|
@@ -28,7 +28,7 @@ export function ToolResultRenderer({ display, content, maxLines }) {
|
|
|
28
28
|
case 'search':
|
|
29
29
|
return (_jsx(SearchRenderer, { data: displayData, ...(maxLines !== undefined && { maxMatches: maxLines }) }));
|
|
30
30
|
case 'file':
|
|
31
|
-
return _jsx(FileRenderer, { data: displayData });
|
|
31
|
+
return (_jsx(FileRenderer, { data: displayData, ...(maxLines !== undefined && { maxLines }) }));
|
|
32
32
|
case 'generic':
|
|
33
33
|
default:
|
|
34
34
|
return (_jsx(GenericRenderer, { content: content, ...(maxLines !== undefined && { maxLines }) }));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface FocusOverlayFrameProps {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
}
|
|
5
|
+
export declare function FocusOverlayFrame({ children }: FocusOverlayFrameProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=FocusOverlayFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FocusOverlayFrame.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/shared/FocusOverlayFrame.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,sBAAsB;IAC5B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE,sBAAsB,2CAarE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
|
|
4
|
+
export function FocusOverlayFrame({ children }) {
|
|
5
|
+
const { columns } = useTerminalSize();
|
|
6
|
+
const divider = '─'.repeat(Math.max(0, columns));
|
|
7
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsx(Text, { color: "gray", children: divider }), _jsx(Box, { paddingX: 1, flexDirection: "column", children: children }), _jsx(Text, { color: "gray", children: divider })] }));
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HintBar.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/shared/HintBar.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE,YAAY,2CAOjE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from 'ink';
|
|
3
|
+
export function HintBar({ hints, separator = ' • ' }) {
|
|
4
|
+
const line = hints.filter(Boolean).join(separator);
|
|
5
|
+
return (_jsx(Text, { color: "gray", wrap: "truncate-end", children: line }));
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinnerFrames.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/constants/spinnerFrames.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,6DAA8D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const BRAILLE_SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/constants/tips.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/constants/tips.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,IAAI,EAAE,MAAM,EA4CxB,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC"}
|
|
@@ -18,6 +18,7 @@ export const tips = [
|
|
|
18
18
|
'Use /prompts to browse, add and delete custom prompts…',
|
|
19
19
|
'Use /log to change logging verbosity…',
|
|
20
20
|
'Use /clear to clear the session context…',
|
|
21
|
+
'Use /sounds to customize notification sounds…',
|
|
21
22
|
'Use /exit or /quit to close dexto…',
|
|
22
23
|
'Use /docs to access documentation…',
|
|
23
24
|
'Use /copy to copy the previous response…',
|
|
@@ -31,7 +32,7 @@ export const tips = [
|
|
|
31
32
|
'Press Escape to close overlays and menus…',
|
|
32
33
|
'Use Up/Down arrows to navigate command history…',
|
|
33
34
|
'Press Enter to submit your message…',
|
|
34
|
-
'Press Ctrl+T to show/hide the
|
|
35
|
+
'Press Ctrl+T to show/hide the todo list…',
|
|
35
36
|
'Press Ctrl+R to search previous prompts…',
|
|
36
37
|
'Press Shift+Enter to insert a new line…',
|
|
37
38
|
// Feature tips
|
|
@@ -22,6 +22,8 @@ interface InputContainerProps {
|
|
|
22
22
|
input: InputState;
|
|
23
23
|
ui: UIState;
|
|
24
24
|
session: SessionState;
|
|
25
|
+
/** If provided, auto-submits once when the UI is ready */
|
|
26
|
+
initialPrompt?: string | undefined;
|
|
25
27
|
approval: ApprovalRequest | null;
|
|
26
28
|
/** Queued messages waiting to be processed */
|
|
27
29
|
queuedMessages: QueuedMessage[];
|
|
@@ -44,6 +46,8 @@ interface InputContainerProps {
|
|
|
44
46
|
setTodos: React.Dispatch<React.SetStateAction<TodoItem[]>>;
|
|
45
47
|
agent: DextoAgent;
|
|
46
48
|
inputService: InputService;
|
|
49
|
+
/** Source agent config file path (if available) */
|
|
50
|
+
configFilePath: string | null;
|
|
47
51
|
/** Optional keyboard scroll handler (for alternate buffer mode) */
|
|
48
52
|
onKeyboardScroll?: (direction: 'up' | 'down') => void;
|
|
49
53
|
/** Whether to stream chunks or wait for complete response (default: true) */
|