@soederpop/luca 0.1.2 → 0.2.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 (381) hide show
  1. package/.github/workflows/release.yaml +167 -0
  2. package/CLAUDE.md +2 -0
  3. package/README.md +3 -0
  4. package/assistants/codingAssistant/ABOUT.md +3 -0
  5. package/assistants/codingAssistant/CORE.md +22 -17
  6. package/assistants/codingAssistant/hooks.ts +17 -4
  7. package/assistants/codingAssistant/tools.ts +1 -106
  8. package/assistants/inkbot/ABOUT.md +5 -0
  9. package/assistants/inkbot/CORE.md +71 -0
  10. package/assistants/inkbot/hooks.ts +14 -0
  11. package/assistants/inkbot/tools.ts +47 -0
  12. package/bun.lock +20 -4
  13. package/commands/inkbot.ts +353 -0
  14. package/commands/release.ts +75 -181
  15. package/dist/agi/container.server.d.ts +63 -0
  16. package/dist/agi/container.server.d.ts.map +1 -0
  17. package/dist/agi/endpoints/ask.d.ts +20 -0
  18. package/dist/agi/endpoints/ask.d.ts.map +1 -0
  19. package/dist/agi/endpoints/conversations/[id].d.ts +27 -0
  20. package/dist/agi/endpoints/conversations/[id].d.ts.map +1 -0
  21. package/dist/agi/endpoints/conversations.d.ts +18 -0
  22. package/dist/agi/endpoints/conversations.d.ts.map +1 -0
  23. package/dist/agi/endpoints/experts.d.ts +8 -0
  24. package/dist/agi/endpoints/experts.d.ts.map +1 -0
  25. package/dist/agi/feature.d.ts +9 -0
  26. package/dist/agi/feature.d.ts.map +1 -0
  27. package/dist/agi/features/assistant.d.ts +509 -0
  28. package/dist/agi/features/assistant.d.ts.map +1 -0
  29. package/dist/agi/features/assistants-manager.d.ts +236 -0
  30. package/dist/agi/features/assistants-manager.d.ts.map +1 -0
  31. package/dist/agi/features/autonomous-assistant.d.ts +281 -0
  32. package/dist/agi/features/autonomous-assistant.d.ts.map +1 -0
  33. package/dist/agi/features/browser-use.d.ts +479 -0
  34. package/dist/agi/features/browser-use.d.ts.map +1 -0
  35. package/dist/agi/features/claude-code.d.ts +824 -0
  36. package/dist/agi/features/claude-code.d.ts.map +1 -0
  37. package/dist/agi/features/conversation-history.d.ts +245 -0
  38. package/dist/agi/features/conversation-history.d.ts.map +1 -0
  39. package/dist/agi/features/conversation.d.ts +464 -0
  40. package/dist/agi/features/conversation.d.ts.map +1 -0
  41. package/dist/agi/features/docs-reader.d.ts +72 -0
  42. package/dist/agi/features/docs-reader.d.ts.map +1 -0
  43. package/dist/agi/features/file-tools.d.ts +110 -0
  44. package/dist/agi/features/file-tools.d.ts.map +1 -0
  45. package/dist/agi/features/luca-coder.d.ts +323 -0
  46. package/dist/agi/features/luca-coder.d.ts.map +1 -0
  47. package/dist/agi/features/openai-codex.d.ts +381 -0
  48. package/dist/agi/features/openai-codex.d.ts.map +1 -0
  49. package/dist/agi/features/openapi.d.ts +200 -0
  50. package/dist/agi/features/openapi.d.ts.map +1 -0
  51. package/dist/agi/features/skills-library.d.ts +167 -0
  52. package/dist/agi/features/skills-library.d.ts.map +1 -0
  53. package/dist/agi/index.d.ts +5 -0
  54. package/dist/agi/index.d.ts.map +1 -0
  55. package/dist/agi/lib/interceptor-chain.d.ts +44 -0
  56. package/dist/agi/lib/interceptor-chain.d.ts.map +1 -0
  57. package/dist/agi/lib/token-counter.d.ts +13 -0
  58. package/dist/agi/lib/token-counter.d.ts.map +1 -0
  59. package/dist/bootstrap/generated.d.ts +5 -0
  60. package/dist/bootstrap/generated.d.ts.map +1 -0
  61. package/dist/browser.d.ts +12 -0
  62. package/dist/browser.d.ts.map +1 -0
  63. package/dist/bus.d.ts +29 -0
  64. package/dist/bus.d.ts.map +1 -0
  65. package/dist/cli/build-info.d.ts +4 -0
  66. package/dist/cli/build-info.d.ts.map +1 -0
  67. package/dist/cli/cli.d.ts +3 -0
  68. package/dist/cli/cli.d.ts.map +1 -0
  69. package/dist/client.d.ts +60 -0
  70. package/dist/client.d.ts.map +1 -0
  71. package/dist/clients/civitai/index.d.ts +472 -0
  72. package/dist/clients/civitai/index.d.ts.map +1 -0
  73. package/dist/clients/client-template.d.ts +30 -0
  74. package/dist/clients/client-template.d.ts.map +1 -0
  75. package/dist/clients/comfyui/index.d.ts +281 -0
  76. package/dist/clients/comfyui/index.d.ts.map +1 -0
  77. package/dist/clients/elevenlabs/index.d.ts +197 -0
  78. package/dist/clients/elevenlabs/index.d.ts.map +1 -0
  79. package/dist/clients/graph.d.ts +64 -0
  80. package/dist/clients/graph.d.ts.map +1 -0
  81. package/dist/clients/openai/index.d.ts +247 -0
  82. package/dist/clients/openai/index.d.ts.map +1 -0
  83. package/dist/clients/rest.d.ts +92 -0
  84. package/dist/clients/rest.d.ts.map +1 -0
  85. package/dist/clients/supabase/index.d.ts +176 -0
  86. package/dist/clients/supabase/index.d.ts.map +1 -0
  87. package/dist/clients/websocket.d.ts +127 -0
  88. package/dist/clients/websocket.d.ts.map +1 -0
  89. package/dist/command.d.ts +163 -0
  90. package/dist/command.d.ts.map +1 -0
  91. package/dist/commands/bootstrap.d.ts +20 -0
  92. package/dist/commands/bootstrap.d.ts.map +1 -0
  93. package/dist/commands/chat.d.ts +37 -0
  94. package/dist/commands/chat.d.ts.map +1 -0
  95. package/dist/commands/code.d.ts +28 -0
  96. package/dist/commands/code.d.ts.map +1 -0
  97. package/dist/commands/console.d.ts +22 -0
  98. package/dist/commands/console.d.ts.map +1 -0
  99. package/dist/commands/describe.d.ts +50 -0
  100. package/dist/commands/describe.d.ts.map +1 -0
  101. package/dist/commands/eval.d.ts +23 -0
  102. package/dist/commands/eval.d.ts.map +1 -0
  103. package/dist/commands/help.d.ts +25 -0
  104. package/dist/commands/help.d.ts.map +1 -0
  105. package/dist/commands/index.d.ts +18 -0
  106. package/dist/commands/index.d.ts.map +1 -0
  107. package/dist/commands/introspect.d.ts +24 -0
  108. package/dist/commands/introspect.d.ts.map +1 -0
  109. package/dist/commands/mcp.d.ts +35 -0
  110. package/dist/commands/mcp.d.ts.map +1 -0
  111. package/dist/commands/prompt.d.ts +38 -0
  112. package/dist/commands/prompt.d.ts.map +1 -0
  113. package/dist/commands/run.d.ts +24 -0
  114. package/dist/commands/run.d.ts.map +1 -0
  115. package/dist/commands/sandbox-mcp.d.ts +34 -0
  116. package/dist/commands/sandbox-mcp.d.ts.map +1 -0
  117. package/dist/commands/save-api-docs.d.ts +21 -0
  118. package/dist/commands/save-api-docs.d.ts.map +1 -0
  119. package/dist/commands/scaffold.d.ts +24 -0
  120. package/dist/commands/scaffold.d.ts.map +1 -0
  121. package/dist/commands/select.d.ts +22 -0
  122. package/dist/commands/select.d.ts.map +1 -0
  123. package/dist/commands/serve.d.ts +29 -0
  124. package/dist/commands/serve.d.ts.map +1 -0
  125. package/dist/container-describer.d.ts +144 -0
  126. package/dist/container-describer.d.ts.map +1 -0
  127. package/dist/container.d.ts +451 -0
  128. package/dist/container.d.ts.map +1 -0
  129. package/dist/endpoint.d.ts +113 -0
  130. package/dist/endpoint.d.ts.map +1 -0
  131. package/dist/feature.d.ts +47 -0
  132. package/dist/feature.d.ts.map +1 -0
  133. package/dist/graft.d.ts +29 -0
  134. package/dist/graft.d.ts.map +1 -0
  135. package/dist/hash-object.d.ts +8 -0
  136. package/dist/hash-object.d.ts.map +1 -0
  137. package/dist/helper.d.ts +209 -0
  138. package/dist/helper.d.ts.map +1 -0
  139. package/dist/introspection/generated.node.d.ts +44623 -0
  140. package/dist/introspection/generated.node.d.ts.map +1 -0
  141. package/dist/introspection/generated.web.d.ts +1412 -0
  142. package/dist/introspection/generated.web.d.ts.map +1 -0
  143. package/dist/introspection/index.d.ts +156 -0
  144. package/dist/introspection/index.d.ts.map +1 -0
  145. package/dist/introspection/scan.d.ts +147 -0
  146. package/dist/introspection/scan.d.ts.map +1 -0
  147. package/dist/node/container.d.ts +256 -0
  148. package/dist/node/container.d.ts.map +1 -0
  149. package/dist/node/feature.d.ts +9 -0
  150. package/dist/node/feature.d.ts.map +1 -0
  151. package/dist/node/features/container-link.d.ts +213 -0
  152. package/dist/node/features/container-link.d.ts.map +1 -0
  153. package/dist/node/features/content-db.d.ts +354 -0
  154. package/dist/node/features/content-db.d.ts.map +1 -0
  155. package/dist/node/features/disk-cache.d.ts +236 -0
  156. package/dist/node/features/disk-cache.d.ts.map +1 -0
  157. package/dist/node/features/dns.d.ts +511 -0
  158. package/dist/node/features/dns.d.ts.map +1 -0
  159. package/dist/node/features/docker.d.ts +485 -0
  160. package/dist/node/features/docker.d.ts.map +1 -0
  161. package/dist/node/features/downloader.d.ts +73 -0
  162. package/dist/node/features/downloader.d.ts.map +1 -0
  163. package/dist/node/features/figlet-fonts.d.ts +4 -0
  164. package/dist/node/features/figlet-fonts.d.ts.map +1 -0
  165. package/dist/node/features/file-manager.d.ts +177 -0
  166. package/dist/node/features/file-manager.d.ts.map +1 -0
  167. package/dist/node/features/fs.d.ts +635 -0
  168. package/dist/node/features/fs.d.ts.map +1 -0
  169. package/dist/node/features/git.d.ts +329 -0
  170. package/dist/node/features/git.d.ts.map +1 -0
  171. package/dist/node/features/google-auth.d.ts +200 -0
  172. package/dist/node/features/google-auth.d.ts.map +1 -0
  173. package/dist/node/features/google-calendar.d.ts +194 -0
  174. package/dist/node/features/google-calendar.d.ts.map +1 -0
  175. package/dist/node/features/google-docs.d.ts +138 -0
  176. package/dist/node/features/google-docs.d.ts.map +1 -0
  177. package/dist/node/features/google-drive.d.ts +202 -0
  178. package/dist/node/features/google-drive.d.ts.map +1 -0
  179. package/dist/node/features/google-mail.d.ts +221 -0
  180. package/dist/node/features/google-mail.d.ts.map +1 -0
  181. package/dist/node/features/google-sheets.d.ts +157 -0
  182. package/dist/node/features/google-sheets.d.ts.map +1 -0
  183. package/dist/node/features/grep.d.ts +207 -0
  184. package/dist/node/features/grep.d.ts.map +1 -0
  185. package/dist/node/features/helpers.d.ts +236 -0
  186. package/dist/node/features/helpers.d.ts.map +1 -0
  187. package/dist/node/features/ink.d.ts +332 -0
  188. package/dist/node/features/ink.d.ts.map +1 -0
  189. package/dist/node/features/ipc-socket.d.ts +298 -0
  190. package/dist/node/features/ipc-socket.d.ts.map +1 -0
  191. package/dist/node/features/json-tree.d.ts +140 -0
  192. package/dist/node/features/json-tree.d.ts.map +1 -0
  193. package/dist/node/features/networking.d.ts +373 -0
  194. package/dist/node/features/networking.d.ts.map +1 -0
  195. package/dist/node/features/nlp.d.ts +125 -0
  196. package/dist/node/features/nlp.d.ts.map +1 -0
  197. package/dist/node/features/opener.d.ts +93 -0
  198. package/dist/node/features/opener.d.ts.map +1 -0
  199. package/dist/node/features/os.d.ts +168 -0
  200. package/dist/node/features/os.d.ts.map +1 -0
  201. package/dist/node/features/package-finder.d.ts +419 -0
  202. package/dist/node/features/package-finder.d.ts.map +1 -0
  203. package/dist/node/features/postgres.d.ts +173 -0
  204. package/dist/node/features/postgres.d.ts.map +1 -0
  205. package/dist/node/features/proc.d.ts +285 -0
  206. package/dist/node/features/proc.d.ts.map +1 -0
  207. package/dist/node/features/process-manager.d.ts +427 -0
  208. package/dist/node/features/process-manager.d.ts.map +1 -0
  209. package/dist/node/features/python.d.ts +477 -0
  210. package/dist/node/features/python.d.ts.map +1 -0
  211. package/dist/node/features/redis.d.ts +247 -0
  212. package/dist/node/features/redis.d.ts.map +1 -0
  213. package/dist/node/features/repl.d.ts +84 -0
  214. package/dist/node/features/repl.d.ts.map +1 -0
  215. package/dist/node/features/runpod.d.ts +527 -0
  216. package/dist/node/features/runpod.d.ts.map +1 -0
  217. package/dist/node/features/secure-shell.d.ts +145 -0
  218. package/dist/node/features/secure-shell.d.ts.map +1 -0
  219. package/dist/node/features/semantic-search.d.ts +207 -0
  220. package/dist/node/features/semantic-search.d.ts.map +1 -0
  221. package/dist/node/features/sqlite.d.ts +180 -0
  222. package/dist/node/features/sqlite.d.ts.map +1 -0
  223. package/dist/node/features/telegram.d.ts +173 -0
  224. package/dist/node/features/telegram.d.ts.map +1 -0
  225. package/dist/node/features/transpiler.d.ts +51 -0
  226. package/dist/node/features/transpiler.d.ts.map +1 -0
  227. package/dist/node/features/tts.d.ts +108 -0
  228. package/dist/node/features/tts.d.ts.map +1 -0
  229. package/dist/node/features/ui.d.ts +562 -0
  230. package/dist/node/features/ui.d.ts.map +1 -0
  231. package/dist/node/features/vault.d.ts +90 -0
  232. package/dist/node/features/vault.d.ts.map +1 -0
  233. package/dist/node/features/vm.d.ts +285 -0
  234. package/dist/node/features/vm.d.ts.map +1 -0
  235. package/dist/node/features/yaml-tree.d.ts +118 -0
  236. package/dist/node/features/yaml-tree.d.ts.map +1 -0
  237. package/dist/node/features/yaml.d.ts +127 -0
  238. package/dist/node/features/yaml.d.ts.map +1 -0
  239. package/dist/node.d.ts +67 -0
  240. package/dist/node.d.ts.map +1 -0
  241. package/dist/python/generated.d.ts +2 -0
  242. package/dist/python/generated.d.ts.map +1 -0
  243. package/dist/react/index.d.ts +36 -0
  244. package/dist/react/index.d.ts.map +1 -0
  245. package/dist/registry.d.ts +97 -0
  246. package/dist/registry.d.ts.map +1 -0
  247. package/dist/scaffolds/generated.d.ts +13 -0
  248. package/dist/scaffolds/generated.d.ts.map +1 -0
  249. package/dist/scaffolds/template.d.ts +11 -0
  250. package/dist/scaffolds/template.d.ts.map +1 -0
  251. package/dist/schemas/base.d.ts +254 -0
  252. package/dist/schemas/base.d.ts.map +1 -0
  253. package/dist/selector.d.ts +130 -0
  254. package/dist/selector.d.ts.map +1 -0
  255. package/dist/server.d.ts +89 -0
  256. package/dist/server.d.ts.map +1 -0
  257. package/dist/servers/express.d.ts +104 -0
  258. package/dist/servers/express.d.ts.map +1 -0
  259. package/dist/servers/mcp.d.ts +201 -0
  260. package/dist/servers/mcp.d.ts.map +1 -0
  261. package/dist/servers/socket.d.ts +121 -0
  262. package/dist/servers/socket.d.ts.map +1 -0
  263. package/dist/state.d.ts +24 -0
  264. package/dist/state.d.ts.map +1 -0
  265. package/dist/web/clients/socket.d.ts +37 -0
  266. package/dist/web/clients/socket.d.ts.map +1 -0
  267. package/dist/web/container.d.ts +55 -0
  268. package/dist/web/container.d.ts.map +1 -0
  269. package/dist/web/extension.d.ts +4 -0
  270. package/dist/web/extension.d.ts.map +1 -0
  271. package/dist/web/feature.d.ts +8 -0
  272. package/dist/web/feature.d.ts.map +1 -0
  273. package/dist/web/features/asset-loader.d.ts +35 -0
  274. package/dist/web/features/asset-loader.d.ts.map +1 -0
  275. package/dist/web/features/container-link.d.ts +167 -0
  276. package/dist/web/features/container-link.d.ts.map +1 -0
  277. package/dist/web/features/esbuild.d.ts +51 -0
  278. package/dist/web/features/esbuild.d.ts.map +1 -0
  279. package/dist/web/features/helpers.d.ts +140 -0
  280. package/dist/web/features/helpers.d.ts.map +1 -0
  281. package/dist/web/features/network.d.ts +69 -0
  282. package/dist/web/features/network.d.ts.map +1 -0
  283. package/dist/web/features/speech.d.ts +71 -0
  284. package/dist/web/features/speech.d.ts.map +1 -0
  285. package/dist/web/features/vault.d.ts +62 -0
  286. package/dist/web/features/vault.d.ts.map +1 -0
  287. package/dist/web/features/vm.d.ts +48 -0
  288. package/dist/web/features/vm.d.ts.map +1 -0
  289. package/dist/web/features/voice-recognition.d.ts +96 -0
  290. package/dist/web/features/voice-recognition.d.ts.map +1 -0
  291. package/dist/web/shims/isomorphic-vm.d.ts +22 -0
  292. package/dist/web/shims/isomorphic-vm.d.ts.map +1 -0
  293. package/docs/apis/features/agi/assistant.md +1 -0
  294. package/docs/apis/features/agi/assistants-manager.md +62 -2
  295. package/docs/apis/features/agi/auto-assistant.md +11 -109
  296. package/docs/apis/features/agi/claude-code.md +138 -0
  297. package/docs/apis/features/agi/conversation.md +60 -31
  298. package/docs/apis/features/agi/luca-coder.md +407 -0
  299. package/docs/apis/features/agi/openapi.md +2 -2
  300. package/docs/apis/features/agi/skills-library.md +12 -0
  301. package/docs/apis/features/node/python.md +81 -11
  302. package/docs/apis/features/node/transpiler.md +74 -0
  303. package/docs/apis/features/web/esbuild.md +0 -6
  304. package/docs/apis/servers/mcp.md +2 -2
  305. package/docs/examples/entity.md +124 -0
  306. package/docs/ideas/assistant-factory-pattern.md +142 -0
  307. package/package.json +74 -21
  308. package/src/agi/container.server.ts +10 -0
  309. package/src/agi/feature.ts +13 -0
  310. package/src/agi/features/agent-memory.ts +694 -0
  311. package/src/agi/features/assistant.ts +37 -26
  312. package/src/agi/features/assistants-manager.ts +95 -5
  313. package/src/agi/features/autonomous-assistant.ts +1 -5
  314. package/src/agi/features/browser-use.ts +32 -2
  315. package/src/agi/features/claude-code.ts +165 -1
  316. package/src/agi/features/coding-tools.ts +175 -0
  317. package/src/agi/features/conversation-history.ts +2 -6
  318. package/src/agi/features/conversation.ts +95 -3
  319. package/src/agi/features/docs-reader.ts +2 -1
  320. package/src/agi/features/file-tools.ts +35 -28
  321. package/src/agi/features/luca-coder.ts +1 -5
  322. package/src/agi/features/openai-codex.ts +1 -1
  323. package/src/agi/features/openapi.ts +3 -3
  324. package/src/agi/features/skills-library.ts +111 -13
  325. package/src/agi/lib/interceptor-chain.ts +10 -0
  326. package/src/agi/lib/token-counter.ts +1 -1
  327. package/src/bootstrap/generated.ts +126 -1
  328. package/src/bus.ts +27 -5
  329. package/src/cli/build-info.ts +2 -2
  330. package/src/client.ts +2 -2
  331. package/src/clients/elevenlabs/index.ts +5 -0
  332. package/src/clients/voicebox/index.ts +300 -0
  333. package/src/commands/bootstrap.ts +2 -1
  334. package/src/commands/chat.ts +1 -0
  335. package/src/commands/code.ts +4 -2
  336. package/src/commands/prompt.ts +34 -34
  337. package/src/commands/sandbox-mcp.ts +69 -163
  338. package/src/commands/save-api-docs.ts +10 -8
  339. package/src/commands/select.ts +8 -3
  340. package/src/container-describer.ts +70 -84
  341. package/src/container.ts +93 -3
  342. package/src/endpoint.ts +1 -1
  343. package/src/entity.ts +173 -0
  344. package/src/feature.ts +3 -3
  345. package/src/helper.ts +8 -4
  346. package/src/introspection/generated.agi.ts +3012 -1356
  347. package/src/introspection/generated.node.ts +179 -33
  348. package/src/introspection/generated.web.ts +95 -3
  349. package/src/introspection/scan.ts +1 -1
  350. package/src/node/container.ts +1 -1
  351. package/src/node/features/content-db.ts +57 -30
  352. package/src/node/features/file-manager.ts +10 -9
  353. package/src/node/features/git.ts +5 -5
  354. package/src/node/features/helpers.ts +1 -1
  355. package/src/node/features/json-tree.ts +1 -1
  356. package/src/node/features/os.ts +3 -3
  357. package/src/node/features/package-finder.ts +1 -1
  358. package/src/node/features/process-manager.ts +51 -18
  359. package/src/node/features/python.ts +3 -3
  360. package/src/node/features/redis.ts +1 -1
  361. package/src/node/features/repl.ts +2 -2
  362. package/src/node/features/transpiler.ts +2 -2
  363. package/src/node/features/ui.ts +1 -1
  364. package/src/node/features/vm.ts +3 -3
  365. package/src/node/features/yaml-tree.ts +1 -1
  366. package/src/node.ts +1 -0
  367. package/src/python/generated.ts +1 -1
  368. package/src/scaffolds/generated.ts +1 -1
  369. package/src/selector.ts +74 -4
  370. package/src/server.ts +2 -2
  371. package/src/servers/mcp.ts +6 -6
  372. package/src/web/features/helpers.ts +1 -1
  373. package/src/web/features/network.ts +1 -0
  374. package/test/assistant.test.ts +14 -5
  375. package/test/conversation.test.ts +220 -0
  376. package/test-integration/memory.test.ts +204 -0
  377. package/tsconfig.build.json +12 -0
  378. package/tsconfig.json +1 -1
  379. package/scripts/examples/telegram-ink-ui.ts +0 -302
  380. package/scripts/examples/using-openai-codex.ts +0 -23
  381. package/scripts/examples/vm-loading-esm-modules.ts +0 -16
