luca 3.0.0 → 3.0.2

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 (372) hide show
  1. package/.github/workflows/release.yaml +1 -0
  2. package/CLAUDE.md +10 -2
  3. package/README.md +130 -112
  4. package/assistants/codingAssistant/CORE.md +6 -1
  5. package/assistants/codingAssistant/hooks.ts +1 -1
  6. package/assistants/inkbot/hooks.ts +1 -1
  7. package/assistants/inkbot/tools.ts +1 -1
  8. package/bun.lock +220 -322
  9. package/commands/audit-docs.ts +2 -2
  10. package/commands/build-bootstrap.ts +2 -3
  11. package/commands/build-python-bridge.ts +2 -3
  12. package/commands/build-scaffolds.ts +2 -3
  13. package/commands/bundle-consumer-project.ts +521 -0
  14. package/commands/generate-api-docs.ts +2 -2
  15. package/commands/inkbot.ts +2 -2
  16. package/commands/release.ts +2 -2
  17. package/commands/try-all-challenges.ts +3 -3
  18. package/commands/try-challenge.ts +3 -3
  19. package/dist/agi/container.server.d.ts +2 -2
  20. package/dist/agi/features/assistant.d.ts +2 -2
  21. package/dist/agi/features/assistants-manager.d.ts +1 -1
  22. package/dist/agi/features/autonomous-assistant.d.ts +1 -1
  23. package/dist/agi/features/browser-use.d.ts +1 -1
  24. package/dist/agi/features/claude-code.d.ts +1 -1
  25. package/dist/agi/features/conversation-history.d.ts +2 -2
  26. package/dist/agi/features/conversation.d.ts +1 -1
  27. package/dist/agi/features/docs-reader.d.ts +1 -1
  28. package/dist/agi/features/file-tools.d.ts +1 -1
  29. package/dist/agi/features/luca-coder.d.ts +1 -1
  30. package/dist/agi/features/openai-codex.d.ts +1 -1
  31. package/dist/agi/features/skills-library.d.ts +1 -1
  32. package/dist/clients/civitai/index.d.ts +4 -4
  33. package/dist/clients/client-template.d.ts +4 -4
  34. package/dist/clients/comfyui/index.d.ts +2 -2
  35. package/dist/clients/elevenlabs/index.d.ts +2 -2
  36. package/dist/clients/openai/index.d.ts +2 -2
  37. package/dist/clients/supabase/index.d.ts +3 -3
  38. package/dist/command.d.ts +1 -1
  39. package/dist/node/container.d.ts +1 -1
  40. package/dist/node/features/helpers.d.ts +3 -3
  41. package/dist/node/features/semantic-search.d.ts +1 -1
  42. package/dist/node/features/vm.d.ts +3 -3
  43. package/dist/node.d.ts +1 -1
  44. package/dist/scaffolds/generated.d.ts +1 -1
  45. package/dist/selector.d.ts +1 -1
  46. package/index.html +217 -190
  47. package/luca.console.ts +1 -1
  48. package/package.json +2 -2
  49. package/public/index.html +217 -190
  50. package/public/slides-ai-native.html +1 -1
  51. package/public/slides-intro.html +2 -2
  52. package/scripts/examples/ask-luca-expert.ts +1 -1
  53. package/scripts/examples/assistant-questions.ts +1 -1
  54. package/scripts/examples/excalidraw-expert.ts +1 -1
  55. package/scripts/examples/file-manager.ts +1 -1
  56. package/scripts/examples/ideas.ts +1 -1
  57. package/scripts/examples/interactive-chat.ts +1 -1
  58. package/scripts/examples/opening-a-web-browser.ts +1 -1
  59. package/scripts/examples/telegram-bot.ts +1 -1
  60. package/scripts/examples/using-assistant-with-mcp.ts +1 -1
  61. package/scripts/examples/using-claude-code.ts +1 -1
  62. package/scripts/examples/using-contentdb.ts +2 -2
  63. package/scripts/examples/using-conversations.ts +1 -1
  64. package/scripts/examples/using-disk-cache.ts +1 -1
  65. package/scripts/examples/using-docker-shell.ts +1 -1
  66. package/scripts/examples/using-elevenlabs.ts +1 -1
  67. package/scripts/examples/using-google-calendar.ts +1 -1
  68. package/scripts/examples/using-google-docs.ts +1 -1
  69. package/scripts/examples/using-google-drive.ts +1 -1
  70. package/scripts/examples/using-google-sheets.ts +1 -1
  71. package/scripts/examples/using-nlp.ts +1 -1
  72. package/scripts/examples/using-ollama.ts +1 -1
  73. package/scripts/examples/using-postgres.ts +1 -1
  74. package/scripts/examples/using-runpod.ts +1 -1
  75. package/scripts/examples/using-tts.ts +1 -1
  76. package/scripts/scaffold.ts +5 -5
  77. package/scripts/scratch.ts +1 -1
  78. package/scripts/test-assistant-hooks.ts +1 -1
  79. package/scripts/test-docs-reader.ts +1 -1
  80. package/src/agi/container.server.ts +6 -2
  81. package/src/agi/features/agent-memory.ts +25 -25
  82. package/src/agi/features/assistant.ts +34 -5
  83. package/src/agi/features/assistants-manager.ts +122 -6
  84. package/src/agi/features/autonomous-assistant.ts +1 -1
  85. package/src/agi/features/browser-use.ts +20 -1
  86. package/src/agi/features/claude-code.ts +51 -5
  87. package/src/agi/features/coding-tools.ts +1 -1
  88. package/src/agi/features/conversation-history.ts +181 -4
  89. package/src/agi/features/conversation.ts +186 -15
  90. package/src/agi/features/docs-reader.ts +2 -2
  91. package/src/agi/features/file-tools.ts +49 -2
  92. package/src/agi/features/luca-coder.ts +7 -5
  93. package/src/agi/features/mcp-bridge.ts +532 -0
  94. package/src/agi/features/openai-codex.ts +2 -2
  95. package/src/agi/features/skills-library.ts +131 -52
  96. package/src/agi/lib/token-counter.ts +80 -0
  97. package/src/bootstrap/generated.ts +56 -57
  98. package/src/browser.ts +1 -1
  99. package/src/cli/build-info.ts +2 -2
  100. package/src/cli/cli.ts +2 -2
  101. package/src/clients/civitai/index.ts +5 -5
  102. package/src/clients/client-template.ts +4 -4
  103. package/src/clients/comfyui/index.ts +4 -4
  104. package/src/clients/elevenlabs/index.ts +4 -4
  105. package/src/clients/openai/index.ts +7 -7
  106. package/src/clients/supabase/index.ts +4 -4
  107. package/src/clients/voicebox/index.ts +4 -4
  108. package/src/command.ts +2 -1
  109. package/src/commands/chat.ts +1 -0
  110. package/src/commands/eval.ts +2 -56
  111. package/src/commands/introspect.ts +1 -1
  112. package/src/commands/prompt.ts +41 -9
  113. package/src/container-describer.ts +8 -1
  114. package/src/container.ts +13 -0
  115. package/src/entity.ts +2 -2
  116. package/src/helper.ts +1 -1
  117. package/src/introspection/generated.agi.ts +28563 -27571
  118. package/src/introspection/generated.node.ts +20281 -20194
  119. package/src/introspection/generated.web.ts +605 -584
  120. package/src/introspection/scan.ts +11 -6
  121. package/src/node/container.ts +1 -1
  122. package/src/node/features/content-db.ts +39 -2
  123. package/src/node/features/display-result.ts +57 -0
  124. package/src/node/features/helpers.ts +42 -15
  125. package/src/node/features/python.ts +25 -19
  126. package/src/node/features/repl.ts +1 -1
  127. package/src/node/features/secure-shell.ts +11 -17
  128. package/src/node/features/semantic-search.ts +2 -2
  129. package/src/node/features/transpiler.ts +2 -3
  130. package/src/node/features/ui.ts +5 -0
  131. package/src/node/features/vm.ts +3 -3
  132. package/src/node.ts +3 -3
  133. package/src/python/generated.ts +0 -1
  134. package/src/scaffolds/generated.ts +82 -83
  135. package/src/selector.ts +1 -1
  136. package/src/servers/express.ts +1 -1
  137. package/src/web/features/helpers.ts +22 -0
  138. package/tsconfig.json +12 -12
  139. package/docs/CLI.md +0 -335
  140. package/docs/CNAME +0 -1
  141. package/docs/README.md +0 -60
  142. package/docs/TABLE-OF-CONTENTS.md +0 -183
  143. package/docs/apis/clients/elevenlabs.md +0 -308
  144. package/docs/apis/clients/graph.md +0 -107
  145. package/docs/apis/clients/openai.md +0 -429
  146. package/docs/apis/clients/rest.md +0 -161
  147. package/docs/apis/clients/websocket.md +0 -174
  148. package/docs/apis/features/agi/assistant.md +0 -625
  149. package/docs/apis/features/agi/assistants-manager.md +0 -282
  150. package/docs/apis/features/agi/auto-assistant.md +0 -279
  151. package/docs/apis/features/agi/browser-use.md +0 -802
  152. package/docs/apis/features/agi/claude-code.md +0 -884
  153. package/docs/apis/features/agi/conversation-history.md +0 -364
  154. package/docs/apis/features/agi/conversation.md +0 -548
  155. package/docs/apis/features/agi/docs-reader.md +0 -99
  156. package/docs/apis/features/agi/file-tools.md +0 -163
  157. package/docs/apis/features/agi/luca-coder.md +0 -407
  158. package/docs/apis/features/agi/openai-codex.md +0 -396
  159. package/docs/apis/features/agi/openapi.md +0 -138
  160. package/docs/apis/features/agi/semantic-search.md +0 -387
  161. package/docs/apis/features/agi/skills-library.md +0 -239
  162. package/docs/apis/features/node/container-link.md +0 -192
  163. package/docs/apis/features/node/content-db.md +0 -450
  164. package/docs/apis/features/node/disk-cache.md +0 -379
  165. package/docs/apis/features/node/dns.md +0 -652
  166. package/docs/apis/features/node/docker.md +0 -706
  167. package/docs/apis/features/node/downloader.md +0 -81
  168. package/docs/apis/features/node/esbuild.md +0 -60
  169. package/docs/apis/features/node/file-manager.md +0 -191
  170. package/docs/apis/features/node/fs.md +0 -1217
  171. package/docs/apis/features/node/git.md +0 -371
  172. package/docs/apis/features/node/google-auth.md +0 -193
  173. package/docs/apis/features/node/google-calendar.md +0 -202
  174. package/docs/apis/features/node/google-docs.md +0 -173
  175. package/docs/apis/features/node/google-drive.md +0 -246
  176. package/docs/apis/features/node/google-mail.md +0 -214
  177. package/docs/apis/features/node/google-sheets.md +0 -194
  178. package/docs/apis/features/node/grep.md +0 -292
  179. package/docs/apis/features/node/helpers.md +0 -164
  180. package/docs/apis/features/node/ink.md +0 -334
  181. package/docs/apis/features/node/ipc-socket.md +0 -249
  182. package/docs/apis/features/node/json-tree.md +0 -86
  183. package/docs/apis/features/node/networking.md +0 -316
  184. package/docs/apis/features/node/nlp.md +0 -133
  185. package/docs/apis/features/node/opener.md +0 -97
  186. package/docs/apis/features/node/os.md +0 -146
  187. package/docs/apis/features/node/package-finder.md +0 -392
  188. package/docs/apis/features/node/postgres.md +0 -234
  189. package/docs/apis/features/node/proc.md +0 -399
  190. package/docs/apis/features/node/process-manager.md +0 -305
  191. package/docs/apis/features/node/python.md +0 -604
  192. package/docs/apis/features/node/redis.md +0 -380
  193. package/docs/apis/features/node/repl.md +0 -88
  194. package/docs/apis/features/node/runpod.md +0 -674
  195. package/docs/apis/features/node/secure-shell.md +0 -176
  196. package/docs/apis/features/node/semantic-search.md +0 -408
  197. package/docs/apis/features/node/sqlite.md +0 -233
  198. package/docs/apis/features/node/telegram.md +0 -279
  199. package/docs/apis/features/node/transpiler.md +0 -74
  200. package/docs/apis/features/node/tts.md +0 -133
  201. package/docs/apis/features/node/ui.md +0 -701
  202. package/docs/apis/features/node/vault.md +0 -59
  203. package/docs/apis/features/node/vm.md +0 -75
  204. package/docs/apis/features/node/yaml-tree.md +0 -85
  205. package/docs/apis/features/node/yaml.md +0 -176
  206. package/docs/apis/features/web/asset-loader.md +0 -59
  207. package/docs/apis/features/web/container-link.md +0 -192
  208. package/docs/apis/features/web/esbuild.md +0 -54
  209. package/docs/apis/features/web/helpers.md +0 -164
  210. package/docs/apis/features/web/network.md +0 -44
  211. package/docs/apis/features/web/speech.md +0 -69
  212. package/docs/apis/features/web/vault.md +0 -59
  213. package/docs/apis/features/web/vm.md +0 -75
  214. package/docs/apis/features/web/voice.md +0 -84
  215. package/docs/apis/servers/express.md +0 -171
  216. package/docs/apis/servers/mcp.md +0 -238
  217. package/docs/apis/servers/websocket.md +0 -170
  218. package/docs/bootstrap/CLAUDE.md +0 -101
  219. package/docs/bootstrap/SKILL.md +0 -341
  220. package/docs/bootstrap/templates/about-command.ts +0 -41
  221. package/docs/bootstrap/templates/docs-models.ts +0 -22
  222. package/docs/bootstrap/templates/docs-readme.md +0 -43
  223. package/docs/bootstrap/templates/example-feature.ts +0 -53
  224. package/docs/bootstrap/templates/health-endpoint.ts +0 -15
  225. package/docs/bootstrap/templates/luca-cli.ts +0 -30
  226. package/docs/bootstrap/templates/runme.md +0 -54
  227. package/docs/challenges/caching-proxy.md +0 -16
  228. package/docs/challenges/content-db-round-trip.md +0 -14
  229. package/docs/challenges/custom-command.md +0 -9
  230. package/docs/challenges/file-watcher-pipeline.md +0 -11
  231. package/docs/challenges/grep-audit-report.md +0 -15
  232. package/docs/challenges/multi-feature-dashboard.md +0 -14
  233. package/docs/challenges/process-orchestrator.md +0 -17
  234. package/docs/challenges/rest-api-server-with-client.md +0 -12
  235. package/docs/challenges/script-runner-with-vm.md +0 -11
  236. package/docs/challenges/simple-rest-api.md +0 -15
  237. package/docs/challenges/websocket-serve-and-client.md +0 -11
  238. package/docs/challenges/yaml-config-system.md +0 -14
  239. package/docs/command-system-overhaul.md +0 -94
  240. package/docs/documentation-audit.md +0 -134
  241. package/docs/examples/assistant/CORE.md +0 -18
  242. package/docs/examples/assistant/hooks.ts +0 -3
  243. package/docs/examples/assistant/tools.ts +0 -10
  244. package/docs/examples/assistant-hooks-reference.ts +0 -171
  245. package/docs/examples/assistant-with-process-manager.md +0 -84
  246. package/docs/examples/content-db.md +0 -77
  247. package/docs/examples/disk-cache.md +0 -83
  248. package/docs/examples/docker.md +0 -101
  249. package/docs/examples/downloader.md +0 -70
  250. package/docs/examples/entity.md +0 -124
  251. package/docs/examples/esbuild.md +0 -80
  252. package/docs/examples/feature-as-tool-provider.md +0 -143
  253. package/docs/examples/file-manager.md +0 -82
  254. package/docs/examples/fs.md +0 -83
  255. package/docs/examples/git.md +0 -85
  256. package/docs/examples/google-auth.md +0 -88
  257. package/docs/examples/google-calendar.md +0 -94
  258. package/docs/examples/google-docs.md +0 -82
  259. package/docs/examples/google-drive.md +0 -96
  260. package/docs/examples/google-sheets.md +0 -95
  261. package/docs/examples/grep.md +0 -85
  262. package/docs/examples/ink-blocks.md +0 -75
  263. package/docs/examples/ink-renderer.md +0 -41
  264. package/docs/examples/ink.md +0 -103
  265. package/docs/examples/ipc-socket.md +0 -103
  266. package/docs/examples/json-tree.md +0 -91
  267. package/docs/examples/networking.md +0 -58
  268. package/docs/examples/nlp.md +0 -91
  269. package/docs/examples/opener.md +0 -78
  270. package/docs/examples/os.md +0 -72
  271. package/docs/examples/package-finder.md +0 -89
  272. package/docs/examples/postgres.md +0 -91
  273. package/docs/examples/proc.md +0 -81
  274. package/docs/examples/process-manager.md +0 -79
  275. package/docs/examples/python.md +0 -132
  276. package/docs/examples/repl.md +0 -93
  277. package/docs/examples/runpod.md +0 -119
  278. package/docs/examples/secure-shell.md +0 -92
  279. package/docs/examples/sqlite.md +0 -86
  280. package/docs/examples/structured-output-with-assistants.md +0 -144
  281. package/docs/examples/telegram.md +0 -77
  282. package/docs/examples/tts.md +0 -86
  283. package/docs/examples/ui.md +0 -80
  284. package/docs/examples/vault.md +0 -70
  285. package/docs/examples/vm.md +0 -86
  286. package/docs/examples/websocket-ask-and-reply-example.md +0 -128
  287. package/docs/examples/yaml-tree.md +0 -93
  288. package/docs/examples/yaml.md +0 -104
  289. package/docs/ideas/assistant-factory-pattern.md +0 -142
  290. package/docs/in-memory-fs.md +0 -4
  291. package/docs/introspection-audit.md +0 -49
  292. package/docs/introspection.md +0 -164
  293. package/docs/mcp/readme.md +0 -162
  294. package/docs/models.ts +0 -41
  295. package/docs/philosophy.md +0 -86
  296. package/docs/principles.md +0 -7
  297. package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +0 -34
  298. package/docs/prompts/check-for-undocumented-features.md +0 -27
  299. package/docs/prompts/mcp-test-easy-command.md +0 -27
  300. package/docs/scaffolds/client.md +0 -149
  301. package/docs/scaffolds/command.md +0 -120
  302. package/docs/scaffolds/endpoint.md +0 -171
  303. package/docs/scaffolds/feature.md +0 -158
  304. package/docs/scaffolds/selector.md +0 -91
  305. package/docs/scaffolds/server.md +0 -196
  306. package/docs/selectors.md +0 -115
  307. package/docs/sessions/custom-command/attempt-log-2.md +0 -195
  308. package/docs/sessions/file-watcher-pipeline/attempt-log-1.md +0 -728
  309. package/docs/sessions/file-watcher-pipeline/attempt-log-2.md +0 -555
  310. package/docs/sessions/grep-audit-report/attempt-log-1.md +0 -289
  311. package/docs/sessions/multi-feature-dashboard/attempt-log-2.md +0 -679
  312. package/docs/sessions/rest-api-server-with-client/attempt-log-1.md +0 -1
  313. package/docs/sessions/rest-api-server-with-client/attempt-log-3.md +0 -920
  314. package/docs/sessions/simple-rest-api/attempt-log-1.md +0 -593
  315. package/docs/sessions/websocket-serve-and-client/attempt-log-2.md +0 -995
  316. package/docs/tutorials/00-bootstrap.md +0 -166
  317. package/docs/tutorials/01-getting-started.md +0 -106
  318. package/docs/tutorials/02-container.md +0 -210
  319. package/docs/tutorials/03-scripts.md +0 -194
  320. package/docs/tutorials/04-features-overview.md +0 -196
  321. package/docs/tutorials/05-state-and-events.md +0 -171
  322. package/docs/tutorials/06-servers.md +0 -157
  323. package/docs/tutorials/07-endpoints.md +0 -198
  324. package/docs/tutorials/08-commands.md +0 -252
  325. package/docs/tutorials/09-clients.md +0 -162
  326. package/docs/tutorials/10-creating-features.md +0 -203
  327. package/docs/tutorials/11-contentbase.md +0 -191
  328. package/docs/tutorials/12-assistants.md +0 -215
  329. package/docs/tutorials/13-introspection.md +0 -157
  330. package/docs/tutorials/14-type-system.md +0 -174
  331. package/docs/tutorials/15-project-patterns.md +0 -222
  332. package/docs/tutorials/16-google-features.md +0 -534
  333. package/docs/tutorials/17-tui-blocks.md +0 -530
  334. package/docs/tutorials/18-semantic-search.md +0 -334
  335. package/docs/tutorials/19-python-sessions.md +0 -401
  336. package/docs/tutorials/20-browser-esm.md +0 -234
  337. package/src/agi/endpoints/ask.ts +0 -60
  338. package/src/agi/endpoints/conversations/[id].ts +0 -45
  339. package/src/agi/endpoints/conversations.ts +0 -31
  340. package/src/agi/endpoints/experts.ts +0 -37
  341. package/test/assistant-hooks.test.ts +0 -306
  342. package/test/assistant.test.ts +0 -81
  343. package/test/bus.test.ts +0 -134
  344. package/test/clients-servers.test.ts +0 -217
  345. package/test/command.test.ts +0 -267
  346. package/test/container-link.test.ts +0 -274
  347. package/test/conversation.test.ts +0 -220
  348. package/test/features.test.ts +0 -160
  349. package/test/fork-and-research.test.ts +0 -450
  350. package/test/integration.test.ts +0 -787
  351. package/test/interceptor-chain.test.ts +0 -61
  352. package/test/node-container.test.ts +0 -121
  353. package/test/python-session.test.ts +0 -105
  354. package/test/rate-limit.test.ts +0 -272
  355. package/test/semantic-search.test.ts +0 -550
  356. package/test/state.test.ts +0 -121
  357. package/test/vm-context.test.ts +0 -146
  358. package/test/vm-loadmodule.test.ts +0 -213
  359. package/test/websocket-ask.test.ts +0 -101
  360. package/test-integration/assistant.test.ts +0 -138
  361. package/test-integration/assistants-manager.test.ts +0 -113
  362. package/test-integration/claude-code.test.ts +0 -98
  363. package/test-integration/conversation-history.test.ts +0 -205
  364. package/test-integration/conversation.test.ts +0 -137
  365. package/test-integration/elevenlabs.test.ts +0 -55
  366. package/test-integration/google-services.test.ts +0 -80
  367. package/test-integration/helpers.ts +0 -89
  368. package/test-integration/memory.test.ts +0 -204
  369. package/test-integration/openai-codex.test.ts +0 -93
  370. package/test-integration/runpod.test.ts +0 -58
  371. package/test-integration/server-endpoints.test.ts +0 -97
  372. package/test-integration/telegram.test.ts +0 -46
