dexto 1.6.8 → 1.6.9

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 (104) hide show
  1. package/README.md +4 -4
  2. package/dist/analytics/wrapper.d.ts.map +1 -1
  3. package/dist/analytics/wrapper.js +43 -9
  4. package/dist/cli/auth/api-client.d.ts +50 -0
  5. package/dist/cli/auth/api-client.d.ts.map +1 -1
  6. package/dist/cli/auth/api-client.js +379 -15
  7. package/dist/cli/auth/browser-launch.d.ts +6 -0
  8. package/dist/cli/auth/browser-launch.d.ts.map +1 -0
  9. package/dist/cli/auth/browser-launch.js +24 -0
  10. package/dist/cli/auth/device.d.ts +14 -0
  11. package/dist/cli/auth/device.d.ts.map +1 -0
  12. package/dist/cli/auth/device.js +93 -0
  13. package/dist/cli/auth/index.d.ts +3 -1
  14. package/dist/cli/auth/index.d.ts.map +1 -1
  15. package/dist/cli/auth/index.js +2 -1
  16. package/dist/cli/auth/login-persistence.d.ts +13 -0
  17. package/dist/cli/auth/login-persistence.d.ts.map +1 -0
  18. package/dist/cli/auth/login-persistence.js +22 -0
  19. package/dist/cli/auth/oauth.d.ts +4 -1
  20. package/dist/cli/auth/oauth.d.ts.map +1 -1
  21. package/dist/cli/auth/oauth.js +6 -2
  22. package/dist/cli/auth/types.d.ts +12 -0
  23. package/dist/cli/auth/types.d.ts.map +1 -0
  24. package/dist/cli/auth/types.js +1 -0
  25. package/dist/cli/commands/agents/register.d.ts +6 -0
  26. package/dist/cli/commands/agents/register.d.ts.map +1 -0
  27. package/dist/cli/commands/agents/register.js +85 -0
  28. package/dist/cli/commands/auth/index.d.ts +1 -1
  29. package/dist/cli/commands/auth/index.d.ts.map +1 -1
  30. package/dist/cli/commands/auth/index.js +1 -1
  31. package/dist/cli/commands/auth/login.d.ts +6 -6
  32. package/dist/cli/commands/auth/login.d.ts.map +1 -1
  33. package/dist/cli/commands/auth/login.js +85 -115
  34. package/dist/cli/commands/auth/logout.d.ts.map +1 -1
  35. package/dist/cli/commands/auth/logout.js +32 -2
  36. package/dist/cli/commands/auth/register.d.ts +3 -0
  37. package/dist/cli/commands/auth/register.d.ts.map +1 -0
  38. package/dist/cli/commands/auth/register.js +94 -0
  39. package/dist/cli/commands/billing/register.d.ts +3 -0
  40. package/dist/cli/commands/billing/register.d.ts.map +1 -0
  41. package/dist/cli/commands/billing/register.js +20 -0
  42. package/dist/cli/commands/helpers/formatters.d.ts.map +1 -1
  43. package/dist/cli/commands/helpers/formatters.js +9 -0
  44. package/dist/cli/commands/image/register.d.ts +6 -0
  45. package/dist/cli/commands/image/register.d.ts.map +1 -0
  46. package/dist/cli/commands/image/register.js +144 -0
  47. package/dist/cli/commands/install.d.ts +2 -2
  48. package/dist/cli/commands/list-agents.d.ts.map +1 -1
  49. package/dist/cli/commands/list-agents.js +3 -3
  50. package/dist/cli/commands/mcp/register.d.ts +6 -0
  51. package/dist/cli/commands/mcp/register.d.ts.map +1 -0
  52. package/dist/cli/commands/mcp/register.js +64 -0
  53. package/dist/cli/commands/plugin/register.d.ts +6 -0
  54. package/dist/cli/commands/plugin/register.d.ts.map +1 -0
  55. package/dist/cli/commands/plugin/register.js +183 -0
  56. package/dist/cli/commands/plugin.d.ts +4 -4
  57. package/dist/cli/commands/register-context.d.ts +12 -0
  58. package/dist/cli/commands/register-context.d.ts.map +1 -0
  59. package/dist/cli/commands/register-context.js +1 -0
  60. package/dist/cli/commands/run/headless.d.ts +20 -0
  61. package/dist/cli/commands/run/headless.d.ts.map +1 -0
  62. package/dist/cli/commands/run/headless.js +275 -0
  63. package/dist/cli/commands/run/register.d.ts +3 -0
  64. package/dist/cli/commands/run/register.d.ts.map +1 -0
  65. package/dist/cli/commands/run/register.js +78 -0
  66. package/dist/cli/commands/search/register.d.ts +3 -0
  67. package/dist/cli/commands/search/register.d.ts.map +1 -0
  68. package/dist/cli/commands/search/register.js +55 -0
  69. package/dist/cli/commands/session/register.d.ts +3 -0
  70. package/dist/cli/commands/session/register.d.ts.map +1 -0
  71. package/dist/cli/commands/session/register.js +75 -0
  72. package/dist/cli/commands/setup.js +4 -4
  73. package/dist/cli/commands/sync-agents.d.ts +3 -3
  74. package/dist/cli/commands/sync-agents.js +4 -4
  75. package/dist/cli/commands/uninstall.d.ts +2 -2
  76. package/dist/cli/modes/cli.d.ts +3 -0
  77. package/dist/cli/modes/cli.d.ts.map +1 -0
  78. package/dist/cli/modes/cli.js +170 -0
  79. package/dist/cli/modes/context.d.ts +20 -0
  80. package/dist/cli/modes/context.d.ts.map +1 -0
  81. package/dist/cli/modes/context.js +1 -0
  82. package/dist/cli/modes/dispatch.d.ts +3 -0
  83. package/dist/cli/modes/dispatch.d.ts.map +1 -0
  84. package/dist/cli/modes/dispatch.js +52 -0
  85. package/dist/cli/modes/mcp.d.ts +3 -0
  86. package/dist/cli/modes/mcp.d.ts.map +1 -0
  87. package/dist/cli/modes/mcp.js +23 -0
  88. package/dist/cli/modes/server.d.ts +3 -0
  89. package/dist/cli/modes/server.d.ts.map +1 -0
  90. package/dist/cli/modes/server.js +36 -0
  91. package/dist/cli/modes/web.d.ts +3 -0
  92. package/dist/cli/modes/web.d.ts.map +1 -0
  93. package/dist/cli/modes/web.js +50 -0
  94. package/dist/cli/utils/setup-utils.js +1 -1
  95. package/dist/index-main.js +150 -991
  96. package/dist/utils/port-utils.d.ts +1 -1
  97. package/dist/utils/port-utils.d.ts.map +1 -1
  98. package/dist/utils/port-utils.js +7 -3
  99. package/dist/webui/assets/index-Bn9YuTdA.css +1 -0
  100. package/dist/webui/assets/index-CNiOYnOb.js +2059 -0
  101. package/dist/webui/index.html +2 -2
  102. package/package.json +12 -12
  103. package/dist/webui/assets/index-d6c-yJNn.js +0 -2059
  104. package/dist/webui/assets/index-yKdFLN1k.css +0 -1