@@ -3,8 +3,7 @@ import { commands } from '../command.js'
3
3
  import { CommandOptionsSchema } from '../schemas/base.js'
4
4
  import type { ContainerContext } from '../container.js'
5
5
  import type { MCPServer } from '../servers/mcp.js'
6
- import { scaffolds, mcpReadme } from '../scaffolds/generated.js'
7
- import { generateScaffold } from '../scaffolds/template.js'
6
+ import { mcpReadme } from '../scaffolds/generated.js'
8
7
 
9
8
  declare module '../command.js' {
10
9
  interface AvailableCommands {
@@ -21,8 +20,18 @@ export const argsSchema = CommandOptionsSchema.extend({
21
20
  .describe('Stdio framing compatibility profile. Defaults to standard. Can also be set via MCP_STDIO_COMPAT.'),
22
21
  })
23
22
 
23
+ /**
24
+ * Run a luca CLI command as a subprocess and return its output.
25
+ * Always spawns fresh so callers see the latest project code.
26
+ */
27
+ async function lucaCLI(proc: any, command: string, args: string[] = []): Promise<{ stdout: string; stderr: string; exitCode: number }> {
28
+ const result = await proc.spawnAndCapture('luca', [command, ...args])
29
+ return { stdout: result.stdout.trim(), stderr: result.stderr.trim(), exitCode: result.exitCode ?? 0 }
30
+ }
31
+
24
32
  export default async function mcpSandbox(options: z.infer<typeof argsSchema>, context: ContainerContext) {
25
33
  const container = context.container as any
34
+ const proc = container.feature('proc')
26
35
  const envCompat = process.env.MCP_HTTP_COMPAT?.toLowerCase()
27
36
  const resolvedCompat = options.mcpCompat || (envCompat === 'codex' ? 'codex' : 'standard')
28
37
  const envStdioCompat = process.env.MCP_STDIO_COMPAT?.toLowerCase()
@@ -38,26 +47,6 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
38
47
  stdioCompat: options.stdioCompat,
39
48
  }) as MCPServer
40
49
 
41
- // Persistent VM context shared across eval calls so variables survive between invocations
42
- const vmFeature = container.feature('vm')
43
- const sandboxContext = vmFeature.createContext({
44
- container,
45
- console,
46
- setTimeout,
47
- setInterval,
48
- clearTimeout,
49
- clearInterval,
50
- fetch,
51
- Bun,
52
- })
53
-
54
- // Pre-populate sandbox with all enabled features
55
- for (const name of container.features.available) {
56
- try {
57
- vmFeature.runSync(`var ${name} = container.feature('${name}')`, sandboxContext)
58
- } catch {}
59
- }
60
-
61
50
  // --- Tool: read_me ---
62
51
  mcpServer.tool('read_me', {
63
52
  description: [
@@ -78,22 +67,11 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
78
67
  'Prefer this over installing npm packages — the container likely already has what you need.',
79
68
  ].join('\n'),
80
69
  schema: z.object({}),
81
- handler: () => {
82
- const sections: string[] = []
83
-
84
- try {
85
- sections.push(container.features.describeAll())
86
- } catch {}
87
-
88
- try {
89
- sections.push(container.clients.describeAll())
90
- } catch {}
91
-
92
- try {
93
- sections.push(container.servers.describeAll())
94
- } catch {}
95
-
96
- return sections.join('\n\n---\n\n')
70
+ handler: async () => {
71
+ const { stdout, stderr } = await lucaCLI(proc, 'eval', [
72
+ '[container.features.describeAll(), container.clients.describeAll(), container.servers.describeAll()].join("\\n\\n---\\n\\n")',
73
+ ])
74
+ return stdout || stderr
97
75
  },
98
76
  })
99
77
 
@@ -113,9 +91,11 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
113
91
  description: z.string().optional()
114
92
  .describe('Brief description of what this helper does'),
115
93
  }),
