dexto 1.5.8 → 1.6.1

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 (224) hide show
  1. package/README.md +3 -3
  2. package/dist/agents/agent-template.yml +2 -2
  3. package/dist/agents/coding-agent/README.md +10 -10
  4. package/dist/agents/coding-agent/coding-agent.yml +84 -83
  5. package/dist/agents/default-agent.yml +32 -47
  6. package/dist/agents/explore-agent/explore-agent.yml +3 -6
  7. package/dist/agents/image-editor-agent/image-editor-agent.yml +1 -1
  8. package/dist/agents/nano-banana-agent/nano-banana-agent.yml +1 -1
  9. package/dist/agents/podcast-agent/podcast-agent.yml +1 -1
  10. package/dist/agents/product-name-researcher/product-name-researcher.yml +1 -1
  11. package/dist/agents/sora-video-agent/sora-video-agent.yml +4 -6
  12. package/dist/agents/triage-demo/triage-agent.yml +1 -1
  13. package/dist/analytics/events.d.ts +1 -1
  14. package/dist/analytics/events.d.ts.map +1 -1
  15. package/dist/api/mcp/tool-aggregation-handler.d.ts +2 -2
  16. package/dist/api/server-hono.d.ts +2 -2
  17. package/dist/api/server-hono.d.ts.map +1 -1
  18. package/dist/api/server-hono.js +37 -60
  19. package/dist/cli/approval/cli-approval-handler.d.ts +10 -3
  20. package/dist/cli/approval/cli-approval-handler.d.ts.map +1 -1
  21. package/dist/cli/approval/cli-approval-handler.js +1 -1
  22. package/dist/cli/assets/sounds/SOURCES.md +35 -0
  23. package/dist/cli/assets/sounds/boot.wav +0 -0
  24. package/dist/cli/assets/sounds/chime.wav +0 -0
  25. package/dist/cli/assets/sounds/coin.wav +0 -0
  26. package/dist/cli/assets/sounds/confirm.wav +0 -0
  27. package/dist/cli/assets/sounds/levelup.wav +0 -0
  28. package/dist/cli/assets/sounds/ping.wav +0 -0
  29. package/dist/cli/assets/sounds/powerup.wav +0 -0
  30. package/dist/cli/assets/sounds/startup.wav +0 -0
  31. package/dist/cli/assets/sounds/success.wav +0 -0
  32. package/dist/cli/assets/sounds/treasure.wav +0 -0
  33. package/dist/cli/assets/sounds/win.wav +0 -0
  34. package/dist/cli/commands/create-app.d.ts +1 -11
  35. package/dist/cli/commands/create-app.d.ts.map +1 -1
  36. package/dist/cli/commands/create-app.js +21 -545
  37. package/dist/cli/commands/create-image.d.ts.map +1 -1
  38. package/dist/cli/commands/create-image.js +54 -53
  39. package/dist/cli/commands/image.d.ts +52 -0
  40. package/dist/cli/commands/image.d.ts.map +1 -0
  41. package/dist/cli/commands/image.js +118 -0
  42. package/dist/cli/commands/index.d.ts +2 -1
  43. package/dist/cli/commands/index.d.ts.map +1 -1
  44. package/dist/cli/commands/index.js +3 -1
  45. package/dist/cli/commands/init-app.d.ts +4 -8
  46. package/dist/cli/commands/init-app.d.ts.map +1 -1
  47. package/dist/cli/commands/init-app.js +37 -161
  48. package/dist/cli/commands/interactive-commands/command-parser.d.ts +2 -0
  49. package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
  50. package/dist/cli/commands/interactive-commands/commands.d.ts +1 -1
  51. package/dist/cli/commands/interactive-commands/commands.d.ts.map +1 -1
  52. package/dist/cli/commands/interactive-commands/commands.js +2 -2
  53. package/dist/cli/commands/interactive-commands/exit-handler.d.ts +12 -0
  54. package/dist/cli/commands/interactive-commands/exit-handler.d.ts.map +1 -0
  55. package/dist/cli/commands/interactive-commands/exit-handler.js +20 -0
  56. package/dist/cli/commands/interactive-commands/exit-stats.d.ts +24 -0
  57. package/dist/cli/commands/interactive-commands/exit-stats.d.ts.map +1 -0
  58. package/dist/cli/commands/interactive-commands/exit-stats.js +17 -0
  59. package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
  60. package/dist/cli/commands/interactive-commands/general-commands.js +55 -5
  61. package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
  62. package/dist/cli/commands/interactive-commands/prompt-commands.js +14 -74
  63. package/dist/cli/commands/interactive-commands/session/index.d.ts +2 -1
  64. package/dist/cli/commands/interactive-commands/session/index.d.ts.map +1 -1
  65. package/dist/cli/commands/interactive-commands/session/index.js +2 -1
  66. package/dist/cli/commands/interactive-commands/session/session-commands.d.ts +2 -2
  67. package/dist/cli/commands/interactive-commands/session/session-commands.d.ts.map +1 -1
  68. package/dist/cli/commands/interactive-commands/session/session-commands.js +2 -4
  69. package/dist/cli/commands/interactive-commands/system/system-commands.d.ts +1 -13
  70. package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
  71. package/dist/cli/commands/interactive-commands/system/system-commands.js +52 -83
  72. package/dist/cli/commands/plugin.d.ts +4 -4
  73. package/dist/cli/commands/sync-agents.d.ts +2 -12
  74. package/dist/cli/commands/sync-agents.d.ts.map +1 -1
  75. package/dist/cli/commands/sync-agents.js +2 -50
  76. package/dist/cli/ink-cli/InkCLIRefactored.d.ts +7 -1
  77. package/dist/cli/ink-cli/InkCLIRefactored.d.ts.map +1 -1
  78. package/dist/cli/ink-cli/InkCLIRefactored.js +138 -27
  79. package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts +2 -2
  80. package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts.map +1 -1
  81. package/dist/cli/ink-cli/components/ApprovalPrompt.js +85 -30
  82. package/dist/cli/ink-cli/components/BackgroundTasksPanel.js +1 -1
  83. package/dist/cli/ink-cli/components/ElicitationForm.d.ts +5 -3
  84. package/dist/cli/ink-cli/components/ElicitationForm.d.ts.map +1 -1
  85. package/dist/cli/ink-cli/components/ElicitationForm.js +414 -180
  86. package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -1
  87. package/dist/cli/ink-cli/components/Footer.js +1 -2
  88. package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
  89. package/dist/cli/ink-cli/components/ResourceAutocomplete.js +20 -11
  90. package/dist/cli/ink-cli/components/SlashCommandAutocomplete.d.ts.map +1 -1
  91. package/dist/cli/ink-cli/components/SlashCommandAutocomplete.js +47 -67
  92. package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
  93. package/dist/cli/ink-cli/components/StatusBar.js +20 -10
  94. package/dist/cli/ink-cli/components/TodoPanel.js +1 -1
  95. package/dist/cli/ink-cli/components/base/BaseSelector.d.ts +2 -1
  96. package/dist/cli/ink-cli/components/base/BaseSelector.d.ts.map +1 -1
  97. package/dist/cli/ink-cli/components/base/BaseSelector.js +37 -27
  98. package/dist/cli/ink-cli/components/chat/Header.d.ts.map +1 -1
  99. package/dist/cli/ink-cli/components/chat/Header.js +1 -1
  100. package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
  101. package/dist/cli/ink-cli/components/chat/MessageItem.js +3 -1
  102. package/dist/cli/ink-cli/components/chat/ToolIcon.d.ts.map +1 -1
  103. package/dist/cli/ink-cli/components/chat/ToolIcon.js +5 -15
  104. package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.js +1 -1
  105. package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -1
  106. package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +1 -1
  107. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts +3 -1
  108. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -1
  109. package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +5 -3
  110. package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts +3 -1
  111. package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
  112. package/dist/cli/ink-cli/components/modes/StaticCLI.js +10 -3
  113. package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts +13 -0
  114. package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts.map +1 -0
  115. package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.js +60 -0
  116. package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +1 -1
  117. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
  118. package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +213 -100
  119. package/dist/cli/ink-cli/components/overlays/PromptList.d.ts.map +1 -1
  120. package/dist/cli/ink-cli/components/overlays/PromptList.js +12 -16
  121. package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts +21 -0
  122. package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts.map +1 -0
  123. package/dist/cli/ink-cli/components/overlays/SoundsSelector.js +566 -0
  124. package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts +1 -1
  125. package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts.map +1 -1
  126. package/dist/cli/ink-cli/components/overlays/ToolBrowser.js +100 -45
  127. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts.map +1 -1
  128. package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.js +8 -13
  129. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts +3 -3
  130. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts.map +1 -1
  131. package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.js +6 -5
  132. package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts +3 -1
  133. package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts.map +1 -1
  134. package/dist/cli/ink-cli/components/renderers/FileRenderer.js +18 -7
  135. package/dist/cli/ink-cli/components/renderers/ShellRenderer.d.ts.map +1 -1
  136. package/dist/cli/ink-cli/components/renderers/ShellRenderer.js +7 -17
  137. package/dist/cli/ink-cli/components/renderers/index.d.ts.map +1 -1
  138. package/dist/cli/ink-cli/components/renderers/index.js +1 -1
  139. package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts +7 -0
  140. package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts.map +1 -0
  141. package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.js +8 -0
  142. package/dist/cli/ink-cli/components/shared/HintBar.d.ts +6 -0
  143. package/dist/cli/ink-cli/components/shared/HintBar.d.ts.map +1 -0
  144. package/dist/cli/ink-cli/components/shared/HintBar.js +6 -0
  145. package/dist/cli/ink-cli/constants/spinnerFrames.d.ts +2 -0
  146. package/dist/cli/ink-cli/constants/spinnerFrames.d.ts.map +1 -0
  147. package/dist/cli/ink-cli/constants/spinnerFrames.js +1 -0
  148. package/dist/cli/ink-cli/constants/tips.d.ts.map +1 -1
  149. package/dist/cli/ink-cli/constants/tips.js +2 -1
  150. package/dist/cli/ink-cli/containers/InputContainer.d.ts +4 -0
  151. package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
  152. package/dist/cli/ink-cli/containers/InputContainer.js +47 -21
  153. package/dist/cli/ink-cli/containers/OverlayContainer.d.ts +2 -0
  154. package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
  155. package/dist/cli/ink-cli/containers/OverlayContainer.js +101 -40
  156. package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
  157. package/dist/cli/ink-cli/hooks/useAgentEvents.js +15 -16
  158. package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts +11 -0
  159. package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts.map +1 -0
  160. package/dist/cli/ink-cli/hooks/useAnimationTick.js +54 -0
  161. package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
  162. package/dist/cli/ink-cli/hooks/useCLIState.js +1 -0
  163. package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts.map +1 -1
  164. package/dist/cli/ink-cli/hooks/useTokenCounter.js +7 -4
  165. package/dist/cli/ink-cli/services/CommandService.d.ts +1 -1
  166. package/dist/cli/ink-cli/services/CommandService.d.ts.map +1 -1
  167. package/dist/cli/ink-cli/services/CommandService.js +2 -2
  168. package/dist/cli/ink-cli/services/processStream.d.ts +2 -2
  169. package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
  170. package/dist/cli/ink-cli/services/processStream.js +27 -19
  171. package/dist/cli/ink-cli/state/initialState.d.ts.map +1 -1
  172. package/dist/cli/ink-cli/state/initialState.js +1 -0
  173. package/dist/cli/ink-cli/state/types.d.ts +15 -3
  174. package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
  175. package/dist/cli/ink-cli/utils/commandOverlays.d.ts.map +1 -1
  176. package/dist/cli/ink-cli/utils/commandOverlays.js +1 -0
  177. package/dist/cli/ink-cli/utils/elicitationSchema.d.ts +11 -0
  178. package/dist/cli/ink-cli/utils/elicitationSchema.d.ts.map +1 -0
  179. package/dist/cli/ink-cli/utils/elicitationSchema.js +80 -0
  180. package/dist/cli/ink-cli/utils/index.d.ts +1 -1
  181. package/dist/cli/ink-cli/utils/index.d.ts.map +1 -1
  182. package/dist/cli/ink-cli/utils/index.js +1 -1
  183. package/dist/cli/ink-cli/utils/messageFormatting.d.ts +10 -19
  184. package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
  185. package/dist/cli/ink-cli/utils/messageFormatting.js +43 -262
  186. package/dist/cli/ink-cli/utils/overlayPresentation.d.ts +19 -0
  187. package/dist/cli/ink-cli/utils/overlayPresentation.d.ts.map +1 -0
  188. package/dist/cli/ink-cli/utils/overlayPresentation.js +33 -0
  189. package/dist/cli/ink-cli/utils/overlaySizing.d.ts +19 -0
  190. package/dist/cli/ink-cli/utils/overlaySizing.d.ts.map +1 -0
  191. package/dist/cli/ink-cli/utils/overlaySizing.js +11 -0
  192. package/dist/cli/ink-cli/utils/soundNotification.d.ts +19 -13
  193. package/dist/cli/ink-cli/utils/soundNotification.d.ts.map +1 -1
  194. package/dist/cli/ink-cli/utils/soundNotification.js +120 -97
  195. package/dist/cli/ink-cli/utils/toolUtils.d.ts.map +1 -1
  196. package/dist/cli/ink-cli/utils/toolUtils.js +2 -9
  197. package/dist/cli/utils/config-validation.d.ts +11 -11
  198. package/dist/cli/utils/config-validation.d.ts.map +1 -1
  199. package/dist/cli/utils/config-validation.js +56 -290
  200. package/dist/cli/utils/image-store.d.ts +16 -0
  201. package/dist/cli/utils/image-store.d.ts.map +1 -0
  202. package/dist/cli/utils/image-store.js +289 -0
  203. package/dist/cli/utils/scaffolding-utils.d.ts +5 -0
  204. package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
  205. package/dist/cli/utils/scaffolding-utils.js +46 -4
  206. package/dist/cli/utils/template-engine.d.ts +28 -16
  207. package/dist/cli/utils/template-engine.d.ts.map +1 -1
  208. package/dist/cli/utils/template-engine.js +339 -479
  209. package/dist/config/cli-overrides.d.ts +4 -3
  210. package/dist/config/cli-overrides.d.ts.map +1 -1
  211. package/dist/config/cli-overrides.js +7 -9
  212. package/dist/index-main.d.ts +2 -0
  213. package/dist/index-main.d.ts.map +1 -0
  214. package/dist/index-main.js +1554 -0
  215. package/dist/index.js +2 -1589
  216. package/dist/utils/session-logger-factory.d.ts +3 -0
  217. package/dist/utils/session-logger-factory.d.ts.map +1 -0
  218. package/dist/utils/session-logger-factory.js +34 -0
  219. package/dist/webui/assets/{index-Cz2z7NQ8.js → index-CKhumsZA.js} +231 -231
  220. package/dist/webui/index.html +1 -1
  221. package/package.json +11 -8
  222. package/dist/cli/cli-subscriber.d.ts +0 -45
  223. package/dist/cli/cli-subscriber.d.ts.map +0 -1
  224. package/dist/cli/cli-subscriber.js +0 -204
