dexto 1.1.10 → 1.2.0

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 (181) hide show
  1. package/README.md +222 -84
  2. package/dist/agents/agent-registry.json +39 -1
  3. package/dist/agents/agent-template.yml +1 -1
  4. package/dist/agents/coding-agent/README.md +188 -0
  5. package/dist/agents/coding-agent/coding-agent.yml +203 -0
  6. package/dist/agents/database-agent/database-agent.yml +44 -2
  7. package/dist/agents/default-agent.yml +137 -13
  8. package/dist/agents/github-agent/github-agent.yml +42 -0
  9. package/dist/agents/image-editor-agent/image-editor-agent.yml +9 -2
  10. package/dist/agents/music-agent/README.md +1 -1
  11. package/dist/agents/music-agent/music-agent.yml +36 -2
  12. package/dist/agents/nano-banana-agent/nano-banana-agent.yml +35 -1
  13. package/dist/agents/podcast-agent/README.md +1 -1
  14. package/dist/agents/podcast-agent/podcast-agent.yml +37 -3
  15. package/dist/agents/product-name-researcher/product-name-researcher.yml +37 -1
  16. package/dist/agents/sora-video-agent/README.md +122 -0
  17. package/dist/agents/sora-video-agent/sora-video-agent.yml +98 -0
  18. package/dist/agents/talk2pdf-agent/talk2pdf-agent.yml +17 -2
  19. package/dist/agents/triage-demo/README.md +6 -6
  20. package/dist/agents/triage-demo/billing-agent.yml +1 -1
  21. package/dist/agents/triage-demo/escalation-agent.yml +1 -1
  22. package/dist/agents/triage-demo/product-info-agent.yml +1 -1
  23. package/dist/agents/triage-demo/technical-support-agent.yml +1 -1
  24. package/dist/agents/triage-demo/triage-agent.yml +16 -1
  25. package/dist/analytics/wrapper.d.ts.map +1 -1
  26. package/dist/analytics/wrapper.js +5 -3
  27. package/dist/api/a2a.d.ts +2 -2
  28. package/dist/api/a2a.d.ts.map +1 -1
  29. package/dist/api/a2a.js +3 -2
  30. package/dist/api/mcp/mcp_handler.d.ts +3 -3
  31. package/dist/api/mcp/mcp_handler.d.ts.map +1 -1
  32. package/dist/api/mcp/mcp_handler.js +7 -4
  33. package/dist/api/mcp/tool-aggregation-handler.d.ts.map +1 -1
  34. package/dist/api/mcp/tool-aggregation-handler.js +34 -42
  35. package/dist/api/memory/memory-handler.d.ts +18 -0
  36. package/dist/api/memory/memory-handler.d.ts.map +1 -0
  37. package/dist/api/memory/memory-handler.js +137 -0
  38. package/dist/api/middleware/errorHandler.d.ts.map +1 -1
  39. package/dist/api/middleware/errorHandler.js +2 -0
  40. package/dist/api/server.d.ts +2 -2
  41. package/dist/api/server.d.ts.map +1 -1
  42. package/dist/api/server.js +1129 -257
  43. package/dist/api/webhook-subscriber.d.ts.map +1 -1
  44. package/dist/api/webhook-subscriber.js +2 -1
  45. package/dist/api/websocket-subscriber.d.ts.map +1 -1
  46. package/dist/api/websocket-subscriber.js +67 -10
  47. package/dist/cli/cli-subscriber.d.ts +2 -1
  48. package/dist/cli/cli-subscriber.d.ts.map +1 -1
  49. package/dist/cli/cli-subscriber.js +11 -3
  50. package/dist/cli/cli.d.ts.map +1 -1
  51. package/dist/cli/cli.js +1 -0
  52. package/dist/cli/commands/install.d.ts +3 -3
  53. package/dist/cli/commands/install.d.ts.map +1 -1
  54. package/dist/cli/commands/install.js +223 -41
  55. package/dist/cli/commands/interactive-commands/model/model-commands.js +2 -2
  56. package/dist/cli/commands/interactive-commands/prompt-commands.d.ts +8 -1
  57. package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
  58. package/dist/cli/commands/interactive-commands/prompt-commands.js +252 -4
  59. package/dist/cli/commands/list-agents.d.ts.map +1 -1
  60. package/dist/cli/commands/list-agents.js +22 -3
  61. package/dist/cli/commands/setup.d.ts +4 -4
  62. package/dist/cli/commands/uninstall.d.ts +1 -1
  63. package/dist/cli/tool-confirmation/cli-confirmation-handler.d.ts +36 -7
  64. package/dist/cli/tool-confirmation/cli-confirmation-handler.d.ts.map +1 -1
  65. package/dist/cli/tool-confirmation/cli-confirmation-handler.js +314 -34
  66. package/dist/cli/utils/options.js +2 -2
  67. package/dist/index.js +117 -64
  68. package/dist/webui/.next/standalone/.next/static/chunks/419-6d449dcb2b056299.js +1 -0
  69. package/dist/webui/.next/standalone/.next/static/chunks/614-3519f8a6051e0088.js +1 -0
  70. package/dist/webui/.next/standalone/.next/static/chunks/656-5a9f6405badf66a8.js +25 -0
  71. package/dist/webui/.next/standalone/.next/static/chunks/765-755286dc586b1a51.js +1 -0
  72. package/dist/webui/.next/standalone/.next/static/chunks/804-f40df92a3adffcc0.js +1 -0
  73. package/dist/webui/.next/standalone/.next/static/chunks/854-232126f3c77e6c0b.js +1 -0
  74. package/dist/webui/.next/standalone/.next/static/chunks/app/chat/[sessionId]/page-a695b09e6bac5274.js +1 -0
  75. package/dist/webui/.next/standalone/.next/static/chunks/app/layout-f4a6ee5a028899d1.js +1 -0
  76. package/dist/webui/.next/standalone/.next/static/chunks/app/page-d1f127a0cac96246.js +1 -0
  77. package/dist/webui/.next/standalone/.next/static/chunks/app/playground/page-6f8d2abe76e51dfc.js +1 -0
  78. package/dist/webui/.next/standalone/.next/static/chunks/main-7decd42f62688419.js +1 -0
  79. package/dist/webui/.next/standalone/.next/static/chunks/{webpack-7c234e7e7e272295.js → webpack-7229fd0786f0483c.js} +1 -1
  80. package/dist/webui/.next/standalone/.next/static/css/c3c26ec984df1deb.css +1 -0
  81. package/dist/webui/.next/standalone/.next/static/css/de70bee13400563f.css +1 -0
  82. package/dist/webui/.next/standalone/.next/static/uqfH8SY_uhwdc0ZkpMwCO/_buildManifest.js +1 -0
  83. package/dist/webui/.next/standalone/package.json +7 -2
  84. package/dist/webui/.next/standalone/packages/webui/.next/BUILD_ID +1 -1
  85. package/dist/webui/.next/standalone/packages/webui/.next/app-build-manifest.json +30 -15
  86. package/dist/webui/.next/standalone/packages/webui/.next/app-path-routes-manifest.json +1 -0
  87. package/dist/webui/.next/standalone/packages/webui/.next/build-manifest.json +7 -7
  88. package/dist/webui/.next/standalone/packages/webui/.next/prerender-manifest.json +3 -3
  89. package/dist/webui/.next/standalone/packages/webui/.next/required-server-files.json +1 -11
  90. package/dist/webui/.next/standalone/packages/webui/.next/routes-manifest.json +11 -8
  91. package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page.js +1 -1
  92. package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page.js.nft.json +1 -1
  93. package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  94. package/dist/webui/.next/standalone/packages/webui/.next/server/app/chat/[sessionId]/page.js +2 -0
  95. package/dist/webui/.next/standalone/packages/webui/.next/server/app/chat/[sessionId]/page.js.nft.json +1 -0
  96. package/dist/webui/.next/standalone/packages/webui/.next/server/app/chat/[sessionId]/page_client-reference-manifest.js +1 -0
  97. package/dist/webui/.next/standalone/packages/webui/.next/server/app/page.js +2 -11
  98. package/dist/webui/.next/standalone/packages/webui/.next/server/app/page.js.nft.json +1 -1
  99. package/dist/webui/.next/standalone/packages/webui/.next/server/app/page_client-reference-manifest.js +1 -1
  100. package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page.js +4 -8
  101. package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page.js.nft.json +1 -1
  102. package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page_client-reference-manifest.js +1 -1
  103. package/dist/webui/.next/standalone/packages/webui/.next/server/app-paths-manifest.json +1 -0
  104. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/1.js +12 -0
  105. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/102.js +25 -0
  106. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/383.js +1 -0
  107. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/{619.js → 426.js} +2 -2
  108. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/43.js +1 -1
  109. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/985.js +5 -0
  110. package/dist/webui/.next/standalone/packages/webui/.next/server/middleware-build-manifest.js +1 -1
  111. package/dist/webui/.next/standalone/packages/webui/.next/server/pages/500.html +1 -1
  112. package/dist/webui/.next/standalone/packages/webui/.next/server/server-reference-manifest.json +1 -1
  113. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/419-6d449dcb2b056299.js +1 -0
  114. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/614-3519f8a6051e0088.js +1 -0
  115. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/656-5a9f6405badf66a8.js +25 -0
  116. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/765-755286dc586b1a51.js +1 -0
  117. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/804-f40df92a3adffcc0.js +1 -0
  118. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/854-232126f3c77e6c0b.js +1 -0
  119. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/chat/[sessionId]/page-a695b09e6bac5274.js +1 -0
  120. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/layout-f4a6ee5a028899d1.js +1 -0
  121. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/page-d1f127a0cac96246.js +1 -0
  122. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/playground/page-6f8d2abe76e51dfc.js +1 -0
  123. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/main-7decd42f62688419.js +1 -0
  124. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/{webpack-7c234e7e7e272295.js → webpack-7229fd0786f0483c.js} +1 -1
  125. package/dist/webui/.next/standalone/packages/webui/.next/static/css/c3c26ec984df1deb.css +1 -0
  126. package/dist/webui/.next/standalone/packages/webui/.next/static/css/de70bee13400563f.css +1 -0
  127. package/dist/webui/.next/standalone/packages/webui/.next/static/uqfH8SY_uhwdc0ZkpMwCO/_buildManifest.js +1 -0
  128. package/dist/webui/.next/standalone/packages/webui/package.json +11 -4
  129. package/dist/webui/.next/standalone/packages/webui/server.js +1 -1
  130. package/dist/webui/.next/static/chunks/419-6d449dcb2b056299.js +1 -0
  131. package/dist/webui/.next/static/chunks/614-3519f8a6051e0088.js +1 -0
  132. package/dist/webui/.next/static/chunks/656-5a9f6405badf66a8.js +25 -0
  133. package/dist/webui/.next/static/chunks/765-755286dc586b1a51.js +1 -0
  134. package/dist/webui/.next/static/chunks/804-f40df92a3adffcc0.js +1 -0
  135. package/dist/webui/.next/static/chunks/854-232126f3c77e6c0b.js +1 -0
  136. package/dist/webui/.next/static/chunks/app/chat/[sessionId]/page-a695b09e6bac5274.js +1 -0
  137. package/dist/webui/.next/static/chunks/app/layout-f4a6ee5a028899d1.js +1 -0
  138. package/dist/webui/.next/static/chunks/app/page-d1f127a0cac96246.js +1 -0
  139. package/dist/webui/.next/static/chunks/app/playground/page-6f8d2abe76e51dfc.js +1 -0
  140. package/dist/webui/.next/static/chunks/main-7decd42f62688419.js +1 -0
  141. package/dist/webui/.next/static/chunks/{webpack-7c234e7e7e272295.js → webpack-7229fd0786f0483c.js} +1 -1
  142. package/dist/webui/.next/static/css/c3c26ec984df1deb.css +1 -0
  143. package/dist/webui/.next/static/css/de70bee13400563f.css +1 -0
  144. package/dist/webui/.next/static/uqfH8SY_uhwdc0ZkpMwCO/_buildManifest.js +1 -0
  145. package/dist/webui/package.json +11 -4
  146. package/package.json +5 -4
  147. package/dist/webui/.next/standalone/.next/static/PvkEd_BO6ZXxX99T_gUvs/_buildManifest.js +0 -1
  148. package/dist/webui/.next/standalone/.next/static/chunks/179-78abc2eacbc41da9.js +0 -1
  149. package/dist/webui/.next/standalone/.next/static/chunks/442-b1916bec348454b3.js +0 -1
  150. package/dist/webui/.next/standalone/.next/static/chunks/544-c4a8f278ed1a25d7.js +0 -1
  151. package/dist/webui/.next/standalone/.next/static/chunks/854-2a6d5a5297a15d52.js +0 -1
  152. package/dist/webui/.next/standalone/.next/static/chunks/app/layout-dde711766eda096b.js +0 -1
  153. package/dist/webui/.next/standalone/.next/static/chunks/app/page-5e94d5a49dc718d0.js +0 -1
  154. package/dist/webui/.next/standalone/.next/static/chunks/app/playground/page-9ae40e0b219583e3.js +0 -1
  155. package/dist/webui/.next/standalone/.next/static/chunks/main-b65ece3506a2355c.js +0 -1
  156. package/dist/webui/.next/standalone/.next/static/css/045cc65741e38fbd.css +0 -3
  157. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/549.js +0 -1
  158. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/950.js +0 -5
  159. package/dist/webui/.next/standalone/packages/webui/.next/static/PvkEd_BO6ZXxX99T_gUvs/_buildManifest.js +0 -1
  160. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/179-78abc2eacbc41da9.js +0 -1
  161. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/442-b1916bec348454b3.js +0 -1
  162. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/544-c4a8f278ed1a25d7.js +0 -1
  163. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/854-2a6d5a5297a15d52.js +0 -1
  164. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/layout-dde711766eda096b.js +0 -1
  165. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/page-5e94d5a49dc718d0.js +0 -1
  166. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/playground/page-9ae40e0b219583e3.js +0 -1
  167. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/main-b65ece3506a2355c.js +0 -1
  168. package/dist/webui/.next/standalone/packages/webui/.next/static/css/045cc65741e38fbd.css +0 -3
  169. package/dist/webui/.next/static/PvkEd_BO6ZXxX99T_gUvs/_buildManifest.js +0 -1
  170. package/dist/webui/.next/static/chunks/179-78abc2eacbc41da9.js +0 -1
  171. package/dist/webui/.next/static/chunks/442-b1916bec348454b3.js +0 -1
  172. package/dist/webui/.next/static/chunks/544-c4a8f278ed1a25d7.js +0 -1
  173. package/dist/webui/.next/static/chunks/854-2a6d5a5297a15d52.js +0 -1
  174. package/dist/webui/.next/static/chunks/app/layout-dde711766eda096b.js +0 -1
  175. package/dist/webui/.next/static/chunks/app/page-5e94d5a49dc718d0.js +0 -1
  176. package/dist/webui/.next/static/chunks/app/playground/page-9ae40e0b219583e3.js +0 -1
  177. package/dist/webui/.next/static/chunks/main-b65ece3506a2355c.js +0 -1
  178. package/dist/webui/.next/static/css/045cc65741e38fbd.css +0 -3
  179. /package/dist/webui/.next/standalone/.next/static/{PvkEd_BO6ZXxX99T_gUvs → uqfH8SY_uhwdc0ZkpMwCO}/_ssgManifest.js +0 -0
  180. /package/dist/webui/.next/standalone/packages/webui/.next/static/{PvkEd_BO6ZXxX99T_gUvs → uqfH8SY_uhwdc0ZkpMwCO}/_ssgManifest.js +0 -0
  181. /package/dist/webui/.next/static/{PvkEd_BO6ZXxX99T_gUvs → uqfH8SY_uhwdc0ZkpMwCO}/_ssgManifest.js +0 -0
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { applyLayeredEnvironmentLoading } from '@dexto/core';
5
5
  await applyLayeredEnvironmentLoading();