116
- handler: (args) => {
117
- const result = generateScaffold(args.type, args.name, args.description)
118
- return result || `No scaffold template available for type: ${args.type}`
94
+ handler: async (args) => {
95
+ const cliArgs = [args.type, args.name]
96
+ if (args.description) cliArgs.push('--description', args.description)
97
+ const { stdout, stderr } = await lucaCLI(proc, 'scaffold', cliArgs)
98
+ return stdout || stderr
119
99
  },
120
100
  })
121
101
 
@@ -124,13 +104,11 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
124
104
  description: [
125
105
  'Evaluate JavaScript/TypeScript code in a Luca container sandbox.',
126
106
  'Use this to prototype and test container API calls before writing them into files.',
127
- 'The sandbox has all features available as top-level variables.',
107
+ 'Each call runs in a fresh luca process — always reflects the latest project code.',
128
108
  '',
129
109
  'The sandbox has a live `container` object and all enabled features as top-level variables',
130
110
  '(e.g. `fs`, `git`, `ui`, `vm`, `proc`, `networking`, etc).',
131
111
  '',
132
- 'Variables you define persist across calls, so you can build up state incrementally.',
133
- '',
134
112
  'The result of the last expression is returned. For async code, use `await`.',
135
113
  '',
136
114
  'Quick reference:',
@@ -149,46 +127,11 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
149
127
  code: z.string().describe('JavaScript code to evaluate in the Luca container sandbox'),
150
128
  }),