@@ -5,12 +5,15 @@ import fsExtra from 'fs-extra';
5
5
  import path from 'node:path';
6
6
  import { getPackageManager, getPackageManagerInstallCommand } from '../utils/package-mgmt.js';
7
7
  import { executeWithTimeout } from '../utils/execute.js';
8
- import { createRequire } from 'module';
9
- import { logger } from '@dexto/core';
10
- import { updateDextoConfigFile } from '../utils/project-utils.js';
8
+ import { getDefaultModelForProvider } from '@dexto/core';
11
9
  import { saveProviderApiKey } from '@dexto/agent-management';
12
10
  import { getProviderDisplayName, isValidApiKeyFormat, PROVIDER_OPTIONS, } from '../utils/provider-setup.js';
13
- const require = createRequire(import.meta.url);
11
+ import { generateIndexForCodeFirstDI } from '../utils/template-engine.js';
12
+ function debug(message) {
13
+ if (process.env.DEXTO_DEBUG_INIT === 'true' || process.env.DEXTO_DEBUG_ALL === 'true') {
14
+ console.error(`[dexto:init] ${message}`);
15
+ }
16
+ }
14
17
  /**
15
18
  * Get user preferences needed to initialize a Dexto app
16
19
  * @returns The user preferences
@@ -90,11 +93,17 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
90
93
  const installCommand = getPackageManagerInstallCommand(packageManager);
91
94
  spinner.start('Installing Dexto...');
92
95
  const label = 'latest';
93
- logger.debug(`Installing Dexto using ${packageManager} with install command: ${installCommand} and label: ${label}`);
96
+ debug(`Installing Dexto using ${packageManager} with install command: ${installCommand} and label: ${label}`);
94
97
  try {
95
- await executeWithTimeout(packageManager, [installCommand, `@dexto/core@${label}`], {
96
- cwd: process.cwd(),
97
- });
98
+ await executeWithTimeout(packageManager, [
99
+ installCommand,
100
+ `@dexto/core@${label}`,
101
+ `@dexto/storage@${label}`,
102
+ // Intentionally omit tool packs to keep the example minimal.
103
+ // TODO: Revisit adding a default tool pack once tool IDs no longer require manual qualification.
104
+ 'dotenv',
105
+ 'tsx',
106
+ ], { cwd: process.cwd() });
98
107
  }
99
108
  catch (installError) {
100
109
  // Handle pnpm workspace root add error specifically
@@ -110,7 +119,7 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
110
119
  }
111
120
  spinner.stop('Dexto installed successfully!');
112
121
  spinner.start('Creating Dexto files...');
113
- // create dexto directories (dexto, dexto/agents)
122
+ // create dexto directories (dexto)
114
123
  const result = await createDextoDirectories(directory);
115
124
  if (!result.ok) {
116
125
  spinner.stop(chalk.inverse(`Dexto already initialized in ${path.join(directory, 'dexto')}. Would you like to overwrite it?`));
@@ -124,34 +133,16 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
124
133
  }
125
134
  }
126
135
  // create dexto config file
127
- logger.debug('Creating dexto config file...');
128
136
  const dextoDir = path.join(directory, 'dexto');
129
- const agentsDir = path.join(dextoDir, 'agents');
130
- let configPath;
131
- try {
132
- configPath = await createDextoConfigFile(agentsDir);
133
- logger.debug(`Dexto config file created at ${configPath}`);
134
- }
135
- catch (configError) {
136
- spinner.stop(chalk.red('Failed to create agent config file'));
137
- logger.error(`Config creation error: ${configError}`);
138
- throw new Error(`Failed to create coding-agent.yml: ${configError instanceof Error ? configError.message : String(configError)}`);
139
- }
140
- // update dexto config file based on llmProvider
141
- if (llmProvider) {
142
- logger.debug(`Updating dexto config file based on llmProvider: ${llmProvider}`);
143
- await updateDextoConfigFile(configPath, llmProvider);
144
- logger.debug(`Dexto config file updated with llmProvider: ${llmProvider}`);
145
- }
146
137
  // create dexto example file if requested
147
138
  if (createExampleFile) {
148
- logger.debug('Creating dexto example file...');
149
- await createDextoExampleFile(dextoDir);
150
- logger.debug('Dexto example file created successfully!');
139
+ debug('Creating dexto example file...');
140
+ await createDextoExampleFile(dextoDir, { llmProvider });
141
+ debug('Dexto example file created successfully!');
151
142
  }
152
143
  // add/update .env file (only if user provided a key)
153
144
  spinner.start('Saving API key to .env file...');
154
- logger.debug(`Saving API key: provider=${llmProvider ?? 'none'}, hasApiKey=${Boolean(llmApiKey)}`);
145
+ debug(`Saving API key: provider=${llmProvider ?? 'none'}, hasApiKey=${Boolean(llmApiKey)}`);
155
146
  if (llmProvider && llmApiKey) {
156
147
  await saveProviderApiKey(llmProvider, llmApiKey, process.cwd());
157
148
  }
@@ -159,29 +150,27 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
159
150
  }
160
151
  catch (err) {
161
152
  spinner.stop(chalk.inverse(`An error occurred initializing Dexto project - ${err}`));
162
- logger.debug(`Error: ${err}`);
153
+ debug(`Error: ${String(err)}`);
163
154
  process.exit(1);
164
155
  }
165
156
  }
166
157
  /** Adds notes for users to get started with their new initialized Dexto project */