6
6
  import { existsSync } from 'fs';
7
7
  import { createRequire } from 'module';
8
+ import path from 'path';
8
9
  import { Command } from 'commander';
9
10
  import * as p from '@clack/prompts';
10
11
  import chalk from 'chalk';
@@ -13,8 +14,8 @@ import { withAnalytics, safeExit, ExitSignal } from './analytics/wrapper.js';
13
14
  // Use createRequire to import package.json without experimental warning
14
15
  const require = createRequire(import.meta.url);
15
16
  const pkg = require('../package.json');
16
- import { logger, getProviderFromModel, getAllSupportedModels, DextoAgent, loadAgentConfig, } from '@dexto/core';
17
- import { resolveAgentPath, getAgentRegistry, isPath, resolveApiKeyForProvider } from '@dexto/core';
17
+ import { logger, getProviderFromModel, getAllSupportedModels, DextoAgent, loadAgentConfig, globalPreferencesExist, loadGlobalPreferences, } from '@dexto/core';
18
+ import { resolveAgentPath, getAgentRegistry, isPath, resolveApiKeyForProvider, getPrimaryApiKeyEnvVar, } from '@dexto/core';
18
19
  import { startAiCli, startHeadlessCli, loadMostRecentSession } from './cli/cli.js';
19
20
  import { startApiServer } from './api/server.js';