151
129
  handler: async (args) => {
152
- try {
153
- const { result, console: calls } = await vmFeature.runCaptured(args.code, sandboxContext)
154
-
155
- const content: Array<{ type: 'text', text: string }> = []
156
-
157
- // Include captured console output if any
158
- if (calls.length > 0) {
159
- const consoleLines = calls.map(c => {
160
- const prefix = c.method === 'log' ? '' : `[${c.method}] `
161
- return prefix + c.args.map(a => typeof a === 'object' ? JSON.stringify(a, null, 2) : String(a)).join(' ')
162
- })
163
- content.push({ type: 'text' as const, text: consoleLines.join('\n') })
164
- }
165
-
166
- // Include the result
167
- let text: string
168
- if (result === undefined) {
169
- text = 'undefined'
170
- } else if (result === null) {
171
- text = 'null'
172
- } else if (typeof result === 'string') {
173
- text = result
174
- } else if (typeof result === 'object') {
175
- try {
176
- text = JSON.stringify(result, null, 2)
177
- } catch {
178
- text = String(result)
179
- }
180
- } else {
181
- text = String(result)
182
- }
183
-
184
- content.push({ type: 'text' as const, text })
185
-
186
- return { content }
187
- } catch (error: any) {
188
- return {
189
- content: [{ type: 'text' as const, text: `Error: ${error.message}\n\n${error.stack || ''}` }],
190
- isError: true,
191
- }
130
+ const { stdout, stderr, exitCode } = await lucaCLI(proc, 'eval', [args.code])
131
+ const text = stdout || stderr || 'undefined'
132
+ return {
133
+ content: [{ type: 'text' as const, text }],
134
+ isError: exitCode !== 0,
192
135
  }
193
136
  },
194
137
  })
