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.
Files changed (224) hide show
  1. package/README.md +3 -3
  2. package/dist/agents/agent-template.yml +2 -2
  3. package/dist/agents/coding-agent/README.md +10 -10
  4. package/dist/agents/coding-agent/coding-agent.yml +84 -83
  5. package/dist/agents/default-agent.yml +32 -47
  6. package/dist/agents/explore-agent/explore-agent.yml +3 -6
  7. package/dist/agents/image-editor-agent/image-editor-agent.yml +1 -1
  8. package/dist/agents/nano-banana-agent/nano-banana-agent.yml +1 -1
  9. package/dist/agents/podcast-agent/podcast-agent.yml +1 -1
  10. package/dist/agents/product-name-researcher/product-name-researcher.yml +1 -1
  11. package/dist/agents/sora-video-agent/sora-video-agent.yml +4 -6
  12. package/dist/agents/triage-demo/triage-agent.yml +1 -1
  13. package/dist/analytics/events.d.ts +1 -1
  14. package/dist/analytics/events.d.ts.map +1 -1
  15. package/dist/api/mcp/tool-aggregation-handler.d.ts +2 -2
  16. package/dist/api/server-hono.d.ts +2 -2
  17. package/dist/api/server-hono.d.ts.map +1 -1
  18. package/dist/api/server-hono.js +37 -60
  19. package/dist/cli/approval/cli-approval-handler.d.ts +10 -3
  20. package/dist/cli/approval/cli-approval-handler.d.ts.map +1 -1
  21. package/dist/cli/approval/cli-approval-handler.js +1 -1
  22. package/dist/cli/assets/sounds/SOURCES.md +35 -0
  23. package/dist/cli/assets/sounds/boot.wav +0 -0
  24. package/dist/cli/assets/sounds/chime.wav +0 -0
  25. package/dist/cli/assets/sounds/coin.wav +0 -0
  26. package/dist/cli/assets/sounds/confirm.wav +0 -0
  27. package/dist/cli/assets/sounds/levelup.wav +0 -0
  28. package/dist/cli/assets/sounds/ping.wav +0 -0
  29. package/dist/cli/assets/sounds/powerup.wav +0 -0
  30. package/dist/cli/assets/sounds/startup.wav +0 -0
  31. package/dist/cli/assets/sounds/success.wav +0 -0
  32. package/dist/cli/assets/sounds/treasure.wav +0 -0
  33. package/dist/cli/assets/sounds/win.wav +0 -0
  34. package/dist/cli/commands/create-app.d.ts +1 -11
  35. package/dist/cli/commands/create-app.d.ts.map +1 -1
  36. package/dist/cli/commands/create-app.js +21 -545
  37. package/dist/cli/commands/create-image.d.ts.map +1 -1
  38. package/dist/cli/commands/create-image.js +54 -53
  39. package/dist/cli/commands/image.d.ts +52 -0
  40. package/dist/cli/commands/image.d.ts.map +1 -0
  41. package/dist/cli/commands/image.js +118 -0
  42. package/dist/cli/commands/index.d.ts +2 -1
  43. package/dist/cli/commands/index.d.ts.map +1 -1
  44. package/dist/cli/commands/index.js +3 -1
  45. package/dist/cli/commands/init-app.d.ts +4 -8
  46. package/dist/cli/commands/init-app.d.ts.map +1 -1
  47. package/dist/cli/commands/init-app.js +37 -161
  48. package/dist/cli/commands/interactive-commands/command-parser.d.ts +2 -0
  49. package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
  50. package/dist/cli/commands/interactive-commands/commands.d.ts +1 -1
  51. package/dist/cli/commands/interactive-commands/commands.d.ts.map +1 -1
  52. package/dist/cli/commands/interactive-commands/commands.js +2 -2
  53. package/dist/cli/commands/interactive-commands/exit-handler.d.ts +12 -0
  54. package/dist/cli/commands/interactive-commands/exit-handler.d.ts.map +1 -0
  55. package/dist/cli/commands/interactive-commands/exit-handler.js +20 -0
  56. package/dist/cli/commands/interactive-commands/exit-stats.d.ts +24 -0
  57. package/dist/cli/commands/interactive-commands/exit-stats.d.ts.map +1 -0
  58. package/dist/cli/commands/interactive-commands/exit-stats.js +17 -0
  59. package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
  60. package/dist/cli/commands/interactive-commands/general-commands.js +55 -5
  61. package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
  62. package/dist/cli/commands/interactive-commands/prompt-commands.js +14 -74
  63. package/dist/cli/commands/interactive-commands/session/index.d.ts +2 -1
  64. package/dist/cli/commands/interactive-commands/session/index.d.ts.map +1 -1
  65. package/dist/cli/commands/interactive-commands/session/index.js +2 -1
  66. package/dist/cli/commands/interactive-commands/session/session-commands.d.ts +2 -2
  67. package/dist/cli/commands/interactive-commands/session/session-commands.d.ts.map +1 -1
  68. package/dist/cli/commands/interactive-commands/session/session-commands.js +2 -4
  69. package/dist/cli/commands/interactive-commands/system/system-commands.d.ts +1 -13
  70. package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
  71. package/dist/cli/commands/interactive-commands/system/system-commands.js +52 -83
  72. package/dist/cli/commands/plugin.d.ts +4 -4
  73. package/dist/cli/commands/sync-agents.d.ts +2 -12
  74. package/dist/cli/commands/sync-agents.d.ts.map +1 -1
  75. package/dist/cli/commands/sync-agents.js +2 -50
  76. package/dist/cli/ink-cli/InkCLIRefactored.d.ts +7 -1
  77. package/dist/cli/ink-cli/InkCLIRefactored.d.ts.map +1 -1
  78. package/dist/cli/ink-cli/InkCLIRefactored.js +138 -27
  79. package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts +2 -2
  80. package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts.map +1 -1
  81. package/dist/cli/ink-cli/components/ApprovalPrompt.js +85 -30
  82. package/dist/cli/ink-cli/components/BackgroundTasksPanel.js +1 -1
  83. package/dist/cli/ink-cli/components/ElicitationForm.d.ts +5 -3
  84. package/dist/cli/ink-cli/components/ElicitationForm.d.ts.map +1 -1
  85. package/dist/cli/ink-cli/components/ElicitationForm.js +414 -180
  86. package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -1
  87. package/dist/cli/ink-cli/components/Footer.js +1 -2
  88. package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
  89. package/dist/cli/ink-cli/components/ResourceAutocomplete.js +20 -11
  90. package/dist/cli/ink-cli/components/SlashCommandAutocomplete.d.ts.map +1 -1
  91. package/dist/cli/ink-cli/components/SlashCommandAutocomplete.js +47 -67
  92. package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
  93. package/dist/cli/ink-cli/components/StatusBar.js +20 -10
  94. package/dist/cli/ink-cli/components/TodoPanel.js +1 -1
  95. package/dist/cli/ink-cli/components/base/BaseSelector.d.ts +2 -1
  96. package/dist/cli/ink-cli/components/base/BaseSelector.d.ts.map +1 -1
  97. package/dist/cli/ink-cli/components/base/BaseSelector.js +37 -27
  98. package/dist/cli/ink-cli/components/chat/Header.d.ts.map +1 -1
  99. package/dist/cli/ink-cli/components/chat/Header.js +1 -1
  100. package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
  101. package/dist/cli/ink-cli/components/chat/MessageItem.js +3 -1
  102. package/dist/cli/ink-cli/components/chat/ToolIcon.d.ts.map +1 -1
  103. package/dist/cli/ink-cli/components/chat/ToolIcon.js +5 -15
  104. package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.js +1 -1
  105. package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -1
  106. package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +1 -1
  107. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts +3 -1
  108. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -1
  109. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +5 -3
  110. package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts +3 -1
  111. package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
  112. package/dist/cli/ink-cli/components/modes/StaticCLI.js +10 -3
  113. package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts +13 -0
  114. package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts.map +1 -0
  115. package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.js +60 -0
  116. package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +1 -1
  117. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
  118. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +213 -100
  119. package/dist/cli/ink-cli/components/overlays/PromptList.d.ts.map +1 -1
  120. package/dist/cli/ink-cli/components/overlays/PromptList.js +12 -16
  121. package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts +21 -0
  122. package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts.map +1 -0
  123. package/dist/cli/ink-cli/components/overlays/SoundsSelector.js +566 -0
  124. package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts +1 -1
  125. package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts.map +1 -1
  126. package/dist/cli/ink-cli/components/overlays/ToolBrowser.js +100 -45
  127. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts.map +1 -1
  128. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.js +8 -13
  129. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts +3 -3
  130. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts.map +1 -1
  131. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.js +6 -5
  132. package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts +3 -1
  133. package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts.map +1 -1
  134. package/dist/cli/ink-cli/components/renderers/FileRenderer.js +18 -7
  135. package/dist/cli/ink-cli/components/renderers/ShellRenderer.d.ts.map +1 -1
  136. package/dist/cli/ink-cli/components/renderers/ShellRenderer.js +7 -17
  137. package/dist/cli/ink-cli/components/renderers/index.d.ts.map +1 -1
  138. package/dist/cli/ink-cli/components/renderers/index.js +1 -1
  139. package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts +7 -0
  140. package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts.map +1 -0
  141. package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.js +8 -0
  142. package/dist/cli/ink-cli/components/shared/HintBar.d.ts +6 -0
  143. package/dist/cli/ink-cli/components/shared/HintBar.d.ts.map +1 -0
  144. package/dist/cli/ink-cli/components/shared/HintBar.js +6 -0
  145. package/dist/cli/ink-cli/constants/spinnerFrames.d.ts +2 -0
  146. package/dist/cli/ink-cli/constants/spinnerFrames.d.ts.map +1 -0
  147. package/dist/cli/ink-cli/constants/spinnerFrames.js +1 -0
  148. package/dist/cli/ink-cli/constants/tips.d.ts.map +1 -1
  149. package/dist/cli/ink-cli/constants/tips.js +2 -1
  150. package/dist/cli/ink-cli/containers/InputContainer.d.ts +4 -0
  151. package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
  152. package/dist/cli/ink-cli/containers/InputContainer.js +47 -21
  153. package/dist/cli/ink-cli/containers/OverlayContainer.d.ts +2 -0
  154. package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
  155. package/dist/cli/ink-cli/containers/OverlayContainer.js +101 -40
  156. package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
  157. package/dist/cli/ink-cli/hooks/useAgentEvents.js +15 -16
  158. package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts +11 -0
  159. package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts.map +1 -0
  160. package/dist/cli/ink-cli/hooks/useAnimationTick.js +54 -0
  161. package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
  162. package/dist/cli/ink-cli/hooks/useCLIState.js +1 -0
  163. package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts.map +1 -1
  164. package/dist/cli/ink-cli/hooks/useTokenCounter.js +7 -4
  165. package/dist/cli/ink-cli/services/CommandService.d.ts +1 -1
  166. package/dist/cli/ink-cli/services/CommandService.d.ts.map +1 -1
  167. package/dist/cli/ink-cli/services/CommandService.js +2 -2
  168. package/dist/cli/ink-cli/services/processStream.d.ts +2 -2
  169. package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
  170. package/dist/cli/ink-cli/services/processStream.js +27 -19
  171. package/dist/cli/ink-cli/state/initialState.d.ts.map +1 -1
  172. package/dist/cli/ink-cli/state/initialState.js +1 -0
  173. package/dist/cli/ink-cli/state/types.d.ts +15 -3
  174. package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
  175. package/dist/cli/ink-cli/utils/commandOverlays.d.ts.map +1 -1
  176. package/dist/cli/ink-cli/utils/commandOverlays.js +1 -0
  177. package/dist/cli/ink-cli/utils/elicitationSchema.d.ts +11 -0
  178. package/dist/cli/ink-cli/utils/elicitationSchema.d.ts.map +1 -0
  179. package/dist/cli/ink-cli/utils/elicitationSchema.js +80 -0
  180. package/dist/cli/ink-cli/utils/index.d.ts +1 -1
  181. package/dist/cli/ink-cli/utils/index.d.ts.map +1 -1
  182. package/dist/cli/ink-cli/utils/index.js +1 -1
  183. package/dist/cli/ink-cli/utils/messageFormatting.d.ts +10 -19
  184. package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
  185. package/dist/cli/ink-cli/utils/messageFormatting.js +43 -262
  186. package/dist/cli/ink-cli/utils/overlayPresentation.d.ts +19 -0
  187. package/dist/cli/ink-cli/utils/overlayPresentation.d.ts.map +1 -0
  188. package/dist/cli/ink-cli/utils/overlayPresentation.js +33 -0
  189. package/dist/cli/ink-cli/utils/overlaySizing.d.ts +19 -0
  190. package/dist/cli/ink-cli/utils/overlaySizing.d.ts.map +1 -0
  191. package/dist/cli/ink-cli/utils/overlaySizing.js +11 -0
  192. package/dist/cli/ink-cli/utils/soundNotification.d.ts +19 -13
  193. package/dist/cli/ink-cli/utils/soundNotification.d.ts.map +1 -1
  194. package/dist/cli/ink-cli/utils/soundNotification.js +120 -97
  195. package/dist/cli/ink-cli/utils/toolUtils.d.ts.map +1 -1
  196. package/dist/cli/ink-cli/utils/toolUtils.js +2 -9
  197. package/dist/cli/utils/config-validation.d.ts +11 -11
  198. package/dist/cli/utils/config-validation.d.ts.map +1 -1
  199. package/dist/cli/utils/config-validation.js +56 -290
  200. package/dist/cli/utils/image-store.d.ts +16 -0
  201. package/dist/cli/utils/image-store.d.ts.map +1 -0
  202. package/dist/cli/utils/image-store.js +289 -0
  203. package/dist/cli/utils/scaffolding-utils.d.ts +5 -0
  204. package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
  205. package/dist/cli/utils/scaffolding-utils.js +46 -4
  206. package/dist/cli/utils/template-engine.d.ts +28 -16
  207. package/dist/cli/utils/template-engine.d.ts.map +1 -1
  208. package/dist/cli/utils/template-engine.js +339 -479
  209. package/dist/config/cli-overrides.d.ts +4 -3
  210. package/dist/config/cli-overrides.d.ts.map +1 -1
  211. package/dist/config/cli-overrides.js +7 -9
  212. package/dist/index-main.d.ts +2 -0
  213. package/dist/index-main.d.ts.map +1 -0
  214. package/dist/index-main.js +1554 -0
  215. package/dist/index.js +2 -1589
  216. package/dist/utils/session-logger-factory.d.ts +3 -0
  217. package/dist/utils/session-logger-factory.d.ts.map +1 -0
  218. package/dist/utils/session-logger-factory.js +34 -0
  219. package/dist/webui/assets/{index-Cz2z7NQ8.js → index-CKhumsZA.js} +231 -231
  220. package/dist/webui/index.html +1 -1
  221. package/package.json +11 -8
  222. package/dist/cli/cli-subscriber.d.ts +0 -45
  223. package/dist/cli/cli-subscriber.d.ts.map +0 -1
  224. 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 Internal)
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
- const MAX_VISIBLE_ITEMS = 12;
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 [selectedIndex, setSelectedIndex] = useState(0);
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(selectedIndex);
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 = selectedIndex;
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
- setSelectedIndex(0);
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' : 'internal',
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: internal tools first, then MCP tools
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 === 'internal' ? -1 : 1;
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
- // Adjust selected index when filter changes
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
- if (selectedIndex < scrollOffset) {
153
- setScrollOffset(selectedIndex);
154
- }
155
- else if (selectedIndex >= scrollOffset + MAX_VISIBLE_ITEMS) {
156
- setScrollOffset(selectedIndex - MAX_VISIBLE_ITEMS + 1);
157
- }
158
- }, [selectedIndex, scrollOffset]);
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
- setSelectedIndex(0);
433
- setScrollOffset(0);
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 visibleTools = filteredTools.slice(scrollOffset, scrollOffset + MAX_VISIBLE_ITEMS);
487
- const filteredInternalCount = filteredTools.filter((t) => t.source === 'internal').length;
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
- return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: "Tool Browser" }), _jsxs(Text, { color: "gray", children: [' ', "(", filteredTools.length, " tools: ", filteredInternalCount, " internal,", ' ', filteredMcpCount, " MCP)"] })] }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "\u2191\u2193 navigate \u00B7 Enter options \u00B7 Esc close" }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "Type to search \u00B7 Backspace to delete" }) }), loadError && (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "red", children: loadError }) })), _jsxs(Box, { paddingX: 0, paddingY: 0, marginTop: 1, children: [_jsx(Text, { color: "gray", children: "Search: " }), _jsx(Text, { color: searchQuery ? 'white' : 'gray', children: searchQuery || 'Type to filter...' }), _jsx(Text, { color: "cyan", children: "\u258C" })] }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: '─'.repeat(Math.min(60, columns - 2)) }) }), filteredTools.length === 0 ? (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "No tools match your search" }) })) : (visibleTools.map((tool, visibleIndex) => {
490
- const actualIndex = scrollOffset + visibleIndex;
491
- const isSelected = actualIndex === selectedIndex;
492
- 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 === 'internal' ? 'magenta' : 'blue', children: [' ', "[", tool.source === 'internal' ? 'Internal' : '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));
493
- })), filteredTools.length > MAX_VISIBLE_ITEMS && (_jsx(Box, { paddingX: 0, paddingY: 0, marginTop: 1, children: _jsxs(Text, { color: "gray", children: [scrollOffset > 0 ? '↑ more above' : '', scrollOffset > 0 && scrollOffset + MAX_VISIBLE_ITEMS < filteredTools.length
494
- ? ' | '
495
- : '', scrollOffset + MAX_VISIBLE_ITEMS < filteredTools.length
496
- ? '↓ more below'
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 === 'internal' ? 'magenta' : 'blue', children: [line.source === 'internal' ? 'Internal Tool' : 'MCP Tool', line.serverName ? ` (${line.serverName})` : ''] }));
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;AAClE,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,sGA4/BrB,CAAC;AAEF,eAAe,gBAAgB,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: [['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'][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
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
- /** Header text: "Edit file" or "Overwrite file" */
12
- headerType: 'edit' | 'overwrite';
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, headerType }: DiffPreviewProps): import("react/jsx-runtime").JSX.Element;
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,mDAAmD;IACnD,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC;CACpC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,gBAAgB,2CAiGjE;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,MAAsB,EAAE,EAAE,sBAAsB,2CAoDzF"}
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, headerType }) {
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 = headerType === 'edit' ? 'Edit file' : 'Overwrite file';
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 = 'Create file' }) {
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: header }) }), _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
+ 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: header }) }), _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
+ 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;AAEnD,UAAU,iBAAiB;IACvB,yCAAyC;IACzC,IAAI,EAAE,eAAe,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,iBAAiB,2CAoCvD"}
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: [' ⎿ ', "Wrote ", lineText] }));
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 file"] });
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,2CAwCvE"}
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
- // Use stdout from display data, fall back to stderr if no stdout
10
- const output = data.stdout || data.stderr || '';
11
- const lines = output.split('\n').filter((line) => line.length > 0);
12
- const displayLines = lines.slice(0, maxLines);
13
- const truncatedCount = lines.length - maxLines;
14
- // No output - show "(No content)"
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,2CAgCzF"}
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,6 @@
1
+ export interface HintBarProps {
2
+ hints: readonly string[];
3
+ separator?: string;
4
+ }
5
+ export declare function HintBar({ hints, separator }: HintBarProps): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=HintBar.d.ts.map
@@ -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,2 @@
1
+ export declare const BRAILLE_SPINNER_FRAMES: readonly ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
2
+ //# sourceMappingURL=spinnerFrames.d.ts.map
@@ -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,EA2CxB,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC"}
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 task list…',
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) */