dexto 1.6.20 → 1.6.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/agents/coding-agent/coding-agent.yml +1 -0
- package/dist/api/server-hono.d.ts.map +1 -1
- package/dist/api/server-hono.js +7 -3
- package/dist/cli/commands/helpers/formatters.d.ts.map +1 -1
- package/dist/cli/commands/helpers/formatters.js +2 -0
- package/dist/cli/commands/setup.d.ts +5 -0
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +33 -12
- package/dist/cli/modes/cli.d.ts.map +1 -1
- package/dist/cli/modes/cli.js +90 -16
- package/dist/cli/utils/dexto-setup.d.ts +1 -1
- package/dist/cli/utils/dexto-setup.js +1 -1
- package/dist/cli/utils/setup-utils.d.ts +2 -3
- package/dist/cli/utils/setup-utils.d.ts.map +1 -1
- package/dist/cli/utils/setup-utils.js +34 -12
- package/dist/config/cli-overrides.d.ts +9 -1
- package/dist/config/cli-overrides.d.ts.map +1 -1
- package/dist/config/cli-overrides.js +57 -0
- package/dist/index-main.js +49 -33
- package/dist/webui/assets/index-DlW-GIHG.js +1613 -0
- package/dist/webui/assets/index-cNwNJ0w6.css +1 -0
- package/dist/webui/index.html +2 -2
- package/package.json +12 -12
- package/dist/webui/assets/index-4kADt2zR.css +0 -1
- package/dist/webui/assets/index-DTNr4Gaw.js +0 -1613
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* - Agent capability requirements (requires: { vision: true, toolUse: true })
|
|
19
19
|
* - Merge strategy configuration for non-LLM fields
|
|
20
20
|
*/
|
|
21
|
+
import { EnvExpandedString, LLM_PROVIDERS, getDefaultModelForProvider, requiresApiKey, requiresBaseURL, resolveApiKeyForProvider, } from '@dexto/core';
|
|
21
22
|
/**
|
|
22
23
|
* Applies CLI overrides to an agent configuration
|
|
23
24
|
* This merges CLI arguments into the base config without validation.
|
|
@@ -96,6 +97,62 @@ export function applyUserPreferences(baseConfig, preferences) {
|
|
|
96
97
|
}
|
|
97
98
|
return mergedConfig;
|
|
98
99
|
}
|
|
100
|
+
export function applyStartupLLMFallback(baseConfig, options) {
|
|
101
|
+
const mergedConfig = JSON.parse(JSON.stringify(baseConfig));
|
|
102
|
+
if (options.hasCompletedSetup ||
|
|
103
|
+
options.hasExplicitProviderOverride ||
|
|
104
|
+
options.hasExplicitModelOverride ||
|
|
105
|
+
options.hasExplicitApiKeyOverride) {
|
|
106
|
+
return mergedConfig;
|
|
107
|
+
}
|
|
108
|
+
if (hasUsableCredentials(mergedConfig.llm.provider, mergedConfig.llm)) {
|
|
109
|
+
return mergedConfig;
|
|
110
|
+
}
|
|
111
|
+
for (const provider of LLM_PROVIDERS) {
|
|
112
|
+
if (!hasExplicitStartupFallbackConfiguration(provider)) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const model = getDefaultModelForProvider(provider);
|
|
116
|
+
if (!model) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
mergedConfig.llm.provider = provider;
|
|
120
|
+
mergedConfig.llm.model = model;
|
|
121
|
+
delete mergedConfig.llm.baseURL;
|
|
122
|
+
const apiKey = resolveApiKeyForProvider(provider);
|
|
123
|
+
if (apiKey) {
|
|
124
|
+
mergedConfig.llm.apiKey = apiKey;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
delete mergedConfig.llm.apiKey;
|
|
128
|
+
}
|
|
129
|
+
return mergedConfig;
|
|
130
|
+
}
|
|
131
|
+
return mergedConfig;
|
|
132
|
+
}
|
|
133
|
+
function hasExplicitStartupFallbackConfiguration(provider) {
|
|
134
|
+
if (resolveApiKeyForProvider(provider)?.trim()) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
if (requiresBaseURL(provider) && process.env.OPENAI_BASE_URL?.trim()) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
export function hasUsableCredentials(provider, llmConfig) {
|
|
143
|
+
const baseURL = llmConfig?.baseURL ? EnvExpandedString().parse(llmConfig.baseURL) : undefined;
|
|
144
|
+
if (requiresBaseURL(provider) && !baseURL?.trim()) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if (!requiresApiKey(provider)) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
const inlineApiKey = llmConfig?.apiKey ? EnvExpandedString().parse(llmConfig.apiKey) : '';
|
|
151
|
+
if (inlineApiKey.trim()) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
return Boolean(resolveApiKeyForProvider(provider)?.trim());
|
|
155
|
+
}
|
|
99
156
|
/**
|
|
100
157
|
* Check if user's current setup is compatible with an agent's requirements.
|
|
101
158
|
* Used when switching to non-default agents to warn users about potential issues.
|
package/dist/index-main.js
CHANGED
|
@@ -48,7 +48,7 @@ import { applyImageDefaults, cleanNullValues, AgentConfigSchema, loadImage, reso
|
|
|
48
48
|
import { getDextoPackageRoot, resolveAgentPath, loadAgentConfig, findDextoProjectRoot, globalPreferencesExist, loadGlobalPreferences, resolveBundledScript, enrichAgentConfig, isDextoAuthEnabled, } from '@dexto/agent-management';
|
|
49
49
|
import { validateCliOptions, handleCliOptionsError } from './cli/utils/options.js';
|
|
50
50
|
import { validateAgentConfig } from './cli/utils/config-validation.js';
|
|
51
|
-
import { applyCLIOverrides, applyUserPreferences } from './config/cli-overrides.js';
|
|
51
|
+
import { applyCLIOverrides, applyStartupLLMFallback, applyUserPreferences, } from './config/cli-overrides.js';
|
|
52
52
|
import { registerRunCommand } from './cli/commands/run/register.js';
|
|
53
53
|
import { registerSessionCommand } from './cli/commands/session/register.js';
|
|
54
54
|
import { registerSearchCommand } from './cli/commands/search/register.js';
|
|
@@ -112,7 +112,7 @@ program
|
|
|
112
112
|
.option('--no-elicitation', 'Disable elicitation (agent cannot prompt user for input)')
|
|
113
113
|
.option('-c, --continue', 'Continue most recent session (CLI mode)')
|
|
114
114
|
.option('-r, --resume <sessionId>', 'Resume a session by ID (CLI mode)')
|
|
115
|
-
.option('--mode <mode>', 'The application in which dexto should talk to you - web | cli | server | mcp', '
|
|
115
|
+
.option('--mode <mode>', 'The application in which dexto should talk to you - web | cli | server | mcp', 'cli')
|
|
116
116
|
.option('--port <port>', 'port for the server (default: 3000 for web, 3001 for server mode)')
|
|
117
117
|
.option('--no-auto-install', 'Disable automatic installation of missing agents from registry')
|
|
118
118
|
.option('--image <package>', 'Image package to load (e.g., @dexto/image-local). Overrides config image field.')
|
|
@@ -387,8 +387,8 @@ program
|
|
|
387
387
|
// Main customer facing description
|
|
388
388
|
.description('Dexto CLI - AI-powered assistant with session management.\n\n' +
|
|
389
389
|
'Basic Usage:\n' +
|
|
390
|
-
' dexto
|
|
391
|
-
' dexto --mode
|
|
390
|
+
' dexto or dexto --mode cli Start interactive CLI (default)\n' +
|
|
391
|
+
' dexto --mode web Start web UI\n' +
|
|
392
392
|
' dexto --prompt "query" Start interactive CLI and run the prompt\n' +
|
|
393
393
|
' dexto run "query" Run one-off headless task\n\n' +
|
|
394
394
|
'Session Management Commands:\n' +
|
|
@@ -451,8 +451,8 @@ program
|
|
|
451
451
|
// the first positional argument as an agent name to avoid ambiguity with prompts.
|
|
452
452
|
// ——— FORCE CLI MODE FOR PROMPT/SESSION FLAGS ———
|
|
453
453
|
// If a prompt or session flag was provided, force CLI mode.
|
|
454
|
-
|
|
455
|
-
|
|
454
|
+
const modeForcedByChatFlags = Boolean(initialPrompt || opts.continue || opts.resume || opts.cloudAgent);
|
|
455
|
+
if (modeForcedByChatFlags && opts.mode !== 'cli') {
|
|
456
456
|
console.error(`ℹ️ Forcing CLI mode due to --prompt/--continue/--resume/--cloud-agent.`);
|
|
457
457
|
console.error(` Original mode: ${opts.mode} → Overridden to: cli`);
|
|
458
458
|
opts.mode = 'cli';
|
|
@@ -524,7 +524,34 @@ program
|
|
|
524
524
|
// Determine validation mode early - used throughout config loading and agent creation
|
|
525
525
|
// Use relaxed validation for interactive modes (web/cli) where users can configure later
|
|
526
526
|
// Use strict validation for non-interactive modes (server/mcp) that need full config upfront
|
|
527
|
-
|
|
527
|
+
let isInteractiveMode = opts.mode === 'web' || opts.mode === 'cli';
|
|
528
|
+
const shouldCheckSetupState = !opts.skipSetup && !(opts.agent && isPath(opts.agent));
|
|
529
|
+
let setupRequired = false;
|
|
530
|
+
if (shouldCheckSetupState) {
|
|
531
|
+
const { requiresSetup } = await import('./cli/utils/setup-utils.js');
|
|
532
|
+
setupRequired = await requiresSetup();
|
|
533
|
+
}
|
|
534
|
+
const canRunInteractiveSetup = isInteractiveMode && opts.interactive !== false;
|
|
535
|
+
if (setupRequired && !canRunInteractiveSetup) {
|
|
536
|
+
console.error('❌ Setup required before starting in this mode.');
|
|
537
|
+
console.error('💡 Run `dexto setup` first, or use --skip-setup to bypass global setup.');
|
|
538
|
+
safeExit('main', 1, 'setup-required-non-interactive');
|
|
539
|
+
}
|
|
540
|
+
const shouldRunSetupBeforeStartup = setupRequired && canRunInteractiveSetup && !opts.provider && !opts.model;
|
|
541
|
+
if (shouldRunSetupBeforeStartup) {
|
|
542
|
+
const { handleSetupCommand } = await import('./cli/commands/setup.js');
|
|
543
|
+
await handleSetupCommand({
|
|
544
|
+
interactive: true,
|
|
545
|
+
defaultMode: opts.mode === 'cli' ? 'cli' : undefined,
|
|
546
|
+
});
|
|
547
|
+
if (!explicitModeProvided && !modeForcedByChatFlags) {
|
|
548
|
+
const preferences = await loadGlobalPreferences();
|
|
549
|
+
if (preferences.defaults.defaultMode) {
|
|
550
|
+
opts.mode = preferences.defaults.defaultMode;
|
|
551
|
+
}
|
|
552
|
+
isInteractiveMode = opts.mode === 'web' || opts.mode === 'cli';
|
|
553
|
+
}
|
|
554
|
+
}
|
|
528
555
|
try {
|
|
529
556
|
// Case 1: File path - skip all validation and setup
|
|
530
557
|
if (opts.agent && isPath(opts.agent)) {
|
|
@@ -559,31 +586,9 @@ program
|
|
|
559
586
|
// Continue anyway - resolver will handle it
|
|
560
587
|
}
|
|
561
588
|
}
|
|
562
|
-
//
|
|
563
|
-
//
|
|
564
|
-
|
|
565
|
-
if (!opts.skipSetup && (await requiresSetup())) {
|
|
566
|
-
if (opts.interactive === false) {
|
|
567
|
-
console.error('❌ Setup required but --no-interactive flag is set.');
|
|
568
|
-
console.error('💡 Run `dexto setup` first, or use --skip-setup to bypass global setup.');
|
|
569
|
-
safeExit('main', 1, 'setup-required-non-interactive');
|
|
570
|
-
}
|
|
571
|
-
const { handleSetupCommand } = await import('./cli/commands/setup.js');
|
|
572
|
-
await handleSetupCommand({ interactive: true });
|
|
573
|
-
// Reload preferences after setup to get the newly selected default mode
|
|
574
|
-
// (setup may have just saved a different mode than the default 'web')
|
|
575
|
-
try {
|
|
576
|
-
const newPreferences = await loadGlobalPreferences();
|
|
577
|
-
if (newPreferences.defaults?.defaultMode) {
|
|
578
|
-
opts.mode = newPreferences.defaults.defaultMode;
|
|
579
|
-
logger.debug(`Updated mode from setup preferences: ${opts.mode}`);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
catch {
|
|
583
|
-
// Ignore errors - will use default mode
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
// Now resolve agent (will auto-install since setup is complete)
|
|
589
|
+
// Resolve the configured agent after setup has been established for
|
|
590
|
+
// interactive startup. This keeps provider selection generic instead of
|
|
591
|
+
// letting bundled agent defaults decide first-run behavior.
|
|
587
592
|
resolvedPath = await resolveAgentPath(opts.agent, opts.autoInstall !== false);
|
|
588
593
|
if (opts.interactive !== false) {
|
|
589
594
|
const { getBundledSyncTargetForAgentPath, shouldPromptForSync, handleSyncAgentsCommand, } = await import('./cli/commands/agents/sync.js');
|
|
@@ -611,9 +616,11 @@ program
|
|
|
611
616
|
// See feature-plans/auto-update.md section 8.11 - Three-Layer LLM Resolution
|
|
612
617
|
const agentId = opts.agent ?? 'coding-agent';
|
|
613
618
|
let preferences = null;
|
|
619
|
+
let hasCompletedSetup = false;
|
|
614
620
|
if (globalPreferencesExist()) {
|
|
615
621
|
try {
|
|
616
622
|
preferences = await loadGlobalPreferences();
|
|
623
|
+
hasCompletedSetup = preferences.setup.completed;
|
|
617
624
|
}
|
|
618
625
|
catch {
|
|
619
626
|
// Preferences exist but couldn't load - continue without them
|
|
@@ -646,6 +653,7 @@ program
|
|
|
646
653
|
await handleSetupCommand({ interactive: true, force: true });
|
|
647
654
|
// Reload preferences after setup
|
|
648
655
|
preferences = await loadGlobalPreferences();
|
|
656
|
+
hasCompletedSetup = preferences.setup.completed;
|
|
649
657
|
}
|
|
650
658
|
else {
|
|
651
659
|
// User cancelled
|
|
@@ -689,7 +697,15 @@ program
|
|
|
689
697
|
// See feature-plans/auto-update.md section 8.11 - Three-Layer LLM Resolution:
|
|
690
698
|
// local.llm ?? preferences.llm ?? bundled.llm
|
|
691
699
|
// The preferences.llm acts as a "global .local.yml" for LLM settings
|
|
692
|
-
|
|
700
|
+
mergedConfig = applyStartupLLMFallback(mergedConfig, {
|
|
701
|
+
hasCompletedSetup,
|
|
702
|
+
hasExplicitProviderOverride: Boolean(opts.provider),
|
|
703
|
+
hasExplicitModelOverride: Boolean(opts.model),
|
|
704
|
+
hasExplicitApiKeyOverride: Boolean(opts.apiKey),
|
|
705
|
+
});
|
|
706
|
+
if (hasCompletedSetup &&
|
|
707
|
+
preferences?.llm?.provider &&
|
|
708
|
+
preferences?.llm?.model) {
|
|
693
709
|
mergedConfig = applyUserPreferences(mergedConfig, preferences);
|
|
694
710
|
logger.debug(`Applied user preferences to ${agentId}`, {
|
|
695
711
|
provider: preferences.llm.provider,
|