@@ -207,8 +150,12 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
207
150
  section: z.enum(['methods', 'getters', 'events', 'state', 'options', 'envVars']).optional()
208
151
  .describe('Optional section to filter to. Omit for full overview.'),
209
152
  }),
210
- handler: (args) => {
211
- return container.introspectAsText(args.section)
153
+ handler: async (args) => {
154
+ const code = args.section
155
+ ? `container.introspectAsText("${args.section}")`
156
+ : 'container.introspectAsText()'
157
+ const { stdout, stderr } = await lucaCLI(proc, 'eval', [code])
158
+ return stdout || stderr
212
159
  },
213
160
  })
214
161
 
@@ -224,22 +171,11 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
224
171
  registry: z.enum(['features', 'clients', 'servers', 'commands', 'endpoints'])
225
172
  .describe('Which registry to list'),
226
173
  }),
227
- handler: (args) => {
228
- const registry = (container as any)[args.registry]
229
- if (!registry) return `Unknown registry: ${args.registry}`
230
- const names: string[] = registry.available
231
- if (names.length === 0) return `No ${args.registry} registered.`
232
- const lines = [`# Available ${args.registry}\n`]
233
- for (const name of names) {
234
- try {
235
- const Ctor = registry.lookup(name) as any
236
- const desc = Ctor.description || ''
237
- lines.push(`- **${name}**${desc ? `: ${desc}` : ''}`)
238
- } catch {
239
- lines.push(`- **${name}**`)
240
- }
241
- }
242
- return lines.join('\n')
174
+ handler: async (args) => {
175
+ const { stdout, stderr } = await lucaCLI(proc, 'eval', [
176
+ `container.${args.registry}.available.map(n => { try { const C = container.${args.registry}.lookup(n); return "- **" + n + "**" + (C.description ? ": " + C.description : "") } catch { return "- **" + n + "**" } }).join("\\n")`,
177
+ ])
178
+ return stdout || stderr
243
179
  },
244
180
  })
