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
@@ -1,47 +1,42 @@
1
1
  // packages/cli/src/cli/commands/auth/login.ts
2
2
  import chalk from 'chalk';
3
3
  import * as p from '@clack/prompts';
4
- import { isAuthenticated, loadAuth, storeAuth, getDextoApiClient, ensureDextoApiKeyForAuthToken, SUPABASE_URL, SUPABASE_ANON_KEY, } from '../../auth/index.js';
4
+ import { getDextoApiClient, isAuthenticated, loadAuth, performDeviceCodeLogin, persistOAuthLoginResult, storeAuth, ensureDextoApiKeyForAuthToken, } from '../../auth/index.js';
5
5
  import { logger } from '@dexto/core';
6
- function printProvisionStatus(status) {
7
- switch (status.level) {
8
- case 'success':
9
- console.log(chalk.green(`✅ ${status.message}`));
10
- return;
11
- case 'error':
12
- console.log(chalk.red(`❌ ${status.message}`));
13
- return;
14
- case 'warning':
15
- console.log(chalk.yellow(`⚠️ ${status.message}`));
16
- return;
17
- case 'info':
18
- console.log(chalk.cyan(`ℹ️ ${status.message}`));
19
- return;
20
- }
6
+ function isCancellationError(errorMessage) {
7
+ const lower = errorMessage.toLowerCase();
8
+ return (lower.includes('canceled') ||
9
+ lower.includes('cancelled') ||
10
+ lower.includes('user denied') ||
11
+ lower.includes('user_denied') ||
12
+ lower.includes('access_denied') ||
13
+ lower.includes('access denied by user') ||
14
+ lower.includes('device login was denied'));
21
15
  }
22
- /**
23
- * Handle login command - multiple methods supported
24
- */
16
+ // Handle login command with device code as the default flow.
25
17
  export async function handleLoginCommand(options = {}) {
26
18
  try {
19
+ if (options.apiKey && options.token) {
20
+ throw new Error('Cannot use both --api-key and --token. Choose one.');
21
+ }
27
22
  if (await isAuthenticated()) {
28
23
  const auth = await loadAuth();
29
24
  const userInfo = auth?.email || auth?.userId || 'user';
30
25
  console.log(chalk.green(`✅ Already logged in as: ${userInfo}`));
31
- // In non-interactive mode, already authenticated = success (idempotent)
32
- if (options.interactive === false) {
33
- return;
34
- }
35
- const shouldContinue = await p.confirm({
36
- message: 'Do you want to login with a different account?',
37
- initialValue: false,
38
- });
39
- if (p.isCancel(shouldContinue) || !shouldContinue) {
40
- return;
26
+ if (!options.apiKey && !options.token) {
27
+ if (options.interactive === false) {
28
+ return;
29
+ }
30
+ const shouldContinue = await p.confirm({
31
+ message: 'Do you want to login with a different account?',
32
+ initialValue: false,
33
+ });
34
+ if (p.isCancel(shouldContinue) || !shouldContinue) {
35
+ return;
36
+ }
41
37
  }
42
38
  }
43
39
  if (options.apiKey) {
44
- // Validate the Dexto API key before storing
45
40
  const client = getDextoApiClient();
46
41
  const isValid = await client.validateDextoApiKey(options.apiKey);
47
42
  if (!isValid) {
@@ -55,88 +50,82 @@ export async function handleLoginCommand(options = {}) {
55
50
  console.log(chalk.green('✅ Dexto API key saved'));
56
51
  return;
57
52
  }
58
- if (options.interactive === false) {
59
- throw new Error('--api-key is required when --no-interactive is used');
60
- }
61
- p.intro(chalk.inverse(' Login to Dexto '));
62
- console.log(chalk.dim('This will open your browser for authentication.'));
63
- const shouldUseOAuth = await p.confirm({
64
- message: 'Continue with browser authentication?',
65
- initialValue: true,
66
- });
67
- if (p.isCancel(shouldUseOAuth)) {
68
- p.cancel('Login cancelled');
53
+ if (options.token) {
54
+ const didLogin = await handleTokenLogin(options.token);
55
+ if (!didLogin) {
56
+ throw new Error('Login was cancelled.');
57
+ }
58
+ console.log(chalk.green('🎉 Login successful!'));
69
59
  return;
70
60
  }
71
- if (shouldUseOAuth) {
72
- await handleBrowserLogin();
73
- }
74
- else {
75
- console.log(chalk.dim('\nAlternatively, you can enter a token manually:'));
76
- await handleTokenLogin();
61
+ if (options.interactive === false) {
62
+ await handleDeviceLogin();
63
+ console.log(chalk.green('🎉 Login successful!'));
64
+ return;
77
65
  }
66
+ p.intro(chalk.inverse(' Login to Dexto '));
67
+ await handleDeviceLogin();
78
68
  p.outro(chalk.green('🎉 Login successful!'));
79
69
  }
80
70
  catch (error) {
81
71
  const errorMessage = error instanceof Error ? error.message : String(error);
82
72
  p.outro(chalk.red(`❌ Login failed: ${errorMessage}`));
83
- // Re-throw to let CLI wrapper handle exit and analytics tracking
84
73
  throw error;
85
74
  }
86
75
  }
87
- export async function handleBrowserLogin() {
88
- const { performOAuthLogin, DEFAULT_OAUTH_CONFIG } = await import('../../auth/oauth.js');
76
+ // Compatibility wrapper used by setup flow; always device login.
77
+ export async function handleAutoLogin() {
78
+ await handleDeviceLogin();
79
+ }
80
+ export async function handleDeviceLogin() {
89
81
  try {
90
- const result = await performOAuthLogin(DEFAULT_OAUTH_CONFIG);
91
- const expiresAt = result.expiresIn ? Date.now() + result.expiresIn * 1000 : undefined;
92
- await storeAuth({
93
- token: result.accessToken,
94
- refreshToken: result.refreshToken,
95
- userId: result.user?.id,
96
- email: result.user?.email,
97
- createdAt: Date.now(),
98
- expiresAt,
99
- });
100
- if (result.user?.email) {
101
- console.log(chalk.dim(`\nWelcome back, ${result.user.email}`));
102
- }
103
- const ensured = await ensureDextoApiKeyForAuthToken(result.accessToken, {
104
- onStatus: printProvisionStatus,
82
+ const result = await performDeviceCodeLogin({
83
+ onPrompt: (prompt) => {
84
+ console.log(chalk.cyan('\nUse any browser to complete login:'));
85
+ if (prompt.verificationUrlComplete) {
86
+ console.log(chalk.dim(` • Open: ${prompt.verificationUrlComplete}`));
87
+ console.log(chalk.dim(` • If asked, code: ${prompt.userCode}`));
88
+ }
89
+ else {
90
+ console.log(chalk.dim(` • Open: ${prompt.verificationUrl}`));
91
+ console.log(chalk.dim(` • Enter code: ${prompt.userCode}`));
92
+ }
93
+ console.log(chalk.dim(` • Code expires in ~${Math.ceil(prompt.expiresIn / 60)} min`));
94
+ },
105
95
  });
106
- if (ensured?.keyId) {
107
- console.log(chalk.dim(` Key ID: ${ensured.keyId}`));
108
- }
109
- if (!ensured) {
110
- console.log(chalk.dim(' You can still use Dexto with your own API keys'));
96
+ const persisted = await persistOAuthLoginResult(result);
97
+ if (persisted.email) {
98
+ console.log(chalk.dim(`\nWelcome back, ${persisted.email}`));
111
99
  }
112
100
  }
113
101
  catch (error) {
114
102
  const errorMessage = error instanceof Error ? error.message : String(error);
115
- if (errorMessage.includes('timed out')) {
116
- throw new Error('Login timed out. Please try again.');
117
- }
118
- else if (errorMessage.includes('user denied')) {
103
+ if (isCancellationError(errorMessage)) {
119
104
  throw new Error('Login was cancelled.');
120
105
  }
121
- else {
122
- throw new Error(`Login failed: ${errorMessage}`);
123
- }
106
+ throw new Error(`Device login failed: ${errorMessage}`);
124
107
  }
125
108
  }
126
- async function handleTokenLogin() {
127
- const token = await p.password({
128
- message: 'Enter your API token:',
129
- validate: (value) => {
130
- if (!value)
131
- return 'Token is required';
132
- if (value.length < 10)
133
- return 'Token seems too short';
134
- return undefined;
135
- },
136
- });
137
- if (p.isCancel(token)) {
138
- p.cancel('Token entry cancelled');
139
- return;
109
+ async function handleTokenLogin(tokenInput) {
110
+ let token = tokenInput?.trim();
111
+ if (!token) {
112
+ const promptedToken = await p.password({
113
+ message: 'Enter your API token:',
114
+ validate: (value) => {
115
+ if (!value)
116
+ return 'Token is required';
117
+ if (value.length < 10)
118
+ return 'Token seems too short';
119
+ return undefined;
120
+ },
121
+ });
122
+ if (p.isCancel(promptedToken)) {
123
+ return false;
124
+ }
125
+ token = promptedToken;
126
+ }
127
+ if (token.length < 10) {
128
+ throw new Error('Token seems too short');
140
129
  }
141
130
  const spinner = p.spinner();
142
131
  spinner.start('Verifying token...');
@@ -148,19 +137,11 @@ async function handleTokenLogin() {
148
137
  }
149
138
  spinner.stop('Token verified!');
150
139
  await storeAuth({
151
- token: token,
140
+ token,
152
141
  createdAt: Date.now(),
153
142
  });
154
- // Provision Dexto API key for gateway access
155
- const ensured = await ensureDextoApiKeyForAuthToken(token, {
156
- onStatus: printProvisionStatus,
157
- });
158
- if (ensured?.keyId) {
159
- console.log(chalk.dim(` Key ID: ${ensured.keyId}`));
160
- }
161
- if (!ensured) {
162
- console.log(chalk.dim(' You can still use Dexto with your own API keys'));
163
- }
143
+ await ensureDextoApiKeyForAuthToken(token);
144
+ return true;
164
145
  }
165
146
  catch (error) {
166
147
  spinner.stop('Verification failed');
@@ -169,19 +150,8 @@ async function handleTokenLogin() {
169
150
  }
170
151
  async function verifyToken(token) {
171
152
  try {
172
- const response = await fetch(`${SUPABASE_URL}/auth/v1/user`, {
173
- headers: {
174
- Authorization: `Bearer ${token}`,
175
- apikey: SUPABASE_ANON_KEY,
176
- 'User-Agent': 'dexto-cli/1.0.0',
177
- },
178
- signal: AbortSignal.timeout(10_000),
179
- });
180
- if (response.ok) {
181
- const userData = await response.json();
182
- return !!userData.id;
183
- }
184
- return false;
153
+ const apiClient = getDextoApiClient();
154
+ return apiClient.validateSupabaseAccessToken(token);
185
155
  }
186
156
  catch (error) {
187
157
  logger.debug(`Token verification failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/logout.ts"],"names":[],"mappings":"AAQA,wBAAsB,mBAAmB,CACrC,OAAO,GAAE;IACL,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACpB,GACP,OAAO,CAAC,IAAI,CAAC,CA2Df"}
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/logout.ts"],"names":[],"mappings":"AAaA,wBAAsB,mBAAmB,CACrC,OAAO,GAAE;IACL,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACpB,GACP,OAAO,CAAC,IAAI,CAAC,CA8Ff"}
@@ -1,7 +1,7 @@
1
1
  // packages/cli/src/cli/commands/auth/logout.ts
2
2
  import chalk from 'chalk';
3
3
  import * as p from '@clack/prompts';
4
- import { isAuthenticated, removeAuth } from '../../auth/index.js';
4
+ import { isAuthenticated, loadAuth, removeAuth, removeDextoApiKeyFromEnv, } from '../../auth/index.js';
5
5
  import { isUsingDextoCredits } from '../../../config/effective-llm.js';
6
6
  import { logger } from '@dexto/core';
7
7
  export async function handleLogoutCommand(options = {}) {
@@ -32,7 +32,37 @@ export async function handleLogoutCommand(options = {}) {
32
32
  return;
33
33
  }
34
34
  }
35
- await removeAuth();
35
+ let provisionedApiKey = null;
36
+ const auth = await loadAuth();
37
+ if (auth?.dextoApiKey && auth.dextoApiKeySource === 'provisioned') {
38
+ provisionedApiKey = auth.dextoApiKey;
39
+ }
40
+ let removeAuthError;
41
+ try {
42
+ await removeAuth();
43
+ }
44
+ catch (error) {
45
+ removeAuthError = error;
46
+ }
47
+ if (provisionedApiKey) {
48
+ try {
49
+ await removeDextoApiKeyFromEnv({ expectedValue: provisionedApiKey });
50
+ }
51
+ catch (cleanupError) {
52
+ if (!removeAuthError) {
53
+ throw cleanupError;
54
+ }
55
+ logger.warn('Failed to clean up provisioned DEXTO_API_KEY after removeAuth error', {
56
+ removeAuthError: removeAuthError instanceof Error
57
+ ? removeAuthError.message
58
+ : String(removeAuthError),
59
+ cleanupError: cleanupError instanceof Error ? cleanupError.message : String(cleanupError),
60
+ });
61
+ }
62
+ }
63
+ if (removeAuthError) {
64
+ throw removeAuthError;
65
+ }
36
66
  console.log(chalk.green('✅ Successfully logged out'));
37
67
  if (usingDextoCredits) {
38
68
  console.log();
@@ -0,0 +1,3 @@
1
+ import type { RuntimeCommandRegisterContext } from '../register-context.js';
2
+ export declare function registerAuthCommand({ program }: RuntimeCommandRegisterContext): void;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/auth/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,mBAAmB,CAAC,EAAE,OAAO,EAAE,EAAE,6BAA6B,GAAG,IAAI,CA0GpF"}
@@ -0,0 +1,94 @@
1
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
2
+ export function registerAuthCommand({ program }) {
3
+ const authCommand = program.command('auth').description('Manage authentication');
4
+ authCommand
5
+ .command('login')
6
+ .description('Login to Dexto')
7
+ .option('--api-key <key>', 'Use Dexto API key instead of device-code login')
8
+ .option('--token <token>', 'Use an existing Supabase access token')
9
+ .option('--no-interactive', 'Disable interactive prompts')
10
+ .action(withAnalytics('auth login', async (options) => {
11
+ try {
12
+ const { handleLoginCommand } = await import('./login.js');
13
+ await handleLoginCommand(options);
14
+ safeExit('auth login', 0);
15
+ }
16
+ catch (err) {
17
+ if (err instanceof ExitSignal)
18
+ throw err;
19
+ console.error(`❌ dexto auth login command failed: ${err}`);
20
+ safeExit('auth login', 1, 'error');
21
+ }
22
+ }));
23
+ authCommand
24
+ .command('logout')
25
+ .description('Logout from Dexto')
26
+ .option('--force', 'Skip confirmation prompt')
27
+ .option('--no-interactive', 'Disable interactive prompts')
28
+ .action(withAnalytics('auth logout', async (options) => {
29
+ try {
30
+ const { handleLogoutCommand } = await import('./logout.js');
31
+ await handleLogoutCommand(options);
32
+ safeExit('auth logout', 0);
33
+ }
34
+ catch (err) {
35
+ if (err instanceof ExitSignal)
36
+ throw err;
37
+ console.error(`❌ dexto auth logout command failed: ${err}`);
38
+ safeExit('auth logout', 1, 'error');
39
+ }
40
+ }));
41
+ authCommand
42
+ .command('status')
43
+ .description('Show authentication status')
44
+ .action(withAnalytics('auth status', async () => {
45
+ try {
46
+ const { handleStatusCommand } = await import('./status.js');
47
+ await handleStatusCommand();
48
+ safeExit('auth status', 0);
49
+ }
50
+ catch (err) {
51
+ if (err instanceof ExitSignal)
52
+ throw err;
53
+ console.error(`❌ dexto auth status command failed: ${err}`);
54
+ safeExit('auth status', 1, 'error');
55
+ }
56
+ }));
57
+ program
58
+ .command('login')
59
+ .description('Login to Dexto (alias for `dexto auth login`)')
60
+ .option('--api-key <key>', 'Use Dexto API key instead of device-code login')
61
+ .option('--token <token>', 'Use an existing Supabase access token')
62
+ .option('--no-interactive', 'Disable interactive prompts')
63
+ .action(withAnalytics('login', async (options) => {
64
+ try {
65
+ const { handleLoginCommand } = await import('./login.js');
66
+ await handleLoginCommand(options);
67
+ safeExit('login', 0);
68
+ }
69
+ catch (err) {
70
+ if (err instanceof ExitSignal)
71
+ throw err;
72
+ console.error(`❌ dexto login command failed: ${err}`);
73
+ safeExit('login', 1, 'error');
74
+ }
75
+ }));
76
+ program
77
+ .command('logout')
78
+ .description('Logout from Dexto (alias for `dexto auth logout`)')
79
+ .option('--force', 'Skip confirmation prompt')
80
+ .option('--no-interactive', 'Disable interactive prompts')
81
+ .action(withAnalytics('logout', async (options) => {
82
+ try {
83
+ const { handleLogoutCommand } = await import('./logout.js');
84
+ await handleLogoutCommand(options);
85
+ safeExit('logout', 0);
86
+ }
87
+ catch (err) {
88
+ if (err instanceof ExitSignal)
89
+ throw err;
90
+ console.error(`❌ dexto logout command failed: ${err}`);
91
+ safeExit('logout', 1, 'error');
92
+ }
93
+ }));
94
+ }
@@ -0,0 +1,3 @@
1
+ import type { RuntimeCommandRegisterContext } from '../register-context.js';
2
+ export declare function registerBillingCommand({ program }: RuntimeCommandRegisterContext): void;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/billing/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,sBAAsB,CAAC,EAAE,OAAO,EAAE,EAAE,6BAA6B,GAAG,IAAI,CAkBvF"}
@@ -0,0 +1,20 @@
1
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
2
+ export function registerBillingCommand({ program }) {
3
+ program
4
+ .command('billing')
5
+ .description('Show billing status and credit balance')
6
+ .option('--buy', 'Open Dexto Nova credits purchase page')
7
+ .action(withAnalytics('billing', async (options) => {
8
+ try {
9
+ const { handleBillingStatusCommand } = await import('./status.js');
10
+ await handleBillingStatusCommand(options);
11
+ safeExit('billing', 0);
12
+ }
13
+ catch (err) {
14
+ if (err instanceof ExitSignal)
15
+ throw err;
16
+ console.error(`❌ dexto billing command failed: ${err}`);
17
+ safeExit('billing', 1, 'error');
18
+ }
19
+ }));
20
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/helpers/formatters.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAY,MAAM,aAAa,CAAC;AAG9E;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,eAAe,EAC1B,SAAS,GAAE,OAAe,GAC3B,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA8DpF"}
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/helpers/formatters.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAY,MAAM,aAAa,CAAC;AAG9E;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,eAAe,EAC1B,SAAS,GAAE,OAAe,GAC3B,MAAM,CAiCR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA8DpF"}
@@ -14,6 +14,15 @@ export function formatSessionInfo(sessionId, metadata, isCurrent = false) {
14
14
  const name = isCurrent ? chalk.green.bold(sessionId) : chalk.cyan(sessionId);
15
15
  let info = `${prefix} ${name}`;
16
16
  if (metadata) {
17
+ const title = typeof metadata.title === 'string' ? metadata.title.trim() : '';
18
+ const displayTitle = title.length > 0 ? title : 'Untitled';
19
+ info += chalk.white(` "${displayTitle}"`);
20
+ const parentSessionId = 'parentSessionId' in metadata && typeof metadata.parentSessionId === 'string'
21
+ ? metadata.parentSessionId
22
+ : undefined;
23
+ if (parentSessionId) {
24
+ info += chalk.magenta(` [forked from ${parentSessionId.slice(0, 8)}]`);
25
+ }
17
26
  const messages = metadata.messageCount || 0;
18
27
  const activity = metadata.lastActivity && metadata.lastActivity > 0
19
28
  ? new Date(metadata.lastActivity).toLocaleString()
@@ -0,0 +1,6 @@
1
+ import type { Command } from 'commander';
2
+ export interface ImageCommandRegisterContext {
3
+ program: Command;
4
+ }
5
+ export declare function registerImageCommand({ program }: ImageCommandRegisterContext): void;
6
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/image/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,MAAM,WAAW,2BAA2B;IACxC,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,EAAE,2BAA2B,GAAG,IAAI,CAqKnF"}
@@ -0,0 +1,144 @@
1
+ import * as p from '@clack/prompts';
2
+ import chalk from 'chalk';
3
+ import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
4
+ export function registerImageCommand({ program }) {
5
+ // `create-image` SUB-COMMAND (hidden alias for `dexto image create`)
6
+ program
7
+ .command('create-image [name]', { hidden: true })
8
+ .description('Alias for `dexto image create`')
9
+ .action(withAnalytics('create-image', async (name) => {
10
+ try {
11
+ p.intro(chalk.inverse('Create Dexto Image'));
12
+ // Create the image project structure
13
+ const { createImage } = await import('../create-image.js');
14
+ const projectPath = await createImage(name);
15
+ p.outro(chalk.greenBright(`Dexto image created successfully at ${projectPath}!`));
16
+ safeExit('create-image', 0);
17
+ }
18
+ catch (err) {
19
+ if (err instanceof ExitSignal)
20
+ throw err;
21
+ console.error(`❌ dexto create-image command failed: ${err}`);
22
+ safeExit('create-image', 1, 'error');
23
+ }
24
+ }));
25
+ // `image` SUB-COMMAND
26
+ const imageCommand = program.command('image').description('Manage images');
27
+ imageCommand.addHelpText('after', `
28
+ Examples:
29
+ $ dexto image create my-image
30
+ $ dexto image install @dexto/image-local
31
+ $ dexto image install @myorg/my-image@1.2.3
32
+ $ dexto image list
33
+ $ dexto image use @myorg/my-image@1.2.3
34
+ $ dexto image remove @myorg/my-image@1.2.3
35
+ $ dexto image doctor
36
+ `);
37
+ imageCommand
38
+ .command('create [name]')
39
+ .description('Create a Dexto image project (scaffold)')
40
+ .action(withAnalytics('image create', async (name) => {
41
+ try {
42
+ p.intro(chalk.inverse('Create Dexto Image'));
43
+ // Create the image project structure
44
+ const { createImage } = await import('../create-image.js');
45
+ const projectPath = await createImage(name);
46
+ p.outro(chalk.greenBright(`Dexto image created successfully at ${projectPath}!`));
47
+ safeExit('image create', 0);
48
+ }
49
+ catch (err) {
50
+ if (err instanceof ExitSignal)
51
+ throw err;
52
+ console.error(`❌ dexto image create command failed: ${err}`);
53
+ safeExit('image create', 1, 'error');
54
+ }
55
+ }));
56
+ imageCommand
57
+ .command('install <image>')
58
+ .description('Install an image into the local Dexto image store')
59
+ .option('--force', 'Force reinstall if already installed')
60
+ .option('--no-activate', 'Do not set as the active version')
61
+ .addHelpText('after', `
62
+ Examples:
63
+ $ dexto image install @dexto/image-local
64
+ $ dexto image install @myorg/my-image@1.2.3
65
+ $ dexto image install ./my-image-1.0.0.tgz
66
+ `)
67
+ .action(withAnalytics('image install', async (image, options) => {
68
+ try {
69
+ const { handleImageInstallCommand } = await import('../image.js');
70
+ await handleImageInstallCommand({ ...options, image });
71
+ safeExit('image install', 0);
72
+ }
73
+ catch (err) {
74
+ if (err instanceof ExitSignal)
75
+ throw err;
76
+ console.error(`❌ dexto image install command failed: ${err}`);
77
+ safeExit('image install', 1, 'error');
78
+ }
79
+ }));
80
+ imageCommand
81
+ .command('list')
82
+ .description('List installed images')
83
+ .action(withAnalytics('image list', async () => {
84
+ try {
85
+ const { handleImageListCommand } = await import('../image.js');
86
+ await handleImageListCommand();
87
+ safeExit('image list', 0);
88
+ }
89
+ catch (err) {
90
+ if (err instanceof ExitSignal)
91
+ throw err;
92
+ console.error(`❌ dexto image list command failed: ${err}`);
93
+ safeExit('image list', 1, 'error');
94
+ }
95
+ }));
96
+ imageCommand
97
+ .command('use <image>')
98
+ .description('Set the active version for an installed image (image@version)')
99
+ .action(withAnalytics('image use', async (image) => {
100
+ try {
101
+ const { handleImageUseCommand } = await import('../image.js');
102
+ await handleImageUseCommand({ image });
103
+ safeExit('image use', 0);
104
+ }
105
+ catch (err) {
106
+ if (err instanceof ExitSignal)
107
+ throw err;
108
+ console.error(`❌ dexto image use command failed: ${err}`);
109
+ safeExit('image use', 1, 'error');
110
+ }
111
+ }));
112
+ imageCommand
113
+ .command('remove <image>')
114
+ .description('Remove an image from the store (image or image@version)')
115
+ .action(withAnalytics('image remove', async (image) => {
116
+ try {
117
+ const { handleImageRemoveCommand } = await import('../image.js');
118
+ await handleImageRemoveCommand({ image });
119
+ safeExit('image remove', 0);
120
+ }
121
+ catch (err) {
122
+ if (err instanceof ExitSignal)
123
+ throw err;
124
+ console.error(`❌ dexto image remove command failed: ${err}`);
125
+ safeExit('image remove', 1, 'error');
126
+ }
127
+ }));
128
+ imageCommand
129
+ .command('doctor')
130
+ .description('Print image store diagnostics')
131
+ .action(withAnalytics('image doctor', async () => {
132
+ try {
133
+ const { handleImageDoctorCommand } = await import('../image.js');
134
+ await handleImageDoctorCommand();
135
+ safeExit('image doctor', 0);
136
+ }
137
+ catch (err) {
138
+ if (err instanceof ExitSignal)
139
+ throw err;
140
+ console.error(`❌ dexto image doctor command failed: ${err}`);
141
+ safeExit('image doctor', 1, 'error');
142
+ }
143
+ }));
144
+ }
@@ -4,13 +4,13 @@ declare const InstallCommandSchema: 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 InstallCommandOptions = z.output<typeof InstallCommandSchema>;
16
16
  export declare function handleInstallCommand(agents: string[], options: Partial<InstallCommandOptions>): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"list-agents.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/list-agents.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,QAAA,MAAM,uBAAuB;;;;;;;;;;;;EAMhB,CAAC;AAEd,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAChF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAiIpF;;GAEG;AACH,wBAAsB,uBAAuB,CACzC,OAAO,EAAE,6BAA6B,GACvC,OAAO,CAAC,IAAI,CAAC,CAiIf"}
1
+ {"version":3,"file":"list-agents.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/list-agents.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,QAAA,MAAM,uBAAuB;;;;;;;;;;;;EAMhB,CAAC;AAEd,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAChF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAiIpF;;GAEG;AACH,wBAAsB,uBAAuB,CACzC,OAAO,EAAE,6BAA6B,GACvC,OAAO,CAAC,IAAI,CAAC,CAmIf"}