20
21
  import { startDiscordBot } from './discord/bot.js';
@@ -40,7 +41,7 @@ program
40
41
  .name('dexto')
41
42
  .description('AI-powered CLI and WebUI for interacting with MCP servers')
42
43
  .version(pkg.version, '-v, --version', 'output the current version')
43
- .option('-a, --agent <name|path>', 'Agent name or path to agent config file')
44
+ .option('-a, --agent <id|path>', 'Agent ID or path to agent config file')
44
45
  .option('-p, --prompt <text>', 'Run prompt and exit. Alternatively provide a single quoted string as positional argument.')
45
46
  .option('-s, --strict', 'Require all server connections to succeed')
46
47
  .option('--no-verbose', 'Disable verbose output')
@@ -51,8 +52,9 @@ program
51
52
  .option('--auto-approve', 'Always approve tool executions without confirmation prompts')
52
53
  .option('-c, --continue', 'Continue most recent conversation')
53
54
  .option('-r, --resume <sessionId>', 'Resume session by ID')
54
- .option('--mode <mode>', 'The application in which dexto should talk to you - cli | web | server | discord | telegram | mcp', 'cli')
55
- .option('--web-port <port>', 'optional port for the web UI', '3000')
55
+ .option('--mode <mode>', 'The application in which dexto should talk to you - web | cli | server | discord | telegram | mcp', 'web')
56
+ .option('--web-port <port>', 'port for the web UI (default: 3000)', '3000')
57
+ .option('--api-port <port>', 'port for the API server (default: web-port + 1)')
56
58
  .option('--no-auto-install', 'Disable automatic installation of missing agents from registry')
