dexto 1.1.4 → 1.1.5

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 (106) hide show
  1. package/README.md +476 -0
  2. package/dist/analytics/constants.d.ts +19 -0
  3. package/dist/analytics/constants.d.ts.map +1 -0
  4. package/dist/analytics/constants.js +24 -0
  5. package/dist/analytics/events.d.ts +112 -0
  6. package/dist/analytics/events.d.ts.map +1 -0
  7. package/dist/analytics/events.js +6 -0
  8. package/dist/analytics/index.d.ts +37 -0
  9. package/dist/analytics/index.d.ts.map +1 -0
  10. package/dist/analytics/index.js +145 -0
  11. package/dist/analytics/state.d.ts +23 -0
  12. package/dist/analytics/state.d.ts.map +1 -0
  13. package/dist/analytics/state.js +74 -0
  14. package/dist/analytics/wrapper.d.ts +11 -0
  15. package/dist/analytics/wrapper.d.ts.map +1 -0
  16. package/dist/analytics/wrapper.js +125 -0
  17. package/dist/cli/cli.d.ts +5 -0
  18. package/dist/cli/cli.d.ts.map +1 -1
  19. package/dist/cli/cli.js +10 -4
  20. package/dist/cli/commands/{interactive-commands/session/helpers → helpers}/formatters.d.ts +1 -1
  21. package/dist/cli/commands/helpers/formatters.d.ts.map +1 -0
  22. package/dist/cli/commands/{interactive-commands/session/helpers → helpers}/formatters.js +1 -1
  23. package/dist/cli/commands/install.d.ts.map +1 -1
  24. package/dist/cli/commands/install.js +56 -2
  25. package/dist/cli/commands/interactive-commands/session/index.d.ts +1 -1
  26. package/dist/cli/commands/interactive-commands/session/index.d.ts.map +1 -1
  27. package/dist/cli/commands/interactive-commands/session/index.js +1 -1
  28. package/dist/cli/commands/interactive-commands/session/session-commands.d.ts.map +1 -1
  29. package/dist/cli/commands/interactive-commands/session/session-commands.js +10 -76
  30. package/dist/cli/commands/list-agents.d.ts +2 -2
  31. package/dist/cli/commands/session-commands.d.ts +28 -0
  32. package/dist/cli/commands/session-commands.d.ts.map +1 -0
  33. package/dist/cli/commands/session-commands.js +184 -0
  34. package/dist/cli/commands/setup.d.ts +2 -2
  35. package/dist/cli/commands/setup.d.ts.map +1 -1
  36. package/dist/cli/commands/setup.js +9 -0
  37. package/dist/cli/commands/uninstall.d.ts.map +1 -1
  38. package/dist/cli/commands/uninstall.js +42 -1
  39. package/dist/cli/utils/api-key-setup.js +1 -1
  40. package/dist/index.js +271 -75
  41. package/dist/webui/.next/standalone/.next/static/chunks/854-2a6d5a5297a15d52.js +1 -0
  42. package/dist/webui/.next/standalone/.next/static/chunks/app/{layout-615a56c6184a488f.js → layout-dde711766eda096b.js} +1 -1
  43. package/dist/webui/.next/standalone/.next/static/chunks/app/{page-24123c97236d46cb.js → page-655c5da45b79231a.js} +1 -1
  44. package/dist/webui/.next/{static/css/75b11629ebbc461a.css → standalone/.next/static/css/daca29b49478cfbe.css} +1 -1
  45. package/dist/webui/.next/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  46. package/dist/webui/.next/standalone/package.json +2 -1
  47. package/dist/webui/.next/standalone/packages/webui/.next/BUILD_ID +1 -1
  48. package/dist/webui/.next/standalone/packages/webui/.next/app-build-manifest.json +5 -7
  49. package/dist/webui/.next/standalone/packages/webui/.next/build-manifest.json +2 -2
  50. package/dist/webui/.next/standalone/packages/webui/.next/prerender-manifest.json +3 -3
  51. package/dist/webui/.next/standalone/packages/webui/.next/required-server-files.json +1 -1
  52. package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page.js +2 -2
  53. package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page.js.nft.json +1 -1
  54. package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  55. package/dist/webui/.next/standalone/packages/webui/.next/server/app/page.js +3 -3
  56. package/dist/webui/.next/standalone/packages/webui/.next/server/app/page.js.nft.json +1 -1
  57. package/dist/webui/.next/standalone/packages/webui/.next/server/app/page_client-reference-manifest.js +1 -1
  58. package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page.js +3 -3
  59. package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page.js.nft.json +1 -1
  60. package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page_client-reference-manifest.js +1 -1
  61. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/43.js +1 -4
  62. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/619.js +30 -0
  63. package/dist/webui/.next/standalone/packages/webui/.next/server/next-font-manifest.js +1 -1
  64. package/dist/webui/.next/standalone/packages/webui/.next/server/next-font-manifest.json +1 -1
  65. package/dist/webui/.next/standalone/packages/webui/.next/server/pages/500.html +1 -1
  66. package/dist/webui/.next/standalone/packages/webui/.next/server/pages/_error.js +2 -2
  67. package/dist/webui/.next/standalone/packages/webui/.next/server/server-reference-manifest.json +1 -1
  68. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/854-2a6d5a5297a15d52.js +1 -0
  69. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/{layout-615a56c6184a488f.js → layout-dde711766eda096b.js} +1 -1
  70. package/dist/webui/.next/{static/chunks/app/page-24123c97236d46cb.js → standalone/packages/webui/.next/static/chunks/app/page-655c5da45b79231a.js} +1 -1
  71. package/dist/webui/.next/standalone/{.next/static/css/75b11629ebbc461a.css → packages/webui/.next/static/css/daca29b49478cfbe.css} +1 -1
  72. package/dist/webui/.next/standalone/packages/webui/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  73. package/dist/webui/.next/standalone/packages/webui/package.json +1 -1
  74. package/dist/webui/.next/standalone/packages/webui/server.js +1 -1
  75. package/dist/webui/.next/static/chunks/854-2a6d5a5297a15d52.js +1 -0
  76. package/dist/webui/.next/static/chunks/app/{layout-615a56c6184a488f.js → layout-dde711766eda096b.js} +1 -1
  77. package/dist/webui/.next/{standalone/packages/webui/.next/static/chunks/app/page-24123c97236d46cb.js → static/chunks/app/page-655c5da45b79231a.js} +1 -1
  78. package/dist/webui/.next/{standalone/packages/webui/.next/static/css/75b11629ebbc461a.css → static/css/daca29b49478cfbe.css} +1 -1
  79. package/dist/webui/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  80. package/dist/webui/package.json +1 -1
  81. package/package.json +7 -4
  82. package/dist/cli/commands/interactive-commands/session/helpers/formatters.d.ts.map +0 -1
  83. package/dist/webui/.next/standalone/.next/static/chunks/221-608218ab04068cb2.js +0 -1
  84. package/dist/webui/.next/standalone/.next/static/chunks/854-47418382efcea1d4.js +0 -1
  85. package/dist/webui/.next/standalone/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  86. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/387.js +0 -14
  87. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/392.js +0 -1
  88. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/450.js +0 -139
  89. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/514.js +0 -2
  90. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/531.js +0 -1
  91. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/723.js +0 -1
  92. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/737.js +0 -1
  93. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/767.js +0 -20
  94. package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/89.js +0 -95
  95. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/221-608218ab04068cb2.js +0 -1
  96. package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/854-47418382efcea1d4.js +0 -1
  97. package/dist/webui/.next/standalone/packages/webui/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  98. package/dist/webui/.next/static/chunks/221-608218ab04068cb2.js +0 -1
  99. package/dist/webui/.next/static/chunks/854-47418382efcea1d4.js +0 -1
  100. package/dist/webui/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  101. /package/dist/webui/.next/standalone/.next/static/{abgua6ybDH7yT2b5rvLlU → wcYVcRLx1mruRrV5-XkIK}/_buildManifest.js +0 -0
  102. /package/dist/webui/.next/standalone/.next/static/{abgua6ybDH7yT2b5rvLlU → wcYVcRLx1mruRrV5-XkIK}/_ssgManifest.js +0 -0
  103. /package/dist/webui/.next/standalone/packages/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → wcYVcRLx1mruRrV5-XkIK}/_buildManifest.js +0 -0
  104. /package/dist/webui/.next/standalone/packages/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → wcYVcRLx1mruRrV5-XkIK}/_ssgManifest.js +0 -0
  105. /package/dist/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → wcYVcRLx1mruRrV5-XkIK}/_buildManifest.js +0 -0
  106. /package/dist/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → wcYVcRLx1mruRrV5-XkIK}/_ssgManifest.js +0 -0
