dexto 1.5.0 → 1.5.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 (42) hide show
  1. package/dist/cli/commands/interactive-commands/command-parser.d.ts +1 -1
  2. package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
  3. package/dist/cli/commands/interactive-commands/command-parser.js +11 -1
  4. package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
  5. package/dist/cli/commands/interactive-commands/general-commands.js +63 -0
  6. package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
  7. package/dist/cli/commands/interactive-commands/system/system-commands.js +3 -2
  8. package/dist/cli/commands/setup.d.ts.map +1 -1
  9. package/dist/cli/commands/setup.js +163 -28
  10. package/dist/cli/ink-cli/components/TextBufferInput.d.ts.map +1 -1
  11. package/dist/cli/ink-cli/components/TextBufferInput.js +7 -3
  12. package/dist/cli/ink-cli/components/chat/Header.js +1 -1
  13. package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
  14. package/dist/cli/ink-cli/components/chat/MessageItem.js +4 -1
  15. package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -1
  16. package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +1 -1
  17. package/dist/cli/ink-cli/components/overlays/CustomModelWizard.d.ts.map +1 -1
  18. package/dist/cli/ink-cli/components/overlays/CustomModelWizard.js +19 -8
  19. package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +1 -1
  20. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts +2 -1
  21. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
  22. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +64 -2
  23. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.d.ts.map +1 -1
  24. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/provider-config.js +44 -1
  25. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.d.ts +6 -0
  26. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/types.d.ts.map +1 -1
  27. package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
  28. package/dist/cli/ink-cli/containers/OverlayContainer.js +2 -2
  29. package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts +8 -1
  30. package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
  31. package/dist/cli/ink-cli/hooks/useAgentEvents.js +144 -6
  32. package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
  33. package/dist/cli/ink-cli/hooks/useCLIState.js +3 -0
  34. package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts +11 -7
  35. package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts.map +1 -1
  36. package/dist/cli/ink-cli/hooks/useTokenCounter.js +41 -18
  37. package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
  38. package/dist/cli/ink-cli/services/processStream.js +20 -8
  39. package/dist/cli/ink-cli/state/types.d.ts +2 -2
  40. package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
  41. package/dist/index.js +24 -3
  42. package/package.json +7 -7