167
158
  export async function postInitDexto(directory) {
168
159
  const nextSteps = [
169
- `1. Run the example: ${chalk.cyan(`node --loader ts-node/esm ${path.join(directory, 'dexto', 'dexto-example.ts')}`)}`,
160
+ `1. Run the example: ${chalk.cyan(`npx tsx ${path.join(directory, 'dexto', 'dexto-example.ts')}`)}`,
170
161
  `2. Add/update your API key(s) in ${chalk.cyan('.env')}`,
171
- `3. Check out the agent configuration file ${chalk.cyan(path.join(directory, 'dexto', 'agents', 'coding-agent.yml'))}`,
172
- `4. Try out different LLMs and MCP servers in the coding-agent.yml file`,
173
- `5. Read more about Dexto: ${chalk.cyan('https://github.com/truffle-ai/dexto')}`,
162
+ `3. Customize the agent in ${chalk.cyan(path.join(directory, 'dexto', 'dexto-example.ts'))}`,
163
+ `4. Read more about Dexto: ${chalk.cyan('https://github.com/truffle-ai/dexto')}`,
174
164
  ].join('\n');
175
165
  p.note(nextSteps, chalk.rgb(255, 165, 0)('Next steps:'));
176
166
  }
177
167
  /**
178
- * Creates the dexto directories (dexto, dexto/agents) in the given directory.
168
+ * Creates the dexto directory in the given directory.
179
169
  * @param directory - The directory to create the dexto directories in
180
170
  * @returns The path to the created dexto directory
181
171
  */
