luca 2.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 (532) hide show
  1. package/.github/workflows/release.yaml +170 -0
  2. package/AGENTS.md +99 -0
  3. package/CLAUDE.md +123 -0
  4. package/CNAME +1 -0
  5. package/README.md +275 -9
  6. package/RUNME.md +56 -0
  7. package/assistants/codingAssistant/ABOUT.md +5 -0
  8. package/assistants/codingAssistant/CORE.md +33 -0
  9. package/assistants/codingAssistant/hooks.ts +21 -0
  10. package/assistants/codingAssistant/tools.ts +12 -0
  11. package/assistants/inkbot/ABOUT.md +16 -0
  12. package/assistants/inkbot/CORE.md +330 -0
  13. package/assistants/inkbot/hooks.ts +6 -0
  14. package/assistants/inkbot/tools.ts +53 -0
  15. package/assistants/researcher/ABOUT.md +5 -0
  16. package/assistants/researcher/CORE.md +46 -0
  17. package/assistants/researcher/hooks.ts +16 -0
  18. package/assistants/researcher/tools.ts +237 -0
  19. package/bun.lock +2667 -0
  20. package/bunfig.toml +3 -0
  21. package/commands/audit-docs.ts +740 -0
  22. package/commands/build-bootstrap.ts +117 -0
  23. package/commands/build-python-bridge.ts +42 -0
  24. package/commands/build-scaffolds.ts +175 -0
  25. package/commands/bundle-consumer-project.ts +521 -0
  26. package/commands/generate-api-docs.ts +114 -0
  27. package/commands/inkbot.ts +874 -0
  28. package/commands/release.ts +80 -0
  29. package/commands/try-all-challenges.ts +543 -0
  30. package/commands/try-challenge.ts +100 -0
  31. package/dist/agi/container.server.d.ts +63 -0
  32. package/dist/agi/container.server.d.ts.map +1 -0
  33. package/dist/agi/endpoints/ask.d.ts +20 -0
  34. package/dist/agi/endpoints/ask.d.ts.map +1 -0
  35. package/dist/agi/endpoints/conversations/[id].d.ts +27 -0
  36. package/dist/agi/endpoints/conversations/[id].d.ts.map +1 -0
  37. package/dist/agi/endpoints/conversations.d.ts +18 -0
  38. package/dist/agi/endpoints/conversations.d.ts.map +1 -0
  39. package/dist/agi/endpoints/experts.d.ts +8 -0
  40. package/dist/agi/endpoints/experts.d.ts.map +1 -0
  41. package/dist/agi/feature.d.ts +9 -0
  42. package/dist/agi/feature.d.ts.map +1 -0
  43. package/dist/agi/features/assistant.d.ts +509 -0
  44. package/dist/agi/features/assistant.d.ts.map +1 -0
  45. package/dist/agi/features/assistants-manager.d.ts +236 -0
  46. package/dist/agi/features/assistants-manager.d.ts.map +1 -0
  47. package/dist/agi/features/autonomous-assistant.d.ts +281 -0
  48. package/dist/agi/features/autonomous-assistant.d.ts.map +1 -0
  49. package/dist/agi/features/browser-use.d.ts +479 -0
  50. package/dist/agi/features/browser-use.d.ts.map +1 -0
  51. package/dist/agi/features/claude-code.d.ts +824 -0
  52. package/dist/agi/features/claude-code.d.ts.map +1 -0
  53. package/dist/agi/features/conversation-history.d.ts +245 -0
  54. package/dist/agi/features/conversation-history.d.ts.map +1 -0
  55. package/dist/agi/features/conversation.d.ts +464 -0
  56. package/dist/agi/features/conversation.d.ts.map +1 -0
  57. package/dist/agi/features/docs-reader.d.ts +72 -0
  58. package/dist/agi/features/docs-reader.d.ts.map +1 -0
  59. package/dist/agi/features/file-tools.d.ts +110 -0
  60. package/dist/agi/features/file-tools.d.ts.map +1 -0
  61. package/dist/agi/features/luca-coder.d.ts +323 -0
  62. package/dist/agi/features/luca-coder.d.ts.map +1 -0
  63. package/dist/agi/features/openai-codex.d.ts +381 -0
  64. package/dist/agi/features/openai-codex.d.ts.map +1 -0
  65. package/dist/agi/features/openapi.d.ts +200 -0
  66. package/dist/agi/features/openapi.d.ts.map +1 -0
  67. package/dist/agi/features/skills-library.d.ts +167 -0
  68. package/dist/agi/features/skills-library.d.ts.map +1 -0
  69. package/dist/agi/index.d.ts +5 -0
  70. package/dist/agi/index.d.ts.map +1 -0
  71. package/dist/agi/lib/interceptor-chain.d.ts +44 -0
  72. package/dist/agi/lib/interceptor-chain.d.ts.map +1 -0
  73. package/dist/agi/lib/token-counter.d.ts +13 -0
  74. package/dist/agi/lib/token-counter.d.ts.map +1 -0
  75. package/dist/bootstrap/generated.d.ts +5 -0
  76. package/dist/bootstrap/generated.d.ts.map +1 -0
  77. package/dist/browser.d.ts +12 -0
  78. package/dist/browser.d.ts.map +1 -0
  79. package/dist/bus.d.ts +29 -0
  80. package/dist/bus.d.ts.map +1 -0
  81. package/dist/cli/build-info.d.ts +4 -0
  82. package/dist/cli/build-info.d.ts.map +1 -0
  83. package/dist/cli/cli.d.ts +3 -12
  84. package/dist/cli/cli.d.ts.map +1 -0
  85. package/dist/client.d.ts +60 -0
  86. package/dist/client.d.ts.map +1 -0
  87. package/dist/clients/civitai/index.d.ts +472 -0
  88. package/dist/clients/civitai/index.d.ts.map +1 -0
  89. package/dist/clients/client-template.d.ts +30 -0
  90. package/dist/clients/client-template.d.ts.map +1 -0
  91. package/dist/clients/comfyui/index.d.ts +281 -0
  92. package/dist/clients/comfyui/index.d.ts.map +1 -0
  93. package/dist/clients/elevenlabs/index.d.ts +197 -0
  94. package/dist/clients/elevenlabs/index.d.ts.map +1 -0
  95. package/dist/clients/graph.d.ts +64 -0
  96. package/dist/clients/graph.d.ts.map +1 -0
  97. package/dist/clients/openai/index.d.ts +247 -0
  98. package/dist/clients/openai/index.d.ts.map +1 -0
  99. package/dist/clients/rest.d.ts +92 -0
  100. package/dist/clients/rest.d.ts.map +1 -0
  101. package/dist/clients/supabase/index.d.ts +176 -0
  102. package/dist/clients/supabase/index.d.ts.map +1 -0
  103. package/dist/clients/websocket.d.ts +127 -0
  104. package/dist/clients/websocket.d.ts.map +1 -0
  105. package/dist/command.d.ts +163 -0
  106. package/dist/command.d.ts.map +1 -0
  107. package/dist/commands/bootstrap.d.ts +20 -0
  108. package/dist/commands/bootstrap.d.ts.map +1 -0
  109. package/dist/commands/chat.d.ts +37 -0
  110. package/dist/commands/chat.d.ts.map +1 -0
  111. package/dist/commands/code.d.ts +28 -0
  112. package/dist/commands/code.d.ts.map +1 -0
  113. package/dist/commands/console.d.ts +22 -0
  114. package/dist/commands/console.d.ts.map +1 -0
  115. package/dist/commands/describe.d.ts +50 -0
  116. package/dist/commands/describe.d.ts.map +1 -0
  117. package/dist/commands/eval.d.ts +23 -0
  118. package/dist/commands/eval.d.ts.map +1 -0
  119. package/dist/commands/help.d.ts +25 -0
  120. package/dist/commands/help.d.ts.map +1 -0
  121. package/dist/commands/index.d.ts +18 -0
  122. package/dist/commands/index.d.ts.map +1 -0
  123. package/dist/commands/introspect.d.ts +24 -0
  124. package/dist/commands/introspect.d.ts.map +1 -0
  125. package/dist/commands/mcp.d.ts +35 -0
  126. package/dist/commands/mcp.d.ts.map +1 -0
  127. package/dist/commands/prompt.d.ts +38 -0
  128. package/dist/commands/prompt.d.ts.map +1 -0
  129. package/dist/commands/run.d.ts +24 -0
  130. package/dist/commands/run.d.ts.map +1 -0
  131. package/dist/commands/sandbox-mcp.d.ts +34 -0
  132. package/dist/commands/sandbox-mcp.d.ts.map +1 -0
  133. package/dist/commands/save-api-docs.d.ts +21 -0
  134. package/dist/commands/save-api-docs.d.ts.map +1 -0
  135. package/dist/commands/scaffold.d.ts +24 -0
  136. package/dist/commands/scaffold.d.ts.map +1 -0
  137. package/dist/commands/select.d.ts +22 -0
  138. package/dist/commands/select.d.ts.map +1 -0
  139. package/dist/commands/serve.d.ts +29 -0
  140. package/dist/commands/serve.d.ts.map +1 -0
  141. package/dist/container-describer.d.ts +144 -0
  142. package/dist/container-describer.d.ts.map +1 -0
  143. package/dist/container.d.ts +451 -0
  144. package/dist/container.d.ts.map +1 -0
  145. package/dist/endpoint.d.ts +113 -0
  146. package/dist/endpoint.d.ts.map +1 -0
  147. package/dist/feature.d.ts +47 -0
  148. package/dist/feature.d.ts.map +1 -0
  149. package/dist/graft.d.ts +29 -0
  150. package/dist/graft.d.ts.map +1 -0
  151. package/dist/hash-object.d.ts +8 -0
  152. package/dist/hash-object.d.ts.map +1 -0
  153. package/dist/helper.d.ts +209 -0
  154. package/dist/helper.d.ts.map +1 -0
  155. package/dist/introspection/generated.node.d.ts +44623 -0
  156. package/dist/introspection/generated.node.d.ts.map +1 -0
  157. package/dist/introspection/generated.web.d.ts +1412 -0
  158. package/dist/introspection/generated.web.d.ts.map +1 -0
  159. package/dist/introspection/index.d.ts +156 -0
  160. package/dist/introspection/index.d.ts.map +1 -0
  161. package/dist/introspection/scan.d.ts +147 -0
  162. package/dist/introspection/scan.d.ts.map +1 -0
  163. package/dist/node/container.d.ts +256 -0
  164. package/dist/node/container.d.ts.map +1 -0
  165. package/dist/node/feature.d.ts +9 -0
  166. package/dist/node/feature.d.ts.map +1 -0
  167. package/dist/node/features/container-link.d.ts +213 -0
  168. package/dist/node/features/container-link.d.ts.map +1 -0
  169. package/dist/node/features/content-db.d.ts +354 -0
  170. package/dist/node/features/content-db.d.ts.map +1 -0
  171. package/dist/node/features/disk-cache.d.ts +236 -0
  172. package/dist/node/features/disk-cache.d.ts.map +1 -0
  173. package/dist/node/features/dns.d.ts +511 -0
  174. package/dist/node/features/dns.d.ts.map +1 -0
  175. package/dist/node/features/docker.d.ts +485 -0
  176. package/dist/node/features/docker.d.ts.map +1 -0
  177. package/dist/node/features/downloader.d.ts +73 -0
  178. package/dist/node/features/downloader.d.ts.map +1 -0
  179. package/dist/node/features/figlet-fonts.d.ts +4 -0
  180. package/dist/node/features/figlet-fonts.d.ts.map +1 -0
  181. package/dist/node/features/file-manager.d.ts +177 -0
  182. package/dist/node/features/file-manager.d.ts.map +1 -0
  183. package/dist/node/features/fs.d.ts +635 -0
  184. package/dist/node/features/fs.d.ts.map +1 -0
  185. package/dist/node/features/git.d.ts +329 -0
  186. package/dist/node/features/git.d.ts.map +1 -0
  187. package/dist/node/features/google-auth.d.ts +200 -0
  188. package/dist/node/features/google-auth.d.ts.map +1 -0
  189. package/dist/node/features/google-calendar.d.ts +194 -0
  190. package/dist/node/features/google-calendar.d.ts.map +1 -0
  191. package/dist/node/features/google-docs.d.ts +138 -0
  192. package/dist/node/features/google-docs.d.ts.map +1 -0
  193. package/dist/node/features/google-drive.d.ts +202 -0
  194. package/dist/node/features/google-drive.d.ts.map +1 -0
  195. package/dist/node/features/google-mail.d.ts +221 -0
  196. package/dist/node/features/google-mail.d.ts.map +1 -0
  197. package/dist/node/features/google-sheets.d.ts +157 -0
  198. package/dist/node/features/google-sheets.d.ts.map +1 -0
  199. package/dist/node/features/grep.d.ts +207 -0
  200. package/dist/node/features/grep.d.ts.map +1 -0
  201. package/dist/node/features/helpers.d.ts +236 -0
  202. package/dist/node/features/helpers.d.ts.map +1 -0
  203. package/dist/node/features/ink.d.ts +332 -0
  204. package/dist/node/features/ink.d.ts.map +1 -0
  205. package/dist/node/features/ipc-socket.d.ts +298 -0
  206. package/dist/node/features/ipc-socket.d.ts.map +1 -0
  207. package/dist/node/features/json-tree.d.ts +140 -0
  208. package/dist/node/features/json-tree.d.ts.map +1 -0
  209. package/dist/node/features/networking.d.ts +373 -0
  210. package/dist/node/features/networking.d.ts.map +1 -0
  211. package/dist/node/features/nlp.d.ts +125 -0
  212. package/dist/node/features/nlp.d.ts.map +1 -0
  213. package/dist/node/features/opener.d.ts +93 -0
  214. package/dist/node/features/opener.d.ts.map +1 -0
  215. package/dist/node/features/os.d.ts +168 -0
  216. package/dist/node/features/os.d.ts.map +1 -0
  217. package/dist/node/features/package-finder.d.ts +419 -0
  218. package/dist/node/features/package-finder.d.ts.map +1 -0
  219. package/dist/node/features/postgres.d.ts +173 -0
  220. package/dist/node/features/postgres.d.ts.map +1 -0
  221. package/dist/node/features/proc.d.ts +285 -0
  222. package/dist/node/features/proc.d.ts.map +1 -0
  223. package/dist/node/features/process-manager.d.ts +427 -0
  224. package/dist/node/features/process-manager.d.ts.map +1 -0
  225. package/dist/node/features/python.d.ts +477 -0
  226. package/dist/node/features/python.d.ts.map +1 -0
  227. package/dist/node/features/redis.d.ts +247 -0
  228. package/dist/node/features/redis.d.ts.map +1 -0
  229. package/dist/node/features/repl.d.ts +84 -0
  230. package/dist/node/features/repl.d.ts.map +1 -0
  231. package/dist/node/features/runpod.d.ts +527 -0
  232. package/dist/node/features/runpod.d.ts.map +1 -0
  233. package/dist/node/features/secure-shell.d.ts +145 -0
  234. package/dist/node/features/secure-shell.d.ts.map +1 -0
  235. package/dist/node/features/semantic-search.d.ts +207 -0
  236. package/dist/node/features/semantic-search.d.ts.map +1 -0
  237. package/dist/node/features/sqlite.d.ts +180 -0
  238. package/dist/node/features/sqlite.d.ts.map +1 -0
  239. package/dist/node/features/telegram.d.ts +173 -0
  240. package/dist/node/features/telegram.d.ts.map +1 -0
  241. package/dist/node/features/transpiler.d.ts +51 -0
  242. package/dist/node/features/transpiler.d.ts.map +1 -0
  243. package/dist/node/features/tts.d.ts +108 -0
  244. package/dist/node/features/tts.d.ts.map +1 -0
  245. package/dist/node/features/ui.d.ts +562 -0
  246. package/dist/node/features/ui.d.ts.map +1 -0
  247. package/dist/node/features/vault.d.ts +90 -0
  248. package/dist/node/features/vault.d.ts.map +1 -0
  249. package/dist/node/features/vm.d.ts +285 -0
  250. package/dist/node/features/vm.d.ts.map +1 -0
  251. package/dist/node/features/yaml-tree.d.ts +118 -0
  252. package/dist/node/features/yaml-tree.d.ts.map +1 -0
  253. package/dist/node/features/yaml.d.ts +127 -0
  254. package/dist/node/features/yaml.d.ts.map +1 -0
  255. package/dist/node.d.ts +67 -0
  256. package/dist/node.d.ts.map +1 -0
  257. package/dist/python/generated.d.ts +2 -0
  258. package/dist/python/generated.d.ts.map +1 -0
  259. package/dist/react/index.d.ts +36 -0
  260. package/dist/react/index.d.ts.map +1 -0
  261. package/dist/registry.d.ts +97 -0
  262. package/dist/registry.d.ts.map +1 -0
  263. package/dist/scaffolds/generated.d.ts +13 -0
  264. package/dist/scaffolds/generated.d.ts.map +1 -0
  265. package/dist/scaffolds/template.d.ts +11 -0
  266. package/dist/scaffolds/template.d.ts.map +1 -0
  267. package/dist/schemas/base.d.ts +254 -0
  268. package/dist/schemas/base.d.ts.map +1 -0
  269. package/dist/selector.d.ts +130 -0
  270. package/dist/selector.d.ts.map +1 -0
  271. package/dist/server.d.ts +89 -0
  272. package/dist/server.d.ts.map +1 -0
  273. package/dist/servers/express.d.ts +104 -0
  274. package/dist/servers/express.d.ts.map +1 -0
  275. package/dist/servers/mcp.d.ts +201 -0
  276. package/dist/servers/mcp.d.ts.map +1 -0
  277. package/dist/servers/socket.d.ts +121 -0
  278. package/dist/servers/socket.d.ts.map +1 -0
  279. package/dist/state.d.ts +24 -0
  280. package/dist/state.d.ts.map +1 -0
  281. package/dist/web/clients/socket.d.ts +37 -0
  282. package/dist/web/clients/socket.d.ts.map +1 -0
  283. package/dist/web/container.d.ts +55 -0
  284. package/dist/web/container.d.ts.map +1 -0
  285. package/dist/web/extension.d.ts +4 -0
  286. package/dist/web/extension.d.ts.map +1 -0
  287. package/dist/web/feature.d.ts +8 -0
  288. package/dist/web/feature.d.ts.map +1 -0
  289. package/dist/web/features/asset-loader.d.ts +35 -0
  290. package/dist/web/features/asset-loader.d.ts.map +1 -0
  291. package/dist/web/features/container-link.d.ts +167 -0
  292. package/dist/web/features/container-link.d.ts.map +1 -0
  293. package/dist/web/features/esbuild.d.ts +51 -0
  294. package/dist/web/features/esbuild.d.ts.map +1 -0
  295. package/dist/web/features/helpers.d.ts +140 -0
  296. package/dist/web/features/helpers.d.ts.map +1 -0
  297. package/dist/web/features/network.d.ts +69 -0
  298. package/dist/web/features/network.d.ts.map +1 -0
  299. package/dist/web/features/speech.d.ts +71 -0
  300. package/dist/web/features/speech.d.ts.map +1 -0
  301. package/dist/web/features/vault.d.ts +62 -0
  302. package/dist/web/features/vault.d.ts.map +1 -0
  303. package/dist/web/features/vm.d.ts +48 -0
  304. package/dist/web/features/vm.d.ts.map +1 -0
  305. package/dist/web/features/voice-recognition.d.ts +96 -0
  306. package/dist/web/features/voice-recognition.d.ts.map +1 -0
  307. package/dist/web/shims/isomorphic-vm.d.ts +22 -0
  308. package/dist/web/shims/isomorphic-vm.d.ts.map +1 -0
  309. package/index.html +1457 -0
  310. package/index.ts +1 -0
  311. package/install.sh +84 -0
  312. package/luca.cli.ts +16 -0
  313. package/luca.console.ts +9 -0
  314. package/main.py +6 -0
  315. package/package.json +219 -58
  316. package/public/index.html +1457 -0
  317. package/public/slides-ai-native.html +902 -0
  318. package/public/slides-intro.html +974 -0
  319. package/pyproject.toml +7 -0
  320. package/scripts/build-web.ts +28 -0
  321. package/scripts/examples/ask-luca-expert.ts +42 -0
  322. package/scripts/examples/assistant-questions.ts +12 -0
  323. package/scripts/examples/excalidraw-expert.ts +75 -0
  324. package/scripts/examples/expert-chat.ts +0 -0
  325. package/scripts/examples/file-manager.ts +14 -0
  326. package/scripts/examples/ideas.ts +12 -0
  327. package/scripts/examples/interactive-chat.ts +20 -0
  328. package/scripts/examples/openai-tool-calls.ts +113 -0
  329. package/scripts/examples/opening-a-web-browser.ts +5 -0
  330. package/scripts/examples/telegram-bot.ts +79 -0
  331. package/scripts/examples/using-assistant-with-mcp.ts +555 -0
  332. package/scripts/examples/using-claude-code.ts +10 -0
  333. package/scripts/examples/using-contentdb.ts +35 -0
  334. package/scripts/examples/using-conversations.ts +35 -0
  335. package/scripts/examples/using-disk-cache.ts +10 -0
  336. package/scripts/examples/using-docker-shell.ts +75 -0
  337. package/scripts/examples/using-elevenlabs.ts +25 -0
  338. package/scripts/examples/using-google-calendar.ts +57 -0
  339. package/scripts/examples/using-google-docs.ts +74 -0
  340. package/scripts/examples/using-google-drive.ts +74 -0
  341. package/scripts/examples/using-google-sheets.ts +89 -0
  342. package/scripts/examples/using-nlp.ts +55 -0
  343. package/scripts/examples/using-ollama.ts +11 -0
  344. package/scripts/examples/using-postgres.ts +55 -0
  345. package/scripts/examples/using-runpod.ts +32 -0
  346. package/scripts/examples/using-tts.ts +40 -0
  347. package/scripts/scaffold.ts +391 -0
  348. package/scripts/scratch.ts +15 -0
  349. package/scripts/stamp-build.sh +12 -0
  350. package/scripts/test-assistant-hooks.ts +13 -0
  351. package/scripts/test-docs-reader.ts +10 -0
  352. package/scripts/test-linux-binary.sh +80 -0
  353. package/scripts/update-introspection-data.ts +58 -0
  354. package/src/agi/README.md +14 -0
  355. package/src/agi/container.server.ts +156 -0
  356. package/src/agi/feature.ts +13 -0
  357. package/src/agi/features/agent-memory.ts +694 -0
  358. package/src/agi/features/assistant.ts +1653 -0
  359. package/src/agi/features/assistants-manager.ts +534 -0
  360. package/src/agi/features/autonomous-assistant.ts +431 -0
  361. package/src/agi/features/browser-use.ts +672 -0
  362. package/src/agi/features/claude-code.ts +1584 -0
  363. package/src/agi/features/coding-tools.ts +175 -0
  364. package/src/agi/features/conversation-history.ts +672 -0
  365. package/src/agi/features/conversation.ts +1494 -0
  366. package/src/agi/features/docs-reader.ts +167 -0
  367. package/src/agi/features/file-tools.ts +340 -0
  368. package/src/agi/features/luca-coder.ts +641 -0
  369. package/src/agi/features/mcp-bridge.ts +532 -0
  370. package/src/agi/features/openai-codex.ts +651 -0
  371. package/src/agi/features/openapi.ts +445 -0
  372. package/src/agi/features/skills-library.ts +557 -0
  373. package/src/agi/index.ts +6 -0
  374. package/src/agi/lib/interceptor-chain.ts +89 -0
  375. package/src/agi/lib/token-counter.ts +202 -0
  376. package/src/bootstrap/generated.ts +9791 -0
  377. package/src/browser.ts +25 -0
  378. package/src/bus.ts +122 -0
  379. package/src/cli/build-info.ts +4 -0
  380. package/src/cli/cli.ts +355 -0
  381. package/src/client.ts +170 -0
  382. package/src/clients/civitai/index.ts +537 -0
  383. package/src/clients/client-template.ts +41 -0
  384. package/src/clients/comfyui/index.ts +604 -0
  385. package/src/clients/elevenlabs/index.ts +317 -0
  386. package/src/clients/graph.ts +87 -0
  387. package/src/clients/openai/index.ts +456 -0
  388. package/src/clients/rest.ts +207 -0
  389. package/src/clients/supabase/index.ts +357 -0
  390. package/src/clients/voicebox/index.ts +300 -0
  391. package/src/clients/websocket.ts +251 -0
  392. package/src/command.ts +506 -0
  393. package/src/commands/bootstrap.ts +244 -0
  394. package/src/commands/chat.ts +309 -0
  395. package/src/commands/code.ts +371 -0
  396. package/src/commands/console.ts +189 -0
  397. package/src/commands/describe.ts +243 -0
  398. package/src/commands/eval.ts +67 -0
  399. package/src/commands/help.ts +240 -0
  400. package/src/commands/index.ts +19 -0
  401. package/src/commands/introspect.ts +218 -0
  402. package/src/commands/mcp.ts +64 -0
  403. package/src/commands/prompt.ts +1014 -0
  404. package/src/commands/run.ts +278 -0
  405. package/src/commands/sandbox-mcp.ts +343 -0
  406. package/src/commands/save-api-docs.ts +51 -0
  407. package/src/commands/scaffold.ts +225 -0
  408. package/src/commands/select.ts +99 -0
  409. package/src/commands/serve.ts +208 -0
  410. package/src/container-describer.ts +1091 -0
  411. package/src/container.ts +1199 -0
  412. package/src/endpoint.ts +365 -0
  413. package/src/entity.ts +173 -0
  414. package/src/feature.ts +118 -0
  415. package/src/graft.ts +181 -0
  416. package/src/hash-object.ts +97 -0
  417. package/src/helper.ts +849 -0
  418. package/src/introspection/generated.agi.ts +41200 -0
  419. package/src/introspection/generated.node.ts +28773 -0
  420. package/src/introspection/generated.web.ts +2272 -0
  421. package/src/introspection/index.ts +296 -0
  422. package/src/introspection/scan.ts +1136 -0
  423. package/src/node/container.ts +409 -0
  424. package/src/node/feature.ts +13 -0
  425. package/src/node/features/container-link.ts +559 -0
  426. package/src/node/features/content-db.ts +849 -0
  427. package/src/node/features/disk-cache.ts +388 -0
  428. package/src/node/features/display-result.ts +57 -0
  429. package/src/node/features/dns.ts +669 -0
  430. package/src/node/features/docker.ts +921 -0
  431. package/src/node/features/downloader.ts +79 -0
  432. package/src/node/features/figlet-fonts.ts +600 -0
  433. package/src/node/features/file-manager.ts +535 -0
  434. package/src/node/features/fs.ts +1050 -0
  435. package/src/node/features/git.ts +592 -0
  436. package/src/node/features/google-auth.ts +504 -0
  437. package/src/node/features/google-calendar.ts +306 -0
  438. package/src/node/features/google-docs.ts +412 -0
  439. package/src/node/features/google-drive.ts +346 -0
  440. package/src/node/features/google-mail.ts +540 -0
  441. package/src/node/features/google-sheets.ts +286 -0
  442. package/src/node/features/grep.ts +427 -0
  443. package/src/node/features/helpers.ts +762 -0
  444. package/src/node/features/ink.ts +490 -0
  445. package/src/node/features/ipc-socket.ts +649 -0
  446. package/src/node/features/json-tree.ts +170 -0
  447. package/src/node/features/networking.ts +961 -0
  448. package/src/node/features/nlp.ts +212 -0
  449. package/src/node/features/opener.ts +180 -0
  450. package/src/node/features/os.ts +403 -0
  451. package/src/node/features/package-finder.ts +540 -0
  452. package/src/node/features/postgres.ts +289 -0
  453. package/src/node/features/proc.ts +503 -0
  454. package/src/node/features/process-manager.ts +844 -0
  455. package/src/node/features/python.ts +912 -0
  456. package/src/node/features/redis.ts +446 -0
  457. package/src/node/features/repl.ts +212 -0
  458. package/src/node/features/runpod.ts +811 -0
  459. package/src/node/features/secure-shell.ts +261 -0
  460. package/src/node/features/semantic-search.ts +935 -0
  461. package/src/node/features/sqlite.ts +289 -0
  462. package/src/node/features/telegram.ts +343 -0
  463. package/src/node/features/transpiler.ts +160 -0
  464. package/src/node/features/tts.ts +185 -0
  465. package/src/node/features/ui.ts +791 -0
  466. package/src/node/features/vault.ts +153 -0
  467. package/src/node/features/vm.ts +462 -0
  468. package/src/node/features/yaml-tree.ts +148 -0
  469. package/src/node/features/yaml.ts +133 -0
  470. package/src/node.ts +76 -0
  471. package/src/python/bridge.py +220 -0
  472. package/src/python/generated.ts +226 -0
  473. package/src/react/index.ts +175 -0
  474. package/src/registry.ts +210 -0
  475. package/src/scaffolds/generated.ts +1814 -0
  476. package/src/scaffolds/template.ts +46 -0
  477. package/src/schemas/base.ts +296 -0
  478. package/src/selector.ts +352 -0
  479. package/src/server.ts +229 -0
  480. package/src/servers/express.ts +283 -0
  481. package/src/servers/mcp.ts +802 -0
  482. package/src/servers/socket.ts +258 -0
  483. package/src/state.ts +101 -0
  484. package/src/web/clients/socket.ts +99 -0
  485. package/src/web/container.ts +75 -0
  486. package/src/web/extension.ts +30 -0
  487. package/src/web/feature.ts +12 -0
  488. package/src/web/features/asset-loader.ts +72 -0
  489. package/src/web/features/container-link.ts +382 -0
  490. package/src/web/features/esbuild.ts +93 -0
  491. package/src/web/features/helpers.ts +291 -0
  492. package/src/web/features/network.ts +85 -0
  493. package/src/web/features/speech.ts +104 -0
  494. package/src/web/features/vault.ts +207 -0
  495. package/src/web/features/vm.ts +85 -0
  496. package/src/web/features/voice-recognition.ts +161 -0
  497. package/src/web/shims/isomorphic-vm.ts +149 -0
  498. package/tsconfig.build.json +12 -0
  499. package/tsconfig.json +58 -0
  500. package/uv.lock +8 -0
  501. package/LICENSE +0 -21
  502. package/dist/cli/cli.js +0 -48
  503. package/dist/cli/common.d.ts +0 -2
  504. package/dist/cli/common.js +0 -6
  505. package/dist/cli/index.d.ts +0 -2
  506. package/dist/cli/index.js +0 -5
  507. package/dist/cli/run.d.ts +0 -1
  508. package/dist/cli/run.js +0 -38
  509. package/dist/core/index.d.ts +0 -4
  510. package/dist/core/index.js +0 -32
  511. package/dist/core/read.d.ts +0 -2
  512. package/dist/core/read.js +0 -29
  513. package/dist/core/request.d.ts +0 -1
  514. package/dist/core/request.js +0 -2
  515. package/dist/core/write.d.ts +0 -2
  516. package/dist/core/write.js +0 -21
  517. package/dist/index.d.ts +0 -1
  518. package/dist/index.js +0 -5
  519. package/dist/utils/common.d.ts +0 -9
  520. package/dist/utils/common.js +0 -57
  521. package/dist/utils/consts.d.ts +0 -3
  522. package/dist/utils/consts.js +0 -11
  523. package/dist/utils/dict.d.ts +0 -1
  524. package/dist/utils/dict.js +0 -7
  525. package/dist/utils/index.d.ts +0 -5
  526. package/dist/utils/index.js +0 -21
  527. package/dist/utils/log.d.ts +0 -1
  528. package/dist/utils/log.js +0 -5
  529. package/dist/utils/types.d.ts +0 -1
  530. package/dist/utils/types.js +0 -2
  531. package/dist/utils/utils.test.d.ts +0 -1
  532. package/dist/utils/utils.test.js +0 -7