@@ -135,9 +135,10 @@ export class IntrospectionScannerFeature extends Feature<IntrospectionScannerSta
135
135
  }
136
136
 
137
137
  const pattern = path.join(srcPath, '**/*.ts');
138
- return await glob(pattern, {
138
+ const files = await glob(pattern, {
139
139
  ignore: ['**/*.d.ts', '**/node_modules/**']
140
140
  });
141
+ return files.sort();
141
142
  }
142
143
 
143
144
  private async analyzeFile(filePath: string): Promise<{ helpers: HelperIntrospection[], containers: Partial<ContainerIntrospection>[] }> {
@@ -1099,23 +1100,27 @@ export class IntrospectionScannerFeature extends Feature<IntrospectionScannerSta
1099
1100
  }
1100
1101
  imports += ` } from '${importSource}';\n\n`;
1101
1102
 
1102
- const registrations = results.map(result => {
1103
+ // Sort by id/className for deterministic output across runs
1104
+ const sortedResults = [...results].sort((a, b) => a.id.localeCompare(b.id));
1105
+ const sortedContainers = [...containerResults].sort((a, b) => (a.className || '').localeCompare(b.className || ''));
1106
+
1107
+ const registrations = sortedResults.map(result => {
1103
1108
  const data = JSON.stringify(result, null, 2);
1104
1109
  return `setBuildTimeData('${result.id}', ${data});`;
1105
1110
  }).join('\n\n');
1106
1111
 
1107
1112
  let containerRegistrations = '';
1108
1113
  if (hasContainers) {
1109
- containerRegistrations = '\n\n// Container introspection data\n' + containerResults.map(result => {
1114
+ containerRegistrations = '\n\n// Container introspection data\n' + sortedContainers.map(result => {
1110
1115
  const data = JSON.stringify(result, null, 2);
1111
1116
  return `setContainerBuildTimeData('${result.className}', ${data});`;
1112
1117
  }).join('\n\n');
1113
1118
  }
1114
1119
 
1115
- const exportStatement = `\nexport const introspectionData = ${JSON.stringify(results, null, 2)};\n`;
1116
- const containerExport = hasContainers ? `\nexport const containerIntrospectionData = ${JSON.stringify(containerResults, null, 2)};\n` : '';
1120
+ const exportStatement = `\nexport const introspectionData = ${JSON.stringify(sortedResults, null, 2)};\n`;
1121
+ const containerExport = hasContainers ? `\nexport const containerIntrospectionData = ${JSON.stringify(sortedContainers, null, 2)};\n` : '';
1117
1122
 
1118
- return `${imports}// Auto-generated introspection registry data\n// Generated at: ${new Date().toISOString()}\n\n${registrations}${containerRegistrations}${exportStatement}${containerExport}`;
1123
+ return `${imports}// Auto-generated introspection registry data\n\n${registrations}${containerRegistrations}${exportStatement}${containerExport}`;
1119
1124
  }
1120
1125
  }
1121
1126
 
@@ -240,7 +240,7 @@ export interface NodeContainerState extends ContainerState {
240
240
  *
241
241
  * @example
242
242
  * ```ts
243
- * import container from '@soederpop/luca/node'
243
+ * import container from 'luca/node'
244
244
  *
245
245
  * // File operations
246
246
  * const content = container.fs.readFile('README.md')
@@ -1,6 +1,6 @@
1
1
  import { Feature } from '../feature.js'
2
2
  import * as contentbaseExports from 'contentbase'
3
- import { parse, Collection, extractSections, type ModelDefinition } from 'contentbase'
3
+ import { parse, Collection, Document, extractSections, type ModelDefinition } from 'contentbase'
4
4
  import { z } from 'zod'
5
5
  import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
6
6
  import { realpathSync } from 'node:fs'
@@ -184,7 +184,7 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
184
184
 
185
185
  const vm = this.container.feature('vm') as any
186
186
 
187
- // Seed luca modules first (helpers does this for @soederpop/luca)
187
+ // Seed luca modules first (helpers does this for luca)
188
188
  const helpers = this.container.feature('helpers') as any
189
189
  if (helpers?.seedVirtualModules) {
190
190
  helpers.seedVirtualModules()
@@ -300,6 +300,43 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
300
300
  return parse(path)
301
301
  }
302
302
 
303
+ /**
304
+ * Get a document object by collection ID, file path, or inline markdown string.
305
+ * Exactly one of `id`, `path`, or `content` must be provided.
306
+ *
307
+ * @param options.id - Collection document ID (e.g. `'guides/intro'`); auto-loads the collection if needed
308
+ * @param options.path - Absolute or relative path to a markdown file on disk
309
+ * @param options.content - Raw markdown string; returned as an in-memory Document
310
+ * @returns The Document instance
311
+ * @example
312
+ * ```typescript
313
+ * // By collection document ID
314
+ * const doc = await contentDb.document({ id: 'guides/intro' })
315
+ *
316
+ * // By file path
317
+ * const doc = await contentDb.document({ path: '/absolute/path/to/file.md' })
318
+ *
319
+ * // In-memory from a markdown string
320
+ * const doc = contentDb.document({ content: '# Hello\n\nworld' })
321
+ * ```
322
+ */
323
+ async document(options: { id: string; path?: never; content?: never } | { path: string; id?: never; content?: never } | { content: string; id?: never; path?: never }): Promise<Document> {
324
+ if ('content' in options && options.content != null) {
325
+ return new Document({ content: options.content, path: '/virtual/document.md' })
326
+ }
327
+
328
+ if ('path' in options && options.path != null) {
329
+ return parse(options.path) as unknown as Document
330
+ }
331
+
332
+ if ('id' in options && options.id != null) {
333
+ if (!this.isLoaded) await this.load()
334
+ return this.collection.document(options.id) as unknown as Document
335
+ }
336
+
337
+ throw new Error('document() requires exactly one of: id, path, or content')
338
+ }
339
+
303
340
  /**
304
341
  * Load the collection, discovering models from models.ts and parsing all documents.
305
342
  *
@@ -0,0 +1,57 @@
1
+ import { inspect } from 'util'
2
+
3
+ const BUILTIN_TYPES = new Set(['Object', 'Array', 'Map', 'Set', 'Date', 'RegExp', 'Promise', 'Error', 'Number', 'String', 'Boolean'])
4
+
5
+ export function displayResult(value: any) {
6
+ if (typeof value !== 'object' || value === null) {
7
+ console.log(value)
8
+ return
9
+ }
10
+
11
+ const hasCustomInspect = typeof value[Symbol.for('nodejs.util.inspect.custom')] === 'function'
12
+ const ctorName = value.constructor?.name
13
+ const isClassInstance = ctorName && !BUILTIN_TYPES.has(ctorName)
14
+
15
+ // Objects with custom inspect or builtins: use standard inspect
16
+ if (hasCustomInspect || !isClassInstance) {
17
+ console.log(inspect(value, { colors: true, depth: 4 }))
18
+ return
19
+ }
20
+
21
+ // Class instances: show clean data (no _ props, no functions)
22
+ const data: Record<string, any> = {}
23
+ for (const [k, v] of Object.entries(value)) {
24
+ if (k.startsWith('_') || typeof v === 'function') continue
25
+ data[k] = v
26
+ }
27
+ const body = inspect(data, { colors: true, depth: 3 })
28
+ console.log(`${ctorName} ${body}`)
29
+
30
+ // Collect methods and getters from own + prototype chain
31
+ const methods: string[] = []
32
+ const getters: string[] = []
33
+
34
+ for (const [k, v] of Object.entries(value)) {
35
+ if (k.startsWith('_')) continue
36
+ if (typeof v === 'function') methods.push(k)
37
+ }
38
+
39
+ let proto = Object.getPrototypeOf(value)
40
+ while (proto && proto !== Object.prototype) {
41
+ for (const k of Object.getOwnPropertyNames(proto)) {
42
+ if (k === 'constructor' || k.startsWith('_')) continue
43
+ const desc = Object.getOwnPropertyDescriptor(proto, k)
44
+ if (!desc) continue
45
+ if (desc.get && !getters.includes(k)) getters.push(k)
46
+ else if (typeof desc.value === 'function' && !methods.includes(k)) methods.push(k)
47
+ }
48
+ proto = Object.getPrototypeOf(proto)
49
+ }
50
+
51
+ if (getters.length || methods.length) {
52
+ const parts: string[] = []
53
+ if (getters.length) parts.push(` \x1b[36mgetters:\x1b[0m ${getters.sort().join(', ')}`)
54
+ if (methods.length) parts.push(` \x1b[36mmethods:\x1b[0m ${methods.sort().map(m => m + '()').join(', ')}`)
55
+ console.log(parts.join('\n'))
56
+ }
57
+ }
@@ -3,6 +3,8 @@ import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '.
3
3
  import { Feature } from '../feature.js'
4
4
  import { Feature as UniversalFeature } from '../../feature.js'
5
5
  import { Client, clients } from '../../client.js'
6
+ import { allHelperInstances } from '../../container.js'
7
+ import type { Helper } from '../../helper.js'
6
8
  import { RestClient } from '../../clients/rest.js'
7
9
  import { GraphClient } from '../../clients/graph.js'
8
10
  import { WebSocketClient } from '../../clients/websocket.js'
@@ -108,14 +110,14 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
108
110
 
109
111
  /**
110
112
  * Whether to use native `import()` for loading project helpers.
111
- * True only if `@soederpop/luca` is actually resolvable in `node_modules`.
113
+ * True only if `luca` is actually resolvable in `node_modules`.
112
114
  * Warns when `node_modules` exists but the package is missing.
113
115
  */
114
116
  get useNativeImport(): boolean {
115
117
  const hasNodeModules = existsSync(resolve(this.rootDir, 'node_modules'))
116
118
  const hasLuca = hasNodeModules && existsSync(resolve(this.rootDir, 'node_modules', '@soederpop', 'luca'))
117
119
 
118
- // VM bundling handles missing @soederpop/luca gracefully — no warning needed
120
+ // VM bundling handles missing luca gracefully — no warning needed
119
121
 
120
122
  return hasLuca
121
123
  }
@@ -126,7 +128,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
126
128
 
127
129
  /**
128
130
  * Seeds the VM feature with virtual modules so that project-level files
129
- * can `import` / `require('@soederpop/luca')`, `zod`, etc. without
131
+ * can `import` / `require('luca')`, `zod`, etc. without
130
132
  * needing them in `node_modules`.
131
133
  *
132
134
  * Called automatically when `useNativeImport` is false.
@@ -138,7 +140,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
138
140
 
139
141
  const vm = this.container.feature('vm') as unknown as VM
140
142
 
141
- // Provide the full @soederpop/luca barrel — everything node.ts exports
143
+ // Provide the full luca barrel — everything node.ts exports
142
144
  // We build the exports object from the already-loaded modules in memory
143
145
  const lucaExports: Record<string, any> = {
144
146
  // Core classes
@@ -208,22 +210,42 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
208
210
  schemasModule.FeatureEventsSchema = FeatureEventsSchema
209
211
  }
210
212
 
211
- vm.defineModule('@soederpop/luca', lucaExports)
212
- vm.defineModule('@soederpop/luca/schemas', schemasModule)
213
- vm.defineModule('@soederpop/luca/node', lucaExports)
213
+ vm.defineModule('luca', lucaExports)
214
+ vm.defineModule('luca/schemas', schemasModule)
215
+ vm.defineModule('luca/node', lucaExports)
214
216
 
215
217
  // Deep import paths AIs and developers might reach for
216
- vm.defineModule('@soederpop/luca/client', { Client, ClientsRegistry: clients.constructor, default: Client })
217
- vm.defineModule('@soederpop/luca/server', { Server, ServersRegistry: servers.constructor, default: Server })
218
- vm.defineModule('@soederpop/luca/clients/rest', { RestClient, default: RestClient })
219
- vm.defineModule('@soederpop/luca/clients/graph', { GraphClient, default: GraphClient })
220
- vm.defineModule('@soederpop/luca/clients/websocket', { WebSocketClient, default: WebSocketClient })
221
- vm.defineModule('@soederpop/luca/servers/express', { ExpressServer, default: ExpressServer })
222
- vm.defineModule('@soederpop/luca/servers/socket', { WebsocketServer, default: WebsocketServer })
218
+ vm.defineModule('luca/client', { Client, ClientsRegistry: clients.constructor, default: Client })
219
+ vm.defineModule('luca/server', { Server, ServersRegistry: servers.constructor, default: Server })
220
+ vm.defineModule('luca/clients/rest', { RestClient, default: RestClient })
221
+ vm.defineModule('luca/clients/graph', { GraphClient, default: GraphClient })
222
+ vm.defineModule('luca/clients/websocket', { WebSocketClient, default: WebSocketClient })
223
+ vm.defineModule('luca/servers/express', { ExpressServer, default: ExpressServer })
224
+ vm.defineModule('luca/servers/socket', { WebsocketServer, default: WebsocketServer })
223
225
 
224
226
  vm.defineModule('zod', { z, default: { z } })
225
227
  }
226
228
 
229
+ /**
230
+ * Returns all instantiated helper instances across all types, optionally filtered by class.
231
+ *
232
+ * @param FilterClass - When provided, only instances of this class are returned.
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * // All instances of any type
237
+ * container.helpers.getInstances()
238
+ *
239
+ * // All Assistant instances
240
+ * const assistants = container.helpers.getInstances(Assistant)
241
+ * ```
242
+ */
243
+ getInstances(): Helper[]
244
+ getInstances<T extends Helper>(FilterClass: new (...args: any[]) => T): T[]
245
+ getInstances<T extends Helper>(FilterClass?: new (...args: any[]) => T): Helper[] | T[] {
246
+ return FilterClass ? allHelperInstances(FilterClass) : allHelperInstances()
247
+ }
248
+
227
249
  /**
228
250
  * Returns a unified view of all available helpers across all registries.
229
251
  * Each key is a registry type, each value is the list of helper names in that registry.
@@ -458,7 +480,11 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
458
480
  try {
459
481
  const fm = await this.ensureFileManager()
460
482
  const absPatterns = [`${dir}/*.ts`, `${dir}/**/*.ts`]
461
- const relPatterns = [`${type}/*.ts`, `${type}/**/*.ts`]
483
+ // Only use relative patterns when rootDir matches the container cwd,
484
+ // otherwise the fileManager (rooted in cwd) returns files from the
485
+ // wrong project which then get resolved against this.rootDir.
486
+ const useRelative = this.rootDir === this.container.cwd
487
+ const relPatterns = useRelative ? [`${type}/*.ts`, `${type}/**/*.ts`] : []
462
488
  const matched = fm.match([...absPatterns, ...relPatterns])
463
489
  files = matched.map((f: string) => f.startsWith('/') ? f : resolve(this.rootDir, f))
464
490
  } catch {}
@@ -608,6 +634,7 @@ export class Helpers extends Feature<HelpersState, HelpersOptions> {
608
634
  const Grafted = graftModule(Command as any, {
609
635
  description: commandModule.description,
610
636
  argsSchema: commandModule.argsSchema,
637
+ positionals: commandModule.positionals ?? mod.positionals,
611
638
  handler: commandModule.handler,
612
639
  }, name, 'commands')
613
640
  commands.register(name, Grafted as any)
@@ -1,8 +1,6 @@
1
1
  import { z } from 'zod'
2
2
  import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
3
3
  import { Feature } from "../feature.js";
4
- import { existsSync } from 'fs';
5
- import { join, resolve } from 'path';
6
4
  import { tmpdir } from 'os';
7
5
  import { bridgeScript } from '../../python/generated.js';
8
6
  import type { ChildProcess } from 'child_process';
@@ -161,7 +159,7 @@ export class Python<
161
159
 
162
160
  // Setup project directory
163
161
  if (this.options.dir) {
164
- this.state.set('projectDir', resolve(this.options.dir))
162
+ this.state.set('projectDir', this.container.paths.resolve(this.options.dir))
165
163
  } else {
166
164
  this.state.set('projectDir', this.container.cwd)
167
165
  }
@@ -170,7 +168,7 @@ export class Python<
170
168
  await this.detectEnvironment()
171
169
 
172
170
  // Execute context script if provided
173
- if (this.options.contextScript && existsSync(this.options.contextScript)) {
171
+ if (this.options.contextScript && this.container.feature('fs').exists(this.options.contextScript)) {
174
172
  await this.execute(`exec(open('${this.options.contextScript}').read())`)
175
173
  }
176
174
 
@@ -217,6 +215,8 @@ export class Python<
217
215
  let environmentType: PythonState['environmentType'] = null
218
216
 
219
217
  const proc = this.container.feature('proc')
218
+ const fs = this.container.feature('fs')
219
+ const paths = this.container.paths
220
220
 
221
221
  /** Resolve a binary to its full path via `which`, falling back to the bare name. */
222
222
  const resolveBin = (name: string): string => {
@@ -228,12 +228,14 @@ export class Python<
228
228
  pythonPath = this.options.pythonPath
229
229
  environmentType = 'system'
230
230
  }
231
- // Check for uv
232
- else if (existsSync(join(projectDir, 'uv.lock')) || existsSync(join(projectDir, 'pyproject.toml'))) {
231
+
232
+ // Check for uv independent so a missing uv binary falls through to conda/venv
233
+ if (!pythonPath && (fs.exists(paths.resolve(projectDir, 'uv.lock')) || fs.exists(paths.resolve(projectDir, 'pyproject.toml')))) {
233
234
  try {
234
235
  const uvBin = resolveBin('uv')
235
236
  const result = await proc.execAndCapture(`${uvBin} run python --version`)
236
- if (result.exitCode === 0) {
237
+ // execAndCapture returns exitCode 0 on ENOENT — check result.error to confirm the binary actually ran
238
+ if (result.exitCode === 0 && !result.error) {
237
239
  pythonPath = `${uvBin} run python`
238
240
  environmentType = 'uv'
239
241
  }
@@ -241,12 +243,13 @@ export class Python<
241
243
  // Fall through to next detection method
242
244
  }
243
245
  }
246
+
244
247
  // Check for conda
245
- else if (existsSync(join(projectDir, 'environment.yml')) || existsSync(join(projectDir, 'conda.yml'))) {
248
+ if (!pythonPath && (fs.exists(paths.resolve(projectDir, 'environment.yml')) || fs.exists(paths.resolve(projectDir, 'conda.yml')))) {
246
249
  try {
247
250
  const condaBin = resolveBin('conda')
248
251
  const result = await proc.execAndCapture(`${condaBin} run python --version`)
249
- if (result.exitCode === 0) {
252
+ if (result.exitCode === 0 && !result.error) {
250
253
  pythonPath = `${condaBin} run python`
251
254
  environmentType = 'conda'
252
255
  }
@@ -254,14 +257,15 @@ export class Python<
254
257
  // Fall through to next detection method
255
258
  }
256
259
  }
260
+
257
261
  // Check for venv
258
- else if (existsSync(join(projectDir, 'venv')) || existsSync(join(projectDir, '.venv'))) {
259
- const venvPath = existsSync(join(projectDir, 'venv')) ? 'venv' : '.venv'
262
+ if (!pythonPath && (fs.exists(paths.resolve(projectDir, 'venv')) || fs.exists(paths.resolve(projectDir, '.venv')))) {
263
+ const venvPath = fs.exists(paths.resolve(projectDir, 'venv')) ? 'venv' : '.venv'
260
264
  const venvPython = process.platform === 'win32'
261
- ? join(projectDir, venvPath, 'Scripts', 'python.exe')
262
- : join(projectDir, venvPath, 'bin', 'python')
265
+ ? paths.resolve(projectDir, venvPath, 'Scripts', 'python.exe')
266
+ : paths.resolve(projectDir, venvPath, 'bin', 'python')
263
267
 
264
- if (existsSync(venvPython)) {
268
+ if (fs.exists(venvPython)) {
265
269
  pythonPath = venvPython
266
270
  environmentType = 'venv'
267
271
  }
@@ -317,6 +321,8 @@ export class Python<
317
321
  */
318
322
  async installDependencies(): Promise<{ stdout: string; stderr: string; exitCode: number }> {
319
323
  const proc = this.container.feature('proc')
324
+ const fs = this.container.feature('fs')
325
+ const paths = this.container.paths
320
326
  const projectDir = this.state.get('projectDir')!
321
327
  const environmentType = this.state.get('environmentType')
322
328
 
@@ -330,9 +336,9 @@ export class Python<
330
336
  installCommand = 'uv sync'
331
337
  break
332
338
  case 'conda':
333
- if (existsSync(join(projectDir, 'environment.yml'))) {
339
+ if (fs.exists(paths.resolve(projectDir, 'environment.yml'))) {
334
340
  installCommand = 'conda env update -f environment.yml'
335
- } else if (existsSync(join(projectDir, 'conda.yml'))) {
341
+ } else if (fs.exists(paths.resolve(projectDir, 'conda.yml'))) {
336
342
  installCommand = 'conda env update -f conda.yml'
337
343
  } else {
338
344
  installCommand = 'conda install --file requirements.txt'
@@ -341,10 +347,10 @@ export class Python<
341
347
  case 'venv':
342
348
  case 'system':
343
349
  default:
344
- if (existsSync(join(projectDir, 'requirements.txt'))) {
350
+ if (fs.exists(paths.resolve(projectDir, 'requirements.txt'))) {
345
351
  const pythonPath = this.state.get('pythonPath')!
346
352
  installCommand = `${pythonPath} -m pip install -r requirements.txt`
347
- } else if (existsSync(join(projectDir, 'pyproject.toml'))) {
353
+ } else if (fs.exists(paths.resolve(projectDir, 'pyproject.toml'))) {
348
354
  const pythonPath = this.state.get('pythonPath')!
349
355
  installCommand = `${pythonPath} -m pip install -e .`
350
356
  } else {
@@ -406,7 +412,7 @@ export class Python<
406
412
  // Create temporary script in system temp dir (not inside the project)
407
413
  const tempDir = `${tmpdir()}/luca-python-temp`
408
414
  await fs.ensureFolder(tempDir)
409
- const scriptPath = join(tempDir, `script-${Date.now()}.py`)
415
+ const scriptPath = this.container.paths.resolve(tempDir, `script-${Date.now()}.py`)
410
416
 
411
417
  // Build the Python script
412
418
  let script = ''
@@ -3,7 +3,7 @@ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
3
3
  import { Feature } from "../feature.js";
4
4
  import vm from 'vm'
5
5
  import readline from 'readline'
6
- import { displayResult } from '../../commands/eval.js'
6
+ import { displayResult } from './display-result.js'
7
7
 
8
8
  export const ReplStateSchema = FeatureStateSchema.extend({
9
9
  started: z.boolean().optional().describe('Whether the REPL server has been started'),
@@ -109,8 +109,8 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
109
109
  sshCmd += ` -i "${key}"`
110
110
  }
111
111
 
112
- // Disable host key checking for automation (optional - you may want to remove this for security)
113
- sshCmd += ` -o StrictHostKeyChecking=no`
112
+ // Batch mode fails immediately instead of hanging on interactive prompts
113
+ sshCmd += ` -o BatchMode=yes -o StrictHostKeyChecking=no`
114
114
 
115
115
  sshCmd += ` ${username}@${host}`
116
116
 
@@ -129,8 +129,8 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
129
129
  scpCmd += ` -i "${key}"`
130
130
  }
131
131
 
132
- // Disable host key checking for automation
133
- scpCmd += ` -o StrictHostKeyChecking=no`
132
+ // Batch mode fails immediately instead of hanging on interactive prompts
133
+ scpCmd += ` -o BatchMode=yes -o StrictHostKeyChecking=no`
134
134
 
135
135
  return scpCmd
136
136
  }
@@ -150,18 +150,12 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
150
150
  * ```
151
151
  */
152
152
  async testConnection(): Promise<boolean> {
153
- try {
154
- const testCmd = `${this.buildSSHConnectionString()} "echo 'connection_test'"`
155
- const result = await this.proc.execAndCapture(testCmd)
156
-
157
- if (result.exitCode === 0 && result.stdout.trim() === 'connection_test') {
158
- this.setState({ connected: true })
159
- return true
160
- } else {
161
- this.setState({ connected: false })
162
- return false
163
- }
164
- } catch (error) {
153
+ const result = await this.exec(`echo 'connected'`).catch(e => '')
154
+
155
+ if (String(result).trim() === 'connected') {
156
+ this.setState({ connected: true })
157
+ return true
158
+ } else {
165
159
  this.setState({ connected: false })
166
160
  return false
167
161
  }
@@ -264,4 +258,4 @@ export class SecureShell extends Feature<SecureShellState, SecureShellOptions> {
264
258
  }
265
259
  }
266
260
 
267
- export default SecureShell
261
+ export default SecureShell
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod'
2
2
  import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
3
- import { type AvailableFeatures } from '@soederpop/luca/feature'
3
+ import { type AvailableFeatures } from 'luca/feature'
4
4
  import { Feature } from '../feature.js'
5
5
  import { Database } from 'bun:sqlite'
6
6
  import { createHash } from 'node:crypto'
@@ -8,7 +8,7 @@ import { mkdirSync, existsSync, statSync } from 'node:fs'
8
8
  import { dirname, join } from 'node:path'
9
9
  import { homedir } from 'node:os'
10
10
 
11
- declare module '@soederpop/luca/feature' {
11
+ declare module 'luca/feature' {
12
12
  interface AvailableFeatures {
13
13
  semanticSearch: typeof SemanticSearch
14
14
  }
@@ -145,16 +145,15 @@ export class Transpiler extends Feature {
145
145
  entrypoints: [filePath],
146
146
  target: 'bun',
147
147
  format: 'cjs',
148
- bundle: true,
149
148
  external,
150
- })
149
+ } as any)
151
150
 
152
151
  if (!result.success) {
153
152
  const msgs = result.logs.map((l: any) => l.message || String(l)).join('\n')
154
153
  throw new Error(`Bundle failed for ${filePath}:\n${msgs}`)
155
154
  }
156
155
 
157
- return await result.outputs[0].text()
156
+ return await result.outputs[0]!.text()
158
157
  }
159
158
  }
160
159
 
@@ -72,6 +72,11 @@ export class UI<T extends UIState = UIState> extends Feature<T> {
72
72
  print: ColoredPrintFunction = Object.assign((...args: any[]) => {
73
73
  return console.log(...args)
74
74
  }, {
75
+ error: (text: string) => console.log(colors.red(text)),
76
+ info: (text: string) => console.log(text),
77
+ success: (text: string) => console.log(colors.green(text)),
78
+ warn: (text: string) => console.log(colors.yellow(text)),
79
+ warning: (text: string) => console.log(colors.yellow(text)),
75
80
  red: (text: string) => console.log(colors.red(text)),
76
81
  green: (text: string) => console.log(colors.green(text)),
77
82
  blue: (text: string) => console.log(colors.blue(text)),
@@ -55,17 +55,17 @@ export class VM<
55
55
  * Register a virtual module that will be available to `require()` inside VM-executed code.
56
56
  * Modules registered here take precedence over Node's native resolution.
57
57
  *
58
- * @param id - The module specifier (e.g. `'@soederpop/luca'`, `'zod'`)
58
+ * @param id - The module specifier (e.g. `'luca'`, `'zod'`)
59
59
  * @param exports - The module's exports object
60
60
  *
61
61
  * @example
62
62
  * ```typescript
63
63
  * const vm = container.feature('vm')
64
- * vm.defineModule('@soederpop/luca', { Container, Feature, fs, proc })
64
+ * vm.defineModule('luca', { Container, Feature, fs, proc })
65
65
  * vm.defineModule('zod', { z })
66
66
  *
67
67
  * // Now loadModule can resolve these in user code:
68
- * // import { Container } from '@soederpop/luca' → works
68
+ * // import { Container } from 'luca' → works
69
69
  * ```
70
70
  */
71
71
  defineModule(id: string, exports: any): void {
package/src/node.ts CHANGED
@@ -17,7 +17,7 @@ export default container as NodeContainer
17
17
  export function createContainer() {
18
18
  console.warn(
19
19
  '[luca] createContainer() is unnecessary — import the default export instead.\n' +
20
- ' `import container from "@soederpop/luca"`\n' +
20
+ ' `import container from "luca"`\n' +
21
21
  ' For a separate instance, use container.subcontainer().'
22
22
  )
23
23
  return container
@@ -45,7 +45,7 @@ export { Client, ClientsRegistry } from './client'
45
45
  export { RestClient } from './clients/rest'
46
46
  export { GraphClient } from './clients/graph'
47
47
  export { WebSocketClient } from './clients/websocket'
48
- export { Command, CommandsRegistry, commands } from './command'
48
+ export { Command, CommandsRegistry, commands, graftModule } from './command'
49
49
  export { Endpoint, EndpointsRegistry, endpoints } from './endpoint'
50
50
  export { Selector, SelectorsRegistry, selectors } from './selector'
51
51
  export { Server, ServersRegistry } from './server'
@@ -69,7 +69,7 @@ export type { Entity } from './entity'
69
69
  export type { EventMap } from './bus'
70
70
  export type { SetStateValue, StateChangeType } from './state'
71
71
 
72
- // Zod — so consumer code can `import { z } from '@soederpop/luca'`
72
+ // Zod — so consumer code can `import { z } from 'luca'`
73
73
  export { z } from 'zod'
74
74
 
75
75
  // Schemas
@@ -1,5 +1,4 @@
1
1
  // Auto-generated Python bridge script
2
- // Generated at: 2026-04-10T05:00:55.842Z
3
2
  // Source: src/python/bridge.py
4
3
  //
5
4
  // Do not edit manually. Run: luca build-python-bridge