182
172
  export async function createDextoDirectories(directory) {
183
173
  const dirPath = path.join(directory, 'dexto');
184
- const agentsPath = path.join(directory, 'dexto', 'agents');
185
174
  try {
186
175
  await fs.access(dirPath);
187
176
  return { ok: false };
@@ -189,138 +178,25 @@ export async function createDextoDirectories(directory) {
189
178
  catch {
190
179
  // fsExtra.ensureDir creates directories recursively if they don't exist
191
180
  await fsExtra.ensureDir(dirPath);
192
- await fsExtra.ensureDir(agentsPath);
193
181
  return { ok: true, dirPath };
194
182
  }
195
183
  }
196
- /**
197
- * Creates a dexto config file in the given directory. Pulls the config file from the installed Dexto package.
198
- * @param directory - The directory to create the config file in
199
- * @returns The path to the created config file
200
- */
201
- export async function createDextoConfigFile(directory) {
202
- // Ensure the directory exists
203
- await fsExtra.ensureDir(directory);
204
- try {
205
- // Locate the Dexto package installation directory
206
- const pkgJsonPath = require.resolve('dexto/package.json');
207
- const pkgDir = path.dirname(pkgJsonPath);
208
- logger.debug(`Package directory: ${pkgDir}`);
209
- // Build path to the configuration template for create-app (with auto-approve toolConfirmation)
210
- const templateConfigSrc = path.join(pkgDir, 'dist', 'agents', 'agent-template.yml');
211
- logger.debug(`Looking for template at: ${templateConfigSrc}`);
212
- // Check if template exists - fail if not found
213
- const templateExists = await fsExtra.pathExists(templateConfigSrc);
214
- if (!templateExists) {
215
- throw new Error(`Template file not found at: ${templateConfigSrc}. This indicates a build issue - the template should be included in the package.`);
216
- }
217
- // Path to the destination config file
218
- const destConfigPath = path.join(directory, 'coding-agent.yml');
219
- logger.debug(`Copying template to: ${destConfigPath}`);
220
- // Copy the config file from the Dexto package
221
- await fsExtra.copy(templateConfigSrc, destConfigPath);
222
- logger.debug(`Successfully created config file at: ${destConfigPath}`);
223
- return destConfigPath;
224
- }
225
- catch (error) {
226
- logger.error(`Failed to create Dexto config file: ${error}`);
227
- throw error;
228
- }
229
- }
230
184
  /**
231
185
  * Creates an example file in the given directory showing how to use Dexto in code. This file has example code to get you started.
232
186
  * @param directory - The directory to create the example index file in
233
187
  * @returns The path to the created example index file
234
188
  */
235
- export async function createDextoExampleFile(directory) {
236
- // Extract the base directory from the given path (e.g., "src" from "src/dexto")
237
- const baseDir = path.dirname(directory);
238
- const configPath = `./${path.posix.join(baseDir, 'dexto/agents/coding-agent.yml')}`;
239
- const indexTsLines = [
240
- "import 'dotenv/config';",
241
- "import { DextoAgent, loadAgentConfig } from '@dexto/core';",
242
- '',
243
- "console.log('🚀 Starting Dexto Basic Example\\n');",
244
- '',
245
- 'try {',
246
- ' // Load the agent configuration',
247
- ` const config = await loadAgentConfig('${configPath}');`,
248
- '',
249
- ' // Create a new DextoAgent instance',
250
- ' const agent = new DextoAgent(config);',
251
- '',
252
- ' // Start the agent (connects to MCP servers)',
253
- " console.log('🔗 Connecting to MCP servers...');",
254
- ' await agent.start();',
255
- " console.log('✅ Agent started successfully!\\n');",
256
- '',
257
- ' // Create a session for this conversation',
258
- ' const session = await agent.createSession();',
259
- " console.log('📝 Session created:', session.id, '\\n');",
260
- '',
261
- ' // Example 1: Simple task',
262
- " console.log('📋 Example 1: Simple information request');",
263
- " const request1 = 'What tools do you have available?';",
264
- " console.log('Request:', request1);",
265
- ' const response1 = await agent.run(request1, undefined, undefined, session.id);',
266
- " console.log('Response:', response1);",
267
- " console.log('\\n——————\\n');",
268
- '',
269
- ' // Example 2: File operation',
270
- " console.log('📄 Example 2: File creation');",
271
- ' const request2 = \'Create a file called test-output.txt with the content "Hello from Dexto!"\';',
272
- " console.log('Request:', request2);",
273
- ' const response2 = await agent.run(request2, undefined, undefined, session.id);',
274
- " console.log('Response:', response2);",
275
- " console.log('\\n——————\\n');",
276
- '',
277
- ' // Example 3: Multi-step conversation',
278
- " console.log('🗣️ Example 3: Multi-step conversation');",
279
- ' const request3a = \'Create a simple HTML file called demo.html with a heading that says "Dexto Demo"\';',
280
- " console.log('Request 3a:', request3a);",
281
- ' const response3a = await agent.run(request3a, undefined, undefined, session.id);',
282
- " console.log('Response:', response3a);",
283
- " console.log('\\n\\n');",
284
- " const request3b = 'Now add a paragraph to that HTML file explaining what Dexto is';",
285
- " console.log('Request 3b:', request3b);",
286
- ' const response3b = await agent.run(request3b, undefined, undefined, session.id);',
287
- " console.log('Response:', response3b);",
288
- " console.log('\\n——————\\n');",
289
- '',
290
- ' // Reset conversation (clear context)',
291
- " console.log('🔄 Resetting conversation context...');",
292
- ' await agent.resetConversation(session.id);',
293
- " console.log('🔄 Conversation context reset');",
294
- " console.log('\\n——————\\n');",
295
- '',
296
- ' // Example 4: Complex task',
297
- " console.log('🏗️ Example 4: Complex multi-tool task');",
298
- ' const request4 = ',
299
- " 'Create a simple webpage about AI agents with HTML, CSS, and JavaScript. ' +",
300
- " 'The page should have a title, some content about what AI agents are, ' +",
301
- " 'and a button that shows an alert when clicked.';",
302
- " console.log('Request:', request4);",
303
- ' const response4 = await agent.run(request4, undefined, undefined, session.id);',
304
- " console.log('Response:', response4);",
305
- " console.log('\\n——————\\n');",
306
- '',
307
- ' // Stop the agent (disconnect from MCP servers)',
308
- " console.log('\\n🛑 Stopping agent...');",
309
- ' await agent.stop();',
310
- " console.log('✅ Agent stopped successfully!');",
311
- '',
312
- '} catch (error) {',
313
- " console.error('❌ Error:', error);",
314
- '}',
315
- '',
316
- "console.log('\\n📖 Read Dexto documentation to understand more about using Dexto: https://docs.dexto.ai');",
317
- ];
318
- const indexTsContent = indexTsLines.join('\n');
189
+ export async function createDextoExampleFile(directory, options) {
190
+ const provider = options?.llmProvider ?? 'openai';
191
+ const model = getDefaultModelForProvider(provider) ?? 'gpt-4o';
192
+ const indexTsContent = generateIndexForCodeFirstDI({
193
+ projectName: 'dexto-example',
194
+ packageName: 'dexto-example',
195
+ description: 'Dexto example',
196
+ llmProvider: provider,
197
+ llmModel: model,
198
+ });
319
199
  const outputPath = path.join(directory, 'dexto-example.ts');
320
- // Log the generated file content and paths for debugging
321
- logger.debug(`Creating example file with config path: ${configPath}`);
322
- logger.debug(`Base directory: ${baseDir}, Output path: ${outputPath}`);
323
- logger.debug(`Generated file content:\n${indexTsContent}`);
324
200
  // Ensure the directory exists before writing the file
325
201
  await fs.writeFile(outputPath, indexTsContent);
326
202
  return outputPath;
@@ -20,6 +20,8 @@ export type CommandHandlerResult = boolean | string | StyledOutput | SendMessage
20
20
  export interface CommandContext {
21
21
  /** Current session ID, or null if no active session */
22
22
  sessionId: string | null;
23
+ /** Source config file path for persistence and display (if available) */
24
+ configFilePath: string | null;
23
25
  }
24
26
  export interface CommandDefinition {
25
27
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"command-parser.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/command-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAEhG,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,iBAAiB,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,uDAAuD;IACvD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,OAAO,EAAE,CACL,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,cAAc,KAClB,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,oBAAoB,CAAS,CAAC;AA4ClF;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAiCvD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAoB9F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,QAAQ,GAAE,OAAe,GAAG,MAAM,CAmB3F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAwDtE"}
1
+ {"version":3,"file":"command-parser.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/command-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAEhG,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,iBAAiB,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,uDAAuD;IACvD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yEAAyE;IACzE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,OAAO,EAAE,CACL,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,cAAc,KAClB,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,oBAAoB,CAAS,CAAC;AA4ClF;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAiCvD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAoB9F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,QAAQ,GAAE,OAAe,GAAG,MAAM,CAmB3F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAwDtE"}
@@ -43,7 +43,7 @@ export declare const CLI_COMMANDS: CommandDefinition[];
43
43
  * @param sessionId - Session ID to use for agent.run() calls
44
44
  * @returns CommandHandlerResult - boolean, string, or StyledOutput
45
45
  */
46
- export declare function executeCommand(command: string, args: string[], agent: DextoAgent, sessionId?: string): Promise<CommandHandlerResult>;
46
+ export declare function executeCommand(command: string, args: string[], agent: DextoAgent, sessionId?: string, configFilePath?: string | null): Promise<CommandHandlerResult>;
47
47
  /**
48
48
  * Get all available command definitions
49
49
  * This is used by external systems that need to inspect available commands
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAgBnF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,EAAE,iBAAiB,EAAO,CAAC;AA6CpD;;;;;GAKG;AACH,wBAAsB,cAAc,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,UAAU,EACjB,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAyD/B;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,EAAE,CAEpD"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAgBnF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,EAAE,iBAAiB,EAAO,CAAC;AA6CpD;;;;;GAKG;AACH,wBAAsB,cAAc,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,UAAU,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAyD/B;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,EAAE,CAEpD"}
@@ -85,9 +85,9 @@ CLI_COMMANDS.push(...baseCommands);
85
85
  * @param sessionId - Session ID to use for agent.run() calls
86
86
  * @returns CommandHandlerResult - boolean, string, or StyledOutput
87
87
  */
88
- export async function executeCommand(command, args, agent, sessionId) {
88
+ export async function executeCommand(command, args, agent, sessionId, configFilePath) {
89
89
  // Create command context with sessionId
90
- const ctx = { sessionId: sessionId ?? null };
90
+ const ctx = { sessionId: sessionId ?? null, configFilePath: configFilePath ?? null };
91
91
  // Find the command (including aliases)
92
92
  const cmd = CLI_COMMANDS.find((c) => c.name === command || (c.aliases && c.aliases.includes(command)));
93
93
  if (cmd) {
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Exit Handler
3
+ *
4
+ * Provides a way for commands to trigger a graceful CLI exit.
5
+ * The exit function is registered by the Ink app and can be called
6
+ * by commands to unmount the app properly.
7
+ */
8
+ type ExitFunction = () => void;
9
+ export declare function registerExitHandler(fn: ExitFunction): void;
10
+ export declare function triggerExit(): void;
11
+ export {};
12
+ //# sourceMappingURL=exit-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-handler.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/exit-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,KAAK,YAAY,GAAG,MAAM,IAAI,CAAC;AAI/B,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAE1D;AAED,wBAAgB,WAAW,IAAI,IAAI,CAOlC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Exit Handler
3
+ *
4
+ * Provides a way for commands to trigger a graceful CLI exit.
5
+ * The exit function is registered by the Ink app and can be called
6
+ * by commands to unmount the app properly.
7
+ */
8
+ let exitFn = null;
9
+ export function registerExitHandler(fn) {
10
+ exitFn = fn;
11
+ }
12
+ export function triggerExit() {
13
+ if (exitFn) {
14
+ exitFn();
15
+ }
16
+ else {
17
+ // Fallback to process.exit if exit handler not registered
18
+ process.exit(0);
19
+ }
20
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Exit Stats Storage
3
+ *
4
+ * Stores session statistics to be displayed after the CLI exits.
5
+ * This allows the stats to be printed to stdout after Ink unmounts,
6
+ * ensuring they appear at the bottom of the terminal.
7
+ */
8
+ import type { SessionMetadata } from '@dexto/core';
9
+ export interface ExitSessionStats {
10
+ sessionId?: string;
11
+ duration?: string;
12
+ messageCount: {
13
+ total: number;
14
+ user: number;
15
+ assistant: number;
16
+ };
17
+ tokenUsage?: NonNullable<SessionMetadata['tokenUsage']>;
18
+ estimatedCost?: SessionMetadata['estimatedCost'];
19
+ modelStats?: NonNullable<SessionMetadata['modelStats']>;
20
+ }
21
+ export declare function setExitStats(stats: ExitSessionStats): void;
22
+ export declare function getExitStats(): ExitSessionStats | null;
23
+ export declare function clearExitStats(): void;
24
+ //# sourceMappingURL=exit-stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-stats.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/exit-stats.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE;QACV,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,UAAU,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;IACxD,aAAa,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IACjD,UAAU,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;CAC3D;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAE1D;AAED,wBAAgB,YAAY,IAAI,gBAAgB,GAAG,IAAI,CAEtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Exit Stats Storage
3
+ *
4
+ * Stores session statistics to be displayed after the CLI exits.
5
+ * This allows the stats to be printed to stdout after Ink unmounts,
6
+ * ensuring they appear at the bottom of the terminal.
7
+ */
8
+ let exitStats = null;
9
+ export function setExitStats(stats) {
10
+ exitStats = stats;
11
+ }
12
+ export function getExitStats() {
13
+ return exitStats;
14
+ }
15
+ export function clearExitStats() {
16
+ exitStats = null;
17
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"general-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/general-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAwC,MAAM,qBAAqB,CAAC;AAgGnG;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,iBAAiB,EAAE,GAAG,iBAAiB,CAgC9F;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,iBAAiB,EAyZ9C,CAAC"}
1
+ {"version":3,"file":"general-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/general-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAwC,MAAM,qBAAqB,CAAC;AAkGnG;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,iBAAiB,EAAE,GAAG,iBAAiB,CAgC9F;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,iBAAiB,EAid9C,CAAC"}
@@ -14,6 +14,8 @@ import { spawn } from 'child_process';
14
14
  import { formatForInkCli } from './utils/format-output.js';
15
15
  import { CommandOutputHelper } from './utils/command-output.js';
16
16
  import { writeToClipboard } from '../../ink-cli/utils/clipboardUtils.js';
17
+ import { setExitStats } from './exit-stats.js';
18
+ import { triggerExit } from './exit-handler.js';
17
19
  /**
18
20
  * Get the shell rc file path for the given shell
19
21
  */
@@ -159,9 +161,57 @@ export const generalCommands = [
159
161
  usage: '/exit',
160
162
  category: 'General',
161
163
  aliases: ['quit', 'q'],
162
- handler: async (_args, _agent, _ctx) => {
163
- console.log(chalk.rgb(255, 165, 0)('Exiting AI CLI. Goodbye!'));
164
- process.exit(0);
164
+ handler: async (_args, agent, ctx) => {
165
+ // Store session stats to be displayed after Ink exits
166
+ try {
167
+ const { sessionId } = ctx;
168
+ if (sessionId) {
169
+ const [sessionMetadata, history] = await Promise.all([
170
+ agent.sessionManager.getSessionMetadata(sessionId),
171
+ agent.getSessionHistory(sessionId),
172
+ ]);
173
+ if (sessionMetadata) {
174
+ // Calculate session duration
175
+ let durationStr;
176
+ if (sessionMetadata.createdAt) {
177
+ const duration = Date.now() - new Date(sessionMetadata.createdAt).getTime();
178
+ const minutes = Math.floor(duration / 60000);
179
+ const seconds = Math.floor((duration % 60000) / 1000);
180
+ durationStr = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
181
+ }
182
+ // Message counts
183
+ const messageCount = {
184
+ total: history?.length || 0,
185
+ user: history?.filter((msg) => msg.role === 'user').length || 0,
186
+ assistant: history?.filter((msg) => msg.role === 'assistant').length || 0,
187
+ };
188
+ // Store stats for display after exit
189
+ setExitStats({
190
+ ...(sessionId && { sessionId }),
191
+ ...(durationStr && { duration: durationStr }),
192
+ messageCount,
193
+ ...(sessionMetadata.tokenUsage && {
194
+ tokenUsage: sessionMetadata.tokenUsage,
195
+ }),
196
+ ...(sessionMetadata.estimatedCost !== undefined && {
197
+ estimatedCost: sessionMetadata.estimatedCost,
198
+ }),
199
+ ...(sessionMetadata.modelStats && {
200
+ modelStats: sessionMetadata.modelStats,
201
+ }),
202
+ });
203
+ }
204
+ }
205
+ }
206
+ catch (error) {
207
+ // Silently ignore errors - don't block exit
208
+ agent.logger.debug(`Failed to collect session stats on exit: ${error instanceof Error ? error.message : String(error)}`);
209
+ }
210
+ // Trigger graceful exit - this will unmount the Ink app
211
+ // After unmount, session stats will be printed to stdout
212
+ triggerExit();
213
+ // Return true to indicate command was handled
214
+ return true;
165
215
  },
166
216
  },
167
217
  {
@@ -175,7 +225,7 @@ export const generalCommands = [
175
225
  const newSession = await agent.createSession();
176
226
  const newSessionId = newSession.id;
177
227
  // Emit session:created to switch the CLI to the new session
178
- agent.agentEventBus.emit('session:created', {
228
+ agent.emit('session:created', {
179
229
  sessionId: newSessionId,
180
230
  switchTo: true,
181
231
  });
@@ -397,7 +447,7 @@ export const generalCommands = [
397
447
  name: 'Global',
398
448
  shortcuts: [
399
449
  { keys: 'Ctrl+C', description: 'Clear input, then exit (press twice)' },
400
- { keys: 'Ctrl+T', description: 'Toggle task list (show/hide tasks)' },
450
+ { keys: 'Ctrl+T', description: 'Toggle todo list (show/hide todos)' },
401
451
  { keys: 'Escape', description: 'Cancel processing / close overlay' },
402
452
  ],
403
453
  },
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/prompt-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAwC,MAAM,qBAAqB,CAAC;AAKnG;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,iBAAiB,EA8L7C,CAAC;AAkKF;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiB9F"}
1
+ {"version":3,"file":"prompt-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/prompt-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAwC,MAAM,qBAAqB,CAAC;AAKnG;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,iBAAiB,EAiI7C,CAAC;AA6IF;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiB9F"}