245
181
 
@@ -254,24 +190,15 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
254
190
  'Use list_registry or find_capability first to see what is available.',
255
191
  ].join('\n'),
256
192
  schema: z.object({
257
- registry: z.enum(['features', 'clients', 'servers', 'commands', 'endpoints'])
258
- .describe('Which registry the helper belongs to'),
259
- name: z.string().describe('Name of the helper (e.g. "fs", "rest", "express")'),
193
+ name: z.string().describe('Name of the helper (e.g. "fs", "rest", "express", "serve")'),
260
194
  section: z.enum(['methods', 'getters', 'events', 'state', 'options', 'envVars']).optional()
261
195
  .describe('Optional section to filter to. Omit for full documentation.'),
262
196
  }),
263
- handler: (args) => {
264
- const registry = (container as any)[args.registry]
265
- if (!registry) return `Unknown registry: ${args.registry}`
266
- if (!registry.has(args.name)) {
267
- return `"${args.name}" not found in ${args.registry}. Available: ${registry.available.join(', ')}`
268
- }
269
- try {
270
- const Ctor = registry.lookup(args.name) as any
271
- return Ctor.introspectAsText(args.section)
272
- } catch (e: any) {
273
- return `Error describing ${args.name}: ${e.message}`
274
- }
197
+ handler: async (args) => {
198
+ const describeArgs = [args.name]
199
+ if (args.section) describeArgs.push(args.section)
200
+ const { stdout, stderr } = await lucaCLI(proc, 'describe', describeArgs)
201
+ return stdout || stderr
275
202
  },
276
203
  })
277
204
 
@@ -282,8 +209,7 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
282
209
  'Use this to inspect a live, running instance — see its current state,',
283
210
  'check method signatures, and understand runtime behavior.',
284
211
  '',
285
- 'Creates or retrieves the helper and returns introspectAsText() the same',
286
- 'rich markdown documentation available on any Helper instance at runtime.',
212
+ 'Runs in a fresh process so you always see the latest code.',
287
213
  'Optionally filter to a specific section.',
288
214
  ].join('\n'),
289
215
  schema: z.object({
@@ -293,20 +219,17 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
293
219
  section: z.enum(['methods', 'getters', 'events', 'state', 'options', 'envVars']).optional()
294
220
  .describe('Optional section to filter to. Omit for full introspection.'),
295
221
  }),
296
- handler: (args) => {
297
- try {
298
- let instance: any
299
- if (args.type === 'feature') {
300
- instance = container.feature(args.name as any)
301
- } else if (args.type === 'client') {
302
- instance = container.client(args.name as any)
303
- } else if (args.type === 'server') {
304
- instance = container.server(args.name as any)
305
- }
306
- return instance.introspectAsText(args.section)
307
- } catch (e: any) {
308
- return `Error inspecting ${args.type} "${args.name}": ${e.message}`
309
- }
222
+ handler: async (args) => {
223
+ const accessor = args.type === 'feature'
224
+ ? `container.feature('${args.name}')`
225
+ : args.type === 'client'
226
+ ? `container.client('${args.name}')`
227
+ : `container.server('${args.name}')`
228
+ const code = args.section
229
+ ? `${accessor}.introspectAsText("${args.section}")`
230
+ : `${accessor}.introspectAsText()`
231
+ const { stdout, stderr } = await lucaCLI(proc, 'eval', [code])
232
+ return stdout || stderr
310
233
  },
311
234
  })
312
235
 
@@ -318,7 +241,8 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
318
241
  content: [
319
242
  '# Luca Container Sandbox',
320
243
  '',
321
- 'You have access to a live Luca container through the `eval` tool. The sandbox is a persistent JavaScript environment with a `container` global and all enabled features available as top-level variables.',
244
+ 'You have access to a live Luca container through the `eval` tool. Each call runs in a fresh process,',
245
+ 'so you always see the latest project code. Use the `eval` tool to prototype and explore.',
322
246
  '',
323
247
  '## Discovering what is available',
324
248
  '',
@@ -353,20 +277,6 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
353
277
  'git.log({ max: 5 }) // Recent git commits',
354
278
  'proc.exec("ls -la") // Run a shell command',
355
279
  '```',
356
- '',
357
- '### Persistent state',
358
- 'Variables you define in one eval call persist to the next:',
359
- '```',
360
- '// Call 1',
361
- 'const data = fs.readFile("package.json")',
362
- '// Call 2',
363
- 'JSON.parse(data).name // still has `data` from previous call',
364
- '```',
365
- '',
366
- '## Recommended first steps',
367
- '1. `container.features.available` — see what features exist',
368
- '2. Pick an interesting feature and `container.features.describe("name")` it',
369
- '3. Try using the feature directly',
370
280
  ].join('\n'),
371
281
  }],
372
282
  })
@@ -375,10 +285,10 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
375
285
  mcpServer.prompt('introspect', {
376
286
  description: 'Get full introspection of the Luca container — all registries, state, methods, events, and environment info.',
377
287
  handler: async () => {
378
- const text = container.introspectAsText()
288
+ const { stdout } = await lucaCLI(proc, 'eval', ['container.introspectAsText()'])
379
289
  return [{
380
290
  role: 'user' as const,
381
- content: `Here is the full container introspection:\n\n${text}`,
291
+ content: `Here is the full container introspection:\n\n${stdout}`,
382
292
  }]
383
293
  },
384
294
  })
@@ -388,7 +298,10 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
388
298
  name: 'Container Info',
