dexto 1.6.8 → 1.6.10

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 (105) 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.d.ts.map +1 -1
  75. package/dist/cli/commands/sync-agents.js +16 -7
  76. package/dist/cli/commands/uninstall.d.ts +2 -2
  77. package/dist/cli/modes/cli.d.ts +3 -0
  78. package/dist/cli/modes/cli.d.ts.map +1 -0
  79. package/dist/cli/modes/cli.js +170 -0
  80. package/dist/cli/modes/context.d.ts +20 -0
  81. package/dist/cli/modes/context.d.ts.map +1 -0
  82. package/dist/cli/modes/context.js +1 -0
  83. package/dist/cli/modes/dispatch.d.ts +3 -0
  84. package/dist/cli/modes/dispatch.d.ts.map +1 -0
  85. package/dist/cli/modes/dispatch.js +52 -0
  86. package/dist/cli/modes/mcp.d.ts +3 -0
  87. package/dist/cli/modes/mcp.d.ts.map +1 -0
  88. package/dist/cli/modes/mcp.js +23 -0
  89. package/dist/cli/modes/server.d.ts +3 -0
  90. package/dist/cli/modes/server.d.ts.map +1 -0
  91. package/dist/cli/modes/server.js +36 -0
  92. package/dist/cli/modes/web.d.ts +3 -0
  93. package/dist/cli/modes/web.d.ts.map +1 -0
  94. package/dist/cli/modes/web.js +50 -0
  95. package/dist/cli/utils/setup-utils.js +1 -1
  96. package/dist/index-main.js +150 -991
  97. package/dist/utils/port-utils.d.ts +1 -1
  98. package/dist/utils/port-utils.d.ts.map +1 -1
  99. package/dist/utils/port-utils.js +7 -3
  100. package/dist/webui/assets/index-Bn9YuTdA.css +1 -0
  101. package/dist/webui/assets/index-CNiOYnOb.js +2059 -0
  102. package/dist/webui/index.html +2 -2
  103. package/package.json +12 -12
  104. package/dist/webui/assets/index-d6c-yJNn.js +0 -2059
  105. package/dist/webui/assets/index-yKdFLN1k.css +0 -1
