dexto 1.6.14 → 1.6.16

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.
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6DxB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0ClB,CAAC;AAEP,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAClE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AA6JtE;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC9F"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+DxB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0ClB,CAAC;AAEP,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAClE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAqKtE;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC9F"}
@@ -1,12 +1,15 @@
1
1
  // packages/cli/src/cli/commands/setup.ts
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
2
4
  import chalk from 'chalk';
3
5
  import { z } from 'zod';
4
6
  import open from 'open';
5
7
  import { acceptsAnyModel, CodexAppServerClient, createCodexBaseURL, getDefaultModelForProvider, getCodexAuthModeLabel, getCodexProviderDisplayName, getCuratedModelsForProvider, getReasoningProfile, getSupportedModels, isCodexBaseURL, LLM_PROVIDERS, LLM_REGISTRY, logger, parseCodexBaseURL, isValidProviderModel, supportsCustomModels, requiresApiKey, resolveApiKeyForProvider, } from '@dexto/core';
6
- import { createInitialPreferences, saveGlobalPreferences, loadGlobalPreferences, getGlobalPreferencesPath, updateGlobalPreferences, setActiveModel, isDextoAuthEnabled, loadCustomModels, saveCustomModel, deleteCustomModel, globalPreferencesExist, } from '@dexto/agent-management';
8
+ import { createInitialPreferences, saveGlobalPreferences, loadGlobalPreferences, getGlobalPreferencesPath, updateGlobalPreferences, setActiveModel, isDextoAuthEnabled, loadCustomModels, saveCustomModel, deleteCustomModel, globalPreferencesExist, getDextoGlobalPath, } from '@dexto/agent-management';
7
9
  import { interactiveApiKeySetup, hasApiKeyConfigured } from '../utils/api-key-setup.js';
8
10
  import { selectProvider, getProviderDisplayName, getProviderEnvVar, providerRequiresBaseURL, getDefaultModel, } from '../utils/provider-setup.js';
9
11
  import { setupLocalModels, setupOllamaModels, hasSelectedModel, getModelFromResult, } from '../utils/local-model-setup.js';
12
+ import { executeCommand } from '../utils/self-management.js';
10
13
  import { requiresSetup } from '../utils/setup-utils.js';
11
14
  import { canUseDextoProvider } from '../utils/dexto-setup.js';
12
15
  import { handleAutoLogin } from './auth/login.js';
@@ -69,6 +72,13 @@ const REASONING_VARIANT_HINTS = {
69
72
  max: 'Maximum reasoning within provider limits',
70
73
  xhigh: 'Extra high reasoning',
71
74
  };