@@ -151,7 +151,7 @@ export async function handleListAgentsCommand(options) {
151
151
  }
152
152
  else if (showInstalled) {
153
153
  console.log(chalk.rgb(255, 165, 0)('📦 No agents installed yet.'));
154
- console.log(chalk.gray(' Use `dexto install <agent-name>` to install agents from the registry.\n'));
154
+ console.log(chalk.gray(' Use `dexto agents install <agent-name>` to install agents from the registry.\n'));
155
155
  }
156
156
  // Show available agents (not installed)
157
157
  if (showAvailable) {
@@ -197,9 +197,9 @@ export async function handleListAgentsCommand(options) {
197
197
  if (!validated.verbose) {
198
198
  console.log(chalk.gray(`📊 Summary: ${totalInstalled} installed, ${availableToInstall} available to install`));
199
199
  if (availableToInstall > 0) {
200
- console.log(chalk.gray(` Use \`dexto install <agent-name>\` to install more agents.`));
200
+ console.log(chalk.gray(` Use \`dexto agents install <agent-name>\` to install more agents.`));
201
201
  }
202
- console.log(chalk.gray(` Use \`dexto list-agents --verbose\` for detailed information.`));
202
+ console.log(chalk.gray(` Use \`dexto agents list --verbose\` for detailed information.`));
203
203
  console.log(chalk.gray(` After installing an agent, use \`dexto -a <agent-name>\` to run it.`));
204
204
  }
205
205
  console.log();
@@ -0,0 +1,6 @@
1
+ import type { Command } from 'commander';
2
+ export interface McpCommandRegisterContext {
3
+ program: Command;
4
+ }
5
+ export declare function registerMcpCommand({ program }: McpCommandRegisterContext): void;
6
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/mcp/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,MAAM,WAAW,yBAAyB;IACtC,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,EAAE,yBAAyB,GAAG,IAAI,CA+G/E"}
@@ -0,0 +1,64 @@
1
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
2
+ export function registerMcpCommand({ program }) {
3
+ // For now, this mode simply aggregates and re-expose tools from configured MCP servers (no agent)
4
+ // dexto --mode mcp will be moved to this sub-command in the future
5
+ program
6
+ .command('mcp')
7
+ .description('Start Dexto as an MCP server. Use --group-servers to aggregate and re-expose tools from configured MCP servers. \
8
+ In the future, this command will expose the agent as an MCP server by default.')
9
+ .option('-s, --strict', 'Require all MCP server connections to succeed')
10
+ .option('--group-servers', 'Aggregate and re-expose tools from configured MCP servers (required for now)')
11
+ .option('--name <n>', 'Name for the MCP server', 'dexto-tools')
12
+ .option('--version <version>', 'Version for the MCP server', '1.0.0')
13
+ .action(withAnalytics('mcp', async (options) => {
14
+ try {
15
+ // Validate that --group-servers flag is provided (mandatory for now)
16
+ if (!options.groupServers) {
17
+ console.error('❌ The --group-servers flag is required. This command currently only supports aggregating and re-exposing tools from configured MCP servers.');
18
+ console.error('Usage: dexto mcp --group-servers');
19
+ safeExit('mcp', 1, 'missing-group-servers');
20
+ return;
21
+ }
22
+ const [{ logger, ServersConfigSchema }, { resolveAgentPath, loadAgentConfig },] = await Promise.all([
23
+ import('@dexto/core'),
24
+ import('@dexto/agent-management'),
25
+ ]);
26
+ // Load and resolve config
27
+ // Get the global agent option from the main program
28
+ const globalOpts = program.opts();
29
+ const configPath = await resolveAgentPath(globalOpts.agent, globalOpts.autoInstall !== false);
30
+ logger.info(`Loading Dexto config from: ${configPath}`);
31
+ const config = await loadAgentConfig(configPath);
32
+ logger.info('Validating MCP servers...');
33
+ // Validate that MCP servers are configured
34
+ if (!config.mcpServers || Object.keys(config.mcpServers).length === 0) {
35
+ console.error('❌ No MCP servers configured. Please configure mcpServers in your config file.');
36
+ safeExit('mcp', 1, 'no-mcp-servers');
37
+ return;
38
+ }
39
+ const validatedServers = ServersConfigSchema.parse(config.mcpServers);
40
+ logger.info(`Validated MCP servers. Configured servers: ${Object.keys(validatedServers).join(', ')}`);
41
+ const [{ createMcpTransport }, { initializeMcpToolAggregationServer }] = await Promise.all([
42
+ import('@dexto/server'),
43
+ import('../../../api/mcp/tool-aggregation-handler.js'),
44
+ ]);
45
+ // Logs are already redirected to file by default to prevent interference with stdio transport
46
+ const currentLogPath = logger.getLogFilePath();
47
+ logger.info(`MCP mode using log file: ${currentLogPath || 'default .dexto location'}`);
48
+ logger.info(`Starting MCP tool aggregation server: ${options.name} v${options.version}`);
49
+ // Create stdio transport for MCP tool aggregation
50
+ const mcpTransport = await createMcpTransport('stdio');
51
+ const strictMode = options.strict ?? false;
52
+ // Initialize tool aggregation server
53
+ await initializeMcpToolAggregationServer(validatedServers, mcpTransport, options.name, options.version, strictMode);
54
+ logger.info('MCP tool aggregation server started successfully');
55
+ }
56
+ catch (err) {
57
+ if (err instanceof ExitSignal)
58
+ throw err;
59
+ // Write to stderr to avoid interfering with MCP protocol
60
+ process.stderr.write(`MCP tool aggregation server startup failed: ${err}\n`);
61
+ safeExit('mcp', 1, 'mcp-agg-failed');
62
+ }
63
+ }, { timeoutMs: 0 }));
64
+ }
@@ -0,0 +1,6 @@
1
+ import type { Command } from 'commander';
2
+ export interface PluginCommandRegisterContext {
3
+ program: Command;
4
+ }
5
+ export declare function registerPluginCommand({ program }: PluginCommandRegisterContext): void;
6
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/plugin/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,MAAM,WAAW,4BAA4B;IACzC,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CAAC,EAAE,OAAO,EAAE,EAAE,4BAA4B,GAAG,IAAI,CA4MrF"}
@@ -0,0 +1,183 @@
1
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
2
+ export function registerPluginCommand({ program }) {
3
+ // `plugin` SUB-COMMAND
4
+ const pluginCommand = program.command('plugin').description('Manage plugins');
5
+ pluginCommand
6
+ .command('list')
7
+ .description('List installed plugins')
8
+ .option('--verbose', 'Show detailed plugin information')
9
+ .action(withAnalytics('plugin list', async (options) => {
10
+ try {
11
+ const { handlePluginListCommand } = await import('../plugin.js');
12
+ await handlePluginListCommand(options);
13
+ safeExit('plugin list', 0);
14
+ }
15
+ catch (err) {
16
+ if (err instanceof ExitSignal)
17
+ throw err;
18
+ console.error(`❌ dexto plugin list command failed: ${err}`);
19
+ safeExit('plugin list', 1, 'error');
20
+ }
21
+ }));
22
+ pluginCommand
23
+ .command('install')
24
+ .description('Install a plugin from a local directory')
25
+ .requiredOption('--path <path>', 'Path to the plugin directory')
26
+ .option('--scope <scope>', 'Installation scope: user, project, or local', 'user')
27
+ .option('--force', 'Force overwrite if already installed')
28
+ .action(withAnalytics('plugin install', async (options) => {
29
+ try {
30
+ const { handlePluginInstallCommand } = await import('../plugin.js');
31
+ await handlePluginInstallCommand(options);
32
+ safeExit('plugin install', 0);
33
+ }
34
+ catch (err) {
35
+ if (err instanceof ExitSignal)
36
+ throw err;
37
+ console.error(`❌ dexto plugin install command failed: ${err}`);
38
+ safeExit('plugin install', 1, 'error');
39
+ }
40
+ }));
41
+ pluginCommand
42
+ .command('uninstall <name>')
43
+ .description('Uninstall a plugin by name')
44
+ .action(withAnalytics('plugin uninstall', async (name) => {
45
+ try {
46
+ const { handlePluginUninstallCommand } = await import('../plugin.js');
47
+ await handlePluginUninstallCommand({ name });
48
+ safeExit('plugin uninstall', 0);
49
+ }
50
+ catch (err) {
51
+ if (err instanceof ExitSignal)
52
+ throw err;
53
+ console.error(`❌ dexto plugin uninstall command failed: ${err}`);
54
+ safeExit('plugin uninstall', 1, 'error');
55
+ }
56
+ }));
57
+ pluginCommand
58
+ .command('validate [path]')
59
+ .description('Validate a plugin directory structure')
60
+ .action(withAnalytics('plugin validate', async (path) => {
61
+ try {
62
+ const { handlePluginValidateCommand } = await import('../plugin.js');
63
+ await handlePluginValidateCommand({ path: path || '.' });
64
+ safeExit('plugin validate', 0);
65
+ }
66
+ catch (err) {
67
+ if (err instanceof ExitSignal)
68
+ throw err;
69
+ console.error(`❌ dexto plugin validate command failed: ${err}`);
70
+ safeExit('plugin validate', 1, 'error');
71
+ }
72
+ }));
73
+ // `plugin marketplace` SUB-COMMANDS
74
+ const marketplaceCommand = pluginCommand
75
+ .command('marketplace')
76
+ .alias('market')
77
+ .description('Manage plugin marketplaces');
78
+ marketplaceCommand
79
+ .command('add <source>')
80
+ .description('Add a marketplace (GitHub: owner/repo, git URL, or local path)')
81
+ .option('--name <name>', 'Custom name for the marketplace')
82
+ .action(withAnalytics('plugin marketplace add', async (source, options) => {
83
+ try {
84
+ const { handleMarketplaceAddCommand } = await import('../plugin.js');
85
+ await handleMarketplaceAddCommand({ source, name: options.name });
86
+ safeExit('plugin marketplace add', 0);
87
+ }
88
+ catch (err) {
89
+ if (err instanceof ExitSignal)
90
+ throw err;
91
+ console.error(`❌ dexto plugin marketplace add command failed: ${err}`);
92
+ safeExit('plugin marketplace add', 1, 'error');
93
+ }
94
+ }));
95
+ marketplaceCommand
96
+ .command('list')
97
+ .description('List registered marketplaces')
98
+ .option('--verbose', 'Show detailed marketplace information')
99
+ .action(withAnalytics('plugin marketplace list', async (options) => {
100
+ try {
101
+ const { handleMarketplaceListCommand } = await import('../plugin.js');
102
+ await handleMarketplaceListCommand(options);
103
+ safeExit('plugin marketplace list', 0);
104
+ }
105
+ catch (err) {
106
+ if (err instanceof ExitSignal)
107
+ throw err;
108
+ console.error(`❌ dexto plugin marketplace list command failed: ${err}`);
109
+ safeExit('plugin marketplace list', 1, 'error');
110
+ }
111
+ }));
112
+ marketplaceCommand
113
+ .command('remove <name>')
114
+ .alias('rm')
115
+ .description('Remove a registered marketplace')
116
+ .action(withAnalytics('plugin marketplace remove', async (name) => {
117
+ try {
118
+ const { handleMarketplaceRemoveCommand } = await import('../plugin.js');
119
+ await handleMarketplaceRemoveCommand({ name });
120
+ safeExit('plugin marketplace remove', 0);
121
+ }
122
+ catch (err) {
123
+ if (err instanceof ExitSignal)
124
+ throw err;
125
+ console.error(`❌ dexto plugin marketplace remove command failed: ${err}`);
126
+ safeExit('plugin marketplace remove', 1, 'error');
127
+ }
128
+ }));
129
+ marketplaceCommand
130
+ .command('update [name]')
131
+ .description('Update marketplace(s) from remote (git pull)')
132
+ .action(withAnalytics('plugin marketplace update', async (name) => {
133
+ try {
134
+ const { handleMarketplaceUpdateCommand } = await import('../plugin.js');
135
+ await handleMarketplaceUpdateCommand({ name });
136
+ safeExit('plugin marketplace update', 0);
137
+ }
138
+ catch (err) {
139
+ if (err instanceof ExitSignal)
140
+ throw err;
141
+ console.error(`❌ dexto plugin marketplace update command failed: ${err}`);
142
+ safeExit('plugin marketplace update', 1, 'error');
143
+ }
144
+ }));
145
+ marketplaceCommand
146
+ .command('plugins [marketplace]')
147
+ .description('List plugins available in marketplaces')
148
+ .option('--verbose', 'Show plugin descriptions')
149
+ .action(withAnalytics('plugin marketplace plugins', async (marketplace, options) => {
150
+ try {
151
+ const { handleMarketplacePluginsCommand } = await import('../plugin.js');
152
+ await handleMarketplacePluginsCommand({
153
+ marketplace,
154
+ verbose: options?.verbose,
155
+ });
156
+ safeExit('plugin marketplace plugins', 0);
157
+ }
158
+ catch (err) {
159
+ if (err instanceof ExitSignal)
160
+ throw err;
161
+ console.error(`❌ dexto plugin marketplace plugins command failed: ${err}`);
162
+ safeExit('plugin marketplace plugins', 1, 'error');
163
+ }
164
+ }));
165
+ marketplaceCommand
166
+ .command('install <plugin>')
167
+ .description('Install a plugin from marketplace (plugin or plugin@marketplace)')
168
+ .option('--scope <scope>', 'Installation scope: user, project, or local', 'user')
169
+ .option('--force', 'Force reinstall if already exists')
170
+ .action(withAnalytics('plugin marketplace install', async (plugin, options) => {
171
+ try {
172
+ const { handleMarketplaceInstallCommand } = await import('../plugin.js');
173
+ await handleMarketplaceInstallCommand({ ...options, plugin });
174
+ safeExit('plugin marketplace install', 0);
175
+ }
176
+ catch (err) {
177
+ if (err instanceof ExitSignal)
178
+ throw err;
179
+ console.error(`❌ dexto plugin marketplace install command failed: ${err}`);
180
+ safeExit('plugin marketplace install', 1, 'error');
181
+ }
182
+ }));
183
+ }
@@ -22,11 +22,11 @@ declare const PluginInstallCommandSchema: z.ZodObject<{
22
22
  }, "strict", z.ZodTypeAny, {
23
23
  path: string;
24
24
  force: boolean;
25
- scope: "local" | "project" | "user";
25
+ scope: "local" | "user" | "project";
26
26
  }, {
27
27
  path: string;
28
28
  force?: boolean | undefined;
29
- scope?: "local" | "project" | "user" | undefined;
29
+ scope?: "local" | "user" | "project" | undefined;
30
30
  }>;
31
31
  declare const PluginUninstallCommandSchema: z.ZodObject<{
32
32
  name: z.ZodString;
@@ -79,12 +79,12 @@ declare const MarketplaceInstallCommandSchema: z.ZodObject<{
79
79
  force: z.ZodDefault<z.ZodBoolean>;
80
80
  }, "strict", z.ZodTypeAny, {
81
81
  force: boolean;
82
- scope: "local" | "project" | "user";
82
+ scope: "local" | "user" | "project";
83
83
  plugin: string;
84
84
  }, {
85
85
  plugin: string;
86
86
  force?: boolean | undefined;
87
- scope?: "local" | "project" | "user" | undefined;
87
+ scope?: "local" | "user" | "project" | undefined;
88
88
  }>;
89
89
  export type PluginListCommandOptions = z.output<typeof PluginListCommandSchema>;
90
90
  export type PluginListCommandOptionsInput = z.input<typeof PluginListCommandSchema>;
@@ -0,0 +1,12 @@
1
+ import type { Command } from 'commander';
2
+ import type { DextoAgent } from '@dexto/core';
3
+ export type BootstrapAgentMode = 'headless-run' | 'non-interactive';
4
+ export interface RuntimeCommandRegisterContext {
5
+ program: Command;
6
+ cliVersion: string;
7
+ bootstrapAgentFromGlobalOpts: (options: {
8
+ mode: BootstrapAgentMode;
9
+ modelOverride?: string;
10
+ }) => Promise<DextoAgent>;
11
+ }
12
+ //# sourceMappingURL=register-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-context.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/register-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAEpE,MAAM,WAAW,6BAA6B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B,EAAE,CAAC,OAAO,EAAE;QACpC,IAAI,EAAE,kBAAkB,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,CAAC;KAC1B,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { type DextoAgent } from '@dexto/core';
2
+ export type HeadlessRunResult = {
3
+ finalMessage?: string;
4
+ totalTokens?: number;
5
+ fatalError?: Error;
6
+ };
7
+ export declare function resolveHeadlessPrompt(promptArg?: string): Promise<string>;
8
+ export declare function printHeadlessMcpStartup(agent: DextoAgent): void;
9
+ export declare function printHeadlessRunSummary(params: {
10
+ agent: DextoAgent;
11
+ sessionId: string;
12
+ prompt: string;
13
+ agentPath: string;
14
+ cliVersion: string;
15
+ }): void;
16
+ export declare function executeHeadlessRun(agent: DextoAgent, sessionId: string, prompt: string): Promise<HeadlessRunResult>;
17
+ export declare function printHeadlessAssistantResponse(message: string, totalTokens?: number): void;
18
+ export declare function writeFinalMessageToStdout(message: string): void;
19
+ export declare function writeHeadlessError(message: string): void;
20
+ //# sourceMappingURL=headless.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headless.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/run/headless.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,UAAU,EAIlB,MAAM,aAAa,CAAC;AAWrB,MAAM,MAAM,iBAAiB,GAAG;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,KAAK,CAAC;CACtB,CAAC;AA0IF,wBAAsB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY/E;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAgC/D;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC5C,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB,GAAG,IAAI,CAgBP;AAED,wBAAsB,kBAAkB,CACpC,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,iBAAiB,CAAC,CA8G5B;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAM1F;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAM/D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAExD"}
@@ -0,0 +1,275 @@
1
+ import { isTextPart, safeStringify, } from '@dexto/core';
2
+ const HEADLESS_TOOL_OUTPUT_MAX_LINES = 20;
3
+ const HEADLESS_SECTION_SEPARATOR = '========================================';
4
+ function writeHeadlessLine(line = '') {
5
+ process.stderr.write(`${line}\n`);
6
+ }
7
+ function writeHeadlessSeparator() {
8
+ writeHeadlessLine(HEADLESS_SECTION_SEPARATOR);
9
+ }
10
+ function writeHeadlessTaggedLine(tag, message) {
11
+ writeHeadlessLine(`[${tag}] ${message}`);
12
+ }
13
+ function writeHeadlessTaggedBlock(tag, content) {
14
+ writeHeadlessLine(`[${tag}]`);
15
+ const lines = content.length > 0 ? content.split('\n') : [''];
16
+ for (const line of lines) {
17
+ writeHeadlessLine(`| ${line}`);
18
+ }
19
+ }
20
+ function formatHeadlessDuration(durationMs) {
21
+ if (durationMs < 1000) {
22
+ return `${Math.round(durationMs)}ms`;
23
+ }
24
+ const seconds = durationMs / 1000;
25
+ if (seconds < 10) {
26
+ return `${seconds.toFixed(2)}s`;
27
+ }
28
+ return `${seconds.toFixed(1)}s`;
29
+ }
30
+ function formatToolNameForHeadless(toolName) {
31
+ const delimiter = '--';
32
+ const delimiterIndex = toolName.indexOf(delimiter);
33
+ if (delimiterIndex > 0) {
34
+ return `${toolName.slice(0, delimiterIndex)}.${toolName.slice(delimiterIndex + delimiter.length)}`;
35
+ }
36
+ return toolName;
37
+ }
38
+ function formatToolArgsForHeadless(args) {
39
+ if (Object.keys(args).length === 0) {
40
+ return '{}';
41
+ }
42
+ return safeStringify(args);
43
+ }
44
+ function formatToolInvocationForHeadless(toolName, args) {
45
+ return `${formatToolNameForHeadless(toolName)}(${formatToolArgsForHeadless(args)})`;
46
+ }
47
+ function truncateOutputForHeadless(output) {
48
+ const lines = output.split('\n');
49
+ if (lines.length <= HEADLESS_TOOL_OUTPUT_MAX_LINES) {
50
+ return output;
51
+ }
52
+ const omittedLineCount = lines.length - HEADLESS_TOOL_OUTPUT_MAX_LINES;
53
+ return `${lines.slice(0, HEADLESS_TOOL_OUTPUT_MAX_LINES).join('\n')}\n... (${omittedLineCount} more lines)`;
54
+ }
55
+ function extractSanitizedToolText(sanitized) {
56
+ if (!sanitized) {
57
+ return undefined;
58
+ }
59
+ const display = sanitized.meta.display;
60
+ if (display?.type === 'shell') {
61
+ const shellDisplay = display;
62
+ const chunks = [shellDisplay.stdout, shellDisplay.stderr].filter((chunk) => Boolean(chunk && chunk.trim()));
63
+ if (chunks.length > 0) {
64
+ return chunks.join('\n');
65
+ }
66
+ }
67
+ if (display?.type === 'diff') {
68
+ return display.unified;
69
+ }
70
+ if (display?.type === 'search') {
71
+ return safeStringify(display.matches);
72
+ }
73
+ if (display?.type === 'file') {
74
+ return safeStringify(display);
75
+ }
76
+ const textParts = sanitized.content.filter(isTextPart).map((part) => part.text);
77
+ if (textParts.length > 0) {
78
+ return textParts.join('\n');
79
+ }
80
+ return safeStringify(sanitized.content);
81
+ }
82
+ function extractToolOutputForHeadless(event) {
83
+ if (!event.success && event.error) {
84
+ return event.error;
85
+ }
86
+ return extractSanitizedToolText(event.sanitized);
87
+ }
88
+ function getTotalTokensFromResponse(event) {
89
+ const usage = event.tokenUsage;
90
+ if (!usage) {
91
+ return undefined;
92
+ }
93
+ if (typeof usage.totalTokens === 'number') {
94
+ return usage.totalTokens;
95
+ }
96
+ const inputTokens = usage.inputTokens ?? 0;
97
+ const outputTokens = usage.outputTokens ?? 0;
98
+ const reasoningTokens = usage.reasoningTokens ?? 0;
99
+ const computedTotal = inputTokens + outputTokens + reasoningTokens;
100
+ return computedTotal > 0 ? computedTotal : undefined;
101
+ }
102
+ async function readPromptFromStdin() {
103
+ const chunks = [];
104
+ for await (const chunk of process.stdin) {
105
+ if (typeof chunk === 'string') {
106
+ chunks.push(Buffer.from(chunk));
107
+ }
108
+ else {
109
+ chunks.push(chunk);
110
+ }
111
+ }
112
+ return Buffer.concat(chunks).toString('utf-8');
113
+ }
114
+ export async function resolveHeadlessPrompt(promptArg) {
115
+ if (promptArg && promptArg !== '-') {
116
+ return promptArg;
117
+ }
118
+ if (!promptArg && process.stdin.isTTY) {
119
+ throw new Error('No prompt provided. Pass a prompt argument (e.g., dexto run "your prompt") or pipe input via stdin.');
120
+ }
121
+ return await readPromptFromStdin();
122
+ }
123
+ export function printHeadlessMcpStartup(agent) {
124
+ const serverStatuses = agent.getMcpServersWithStatus().filter((server) => server.enabled);
125
+ if (serverStatuses.length === 0) {
126
+ writeHeadlessTaggedLine('MCP', 'startup: no servers');
127
+ return;
128
+ }
129
+ const readyServers = [];
130
+ const failedServers = [];
131
+ for (const server of serverStatuses) {
132
+ if (server.status === 'connected') {
133
+ readyServers.push(server.name);
134
+ writeHeadlessTaggedLine('MCP', `${server.name} ready`);
135
+ continue;
136
+ }
137
+ failedServers.push(server.name);
138
+ const reason = server.error ? `failed: ${server.error}` : `failed: ${server.status}`;
139
+ writeHeadlessTaggedLine('MCP', `${server.name} ${reason}`);
140
+ }
141
+ const summaryParts = [];
142
+ if (readyServers.length > 0) {
143
+ summaryParts.push(`ready: ${readyServers.join(', ')}`);
144
+ }
145
+ if (failedServers.length > 0) {
146
+ summaryParts.push(`failed: ${failedServers.join(', ')}`);
147
+ }
148
+ writeHeadlessTaggedLine('MCP', `startup: ${summaryParts.join('; ')}`);
149
+ }
150
+ export function printHeadlessRunSummary(params) {
151
+ const { agent, sessionId, prompt, agentPath, cliVersion } = params;
152
+ const llmConfig = agent.getCurrentLLMConfig(sessionId);
153
+ writeHeadlessSeparator();
154
+ writeHeadlessTaggedLine('RUN', `Dexto CLI v${cliVersion}`);
155
+ writeHeadlessSeparator();
156
+ writeHeadlessLine('[CONFIG]');
157
+ writeHeadlessLine(`workdir: ${process.cwd()}`);
158
+ writeHeadlessLine(`agent: ${agentPath}`);
159
+ writeHeadlessLine(`model: ${llmConfig.model}`);
160
+ writeHeadlessLine(`provider: ${llmConfig.provider}`);
161
+ writeHeadlessLine(`approval: ${agent.config.permissions.mode}`);
162
+ writeHeadlessLine(`session id: ${sessionId}`);
163
+ writeHeadlessSeparator();
164
+ writeHeadlessTaggedBlock('USER', prompt);
165
+ }
166
+ export async function executeHeadlessRun(agent, sessionId, prompt) {
167
+ const toolCallState = new Map();
168
+ let anonymousToolCallCounter = 0;
169
+ let finalMessage;
170
+ let totalTokens;
171
+ let fatalError;
172
+ for await (const event of await agent.stream(prompt, sessionId)) {
173
+ switch (event.name) {
174
+ case 'llm:tool-call': {
175
+ const callKey = event.callId ?? `anonymous-${++anonymousToolCallCounter}`;
176
+ const call = {
177
+ toolName: event.toolName,
178
+ args: event.args,
179
+ startedAt: Date.now(),
180
+ };
181
+ toolCallState.set(callKey, call);
182
+ writeHeadlessTaggedLine('TOOL', formatToolInvocationForHeadless(call.toolName, call.args));
183
+ break;
184
+ }
185
+ case 'tool:running': {
186
+ const runningCall = toolCallState.get(event.toolCallId);
187
+ if (runningCall) {
188
+ runningCall.startedAt = Date.now();
189
+ }
190
+ break;
191
+ }
192
+ case 'llm:tool-result': {
193
+ let matchedCallKey = event.callId;
194
+ let matchedCall = matchedCallKey ? toolCallState.get(matchedCallKey) : undefined;
195
+ if (!matchedCall) {
196
+ const reverseEntries = Array.from(toolCallState.entries()).reverse();
197
+ const fallback = reverseEntries.find(([, call]) => call.toolName === event.toolName);
198
+ if (fallback) {
199
+ matchedCallKey = fallback[0];
200
+ matchedCall = fallback[1];
201
+ }
202
+ }
203
+ const toolName = matchedCall?.toolName ?? event.toolName;
204
+ const args = matchedCall?.args ?? {};
205
+ const invocation = formatToolInvocationForHeadless(toolName, args);
206
+ const durationText = matchedCall
207
+ ? ` in ${formatHeadlessDuration(Date.now() - matchedCall.startedAt)}`
208
+ : '';
209
+ const statusTag = event.success ? 'TOOL:OK' : 'TOOL:ERR';
210
+ writeHeadlessTaggedLine(statusTag, `${invocation}${durationText}`);
211
+ const output = extractToolOutputForHeadless(event);
212
+ if (output && output.trim().length > 0) {
213
+ writeHeadlessTaggedBlock('TOOL:OUT', truncateOutputForHeadless(output));
214
+ }
215
+ if (matchedCallKey) {
216
+ toolCallState.delete(matchedCallKey);
217
+ }
218
+ break;
219
+ }
220
+ case 'llm:response': {
221
+ finalMessage = event.content;
222
+ totalTokens = getTotalTokensFromResponse(event);
223
+ break;
224
+ }
225
+ case 'llm:unsupported-input': {
226
+ writeHeadlessTaggedLine('WARNING', event.errors.join('; '));
227
+ break;
228
+ }
229
+ case 'llm:error': {
230
+ if (!event.recoverable) {
231
+ fatalError = event.error;
232
+ writeHeadlessTaggedLine('ERROR', event.error.message);
233
+ }
234
+ break;
235
+ }
236
+ case 'run:complete': {
237
+ if (event.finishReason === 'error' && event.error) {
238
+ fatalError = event.error;
239
+ writeHeadlessTaggedLine('ERROR', event.error.message);
240
+ }
241
+ break;
242
+ }
243
+ default:
244
+ break;
245
+ }
246
+ }
247
+ const result = {};
248
+ if (finalMessage !== undefined) {
249
+ result.finalMessage = finalMessage;
250
+ }
251
+ if (totalTokens !== undefined) {
252
+ result.totalTokens = totalTokens;
253
+ }
254
+ if (fatalError !== undefined) {
255
+ result.fatalError = fatalError;
256
+ }
257
+ return result;
258
+ }
259
+ export function printHeadlessAssistantResponse(message, totalTokens) {
260
+ writeHeadlessSeparator();
261
+ writeHeadlessTaggedBlock('DEXTO', message);
262
+ if (typeof totalTokens === 'number') {
263
+ writeHeadlessTaggedLine('TOKENS', new Intl.NumberFormat('en-US').format(totalTokens));
264
+ }
265
+ }
266
+ export function writeFinalMessageToStdout(message) {
267
+ if (message.endsWith('\n')) {
268
+ process.stdout.write(message);
269
+ return;
270
+ }
271
+ process.stdout.write(`${message}\n`);
272
+ }
273
+ export function writeHeadlessError(message) {
274
+ writeHeadlessTaggedLine('ERROR', message);
275
+ }
@@ -0,0 +1,3 @@
1
+ import type { RuntimeCommandRegisterContext } from '../register-context.js';
2
+ export declare function registerRunCommand({ program, cliVersion, bootstrapAgentFromGlobalOpts, }: RuntimeCommandRegisterContext): void;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/run/register.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,kBAAkB,CAAC,EAC/B,OAAO,EACP,UAAU,EACV,4BAA4B,GAC/B,EAAE,6BAA6B,GAAG,IAAI,CA+FtC"}