@@ -0,0 +1,534 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
3
+ import { type AvailableFeatures } from 'luca/feature'
4
+ import { Feature } from '../feature.js'
5
+ import type { Assistant } from './assistant.js'
6
+ import type { ConversationHistory, ConversationMeta, ConversationRecord } from './conversation-history.js'
7
+ import type { InterceptorFn, InterceptorPoint, InterceptorPoints } from '../lib/interceptor-chain.js'
8
+ import hashObject from '../../hash-object.js'
9
+
10
+ declare module 'luca/feature' {
11
+ interface AvailableFeatures {
12
+ assistantsManager: typeof AssistantsManager
13
+ }
14
+ }
15
+
16
+ /**
17
+ * Metadata for a discovered assistant subdirectory.
18
+ */
19
+ export interface AssistantEntry {
20
+ /** The subdirectory name, used as the assistant identifier. */
21
+ name: string
22
+ /** Absolute path to the assistant folder. */
23
+ folder: string
24
+ /** Whether a CORE.md system prompt file exists. */
25
+ hasCorePrompt: boolean
26
+ /** Whether a tools.ts file exists. */
27
+ hasTools: boolean
28
+ /** Whether a hooks.ts file exists. */
29
+ hasHooks: boolean
30
+ /** Whether a voice.yaml configuration file exists. */
31
+ hasVoice: boolean
32
+ /** Contents of ABOUT.md if present, undefined otherwise. */
33
+ about?: string
34
+ /** Frontmatter metadata parsed from CORE.md. */
35
+ meta?: Record<string, any>
36
+ }
37
+
38
+ export const AssistantsManagerEventsSchema = FeatureEventsSchema.extend({
39
+ discovered: z.tuple([]).describe('Emitted when assistant discovery scan completes'),
40
+ assistantCreated: z.tuple([
41
+ z.string().describe('The assistant name'),
42
+ z.any().describe('The assistant instance'),
43
+ ]).describe('Emitted when a new assistant instance is created'),
44
+ assistantRegistered: z.tuple([
45
+ z.string().describe('The assistant id'),
46
+ ]).describe('Emitted when an assistant factory is registered at runtime'),
47
+ })
48
+
49
+ export const AssistantsManagerStateSchema = FeatureStateSchema.extend({
50
+ discovered: z.boolean().describe('Whether discovery has been run'),
51
+ assistantCount: z.number().describe('Number of discovered assistant definitions'),
52
+ activeCount: z.number().describe('Number of currently instantiated assistants'),
53
+ entries: z.record(z.string(), z.any()).describe('Discovered assistant entries keyed by name'),
54
+ instances: z.record(z.string(), z.any()).describe('Active assistant instances keyed by name'),
55
+ factories: z.record(z.string(), z.any()).describe('Registered factory functions keyed by name'),
56
+ extraFolders: z.array(z.string()).describe('Additional folders to scan during discovery'),
57
+ })
58
+
59
+ export const AssistantsManagerOptionsSchema = FeatureOptionsSchema.extend({})
60
+
61
+ export type AssistantsManagerState = z.infer<typeof AssistantsManagerStateSchema>
62
+ export type AssistantsManagerOptions = z.infer<typeof AssistantsManagerOptionsSchema>
63
+
64
+ /**
65
+ * Discovers and manages assistant definitions by looking for subdirectories
66
+ * in two locations: ~/.luca/assistants/ and cwd/assistants/. Each subdirectory
67
+ * containing a CORE.md is treated as an assistant definition.
68
+ *
69
+ * Use `discover()` to scan for available assistants, `list()` to enumerate them,
70
+ * and `create(name)` to instantiate one as a running Assistant feature.
71
+ *
72
+ * @extends Feature
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const manager = container.feature('assistantsManager')
77
+ * manager.discover()
78
+ * console.log(manager.list()) // [{ name: 'chief-of-staff', folder: '...', ... }]
79
+ * const assistant = manager.create('chief-of-staff')
80
+ * const answer = await assistant.ask('Hello!')
81
+ * ```
82
+ */
83
+ export class AssistantsManager extends Feature<AssistantsManagerState, AssistantsManagerOptions> {
84
+ static override stateSchema = AssistantsManagerStateSchema
85
+ static override optionsSchema = AssistantsManagerOptionsSchema
86
+ static override eventsSchema = AssistantsManagerEventsSchema
87
+ static override shortcut = 'features.assistantsManager' as const
88
+
89
+ static { Feature.register(this, 'assistantsManager') }
90
+
91
+ /** @returns Default state with discovery not yet run and zero counts. */
92
+ override get initialState(): AssistantsManagerState {
93
+ return {
94
+ ...super.initialState,
95
+ discovered: false,
96
+ assistantCount: 0,
97
+ activeCount: 0,
98
+ entries: {},
99
+ instances: {},
100
+ factories: {},
101
+ extraFolders: [],
102
+ }
103
+ }
104
+
105
+
106
+ /** Discovered assistant entries keyed by name. */
107
+ get entries(): Record<string, AssistantEntry> {
108
+ return (this.state.get('entries') || {}) as Record<string, AssistantEntry>
109
+ }
110
+
111
+ /** Active assistant instances keyed by name. */
112
+ get instances(): Record<string, Assistant> {
113
+ return (this.state.get('instances') || {}) as Record<string, Assistant>
114
+ }
115
+
116
+ /** Registered factory functions keyed by name. */
117
+ get factories(): Record<string, (options: Record<string, any>) => Assistant> {
118
+ return (this.state.get('factories') || {}) as Record<string, (options: Record<string, any>) => Assistant>
119
+ }
120
+
121
+ /** Interceptor registrations to be applied to every assistant this manager creates. */
122
+ private _interceptors: Array<{ point: InterceptorPoint; fn: InterceptorFn<any> }> = []
123
+
124
+ /**
125
+ * Registers a pipeline interceptor that is applied to every assistant created by this manager.
126
+ * Interceptors are applied at the given interception point on each assistant at creation time.
127
+ * This mirrors the per-assistant `assistant.intercept(point, fn)` API, but scopes it globally
128
+ * across all assistants managed here — useful for cross-cutting concerns like logging, tracing,
129
+ * or policy enforcement.
130
+ *
131
+ * @param {InterceptorPoint} point - The interception point (beforeAsk, beforeTurn, beforeToolCall, afterToolCall, beforeResponse)
132
+ * @param {InterceptorFn<InterceptorPoints[K]>} fn - Middleware function receiving (ctx, next)
133
+ * @returns {this} This instance, for chaining
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * manager.intercept('beforeAsk', async (ctx, next) => {
138
+ * console.log(`[${ctx.assistant.name}] asking: ${ctx.message}`)
139
+ * await next()
140
+ * })
141
+ * ```
142
+ */
143
+ intercept<K extends InterceptorPoint>(point: K, fn: InterceptorFn<InterceptorPoints[K]>): this {
144
+ this._interceptors.push({ point, fn })
145
+ return this
146
+ }
147
+
148
+ /**
149
+ * Discovers assistants by listing subdirectories in ~/.luca/assistants/
150
+ * and cwd/assistants/. Each subdirectory containing a CORE.md is an assistant.
151
+ *
152
+ * @returns {Promise<this>} This instance, for chaining
153
+ */
154
+ /**
155
+ * Registers an additional folder to scan during assistant discovery and
156
+ * immediately triggers a new discovery pass.
157
+ *
158
+ * @param {string} folderPath - Absolute path to a folder containing assistant subdirectories
159
+ * @returns {Promise<this>} This instance, for chaining
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * await manager.addDiscoveryFolder('/path/to/more/assistants')
164
+ * console.log(manager.available) // includes assistants from the new folder
165
+ * ```
166
+ */
167
+ async addDiscoveryFolder(folderPath: string): Promise<this> {
168
+ const current = this.state.get('extraFolders') as string[]
169
+ if (!current.includes(folderPath)) {
170
+ this.state.set('extraFolders', [...current, folderPath])
171
+ }
172
+ return this.discover()
173
+ }
174
+
175
+ async discover(): Promise<this> {
176
+ const { fs, paths, os } = this.container
177
+
178
+ const discovered: Record<string, AssistantEntry> = {}
179
+
180
+ const locations = [
181
+ `${os.homedir}/.luca/assistants`,
182
+ paths.resolve('assistants'),
183
+ ...(this.state.get('extraFolders') as string[]),
184
+ ]
185
+
186
+ for (const location of locations) {
187
+ if (!fs.exists(location)) continue
188
+
189
+ const dirEntries = fs.readdirSync(location)
190
+
191
+ for (const entry of dirEntries) {
192
+ const folder = `${location}/${entry}`
193
+ if (!fs.isDirectory(folder)) continue
194
+
195
+ const hasCorePrompt = fs.exists(`${folder}/CORE.md`)
196
+ if (!hasCorePrompt) continue
197
+
198
+ // Don't overwrite earlier entries (home takes precedence for same name)
199
+ if (!discovered[entry]) {
200
+ const hasAbout = fs.exists(`${folder}/ABOUT.md`)
201
+ let about: string | undefined
202
+ let meta: Record<string, any> | undefined
203
+
204
+ if (hasAbout) {
205
+ about = fs.readFileSync(`${folder}/ABOUT.md`, 'utf8') as string
206
+ }
207
+
208
+ try {
209
+ const coreContent = fs.readFileSync(`${folder}/CORE.md`, 'utf8') as string
210
+ const fmMatch = coreContent.match(/^---\r?\n([\s\S]*?)\r?\n---/)
211
+ if (fmMatch) {
212
+ const yaml = this.container.feature('yaml')
213
+ meta = yaml.parse(fmMatch[1]!)
214
+ }
215
+ } catch {
216
+ // CORE.md exists but couldn't be parsed — skip meta
217
+ }
218
+
219
+ discovered[entry] = {
220
+ name: entry,
221
+ folder,
222
+ hasCorePrompt: true,
223
+ hasTools: fs.exists(`${folder}/tools.ts`),
224
+ hasHooks: fs.exists(`${folder}/hooks.ts`),
225
+ hasVoice: fs.exists(`${folder}/voice.yaml`),
226
+ ...(about != null && { about }),
227
+ ...(meta != null && { meta }),
228
+ }
229
+ }
230
+ }
231
+ }
232
+
233
+ this.state.setState({
234
+ entries: discovered,
235
+ discovered: true,
236
+ assistantCount: Object.keys(discovered).length,
237
+ })
238
+
239
+ this.emit('discovered')
240
+ return this
241
+ }
242
+
243
+ /**
244
+ * Downloads the core assistants that ship with luca from GitHub
245
+ * into ~/.luca/assistants.
246
+ *
247
+ * @returns {Promise<{ files: string[] }>} The files extracted
248
+ *
249
+ * @example
250
+ * ```typescript
251
+ * const manager = container.feature('assistantsManager')
252
+ * await manager.downloadLucaCoreAssistants()
253
+ * await manager.discover()
254
+ * console.log(manager.available)
255
+ * ```
256
+ */
257
+ async downloadLucaCoreAssistants() {
258
+ const { os, paths } = this.container
259
+ const dest = `${os.homedir}/.luca/assistants`
260
+ const git = this.container.feature('git') as any
261
+
262
+ return await git.extractFolder({
263
+ source: 'soederpop/luca/assistants',
264
+ destination: dest,
265
+ })
266
+ }
267
+
268
+ get available() {
269
+ const entryKeys = Object.keys(this.entries)
270
+ const factoryKeys = Object.keys(this.factories)
271
+ return [...new Set([...entryKeys, ...factoryKeys])]
272
+ }
273
+
274
+ /**
275
+ * Returns all discovered assistant entries as an array.
276
+ *
277
+ * @returns {AssistantEntry[]} All discovered entries
278
+ */
279
+ list(): AssistantEntry[] {
280
+ const discovered = Object.values(this.entries)
281
+ const discoveredNames = new Set(discovered.map((e) => e.name))
282
+
283
+ // Include registered factories that weren't discovered on disk
284
+ const registeredOnly = Object.keys(this.factories)
285
+ .filter((name) => !discoveredNames.has(name))
286
+ .map((name): AssistantEntry => ({
287
+ name,
288
+ folder: '',
289
+ hasCorePrompt: false,
290
+ hasTools: false,
291
+ hasHooks: false,
292
+ hasVoice: false,
293
+ }))
294
+
295
+ return [...discovered, ...registeredOnly]
296
+ }
297
+
298
+ /**
299
+ * Looks up a single assistant entry by name.
300
+ *
301
+ * @param {string} name - The assistant name (e.g. 'chief-of-staff')
302
+ * @returns {AssistantEntry | undefined} The entry, or undefined if not found
303
+ */
304
+ get(name: string): AssistantEntry | undefined {
305
+ return this.entries[name]
306
+ }
307
+
308
+ /**
309
+ * Registers a factory function that creates an assistant at runtime.
310
+ * Registered factories take precedence over discovered entries when
311
+ * calling `create()`.
312
+ *
313
+ * @param {string} id - The assistant identifier
314
+ * @param {(options: Record<string, any>) => Assistant} factory - Factory function that receives create options and returns an Assistant
315
+ * @returns {this} This instance, for chaining
316
+ *
317
+ * @example
318
+ * ```typescript
319
+ * manager.register('custom-bot', (options) => {
320
+ * return container.feature('assistant', {
321
+ * systemPrompt: 'You are a custom bot.',
322
+ * ...options,
323
+ * })
324
+ * })
325
+ * const bot = manager.create('custom-bot')
326
+ * ```
327
+ */
328
+ register(id: string, factory: (options: Record<string, any>) => Assistant): this {
329
+ this.state.set('factories', { ...this.factories, [id]: factory })
330
+ this.emit('assistantRegistered', id)
331
+ return this
332
+ }
333
+
334
+ /**
335
+ * Creates and returns a new Assistant feature instance for the given name.
336
+ * Checks runtime-registered factories first, then falls back to discovered entries.
337
+ * The assistant is configured with the discovered folder path. Any additional
338
+ * options are merged in.
339
+ *
340
+ * @param {string} name - The assistant name (must match a registered factory or discovered entry)
341
+ * @param {Record<string, any>} options - Additional options to pass to the Assistant constructor
342
+ * @returns {Assistant} The created assistant instance
343
+ * @throws {Error} If the name is not found among registered factories or discovered assistants
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * const assistant = manager.create('chief-of-staff', { model: 'gpt-4.1' })
348
+ * ```
349
+ */
350
+ create(name: string, options: Record<string, any> = {}): Assistant {
351
+ // Check registered factories first
352
+ const factory = this.factories[name]
353
+ if (factory) {
354
+ const instance = factory(options)
355
+ this._bindAssistant(instance)
356
+ const updated = { ...this.instances, [name]: instance }
357
+ this.state.setState({ instances: updated, activeCount: Object.keys(updated).length })
358
+ this.emit('assistantCreated', name, instance)
359
+ return instance
360
+ }
361
+
362
+ const entry = this.get(name)
363
+
364
+ if (!entry) {
365
+ throw new Error(
366
+ `Assistant "${name}" not found. Available assistants: ${this.available.join(', ') || '(none — run discover() first)'}`
367
+ )
368
+ }
369
+
370
+ const instance = this.container.feature('assistant', {
371
+ folder: entry.folder,
372
+ ...options,
373
+ })
374
+
375
+ this._bindAssistant(instance)
376
+ const updated = { ...this.instances, [name]: instance }
377
+ this.state.setState({ instances: updated, activeCount: Object.keys(updated).length })
378
+ this.emit('assistantCreated', name, instance)
379
+
380
+ return instance
381
+ }
382
+
383
+ /**
384
+ * Wires an assistant into the manager: bridges all assistant events up to the manager
385
+ * as `assistantEvent:<eventName>` with (assistant, ...originalArgs), and applies any
386
+ * globally registered interceptors.
387
+ */
388
+ private _bindAssistant(instance: Assistant): void {
389
+ instance.on('*', (event: string, ...args: any[]) => {
390
+ this.emit(`assistantEvent:${event}` as any, instance, ...args)
391
+ })
392
+
393
+ for (const { point, fn } of this._interceptors) {
394
+ instance.intercept(point, fn)
395
+ }
396
+ }
397
+
398
+ /**
399
+ * Reload tools, hooks, and system prompt from disk for active assistants.
400
+ * When called with a name, reloads only that assistant. When called without
401
+ * arguments, reloads all active instances.
402
+ *
403
+ * @param {string} [name] - Optional assistant name to reload. Omit to reload all.
404
+ * @returns {{ reloaded: string[] }} Names of assistants that were reloaded
405
+ * @throws {Error} If a specific name is given but no active instance exists for it
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * manager.reload('researcher') // reload one
410
+ * manager.reload() // reload all active
411
+ * ```
412
+ */
413
+ reload(name?: string): { reloaded: string[] } {
414
+ const reloaded: string[] = []
415
+
416
+ if (name) {
417
+ const instance = this.instances[name]
418
+ if (!instance) {
419
+ throw new Error(
420
+ `No active assistant "${name}" to reload. Active: ${Object.keys(this.instances).join(', ') || '(none)'}`
421
+ )
422
+ }
423
+ instance.reload()
424
+ reloaded.push(name)
425
+ } else {
426
+ for (const [key, instance] of Object.entries(this.instances)) {
427
+ instance.reload()
428
+ reloaded.push(key)
429
+ }
430
+ }
431
+
432
+ return { reloaded }
433
+ }
434
+
435
+ /**
436
+ * Build the thread prefix for a given assistant name, matching the
437
+ * convention used by the Assistant class: `name:cwdHash:`.
438
+ * This allows history lookups without an active instance.
439
+ *
440
+ * @param {string} assistantId - The assistant name
441
+ * @returns {string} The thread prefix
442
+ */
443
+ threadPrefixFor(assistantId: string): string {
444
+ const cwdHash = hashObject(this.container.cwd).slice(0, 8)
445
+ return `${assistantId}:${cwdHash}:`
446
+ }
447
+
448
+ /**
449
+ * Load conversation history for an assistant. Works whether or not the
450
+ * assistant is currently instantiated — uses the thread prefix convention
451
+ * to query the conversationHistory feature directly.
452
+ *
453
+ * @param {string} assistantId - The assistant name (e.g. 'researcher')
454
+ * @param {object} [options] - Query options
455
+ * @param {number} [options.limit] - Maximum number of records to return
456
+ * @param {boolean} [options.includeMessages] - Load full records with messages (default: false, returns metadata only)
457
+ * @param {string} [options.thread] - Load a specific thread ID instead of all threads for this assistant
458
+ * @returns {Promise<ConversationMeta[] | ConversationRecord[]>} Metadata or full records, newest first
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * // List recent sessions (metadata only)
463
+ * const sessions = await manager.loadAssistantHistory('researcher', { limit: 5 })
464
+ *
465
+ * // Load full records with messages
466
+ * const full = await manager.loadAssistantHistory('researcher', { includeMessages: true, limit: 3 })
467
+ *
468
+ * // Load a specific thread
469
+ * const thread = await manager.loadAssistantHistory('researcher', { thread: 'researcher:abc12345:2026-04-12' })
470
+ * ```
471
+ */
472
+ async loadAssistantHistory(
473
+ assistantId: string,
474
+ options?: { limit?: number; includeMessages?: boolean; thread?: string },
475
+ ): Promise<ConversationMeta[] | ConversationRecord[]> {
476
+ const history = this.container.feature('conversationHistory') as ConversationHistory
477
+
478
+ if (options?.thread) {
479
+ const record = await history.findByThread(options.thread)
480
+ return record ? [record] : []
481
+ }
482
+
483
+ const prefix = this.threadPrefixFor(assistantId)
484
+ const metas = await history.findByThreadPrefix(prefix)
485
+ const limited = options?.limit ? metas.slice(0, options.limit) : metas
486
+
487
+ if (!options?.includeMessages) return limited
488
+
489
+ const records: ConversationRecord[] = []
490
+ for (const meta of limited) {
491
+ const record = await history.load(meta.id)
492
+ if (record) records.push(record)
493
+ }
494
+ return records
495
+ }
496
+
497
+ /**
498
+ * Returns a previously created assistant instance by name.
499
+ *
500
+ * @param {string} name - The assistant name
501
+ * @returns {Assistant | undefined} The instance, or undefined if not yet created
502
+ */
503
+ getInstance(name: string): Assistant | undefined {
504
+ return this.instances[name]
505
+ }
506
+
507
+ /**
508
+ * Generates a markdown summary of all discovered assistants,
509
+ * listing their names and which definition files are present.
510
+ *
511
+ * @returns {string} Markdown-formatted summary
512
+ */
513
+ toSummary(): string {
514
+ const entries = this.list()
515
+
516
+ if (entries.length === 0) {
517
+ return '## Assistants\n\nNo assistants discovered.'
518
+ }
519
+
520
+ const lines = entries.map((e) => {
521
+ const files = [
522
+ e.hasCorePrompt && 'CORE.md',
523
+ e.hasTools && 'tools.ts',
524
+ e.hasHooks && 'hooks.ts',
525
+ ].filter(Boolean)
526
+
527
+ return `- **${e.name}** — ${files.join(', ')}`
528
+ })
529
+
530
+ return `## Assistants\n\n${lines.join('\n')}`
531
+ }
532
+ }
533
+
534
+ export default AssistantsManager