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
@@ -2,135 +2,86 @@
2
2
  * Template Engine for Dexto Project Scaffolding
3
3
  *
4
4
  * Provides code generation functions for various project types.
5
- * Uses the image/harness terminology strategy:
6
- * - "Image" for distributable artifacts, packages, composition
7
- * - "Harness" for runtime behavior, what it provides
5
+ *
6
+ * Note: create-app/init-app scaffolds are programmatic (no YAML/images).
7
+ * Image scaffolds are generated via `dexto create-image`.
8
8
  */
9
9
  /**
10
- * Generates src/index.ts for an app using an image
10
+ * Generates src/index.ts for an app using programmatic configuration.
11
11
  */
12
- export function generateIndexForImage(context) {
13
- return `// Load image environment (Pattern 1: Static Import)
14
- // This auto-registers providers as a side-effect
15
- import '${context.imageName}';
16
-
17
- // Import from core packages
18
- import { DextoAgent } from '@dexto/core';
19
- import { loadAgentConfig } from '@dexto/agent-management';
20
-
21
- async function main() {
22
- console.log('🚀 Starting ${context.projectName}\\n');
23
-
24
- // Load agent configuration
25
- const config = await loadAgentConfig('./agents/default.yml');
26
-
27
- // Create agent - providers already registered by image environment
28
- const agent = new DextoAgent(config, './agents/default.yml');
29
-
30
- await agent.start();
31
- console.log('✅ Agent started\\n');
32
-
33
- // Create a session
34
- const session = await agent.createSession();
35
-
36
- // Example interaction
37
- const response = await agent.run(
38
- 'Hello! What can you help me with?',
39
- undefined, // imageDataInput
40
- undefined, // fileDataInput
41
- session.id // sessionId
42
- );
43
-
44
- console.log('Agent response:', response);
45
-
46
- // Cleanup
47
- await agent.stop();
48
- }
12
+ export function generateIndexForCodeFirstDI(context) {
13
+ const defaultProvider = context.llmProvider ?? 'openai';
14
+ const defaultModel = context.llmModel ?? 'gpt-4o';
15
+ return `// Standalone Dexto app (programmatic)
16
+ import 'dotenv/config';
17
+
18
+ import { DextoAgent, createLogger } from '@dexto/core';
19
+ import { MemoryBlobStore, MemoryCacheStore, MemoryDatabaseStore } from '@dexto/storage';
20
+
21
+ const agentId = '${context.projectName}';
22
+ const logger = createLogger({
23
+ agentId,
24
+ config: { level: 'info', transports: [{ type: 'console', colorize: true }] },
25
+ });
49
26
 
50
- main().catch((error) => {
51
- console.error('Error:', error);
52
- process.exit(1);
27
+ const agent = new DextoAgent({
28
+ agentId,
29
+ llm: { provider: '${defaultProvider}', model: '${defaultModel}' },
30
+ systemPrompt: 'You are a helpful AI assistant.',
31
+ logger,
32
+ storage: {
33
+ cache: new MemoryCacheStore(),
34
+ database: new MemoryDatabaseStore(),
35
+ blob: new MemoryBlobStore({}, logger),
36
+ },
53
37
  });
38
+
39
+ await agent.start();
40
+ const session = await agent.createSession();
41
+ console.log((await agent.generate('Hello! What can you do?', session.id)).content);
42
+ await agent.stop();
54
43
  `;
55
44
  }
56
45
  /**
57
- * Generates src/index.ts for a web server application using an image
46
+ * Generates src/index.ts for a web server application using programmatic configuration.
58
47
  */
59
- export function generateWebServerIndex(context) {
60
- return `// Load image environment (Pattern 1: Static Import)
61
- // This auto-registers providers as a side-effect
62
- import '${context.imageName}';
63
-
64
- // Import from core packages
65
- import { DextoAgent } from '@dexto/core';
66
- import { loadAgentConfig } from '@dexto/agent-management';
48
+ export function generateWebServerIndexForCodeFirstDI(context) {
49
+ const defaultProvider = context.llmProvider ?? 'openai';
50
+ const defaultModel = context.llmModel ?? 'gpt-4o';
51
+ return `// Dexto Web Server (programmatic)
52
+ import 'dotenv/config';
53
+
54
+ import { DextoAgent, createLogger } from '@dexto/core';
55
+ import { MemoryBlobStore, MemoryCacheStore, MemoryDatabaseStore } from '@dexto/storage';
67
56
  import { startDextoServer } from '@dexto/server';
68
57
  import { resolve } from 'node:path';
69
- import { existsSync } from 'node:fs';
70
58
 
71
- async function main() {
72
- console.log('🚀 Starting ${context.projectName}\\n');
73
-
74
- // Load agent configuration
75
- console.log('📝 Loading configuration...');
76
- const config = await loadAgentConfig('./agents/default.yml');
77
- console.log('✅ Config loaded\\n');
78
-
79
- // Create agent
80
- console.log('🤖 Creating agent...');
81
- const agent = new DextoAgent(config, './agents/default.yml');
82
- console.log('✅ Agent created\\n');
83
-
84
- // Start the server
85
- console.log('🌐 Starting Dexto server...');
86
-
87
- const webRoot = resolve(process.cwd(), 'app');
88
-
89
- if (!existsSync(webRoot)) {
90
- console.error(\`❌ Error: Web root not found at \${webRoot}\`);
91
- console.error(' Make sure the app/ directory exists');
92
- process.exit(1);
93
- }
94
-
95
- console.log(\`📁 Serving static files from: \${webRoot}\`);
59
+ const agentId = '${context.projectName}';
60
+ const logger = createLogger({
61
+ agentId,
62
+ config: { level: 'info', transports: [{ type: 'console', colorize: true }] },
63
+ });
96
64
 
97
- const { stop } = await startDextoServer(agent, {
98
- port: 3000,
99
- webRoot,
100
- agentCard: {
101
- name: '${context.projectName}',
102
- description: '${context.description}',
103
- },
104
- });
105
-
106
- console.log('\\n✅ Server is running!\\n');
107
- console.log('🌐 Open your browser:');
108
- console.log(' http://localhost:3000\\n');
109
- console.log('📚 Available endpoints:');
110
- console.log(' • Web UI: http://localhost:3000');
111
- console.log(' • REST API: http://localhost:3000/api/*');
112
- console.log(' • Health Check: http://localhost:3000/health');
113
- console.log(' • OpenAPI Spec: http://localhost:3000/openapi.json');
114
- console.log(' • Agent Card: http://localhost:3000/.well-known/agent-card.json\\n');
115
-
116
- console.log('Press Ctrl+C to stop the server...\\n');
117
-
118
- // Handle graceful shutdown
119
- const shutdown = async () => {
120
- console.log('\\n🛑 Shutting down...');
121
- await stop();
122
- console.log('✅ Server stopped\\n');
123
- process.exit(0);
124
- };
125
-
126
- process.on('SIGINT', shutdown);
127
- process.on('SIGTERM', shutdown);
128
- }
65
+ const agent = new DextoAgent({
66
+ agentId,
67
+ llm: { provider: '${defaultProvider}', model: '${defaultModel}' },
68
+ systemPrompt: 'You are a helpful AI assistant.',
69
+ logger,
70
+ storage: {
71
+ cache: new MemoryCacheStore(),
72
+ database: new MemoryDatabaseStore(),
73
+ blob: new MemoryBlobStore({}, logger),
74
+ },
75
+ });
129
76
 
130
- main().catch((error) => {
131
- console.error('Error:', error);
132
- process.exit(1);
77
+ const { stop } = await startDextoServer(agent, {
78
+ port: 3000,
79
+ webRoot: resolve(process.cwd(), 'app'),
80
+ agentCard: { name: '${context.projectName}', description: '${context.description}' },
133
81
  });
82
+
83
+ process.on('SIGINT', () => void stop());
84
+ process.on('SIGTERM', () => void stop());
134
85
  `;
135
86
  }
136
87
  /**
@@ -569,44 +520,8 @@ header h1 {
569
520
  */
570
521
  export function generateDextoImageFile(context) {
571
522
  const extendsField = context.baseImage ? ` extends: '${context.baseImage}',\n` : '';
572
- return `import { defineImage } from '@dexto/core';
573
-
574
- export default defineImage({
575
- name: '${context.imageName || context.projectName}',
576
- version: '1.0.0',
577
- description: '${context.description}',
578
- target: '${context.target || 'local-development'}',
579
- ${extendsField}
580
- // Providers are AUTO-DISCOVERED from convention-based folders:
581
- // tools/ - Custom tool providers
582
- // blob-store/ - Blob storage providers
583
- // compression/ - Compression strategy providers
584
- // plugins/ - Plugin providers
585
- //
586
- // Each provider must export from an index.ts file in its folder.
587
- // The bundler will automatically register them when the image is imported.
588
-
589
- providers: {
590
- // Manual registration for built-in core providers
591
- // (These come from core, not from our providers/ folder)
592
- // TODO: This is a hack to get the local blob store provider to work. Should be auto-registered or dealt with in a better way.
593
- blobStore: {
594
- register: async () => {
595
- const { localBlobStoreProvider, inMemoryBlobStoreProvider } = await import(
596
- '@dexto/core'
597
- );
598
- const { blobStoreRegistry } = await import('@dexto/core');
599
-
600
- blobStoreRegistry.register(localBlobStoreProvider);
601
- blobStoreRegistry.register(inMemoryBlobStoreProvider);
602
-
603
- console.log('✓ Registered core blob storage providers: local, in-memory');
604
- },
605
- },
606
- },
607
-
608
- defaults: {
609
- storage: {
523
+ const storageDefaults = context.baseImage
524
+ ? ` storage: {
610
525
  blob: {
611
526
  type: 'local',
612
527
  storePath: './data/blobs',
@@ -618,83 +533,48 @@ ${extendsField}
618
533
  cache: {
619
534
  type: 'in-memory',
620
535
  },
621
- },
622
- logging: {
623
- level: 'info',
624
- fileLogging: true,
625
- },
626
- },
627
-
628
- constraints: ['filesystem-required', 'offline-capable'],
629
- });
630
- `;
631
- }
632
- /**
633
- * Generates dexto.config.ts file for manual registration projects
634
- */
635
- export function generateDextoConfigFile(context) {
636
- return `/**
637
- * ${context.projectName} - Provider Registration
638
- *
639
- * This file registers all custom providers before agent initialization.
640
- * This is the manual registration approach - for most use cases, consider
641
- * using Dexto images instead (see: dexto create-image).
642
- */
643
-
644
- import {
645
- blobStoreRegistry,
646
- customToolRegistry,
647
- compactionRegistry,
648
- pluginRegistry,
649
- } from '@dexto/core';
536
+ },`
537
+ : ` storage: {
538
+ blob: {
539
+ type: 'example-blob',
540
+ },
541
+ database: {
542
+ type: 'example-database',
543
+ },
544
+ cache: {
545
+ type: 'example-cache',
546
+ },
547
+ },`;
548
+ return `import type { ImageDefinition } from '@dexto/image-bundler';
650
549
 
651
- /**
652
- * Project metadata
653
- */
654
- export const projectConfig = {
655
- name: '${context.projectName}',
550
+ const image = {
551
+ name: '${context.imageName || context.projectName}',
656
552
  version: '1.0.0',
657
553
  description: '${context.description}',
658
- };
659
-
660
- /**
661
- * Register all custom providers
662
- *
663
- * This function is called at application startup before loading agent configs.
664
- * Register your providers here by importing them and calling the appropriate
665
- * registry.register() method.
666
- */
667
- export function registerProviders() {
668
- // Example: Register blob storage provider
669
- // import { myBlobProvider } from './storage/my-blob.js';
670
- // blobStoreRegistry.register(myBlobProvider);
671
-
672
- // Example: Register custom tool
673
- // import { myToolProvider } from './tools/my-tool.js';
674
- // customToolRegistry.register(myToolProvider);
675
-
676
- // Example: Register plugin
677
- // import { myPluginProvider } from './plugins/my-plugin.js';
678
- // pluginRegistry.register(myPluginProvider);
554
+ target: '${context.target || 'local-development'}',
555
+ ${extendsField}
556
+ // Factories are AUTO-DISCOVERED from convention-based folders:
557
+ // tools/<type>/index.ts
558
+ // storage/blob/<type>/index.ts
559
+ // storage/database/<type>/index.ts
560
+ // storage/cache/<type>/index.ts
561
+ // hooks/<type>/index.ts
562
+ // compaction/<type>/index.ts
563
+ //
564
+ // Each factory module must export a factory constant (export const factory = ...).
679
565
 
680
- console.log(\`✓ Registered providers for \${projectConfig.name}\`);
681
- }
566
+ defaults: {
567
+ ${storageDefaults}
568
+ logger: {
569
+ level: 'info',
570
+ transports: [{ type: 'console', colorize: true }],
571
+ },
572
+ },
682
573
 
683
- /**
684
- * Optional: Project-wide initialization logic
685
- * Use this for setting up monitoring, analytics, error tracking, etc.
686
- */
687
- export async function initialize() {
688
- console.log(\`✓ Initialized \${projectConfig.name} v\${projectConfig.version}\`);
689
- }
574
+ constraints: ['filesystem-required', 'offline-capable'],
575
+ } satisfies ImageDefinition;
690
576
 
691
- /**
692
- * Optional: Cleanup logic
693
- * Called when the application shuts down
694
- */
695
- export async function cleanup() {
696
- console.log(\`✓ Cleaned up \${projectConfig.name}\`);
697
- }
577
+ export default image;
698
578
  `;
699
579
  }
700
580
  /**
@@ -703,7 +583,7 @@ export async function cleanup() {
703
583
  export function generateImageReadme(context) {
704
584
  const imageName = context.imageName || context.projectName;
705
585
  const extendsNote = context.baseImage
706
- ? `\n\nThis image extends \`${context.baseImage}\`, inheriting its providers and adding custom ones.\n`
586
+ ? `\n\nThis image extends \`${context.baseImage}\`, inheriting its factories and adding custom ones.\n`
707
587
  : '';
708
588
  return `# ${imageName}
709
589
 
@@ -711,16 +591,14 @@ ${context.description}${extendsNote}
711
591
 
712
592
  ## What is this?
713
593
 
714
- A **Dexto image** - a pre-configured agent harness packaged as an npm module.
715
- Install it, import it, and you have a complete runtime harness ready to use.
594
+ A **Dexto image** is a distributable npm module that exports a typed \`DextoImage\` (a plain object)
595
+ describing tool/storage/hook/compaction factories + optional default config.
716
596
 
717
597
  ## What's Included
718
598
 
719
- The harness provides:
720
- - ✅ Pre-registered providers (auto-discovered from convention-based folders)
721
- - ✅ Runtime orchestration
722
- - ✅ Context management
723
- - ✅ Default configurations
599
+ This package contains:
600
+ - ✅ Factories (auto-discovered from convention-based folders)
601
+ - ✅ Optional defaults (\`image.defaults\`) that merge into agent config (config wins)
724
602
 
725
603
  ## Quick Start
726
604
 
@@ -728,40 +606,33 @@ The harness provides:
728
606
  # Build the image
729
607
  pnpm run build
730
608
 
731
- # Use in your app
732
- pnpm add ${imageName}
609
+ # Install into the Dexto CLI (local)
610
+ npm pack
611
+ dexto image install ./<generated-file>.tgz
733
612
  \`\`\`
734
613
 
735
614
  ## Usage
736
615
 
737
- \`\`\`typescript
738
- import { createAgent } from '${imageName}';
739
- import { loadAgentConfig } from '@dexto/agent-management';
740
-
741
- const config = await loadAgentConfig('./agents/default.yml');
742
-
743
- // Import creates the harness (providers auto-registered)
744
- const agent = createAgent(config);
745
-
746
- // The harness handles everything
747
- await agent.start();
748
- \`\`\`
616
+ Set \`image: '${imageName}'\` in your agent config (or pass \`--image\` in the CLI), then run Dexto.
749
617
 
750
- ## Adding Providers
618
+ ## Adding Factories
751
619
 
752
- Add your custom providers to convention-based folders:
753
- - \`tools/\` - Custom tool providers
754
- - \`blob-store/\` - Blob storage providers
755
- - \`compression/\` - Compression strategies
756
- - \`plugins/\` - Plugin providers
620
+ Add your custom factories to convention-based folders:
621
+ - \`tools/<type>/\` - Tool factories
622
+ - \`storage/blob/<type>/\` - Blob storage factories
623
+ - \`storage/database/<type>/\` - Database factories
624
+ - \`storage/cache/<type>/\` - Cache factories
625
+ - \`hooks/<type>/\` - Hook factories
626
+ - \`compaction/<type>/\` - Compaction factories
757
627
 
758
- **Convention:** Each provider lives in its own folder with an \`index.ts\` file.
628
+ **Convention:** Each factory lives in its own folder with an \`index.ts\` file.
629
+ Each \`index.ts\` must export a \`factory\` constant (e.g. \`export const factory = myToolFactory;\`).
759
630
 
760
631
  Example:
761
632
  \`\`\`
762
633
  tools/
763
634
  my-tool/
764
- index.ts # Provider implementation (auto-discovered)
635
+ index.ts # Factory implementation (auto-discovered)
765
636
  helpers.ts # Optional helper functions
766
637
  types.ts # Optional type definitions
767
638
  \`\`\`
@@ -772,20 +643,10 @@ tools/
772
643
  pnpm run build
773
644
  \`\`\`
774
645
 
775
- This runs \`dexto-bundle build\` which:
776
- 1. Discovers providers from convention-based folders
777
- 2. Generates \`dist/index.js\` with side-effect registration
778
- 3. Exports \`createAgent()\` factory function
779
-
780
- ## Architecture
781
-
782
- When imported, this image:
783
- 1. Auto-registers providers (side effect)
784
- 2. Exposes harness factory (\`createAgent\`)
785
- 3. Re-exports registries for runtime customization
786
-
787
- The resulting harness manages your agent's runtime, including provider lifecycle,
788
- context management, and tool orchestration.
646
+ This runs \`dexto-bundle build\`, which:
647
+ 1. Discovers factories from convention-based folders
648
+ 2. Compiles factory source files to \`dist/\`
649
+ 3. Generates \`dist/index.js\` exporting a \`DextoImage\` (no side effects)
789
650
 
790
651
  ## Publishing
791
652
 
@@ -795,24 +656,19 @@ npm publish
795
656
 
796
657
  Users can then:
797
658
  \`\`\`bash
798
- pnpm add ${imageName}
659
+ dexto image install ${imageName}
799
660
  \`\`\`
800
-
801
- ## Learn More
802
-
803
- - [Dexto Images Guide](https://docs.dexto.ai/docs/guides/images)
804
- - [Provider Development](https://docs.dexto.ai/docs/guides/providers)
805
- - [Bundler Documentation](https://docs.dexto.ai/docs/tools/bundler)
806
661
  `;
807
662
  }
808
663
  /**
809
- * Generates an example custom tool provider
664
+ * Generates an example custom tool factory
810
665
  */
811
666
  export function generateExampleTool(toolName = 'example-tool') {
812
- // Convert kebab-case to camelCase for provider name
813
- const providerName = toolName.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
667
+ // Convert kebab-case to camelCase for a readable type name base
668
+ const typeNameBase = toolName.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
814
669
  return `import { z } from 'zod';
815
- import type { CustomToolProvider, InternalTool, ToolCreationContext } from '@dexto/core';
670
+ import type { ToolFactory } from '@dexto/agent-config';
671
+ import type { Tool, ToolExecutionContext } from '@dexto/core';
816
672
 
817
673
  const ConfigSchema = z
818
674
  .object({
@@ -821,32 +677,34 @@ const ConfigSchema = z
821
677
  })
822
678
  .strict();
823
679
 
824
- type ${providerName.charAt(0).toUpperCase() + providerName.slice(1)}Config = z.output<typeof ConfigSchema>;
680
+ type ${typeNameBase.charAt(0).toUpperCase() + typeNameBase.slice(1)}Config = z.output<typeof ConfigSchema>;
825
681
 
826
682
  /**
827
- * Example custom tool provider
683
+ * Example tool factory
828
684
  *
829
- * This demonstrates how to create a custom tool that can be used by the agent.
830
- * The tool is auto-discovered by the bundler when placed in the tools/ folder.
685
+ * This demonstrates how to create a tool factory that can be used by an image.
686
+ * The bundler auto-discovers this module when placed in tools/<type>/index.ts.
687
+ *
688
+ * Contract: export a factory constant with { configSchema, create }.
831
689
  */
832
- export const ${providerName}Provider: CustomToolProvider<'${toolName}', ${providerName.charAt(0).toUpperCase() + providerName.slice(1)}Config> = {
833
- type: '${toolName}',
690
+ export const factory: ToolFactory<${typeNameBase.charAt(0).toUpperCase() + typeNameBase.slice(1)}Config> = {
834
691
  configSchema: ConfigSchema,
835
-
836
- create: (config: ${providerName.charAt(0).toUpperCase() + providerName.slice(1)}Config, context: ToolCreationContext): InternalTool[] => {
837
- // Create and return tools
838
- const tool: InternalTool = {
839
- id: '${providerName}',
840
- description: 'An example custom tool that demonstrates the tool provider pattern',
692
+ metadata: {
693
+ displayName: 'Example Tool',
694
+ description: 'Example tool factory',
695
+ category: 'utilities',
696
+ },
697
+ create: (_config) => {
698
+ const tool: Tool = {
699
+ id: '${toolName}',
700
+ description: 'An example tool that demonstrates the tool factory pattern',
841
701
  inputSchema: z.object({
842
702
  input: z.string().describe('Input text to process'),
843
703
  }),
844
-
845
- execute: async (input: unknown) => {
704
+ execute: async (input: unknown, context: ToolExecutionContext) => {
846
705
  const { input: inputText } = input as { input: string };
847
706
  context.logger.info(\`Example tool called with: \${inputText}\`);
848
707
 
849
- // Your tool logic here
850
708
  return {
851
709
  result: \`Processed: \${inputText}\`,
852
710
  };
@@ -855,33 +713,196 @@ export const ${providerName}Provider: CustomToolProvider<'${toolName}', ${provid
855
713
 
856
714
  return [tool];
857
715
  },
716
+ };
717
+ `;
718
+ }
719
+ /**
720
+ * Generates an example custom hook factory
721
+ */
722
+ export function generateExampleHook(hookName) {
723
+ return `import { z } from 'zod';
724
+ import type { HookFactory } from '@dexto/agent-config';
725
+ import type { Hook } from '@dexto/core';
858
726
 
859
- metadata: {
860
- displayName: 'Example Tool',
861
- description: 'Example custom tool provider',
862
- category: 'utilities',
727
+ const ConfigSchema = z
728
+ .object({
729
+ type: z.literal('${hookName}'),
730
+ })
731
+ .strict();
732
+
733
+ type ExampleHookConfig = z.output<typeof ConfigSchema>;
734
+
735
+ /**
736
+ * Example hook factory
737
+ *
738
+ * Hooks are resolved from image factories, same as tools.
739
+ * The bundler auto-discovers this module when placed in hooks/<type>/index.ts.
740
+ */
741
+ export const factory: HookFactory<ExampleHookConfig> = {
742
+ configSchema: ConfigSchema,
743
+ create: (_config) => {
744
+ const hook: Hook = {
745
+ beforeLLMRequest: async (payload, context) => {
746
+ context.logger.info(\`${hookName} saw input: \${payload.text}\`);
747
+ return { ok: true };
748
+ },
749
+ };
750
+
751
+ return hook;
863
752
  },
864
753
  };
865
754
  `;
866
755
  }
867
756
  /**
868
- * Generates README for an app project
757
+ * Generates an example custom compaction factory
869
758
  */
870
- export function generateAppReadme(context) {
871
- const usingImage = context.imageName;
872
- const imageSection = usingImage
873
- ? `\n## Image
759
+ export function generateExampleCompaction(compactionType) {
760
+ return `import { z } from 'zod';
761
+ import type { CompactionFactory } from '@dexto/agent-config';
762
+ import type { CompactionStrategy } from '@dexto/core';
763
+
764
+ const ConfigSchema = z
765
+ .object({
766
+ type: z.literal('${compactionType}'),
767
+ enabled: z.boolean().default(true).describe('Enable compaction strategy'),
768
+ maxContextTokens: z
769
+ .number()
770
+ .positive()
771
+ .optional()
772
+ .describe('Max tokens before compaction'),
773
+ thresholdPercent: z
774
+ .number()
775
+ .min(0.1)
776
+ .max(1.0)
777
+ .default(0.9)
778
+ .describe('Trigger threshold (0–1)'),
779
+ })
780
+ .strict();
781
+
782
+ type ExampleCompactionConfig = z.output<typeof ConfigSchema>;
783
+
784
+ /**
785
+ * Example compaction factory
786
+ *
787
+ * Compaction is a DI surface. Agents select exactly one strategy via \`compaction.type\`.
788
+ * The bundler auto-discovers this module when placed in compaction/<type>/index.ts.
789
+ */
790
+ export const factory: CompactionFactory<ExampleCompactionConfig> = {
791
+ configSchema: ConfigSchema,
792
+ create: (config) => {
793
+ const strategy: CompactionStrategy = {
794
+ name: '${compactionType}',
795
+ getSettings: () => ({
796
+ enabled: config.enabled,
797
+ maxContextTokens: config.maxContextTokens,
798
+ thresholdPercent: config.thresholdPercent,
799
+ }),
800
+ getModelLimits: (modelContextWindow) => ({
801
+ contextWindow: config.maxContextTokens
802
+ ? Math.min(modelContextWindow, config.maxContextTokens)
803
+ : modelContextWindow,
804
+ }),
805
+ shouldCompact: () => false,
806
+ compact: async () => [],
807
+ };
874
808
 
875
- This app uses the \`${context.imageName}\` image, which provides a complete agent harness with:
876
- - Pre-configured providers
877
- - Runtime orchestration
878
- - Context management
809
+ return strategy;
810
+ },
811
+ };
812
+ `;
813
+ }
814
+ /**
815
+ * Generates an example in-memory cache factory
816
+ */
817
+ export function generateExampleCacheFactory(cacheType) {
818
+ return `import { z } from 'zod';
819
+ import type { CacheFactory } from '@dexto/agent-config';
820
+ import { MemoryCacheStore } from '@dexto/storage';
879
821
 
880
- The harness is automatically initialized when you import the image.\n`
881
- : '';
822
+ const ConfigSchema = z
823
+ .object({
824
+ type: z.literal('${cacheType}'),
825
+ })
826
+ .strict();
827
+
828
+ type ExampleCacheConfig = z.output<typeof ConfigSchema>;
829
+
830
+ /**
831
+ * Example cache factory
832
+ *
833
+ * Storage backends are resolved from image factories.
834
+ * The bundler auto-discovers this module when placed in storage/cache/<type>/index.ts.
835
+ */
836
+ export const factory: CacheFactory<ExampleCacheConfig> = {
837
+ configSchema: ConfigSchema,
838
+ create: (_config, _logger) => new MemoryCacheStore(),
839
+ };
840
+ `;
841
+ }
842
+ /**
843
+ * Generates an example in-memory database factory
844
+ */
845
+ export function generateExampleDatabaseFactory(databaseType) {
846
+ return `import { z } from 'zod';
847
+ import type { DatabaseFactory } from '@dexto/agent-config';
848
+ import { MemoryDatabaseStore } from '@dexto/storage';
849
+
850
+ const ConfigSchema = z
851
+ .object({
852
+ type: z.literal('${databaseType}'),
853
+ })
854
+ .strict();
855
+
856
+ type ExampleDatabaseConfig = z.output<typeof ConfigSchema>;
857
+
858
+ /**
859
+ * Example database factory
860
+ *
861
+ * Storage backends are resolved from image factories.
862
+ * The bundler auto-discovers this module when placed in storage/database/<type>/index.ts.
863
+ */
864
+ export const factory: DatabaseFactory<ExampleDatabaseConfig> = {
865
+ configSchema: ConfigSchema,
866
+ create: (_config, _logger) => new MemoryDatabaseStore(),
867
+ };
868
+ `;
869
+ }
870
+ /**
871
+ * Generates an example in-memory blob store factory
872
+ */
873
+ export function generateExampleBlobStoreFactory(blobType) {
874
+ return `import { z } from 'zod';
875
+ import type { BlobStoreFactory } from '@dexto/agent-config';
876
+ import { InMemoryBlobStoreSchema, MemoryBlobStore } from '@dexto/storage';
877
+
878
+ const ConfigSchema = InMemoryBlobStoreSchema.extend({
879
+ type: z.literal('${blobType}'),
880
+ }).strict();
881
+
882
+ type ExampleBlobStoreConfig = z.output<typeof ConfigSchema>;
883
+
884
+ /**
885
+ * Example blob store factory
886
+ *
887
+ * Blob stores are resolved from image factories.
888
+ * The bundler auto-discovers this module when placed in storage/blob/<type>/index.ts.
889
+ */
890
+ export const factory: BlobStoreFactory<ExampleBlobStoreConfig> = {
891
+ configSchema: ConfigSchema,
892
+ create: (config, logger) => {
893
+ const { type: _type, ...options } = config;
894
+ return new MemoryBlobStore(options, logger);
895
+ },
896
+ };
897
+ `;
898
+ }
899
+ /**
900
+ * Generates README for an app project
901
+ */
902
+ export function generateAppReadme(context) {
882
903
  return `# ${context.projectName}
883
904
 
884
- ${context.description}${imageSection}
905
+ ${context.description}
885
906
 
886
907
  ## Quick Start
887
908
 
@@ -903,8 +924,6 @@ pnpm start
903
924
  ${context.projectName}/
904
925
  ├── src/
905
926
  │ └── index.ts # Entry point
906
- ├── agents/
907
- │ └── default.yml # Agent configuration
908
927
  ├── .env # Environment variables (gitignored)
909
928
  ├── package.json
910
929
  └── tsconfig.json
@@ -912,178 +931,19 @@ ${context.projectName}/
912
931
 
913
932
  ## Configuration
914
933
 
915
- Edit \`agents/default.yml\` to configure:
916
- - System prompts
917
- - LLM provider and model
918
- - MCP servers
919
- - Internal tools
920
- - Custom tools
934
+ Edit \`src/index.ts\` to configure:
935
+ - System prompt
936
+ - LLM provider/model/API keys
937
+ - Storage backends
938
+ - Tools
939
+ - External tools via MCP (\`mcpServers\`)
940
+
941
+ By default this scaffold uses in-memory storage. To add persistence, swap in a file-backed
942
+ database and blob store (e.g. SQLite + local blobs).
921
943
 
922
944
  ## Learn More
923
945
 
924
946
  - [Dexto Documentation](https://docs.dexto.ai)
925
947
  - [Agent Configuration Guide](https://docs.dexto.ai/docs/guides/configuration)
926
- - [Using Images](https://docs.dexto.ai/docs/guides/images)
927
- `;
928
- }
929
- /**
930
- * Generates auto-discovery script for from-core mode
931
- */
932
- export function generateDiscoveryScript() {
933
- return `#!/usr/bin/env tsx
934
- /**
935
- * Provider Auto-Discovery Script
936
- *
937
- * Scans conventional folders (tools/, blob-store/, compression/, plugins/)
938
- * and generates src/providers.ts with import + registration statements.
939
- */
940
-
941
- import * as fs from 'fs/promises';
942
- import * as path from 'path';
943
- import { fileURLToPath } from 'url';
944
-
945
- const __filename = fileURLToPath(import.meta.url);
946
- const __dirname = path.dirname(__filename);
947
- const projectRoot = path.resolve(__dirname, '..');
948
-
949
- interface ProviderInfo {
950
- category: 'customTools' | 'blobStore' | 'compression' | 'plugins';
951
- folderName: string;
952
- path: string;
953
- registryName: string;
954
- }
955
-
956
- const PROVIDER_CATEGORIES = [
957
- { folder: 'tools', category: 'customTools' as const, registry: 'customToolRegistry' },
958
- { folder: 'blob-store', category: 'blobStore' as const, registry: 'blobStoreRegistry' },
959
- { folder: 'compaction', category: 'compaction' as const, registry: 'compactionRegistry' },
960
- { folder: 'plugins', category: 'plugins' as const, registry: 'pluginRegistry' },
961
- ];
962
-
963
- async function discoverProviders(): Promise<ProviderInfo[]> {
964
- const providers: ProviderInfo[] = [];
965
-
966
- for (const { folder, category, registry } of PROVIDER_CATEGORIES) {
967
- const folderPath = path.join(projectRoot, folder);
968
-
969
- try {
970
- const entries = await fs.readdir(folderPath, { withFileTypes: true });
971
-
972
- for (const entry of entries) {
973
- if (!entry.isDirectory()) continue;
974
- if (entry.name.startsWith('.')) continue;
975
-
976
- // Check if provider has index.ts
977
- const indexPath = path.join(folderPath, entry.name, 'index.ts');
978
- try {
979
- await fs.access(indexPath);
980
- providers.push({
981
- category,
982
- folderName: entry.name,
983
- path: \`../\${folder}/\${entry.name}/index.js\`,
984
- registryName: registry,
985
- });
986
- } catch {
987
- // No index.ts found, skip
988
- }
989
- }
990
- } catch {
991
- // Folder doesn't exist or can't be read, skip
992
- }
993
- }
994
-
995
- return providers;
996
- }
997
-
998
- function generateProvidersFile(providers: ProviderInfo[]): string {
999
- // Helper to convert kebab-case to camelCase for valid JS identifiers
1000
- const toCamelCase = (str: string): string => {
1001
- return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
1002
- };
1003
-
1004
- const imports: string[] = [];
1005
- const registrations: string[] = [];
1006
- const registries = new Set<string>();
1007
-
1008
- providers.forEach((provider, index) => {
1009
- const varName = \`provider\${index}\`;
1010
- const providerName = \`\${toCamelCase(provider.folderName)}Provider\`;
1011
- imports.push(\`import { \${providerName} as \${varName} } from '\${provider.path}';\`);
1012
- registrations.push(\` \${provider.registryName}.register(\${varName});\`);
1013
- registries.add(provider.registryName);
1014
- });
1015
-
1016
- const registryImports = Array.from(registries).join(', ');
1017
-
1018
- return \`// AUTO-GENERATED - DO NOT EDIT
1019
- // This file is generated by scripts/discover-providers.ts
1020
- // Run 'pnpm run discover' to regenerate
1021
-
1022
- import { \${registryImports} } from '@dexto/core';
1023
- \${imports.join('\\n')}
1024
-
1025
- /**
1026
- * Register all discovered providers
1027
- * Called automatically when this module is imported
1028
- */
1029
- export function registerProviders(): void {
1030
- \${registrations.join('\\n')}
1031
- }
1032
-
1033
- // Auto-register on import
1034
- registerProviders();
1035
-
1036
- console.log('✓ Registered \${providers.length} provider(s)');
1037
- \`;
1038
- }
1039
-
1040
- function generateEntryPoint(): string {
1041
- return \`// AUTO-GENERATED - DO NOT EDIT
1042
- // This file is the build entry point that wires everything together
1043
- // Run 'pnpm run discover' to regenerate
1044
-
1045
- // Register providers first
1046
- import './_providers.js';
1047
-
1048
- // Then run the user's app
1049
- import './index.js';
1050
- \`;
1051
- }
1052
-
1053
- async function main() {
1054
- console.log('🔍 Discovering providers...\\n');
1055
-
1056
- const providers = await discoverProviders();
1057
-
1058
- if (providers.length === 0) {
1059
- console.log('⚠️ No providers found');
1060
- console.log(' Add providers to: tools/, blob-store/, compression/, or plugins/\\n');
1061
- } else {
1062
- console.log(\`✅ Found \${providers.length} provider(s):\`);
1063
- providers.forEach(p => {
1064
- console.log(\` • \${p.category}/\${p.folderName}\`);
1065
- });
1066
- console.log();
1067
- }
1068
-
1069
- // Generate provider registrations
1070
- const providersPath = path.join(projectRoot, 'src', '_providers.ts');
1071
- const providersContent = generateProvidersFile(providers);
1072
- await fs.writeFile(providersPath, providersContent, 'utf-8');
1073
- console.log(\`📝 Generated: src/_providers.ts\`);
1074
-
1075
- // Generate build entry point
1076
- const entryPath = path.join(projectRoot, 'src', '_entry.ts');
1077
- const entryContent = generateEntryPoint();
1078
- await fs.writeFile(entryPath, entryContent, 'utf-8');
1079
- console.log(\`📝 Generated: src/_entry.ts\`);
1080
-
1081
- console.log();
1082
- }
1083
-
1084
- main().catch(error => {
1085
- console.error('❌ Discovery failed:', error);
1086
- process.exit(1);
1087
- });
1088
948
  `;
1089
949
  }