57
59
  .enablePositionalOptions();
58
60
  // 2) `create-app` SUB-COMMAND
@@ -156,10 +158,17 @@ program
156
158
  // 5) `install` SUB-COMMAND
157
159
  program
158
160
  .command('install [agents...]')
159
- .description('Install agents from the registry')
161
+ .description('Install agents from registry or custom YAML files/directories')
160
162
  .option('--all', 'Install all available agents from registry')
161
163
  .option('--no-inject-preferences', 'Skip injecting global preferences into installed agents')
162
164
  .option('--force', 'Force reinstall even if agent is already installed')
165
+ .addHelpText('after', `
166
+ Examples:
167
+ $ dexto install default-agent Install agent from registry
168
+ $ dexto install agent1 agent2 Install multiple registry agents
169
+ $ dexto install --all Install all available registry agents
170
+ $ dexto install ./my-agent.yml Install custom agent from YAML file
171
+ $ dexto install ./my-agent-dir/ Install custom agent from directory (interactive)`)
163
172
  .action(withAnalytics('install', async (agents = [], options) => {
164
173
  try {
165
174
  await handleInstallCommand(agents, options);
@@ -231,7 +240,7 @@ async function bootstrapAgentFromGlobalOpts() {
231
240
  const resolvedPath = await resolveAgentPath(globalOpts.agent, globalOpts.autoInstall !== false, true);
232
241
  const rawConfig = await loadAgentConfig(resolvedPath);
233
242
  const mergedConfig = applyCLIOverrides(rawConfig, globalOpts);
234
- const agent = new DextoAgent(mergedConfig, globalOpts.agent);
243
+ const agent = new DextoAgent(mergedConfig, resolvedPath);
235
244
  await agent.start();
236
245
  // Register graceful shutdown
237
246
  const shutdown = async () => {
@@ -402,31 +411,55 @@ program
402
411
  // Main customer facing description
403
412
  .description('Dexto CLI - AI-powered assistant with session management\n\n' +
404
413
  'Basic Usage:\n' +
405
- ' dexto Start interactive REPL\n' +
406
- ' dexto "query" Start REPL with initial prompt\n' +
407
- ' dexto -p "query" Run query, then exit\n' +
414
+ ' dexto Start web UI (default)\n' +
415
+ ' dexto "query" Run one-shot query (auto-uses CLI mode)\n' +
416
+ ' dexto -p "query" Run one-shot query, then exit\n' +
408
417
  ' cat file | dexto -p "query" Process piped content\n\n' +
418
+ 'CLI Mode:\n' +
419
+ ' dexto --mode cli Start interactive CLI REPL\n\n' +
409
420
  'Session Management:\n' +
410
421
  ' dexto -c Continue most recent conversation\n' +
411
- ' dexto -c -p "query" Continue conversation, then exit\n' +
412
- ' dexto -r "<session-id>" "query" Resume session by ID\n\n' +
422
+ ' dexto -c -p "query" Continue with one-shot query, then exit\n' +
423
+ ' dexto -r "<session-id>" "query" Resume with one-shot query\n\n' +
413
424
  'Tool Confirmation:\n' +
414
425
  ' dexto --auto-approve Auto-approve all tool executions\n\n' +
426
+ 'Agent Selection:\n' +
427
+ ' dexto --agent coding-agent Use installed agent by name\n' +
428
+ ' dexto --agent ./my-agent.yml Use agent from file path\n' +
429
+ ' dexto -a agents/custom.yml Short form with relative path\n\n' +
415
430
  'Advanced Modes:\n' +
416
- ' dexto --mode web Run web UI\n' +
417
431
  ' dexto --mode server Run as API server\n' +
418
432
  ' dexto --mode discord Run as Discord bot\n' +
419
433
  ' dexto --mode telegram Run as Telegram bot\n' +
420
434
  ' dexto --mode mcp Run as MCP server\n\n' +
421
435
  'Session Commands: dexto session list|history|delete • search\n' +
422
436
  'Search: dexto search <query> [--session <id>] [--role <role>]\n\n' +
423
- 'See https://github.com/truffle-ai/dexto for more examples and documentation')
437
+ 'See https://docs.dexto.ai for documentation and examples')
424
438
  .action(withAnalytics('main', async (prompt = []) => {
425
439
  // ——— ENV CHECK (optional) ———
426
440
  if (!existsSync('.env')) {
427
441
  logger.debug('WARNING: .env file not found; copy .env.example and set your API keys.');
428
442
  }
429
443
  const opts = program.opts();
444
+ // ——— LOAD DEFAULT MODE FROM PREFERENCES ———
445
+ // If --mode was not explicitly provided on CLI, use defaultMode from preferences
446
+ const modeSource = program.getOptionValueSource('mode');
447
+ const explicitModeProvided = modeSource === 'cli';
448
+ if (!explicitModeProvided) {
449
+ try {
450
+ if (globalPreferencesExist()) {
451
+ const preferences = await loadGlobalPreferences();
452
+ if (preferences.defaults?.defaultMode) {
453
+ opts.mode = preferences.defaults.defaultMode;
454
+ logger.debug(`Using default mode from preferences: ${opts.mode}`);
455
+ }
456
+ }
457
+ }
458
+ catch (error) {
459
+ // Silently fall back to hardcoded default if preferences loading fails
460
+ logger.debug(`Failed to load default mode from preferences: ${error instanceof Error ? error.message : String(error)}`);
461
+ }
462
+ }
430
463
  let headlessInput = undefined;
431
464
  // Prefer explicit -p/--prompt for headless one-shot
432
465
  if (opts.prompt !== undefined && String(opts.prompt).trim() !== '') {
@@ -449,6 +482,13 @@ program
449
482
  }
450
483
  // Note: Agent selection must be passed via -a/--agent. We no longer interpret
451
484
  // the first positional argument as an agent name to avoid ambiguity with prompts.
485
+ // ——— FORCE CLI MODE FOR HEADLESS PROMPTS ———
486
+ // If a prompt was provided via -p or positional args, force CLI mode
487
+ if (headlessInput && opts.mode !== 'cli') {
488
+ console.log(`ℹ️ Prompt detected via -p or positional argument. Forcing CLI mode for one-shot execution.`);
489
+ console.log(` Original mode: ${opts.mode} → Overridden to: cli`);
490
+ opts.mode = 'cli';
491
+ }
452
492
  // ——— Infer provider & API key from model ———
453
493
  if (opts.model) {
454
494
  let provider;
@@ -462,7 +502,8 @@ program
462
502
  }
463
503
  const apiKey = resolveApiKeyForProvider(provider);
464
504
  if (!apiKey) {
465
- console.error(`❌ Missing API key for provider '${provider}' - please set the appropriate environment variable`);
505
+ const envVar = getPrimaryApiKeyEnvVar(provider);
506
+ console.error(`❌ Missing API key for provider '${provider}' - please set $${envVar}`);
466
507
  safeExit('main', 1, 'missing-api-key');
467
508
  }
468
509
  opts.provider = provider;
@@ -529,6 +570,7 @@ program
529
570
  }
530
571
  // ——— CREATE AGENT ———
531
572
  let agent;
573
+ let derivedAgentId;
532
574
  try {
533
575
  console.log(`🚀 Initializing Dexto with config: ${resolvedPath}`);
534
576
  // Set run mode for tool confirmation provider
@@ -541,51 +583,14 @@ program
541
583
  }
542
584
  }
543
585
  // DextoAgent will parse/validate again (parse-twice pattern)
544
- agent = new DextoAgent(validatedConfig, opts.agent);
586
+ agent = new DextoAgent(validatedConfig, resolvedPath);
545
587
  // Start the agent (initialize async services)
546
588
  await agent.start();
547
- // Handle session options - simplified logic
548
- if (opts.resume) {
549
- try {
550
- // Resume specific session by ID
551
- await agent.loadSessionAsDefault(opts.resume);
552
- logger.info(`Resumed session: ${opts.resume}`, null, 'cyan');
553
- }
554
- catch (err) {
555
- console.error(`❌ Failed to resume session '${opts.resume}': ${err instanceof Error ? err.message : String(err)}`);
556
- console.error('💡 Use `dexto session list` to see available sessions');
557
- safeExit('main', 1, 'resume-failed');
558
- }
559
- }
560
- else if (opts.continue) {
561
- try {
562
- // Continue from most recent session
563
- await loadMostRecentSession(agent);
564
- // If no sessions existed, create a new one to honor default-new invariant
565
- const sessionsAfter = await agent.listSessions();
566
- if (sessionsAfter.length === 0) {
567
- const session = await agent.createSession();
568
- await agent.loadSessionAsDefault(session.id);
569
- logger.info(`Created new session: ${session.id}`, null, 'green');
570
- }
571
- }
572
- catch (err) {
573
- console.error(`❌ Failed to continue session: ${err instanceof Error ? err.message : String(err)}`);
574
- safeExit('main', 1, 'continue-failed');
575
- }
576
- }
577
- else {
578
- // Default behavior: create new session
579
- try {
580
- const session = await agent.createSession();
581
- await agent.loadSessionAsDefault(session.id);
582
- logger.info(`Created new session: ${session.id}`, null, 'green');
583
- }
584
- catch (err) {
585
- console.error(`❌ Failed to create new session: ${err instanceof Error ? err.message : String(err)}`);
586
- safeExit('main', 1, 'create-session-failed');
587
- }
588
- }
589
+ // Derive a concise agent ID for display purposes (used by API/UI)
590
+ // Prefer agentCard.name, otherwise extract from filename
591
+ derivedAgentId =
592
+ validatedConfig.agentCard?.name ||
593
+ path.basename(resolvedPath, path.extname(resolvedPath));
589
594
  }
590
595
  catch (err) {
591
596
  if (err instanceof ExitSignal)
@@ -597,6 +602,48 @@ program
597
602
  // ——— Dispatch based on --mode ———
598
603
  switch (opts.mode) {
599
604
  case 'cli': {
605
+ // Handle session options - only for CLI mode
606
+ if (opts.resume) {
607
+ try {
608
+ // Resume specific session by ID
609
+ await agent.loadSessionAsDefault(opts.resume);
610
+ logger.info(`Resumed session: ${opts.resume}`, null, 'cyan');
611
+ }
612
+ catch (err) {
613
+ console.error(`❌ Failed to resume session '${opts.resume}': ${err instanceof Error ? err.message : String(err)}`);
614
+ console.error('💡 Use `dexto session list` to see available sessions');
615
+ safeExit('main', 1, 'resume-failed');
616
+ }
617
+ }
618
+ else if (opts.continue) {
619
+ try {
620
+ // Continue from most recent session
621
+ await loadMostRecentSession(agent);
622
+ // If no sessions existed, create a new one to honor default-new invariant
623
+ const sessionsAfter = await agent.listSessions();
624
+ if (sessionsAfter.length === 0) {
625
+ const session = await agent.createSession();
626
+ await agent.loadSessionAsDefault(session.id);
627
+ logger.info(`Created new session: ${session.id}`, null, 'green');
628
+ }
629
+ }
630
+ catch (err) {
631
+ console.error(`❌ Failed to continue session: ${err instanceof Error ? err.message : String(err)}`);
632
+ safeExit('main', 1, 'continue-failed');
633
+ }
634
+ }
635
+ else {
636
+ // Default behavior: create new session for CLI mode
637
+ try {
638
+ const session = await agent.createSession();
639
+ await agent.loadSessionAsDefault(session.id);
640
+ logger.info(`Created new session: ${session.id}`, null, 'green');
641
+ }
642
+ catch (err) {
643
+ console.error(`❌ Failed to create new session: ${err instanceof Error ? err.message : String(err)}`);
644
+ safeExit('main', 1, 'create-session-failed');
645
+ }
646
+ }
600
647
  const toolConfirmationMode = agent.getEffectiveConfig().toolConfirmation?.mode ?? 'event-based';
601
648
  if (toolConfirmationMode === 'event-based') {
602
649
  // Set up CLI tool confirmation subscriber
@@ -621,11 +668,15 @@ program
621
668
  case 'web': {
622
669
  const webPort = parseInt(opts.webPort, 10);
623
670
  const frontPort = getPort(process.env.FRONTEND_PORT, webPort, 'FRONTEND_PORT');
624
- const apiPort = getPort(process.env.API_PORT, webPort + 1, 'API_PORT');
671
+ // Use explicit --api-port if provided, otherwise default to webPort + 1
672
+ const defaultApiPort = opts.apiPort
673
+ ? parseInt(opts.apiPort, 10)
674
+ : webPort + 1;
675
+ const apiPort = getPort(process.env.API_PORT, defaultApiPort, 'API_PORT');
625
676
  const apiUrl = process.env.API_URL ?? `http://localhost:${apiPort}`;
626
677
  const nextJSserverURL = process.env.FRONTEND_URL ?? `http://localhost:${frontPort}`;
627
678
  // Start API server
628
- await startApiServer(agent, apiPort, agent.getEffectiveConfig().agentCard || {}, opts.agent);
679
+ await startApiServer(agent, apiPort, agent.getEffectiveConfig().agentCard || {}, derivedAgentId);
629
680
  // Start Next.js web server
630
681
  const webServerStarted = await startNextJsWebServer(apiUrl, frontPort, nextJSserverURL);
631
682
  // Open WebUI in browser if server started successfully
@@ -646,10 +697,12 @@ program
646
697
  case 'server': {
647
698
  // Start server with REST APIs and WebSockets only
648
699
  const agentCard = agent.getEffectiveConfig().agentCard ?? {};
649
- const apiPort = getPort(process.env.API_PORT, 3001, 'API_PORT');
700
+ // Use explicit --api-port if provided, otherwise default to 3001
701
+ const defaultApiPort = opts.apiPort ? parseInt(opts.apiPort, 10) : 3001;
702
+ const apiPort = getPort(process.env.API_PORT, defaultApiPort, 'API_PORT');
650
703
  const apiUrl = process.env.API_URL ?? `http://localhost:${apiPort}`;
651
704
  console.log('🌐 Starting server (REST APIs + WebSockets)...');
652
- await startApiServer(agent, apiPort, agentCard, opts.agent);
705
+ await startApiServer(agent, apiPort, agentCard, derivedAgentId);
653
706
  console.log(`✅ Server running at ${apiUrl}`);
654
707
  console.log('Available endpoints:');
655
708
  console.log(' POST /api/message - Send async message');
@@ -699,7 +752,7 @@ program
699
752
  );
700
753
  // Use stdio transport in mcp mode
701
754
  const mcpTransport = await createMcpTransport('stdio');
702
- await initializeMcpServer(agent, agentCardData, mcpTransport);
755
+ await initializeMcpServer(() => agent, () => agentCardData, mcpTransport);
703
756
  }
704
757
  catch (err) {
705
758
  // Write to stderr instead of stdout to avoid interfering with MCP protocol
@@ -709,7 +762,7 @@ program
709
762
  break;
710
763
  }
711
764
  default:
712
- console.error(`❌ Unknown mode '${opts.mode}'. Use cli, web, server, discord, telegram, or mcp.`);
765
+ console.error(`❌ Unknown mode '${opts.mode}'. Use web, cli, server, discord, telegram, or mcp.`);
713
766
  safeExit('main', 1, 'unknown-mode');
714
767
  }
715
768
  }, { timeoutMs: 0 }));