@@ -0,0 +1,78 @@
1
+ import { resolveAgentPath } from '@dexto/agent-management';
2
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
3
+ export function registerRunCommand({ program, cliVersion, bootstrapAgentFromGlobalOpts, }) {
4
+ program
5
+ .command('run [prompt]')
6
+ .description('Run a single prompt non-interactively (headless mode)')
7
+ .option('-m, --model <model>', 'Specify the LLM model to use for this run')
8
+ .addHelpText('after', `
9
+ Examples:
10
+ $ dexto run "summarize this repository"
11
+ $ echo "fix lint errors" | dexto run
12
+ $ dexto run - < prompt.txt
13
+ `)
14
+ .action(withAnalytics('run', async (promptArg, runOptions) => {
15
+ let agent;
16
+ let exitCode = 0;
17
+ let exitReason = 'ok';
18
+ try {
19
+ const { executeHeadlessRun, printHeadlessAssistantResponse, printHeadlessMcpStartup, printHeadlessRunSummary, resolveHeadlessPrompt, writeFinalMessageToStdout, writeHeadlessError, } = await import('./headless.js');
20
+ const prompt = await resolveHeadlessPrompt(promptArg);
21
+ if (prompt.trim().length === 0) {
22
+ writeHeadlessError('Prompt cannot be empty.');
23
+ exitCode = 1;
24
+ exitReason = 'empty-prompt';
25
+ }
26
+ else {
27
+ const bootstrapOptions = runOptions?.model
28
+ ? { mode: 'headless-run', modelOverride: runOptions.model }
29
+ : { mode: 'headless-run' };
30
+ agent = await bootstrapAgentFromGlobalOpts(bootstrapOptions);
31
+ const session = await agent.createSession();
32
+ const globalOpts = program.opts();
33
+ const resolvedAgentPath = await resolveAgentPath(globalOpts.agent, globalOpts.autoInstall !== false);
34
+ printHeadlessRunSummary({
35
+ agent,
36
+ sessionId: session.id,
37
+ prompt,
38
+ agentPath: resolvedAgentPath,
39
+ cliVersion,
40
+ });
41
+ printHeadlessMcpStartup(agent);
42
+ const runResult = await executeHeadlessRun(agent, session.id, prompt);
43
+ if (runResult.finalMessage !== undefined) {
44
+ printHeadlessAssistantResponse(runResult.finalMessage, runResult.totalTokens);
45
+ writeFinalMessageToStdout(runResult.finalMessage);
46
+ }
47
+ else {
48
+ writeHeadlessError('No final response was produced.');
49
+ exitCode = 1;
50
+ exitReason = 'no-final-response';
51
+ }
52
+ if (runResult.fatalError) {
53
+ exitCode = 1;
54
+ exitReason = 'fatal-error';
55
+ }
56
+ }
57
+ }
58
+ catch (err) {
59
+ if (err instanceof ExitSignal)
60
+ throw err;
61
+ const errorMessage = err instanceof Error ? err.message : String(err);
62
+ process.stderr.write(`dexto run failed: ${errorMessage}\n`);
63
+ exitCode = 1;
64
+ exitReason = 'error';
65
+ }
66
+ finally {
67
+ if (agent) {
68
+ try {
69
+ await agent.stop();
70
+ }
71
+ catch {
72
+ // Ignore shutdown errors in headless mode cleanup
73
+ }
74
+ }
75
+ }
76
+ safeExit('run', exitCode, exitReason);
77
+ }));
78
+ }
@@ -0,0 +1,3 @@
1
+ import type { RuntimeCommandRegisterContext } from '../register-context.js';
2
+ export declare function registerSearchCommand({ program, bootstrapAgentFromGlobalOpts, }: RuntimeCommandRegisterContext): void;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/search/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,qBAAqB,CAAC,EAClC,OAAO,EACP,4BAA4B,GAC/B,EAAE,6BAA6B,GAAG,IAAI,CA8EtC"}
@@ -0,0 +1,55 @@
1
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
2
+ export function registerSearchCommand({ program, bootstrapAgentFromGlobalOpts, }) {
3
+ program
4
+ .command('search')
5
+ .description('Search session history')
6
+ .argument('<query>', 'Search query')
7
+ .option('--session <sessionId>', 'Search in specific session')
8
+ .option('--role <role>', 'Filter by role (user, assistant, system, tool)')
9
+ .option('--limit <number>', 'Limit number of results', '10')
10
+ .action(withAnalytics('search', async (query, options) => {
11
+ let agent = null;
12
+ try {
13
+ const searchOptions = {};
14
+ if (options.session) {
15
+ searchOptions.sessionId = options.session;
16
+ }
17
+ if (options.role) {
18
+ const allowed = new Set(['user', 'assistant', 'system', 'tool']);
19
+ if (!allowed.has(options.role)) {
20
+ console.error(`❌ Invalid role: ${options.role}. Use one of: user, assistant, system, tool`);
21
+ safeExit('search', 1, 'invalid-role');
22
+ }
23
+ searchOptions.role = options.role;
24
+ }
25
+ if (options.limit) {
26
+ const rawLimit = options.limit.trim();
27
+ const parsed = Number(rawLimit);
28
+ if (!/^\d+$/.test(rawLimit) ||
29
+ !Number.isInteger(parsed) ||
30
+ parsed <= 0) {
31
+ console.error(`❌ Invalid --limit: ${options.limit}. Use a positive integer (e.g., 10).`);
32
+ safeExit('search', 1, 'invalid-limit');
33
+ }
34
+ searchOptions.limit = parsed;
35
+ }
36
+ agent = await bootstrapAgentFromGlobalOpts({
37
+ mode: 'non-interactive',
38
+ });
39
+ const { handleSessionSearchCommand } = await import('../session-commands.js');
40
+ await handleSessionSearchCommand(agent, query, searchOptions);
41
+ safeExit('search', 0);
42
+ }
43
+ catch (err) {
44
+ if (err instanceof ExitSignal)
45
+ throw err;
46
+ console.error(`❌ dexto search command failed: ${err}`);
47
+ safeExit('search', 1, 'error');
48
+ }
49
+ finally {
50
+ if (agent) {
51
+ await agent.stop().catch(() => { });
52
+ }
53
+ }
54
+ }));
55
+ }
@@ -0,0 +1,3 @@
1
+ import type { RuntimeCommandRegisterContext } from '../register-context.js';
2
+ export declare function registerSessionCommand({ program, bootstrapAgentFromGlobalOpts, }: RuntimeCommandRegisterContext): void;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/session/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,sBAAsB,CAAC,EACnC,OAAO,EACP,4BAA4B,GAC/B,EAAE,6BAA6B,GAAG,IAAI,CA4EtC"}
@@ -0,0 +1,75 @@
1
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
2
+ export function registerSessionCommand({ program, bootstrapAgentFromGlobalOpts, }) {
3
+ const sessionCommand = program.command('session').description('Manage chat sessions');
4
+ sessionCommand
5
+ .command('list')
6
+ .description('List all sessions')
7
+ .action(withAnalytics('session list', async () => {
8
+ let agent = null;
9
+ try {
10
+ agent = await bootstrapAgentFromGlobalOpts({ mode: 'non-interactive' });
11
+ const { handleSessionListCommand } = await import('../session-commands.js');
12
+ await handleSessionListCommand(agent);
13
+ safeExit('session list', 0);
14
+ }
15
+ catch (err) {
16
+ if (err instanceof ExitSignal)
17
+ throw err;
18
+ console.error(`❌ dexto session list command failed: ${err}`);
19
+ safeExit('session list', 1, 'error');
20
+ }
21
+ finally {
22
+ if (agent) {
23
+ await agent.stop().catch(() => { });
24
+ }
25
+ }
26
+ }));
27
+ sessionCommand
28
+ .command('history')
29
+ .description('Show session history')
30
+ .argument('[sessionId]', 'Session ID (defaults to current session)')
31
+ .action(withAnalytics('session history', async (sessionId) => {
32
+ let agent = null;
33
+ try {
34
+ agent = await bootstrapAgentFromGlobalOpts({ mode: 'non-interactive' });
35
+ const { handleSessionHistoryCommand } = await import('../session-commands.js');
36
+ await handleSessionHistoryCommand(agent, sessionId);
37
+ safeExit('session history', 0);
38
+ }
39
+ catch (err) {
40
+ if (err instanceof ExitSignal)
41
+ throw err;
42
+ console.error(`❌ dexto session history command failed: ${err}`);
43
+ safeExit('session history', 1, 'error');
44
+ }
45
+ finally {
46
+ if (agent) {
47
+ await agent.stop().catch(() => { });
48
+ }
49
+ }
50
+ }));
51
+ sessionCommand
52
+ .command('delete')
53
+ .description('Delete a session')
54
+ .argument('<sessionId>', 'Session ID to delete')
55
+ .action(withAnalytics('session delete', async (sessionId) => {
56
+ let agent = null;
57
+ try {
58
+ agent = await bootstrapAgentFromGlobalOpts({ mode: 'non-interactive' });
59
+ const { handleSessionDeleteCommand } = await import('../session-commands.js');
60
+ await handleSessionDeleteCommand(agent, sessionId);
61
+ safeExit('session delete', 0);
62
+ }
63
+ catch (err) {
64
+ if (err instanceof ExitSignal)
65
+ throw err;
66
+ console.error(`❌ dexto session delete command failed: ${err}`);
67
+ safeExit('session delete', 1, 'error');
68
+ }
69
+ finally {
70
+ if (agent) {
71
+ await agent.stop().catch(() => { });
72
+ }
73
+ }
74
+ }));
75
+ }
@@ -9,7 +9,7 @@ import { selectProvider, getProviderDisplayName, getProviderEnvVar, providerRequ
9
9
  import { setupLocalModels, setupOllamaModels, hasSelectedModel, getModelFromResult, } from '../utils/local-model-setup.js';
10
10
  import { requiresSetup } from '../utils/setup-utils.js';
11
11
  import { canUseDextoProvider } from '../utils/dexto-setup.js';
12
- import { handleBrowserLogin } from './auth/login.js';
12
+ import { handleAutoLogin } from './auth/login.js';
13
13
  import { loadAuth, getDextoApiClient } from '../auth/index.js';
14
14
  import { DEXTO_CREDITS_URL } from '../auth/constants.js';
15
15
  import * as p from '@clack/prompts';
@@ -431,16 +431,16 @@ async function handleDextoProviderSetup(options = {}) {
431
431
  const hasKey = await canUseDextoProvider();
432
432
  if (!hasKey) {
433
433
  p.note(`Dexto gives you instant access to ${chalk.cyan('all AI models')} with a single account.\n\n` +
434
- `We'll open your browser to sign in or create an account.`, 'Login Required');
434
+ `We'll guide you through device-code login.`, 'Login Required');
435
435
  const shouldLogin = await p.confirm({
436
- message: 'Continue with browser login?',
436
+ message: 'Continue with Dexto login?',
437
437
  initialValue: true,
438
438
  });
439
439
  if (p.isCancel(shouldLogin) || !shouldLogin) {
440
440
  return abort('Setup cancelled');
441
441
  }
442
442
  try {
443
- await handleBrowserLogin();
443
+ await handleAutoLogin();
444
444
  // Verify key was actually provisioned (provisionKeys silently catches errors)
445
445
  if (!(await canUseDextoProvider())) {
446
446
  p.log.error('API key provisioning failed. Please try again or use `dexto setup` with a different provider.');
@@ -25,9 +25,9 @@ export declare function shouldPromptForSync(): Promise<boolean>;
25
25
  *
26
26
  * @example
27
27
  * ```bash
28
- * dexto sync-agents # Interactive - prompt for each
29
- * dexto sync-agents --list # Show what would be updated
30
- * dexto sync-agents --force # Update all without prompting
28
+ * dexto agents sync # Interactive - prompt for each
29
+ * dexto agents sync --list # Show what would be updated
30
+ * dexto agents sync --force # Update all without prompting
31
31
  * ```
32
32
  */
33
33
  export declare function handleSyncAgentsCommand(options: SyncAgentsCommandOptions): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"sync-agents.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync-agents.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,wCAAwC;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AA6LD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAyB5D;AAoDD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiO9F"}
1
+ {"version":3,"file":"sync-agents.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync-agents.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,wCAAwC;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AA0MD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAyB5D;AAoDD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiO9F"}
@@ -65,10 +65,19 @@ async function getBundledAgentHash(agentEntry) {
65
65
  /**
66
66
  * Get hash of installed agent
67
67
  */
68
- async function getInstalledAgentHash(agentId) {
68
+ async function getInstalledAgentHash(agentId, agentEntry) {
69
69
  try {
70
70
  const installedPath = path.join(getDextoGlobalPath('agents'), agentId);
71
71
  const stat = await fs.stat(installedPath);
72
+ // Single-file bundled agents are installed inside an agent directory.
73
+ // Hash the installed YAML file so bundled vs installed comparisons stay symmetric.
74
+ if (agentEntry && !agentEntry.source.endsWith('/')) {
75
+ if (!stat.isDirectory()) {
76
+ return await hashFile(installedPath);
77
+ }
78
+ const installedFile = path.join(installedPath, path.basename(agentEntry.source));
79
+ return await hashFile(installedFile);
80
+ }
72
81
  if (stat.isDirectory()) {
73
82
  return await hashDirectory(installedPath);
74
83
  }
@@ -123,7 +132,7 @@ async function getAgentStatus(agentId, agentEntry) {
123
132
  }
124
133
  try {
125
134
  const bundledHash = await getBundledAgentHash(agentEntry);
126
- const installedHash = await getInstalledAgentHash(agentId);
135
+ const installedHash = await getInstalledAgentHash(agentId, agentEntry);
127
136
  if (!bundledHash || !installedHash) {
128
137
  return {
129
138
  id: agentId,
@@ -178,7 +187,7 @@ export async function shouldPromptForSync() {
178
187
  if (!agentEntry)
179
188
  continue;
180
189
  const bundledHash = await getBundledAgentHash(agentEntry);
181
- const installedHash = await getInstalledAgentHash(agentId);
190
+ const installedHash = await getInstalledAgentHash(agentId, agentEntry);
182
191
  if (bundledHash && installedHash && bundledHash !== installedHash) {
183
192
  return true;
184
193
  }
@@ -243,9 +252,9 @@ function formatStatus(status) {
243
252
  *
244
253
  * @example
245
254
  * ```bash
246
- * dexto sync-agents # Interactive - prompt for each
247
- * dexto sync-agents --list # Show what would be updated
248
- * dexto sync-agents --force # Update all without prompting
255
+ * dexto agents sync # Interactive - prompt for each
256
+ * dexto agents sync --list # Show what would be updated
257
+ * dexto agents sync --force # Update all without prompting
249
258
  * ```
250
259
  */
251
260
  export async function handleSyncAgentsCommand(options) {
@@ -363,7 +372,7 @@ export async function handleSyncAgentsCommand(options) {
363
372
  console.log('');
364
373
  // If list mode, stop here
365
374
  if (list) {
366
- p.outro('Use `dexto sync-agents` to update agents');
375
+ p.outro('Use `dexto agents sync` to update agents');
367
376
  return;
368
377
  }
369
378
  // No updates needed
@@ -4,13 +4,13 @@ declare const UninstallCommandSchema: z.ZodObject<{
4
4
  all: z.ZodDefault<z.ZodBoolean>;
5
5
  force: z.ZodDefault<z.ZodBoolean>;
6
6
  }, "strict", z.ZodTypeAny, {
7
- all: boolean;
8
7
  agents: string[];
9
8
  force: boolean;
9
+ all: boolean;
10
10
  }, {
11
11
  agents: string[];
12
- all?: boolean | undefined;
13
12
  force?: boolean | undefined;
13
+ all?: boolean | undefined;
14
14
  }>;
15
15
  export type UninstallCommandOptions = z.output<typeof UninstallCommandSchema>;
16
16
  export declare function handleUninstallCommand(agents: string[], options: Partial<UninstallCommandOptions>): Promise<void>;
@@ -0,0 +1,3 @@
1
+ import type { MainModeContext } from './context.js';
2
+ export declare function runCliMode(context: MainModeContext): Promise<void>;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/cli.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAsBpD,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuLxE"}
@@ -0,0 +1,170 @@
1
+ import * as p from '@clack/prompts';
2
+ import chalk from 'chalk';
3
+ import { logger } from '@dexto/core';
4
+ import { safeExit, ExitSignal } from '../../analytics/wrapper.js';
5
+ async function getMostRecentSessionId(agent) {
6
+ const sessionIds = await agent.listSessions();
7
+ if (sessionIds.length === 0) {
8
+ return null;
9
+ }
10
+ let mostRecentId = null;
11
+ let mostRecentActivity = 0;
12
+ for (const sessionId of sessionIds) {
13
+ const metadata = await agent.getSessionMetadata(sessionId);
14
+ if (metadata && metadata.lastActivity > mostRecentActivity) {
15
+ mostRecentActivity = metadata.lastActivity;
16
+ mostRecentId = sessionId;
17
+ }
18
+ }
19
+ return mostRecentId;
20
+ }
21
+ export async function runCliMode(context) {
22
+ const { agent, opts, validatedConfig, resolvedPath, initialPrompt, getVersionCheckResult } = context;
23
+ const needsHandler = validatedConfig.permissions.mode === 'manual' || validatedConfig.elicitation.enabled;
24
+ if (needsHandler) {
25
+ const { createCLIApprovalHandler } = await import('../approval/index.js');
26
+ const handler = createCLIApprovalHandler(agent);
27
+ agent.setApprovalHandler(handler);
28
+ logger.debug('CLI approval handler configured for Ink CLI');
29
+ }
30
+ await agent.start();
31
+ try {
32
+ const llmConfig = agent.getCurrentLLMConfig();
33
+ const { requiresApiKey } = await import('@dexto/core');
34
+ if (requiresApiKey(llmConfig.provider) && !llmConfig.apiKey?.trim()) {
35
+ const { interactiveApiKeySetup } = await import('../utils/api-key-setup.js');
36
+ console.log(chalk.yellow(`\n⚠️ API key required for provider '${llmConfig.provider}'\n`));
37
+ const setupResult = await interactiveApiKeySetup(llmConfig.provider, {
38
+ exitOnCancel: false,
39
+ model: llmConfig.model,
40
+ });
41
+ if (setupResult.cancelled) {
42
+ safeExit('main', 0, 'api-key-setup-cancelled');
43
+ }
44
+ if (setupResult.skipped) {
45
+ safeExit('main', 0, 'api-key-pending');
46
+ }
47
+ if (setupResult.success && setupResult.apiKey) {
48
+ await agent.switchLLM({
49
+ provider: llmConfig.provider,
50
+ model: llmConfig.model,
51
+ apiKey: setupResult.apiKey,
52
+ });
53
+ logger.info('API key configured successfully, continuing...');
54
+ }
55
+ }
56
+ let cliSessionId;
57
+ if (opts.resume) {
58
+ const existing = await agent.getSession(opts.resume);
59
+ if (!existing) {
60
+ console.error(`❌ Session '${opts.resume}' not found`);
61
+ console.error('💡 Use `dexto session list` to see available sessions');
62
+ safeExit('main', 1, 'resume-failed');
63
+ }
64
+ cliSessionId = opts.resume;
65
+ }
66
+ else if (opts.continue) {
67
+ const mostRecentSessionId = await getMostRecentSessionId(agent);
68
+ if (mostRecentSessionId) {
69
+ cliSessionId = mostRecentSessionId;
70
+ }
71
+ else {
72
+ const session = await agent.createSession();
73
+ cliSessionId = session.id;
74
+ }
75
+ }
76
+ else {
77
+ const session = await agent.createSession();
78
+ cliSessionId = session.id;
79
+ }
80
+ const cliUpdateInfo = await getVersionCheckResult();
81
+ const { shouldPromptForSync, handleSyncAgentsCommand } = await import('../commands/sync-agents.js');
82
+ const needsSync = await shouldPromptForSync();
83
+ if (needsSync) {
84
+ const shouldSync = await p.confirm({
85
+ message: 'Agent config updates available. Sync now?',
86
+ initialValue: true,
87
+ });
88
+ if (!p.isCancel(shouldSync) && shouldSync) {
89
+ await handleSyncAgentsCommand({ force: true, quiet: true });
90
+ }
91
+ }
92
+ const originalConsole = {
93
+ log: console.log,
94
+ error: console.error,
95
+ warn: console.warn,
96
+ info: console.info,
97
+ };
98
+ const noOp = () => { };
99
+ console.log = noOp;
100
+ console.error = noOp;
101
+ console.warn = noOp;
102
+ console.info = noOp;
103
+ let inkError = undefined;
104
+ try {
105
+ const [{ startInkCliRefactored, setTuiRuntimeServices }, { registerGracefulShutdown }, { applyLayeredEnvironmentLoading }, { getProviderDisplayName, isValidApiKeyFormat, getProviderInstructions }, { performDeviceCodeLogin, persistOAuthLoginResult, ensureDextoApiKeyForAuthToken, loadAuth, storeAuth, removeAuth, removeDextoApiKeyFromEnv, }, { isUsingDextoCredits }, { canUseDextoProvider }, { capture },] = await Promise.all([
106
+ import('@dexto/tui'),
107
+ import('../../utils/graceful-shutdown.js'),
108
+ import('../../utils/env.js'),
109
+ import('../utils/provider-setup.js'),
110
+ import('../auth/index.js'),
111
+ import('../../config/effective-llm.js'),
112
+ import('../utils/dexto-setup.js'),
113
+ import('../../analytics/index.js'),
114
+ ]);
115
+ setTuiRuntimeServices({
116
+ registerGracefulShutdown,
117
+ capture: (event, properties) => {
118
+ capture(event, properties);
119
+ },
120
+ applyLayeredEnvironmentLoading,
121
+ getProviderDisplayName,
122
+ isValidApiKeyFormat,
123
+ getProviderInstructions,
124
+ performDeviceCodeLogin,
125
+ persistOAuthLoginResult,
126
+ ensureDextoApiKeyForAuthToken,
127
+ loadAuth,
128
+ storeAuth,
129
+ removeAuth,
130
+ removeDextoApiKeyFromEnv,
131
+ isUsingDextoCredits,
132
+ canUseDextoProvider,
133
+ });
134
+ await startInkCliRefactored(agent, cliSessionId, {
135
+ updateInfo: cliUpdateInfo ?? undefined,
136
+ configFilePath: resolvedPath,
137
+ ...(initialPrompt && { initialPrompt }),
138
+ bypassPermissions: opts.bypassPermissions,
139
+ });
140
+ }
141
+ catch (error) {
142
+ inkError = error;
143
+ }
144
+ finally {
145
+ console.log = originalConsole.log;
146
+ console.error = originalConsole.error;
147
+ console.warn = originalConsole.warn;
148
+ console.info = originalConsole.info;
149
+ }
150
+ if (inkError) {
151
+ if (inkError instanceof ExitSignal)
152
+ throw inkError;
153
+ const errorMessage = inkError instanceof Error ? inkError.message : String(inkError);
154
+ console.error(`❌ Ink CLI failed: ${errorMessage}`);
155
+ if (inkError instanceof Error && inkError.stack) {
156
+ console.error(inkError.stack);
157
+ }
158
+ safeExit('main', 1, 'ink-cli-error');
159
+ }
160
+ safeExit('main', 0);
161
+ }
162
+ finally {
163
+ try {
164
+ await agent.stop();
165
+ }
166
+ catch {
167
+ // Ignore shutdown errors
168
+ }
169
+ }
170
+ }
@@ -0,0 +1,20 @@
1
+ import type { ValidatedAgentConfig } from '@dexto/agent-config';
2
+ import type { DextoAgent } from '@dexto/core';
3
+ import type { UpdateInfo } from '../utils/version-check.js';
4
+ export interface MainModeOptions {
5
+ mode: string;
6
+ port?: string;
7
+ resume?: string;
8
+ continue?: boolean;
9
+ bypassPermissions?: boolean;
10
+ }
11
+ export interface MainModeContext {
12
+ agent: DextoAgent;
13
+ opts: MainModeOptions;
14
+ validatedConfig: ValidatedAgentConfig;
15
+ resolvedPath: string;
16
+ derivedAgentId: string;
17
+ initialPrompt: string | undefined;
18
+ getVersionCheckResult: () => Promise<UpdateInfo | null>;
19
+ }
20
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,eAAe,CAAC;IACtB,eAAe,EAAE,oBAAoB,CAAC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,qBAAqB,EAAE,MAAM,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAC3D"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { MainModeContext } from './context.js';
2
+ export declare function dispatchMainMode(context: MainModeContext): Promise<void>;
3
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/dispatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD9E"}
@@ -0,0 +1,52 @@
1
+ import { safeExit, ExitSignal } from '../../analytics/wrapper.js';
2
+ export async function dispatchMainMode(context) {
3
+ const mode = context.opts.mode;
4
+ try {
5
+ switch (mode) {
6
+ case 'cli': {
7
+ const { runCliMode } = await import('./cli.js');
8
+ await runCliMode(context);
9
+ return;
10
+ }
11
+ case 'web': {
12
+ const { runWebMode } = await import('./web.js');
13
+ await runWebMode(context);
14
+ return;
15
+ }
16
+ case 'server': {
17
+ const { runServerMode } = await import('./server.js');
18
+ await runServerMode(context);
19
+ return;
20
+ }
21
+ case 'mcp': {
22
+ const { runMcpMode } = await import('./mcp.js');
23
+ await runMcpMode(context);
24
+ return;
25
+ }
26
+ default:
27
+ if (mode === 'discord' || mode === 'telegram') {
28
+ console.error(`❌ Error: '${mode}' mode has been moved to examples`);
29
+ console.error('');
30
+ console.error(`The ${mode} bot is now a standalone example that you can customize.`);
31
+ console.error('');
32
+ console.error(`📖 See: examples/${mode}-bot/README.md`);
33
+ console.error('');
34
+ console.error('To run it:');
35
+ console.error(` cd examples/${mode}-bot`);
36
+ console.error(' pnpm install');
37
+ console.error(' pnpm start');
38
+ }
39
+ else {
40
+ console.error(`❌ Unknown mode '${mode}'. Use web, cli, server, or mcp.`);
41
+ }
42
+ safeExit('main', 1, 'unknown-mode');
43
+ }
44
+ }
45
+ catch (err) {
46
+ if (err instanceof ExitSignal)
47
+ throw err;
48
+ const message = err instanceof Error ? err.message : String(err);
49
+ console.error(`❌ Failed to start '${mode}' mode: ${message}`);
50
+ safeExit('main', 1, 'mode-startup-failed');
51
+ }
52
+ }
@@ -0,0 +1,3 @@
1
+ import type { MainModeContext } from './context.js';
2
+ export declare function runMcpMode(context: MainModeContext): Promise<void>;
3
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBxE"}
@@ -0,0 +1,23 @@
1
+ import { createAgentCard } from '@dexto/core';
2
+ import { safeExit } from '../../analytics/wrapper.js';
3
+ export async function runMcpMode(context) {
4
+ const { agent } = context;
5
+ const agentCardConfig = agent.config.agentCard || {
6
+ name: 'dexto',
7
+ version: '1.0.0',
8
+ };
9
+ try {
10
+ const agentCardData = createAgentCard({
11
+ defaultName: agentCardConfig.name ?? 'dexto',
12
+ defaultVersion: agentCardConfig.version ?? '1.0.0',
13
+ defaultBaseUrl: 'stdio://local-dexto',
14
+ }, agentCardConfig);
15
+ const { createMcpTransport, initializeMcpServer } = await import('@dexto/server');
16
+ const mcpTransport = await createMcpTransport('stdio');
17
+ await initializeMcpServer(agent, agentCardData, mcpTransport);
18
+ }
19
+ catch (err) {
20
+ process.stderr.write(`MCP server startup failed: ${err}\n`);
21
+ safeExit('main', 1, 'mcp-startup-failed');
22
+ }
23
+ }