dexto 1.5.7 → 1.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/coding-agent/coding-agent.yml +2 -0
- package/dist/analytics/events.d.ts +1 -1
- package/dist/analytics/events.d.ts.map +1 -1
- package/dist/cli/auth/constants.d.ts +4 -0
- package/dist/cli/auth/constants.d.ts.map +1 -1
- package/dist/cli/auth/constants.js +4 -0
- package/dist/cli/commands/auth/logout.js +2 -2
- package/dist/cli/commands/billing/status.d.ts +3 -1
- package/dist/cli/commands/billing/status.d.ts.map +1 -1
- package/dist/cli/commands/billing/status.js +23 -1
- package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/prompt-commands.js +18 -2
- package/dist/cli/commands/list-agents.d.ts.map +1 -1
- package/dist/cli/commands/list-agents.js +3 -2
- package/dist/cli/commands/setup.d.ts +5 -5
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +766 -207
- package/dist/cli/ink-cli/InkCLIRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/InkCLIRefactored.js +11 -1
- package/dist/cli/ink-cli/components/BackgroundTasksPanel.d.ts +18 -0
- package/dist/cli/ink-cli/components/BackgroundTasksPanel.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/BackgroundTasksPanel.js +48 -0
- package/dist/cli/ink-cli/components/ErrorBoundary.js +1 -1
- package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/Footer.js +4 -4
- package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ResourceAutocomplete.js +150 -41
- package/dist/cli/ink-cli/components/StatusBar.d.ts +3 -1
- package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/StatusBar.js +17 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.js +9 -5
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +2 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.js +2 -1
- package/dist/cli/ink-cli/components/overlays/ContextStatsOverlay.js +1 -1
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/CustomModelWizard.js +8 -4
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/McpRemoveSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts +1 -0
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +144 -41
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts +1 -0
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.js +281 -39
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts +9 -1
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.js +35 -9
- package/dist/cli/ink-cli/containers/InputContainer.js +2 -2
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/OverlayContainer.js +134 -23
- package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useAgentEvents.js +61 -0
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useCLIState.js +3 -0
- package/dist/cli/ink-cli/hooks/useInputOrchestrator.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useInputOrchestrator.js +8 -0
- package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/processStream.js +50 -2
- package/dist/cli/ink-cli/state/initialState.d.ts.map +1 -1
- package/dist/cli/ink-cli/state/initialState.js +3 -0
- package/dist/cli/ink-cli/state/types.d.ts +9 -0
- package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/llm-provider-display.d.ts +3 -0
- package/dist/cli/ink-cli/utils/llm-provider-display.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/llm-provider-display.js +22 -0
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts +4 -6
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.js +77 -9
- package/dist/cli/utils/dexto-auth-check.d.ts +7 -7
- package/dist/cli/utils/dexto-auth-check.d.ts.map +1 -1
- package/dist/cli/utils/dexto-auth-check.js +16 -16
- package/dist/cli/utils/options.js +1 -1
- package/dist/cli/utils/provider-setup.d.ts +2 -2
- package/dist/cli/utils/provider-setup.d.ts.map +1 -1
- package/dist/cli/utils/provider-setup.js +10 -2
- package/dist/config/cli-overrides.js +1 -1
- package/dist/config/effective-llm.d.ts +4 -4
- package/dist/config/effective-llm.d.ts.map +1 -1
- package/dist/config/effective-llm.js +4 -4
- package/dist/index.js +12 -3
- package/dist/webui/assets/{index-Dl3mj53P.js → index-Cz2z7NQ8.js} +74 -74
- package/dist/webui/index.html +1 -1
- package/package.json +7 -7
|
@@ -12,14 +12,15 @@ import { Box, Text } from 'ink';
|
|
|
12
12
|
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
|
|
13
13
|
import { writeToClipboard } from '../../utils/clipboardUtils.js';
|
|
14
14
|
const MAX_VISIBLE_ITEMS = 12;
|
|
15
|
-
const
|
|
15
|
+
const LIST_ACTIONS = ['view', 'config', 'back'];
|
|
16
16
|
/**
|
|
17
17
|
* Tool browser with search and detail views
|
|
18
18
|
*/
|
|
19
|
-
const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent }, ref) {
|
|
19
|
+
const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent, sessionId }, ref) {
|
|
20
20
|
const { columns, rows } = useTerminalSize();
|
|
21
21
|
const [tools, setTools] = useState([]);
|
|
22
22
|
const [isLoading, setIsLoading] = useState(false);
|
|
23
|
+
const [loadError, setLoadError] = useState(null);
|
|
23
24
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
24
25
|
const [searchQuery, setSearchQuery] = useState('');
|
|
25
26
|
const [scrollOffset, setScrollOffset] = useState(0);
|
|
@@ -27,16 +28,33 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
27
28
|
const [selectedTool, setSelectedTool] = useState(null);
|
|
28
29
|
const [detailScrollOffset, setDetailScrollOffset] = useState(0);
|
|
29
30
|
const [copyFeedback, setCopyFeedback] = useState(null);
|
|
31
|
+
const [listActionsIndex, setListActionsIndex] = useState(0);
|
|
32
|
+
const [configIndex, setConfigIndex] = useState(0);
|
|
33
|
+
const [scopeToolName, setScopeToolName] = useState(null);
|
|
34
|
+
const [scopeNextEnabled, setScopeNextEnabled] = useState(true);
|
|
35
|
+
const [scopeTarget, setScopeTarget] = useState('session');
|
|
30
36
|
const selectedIndexRef = useRef(selectedIndex);
|
|
31
37
|
const viewModeRef = useRef(viewMode);
|
|
32
38
|
const detailScrollOffsetRef = useRef(detailScrollOffset);
|
|
33
39
|
const detailMaxScrollOffsetRef = useRef(0);
|
|
34
40
|
const selectedToolRef = useRef(null);
|
|
41
|
+
const toolsRef = useRef([]);
|
|
42
|
+
const listActionsIndexRef = useRef(listActionsIndex);
|
|
43
|
+
const configIndexRef = useRef(configIndex);
|
|
44
|
+
const scopeTargetRef = useRef(scopeTarget);
|
|
45
|
+
const scopeNextEnabledRef = useRef(scopeNextEnabled);
|
|
46
|
+
const scopeToolNameRef = useRef(scopeToolName);
|
|
35
47
|
// Keep refs in sync
|
|
36
48
|
selectedIndexRef.current = selectedIndex;
|
|
37
49
|
viewModeRef.current = viewMode;
|
|
38
50
|
detailScrollOffsetRef.current = detailScrollOffset;
|
|
39
51
|
selectedToolRef.current = selectedTool;
|
|
52
|
+
toolsRef.current = tools;
|
|
53
|
+
listActionsIndexRef.current = listActionsIndex;
|
|
54
|
+
configIndexRef.current = configIndex;
|
|
55
|
+
scopeTargetRef.current = scopeTarget;
|
|
56
|
+
scopeNextEnabledRef.current = scopeNextEnabled;
|
|
57
|
+
scopeToolNameRef.current = scopeToolName;
|
|
40
58
|
// Fetch tools from agent
|
|
41
59
|
useEffect(() => {
|
|
42
60
|
if (!isVisible)
|
|
@@ -48,14 +66,21 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
48
66
|
setScrollOffset(0);
|
|
49
67
|
setViewMode('list');
|
|
50
68
|
setSelectedTool(null);
|
|
69
|
+
setListActionsIndex(0);
|
|
70
|
+
setConfigIndex(0);
|
|
71
|
+
setLoadError(null);
|
|
51
72
|
const fetchTools = async () => {
|
|
52
73
|
try {
|
|
53
|
-
const [allTools, mcpTools] = await Promise.all([
|
|
74
|
+
const [allTools, mcpTools, enabledTools, autoApprovedTools] = await Promise.all([
|
|
54
75
|
agent.getAllTools(),
|
|
55
76
|
agent.getAllMcpTools(),
|
|
77
|
+
agent.getEnabledTools(sessionId || undefined),
|
|
78
|
+
sessionId ? agent.getSessionAutoApproveTools(sessionId) : Promise.resolve([]),
|
|
56
79
|
]);
|
|
57
80
|
const toolList = [];
|
|
58
81
|
const mcpToolNames = new Set(Object.keys(mcpTools));
|
|
82
|
+
const enabledToolNames = new Set(Object.keys(enabledTools));
|
|
83
|
+
const autoApprovedToolNames = new Set(autoApprovedTools ?? []);
|
|
59
84
|
for (const [toolName, toolInfo] of Object.entries(allTools)) {
|
|
60
85
|
const isMcpTool = mcpToolNames.has(toolName) || toolName.startsWith('mcp--');
|
|
61
86
|
// Extract server name from MCP tool name (format: mcp--serverName--toolName)
|
|
@@ -72,6 +97,8 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
72
97
|
source: isMcpTool ? 'mcp' : 'internal',
|
|
73
98
|
serverName,
|
|
74
99
|
inputSchema: toolInfo.parameters,
|
|
100
|
+
isEnabled: enabledToolNames.has(toolName),
|
|
101
|
+
isAutoApproved: autoApprovedToolNames.has(toolName),
|
|
75
102
|
});
|
|
76
103
|
}
|
|
77
104
|
// Sort: internal tools first, then MCP tools
|
|
@@ -84,12 +111,15 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
84
111
|
if (!cancelled) {
|
|
85
112
|
setTools(toolList);
|
|
86
113
|
setIsLoading(false);
|
|
114
|
+
setLoadError(null);
|
|
87
115
|
}
|
|
88
116
|
}
|
|
89
117
|
catch (error) {
|
|
90
118
|
if (!cancelled) {
|
|
119
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
91
120
|
setTools([]);
|
|
92
121
|
setIsLoading(false);
|
|
122
|
+
setLoadError(`Failed to load tools: ${message}`);
|
|
93
123
|
}
|
|
94
124
|
}
|
|
95
125
|
};
|
|
@@ -97,7 +127,7 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
97
127
|
return () => {
|
|
98
128
|
cancelled = true;
|
|
99
129
|
};
|
|
100
|
-
}, [isVisible, agent]);
|
|
130
|
+
}, [isVisible, agent, sessionId]);
|
|
101
131
|
// Filter tools based on search query
|
|
102
132
|
const filteredTools = useMemo(() => {
|
|
103
133
|
if (!searchQuery.trim()) {
|
|
@@ -126,14 +156,118 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
126
156
|
setScrollOffset(selectedIndex - MAX_VISIBLE_ITEMS + 1);
|
|
127
157
|
}
|
|
128
158
|
}, [selectedIndex, scrollOffset]);
|
|
129
|
-
|
|
130
|
-
|
|
159
|
+
const openListActions = (tool) => {
|
|
160
|
+
setSelectedTool(tool);
|
|
161
|
+
setListActionsIndex(0);
|
|
162
|
+
setViewMode('list-actions');
|
|
163
|
+
};
|
|
164
|
+
const openToolDetails = (tool) => {
|
|
131
165
|
setSelectedTool(tool);
|
|
132
166
|
setViewMode('detail');
|
|
133
167
|
setDetailScrollOffset(0);
|
|
134
168
|
};
|
|
135
|
-
|
|
136
|
-
|
|
169
|
+
const openConfigMenu = (tool) => {
|
|
170
|
+
setSelectedTool(tool);
|
|
171
|
+
setConfigIndex(0);
|
|
172
|
+
setViewMode('config');
|
|
173
|
+
};
|
|
174
|
+
const openScopePrompt = (tool) => {
|
|
175
|
+
const nextEnabled = !tool.isEnabled;
|
|
176
|
+
const nextScope = sessionId ? 'session' : 'global';
|
|
177
|
+
setSelectedTool(tool);
|
|
178
|
+
setScopeToolName(tool.name);
|
|
179
|
+
setScopeNextEnabled(nextEnabled);
|
|
180
|
+
setScopeTarget(nextScope);
|
|
181
|
+
setViewMode('scope');
|
|
182
|
+
scopeToolNameRef.current = tool.name;
|
|
183
|
+
scopeNextEnabledRef.current = nextEnabled;
|
|
184
|
+
scopeTargetRef.current = nextScope;
|
|
185
|
+
};
|
|
186
|
+
const closeScopePrompt = () => {
|
|
187
|
+
setViewMode('config');
|
|
188
|
+
setScopeToolName(null);
|
|
189
|
+
};
|
|
190
|
+
const applyToolToggle = async (overrideTarget) => {
|
|
191
|
+
const targetToolName = scopeToolNameRef.current ?? scopeToolName ?? selectedToolRef.current?.name;
|
|
192
|
+
if (!targetToolName)
|
|
193
|
+
return;
|
|
194
|
+
const effectiveTarget = overrideTarget ?? scopeTargetRef.current;
|
|
195
|
+
const nextEnabled = scopeNextEnabledRef.current;
|
|
196
|
+
const previousTools = toolsRef.current;
|
|
197
|
+
const updatedTools = previousTools.map((tool) => {
|
|
198
|
+
if (tool.name !== targetToolName) {
|
|
199
|
+
return tool;
|
|
200
|
+
}
|
|
201
|
+
const updatedTool = { ...tool, isEnabled: nextEnabled };
|
|
202
|
+
if (!nextEnabled && tool.isAutoApproved) {
|
|
203
|
+
updatedTool.isAutoApproved = false;
|
|
204
|
+
}
|
|
205
|
+
return updatedTool;
|
|
206
|
+
});
|
|
207
|
+
setTools(updatedTools);
|
|
208
|
+
const updatedSelected = updatedTools.find((tool) => tool.name === targetToolName) ?? null;
|
|
209
|
+
setSelectedTool(updatedSelected);
|
|
210
|
+
const autoApprovedTools = updatedTools
|
|
211
|
+
.filter((tool) => tool.isAutoApproved)
|
|
212
|
+
.map((tool) => tool.name);
|
|
213
|
+
if (sessionId) {
|
|
214
|
+
agent.setSessionAutoApproveTools(sessionId, autoApprovedTools);
|
|
215
|
+
}
|
|
216
|
+
const disabledTools = updatedTools
|
|
217
|
+
.filter((tool) => !tool.isEnabled)
|
|
218
|
+
.map((tool) => tool.name);
|
|
219
|
+
if (effectiveTarget === 'session' && sessionId) {
|
|
220
|
+
agent.setSessionDisabledTools(sessionId, disabledTools);
|
|
221
|
+
}
|
|
222
|
+
else if (effectiveTarget === 'global') {
|
|
223
|
+
try {
|
|
224
|
+
const { updateAgentPreferences, saveAgentPreferences, agentPreferencesExist } = await import('@dexto/agent-management');
|
|
225
|
+
if (agentPreferencesExist(agent.config.agentId)) {
|
|
226
|
+
await updateAgentPreferences(agent.config.agentId, {
|
|
227
|
+
tools: { disabled: disabledTools },
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
await saveAgentPreferences(agent.config.agentId, {
|
|
232
|
+
tools: { disabled: disabledTools },
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
agent.setGlobalDisabledTools(disabledTools);
|
|
236
|
+
}
|
|
237
|
+
catch (_error) {
|
|
238
|
+
// If we can't persist, still keep session state so user sees effect
|
|
239
|
+
if (sessionId) {
|
|
240
|
+
agent.setSessionDisabledTools(sessionId, disabledTools);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
setTools(previousTools);
|
|
244
|
+
setSelectedTool(previousTools.find((tool) => tool.name === targetToolName) ?? null);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
closeScopePrompt();
|
|
249
|
+
};
|
|
250
|
+
const toggleAutoApprove = () => {
|
|
251
|
+
if (!sessionId)
|
|
252
|
+
return;
|
|
253
|
+
const updatedTools = toolsRef.current.map((tool) => tool.name === selectedToolRef.current?.name
|
|
254
|
+
? { ...tool, isAutoApproved: !tool.isAutoApproved }
|
|
255
|
+
: tool);
|
|
256
|
+
const updatedSelected = updatedTools.find((tool) => tool.name === selectedToolRef.current?.name);
|
|
257
|
+
setTools(updatedTools);
|
|
258
|
+
setSelectedTool(updatedSelected ?? null);
|
|
259
|
+
const autoApprovedTools = updatedTools
|
|
260
|
+
.filter((tool) => tool.isAutoApproved)
|
|
261
|
+
.map((tool) => tool.name);
|
|
262
|
+
agent.setSessionAutoApproveTools(sessionId, autoApprovedTools);
|
|
263
|
+
};
|
|
264
|
+
const closeConfigMenu = () => {
|
|
265
|
+
setViewMode('list-actions');
|
|
266
|
+
};
|
|
267
|
+
const closeDetailView = () => {
|
|
268
|
+
setViewMode('list-actions');
|
|
269
|
+
};
|
|
270
|
+
const closeListActions = () => {
|
|
137
271
|
setViewMode('list');
|
|
138
272
|
setSelectedTool(null);
|
|
139
273
|
};
|
|
@@ -142,13 +276,69 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
142
276
|
handleInput: (input, key) => {
|
|
143
277
|
if (!isVisible)
|
|
144
278
|
return false;
|
|
145
|
-
//
|
|
279
|
+
// Scope selection view
|
|
280
|
+
if (viewModeRef.current === 'scope') {
|
|
281
|
+
if (key.escape || key.backspace || key.delete) {
|
|
282
|
+
closeScopePrompt();
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
if (key.upArrow || key.downArrow) {
|
|
286
|
+
setScopeTarget((prev) => (prev === 'session' ? 'global' : 'session'));
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
if (key.return) {
|
|
290
|
+
if (scopeTargetRef.current === 'session' && !sessionId) {
|
|
291
|
+
setScopeTarget('global');
|
|
292
|
+
scopeTargetRef.current = 'global';
|
|
293
|
+
void applyToolToggle('global');
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
void applyToolToggle();
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
// Config menu view
|
|
302
|
+
if (viewModeRef.current === 'config') {
|
|
303
|
+
if (key.escape || key.backspace || key.delete) {
|
|
304
|
+
closeConfigMenu();
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
if (key.upArrow) {
|
|
308
|
+
const nextIndex = (configIndexRef.current - 1 + 3) % 3;
|
|
309
|
+
setConfigIndex(nextIndex);
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
if (key.downArrow) {
|
|
313
|
+
const nextIndex = (configIndexRef.current + 1) % 3;
|
|
314
|
+
setConfigIndex(nextIndex);
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
if (key.return) {
|
|
318
|
+
const tool = selectedToolRef.current;
|
|
319
|
+
if (tool) {
|
|
320
|
+
if (configIndexRef.current === 0) {
|
|
321
|
+
openScopePrompt(tool);
|
|
322
|
+
}
|
|
323
|
+
else if (configIndexRef.current === 1) {
|
|
324
|
+
if (sessionId && tool.isEnabled) {
|
|
325
|
+
toggleAutoApprove();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
closeConfigMenu();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
// Detail view
|
|
146
337
|
if (viewModeRef.current === 'detail') {
|
|
147
338
|
if (key.escape || key.backspace || key.delete) {
|
|
148
|
-
|
|
339
|
+
closeDetailView();
|
|
149
340
|
return true;
|
|
150
341
|
}
|
|
151
|
-
// Handle scrolling in detail view - check refs before setState to avoid flicker
|
|
152
342
|
if (key.upArrow) {
|
|
153
343
|
if (detailScrollOffsetRef.current > 0) {
|
|
154
344
|
setDetailScrollOffset((prev) => prev - 1);
|
|
@@ -178,10 +368,53 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
178
368
|
}
|
|
179
369
|
return true;
|
|
180
370
|
}
|
|
181
|
-
return
|
|
371
|
+
if (key.return) {
|
|
372
|
+
const tool = selectedToolRef.current;
|
|
373
|
+
if (tool) {
|
|
374
|
+
openConfigMenu(tool);
|
|
375
|
+
}
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
// List action menu view
|
|
381
|
+
if (viewModeRef.current === 'list-actions') {
|
|
382
|
+
if (key.escape || key.backspace || key.delete) {
|
|
383
|
+
closeListActions();
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
if (key.upArrow) {
|
|
387
|
+
const nextIndex = (listActionsIndexRef.current - 1 + LIST_ACTIONS.length) %
|
|
388
|
+
LIST_ACTIONS.length;
|
|
389
|
+
setListActionsIndex(nextIndex);
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
if (key.downArrow) {
|
|
393
|
+
const nextIndex = (listActionsIndexRef.current + 1) % LIST_ACTIONS.length;
|
|
394
|
+
setListActionsIndex(nextIndex);
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
if (key.return) {
|
|
398
|
+
const tool = selectedToolRef.current;
|
|
399
|
+
const action = LIST_ACTIONS[listActionsIndexRef.current];
|
|
400
|
+
if (!tool) {
|
|
401
|
+
closeListActions();
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
if (action === 'view') {
|
|
405
|
+
openToolDetails(tool);
|
|
406
|
+
}
|
|
407
|
+
else if (action === 'config') {
|
|
408
|
+
openConfigMenu(tool);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
closeListActions();
|
|
412
|
+
}
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
return true;
|
|
182
416
|
}
|
|
183
417
|
// In list view
|
|
184
|
-
// Escape closes
|
|
185
418
|
if (key.escape) {
|
|
186
419
|
onClose();
|
|
187
420
|
return true;
|
|
@@ -224,33 +457,39 @@ const ToolBrowser = forwardRef(function ToolBrowser({ isVisible, onClose, agent
|
|
|
224
457
|
if (key.return && itemsLength > 0) {
|
|
225
458
|
const tool = filteredTools[selectedIndexRef.current];
|
|
226
459
|
if (tool) {
|
|
227
|
-
|
|
460
|
+
openListActions(tool);
|
|
228
461
|
return true;
|
|
229
462
|
}
|
|
230
463
|
}
|
|
231
464
|
return false;
|
|
232
465
|
},
|
|
233
|
-
}), [isVisible, filteredTools, onClose,
|
|
466
|
+
}), [isVisible, filteredTools, onClose, sessionId]);
|
|
234
467
|
if (!isVisible)
|
|
235
468
|
return null;
|
|
236
469
|
if (isLoading) {
|
|
237
470
|
return (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "Loading tools..." }) }));
|
|
238
471
|
}
|
|
239
|
-
|
|
472
|
+
if (viewMode === 'list-actions' && selectedTool) {
|
|
473
|
+
return (_jsx(ToolActionsMenu, { tool: selectedTool, columns: columns, listActionsIndex: listActionsIndex }));
|
|
474
|
+
}
|
|
240
475
|
if (viewMode === 'detail' && selectedTool) {
|
|
241
|
-
|
|
242
|
-
const maxVisibleLines = Math.min(18, Math.max(5, rows - 6)); // Cap at 18 to reduce flicker
|
|
476
|
+
const maxVisibleLines = Math.min(18, Math.max(5, rows - 6));
|
|
243
477
|
return (_jsx(ToolDetailView, { tool: selectedTool, columns: columns, scrollOffset: detailScrollOffset, maxVisibleLines: maxVisibleLines, maxScrollOffsetRef: detailMaxScrollOffsetRef, copyFeedback: copyFeedback }));
|
|
244
478
|
}
|
|
479
|
+
if (viewMode === 'config' && selectedTool) {
|
|
480
|
+
return (_jsx(ToolSettingsView, { tool: selectedTool, columns: columns, configIndex: configIndex, sessionAvailable: Boolean(sessionId) }));
|
|
481
|
+
}
|
|
482
|
+
if (viewMode === 'scope' && selectedTool) {
|
|
483
|
+
return (_jsx(ToolScopeView, { tool: selectedTool, columns: columns, scopeTarget: scopeTarget, scopeNextEnabled: scopeNextEnabled, sessionAvailable: Boolean(sessionId) }));
|
|
484
|
+
}
|
|
245
485
|
// List view
|
|
246
486
|
const visibleTools = filteredTools.slice(scrollOffset, scrollOffset + MAX_VISIBLE_ITEMS);
|
|
247
|
-
// Show counts based on filtered results, not total
|
|
248
487
|
const filteredInternalCount = filteredTools.filter((t) => t.source === 'internal').length;
|
|
249
488
|
const filteredMcpCount = filteredTools.filter((t) => t.source === 'mcp').length;
|
|
250
|
-
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
|
|
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) => {
|
|
251
490
|
const actualIndex = scrollOffset + visibleIndex;
|
|
252
491
|
const isSelected = actualIndex === selectedIndex;
|
|
253
|
-
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, ")"] })] }, tool.name));
|
|
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));
|
|
254
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
|
|
255
494
|
? ' | '
|
|
256
495
|
: '', scrollOffset + MAX_VISIBLE_ITEMS < filteredTools.length
|
|
@@ -299,36 +538,29 @@ function buildDetailLineData(tool, maxWidth) {
|
|
|
299
538
|
});
|
|
300
539
|
// Parameter description (wrapped)
|
|
301
540
|
if (description) {
|
|
302
|
-
const
|
|
303
|
-
for (const
|
|
304
|
-
lines.push({ type: 'param-desc', text:
|
|
541
|
+
const descLines = wrapText(description, maxWidth - 2).split('\n');
|
|
542
|
+
for (const descLine of descLines) {
|
|
543
|
+
lines.push({ type: 'param-desc', text: descLine });
|
|
305
544
|
}
|
|
306
545
|
}
|
|
307
546
|
// Enum values
|
|
308
|
-
if (enumValues) {
|
|
547
|
+
if (enumValues && enumValues.length > 0) {
|
|
309
548
|
lines.push({ type: 'param-enum', values: enumValues });
|
|
310
549
|
}
|
|
311
|
-
// Empty line between parameters
|
|
312
|
-
lines.push({ type: 'empty' });
|
|
313
550
|
}
|
|
314
551
|
}
|
|
315
|
-
else {
|
|
316
|
-
// Empty line before "no parameters"
|
|
317
|
-
lines.push({ type: 'empty' });
|
|
318
|
-
lines.push({ type: 'param-desc', text: 'No parameters' });
|
|
319
|
-
}
|
|
320
552
|
}
|
|
321
553
|
return lines;
|
|
322
554
|
}
|
|
323
555
|
/**
|
|
324
|
-
* Render a
|
|
556
|
+
* Render a detail line based on type
|
|
325
557
|
*/
|
|
326
|
-
function renderDetailLine(line,
|
|
558
|
+
function renderDetailLine(line, _index) {
|
|
327
559
|
switch (line.type) {
|
|
328
560
|
case 'title':
|
|
329
561
|
return (_jsx(Text, { color: "cyan", bold: true, children: line.text }));
|
|
330
562
|
case 'source':
|
|
331
|
-
return (_jsxs(
|
|
563
|
+
return (_jsxs(Text, { color: line.source === 'internal' ? 'magenta' : 'blue', children: [line.source === 'internal' ? 'Internal Tool' : 'MCP Tool', line.serverName ? ` (${line.serverName})` : ''] }));
|
|
332
564
|
case 'empty':
|
|
333
565
|
return _jsx(Text, { children: " " });
|
|
334
566
|
case 'header':
|
|
@@ -343,9 +575,9 @@ function renderDetailLine(line, index) {
|
|
|
343
575
|
return (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsxs(Text, { color: "gray", children: ["Allowed: ", line.values.join(' | ')] })] }));
|
|
344
576
|
}
|
|
345
577
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
578
|
+
function ToolActionsMenu({ tool, columns, listActionsIndex, }) {
|
|
579
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: "Tool Options" }), _jsxs(Text, { color: "gray", children: [" ", tool.name] })] }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: listActionsIndex === 0 ? 'cyan' : 'gray', children: [listActionsIndex === 0 ? '▶ ' : ' ', "View details"] }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: listActionsIndex === 1 ? 'cyan' : 'gray', children: [listActionsIndex === 1 ? '▶ ' : ' ', "Edit tool settings"] }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: listActionsIndex === 2 ? 'cyan' : 'gray', children: [listActionsIndex === 2 ? '▶ ' : ' ', "Back"] }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "\u2191\u2193 select \u00B7 Enter confirm \u00B7 Esc back" }) })] }));
|
|
580
|
+
}
|
|
349
581
|
function ToolDetailView({ tool, columns, scrollOffset, maxVisibleLines, maxScrollOffsetRef, copyFeedback, }) {
|
|
350
582
|
const maxWidth = Math.min(80, columns - 4);
|
|
351
583
|
// Build plain data for lines (memoized)
|
|
@@ -358,7 +590,7 @@ function ToolDetailView({ tool, columns, scrollOffset, maxVisibleLines, maxScrol
|
|
|
358
590
|
// Calculate scroll indicators
|
|
359
591
|
const hasMoreAbove = clampedOffset > 0;
|
|
360
592
|
const hasMoreBelow = clampedOffset + maxVisibleLines < totalLines;
|
|
361
|
-
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: "Tool Details" }), _jsx(Text, { color: "gray", children: " - \u2191\u2193 scroll, c copy schema, Esc back" }), copyFeedback && (_jsxs(Text, { color: "green", bold: true, children: [' ', copyFeedback] }))] }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: '─'.repeat(Math.min(60, columns - 2)) }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: hasMoreAbove ? `↑ ${clampedOffset} more above` : ' ' }) }), Array.from({ length: maxVisibleLines }, (_, i) => {
|
|
593
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: "Tool Details" }), _jsx(Text, { color: "gray", children: " - \u2191\u2193 scroll, c copy schema, Enter settings, Esc back" }), copyFeedback && (_jsxs(Text, { color: "green", bold: true, children: [' ', copyFeedback] }))] }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: '─'.repeat(Math.min(60, columns - 2)) }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: hasMoreAbove ? `↑ ${clampedOffset} more above` : ' ' }) }), Array.from({ length: maxVisibleLines }, (_, i) => {
|
|
362
594
|
const absoluteIndex = clampedOffset + i;
|
|
363
595
|
const line = lineData[absoluteIndex];
|
|
364
596
|
return (_jsx(Box, { paddingX: 0, paddingY: 0, children: line ? renderDetailLine(line, absoluteIndex) : _jsx(Text, { children: " " }) }, i));
|
|
@@ -366,6 +598,16 @@ function ToolDetailView({ tool, columns, scrollOffset, maxVisibleLines, maxScrol
|
|
|
366
598
|
? `↓ ${totalLines - clampedOffset - maxVisibleLines} more below`
|
|
367
599
|
: ' ' }) })] }));
|
|
368
600
|
}
|
|
601
|
+
function ToolSettingsView({ tool, columns, configIndex, sessionAvailable, }) {
|
|
602
|
+
const autoApproveDisabled = !tool.isEnabled;
|
|
603
|
+
const autoApproveUnavailable = !sessionAvailable || autoApproveDisabled;
|
|
604
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: "Tool Settings" }), _jsxs(Text, { color: "gray", children: [" ", tool.name] })] }), _jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "gray", children: "Status: " }), _jsx(Text, { color: tool.isEnabled ? 'green' : 'red', children: tool.isEnabled ? 'Enabled' : 'Disabled' }), _jsx(Text, { color: "gray", children: " \u00B7 Auto-approve: " }), _jsx(Text, { color: tool.isAutoApproved ? 'green' : 'red', children: tool.isAutoApproved ? 'On' : 'Off' }), _jsx(Text, { color: "gray", children: " (session)" })] }), autoApproveDisabled && (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "yellow", children: "Enable the tool to allow auto-approve." }) })), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: configIndex === 0 ? 'cyan' : 'gray', children: [configIndex === 0 ? '▶ ' : ' ', tool.isEnabled ? 'Disable tool' : 'Enable tool'] }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: configIndex === 1 ? (autoApproveUnavailable ? 'yellow' : 'cyan') : 'gray', children: [configIndex === 1 ? '▶ ' : ' ', tool.isAutoApproved
|
|
605
|
+
? 'Disable auto-approve (session)'
|
|
606
|
+
: 'Enable auto-approve (session)'] }) }), !sessionAvailable && (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "yellow", children: "Auto-approve requires an active session." }) })), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: configIndex === 2 ? 'cyan' : 'gray', children: [configIndex === 2 ? '▶ ' : ' ', "Back"] }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "\u2191\u2193 select \u00B7 Enter confirm \u00B7 Esc back" }) })] }));
|
|
607
|
+
}
|
|
608
|
+
function ToolScopeView({ tool, columns, scopeTarget, scopeNextEnabled, sessionAvailable, }) {
|
|
609
|
+
return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "cyan", bold: true, children: scopeNextEnabled ? 'Enable Tool' : 'Disable Tool' }), _jsxs(Text, { color: "gray", children: [" ", tool.name] })] }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "Apply to:" }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: scopeTarget === 'session' ? 'cyan' : 'gray', children: [scopeTarget === 'session' ? '▶ ' : ' ', "Session (default)"] }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: scopeTarget === 'global' ? 'cyan' : 'gray', children: [scopeTarget === 'global' ? '▶ ' : ' ', "Global (persisted)"] }) }), !sessionAvailable && scopeTarget === 'session' && (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "yellow", children: "No active session; switching to global." }) })), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "\u2191\u2193 choose scope \u00B7 Enter confirm \u00B7 Esc back" }) })] }));
|
|
610
|
+
}
|
|
369
611
|
/**
|
|
370
612
|
* Truncate text to max length with ellipsis
|
|
371
613
|
*/
|
|
@@ -20,9 +20,17 @@ export declare function getProviderConfig(provider: CustomModelProvider): Provid
|
|
|
20
20
|
export declare function getProviderLabel(provider: CustomModelProvider): string;
|
|
21
21
|
/**
|
|
22
22
|
* Get all available provider types.
|
|
23
|
-
* Filters out 'dexto' when the feature flag is disabled.
|
|
23
|
+
* Filters out 'dexto-nova' when the feature flag is disabled.
|
|
24
24
|
*/
|
|
25
25
|
export declare function getAvailableProviders(): CustomModelProvider[];
|
|
26
|
+
/**
|
|
27
|
+
* Maps a provider-selection menu index to the selected provider, using the same
|
|
28
|
+
* provider ordering as the UI.
|
|
29
|
+
*
|
|
30
|
+
* This avoids subtle bugs when the displayed ordering differs from the base
|
|
31
|
+
* CUSTOM_MODEL_PROVIDERS array (e.g. feature-flagged reordering).
|
|
32
|
+
*/
|
|
33
|
+
export declare function getProviderByMenuIndex(index: number): CustomModelProvider | undefined;
|
|
26
34
|
/**
|
|
27
35
|
* Check if a provider has async validation.
|
|
28
36
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-config.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAQhF,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,YAAY,CAAC;AA4D7D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,mBAAmB,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"provider-config.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAQhF,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,YAAY,CAAC;AA4D7D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,mBAAmB,EAAE,cAAc,CAgcxE,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,cAAc,CAE/E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,CAGtE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,mBAAmB,EAAE,CAW7D;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAIrF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAEzE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACpC,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB"}
|
|
@@ -120,6 +120,7 @@ export const PROVIDER_CONFIGS = {
|
|
|
120
120
|
validate: validators.slashFormat,
|
|
121
121
|
},
|
|
122
122
|
{ ...DISPLAY_NAME_STEP, placeholder: 'e.g., Claude 3.5 Sonnet' },
|
|
123
|
+
MAX_INPUT_TOKENS_STEP,
|
|
123
124
|
REASONING_EFFORT_STEP,
|
|
124
125
|
{
|
|
125
126
|
...API_KEY_STEP,
|
|
@@ -134,6 +135,9 @@ export const PROVIDER_CONFIGS = {
|
|
|
134
135
|
if (values.displayName?.trim()) {
|
|
135
136
|
model.displayName = values.displayName.trim();
|
|
136
137
|
}
|
|
138
|
+
if (values.maxInputTokens?.trim()) {
|
|
139
|
+
model.maxInputTokens = parseInt(values.maxInputTokens, 10);
|
|
140
|
+
}
|
|
137
141
|
if (values.reasoningEffort?.trim()) {
|
|
138
142
|
model.reasoningEffort =
|
|
139
143
|
values.reasoningEffort.toLowerCase();
|
|
@@ -423,9 +427,9 @@ export const PROVIDER_CONFIGS = {
|
|
|
423
427
|
docsUrl: 'https://docs.dexto.ai/docs/guides/supported-llm-providers#google-vertex-ai',
|
|
424
428
|
},
|
|
425
429
|
},
|
|
426
|
-
dexto: {
|
|
427
|
-
displayName: 'Dexto',
|
|
428
|
-
description: 'Access 100+ models with
|
|
430
|
+
'dexto-nova': {
|
|
431
|
+
displayName: 'Dexto Nova',
|
|
432
|
+
description: 'Access 100+ models with Nova credits',
|
|
429
433
|
steps: [
|
|
430
434
|
{
|
|
431
435
|
field: 'name',
|
|
@@ -446,6 +450,9 @@ export const PROVIDER_CONFIGS = {
|
|
|
446
450
|
if (values.displayName?.trim()) {
|
|
447
451
|
model.displayName = values.displayName.trim();
|
|
448
452
|
}
|
|
453
|
+
if (values.maxInputTokens?.trim()) {
|
|
454
|
+
model.maxInputTokens = parseInt(values.maxInputTokens, 10);
|
|
455
|
+
}
|
|
449
456
|
if (values.reasoningEffort?.trim()) {
|
|
450
457
|
model.reasoningEffort =
|
|
451
458
|
values.reasoningEffort.toLowerCase();
|
|
@@ -455,7 +462,7 @@ export const PROVIDER_CONFIGS = {
|
|
|
455
462
|
asyncValidation: {
|
|
456
463
|
field: 'name',
|
|
457
464
|
validate: async (modelId) => {
|
|
458
|
-
// Reuse OpenRouter validation since Dexto uses OpenRouter model IDs
|
|
465
|
+
// Reuse OpenRouter validation since Dexto Nova uses OpenRouter model IDs
|
|
459
466
|
let status = lookupOpenRouterModel(modelId);
|
|
460
467
|
// If cache is stale/empty, try to refresh
|
|
461
468
|
if (status === 'unknown') {
|
|
@@ -469,14 +476,14 @@ export const PROVIDER_CONFIGS = {
|
|
|
469
476
|
}
|
|
470
477
|
}
|
|
471
478
|
if (status === 'invalid') {
|
|
472
|
-
return `Model '${modelId}' not found. Dexto uses OpenRouter model IDs - check https://openrouter.ai/models`;
|
|
479
|
+
return `Model '${modelId}' not found. Dexto Nova uses OpenRouter model IDs - check https://openrouter.ai/models`;
|
|
473
480
|
}
|
|
474
481
|
return null;
|
|
475
482
|
},
|
|
476
483
|
},
|
|
477
484
|
setupInfo: {
|
|
478
|
-
title: 'Dexto Setup',
|
|
479
|
-
description: 'Add OpenRouter-format models that use your Dexto credits. Requires login: run `dexto login` first.',
|
|
485
|
+
title: 'Dexto Nova Setup',
|
|
486
|
+
description: 'Add OpenRouter-format models that use your Dexto Nova credits. Requires login: run `dexto login` first.',
|
|
480
487
|
docsUrl: 'https://openrouter.ai/models',
|
|
481
488
|
},
|
|
482
489
|
},
|
|
@@ -497,11 +504,30 @@ export function getProviderLabel(provider) {
|
|
|
497
504
|
}
|
|
498
505
|
/**
|
|
499
506
|
* Get all available provider types.
|
|
500
|
-
* Filters out 'dexto' when the feature flag is disabled.
|
|
507
|
+
* Filters out 'dexto-nova' when the feature flag is disabled.
|
|
501
508
|
*/
|
|
502
509
|
export function getAvailableProviders() {
|
|
503
510
|
const dextoEnabled = isDextoAuthEnabled();
|
|
504
|
-
|
|
511
|
+
const providers = CUSTOM_MODEL_PROVIDERS.filter((provider) => provider !== 'dexto-nova' || dextoEnabled);
|
|
512
|
+
if (!dextoEnabled) {
|
|
513
|
+
return providers;
|
|
514
|
+
}
|
|
515
|
+
// When enabled, put Dexto Nova first for better UX.
|
|
516
|
+
const withoutDexto = providers.filter((p) => p !== 'dexto-nova');
|
|
517
|
+
return ['dexto-nova', ...withoutDexto];
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Maps a provider-selection menu index to the selected provider, using the same
|
|
521
|
+
* provider ordering as the UI.
|
|
522
|
+
*
|
|
523
|
+
* This avoids subtle bugs when the displayed ordering differs from the base
|
|
524
|
+
* CUSTOM_MODEL_PROVIDERS array (e.g. feature-flagged reordering).
|
|
525
|
+
*/
|
|
526
|
+
export function getProviderByMenuIndex(index) {
|
|
527
|
+
const providers = getAvailableProviders();
|
|
528
|
+
if (index < 0 || index >= providers.length)
|
|
529
|
+
return undefined;
|
|
530
|
+
return providers[index];
|
|
505
531
|
}
|
|
506
532
|
/**
|
|
507
533
|
* Check if a provider has async validation.
|
|
@@ -417,7 +417,7 @@ export const InputContainer = forwardRef(function InputContainer({ buffer, input
|
|
|
417
417
|
{
|
|
418
418
|
id: generateMessageId('error'),
|
|
419
419
|
role: 'system',
|
|
420
|
-
content:
|
|
420
|
+
content: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
421
421
|
timestamp: new Date(),
|
|
422
422
|
},
|
|
423
423
|
]);
|
|
@@ -545,7 +545,7 @@ export const InputContainer = forwardRef(function InputContainer({ buffer, input
|
|
|
545
545
|
{
|
|
546
546
|
id: generateMessageId('error'),
|
|
547
547
|
role: 'system',
|
|
548
|
-
content:
|
|
548
|
+
content: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
549
549
|
timestamp: new Date(),
|
|
550
550
|
},
|
|
551
551
|
]);
|