389
299
  description: 'Full introspection of the running Luca container',
390
300
  mimeType: 'text/markdown',
391
- handler: () => container.introspectAsText(),
301
+ handler: async () => {
302
+ const { stdout } = await lucaCLI(proc, 'eval', ['container.introspectAsText()'])
303
+ return stdout
304
+ },
392
305
  })
393
306
 
394
307
  // --- Resource: feature list ---
@@ -396,18 +309,11 @@ export default async function mcpSandbox(options: z.infer<typeof argsSchema>, co
396
309
  name: 'Available Features',
397
310
  description: 'List of all registered features with descriptions',
398
311
  mimeType: 'text/markdown',
399
- handler: () => {
400
- const lines = ['# Available Features\n']
401
- for (const name of container.features.available) {
402
- try {
403
- const Ctor = container.features.lookup(name) as any
404
- const desc = Ctor.description || ''
405
- lines.push(`- **${name}**: ${desc}`)
406
- } catch {
407
- lines.push(`- **${name}**`)
408
- }
409
- }
410
- return lines.join('\n')
312
+ handler: async () => {
313
+ const { stdout } = await lucaCLI(proc, 'eval', [
314
+ '"# Available Features\\n" + container.features.available.map(n => { try { const C = container.features.lookup(n); return "- **" + n + "**: " + (C.description || "") } catch { return "- **" + n + "**" } }).join("\\n")',
315
+ ])
316
+ return stdout
411
317
  },
412
318
  })
413
319
 
@@ -2,6 +2,7 @@ import { z } from 'zod'
2
2
  import { commands } from '../command.js'
3
3
  import { CommandOptionsSchema } from '../schemas/base.js'
4
4
  import type { ContainerContext } from '../container.js'
5
+ import type { NodeContainer } from '../node/container.js'
5
6
 