@@ -37,8 +37,17 @@ const CustomModelWizard = forwardRef(function CustomModelWizard({ isVisible, onC
37
37
  const localModelWizardRef = useRef(null);
38
38
  // Get provider config (data-driven, no conditionals)
39
39
  const providerConfig = selectedProvider ? getProviderConfig(selectedProvider) : null;
40
- const wizardSteps = providerConfig?.steps ?? [];
41
- const currentStepConfig = wizardSteps[currentStep];
40
+ const allWizardSteps = providerConfig?.steps ?? [];
41
+ /**
42
+ * Get visible steps based on current values.
43
+ * Steps with a condition function are only shown if the condition returns true.
44
+ */
45
+ const getVisibleSteps = useCallback((currentValues) => {
46
+ return allWizardSteps.filter((step) => !step.condition || step.condition(currentValues));
47
+ }, [allWizardSteps]);
48
+ // Current visible steps based on accumulated values
49
+ const visibleSteps = getVisibleSteps(values);
50
+ const currentStepConfig = visibleSteps[currentStep];
42
51
  // Reset when becoming visible
43
52
  useEffect(() => {
44
53
  if (isVisible) {
@@ -117,15 +126,17 @@ const CustomModelWizard = forwardRef(function CustomModelWizard({ isVisible, onC
117
126
  setValues(newValues);
118
127
  setError(null);
119
128
  setCurrentInput('');
129
+ // Get updated visible steps with new values
130
+ const updatedVisibleSteps = getVisibleSteps(newValues);
120
131
  // Check if we're done
121
- if (currentStep >= wizardSteps.length - 1) {
132
+ if (currentStep >= updatedVisibleSteps.length - 1) {
122
133
  await saveModel(newValues);
123
134
  }
124
135
  else {
125
136
  const nextStep = currentStep + 1;
126
137
  setCurrentStep(nextStep);
127
138
  // Pre-populate next step from stored values (for edit mode)
128
- const nextStepConfig = wizardSteps[nextStep];
139
+ const nextStepConfig = updatedVisibleSteps[nextStep];
129
140
  const nextValue = nextStepConfig ? newValues[nextStepConfig.field] : undefined;
130
141
  setCurrentInput(nextValue ?? '');
131
142
  }
@@ -133,11 +144,11 @@ const CustomModelWizard = forwardRef(function CustomModelWizard({ isVisible, onC
133
144
  currentInput,
134
145
  currentStep,
135
146
  currentStepConfig,
147
+ getVisibleSteps,
136
148
  isSaving,
137
149
  isValidating,
138
150
  selectedProvider,
139
151
  values,
140
- wizardSteps,
141
152
  ]);
142
153
  /**
143
154
  * Build and save the model using provider config's buildModel function.
@@ -191,7 +202,7 @@ const CustomModelWizard = forwardRef(function CustomModelWizard({ isVisible, onC
191
202
  if (currentStep > 0) {
192
203
  setCurrentStep(currentStep - 1);
193
204
  // Restore previous value
194
- const prevStep = wizardSteps[currentStep - 1];
205
+ const prevStep = visibleSteps[currentStep - 1];
195
206
  if (prevStep) {
196
207
  setCurrentInput(values[prevStep.field] || '');
197
208
  }
@@ -205,7 +216,7 @@ const CustomModelWizard = forwardRef(function CustomModelWizard({ isVisible, onC
205
216
  else {
206
217
  onClose();
207
218
  }
208
- }, [currentStep, onClose, selectedProvider, values, wizardSteps]);
219
+ }, [currentStep, onClose, selectedProvider, values, visibleSteps]);
209
220
  // Handle keyboard input
210
221
  useImperativeHandle(ref, () => ({
211
222
  handleInput: (input, key) => {
@@ -281,6 +292,6 @@ const CustomModelWizard = forwardRef(function CustomModelWizard({ isVisible, onC
281
292
  // Wizard steps screen for other providers
282
293
  if (!currentStepConfig || !providerConfig)
283
294
  return null;
284
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, marginTop: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "green", children: isEditing ? 'Edit Custom Model' : 'Add Custom Model' }), _jsxs(Text, { color: "gray", children: [' ', "(", providerConfig.displayName, ") Step ", currentStep + 1, "/", wizardSteps.length] })] }), providerConfig.setupInfo && currentStep === 0 && (_jsx(SetupInfoBanner, { title: providerConfig.setupInfo.title, description: providerConfig.setupInfo.description, docsUrl: providerConfig.setupInfo.docsUrl })), _jsx(WizardStepInput, { step: currentStepConfig, currentInput: currentInput, error: error, isValidating: isValidating, isSaving: isSaving, additionalContent: currentStepConfig.field === 'apiKey' ? (_jsx(ApiKeyStep, { provider: selectedProvider })) : undefined }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", children: ["Enter to continue \u2022 Esc to", ' ', currentStep > 0 ? 'go back' : 'back to provider'] }) })] }));
295
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, marginTop: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "green", children: isEditing ? 'Edit Custom Model' : 'Add Custom Model' }), _jsxs(Text, { color: "gray", children: [' ', "(", providerConfig.displayName, ") Step ", currentStep + 1, "/", visibleSteps.length] })] }), providerConfig.setupInfo && currentStep === 0 && (_jsx(SetupInfoBanner, { title: providerConfig.setupInfo.title, description: providerConfig.setupInfo.description, docsUrl: providerConfig.setupInfo.docsUrl })), _jsx(WizardStepInput, { step: currentStepConfig, currentInput: currentInput, error: error, isValidating: isValidating, isSaving: isSaving, additionalContent: currentStepConfig.field === 'apiKey' ? (_jsx(ApiKeyStep, { provider: selectedProvider })) : undefined }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", children: ["Enter to continue \u2022 Esc to", ' ', currentStep > 0 ? 'go back' : 'back to provider'] }) })] }));
285
296
  });
286
297
  export default CustomModelWizard;
@@ -54,6 +54,6 @@ const LogLevelSelector = forwardRef(function LogLevelSelector({ isVisible, onSel
54
54
  const handleSelect = (option) => {
55
55
  onSelect(option.level);
56
56
  };
57
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BaseSelector, { ref: baseSelectorRef, items: levels, isVisible: isVisible, isLoading: false, selectedIndex: selectedIndex, onSelectIndex: setSelectedIndex, onSelect: handleSelect, onClose: onClose, formatItem: formatItem, title: "Select Log Level", borderColor: "yellowBright", emptyMessage: "No log levels available" }), logFilePath && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", children: ["\uD83D\uDCC1 Log file: ", logFilePath] }) }))] }));
57
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BaseSelector, { ref: baseSelectorRef, items: levels, isVisible: isVisible, isLoading: false, selectedIndex: selectedIndex, onSelectIndex: setSelectedIndex, onSelect: handleSelect, onClose: onClose, formatItem: formatItem, title: "Select Log Level", borderColor: "yellowBright", emptyMessage: "No log levels available" }), logFilePath && process.env.DEXTO_PRIVACY_MODE !== 'true' && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "gray", children: ["\uD83D\uDCC1 Log file: ", logFilePath] }) }))] }));
58
58
  });
59
59
  export default LogLevelSelector;
@@ -7,9 +7,10 @@
7
7
  import type { Key } from '../../hooks/useInputOrchestrator.js';
8
8
  import type { DextoAgent, LLMProvider } from '@dexto/core';
9
9
  import { type CustomModel } from '@dexto/agent-management';
10
+ type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
10
11
  interface ModelSelectorProps {
11
12
  isVisible: boolean;
12
- onSelectModel: (provider: LLMProvider, model: string, displayName?: string, baseURL?: string) => void;
13
+ onSelectModel: (provider: LLMProvider, model: string, displayName?: string, baseURL?: string, reasoningEffort?: ReasoningEffort) => void;
13
14
  onClose: () => void;
14
15
  onAddCustomModel: () => void;
15
16
  onEditCustomModel: (model: CustomModel) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"ModelSelectorRefactored.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/overlays/ModelSelectorRefactored.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAIH,KAAK,WAAW,EACnB,MAAM,yBAAyB,CAAC;AAEjC,UAAU,kBAAkB;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,CACX,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,KACf,IAAI,CAAC;IACV,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,iBAAiB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AA0BD;;GAEG;AACH,QAAA,MAAM,aAAa,oHAmmBjB,CAAC;AAEH,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"ModelSelectorRefactored.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/overlays/ModelSelectorRefactored.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO3D,OAAO,EAIH,KAAK,WAAW,EACnB,MAAM,yBAAyB,CAAC;AAEjC,KAAK,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhF,UAAU,kBAAkB;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,CACX,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,EAChB,eAAe,CAAC,EAAE,eAAe,KAChC,IAAI,CAAC;IACV,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,iBAAiB,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAiDD;;GAEG;AACH,QAAA,MAAM,aAAa,oHA4rBjB,CAAC;AAEH,eAAe,aAAa,CAAC"}
@@ -7,12 +7,30 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
7
7
  */
8
8
  import { useState, useEffect, forwardRef, useRef, useImperativeHandle, useMemo, useCallback, } from 'react';
9
9
  import { Box, Text } from 'ink';
10
- import { listOllamaModels, DEFAULT_OLLAMA_URL, getLocalModelById } from '@dexto/core';
10
+ import { listOllamaModels, DEFAULT_OLLAMA_URL, getLocalModelById, isReasoningCapableModel, } from '@dexto/core';
11
11
  import { loadCustomModels, deleteCustomModel, getAllInstalledModels, } from '@dexto/agent-management';
12
12
  function isAddCustomOption(item) {
13
13
  return 'type' in item && item.type === 'add-custom';
14
14
  }
15
15
  const MAX_VISIBLE_ITEMS = 10;
16
+ // Reasoning effort options - defined at module scope to avoid recreation on each render
17
+ const REASONING_EFFORT_OPTIONS = [
18
+ {
19
+ value: 'auto',
20
+ label: 'Auto',
21
+ description: 'Let the model decide (recommended for most tasks)',
22
+ },
23
+ { value: 'none', label: 'None', description: 'No reasoning, fastest responses' },
24
+ { value: 'minimal', label: 'Minimal', description: 'Barely any reasoning, very fast' },
25
+ { value: 'low', label: 'Low', description: 'Light reasoning, fast responses' },
26
+ {
27
+ value: 'medium',
28
+ label: 'Medium',
29
+ description: 'Balanced reasoning (OpenAI recommended)',
30
+ },
31
+ { value: 'high', label: 'High', description: 'Thorough reasoning for complex tasks' },
32
+ { value: 'xhigh', label: 'Extra High', description: 'Maximum quality, slower/costlier' },
33
+ ];
16
34
  /**
17
35
  * Model selector with search and custom model support
18
36
  */
@@ -27,6 +45,9 @@ const ModelSelector = forwardRef(function ModelSelector({ isVisible, onSelectMod
27
45
  const [pendingDeleteConfirm, setPendingDeleteConfirm] = useState(false);
28
46
  const selectedIndexRef = useRef(selectedIndex);
29
47
  const deleteTimeoutRef = useRef(null);
48
+ // Reasoning effort sub-step state
49
+ const [pendingReasoningModel, setPendingReasoningModel] = useState(null);
50
+ const [reasoningEffortIndex, setReasoningEffortIndex] = useState(0); // Default to 'Auto' (index 0)
30
51
  // Keep ref in sync
31
52
  selectedIndexRef.current = selectedIndex;
32
53
  // Clear delete confirmation timeout on unmount
@@ -48,6 +69,8 @@ const ModelSelector = forwardRef(function ModelSelector({ isVisible, onSelectMod
48
69
  setScrollOffset(0);
49
70
  setCustomModelAction(null);
50
71
  setPendingDeleteConfirm(false);
72
+ setPendingReasoningModel(null);
73
+ setReasoningEffortIndex(0); // Default to 'Auto'
51
74
  if (deleteTimeoutRef.current) {
52
75
  clearTimeout(deleteTimeoutRef.current);
53
76
  deleteTimeoutRef.current = null;
@@ -256,6 +279,30 @@ const ModelSelector = forwardRef(function ModelSelector({ isVisible, onSelectMod
256
279
  handleInput: (input, key) => {
257
280
  if (!isVisible)
258
281
  return false;
282
+ // Handle reasoning effort sub-step
283
+ if (pendingReasoningModel) {
284
+ if (key.escape) {
285
+ // Go back to model selection
286
+ setPendingReasoningModel(null);
287
+ return true;
288
+ }
289
+ if (key.upArrow) {
290
+ setReasoningEffortIndex((prev) => prev > 0 ? prev - 1 : REASONING_EFFORT_OPTIONS.length - 1);
291
+ return true;
292
+ }
293
+ if (key.downArrow) {
294
+ setReasoningEffortIndex((prev) => prev < REASONING_EFFORT_OPTIONS.length - 1 ? prev + 1 : 0);
295
+ return true;
296
+ }
297
+ if (key.return) {
298
+ const selectedOption = REASONING_EFFORT_OPTIONS[reasoningEffortIndex];
299
+ const reasoningEffort = selectedOption?.value === 'auto' ? undefined : selectedOption?.value;
300
+ onSelectModel(pendingReasoningModel.provider, pendingReasoningModel.name, pendingReasoningModel.displayName, pendingReasoningModel.baseURL, reasoningEffort);
301
+ setPendingReasoningModel(null);
302
+ return true;
303
+ }
304
+ return true; // Consume all input in reasoning effort mode
305
+ }
259
306
  // Escape always works
260
307
  if (key.escape) {
261
308
  // If in action mode, just clear it first
@@ -408,7 +455,13 @@ const ModelSelector = forwardRef(function ModelSelector({ isVisible, onSelectMod
408
455
  }
409
456
  return true;
410
457
  }
411
- // Normal selection
458
+ // Normal selection - check if reasoning-capable
459
+ if (isReasoningCapableModel(item.name)) {
460
+ // Show reasoning effort sub-step
461
+ setPendingReasoningModel(item);
462
+ setReasoningEffortIndex(0); // Default to 'Auto'
463
+ return true;
464
+ }
412
465
  onSelectModel(item.provider, item.name, item.displayName, item.baseURL);
413
466
  return true;
414
467
  }
@@ -426,12 +479,21 @@ const ModelSelector = forwardRef(function ModelSelector({ isVisible, onSelectMod
426
479
  pendingDeleteConfirm,
427
480
  customModels,
428
481
  handleDeleteCustomModel,
482
+ pendingReasoningModel,
483
+ reasoningEffortIndex,
429
484
  ]);
430
485
  if (!isVisible)
431
486
  return null;
432
487
  if (isLoading) {
433
488
  return (_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "Loading models..." }) }));
434
489
  }
490
+ // Reasoning effort sub-step UI
491
+ if (pendingReasoningModel) {
492
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "cyan", bold: true, children: "Configure Reasoning Effort" }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: "gray", children: ["for ", pendingReasoningModel.displayName || pendingReasoningModel.name] }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: "\u2191\u2193 navigate, Enter select, Esc back" }) }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: '─'.repeat(50) }) }), REASONING_EFFORT_OPTIONS.map((option, index) => {
493
+ const isSelected = index === reasoningEffortIndex;
494
+ return (_jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsxs(Text, { color: isSelected ? 'cyan' : 'gray', bold: isSelected, children: [isSelected ? '› ' : ' ', option.label] }), _jsxs(Text, { color: isSelected ? 'white' : 'gray', children: [' ', "- ", option.description] })] }, option.value));
495
+ })] }));
496
+ }
435
497
  const visibleItems = filteredItems.slice(scrollOffset, scrollOffset + MAX_VISIBLE_ITEMS);
436
498
  const hasCustomModels = customModels.length > 0;
437
499
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { paddingX: 0, paddingY: 0, children: _jsxs(Text, { color: "cyan", bold: true, children: ["Select Model (", selectedIndex + 1, "/", filteredItems.length, ")"] }) }), _jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "gray", children: "\u2191\u2193 navigate, Enter select, Esc close" }), hasCustomModels && _jsx(Text, { color: "gray", children: ", \u2192\u2190 for custom actions" })] }), _jsxs(Box, { paddingX: 0, paddingY: 0, children: [_jsx(Text, { color: "gray", children: "\uD83D\uDD0D " }), _jsx(Text, { color: searchQuery ? 'white' : 'gray', children: searchQuery || 'Type to search...' }), _jsx(Text, { color: "cyan", children: "\u258C" })] }), _jsx(Box, { paddingX: 0, paddingY: 0, children: _jsx(Text, { color: "gray", children: '─'.repeat(50) }) }), visibleItems.map((item, visibleIndex) => {
@@ -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;AAGhF,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,YAAY,CAAC;AAqC7D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,mBAAmB,EAAE,cAAc,CAwWxE,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;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,mBAAmB,EAAE,CAEtE;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"}
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,CA4XxE,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;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,SAAS,mBAAmB,EAAE,CAEtE;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"}
@@ -3,7 +3,7 @@
3
3
  * Each provider has its own config with display name, description, steps, and model builder.
4
4
  */
5
5
  import { CUSTOM_MODEL_PROVIDERS } from '@dexto/agent-management';
6
- import { lookupOpenRouterModel, refreshOpenRouterModelCache, getLocalModelById } from '@dexto/core';
6
+ import { lookupOpenRouterModel, refreshOpenRouterModelCache, getLocalModelById, isReasoningCapableModel, } from '@dexto/core';
7
7
  import { validators } from './types.js';
8
8
  import * as fs from 'fs';
9
9
  import * as os from 'os';
@@ -36,6 +36,29 @@ const DISPLAY_NAME_STEP = {
36
36
  placeholder: 'e.g., My Custom Model',
37
37
  required: false,
38
38
  };
39
+ /**
40
+ * Common reasoning effort step - for OpenAI reasoning models (o1, o3, codex, gpt-5.x).
41
+ * Only shown when the model name indicates reasoning capability.
42
+ */
43
+ const REASONING_EFFORT_STEP = {
44
+ field: 'reasoningEffort',
45
+ label: 'Reasoning Effort (optional)',
46
+ placeholder: 'none | minimal | low | medium | high | xhigh (blank for auto)',
47
+ required: false,
48
+ validate: (value) => {
49
+ if (!value?.trim())
50
+ return null;
51
+ const validValues = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh'];
52
+ if (!validValues.includes(value.toLowerCase())) {
53
+ return `Invalid reasoning effort. Use: ${validValues.join(', ')}`;
54
+ }
55
+ return null;
56
+ },
57
+ condition: (values) => {
58
+ const modelName = values.name || '';
59
+ return isReasoningCapableModel(modelName);
60
+ },
61
+ };
39
62
  /**
40
63
  * Provider configuration registry.
41
64
  * Keys are CustomModelProvider values.
@@ -61,6 +84,7 @@ export const PROVIDER_CONFIGS = {
61
84
  },
62
85
  { ...DISPLAY_NAME_STEP, placeholder: 'e.g., My Local Llama 3' },
63
86
  MAX_INPUT_TOKENS_STEP,
87
+ REASONING_EFFORT_STEP,
64
88
  API_KEY_STEP,
65
89
  ],
66
90
  buildModel: (values, provider) => {
@@ -77,6 +101,10 @@ export const PROVIDER_CONFIGS = {
77
101
  if (values.maxInputTokens?.trim()) {
78
102
  model.maxInputTokens = parseInt(values.maxInputTokens, 10);
79
103
  }
104
+ if (values.reasoningEffort?.trim()) {
105
+ model.reasoningEffort =
106
+ values.reasoningEffort.toLowerCase();
107
+ }
80
108
  return model;
81
109
  },
82
110
  },
@@ -92,6 +120,7 @@ export const PROVIDER_CONFIGS = {
92
120
  validate: validators.slashFormat,
93
121
  },
94
122
  { ...DISPLAY_NAME_STEP, placeholder: 'e.g., Claude 3.5 Sonnet' },
123
+ REASONING_EFFORT_STEP,
95
124
  {
96
125
  ...API_KEY_STEP,
97
126
  placeholder: 'Saved as OPENROUTER_API_KEY if not set, otherwise per-model',
@@ -105,6 +134,10 @@ export const PROVIDER_CONFIGS = {
105
134
  if (values.displayName?.trim()) {
106
135
  model.displayName = values.displayName.trim();
107
136
  }
137
+ if (values.reasoningEffort?.trim()) {
138
+ model.reasoningEffort =
139
+ values.reasoningEffort.toLowerCase();
140
+ }
108
141
  return model;
109
142
  },
110
143
  asyncValidation: {
@@ -141,6 +174,7 @@ export const PROVIDER_CONFIGS = {
141
174
  validate: validators.slashFormat,
142
175
  },
143
176
  { ...DISPLAY_NAME_STEP, placeholder: 'e.g., GPT-4o via Glama' },
177
+ REASONING_EFFORT_STEP,
144
178
  {
145
179
  ...API_KEY_STEP,
146
180
  placeholder: 'Saved as GLAMA_API_KEY if not set, otherwise per-model',
@@ -154,6 +188,10 @@ export const PROVIDER_CONFIGS = {
154
188
  if (values.displayName?.trim()) {
155
189
  model.displayName = values.displayName.trim();
156
190
  }
191
+ if (values.reasoningEffort?.trim()) {
192
+ model.reasoningEffort =
193
+ values.reasoningEffort.toLowerCase();
194
+ }
157
195
  return model;
158
196
  },
159
197
  },
@@ -177,6 +215,7 @@ export const PROVIDER_CONFIGS = {
177
215
  },
178
216
  { ...DISPLAY_NAME_STEP, placeholder: 'e.g., My LiteLLM GPT-4' },
179
217
  MAX_INPUT_TOKENS_STEP,
218
+ REASONING_EFFORT_STEP,
180
219
  {
181
220
  ...API_KEY_STEP,
182
221
  placeholder: 'Saved as LITELLM_API_KEY if not set, otherwise per-model',
@@ -196,6 +235,10 @@ export const PROVIDER_CONFIGS = {
196
235
  if (values.maxInputTokens?.trim()) {
197
236
  model.maxInputTokens = parseInt(values.maxInputTokens, 10);
198
237
  }
238
+ if (values.reasoningEffort?.trim()) {
239
+ model.reasoningEffort =
240
+ values.reasoningEffort.toLowerCase();
241
+ }
199
242
  return model;
200
243
  },
201
244
  },
@@ -12,6 +12,12 @@ export interface WizardStep {
12
12
  placeholder: string;
13
13
  required: boolean;
14
14
  validate?: (value: string) => string | null;
15
+ /**
16
+ * Optional condition to determine if this step should be shown.
17
+ * Takes the current accumulated values and returns true if the step should be shown.
18
+ * If omitted, the step is always shown.
19
+ */
20
+ condition?: (values: Record<string, string>) => boolean;
15
21
  }
16
22
  /**
17
23
  * Props passed to each provider-specific wizard component.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/ink-cli/components/overlays/custom-model-wizard/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wCAAwC,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAC;IACtB,uCAAuC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,sDAAsD;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;IAClD,sCAAsC;IACtC,QAAQ,EAAE,MAAM,UAAU,EAAE,CAAC;IAC7B,8BAA8B;IAC9B,oBAAoB,EAAE,MAAM,UAAU,GAAG,SAAS,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,kDAAkD;IAClD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,mBAAmB,KAAK,WAAW,CAAC;IAC3F,oDAAoD;IACpD,eAAe,CAAC,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;KACvD,CAAC;IACF,sDAAsD;IACtD,SAAS,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACL;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;sBACD,MAAM,MAAM,GAAG,MAAM;aAE9B,MAAM;wBAaK,MAAM;qBAOT,MAAM;CAK1B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/cli/ink-cli/components/overlays/custom-model-wizard/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wCAAwC,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAC;IACtB,uCAAuC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,sDAAsD;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;IAClD,sCAAsC;IACtC,QAAQ,EAAE,MAAM,UAAU,EAAE,CAAC;IAC7B,8BAA8B;IAC9B,oBAAoB,EAAE,MAAM,UAAU,GAAG,SAAS,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,kDAAkD;IAClD,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,mBAAmB,KAAK,WAAW,CAAC;IAC3F,oDAAoD;IACpD,eAAe,CAAC,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;KACvD,CAAC;IACF,sDAAsD;IACtD,SAAS,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACL;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;sBACD,MAAM,MAAM,GAAG,MAAM;aAE9B,MAAM;wBAaK,MAAM;qBAOT,MAAM;CAK1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"OverlayContainer.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/containers/OverlayContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAyE,MAAM,OAAO,CAAC;AAE9F,OAAO,KAAK,EAAE,UAAU,EAAmD,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAGH,KAAK,eAAe,EACvB,MAAM,iCAAiC,CAAC;AA0EzC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK3D,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,qBAAqB;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,sGA60D5B,CAAC"}
1
+ {"version":3,"file":"OverlayContainer.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/containers/OverlayContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAyE,MAAM,OAAO,CAAC;AAE9F,OAAO,KAAK,EAAE,UAAU,EAAmD,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAGH,KAAK,eAAe,EACvB,MAAM,iCAAiC,CAAC;AA0EzC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK3D,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,qBAAqB;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,sGAm1D5B,CAAC"}
@@ -200,7 +200,7 @@ export const OverlayContainer = forwardRef(function OverlayContainer({ ui, input
200
200
  return null;
201
201
  };
202
202
  // Handle model selection
203
- const handleModelSelect = useCallback(async (provider, model, displayName, baseURL) => {
203
+ const handleModelSelect = useCallback(async (provider, model, displayName, baseURL, reasoningEffort) => {
204
204
  setUi((prev) => ({ ...prev, activeOverlay: 'none', mcpWizardServerType: null }));
205
205
  buffer.setText('');
206
206
  setInput((prev) => ({ ...prev, historyIndex: -1 }));
@@ -214,7 +214,7 @@ export const OverlayContainer = forwardRef(function OverlayContainer({ ui, input
214
214
  timestamp: new Date(),
215
215
  },
216
216
  ]);
217
- await agent.switchLLM({ provider: provider, model, baseURL }, session.id || undefined);
217
+ await agent.switchLLM({ provider: provider, model, baseURL, reasoningEffort }, session.id || undefined);
218
218
  // Update session state with display name (fallback to model ID)
219
219
  setSession((prev) => ({ ...prev, modelName: displayName || model }));
220
220
  setMessages((prev) => [
@@ -11,6 +11,8 @@
11
11
  * - session:created - New session creation (e.g., from /clear)
12
12
  * - message:queued - New message added to queue
13
13
  * - message:removed - Message removed from queue (e.g., up arrow edit)
14
+ * - run:invoke - External trigger (scheduler, A2A, API) starting a run
15
+ * - run:complete (for external triggers) - External run finished
14
16
  *
15
17
  * Uses AbortController pattern for cleanup.
16
18
  */
@@ -21,16 +23,21 @@ import type { ApprovalRequest } from '../components/ApprovalPrompt.js';
21
23
  interface UseAgentEventsProps {
22
24
  agent: DextoAgent;
23
25
  setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
26
+ setPendingMessages: React.Dispatch<React.SetStateAction<Message[]>>;
24
27
  setUi: React.Dispatch<React.SetStateAction<UIState>>;
25
28
  setSession: React.Dispatch<React.SetStateAction<SessionState>>;
26
29
  setApproval: React.Dispatch<React.SetStateAction<ApprovalRequest | null>>;
27
30
  setApprovalQueue: React.Dispatch<React.SetStateAction<ApprovalRequest[]>>;
28
31
  setQueuedMessages: React.Dispatch<React.SetStateAction<QueuedMessage[]>>;
32
+ /** Current session ID for filtering events */
33
+ currentSessionId: string | null;
29
34
  }
30
35
  /**
31
36
  * Subscribes to agent event bus for non-streaming events only.
32
37
  * Streaming events are handled via agent.stream() iterator.
38
+ *
39
+ * Also handles external triggers (run:invoke) from scheduler, A2A, etc.
33
40
  */
34
- export declare function useAgentEvents({ agent, setMessages, setUi, setSession, setApproval, setApprovalQueue, setQueuedMessages, }: UseAgentEventsProps): void;
41
+ export declare function useAgentEvents({ agent, setMessages, setPendingMessages, setUi, setSession, setApproval, setApprovalQueue, setQueuedMessages, currentSessionId, }: UseAgentEventsProps): void;
35
42
  export {};
36
43
  //# sourceMappingURL=useAgentEvents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAgentEvents.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/hooks/useAgentEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAuB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,UAAU,mBAAmB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;CAC5E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,KAAK,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,iBAAiB,GACpB,EAAE,mBAAmB,GAAG,IAAI,CAqH5B"}
1
+ {"version":3,"file":"useAgentEvents.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/hooks/useAgentEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAEH,KAAK,UAAU,EACf,KAAK,aAAa,EAErB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGvE,UAAU,mBAAmB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAYD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,EACL,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GACnB,EAAE,mBAAmB,GAAG,IAAI,CAqS5B"}
@@ -11,23 +11,39 @@
11
11
  * - session:created - New session creation (e.g., from /clear)
12
12
  * - message:queued - New message added to queue
13
13
  * - message:removed - Message removed from queue (e.g., up arrow edit)
14
+ * - run:invoke - External trigger (scheduler, A2A, API) starting a run
15
+ * - run:complete (for external triggers) - External run finished
14
16
  *
15
17
  * Uses AbortController pattern for cleanup.
16
18
  */
17
- import { useEffect } from 'react';
19
+ import { useEffect, useRef } from 'react';
18
20
  import { setMaxListeners } from 'events';
19
- import { getModelDisplayName } from '@dexto/core';
21
+ import { getModelDisplayName, } from '@dexto/core';
22
+ import { generateMessageId } from '../utils/idGenerator.js';
23
+ /**
24
+ * Extract text content from ContentPart array
25
+ */
26
+ function extractTextContent(content) {
27
+ return content
28
+ .filter((part) => part.type === 'text')
29
+ .map((part) => part.text)
30
+ .join('\n');
31
+ }
20
32
  /**
21
33
  * Subscribes to agent event bus for non-streaming events only.
22
34
  * Streaming events are handled via agent.stream() iterator.
35
+ *
36
+ * Also handles external triggers (run:invoke) from scheduler, A2A, etc.
23
37
  */
24
- export function useAgentEvents({ agent, setMessages, setUi, setSession, setApproval, setApprovalQueue, setQueuedMessages, }) {
38
+ export function useAgentEvents({ agent, setMessages, setPendingMessages, setUi, setSession, setApproval, setApprovalQueue, setQueuedMessages, currentSessionId, }) {
39
+ // Track if an external trigger is active (scheduler, A2A, etc.)
40
+ const externalTriggerRef = useRef({ active: false, sessionId: null, messageId: null });
25
41
  useEffect(() => {
26
42
  const bus = agent.agentEventBus;
27
43
  const controller = new AbortController();
28
44
  const { signal } = controller;
29
- // Increase listener limit for safety
30
- setMaxListeners(15, signal);
45
+ // Increase listener limit for safety (added more for external trigger events)
46
+ setMaxListeners(25, signal);
31
47
  // NOTE: approval:request is now handled in processStream (via iterator) for proper
32
48
  // event ordering. Direct bus subscription here caused a race condition where
33
49
  // approval UI showed before text messages were added.
@@ -97,9 +113,131 @@ export function useAgentEvents({ agent, setMessages, setUi, setSession, setAppro
97
113
  }, { signal });
98
114
  // Note: message:dequeued is handled in processStream (via iterator) for proper synchronization
99
115
  // with streaming events. Don't handle it here via event bus.
116
+ // ============================================================================
117
+ // EXTERNAL TRIGGER HANDLING (scheduler, A2A, API)
118
+ // When an external source invokes the agent, we receive events here instead of
119
+ // through processStream (which only handles user-initiated streams).
120
+ // ============================================================================
121
+ // Handle external trigger invocation (scheduler, A2A, API)
122
+ bus.on('run:invoke', (payload) => {
123
+ // Only handle if this is for the current session
124
+ if (payload.sessionId !== currentSessionId) {
125
+ return;
126
+ }
127
+ // Mark external trigger as active
128
+ const messageId = generateMessageId('assistant');
129
+ externalTriggerRef.current = {
130
+ active: true,
131
+ sessionId: payload.sessionId,
132
+ messageId,
133
+ };
134
+ // Extract prompt text from content parts
135
+ const promptText = extractTextContent(payload.content);
136
+ // Add the scheduled prompt as a "user" message with a source indicator
137
+ const sourceLabel = payload.source === 'scheduler'
138
+ ? '⏰ Scheduled Task'
139
+ : payload.source === 'a2a'
140
+ ? '🤖 A2A Request'
141
+ : payload.source === 'api'
142
+ ? '🔌 API Request'
143
+ : '📥 External Request';
144
+ setMessages((prev) => [
145
+ ...prev,
146
+ {
147
+ id: generateMessageId('system'),
148
+ role: 'system',
149
+ content: `${sourceLabel}`,
150
+ timestamp: new Date(),
151
+ },
152
+ {
153
+ id: generateMessageId('user'),
154
+ role: 'user',
155
+ content: promptText,
156
+ timestamp: new Date(),
157
+ },
158
+ ]);
159
+ // Set processing state
160
+ setUi((prev) => ({
161
+ ...prev,
162
+ isProcessing: true,
163
+ isThinking: true,
164
+ }));
165
+ // Add assistant pending message for streaming
166
+ setPendingMessages([
167
+ {
168
+ id: messageId,
169
+ role: 'assistant',
170
+ content: '',
171
+ timestamp: new Date(),
172
+ isStreaming: true,
173
+ },
174
+ ]);
175
+ }, { signal });
176
+ // Handle streaming chunks for external triggers
177
+ bus.on('llm:chunk', (payload) => {
178
+ // Only handle if this is for an active external trigger
179
+ if (!externalTriggerRef.current.active ||
180
+ payload.sessionId !== externalTriggerRef.current.sessionId) {
181
+ return;
182
+ }
183
+ // Only handle text chunks (not reasoning)
184
+ if (payload.chunkType !== 'text') {
185
+ return;
186
+ }
187
+ // Update pending message with new content
188
+ setPendingMessages((prev) => prev.map((msg) => msg.id === externalTriggerRef.current.messageId
189
+ ? { ...msg, content: msg.content + payload.content }
190
+ : msg));
191
+ // Clear thinking state once we start receiving chunks
192
+ setUi((prev) => (prev.isThinking ? { ...prev, isThinking: false } : prev));
193
+ }, { signal });
194
+ // Handle LLM thinking for external triggers
195
+ bus.on('llm:thinking', (payload) => {
196
+ if (!externalTriggerRef.current.active ||
197
+ payload.sessionId !== externalTriggerRef.current.sessionId) {
198
+ return;
199
+ }
200
+ setUi((prev) => ({ ...prev, isThinking: true }));
201
+ }, { signal });
202
+ // Handle run completion for external triggers
203
+ bus.on('run:complete', (payload) => {
204
+ // Only handle if this is for an active external trigger
205
+ if (!externalTriggerRef.current.active ||
206
+ payload.sessionId !== externalTriggerRef.current.sessionId) {
207
+ return;
208
+ }
209
+ // Finalize the pending message
210
+ setPendingMessages((prev) => {
211
+ const pendingMsg = prev.find((m) => m.id === externalTriggerRef.current.messageId);
212
+ if (pendingMsg) {
213
+ // Move to finalized messages
214
+ setMessages((msgs) => [...msgs, { ...pendingMsg, isStreaming: false }]);
215
+ }
216
+ // Clear pending
217
+ return prev.filter((m) => m.id !== externalTriggerRef.current.messageId);
218
+ });
219
+ // Clear processing state
220
+ setUi((prev) => ({
221
+ ...prev,
222
+ isProcessing: false,
223
+ isThinking: false,
224
+ }));
225
+ // Reset external trigger tracking
226
+ externalTriggerRef.current = { active: false, sessionId: null, messageId: null };
227
+ }, { signal });
100
228
  // Cleanup: abort controller removes all listeners at once
101
229
  return () => {
102
230
  controller.abort();
103
231
  };
104
- }, [agent, setMessages, setUi, setSession, setApproval, setApprovalQueue, setQueuedMessages]);
232
+ }, [
233
+ agent,
234
+ setMessages,
235
+ setPendingMessages,
236
+ setUi,
237
+ setSession,
238
+ setApproval,
239
+ setApprovalQueue,
240
+ setQueuedMessages,
241
+ currentSessionId,
242
+ ]);
105
243
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useCLIState.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/hooks/useCLIState.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAEjF,OAAO,EAAuB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAGrF,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE3E,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,UAAU,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC;IACzB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,cAAc;IAE3B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAE7D,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAGpE,cAAc,EAAE,OAAO,EAAE,CAAC;IAC1B,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAEnE,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,aAAa,EAAE,eAAe,EAAE,CAAC;IACjC,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAG1E,MAAM,EAAE,UAAU,CAAC;IAGnB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,cAAc,CAAC;IAG/B,mBAAmB,EAAE,KAAK,CAAC,SAAS,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAGpE,eAAe,EAAE,OAAO,EAAE,CAAC;IAG3B,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC5B;AAED,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAAE,iBAAiB,GACtC,EAAE,gBAAgB,GAAG,cAAc,CAgMnC"}
1
+ {"version":3,"file":"useCLIState.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/hooks/useCLIState.ts"],"names":[],"mappings":"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"}