75
+ const OPENAI_CODEX_PACKAGE = '@openai/codex';
76
+ const DEXTO_DEPS_PACKAGE_JSON = {
77
+ name: 'dexto-deps',
78
+ version: '1.0.0',
79
+ private: true,
80
+ description: 'Managed dependencies for Dexto',
81
+ };
72
82
  function toReasoningVariantLabel(variant, defaultVariant) {
73
83
  const normalized = variant.toLowerCase();
74
84
  const withKnownCasing = normalized === 'xhigh'
@@ -420,6 +430,104 @@ function getConfiguredProviderDisplayName(provider, baseURL) {
420
430
  function isCodexConfigured(provider, baseURL) {
421
431
  return provider === 'openai-compatible' && isCodexBaseURL(baseURL);
422
432
  }
433
+ async function ensureDextoDepsPackageJson() {
434
+ const depsDir = getDextoGlobalPath('deps');
435
+ await fs.mkdir(depsDir, { recursive: true });
436
+ const packageJsonPath = path.join(depsDir, 'package.json');
437
+ try {
438
+ await fs.access(packageJsonPath);
439
+ }
440
+ catch (error) {
441
+ if (error.code !== 'ENOENT') {
442
+ throw error;
443
+ }
444
+ await fs.writeFile(packageJsonPath, JSON.stringify(DEXTO_DEPS_PACKAGE_JSON, null, 2), 'utf-8');
445
+ }
446
+ return depsDir;
447
+ }
448
+ function isMissingCodexCliError(error) {
449
+ if (!(error instanceof Error)) {
450
+ return false;
451
+ }
452
+ const code = error.code;
453
+ return (error.message.includes('Codex CLI not found on PATH') ||
454
+ error.message.includes('spawn codex ENOENT') ||
455
+ (code === 'ENOENT' && error.message.includes('spawn')));
456
+ }
457
+ function getCodexSetupErrorMessage(error) {
458
+ if (isMissingCodexCliError(error)) {
459
+ return 'Codex CLI not found on PATH. Install Codex to use ChatGPT Login in Dexto.';
460
+ }
461
+ return error instanceof Error ? error.message : String(error);
462
+ }
463
+ async function resolveCodexInstaller() {
464
+ const candidates = [
465
+ {
466
+ command: 'npm',
467
+ args: ['install', OPENAI_CODEX_PACKAGE, '--no-audit', '--no-fund'],
468
+ label: 'npm',
469
+ },
470
+ {
471
+ command: 'pnpm',
472
+ args: ['add', OPENAI_CODEX_PACKAGE],
473
+ label: 'pnpm',
474
+ },
475
+ {
476
+ command: 'bun',
477
+ args: ['add', OPENAI_CODEX_PACKAGE],
478
+ label: 'bun',
479
+ },
480
+ ];
481
+ for (const candidate of candidates) {
482
+ const probe = await executeCommand(candidate.command, ['--version']);
483
+ if (probe.code === 0) {
484
+ return candidate;
485
+ }
486
+ }
487
+ return null;
488
+ }
489
+ function getCodexInstallerFailureMessage(installer, result) {
490
+ const details = `${result.stderr}\n${result.stdout}`
491
+ .split(/\r?\n/)
492
+ .map((line) => line.trim())
493
+ .filter((line) => line.length > 0);
494
+ const lastLine = details.at(-1);
495
+ return lastLine
496
+ ? `Failed to install the OpenAI Codex CLI via ${installer.label}: ${lastLine}`
497
+ : `Failed to install the OpenAI Codex CLI via ${installer.label}.`;
498
+ }
499
+ async function installManagedCodexCli() {
500
+ const depsDir = await ensureDextoDepsPackageJson();
501
+ const installer = await resolveCodexInstaller();
502
+ if (!installer) {
503
+ throw new Error('Could not find npm, pnpm, or bun to install the OpenAI Codex CLI automatically.');
504
+ }
505
+ const result = await executeCommand(installer.command, installer.args, { cwd: depsDir });
506
+ if (result.code !== 0) {
507
+ throw new Error(getCodexInstallerFailureMessage(installer, result));
508
+ }
509
+ }
510
+ async function createCodexClientForSetup() {
511
+ try {
512
+ return await CodexAppServerClient.create();
513
+ }
514
+ catch (error) {
515
+ if (!isMissingCodexCliError(error)) {
516
+ throw error;
517
+ }
518
+ const spinner = p.spinner();
519
+ spinner.start('Installing OpenAI Codex CLI...');
520
+ try {
521
+ await installManagedCodexCli();
522
+ spinner.stop('OpenAI Codex CLI installed');
523
+ }
524
+ catch (installError) {
525
+ spinner.stop('OpenAI Codex CLI installation failed');
526
+ throw installError;
527
+ }
528
+ return await CodexAppServerClient.create();
529
+ }
530
+ }
423
531
  async function ensureCodexChatGPTLogin(client) {
424
532
  const spinner = p.spinner();
425
533
  spinner.start('Starting ChatGPT login with Codex...');
@@ -510,7 +618,7 @@ async function handleCodexProviderSetup(options = {}) {
510
618
  console.log(chalk.cyan('\nChatGPT Login Setup\n'));
511
619
  let client = null;
512
620
  try {
513
- client = await CodexAppServerClient.create();
621
+ client = await createCodexClientForSetup();
514
622
  const account = await ensureCodexChatGPTSession(client);
515
623
  if (!account || account.account?.type !== 'chatgpt') {
516
624
  return abort('Setup cancelled');
@@ -579,7 +687,7 @@ async function handleCodexProviderSetup(options = {}) {
579
687
  return true;
580
688
  }
581
689
  catch (error) {
582
- const errorMessage = error instanceof Error ? error.message : String(error);
690
+ const errorMessage = getCodexSetupErrorMessage(error);
583
691
  p.log.error(`ChatGPT Login setup failed: ${errorMessage}`);
584
692
  return abort('Setup cancelled', 1);
585
693
  }
@@ -601,7 +709,7 @@ async function handleCodexChatGPTLoginRefresh(options = {}) {
601
709
  console.log(chalk.cyan('\nChatGPT Login\n'));
602
710
  let client = null;
603
711
  try {
604
- client = await CodexAppServerClient.create();
712
+ client = await createCodexClientForSetup();
605
713
  const account = await ensureCodexChatGPTSession(client);
606
714
  if (!account || account.account?.type !== 'chatgpt') {
607
715
  return abort('ChatGPT login cancelled');
@@ -610,7 +718,7 @@ async function handleCodexChatGPTLoginRefresh(options = {}) {
610
718
  return true;
611
719
  }
612
720
  catch (error) {
613
- const errorMessage = error instanceof Error ? error.message : String(error);
721
+ const errorMessage = getCodexSetupErrorMessage(error);
614
722
  p.log.error(`ChatGPT Login failed: ${errorMessage}`);
615
723
  return abort('ChatGPT login cancelled', 1);
616
724
  }
@@ -0,0 +1,2 @@
1
+ export declare function ensureImageImporterConfigured(): Promise<void>;
2
+ //# sourceMappingURL=image-importer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-importer.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/image-importer.ts"],"names":[],"mappings":"AAKA,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAOnE"}
@@ -0,0 +1,10 @@
1
+ import { setImageImporter } from '@dexto/agent-config';
2
+ import { importImageModule } from './image-store.js';
3
+ let imageImporterConfigured = false;
4
+ export async function ensureImageImporterConfigured() {
5
+ if (imageImporterConfigured) {
6
+ return;
7
+ }
8
+ setImageImporter((specifier) => importImageModule(specifier));
9
+ imageImporterConfigured = true;
10
+ }
@@ -8,6 +8,7 @@ import * as p from '@clack/prompts';
8
8
  type SelectOptions = Parameters<typeof p.select>[0];
9
9
  type TextOptions = Parameters<typeof p.text>[0];
10
10
  type ConfirmOptions = Parameters<typeof p.confirm>[0];
11
+ type MultiselectOptions = Parameters<typeof p.multiselect>[0];
11
12
  /**
12
13
  * Select prompt that exits on cancel.
13
14
  * Use for linear flows where cancel should abort the entire operation.
@@ -43,5 +44,10 @@ export declare function textOrExit(options: TextOptions, cancelMessage?: string)
43
44
  * }, 'Operation cancelled');
44
45
  */
45
46
  export declare function confirmOrExit(options: ConfirmOptions, cancelMessage?: string): Promise<boolean>;
47
+ /**
48
+ * Multiselect prompt that exits on cancel.
49
+ * Use for linear flows where cancel should abort the entire operation.
50
+ */
51
+ export declare function multiselectOrExit<T extends string>(options: MultiselectOptions, cancelMessage?: string): Promise<T[]>;
46
52
  export {};
47
53
  //# sourceMappingURL=prompt-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-helpers.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompt-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAMpC,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAMtD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC/C,OAAO,EAAE,aAAa,EACtB,aAAa,SAAc,GAC5B,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC5B,OAAO,EAAE,WAAW,EACpB,aAAa,SAAc,GAC5B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAC/B,OAAO,EAAE,cAAc,EACvB,aAAa,SAAc,GAC5B,OAAO,CAAC,OAAO,CAAC,CAOlB"}
1
+ {"version":3,"file":"prompt-helpers.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompt-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAMpC,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAM9D;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC/C,OAAO,EAAE,aAAa,EACtB,aAAa,SAAc,GAC5B,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC5B,OAAO,EAAE,WAAW,EACpB,aAAa,SAAc,GAC5B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAC/B,OAAO,EAAE,cAAc,EACvB,aAAa,SAAc,GAC5B,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EACpD,OAAO,EAAE,kBAAkB,EAC3B,aAAa,SAAc,GAC5B,OAAO,CAAC,CAAC,EAAE,CAAC,CAOd"}
@@ -64,3 +64,15 @@ export async function confirmOrExit(options, cancelMessage = 'Cancelled') {
64
64
  }
65
65
  return result;
66
66
  }
67
+ /**
68
+ * Multiselect prompt that exits on cancel.
69
+ * Use for linear flows where cancel should abort the entire operation.
70
+ */
71
+ export async function multiselectOrExit(options, cancelMessage = 'Cancelled') {
72
+ const result = await p.multiselect(options);
73
+ if (p.isCancel(result)) {
74
+ p.cancel(cancelMessage);
75
+ process.exit(0);
76
+ }
77
+ return result;
78
+ }
@@ -44,8 +44,8 @@ const cliVersion = resolveCliVersion();
44
44
  // Set CLI version for Dexto Gateway usage tracking
45
45
  process.env.DEXTO_CLI_VERSION = cliVersion;
46
46
  import { logger, getProviderFromModel, getAllSupportedModels, startLlmRegistryAutoUpdate, DextoAgent, isPath, resolveApiKeyForProvider, getPrimaryApiKeyEnvVar, } from '@dexto/core';
47
- import { applyImageDefaults, cleanNullValues, AgentConfigSchema, loadImage, resolveServicesFromConfig, setImageImporter, toDextoAgentOptions, } from '@dexto/agent-config';
48
- import { getDextoPackageRoot, resolveAgentPath, loadAgentConfig, globalPreferencesExist, loadGlobalPreferences, resolveBundledScript, enrichAgentConfig, isDextoAuthEnabled, } from '@dexto/agent-management';
47
+ import { applyImageDefaults, cleanNullValues, AgentConfigSchema, loadImage, resolveServicesFromConfig, toDextoAgentOptions, } from '@dexto/agent-config';
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
51
  import { applyCLIOverrides, applyUserPreferences } from './config/cli-overrides.js';
@@ -59,19 +59,12 @@ import { registerImageCommand } from './cli/commands/image/register.js';
59
59
  import { registerPluginCommand } from './cli/commands/plugin/register.js';
60
60
  import { registerAgentsCommand } from './cli/commands/agents/register.js';
61
61
  import { registerDeployCommand } from './cli/commands/deploy/register.js';
62
+ import { registerInitCommand } from './cli/commands/init.js';
63
+ import { ensureImageImporterConfigured } from './cli/utils/image-importer.js';
62
64
  const program = new Command();
63
- let imageImporterConfigured = false;
64
65
  let dextoApiKeyBootstrapped = false;
65
66
  let versionCheckPromise = null;
66
67
  let llmRegistryAutoUpdateStarted = false;
67
- async function ensureImageImporterConfigured() {
68
- if (imageImporterConfigured) {
69
- return;
70
- }
71
- const { importImageModule } = await import('./cli/utils/image-store.js');
72
- setImageImporter((specifier) => importImageModule(specifier));
73
- imageImporterConfigured = true;
74
- }
75
68
  async function ensureDextoApiKeyBootstrap() {
76
69
  if (dextoApiKeyBootstrapped) {
77
70
  return;
@@ -148,6 +141,7 @@ program
148
141
  }));
149
142
  registerImageCommand({ program });
150
143
  registerDeployCommand({ program });
144
+ registerInitCommand({ program });
151
145
  // 4) `init-app` SUB-COMMAND
152
146
  program
153
147
  .command('init-app')
@@ -294,6 +288,7 @@ async function bootstrapAgentFromGlobalOpts(options) {
294
288
  inferredApiKey = apiKey;
295
289
  }
296
290
  const resolvedPath = await resolveAgentPath(globalOpts.agent, globalOpts.autoInstall !== false);
291
+ const workspaceRoot = findDextoProjectRoot(process.cwd()) ?? process.cwd();
297
292
  const rawConfig = await loadAgentConfig(resolvedPath);
298
293
  const mergedConfig = applyCLIOverrides(rawConfig, {
299
294
  ...globalOpts,
@@ -330,6 +325,7 @@ async function bootstrapAgentFromGlobalOpts(options) {
330
325
  // Headless run keeps output deterministic and noise-free.
331
326
  // Other non-interactive commands keep visible logs.
332
327
  logLevel: isHeadlessRun ? 'error' : 'info',
328
+ workspaceRoot,
333
329
  });
334
330
  if (isHeadlessRun) {
335
331
  // Force silent transport in headless mode even when agent config defines logger settings.
@@ -699,9 +695,11 @@ program
699
695
  // Enrichment adds filesystem paths to storage (schema has in-memory defaults)
700
696
  // Interactive CLI mode: only log to file (console would interfere with chat UI)
701
697
  const isInteractiveCli = opts.mode === 'cli';
698
+ const workspaceRoot = findDextoProjectRoot(process.cwd()) ?? process.cwd();
702
699
  const enrichedConfig = enrichAgentConfig(configWithImageDefaults, resolvedPath, {
703
700
  isInteractiveCli,
704
701
  logLevel: 'info', // CLI uses info-level logging for visibility
702
+ workspaceRoot,
705
703
  });
706
704
  // Validate enriched config + preflight credentials.
707
705
  // - Interactive modes (web/cli): warn and continue when credentials are missing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dexto",
3
- "version": "1.6.14",
3
+ "version": "1.6.16",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "dexto": "./dist/index.js"
@@ -34,16 +34,16 @@
34
34
  "ws": "^8.18.1",
35
35
  "yaml": "^2.7.1",
36
36
  "zod": "^3.25.0",
37
- "@dexto/agent-config": "1.6.14",
38
- "@dexto/agent-management": "1.6.14",
39
- "@dexto/analytics": "1.6.14",
40
- "@dexto/core": "1.6.14",
41
- "@dexto/image-local": "1.6.14",
42
- "@dexto/image-logger-agent": "1.6.14",
43
- "@dexto/registry": "1.6.14",
44
- "@dexto/server": "1.6.14",
45
- "@dexto/storage": "1.6.14",
46
- "@dexto/tui": "1.6.14"
37
+ "@dexto/agent-config": "1.6.16",
38
+ "@dexto/agent-management": "1.6.16",
39
+ "@dexto/analytics": "1.6.16",
40
+ "@dexto/core": "1.6.16",
41
+ "@dexto/image-local": "1.6.16",
42
+ "@dexto/image-logger-agent": "1.6.16",
43
+ "@dexto/registry": "1.6.16",
44
+ "@dexto/server": "1.6.16",
45
+ "@dexto/storage": "1.6.16",
46
+ "@dexto/tui": "1.6.16"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/ws": "^8.5.11",