6
7
  declare module '../command.js' {
7
8
  interface AvailableCommands {
@@ -14,7 +15,7 @@ export const argsSchema = CommandOptionsSchema.extend({
14
15
  })
15
16
 
16
17
  export async function apiDocs(options: z.infer<typeof argsSchema>, context: ContainerContext) {
17
- const { container } = context
18
+ const container = context.container as unknown as NodeContainer
18
19
  await container.helpers.discoverAll()
19
20
  const outputFolder = options.outputPath ? container.paths.resolve(options.outputPath) : container.paths.resolve('docs','luca')
20
21
 
@@ -22,19 +23,20 @@ export async function apiDocs(options: z.infer<typeof argsSchema>, context: Cont
22
23
  outputFolder
23
24
  )
24
25
 
25
- const mkPath = (...args) => container.paths.resolve(outputFolder, ...args)
26
+ const mkPath = (...args: string[]) => container.paths.resolve(outputFolder, ...args)
26
27
 
27
- const result = await container.fs.writeFileAsync(mkPath('agi-container.md'), container.introspectAsText())
28
+ await container.fs.writeFileAsync(mkPath('agi-container.md'), (container as any).introspectAsText())
28
29
 
29
- for(let reg of ['features','clients','servers']) {
30
- const helperIds = container[reg].available
31
- const folder = mkPath(reg)
30
+ for(const reg of ['features','clients','servers']) {
31
+ const registry = (container as any)[reg]
32
+ const helperIds: string[] = registry.available
33
+ const folder = mkPath(reg)
32
34
  await container.fs.ensureFolder(folder)
33
35
 
34
36
  await Promise.all(
35
- helperIds.map((helperId) => container.fs.writeFileAsync(
37
+ helperIds.map((helperId: string) => container.fs.writeFileAsync(
36
38
  container.paths.resolve(folder, `${helperId}.md`),
37
- container[reg].describe(helperId)
39
+ registry.describe(helperId)
38
40
  ))
39
41
  )
40
42
  }
@@ -13,7 +13,7 @@ declare module '../command.js' {
13
13
  export const argsSchema = CommandOptionsSchema.extend({
14
14
  json: z.boolean().default(false).describe('Output result as raw JSON (data only, no metadata)'),
15
15
  noCache: z.boolean().default(false).describe('Skip cache lookup and force a fresh run'),
16
- })
16
+ }).passthrough()
17
17
 
18
18
  export default async function selectCommand(options: z.infer<typeof argsSchema>, context: ContainerContext) {
19
19
  const container = context.container as any
@@ -42,13 +42,18 @@ export default async function selectCommand(options: z.infer<typeof argsSchema>,
42
42
 
43
43
  const instance = container.select(name)
44
44
 
45
- // Pass remaining args (after command name and selector name) as input
46
- const selectorArgs: Record<string, any> = { ...options }
45
+ // Pass remaining args (after command name and selector name) as input.
46
+ // Pull from container.argv directly the select command's own argsSchema
47
+ // would otherwise strip selector-specific keys during Zod parse.
48
+ const rawArgv = { ...(container as any).argv }
49
+ const selectorArgs: Record<string, any> = { ...rawArgv }
47
50
  delete selectorArgs._
48
51
  delete selectorArgs.json
49
52
  delete selectorArgs.noCache
50
53
  delete selectorArgs.cache
51
54
  delete selectorArgs.dispatchSource
55
+ delete selectorArgs.help
56
+ delete selectorArgs.name
52
57
 
53
58
  // minimist turns --no-cache into { cache: false }
54
59
  const skipCache = options.noCache || (container.argv.cache === false)
@@ -1,5 +1,6 @@
1
1
  import type { IntrospectionSection, MethodIntrospection, GetterIntrospection, HelperIntrospection } from './introspection/index.js'
2
2
  import { presentIntrospectionAsMarkdown } from './helper.js'
3
+ import { z } from 'zod'
3
4
 
4
5
  type Platform = 'browser' | 'server' | 'node' | 'all'
5
6
 
@@ -189,93 +190,78 @@ export class ContainerDescriber {
189
190
  * Generate tool definitions suitable for use with AI assistant tool-calling interfaces.
190
191
  * Registry names in the enum are populated dynamically from the container.
191
192
  */
192
- toTools(): Array<{ name: string; description: string; parameters: Record<string, any>; execute: (args: any) => Promise<string> }> {
193
- const registryEnum = this.registryNames
194
-
195
- return [
196
- {
197
- name: 'describe_container',
198
- description: 'Describe the container itself — its class, registries, and configuration.',
199
- parameters: {
200
- type: 'object',
201
- properties: {
202
- sections: {
203
- type: 'array',
204
- items: { type: 'string', enum: ['description', 'usage', 'methods', 'getters', 'events', 'state', 'options', 'envVars', 'examples'] },
205
- description: 'Which sections to include. Omit for all.',
206
- },
207
- },
208
- required: [],
209
- },
210
- execute: async (args: any) => {
211
- const result = await this.describeContainer({ sections: args.sections })
212
- return result.text
213
- },
193
+ toTools(): { schemas: Record<string, z.ZodType>; handlers: Record<string, Function> } {
194
+ const registryEnum = this.registryNames as [string, ...string[]]
195
+ const sectionEnum = ['description', 'usage', 'methods', 'getters', 'events', 'state', 'options', 'envVars', 'examples'] as const
196
+ const platformEnum = ['browser', 'server', 'all'] as const
197
+
198
+ const schemas: Record<string, z.ZodType> = {
199
+ describe_container: z.object({
200
+ sections: z.array(z.enum(sectionEnum)).optional().describe('Which sections to include. Omit for all.'),
201
+ }).describe('Describe the container itself — its class, registries, and configuration.'),
202
+
203
+ describe_registry: z.object({
204
+ registry: z.enum(registryEnum).describe(`Which registry to describe. Available: ${registryEnum.join(', ')}`),
205
+ platform: z.enum(platformEnum).optional().describe('Filter by platform. Defaults to all.'),
206
+ sections: z.array(z.enum(sectionEnum)).optional().describe('Which sections to include per helper. Omit for concise index.'),
207
+ }).describe(`List all helpers in a registry with concise summaries. Available registries: ${registryEnum.join(', ')}`),
208
+
209
+ describe_helper: z.object({
210
+ target: z.string().describe('The helper to describe. Examples: "fs", "features.fs", "fs.readFile", "ui.banner"'),
211
+ platform: z.enum(platformEnum).optional().describe('Filter by platform. Defaults to all.'),
212
+ sections: z.array(z.enum(sectionEnum)).optional().describe('Which sections to include. Omit for all.'),
213
+ }).describe('Describe a specific helper by name. Supports qualified names like "features.fs" or unqualified like "fs". Also supports member access like "fs.readFile" or "ui.banner".'),
214
+ }
215
+
216
+ const handlers: Record<string, Function> = {
217
+ describe_container: async (args: any) => {
218
+ const result = await this.describeContainer({ sections: args.sections })
219
+ return result.text
214
220
  },
215
- {
216
- name: 'describe_registry',
217
- description: `List all helpers in a registry with concise summaries. Available registries: ${registryEnum.join(', ')}`,
218
- parameters: {
219
- type: 'object',
220
- properties: {
221
- registry: {
222
- type: 'string',
223
- enum: registryEnum,
224
- description: 'Which registry to describe.',
225
- },
226
- platform: {
227
- type: 'string',
228
- enum: ['browser', 'server', 'all'],
229
- description: 'Filter by platform. Defaults to all.',
230
- },
231
- sections: {
232
- type: 'array',
233
- items: { type: 'string', enum: ['description', 'usage', 'methods', 'getters', 'events', 'state', 'options', 'envVars', 'examples'] },
234
- description: 'Which sections to include per helper. Omit for concise index.',
235
- },
236
- },
237
- required: ['registry'],
238
- },
239
- execute: async (args: any) => {
240
- const result = await this.describeRegistry(args.registry, {
241
- sections: args.sections,
242
- platform: args.platform,
243
- })
244
- return result.text
245
- },
221
+ describe_registry: async (args: any) => {
222
+ const result = await this.describeRegistry(args.registry, {
223
+ sections: args.sections,
224
+ platform: args.platform,
225
+ })
226
+ return result.text
246
227
  },
247
- {
248
- name: 'describe_helper',
249
- description: 'Describe a specific helper by name. Supports qualified names like "features.fs" or unqualified like "fs". Also supports member access like "fs.readFile" or "ui.banner".',
250
- parameters: {
251
- type: 'object',
252
- properties: {
253
- target: {
254
- type: 'string',
255
- description: 'The helper to describe. Examples: "fs", "features.fs", "fs.readFile", "ui.banner"',
256
- },
257
- platform: {
258
- type: 'string',
259
- enum: ['browser', 'server', 'all'],
260
- description: 'Filter by platform. Defaults to all.',
261
- },
262
- sections: {
263
- type: 'array',
264
- items: { type: 'string', enum: ['description', 'usage', 'methods', 'getters', 'events', 'state', 'options', 'envVars', 'examples'] },
265
- description: 'Which sections to include. Omit for all.',
266
- },
267
- },
268
- required: ['target'],
269
- },
270
- execute: async (args: any) => {
271
- const result = await this.describeHelper(args.target, {
272
- sections: args.sections,
273
- platform: args.platform,
274
- })
275
- return result.text
276
- },
228
+ describe_helper: async (args: any) => {
229
+ const result = await this.describeHelper(args.target, {
230
+ sections: args.sections,
231
+ platform: args.platform,
232
+ })
233
+ return result.text
277
234
  },
278
- ]
235
+ }
236
+
237
+ return { schemas, handlers }
238
+ }
239
+
240
+ /**
241
+ * Register the describer tools on an assistant and append a system prompt
242
+ * extension explaining how and when to use them.
243
+ *
244
+ * @param assistant - Any assistant instance that exposes `use()` and `addSystemPromptExtension()`
245
+ */
246
+ setupToolsConsumer(assistant: {
247
+ use: (tools: { schemas: Record<string, z.ZodType>; handlers: Record<string, Function> }) => void
248
+ addSystemPromptExtension: (key: string, value: string) => void
249
+ }): void {
250
+ assistant.use(this.toTools())
251
+
252
+ const registries = this.registryNames.join(', ')
253
+
254
+ assistant.addSystemPromptExtension('container_describer', `
255
+ ## Container Introspection Tools
256
+
257
+ You have access to three tools for exploring the runtime container and its helpers:
258
+
259
+ - **describe_container** — Overview of the container itself: its registries, configuration, and what it provides.
260
+ - **describe_registry** — List all helpers in a registry with concise summaries. Available registries: ${registries}.
261
+ - **describe_helper** — Full docs for a specific helper. Accepts unqualified names ("fs"), registry-qualified names ("features.fs"), or member access ("fs.readFile", "ui.banner").
262
+
263
+ Use these tools whenever you are unsure what helpers are available, what a helper does, or how to call one of its methods. Always prefer introspecting the container over guessing at method signatures.
264
+ `.trim())
279
265
  }
280
266
 
281
267
  // --- Resolution ---