@@ -19,7 +19,7 @@
19
19
  */
20
20
  import chalk from 'chalk';
21
21
  import { logger } from '@dexto/core';
22
- import { formatSessionInfo, formatHistoryMessage } from './helpers/formatters.js';
22
+ import { formatSessionInfo, formatHistoryMessage } from '../../helpers/formatters.js';
23
23
  /**
24
24
  * Helper to get current session info
25
25
  */
@@ -43,7 +43,7 @@ async function displaySessionHistory(sessionId, agent) {
43
43
  console.log(formatHistoryMessage(message, index));
44
44
  });
45
45
  console.log(chalk.dim(`\n Total: ${history.length} messages`));
46
- console.log(chalk.dim(' 💡 Use /clear to reset session or /session switch to change sessions\n'));
46
+ console.log(chalk.dim(' 💡 Use /clear to reset session or dexto -r <id> to resume a different session\n'));
47
47
  }
48
48
  /**
49
49
  * Session management commands
@@ -65,7 +65,7 @@ export const sessionCommand = {
65
65
  const sessionIds = await agent.listSessions();
66
66
  const current = await getCurrentSessionInfo(agent);
67
67
  if (sessionIds.length === 0) {
68
- console.log(chalk.dim(' No sessions found. Use /session new to create one.\n'));
68
+ console.log(chalk.dim(' No sessions found. Run `dexto` to start a new session, or use `dexto -c`/`dexto -r <id>`.\n'));
69
69
  return true;
70
70
  }
71
71
  // Fetch metadata concurrently; errors do not abort listing
@@ -75,7 +75,7 @@ export const sessionCommand = {
75
75
  return { id, metadata };
76
76
  }
77
77
  catch (e) {
78
- logger.error(`Failed to fetch metadata for session ${id}: ${e instanceof Error ? e.message : String(e)}`);
78
+ logger.error(`Failed to fetch metadata for session ${id}: ${e instanceof Error ? e.message : String(e)}`, null, 'red');
79
79
  return { id, metadata: undefined };
80
80
  }
81
81
  }));
@@ -88,7 +88,7 @@ export const sessionCommand = {
88
88
  displayed++;
89
89
  }
90
90
  console.log(chalk.dim(`\n Total: ${displayed} of ${sessionIds.length} sessions`));
91
- console.log(chalk.dim(' 💡 Use /session switch <id> to change sessions\n'));
91
+ console.log(chalk.dim(' 💡 Use `dexto -r <id>` to resume a session\n'));
92
92
  }
93
93
  catch (error) {
94
94
  logger.error(`Failed to list sessions: ${error instanceof Error ? error.message : String(error)}`);
@@ -96,69 +96,6 @@ export const sessionCommand = {
96
96
  return true;
97
97
  },
98
98
  },
99
- {
100
- name: 'new',
101
- description: 'Create a new session',
102
- usage: '/session new [id]',
103
- handler: async (args, agent) => {
104
- try {
105
- const sessionId = args[0]; // Optional custom ID
106
- const session = await agent.createSession(sessionId);
107
- console.log(chalk.green(`✅ Created new session: ${chalk.bold(session.id)}`));
108
- // Switch to the new session
109
- await agent.loadSessionAsDefault(session.id);
110
- console.log(chalk.yellow(`🔄 Switched to new session`));
111
- }
112
- catch (error) {
113
- logger.error(`Failed to create session: ${error instanceof Error ? error.message : String(error)}`);
114
- }
115
- return true;
116
- },
117
- },
118
- {
119
- name: 'switch',
120
- description: 'Switch to a different session',
121
- usage: '/session switch <id>',
122
- handler: async (args, agent) => {
123
- if (args.length === 0) {
124
- console.log(chalk.red('❌ Session ID required. Usage: /session switch <id>'));
125
- return true;
126
- }
127
- try {
128
- const sessionId = args[0]; // Safe to assert non-null since we checked args.length
129
- await agent.loadSessionAsDefault(sessionId);
130
- const metadata = await agent.getSessionMetadata(sessionId);
131
- console.log(chalk.green(`✅ Switched to session: ${chalk.bold(sessionId)}`));
132
- if (metadata && metadata.messageCount > 0) {
133
- console.log(chalk.dim(` ${metadata.messageCount} messages in history`));
134
- }
135
- else {
136
- console.log(chalk.dim(' New session - no previous messages'));
137
- }
138
- }
139
- catch (error) {
140
- logger.error(`Failed to switch session: ${error instanceof Error ? error.message : String(error)}`);
141
- }
142
- return true;
143
- },
144
- },
145
- {
146
- name: 'current',
147
- description: 'Show current session',
148
- usage: '/session current',
149
- handler: async (args, agent) => {
150
- try {
151
- const current = await getCurrentSessionInfo(agent);
152
- console.log(chalk.blue('\n📍 Current Session:\n'));
153
- console.log(' ' + formatSessionInfo(current.id, current.metadata, true));
154
- console.log();
155
- }
156
- catch (error) {
157
- logger.error(`Failed to get current session: ${error instanceof Error ? error.message : String(error)}`);
158
- }
159
- return true;
160
- },
161
- },
162
99
  {
163
100
  name: 'history',
164
101
  description: 'Show session history for current session',
@@ -176,7 +113,7 @@ export const sessionCommand = {
176
113
  console.log(chalk.dim(' Use /session list to see available sessions'));
177
114
  }
178
115
  else {
179
- logger.error(`Failed to get session history: ${error instanceof Error ? error.message : String(error)}`);
116
+ logger.error(`Failed to get session history: ${error instanceof Error ? error.message : String(error)}`, null, 'red');
180
117
  }
181
118
  }
182
119
  return true;
@@ -204,7 +141,7 @@ export const sessionCommand = {
204
141
  console.log(chalk.green(`✅ Deleted session: ${chalk.bold(sessionId)}`));
205
142
  }
206
143
  catch (error) {
207
- logger.error(`Failed to delete session: ${error instanceof Error ? error.message : String(error)}`);
144
+ logger.error(`Failed to delete session: ${error instanceof Error ? error.message : String(error)}`, null, 'red');
208
145
  }
209
146
  return true;
210
147
  },
@@ -217,15 +154,12 @@ export const sessionCommand = {
217
154
  console.log(chalk.bold.blue('\n📋 Session Management Commands:\n'));
218
155
  console.log(chalk.cyan('Available subcommands:'));
219
156
  console.log(` ${chalk.yellow('/session list')} - List all sessions with their status and activity`);
220
- console.log(` ${chalk.yellow('/session new')} ${chalk.blue('[name]')} - Create a new session (optional custom name)`);
221
- console.log(` ${chalk.yellow('/session switch')} ${chalk.blue('<id>')} - Switch to a different session`);
222
- console.log(` ${chalk.yellow('/session current')} - Show current session info and message count`);
223
157
  console.log(` ${chalk.yellow('/session history')} - Display session history for current session`);
224
158
  console.log(` ${chalk.yellow('/session delete')} ${chalk.blue('<id>')} - Delete a session (cannot delete active session)`);
225
159
  console.log(` ${chalk.yellow('/session help')} - Show this help message`);
226
160
  console.log(chalk.dim('\n💡 Sessions allow you to maintain separate chat sessions'));
227
- console.log(chalk.dim('💡 Use /session switch <id> to change sessions'));
228
- console.log(chalk.dim('💡 Session names can be custom or auto-generated UUIDs\n'));
161
+ console.log(chalk.dim('💡 Use `dexto -r <id>` to resume a different session'));
162
+ console.log(chalk.dim('💡 Use `dexto` to start a new session or `dexto -c` to continue most recent\n'));
229
163
  return true;
230
164
  },
231
165
  },
@@ -247,7 +181,7 @@ export const sessionCommand = {
247
181
  return subcmd.handler(subArgs, agent);
248
182
  }
249
183
  console.log(chalk.red(`❌ Unknown session subcommand: ${subcommand}`));
250
- console.log(chalk.dim('Available subcommands: list, new, switch, current, history, delete, help'));
184
+ console.log(chalk.dim('Available subcommands: list, history, delete, help'));
251
185
  console.log(chalk.dim('💡 Use /session help for detailed command descriptions'));
252
186
  return true;
253
187
  },
@@ -4,13 +4,13 @@ declare const ListAgentsCommandSchema: z.ZodObject<{
4
4
  installed: z.ZodDefault<z.ZodBoolean>;
5
5
  available: z.ZodDefault<z.ZodBoolean>;
6
6
  }, "strict", z.ZodTypeAny, {
7
+ installed: boolean;
7
8
  verbose: boolean;
8
9
  available: boolean;
9
- installed: boolean;
10
10
  }, {
11
+ installed?: boolean | undefined;
11
12
  verbose?: boolean | undefined;
12
13
  available?: boolean | undefined;
13
- installed?: boolean | undefined;
14
14
  }>;
15
15
  export type ListAgentsCommandOptions = z.output<typeof ListAgentsCommandSchema>;
16
16
  export type ListAgentsCommandOptionsInput = z.input<typeof ListAgentsCommandSchema>;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Non-Interactive Session Management Commands
3
+ *
4
+ * This module provides CLI commands for managing sessions outside of interactive mode.
5
+ * These commands allow users to manage sessions via direct CLI invocation.
6
+ */
7
+ import { DextoAgent } from '@dexto/core';
8
+ /**
9
+ * List all available sessions
10
+ */
11
+ export declare function handleSessionListCommand(agent: DextoAgent): Promise<void>;
12
+ /**
13
+ * Show session history
14
+ */
15
+ export declare function handleSessionHistoryCommand(agent: DextoAgent, sessionId?: string): Promise<void>;
16
+ /**
17
+ * Delete a session
18
+ */
19
+ export declare function handleSessionDeleteCommand(agent: DextoAgent, sessionId: string): Promise<void>;
20
+ /**
21
+ * Search session history
22
+ */
23
+ export declare function handleSessionSearchCommand(agent: DextoAgent, query: string, options?: {
24
+ sessionId?: string;
25
+ role?: 'user' | 'assistant' | 'system' | 'tool';
26
+ limit?: number;
27
+ }): Promise<void>;
28
+ //# sourceMappingURL=session-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/session-commands.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAU,UAAU,EAAwB,MAAM,aAAa,CAAC;AA0CvE;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmD/E;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC7C,KAAK,EAAE,UAAU,EACjB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC5C,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC5C,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACL,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CACb,GACP,OAAO,CAAC,IAAI,CAAC,CAyFf"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Non-Interactive Session Management Commands
3
+ *
4
+ * This module provides CLI commands for managing sessions outside of interactive mode.
5
+ * These commands allow users to manage sessions via direct CLI invocation.
6
+ */
7
+ import chalk from 'chalk';
8
+ import { logger } from '@dexto/core';
9
+ import { formatSessionInfo, formatHistoryMessage } from './helpers/formatters.js';
10
+ /**
11
+ * Escape special regex characters in a string to prevent ReDoS attacks
12
+ */
13
+ function escapeRegExp(string) {
14
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
15
+ }
16
+ /**
17
+ * Helper to get current session info
18
+ */
19
+ async function getCurrentSessionInfo(agent) {
20
+ const currentId = agent.getCurrentSessionId();
21
+ const metadata = await agent.getSessionMetadata(currentId);
22
+ return { id: currentId, metadata };
23
+ }
24
+ /**
25
+ * Helper to display session history with consistent formatting
26
+ */
27
+ async function displaySessionHistory(sessionId, agent) {
28
+ console.log(chalk.blue(`\n💬 Session History for: ${chalk.bold(sessionId)}\n`));
29
+ const history = await agent.getSessionHistory(sessionId);
30
+ if (history.length === 0) {
31
+ console.log(chalk.dim(' No messages in this session yet.\n'));
32
+ return;
33
+ }
34
+ // Display each message with formatting
35
+ history.forEach((message, index) => {
36
+ console.log(formatHistoryMessage(message, index));
37
+ });
38
+ console.log(chalk.dim(`\n Total: ${history.length} messages`));
39
+ }
40
+ /**
41
+ * List all available sessions
42
+ */
43
+ export async function handleSessionListCommand(agent) {
44
+ try {
45
+ console.log(chalk.bold.blue('\n📋 Sessions:\n'));
46
+ const sessionIds = await agent.listSessions();
47
+ const current = await getCurrentSessionInfo(agent);
48
+ if (sessionIds.length === 0) {
49
+ console.log(chalk.dim(' No sessions found. Run `dexto` to start a new session, or use `dexto -c`/`dexto -r <id>`.\n'));
50
+ return;
51
+ }
52
+ // Fetch metadata concurrently; errors do not abort listing
53
+ const entries = await Promise.all(sessionIds.map(async (id) => {
54
+ try {
55
+ const metadata = await agent.getSessionMetadata(id);
56
+ return { id, metadata };
57
+ }
58
+ catch (e) {
59
+ logger.error(`Failed to fetch metadata for session ${id}: ${e instanceof Error ? e.message : String(e)}`, null, 'red');
60
+ return { id, metadata: undefined };
61
+ }
62
+ }));
63
+ let displayed = 0;
64
+ for (const { id, metadata } of entries) {
65
+ if (!metadata)
66
+ continue;
67
+ const isCurrent = id === current.id;
68
+ console.log(` ${formatSessionInfo(id, metadata, isCurrent)}`);
69
+ displayed++;
70
+ }
71
+ console.log(chalk.dim(`\n Total: ${displayed} of ${sessionIds.length} sessions`));
72
+ console.log(chalk.dim(' 💡 Use `dexto -r <id>` to resume a session\n'));
73
+ }
74
+ catch (error) {
75
+ logger.error(`Failed to list sessions: ${error instanceof Error ? error.message : String(error)}`, null, 'red');
76
+ throw error;
77
+ }
78
+ }
79
+ /**
80
+ * Show session history
81
+ */
82
+ export async function handleSessionHistoryCommand(agent, sessionId) {
83
+ try {
84
+ // Use provided session ID or current session
85
+ const targetSessionId = sessionId || agent.getCurrentSessionId();
86
+ await displaySessionHistory(targetSessionId, agent);
87
+ }
88
+ catch (error) {
89
+ if (error instanceof Error && error.message.includes('not found')) {
90
+ console.log(chalk.red(`❌ Session not found: ${sessionId || 'current'}`));
91
+ console.log(chalk.dim(' Use `dexto session list` to see available sessions'));
92
+ }
93
+ else {
94
+ logger.error(`Failed to get session history: ${error instanceof Error ? error.message : String(error)}`, null, 'red');
95
+ }
96
+ throw error;
97
+ }
98
+ }
99
+ /**
100
+ * Delete a session
101
+ */
102
+ export async function handleSessionDeleteCommand(agent, sessionId) {
103
+ try {
104
+ const current = await getCurrentSessionInfo(agent);
105
+ // Check if trying to delete current session
106
+ if (sessionId === current.id) {
107
+ console.log(chalk.yellow('⚠️ Cannot delete the currently active session.'));
108
+ console.log(chalk.dim(' Switch to another session first, then delete this one.'));
109
+ return;
110
+ }
111
+ await agent.deleteSession(sessionId);
112
+ console.log(chalk.green(`✅ Deleted session: ${chalk.bold(sessionId)}`));
113
+ }
114
+ catch (error) {
115
+ logger.error(`Failed to delete session: ${error instanceof Error ? error.message : String(error)}`, null, 'red');
116
+ throw error;
117
+ }
118
+ }
119
+ /**
120
+ * Search session history
121
+ */
122
+ export async function handleSessionSearchCommand(agent, query, options = {}) {
123
+ try {
124
+ const searchOptions = {
125
+ limit: options.limit || 10,
126
+ };
127
+ if (options.sessionId) {
128
+ searchOptions.sessionId = options.sessionId;
129
+ }
130
+ if (options.role) {
131
+ const allowed = new Set(['user', 'assistant', 'system', 'tool']);
132
+ if (!allowed.has(options.role)) {
133
+ console.log(chalk.red(`❌ Invalid role: ${options.role}. Use one of: user, assistant, system, tool`));
134
+ return;
135
+ }
136
+ searchOptions.role = options.role;
137
+ }
138
+ console.log(chalk.blue(`🔍 Searching for: "${query}"`));
139
+ if (searchOptions.sessionId) {
140
+ console.log(chalk.dim(` Session: ${searchOptions.sessionId}`));
141
+ }
142
+ if (searchOptions.role) {
143
+ console.log(chalk.dim(` Role: ${searchOptions.role}`));
144
+ }
145
+ console.log(chalk.dim(` Limit: ${searchOptions.limit}`));
146
+ console.log();
147
+ const results = await agent.searchMessages(query, searchOptions);
148
+ if (results.results.length === 0) {
149
+ console.log(chalk.yellow('📭 No messages found matching your search'));
150
+ return;
151
+ }
152
+ console.log(chalk.green(`✅ Found ${results.total} result${results.total === 1 ? '' : 's'}`));
153
+ if (results.hasMore) {
154
+ console.log(chalk.dim(` Showing first ${results.results.length} results`));
155
+ }
156
+ console.log();
157
+ // Precompile safe regex for highlighting (only if query is not empty)
158
+ const highlightRegex = query.trim()
159
+ ? new RegExp(`(${escapeRegExp(query.trim().slice(0, 256))})`, 'gi')
160
+ : null;
161
+ // Display results
162
+ results.results.forEach((result, index) => {
163
+ const roleColor = result.message.role === 'user'
164
+ ? chalk.blue
165
+ : result.message.role === 'assistant'
166
+ ? chalk.green
167
+ : chalk.yellow;
168
+ console.log(`${chalk.dim(`${index + 1}.`)} ${chalk.cyan(result.sessionId)} ${roleColor(`[${result.message.role}]`)}`);
169
+ // Safe highlighting - only if we have a valid regex
170
+ const highlightedContext = highlightRegex
171
+ ? result.context.replace(highlightRegex, chalk.inverse('$1'))
172
+ : result.context;
173
+ console.log(` ${highlightedContext}`);
174
+ console.log();
175
+ });
176
+ if (results.hasMore) {
177
+ console.log(chalk.dim('💡 Use --limit to see more results'));
178
+ }
179
+ }
180
+ catch (error) {
181
+ logger.error(`Search failed: ${error instanceof Error ? error.message : String(error)}`, null, 'red');
182
+ throw error;
183
+ }
184
+ }
@@ -12,9 +12,9 @@ declare const SetupCommandSchema: z.ZodEffects<z.ZodObject<{
12
12
  model?: string | undefined;
13
13
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
14
14
  }, {
15
+ interactive?: boolean | undefined;
15
16
  model?: string | undefined;
16
17
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
17
- interactive?: boolean | undefined;
18
18
  defaultAgent?: string | undefined;
19
19
  force?: boolean | undefined;
20
20
  }>, {
@@ -24,9 +24,9 @@ declare const SetupCommandSchema: z.ZodEffects<z.ZodObject<{
24
24
  model?: string | undefined;
25
25
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
26
26
  }, {
27
+ interactive?: boolean | undefined;
27
28
  model?: string | undefined;
28
29
  provider?: "openai" | "openai-compatible" | "anthropic" | "google" | "groq" | "xai" | "cohere" | undefined;
29
- interactive?: boolean | undefined;
30
30
  defaultAgent?: string | undefined;
31
31
  force?: boolean | undefined;
32
32
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmClB,CAAC;AAEP,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAClE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAiBtE,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgF9F"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBxB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmClB,CAAC;AAEP,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAClE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAiBtE,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAyF9F"}
@@ -9,6 +9,7 @@ import { selectProvider } from '../utils/provider-setup.js';
9
9
  import { requiresSetup } from '../utils/setup-utils.js';
10
10
  import * as p from '@clack/prompts';
11
11
  import { logger } from '@dexto/core';
12
+ import { capture } from '../../analytics/index.js';
12
13
  // Zod schema for setup command validation
13
14
  const SetupCommandSchema = z
14
15
  .object({
@@ -103,10 +104,18 @@ export async function handleSetupCommand(options) {
103
104
  throw new Error(`Provider '${provider}' requires a specific model. Use --model option.`);
104
105
  }
105
106
  const apiKeyVar = getPrimaryApiKeyEnvVar(provider);
107
+ const hadApiKeyBefore = Boolean(resolveApiKeyForProvider(provider));
106
108
  const defaultAgent = validated.defaultAgent;
107
109
  // Create and save preferences
108
110
  const preferences = createInitialPreferences(provider, model, apiKeyVar, defaultAgent);
109
111
  await saveGlobalPreferences(preferences);
112
+ // Track provider/model selected during setup
113
+ capture('dexto_setup', {
114
+ provider,
115
+ model,
116
+ hadApiKeyBefore,
117
+ setupMode: validated.interactive ? 'interactive' : 'non-interactive',
118
+ });
110
119
  // Setup API key interactively (only if interactive mode enabled and key doesn't exist)
111
120
  if (validated.interactive) {
112
121
  const existingApiKey = resolveApiKeyForProvider(provider);
@@ -1 +1 @@
1
- {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/uninstall.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,sBAAsB;;;;;;;;;;;;EAMf,CAAC;AAEd,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAgC9E,wBAAsB,sBAAsB,CACxC,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,CAyEf"}
1
+ {"version":3,"file":"uninstall.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/uninstall.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,QAAA,MAAM,sBAAsB;;;;;;;;;;;;EAMf,CAAC;AAEd,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAgC9E,wBAAsB,sBAAsB,CACxC,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,CA+Gf"}
@@ -1,6 +1,7 @@
1
1
  // packages/cli/src/cli/commands/uninstall.ts
2
2
  import { z } from 'zod';
3
3
  import { getAgentRegistry } from '@dexto/core';
4
+ import { capture } from '../../analytics/index.js';
4
5
  // Zod schema for uninstall command validation
5
6
  const UninstallCommandSchema = z
6
7
  .object({
@@ -57,6 +58,8 @@ export async function handleUninstallCommand(agents, options) {
57
58
  let successCount = 0;
58
59
  let errorCount = 0;
59
60
  const errors = [];
61
+ const uninstalled = [];
62
+ const failed = [];
60
63
  // Uninstall each agent
61
64
  for (const agentName of agentsToUninstall) {
62
65
  try {
@@ -64,15 +67,53 @@ export async function handleUninstallCommand(agents, options) {
64
67
  await registry.uninstallAgent(agentName, validated.force);
65
68
  successCount++;
66
69
  console.log(`✅ ${agentName} uninstalled successfully`);
70
+ uninstalled.push(agentName);
71
+ // Per-agent analytics for successful uninstall
72
+ try {
73
+ capture('dexto_uninstall_agent', {
74
+ agent: agentName,
75
+ status: 'uninstalled',
76
+ force: validated.force,
77
+ });
78
+ }
79
+ catch {
80
+ // Analytics failures should not block CLI execution.
81
+ }
67
82
  }
68
83
  catch (error) {
69
84
  errorCount++;
70
85
  const errorMsg = `Failed to uninstall ${agentName}: ${error instanceof Error ? error.message : String(error)}`;
71
86
  errors.push(errorMsg);
87
+ failed.push(agentName);
72
88
  console.error(`❌ ${errorMsg}`);
89
+ // Per-agent analytics for failed uninstall
90
+ try {
91
+ capture('dexto_uninstall_agent', {
92
+ agent: agentName,
93
+ status: 'failed',
94
+ error_message: error instanceof Error ? error.message : String(error),
95
+ force: validated.force,
96
+ });
97
+ }
98
+ catch {
99
+ // Analytics failures should not block CLI execution.
100
+ }
73
101
  }
74
102
  }
75
- // For single agent operations, throw error if it failed
103
+ // Emit analytics for both single- and multi-agent cases
104
+ try {
105
+ capture('dexto_uninstall', {
106
+ requested: agentsToUninstall,
107
+ uninstalled,
108
+ failed,
109
+ successCount,
110
+ errorCount,
111
+ });
112
+ }
113
+ catch {
114
+ // Analytics failures should not block CLI execution.
115
+ }
116
+ // For single agent operations, throw error if it failed (after emitting analytics)
76
117
  if (agentsToUninstall.length === 1) {
77
118
  if (errorCount > 0) {
78
119
  throw new Error(errors[0]);
@@ -135,7 +135,7 @@ function showManualSetupInstructions(provider) {
135
135
  `${chalk.bold('1. Get an API key:')}`,
136
136
  ` • ${chalk.green('Google Gemini (Free)')}: https://aistudio.google.com/apikey`,
137
137
  ` • ${chalk.blue('OpenAI')}: https://platform.openai.com/api-keys`,
138
- ` • ${chalk.magenta('Anthropic')}: https://console.anthropic.com/keys`,
138
+ ` • ${chalk.magenta('Anthropic')}: https://console.anthropic.com/settings/keys`,
139
139
  ` • ${chalk.yellow('Groq (Free)')}: https://console.groq.com/keys`,
140
140
  ``,
141
141
  ...envInstructions,