@soederpop/luca 0.1.1 → 0.1.3

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 (369) hide show
  1. package/CLAUDE.md +2 -0
  2. package/assistants/codingAssistant/hooks.ts +3 -0
  3. package/assistants/inkbot/CORE.md +69 -0
  4. package/assistants/inkbot/hooks.ts +14 -0
  5. package/assistants/inkbot/tools.ts +47 -0
  6. package/commands/inkbot.ts +353 -0
  7. package/dist/agi/container.server.d.ts +63 -0
  8. package/dist/agi/container.server.d.ts.map +1 -0
  9. package/dist/agi/endpoints/ask.d.ts +20 -0
  10. package/dist/agi/endpoints/ask.d.ts.map +1 -0
  11. package/dist/agi/endpoints/conversations/[id].d.ts +27 -0
  12. package/dist/agi/endpoints/conversations/[id].d.ts.map +1 -0
  13. package/dist/agi/endpoints/conversations.d.ts +18 -0
  14. package/dist/agi/endpoints/conversations.d.ts.map +1 -0
  15. package/dist/agi/endpoints/experts.d.ts +8 -0
  16. package/dist/agi/endpoints/experts.d.ts.map +1 -0
  17. package/dist/agi/feature.d.ts +9 -0
  18. package/dist/agi/feature.d.ts.map +1 -0
  19. package/dist/agi/features/assistant.d.ts +509 -0
  20. package/dist/agi/features/assistant.d.ts.map +1 -0
  21. package/dist/agi/features/assistants-manager.d.ts +236 -0
  22. package/dist/agi/features/assistants-manager.d.ts.map +1 -0
  23. package/dist/agi/features/autonomous-assistant.d.ts +281 -0
  24. package/dist/agi/features/autonomous-assistant.d.ts.map +1 -0
  25. package/dist/agi/features/browser-use.d.ts +479 -0
  26. package/dist/agi/features/browser-use.d.ts.map +1 -0
  27. package/dist/agi/features/claude-code.d.ts +824 -0
  28. package/dist/agi/features/claude-code.d.ts.map +1 -0
  29. package/dist/agi/features/conversation-history.d.ts +245 -0
  30. package/dist/agi/features/conversation-history.d.ts.map +1 -0
  31. package/dist/agi/features/conversation.d.ts +464 -0
  32. package/dist/agi/features/conversation.d.ts.map +1 -0
  33. package/dist/agi/features/docs-reader.d.ts +72 -0
  34. package/dist/agi/features/docs-reader.d.ts.map +1 -0
  35. package/dist/agi/features/file-tools.d.ts +110 -0
  36. package/dist/agi/features/file-tools.d.ts.map +1 -0
  37. package/dist/agi/features/luca-coder.d.ts +323 -0
  38. package/dist/agi/features/luca-coder.d.ts.map +1 -0
  39. package/dist/agi/features/openai-codex.d.ts +381 -0
  40. package/dist/agi/features/openai-codex.d.ts.map +1 -0
  41. package/dist/agi/features/openapi.d.ts +200 -0
  42. package/dist/agi/features/openapi.d.ts.map +1 -0
  43. package/dist/agi/features/skills-library.d.ts +167 -0
  44. package/dist/agi/features/skills-library.d.ts.map +1 -0
  45. package/dist/agi/index.d.ts +5 -0
  46. package/dist/agi/index.d.ts.map +1 -0
  47. package/dist/agi/lib/interceptor-chain.d.ts +44 -0
  48. package/dist/agi/lib/interceptor-chain.d.ts.map +1 -0
  49. package/dist/agi/lib/token-counter.d.ts +13 -0
  50. package/dist/agi/lib/token-counter.d.ts.map +1 -0
  51. package/dist/bootstrap/generated.d.ts +5 -0
  52. package/dist/bootstrap/generated.d.ts.map +1 -0
  53. package/dist/browser.d.ts +12 -0
  54. package/dist/browser.d.ts.map +1 -0
  55. package/dist/bus.d.ts +29 -0
  56. package/dist/bus.d.ts.map +1 -0
  57. package/dist/cli/build-info.d.ts +4 -0
  58. package/dist/cli/build-info.d.ts.map +1 -0
  59. package/dist/cli/cli.d.ts +3 -0
  60. package/dist/cli/cli.d.ts.map +1 -0
  61. package/dist/client.d.ts +60 -0
  62. package/dist/client.d.ts.map +1 -0
  63. package/dist/clients/civitai/index.d.ts +472 -0
  64. package/dist/clients/civitai/index.d.ts.map +1 -0
  65. package/dist/clients/client-template.d.ts +30 -0
  66. package/dist/clients/client-template.d.ts.map +1 -0
  67. package/dist/clients/comfyui/index.d.ts +281 -0
  68. package/dist/clients/comfyui/index.d.ts.map +1 -0
  69. package/dist/clients/elevenlabs/index.d.ts +197 -0
  70. package/dist/clients/elevenlabs/index.d.ts.map +1 -0
  71. package/dist/clients/graph.d.ts +64 -0
  72. package/dist/clients/graph.d.ts.map +1 -0
  73. package/dist/clients/openai/index.d.ts +247 -0
  74. package/dist/clients/openai/index.d.ts.map +1 -0
  75. package/dist/clients/rest.d.ts +92 -0
  76. package/dist/clients/rest.d.ts.map +1 -0
  77. package/dist/clients/supabase/index.d.ts +176 -0
  78. package/dist/clients/supabase/index.d.ts.map +1 -0
  79. package/dist/clients/websocket.d.ts +127 -0
  80. package/dist/clients/websocket.d.ts.map +1 -0
  81. package/dist/command.d.ts +163 -0
  82. package/dist/command.d.ts.map +1 -0
  83. package/dist/commands/bootstrap.d.ts +20 -0
  84. package/dist/commands/bootstrap.d.ts.map +1 -0
  85. package/dist/commands/chat.d.ts +37 -0
  86. package/dist/commands/chat.d.ts.map +1 -0
  87. package/dist/commands/code.d.ts +28 -0
  88. package/dist/commands/code.d.ts.map +1 -0
  89. package/dist/commands/console.d.ts +22 -0
  90. package/dist/commands/console.d.ts.map +1 -0
  91. package/dist/commands/describe.d.ts +50 -0
  92. package/dist/commands/describe.d.ts.map +1 -0
  93. package/dist/commands/eval.d.ts +23 -0
  94. package/dist/commands/eval.d.ts.map +1 -0
  95. package/dist/commands/help.d.ts +25 -0
  96. package/dist/commands/help.d.ts.map +1 -0
  97. package/dist/commands/index.d.ts +18 -0
  98. package/dist/commands/index.d.ts.map +1 -0
  99. package/dist/commands/introspect.d.ts +24 -0
  100. package/dist/commands/introspect.d.ts.map +1 -0
  101. package/dist/commands/mcp.d.ts +35 -0
  102. package/dist/commands/mcp.d.ts.map +1 -0
  103. package/dist/commands/prompt.d.ts +38 -0
  104. package/dist/commands/prompt.d.ts.map +1 -0
  105. package/dist/commands/run.d.ts +24 -0
  106. package/dist/commands/run.d.ts.map +1 -0
  107. package/dist/commands/sandbox-mcp.d.ts +34 -0
  108. package/dist/commands/sandbox-mcp.d.ts.map +1 -0
  109. package/dist/commands/save-api-docs.d.ts +21 -0
  110. package/dist/commands/save-api-docs.d.ts.map +1 -0
  111. package/dist/commands/scaffold.d.ts +24 -0
  112. package/dist/commands/scaffold.d.ts.map +1 -0
  113. package/dist/commands/select.d.ts +22 -0
  114. package/dist/commands/select.d.ts.map +1 -0
  115. package/dist/commands/serve.d.ts +29 -0
  116. package/dist/commands/serve.d.ts.map +1 -0
  117. package/dist/container-describer.d.ts +144 -0
  118. package/dist/container-describer.d.ts.map +1 -0
  119. package/dist/container.d.ts +451 -0
  120. package/dist/container.d.ts.map +1 -0
  121. package/dist/endpoint.d.ts +113 -0
  122. package/dist/endpoint.d.ts.map +1 -0
  123. package/dist/feature.d.ts +47 -0
  124. package/dist/feature.d.ts.map +1 -0
  125. package/dist/graft.d.ts +29 -0
  126. package/dist/graft.d.ts.map +1 -0
  127. package/dist/hash-object.d.ts +8 -0
  128. package/dist/hash-object.d.ts.map +1 -0
  129. package/dist/helper.d.ts +209 -0
  130. package/dist/helper.d.ts.map +1 -0
  131. package/dist/introspection/generated.node.d.ts +44623 -0
  132. package/dist/introspection/generated.node.d.ts.map +1 -0
  133. package/dist/introspection/generated.web.d.ts +1412 -0
  134. package/dist/introspection/generated.web.d.ts.map +1 -0
  135. package/dist/introspection/index.d.ts +156 -0
  136. package/dist/introspection/index.d.ts.map +1 -0
  137. package/dist/introspection/scan.d.ts +147 -0
  138. package/dist/introspection/scan.d.ts.map +1 -0
  139. package/dist/node/container.d.ts +256 -0
  140. package/dist/node/container.d.ts.map +1 -0
  141. package/dist/node/feature.d.ts +9 -0
  142. package/dist/node/feature.d.ts.map +1 -0
  143. package/dist/node/features/container-link.d.ts +213 -0
  144. package/dist/node/features/container-link.d.ts.map +1 -0
  145. package/dist/node/features/content-db.d.ts +354 -0
  146. package/dist/node/features/content-db.d.ts.map +1 -0
  147. package/dist/node/features/disk-cache.d.ts +236 -0
  148. package/dist/node/features/disk-cache.d.ts.map +1 -0
  149. package/dist/node/features/dns.d.ts +511 -0
  150. package/dist/node/features/dns.d.ts.map +1 -0
  151. package/dist/node/features/docker.d.ts +485 -0
  152. package/dist/node/features/docker.d.ts.map +1 -0
  153. package/dist/node/features/downloader.d.ts +73 -0
  154. package/dist/node/features/downloader.d.ts.map +1 -0
  155. package/dist/node/features/figlet-fonts.d.ts +4 -0
  156. package/dist/node/features/figlet-fonts.d.ts.map +1 -0
  157. package/dist/node/features/file-manager.d.ts +177 -0
  158. package/dist/node/features/file-manager.d.ts.map +1 -0
  159. package/dist/node/features/fs.d.ts +635 -0
  160. package/dist/node/features/fs.d.ts.map +1 -0
  161. package/dist/node/features/git.d.ts +329 -0
  162. package/dist/node/features/git.d.ts.map +1 -0
  163. package/dist/node/features/google-auth.d.ts +200 -0
  164. package/dist/node/features/google-auth.d.ts.map +1 -0
  165. package/dist/node/features/google-calendar.d.ts +194 -0
  166. package/dist/node/features/google-calendar.d.ts.map +1 -0
  167. package/dist/node/features/google-docs.d.ts +138 -0
  168. package/dist/node/features/google-docs.d.ts.map +1 -0
  169. package/dist/node/features/google-drive.d.ts +202 -0
  170. package/dist/node/features/google-drive.d.ts.map +1 -0
  171. package/dist/node/features/google-mail.d.ts +221 -0
  172. package/dist/node/features/google-mail.d.ts.map +1 -0
  173. package/dist/node/features/google-sheets.d.ts +157 -0
  174. package/dist/node/features/google-sheets.d.ts.map +1 -0
  175. package/dist/node/features/grep.d.ts +207 -0
  176. package/dist/node/features/grep.d.ts.map +1 -0
  177. package/dist/node/features/helpers.d.ts +236 -0
  178. package/dist/node/features/helpers.d.ts.map +1 -0
  179. package/dist/node/features/ink.d.ts +332 -0
  180. package/dist/node/features/ink.d.ts.map +1 -0
  181. package/dist/node/features/ipc-socket.d.ts +298 -0
  182. package/dist/node/features/ipc-socket.d.ts.map +1 -0
  183. package/dist/node/features/json-tree.d.ts +140 -0
  184. package/dist/node/features/json-tree.d.ts.map +1 -0
  185. package/dist/node/features/networking.d.ts +373 -0
  186. package/dist/node/features/networking.d.ts.map +1 -0
  187. package/dist/node/features/nlp.d.ts +125 -0
  188. package/dist/node/features/nlp.d.ts.map +1 -0
  189. package/dist/node/features/opener.d.ts +93 -0
  190. package/dist/node/features/opener.d.ts.map +1 -0
  191. package/dist/node/features/os.d.ts +168 -0
  192. package/dist/node/features/os.d.ts.map +1 -0
  193. package/dist/node/features/package-finder.d.ts +419 -0
  194. package/dist/node/features/package-finder.d.ts.map +1 -0
  195. package/dist/node/features/postgres.d.ts +173 -0
  196. package/dist/node/features/postgres.d.ts.map +1 -0
  197. package/dist/node/features/proc.d.ts +285 -0
  198. package/dist/node/features/proc.d.ts.map +1 -0
  199. package/dist/node/features/process-manager.d.ts +427 -0
  200. package/dist/node/features/process-manager.d.ts.map +1 -0
  201. package/dist/node/features/python.d.ts +477 -0
  202. package/dist/node/features/python.d.ts.map +1 -0
  203. package/dist/node/features/redis.d.ts +247 -0
  204. package/dist/node/features/redis.d.ts.map +1 -0
  205. package/dist/node/features/repl.d.ts +84 -0
  206. package/dist/node/features/repl.d.ts.map +1 -0
  207. package/dist/node/features/runpod.d.ts +527 -0
  208. package/dist/node/features/runpod.d.ts.map +1 -0
  209. package/dist/node/features/secure-shell.d.ts +145 -0
  210. package/dist/node/features/secure-shell.d.ts.map +1 -0
  211. package/dist/node/features/semantic-search.d.ts +207 -0
  212. package/dist/node/features/semantic-search.d.ts.map +1 -0
  213. package/dist/node/features/sqlite.d.ts +180 -0
  214. package/dist/node/features/sqlite.d.ts.map +1 -0
  215. package/dist/node/features/telegram.d.ts +173 -0
  216. package/dist/node/features/telegram.d.ts.map +1 -0
  217. package/dist/node/features/transpiler.d.ts +51 -0
  218. package/dist/node/features/transpiler.d.ts.map +1 -0
  219. package/dist/node/features/tts.d.ts +108 -0
  220. package/dist/node/features/tts.d.ts.map +1 -0
  221. package/dist/node/features/ui.d.ts +562 -0
  222. package/dist/node/features/ui.d.ts.map +1 -0
  223. package/dist/node/features/vault.d.ts +90 -0
  224. package/dist/node/features/vault.d.ts.map +1 -0
  225. package/dist/node/features/vm.d.ts +285 -0
  226. package/dist/node/features/vm.d.ts.map +1 -0
  227. package/dist/node/features/yaml-tree.d.ts +118 -0
  228. package/dist/node/features/yaml-tree.d.ts.map +1 -0
  229. package/dist/node/features/yaml.d.ts +127 -0
  230. package/dist/node/features/yaml.d.ts.map +1 -0
  231. package/dist/node.d.ts +67 -0
  232. package/dist/node.d.ts.map +1 -0
  233. package/dist/python/generated.d.ts +2 -0
  234. package/dist/python/generated.d.ts.map +1 -0
  235. package/dist/react/index.d.ts +36 -0
  236. package/dist/react/index.d.ts.map +1 -0
  237. package/dist/registry.d.ts +97 -0
  238. package/dist/registry.d.ts.map +1 -0
  239. package/dist/scaffolds/generated.d.ts +13 -0
  240. package/dist/scaffolds/generated.d.ts.map +1 -0
  241. package/dist/scaffolds/template.d.ts +11 -0
  242. package/dist/scaffolds/template.d.ts.map +1 -0
  243. package/dist/schemas/base.d.ts +254 -0
  244. package/dist/schemas/base.d.ts.map +1 -0
  245. package/dist/selector.d.ts +130 -0
  246. package/dist/selector.d.ts.map +1 -0
  247. package/dist/server.d.ts +89 -0
  248. package/dist/server.d.ts.map +1 -0
  249. package/dist/servers/express.d.ts +104 -0
  250. package/dist/servers/express.d.ts.map +1 -0
  251. package/dist/servers/mcp.d.ts +201 -0
  252. package/dist/servers/mcp.d.ts.map +1 -0
  253. package/dist/servers/socket.d.ts +121 -0
  254. package/dist/servers/socket.d.ts.map +1 -0
  255. package/dist/state.d.ts +24 -0
  256. package/dist/state.d.ts.map +1 -0
  257. package/dist/web/clients/socket.d.ts +37 -0
  258. package/dist/web/clients/socket.d.ts.map +1 -0
  259. package/dist/web/container.d.ts +55 -0
  260. package/dist/web/container.d.ts.map +1 -0
  261. package/dist/web/extension.d.ts +4 -0
  262. package/dist/web/extension.d.ts.map +1 -0
  263. package/dist/web/feature.d.ts +8 -0
  264. package/dist/web/feature.d.ts.map +1 -0
  265. package/dist/web/features/asset-loader.d.ts +35 -0
  266. package/dist/web/features/asset-loader.d.ts.map +1 -0
  267. package/dist/web/features/container-link.d.ts +167 -0
  268. package/dist/web/features/container-link.d.ts.map +1 -0
  269. package/dist/web/features/esbuild.d.ts +51 -0
  270. package/dist/web/features/esbuild.d.ts.map +1 -0
  271. package/dist/web/features/helpers.d.ts +140 -0
  272. package/dist/web/features/helpers.d.ts.map +1 -0
  273. package/dist/web/features/network.d.ts +69 -0
  274. package/dist/web/features/network.d.ts.map +1 -0
  275. package/dist/web/features/speech.d.ts +71 -0
  276. package/dist/web/features/speech.d.ts.map +1 -0
  277. package/dist/web/features/vault.d.ts +62 -0
  278. package/dist/web/features/vault.d.ts.map +1 -0
  279. package/dist/web/features/vm.d.ts +48 -0
  280. package/dist/web/features/vm.d.ts.map +1 -0
  281. package/dist/web/features/voice-recognition.d.ts +96 -0
  282. package/dist/web/features/voice-recognition.d.ts.map +1 -0
  283. package/dist/web/shims/isomorphic-vm.d.ts +22 -0
  284. package/dist/web/shims/isomorphic-vm.d.ts.map +1 -0
  285. package/docs/apis/features/agi/assistant.md +1 -0
  286. package/docs/apis/features/agi/assistants-manager.md +62 -2
  287. package/docs/apis/features/agi/auto-assistant.md +11 -109
  288. package/docs/apis/features/agi/claude-code.md +138 -0
  289. package/docs/apis/features/agi/conversation.md +60 -31
  290. package/docs/apis/features/agi/luca-coder.md +407 -0
  291. package/docs/apis/features/agi/openapi.md +2 -2
  292. package/docs/apis/features/agi/skills-library.md +12 -0
  293. package/docs/apis/features/node/python.md +81 -11
  294. package/docs/apis/features/node/transpiler.md +74 -0
  295. package/docs/apis/features/web/esbuild.md +0 -6
  296. package/docs/apis/servers/mcp.md +2 -2
  297. package/docs/examples/entity.md +124 -0
  298. package/package.json +73 -21
  299. package/scripts/test-assistant-hooks.ts +13 -0
  300. package/src/agi/feature.ts +13 -0
  301. package/src/agi/features/assistant.ts +36 -25
  302. package/src/agi/features/assistants-manager.ts +70 -5
  303. package/src/agi/features/autonomous-assistant.ts +1 -5
  304. package/src/agi/features/browser-use.ts +2 -2
  305. package/src/agi/features/claude-code.ts +165 -1
  306. package/src/agi/features/conversation-history.ts +2 -6
  307. package/src/agi/features/conversation.ts +95 -3
  308. package/src/agi/features/docs-reader.ts +2 -1
  309. package/src/agi/features/file-tools.ts +2 -2
  310. package/src/agi/features/luca-coder.ts +1 -5
  311. package/src/agi/features/openai-codex.ts +1 -1
  312. package/src/agi/features/openapi.ts +3 -3
  313. package/src/agi/features/skills-library.ts +90 -2
  314. package/src/agi/lib/interceptor-chain.ts +10 -0
  315. package/src/agi/lib/token-counter.ts +1 -1
  316. package/src/bootstrap/generated.ts +126 -1
  317. package/src/bus.ts +27 -5
  318. package/src/cli/build-info.ts +2 -2
  319. package/src/client.ts +2 -2
  320. package/src/clients/elevenlabs/index.ts +5 -0
  321. package/src/commands/bootstrap.ts +2 -1
  322. package/src/commands/chat.ts +1 -0
  323. package/src/commands/code.ts +4 -2
  324. package/src/commands/prompt.ts +34 -34
  325. package/src/commands/sandbox-mcp.ts +69 -163
  326. package/src/commands/save-api-docs.ts +10 -8
  327. package/src/commands/select.ts +8 -3
  328. package/src/container-describer.ts +70 -84
  329. package/src/container.ts +93 -3
  330. package/src/endpoint.ts +1 -1
  331. package/src/entity.ts +173 -0
  332. package/src/feature.ts +3 -3
  333. package/src/helper.ts +8 -4
  334. package/src/introspection/generated.agi.ts +1403 -929
  335. package/src/introspection/generated.node.ts +127 -33
  336. package/src/introspection/generated.web.ts +95 -3
  337. package/src/introspection/scan.ts +1 -1
  338. package/src/node/container.ts +1 -1
  339. package/src/node/features/content-db.ts +3 -3
  340. package/src/node/features/file-manager.ts +10 -9
  341. package/src/node/features/git.ts +5 -5
  342. package/src/node/features/helpers.ts +1 -1
  343. package/src/node/features/json-tree.ts +1 -1
  344. package/src/node/features/os.ts +3 -3
  345. package/src/node/features/package-finder.ts +1 -1
  346. package/src/node/features/process-manager.ts +1 -1
  347. package/src/node/features/python.ts +3 -3
  348. package/src/node/features/redis.ts +1 -1
  349. package/src/node/features/repl.ts +2 -2
  350. package/src/node/features/transpiler.ts +34 -9
  351. package/src/node/features/ui.ts +1 -1
  352. package/src/node/features/vm.ts +6 -5
  353. package/src/node/features/yaml-tree.ts +1 -1
  354. package/src/node.ts +1 -0
  355. package/src/python/generated.ts +1 -1
  356. package/src/scaffolds/generated.ts +1 -1
  357. package/src/selector.ts +74 -4
  358. package/src/server.ts +2 -2
  359. package/src/servers/mcp.ts +6 -6
  360. package/src/web/features/helpers.ts +1 -1
  361. package/src/web/features/network.ts +1 -0
  362. package/test/assistant.test.ts +72 -0
  363. package/test/conversation.test.ts +220 -0
  364. package/test/vm-loadmodule.test.ts +213 -0
  365. package/tsconfig.build.json +12 -0
  366. package/tsconfig.json +1 -1
  367. package/scripts/examples/telegram-ink-ui.ts +0 -302
  368. package/scripts/examples/using-openai-codex.ts +0 -23
  369. package/scripts/examples/vm-loading-esm-modules.ts +0 -16
@@ -1,5 +1,5 @@
1
1
  // Auto-generated bootstrap content
2
- // Generated at: 2026-03-28T06:19:50.048Z
2
+ // Generated at: 2026-04-03T01:24:53.975Z
3
3
  // Source: docs/bootstrap/*.md, docs/bootstrap/templates/*, docs/examples/*.md, docs/tutorials/*.md
4
4
  //
5
5
  // Do not edit manually. Run: luca build-bootstrap
@@ -1253,6 +1253,131 @@ console.log('Running after killAll:', remaining.length)
1253
1253
  ## Summary
1254
1254
 
1255
1255
  This demo covered the \`processManager\` feature: spawning processes that return handles immediately, tracking them by ID or tag, listing all tracked processes, and killing them individually or all at once. It is the right tool for orchestrating background services, dev servers, and any scenario where you need non-blocking process management with lifecycle events.
1256
+ `,
1257
+ "entity.md": `---
1258
+ title: "Entity"
1259
+ tags: [entity, state, events, tools, core]
1260
+ lastTested: null
1261
+ lastTestPassed: null
1262
+ ---
1263
+
1264
+ # entity
1265
+
1266
+ Lightweight, composable objects with observable state, a typed event bus, and an optional tool interface.
1267
+
1268
+ ## Overview
1269
+
1270
+ An entity is a plain object — not a class — created via \`container.entity(id, options?)\`. Same id + options always returns the same underlying state and bus instance. Entities are designed to be extended with methods and getters via \`.extend()\`, and can expose those methods as AI tools via \`.expose()\`.
1271
+
1272
+ ## Basic Entity with Observable State
1273
+
1274
+ Create an entity and read/write state through the observable \`state\` property.
1275
+
1276
+ \`\`\`ts
1277
+ const counter = container.entity<{ count: number }>('counter')
1278
+ counter.setState({ count: 0 })
1279
+
1280
+ counter.state.observe((next) => {
1281
+ console.log('count changed to', next.count)
1282
+ })
1283
+
1284
+ counter.setState(s => ({ count: s.count + 1 }))
1285
+ counter.setState(s => ({ count: s.count + 1 }))
1286
+ console.log('final count:', counter.state.get('count'))
1287
+ \`\`\`
1288
+
1289
+ \`setState\` accepts either a partial object or a function that receives the current state. Observers fire synchronously after each change.
1290
+
1291
+ ## Typed Event Bus
1292
+
1293
+ Every entity has a built-in event bus. Declare the event map as the third type parameter.
1294
+
1295
+ \`\`\`ts
1296
+ type TimerEvents = {
1297
+ tick: [elapsed: number]
1298
+ done: []
1299
+ }
1300
+
1301
+ const timer = container.entity<{}, {}, TimerEvents>('timer')
1302
+
1303
+ timer.on('tick', (elapsed) => {
1304
+ console.log('tick at', elapsed, 'ms')
1305
+ })
1306
+
1307
+ timer.once('done', () => {
1308
+ console.log('timer finished')
1309
+ })
1310
+
1311
+ timer.emit('tick', 100)
1312
+ timer.emit('tick', 200)
1313
+ timer.emit('done')
1314
+ \`\`\`
1315
+
1316
+ \`once\` auto-detaches after the first fire. \`waitFor\` returns a promise that resolves on the next emit of that event.
1317
+
1318
+ ## Extending with Methods
1319
+
1320
+ Use \`.extend()\` to graft methods and getters onto an entity. All base properties — \`state\`, \`options\`, \`container\`, and the event methods — are available via \`this\`.
1321
+
1322
+ \`\`\`ts
1323
+ const session = container.entity('session', { userId: '42' })
1324
+ .extend({
1325
+ greet() {
1326
+ return \`Hello user \${this.options.userId}\`
1327
+ },
1328
+ get label() {
1329
+ return \`Session \${this.id} (user \${this.options.userId})\`
1330
+ },
1331
+ bump() {
1332
+ const visits = (this.state.get('visits') ?? 0) + 1
1333
+ this.setState({ visits })
1334
+ this.emit('visited', visits)
1335
+ return visits
1336
+ },
1337
+ })
1338
+
1339
+ console.log(session.greet())
1340
+ console.log(session.label)
1341
+ console.log('visits:', session.bump())
1342
+ console.log('visits:', session.bump())
1343
+ \`\`\`
1344
+
1345
+ Extensions are chained via prototype delegation — each layer can see everything below it.
1346
+
1347
+ ## Exposing Methods as AI Tools
1348
+
1349
+ Use \`.expose(methodName, zodSchema)\` to register methods as tools. \`.toTools()\` returns \`{ schemas, handlers }\` compatible with \`assistant.addTools()\`.
1350
+
1351
+ \`\`\`ts
1352
+ const search = container.entity('search', {})
1353
+ .extend({
1354
+ async lookup({ query }: { query: string }) {
1355
+ return \`Results for: \${query}\`
1356
+ },
1357
+ async summarize({ text, maxWords }: { text: string; maxWords: number }) {
1358
+ return text.split(' ').slice(0, maxWords).join(' ')
1359
+ },
1360
+ })
1361
+ .expose('lookup', z.object({
1362
+ query: z.string().describe('The search query'),
1363
+ }))
1364
+ .expose('summarize', z.object({
1365
+ text: z.string().describe('Text to summarize'),
1366
+ maxWords: z.number().describe('Maximum words in summary'),
1367
+ }))
1368
+
1369
+ const { schemas, handlers } = search.toTools()
1370
+ console.log('registered tools:', Object.keys(schemas))
1371
+
1372
+ // Pass directly to an assistant
1373
+ // assistant.addTools(search)
1374
+ \`\`\`
1375
+
1376
+ \`.expose()\` is chainable and returns \`this\`, so you can stack as many as you need.
1377
+
1378
+ ## Summary
1379
+
1380
+ Entities give you observable state, a typed event bus, and prototype-safe method extension — all as a plain object with no class overhead. The \`.expose()\` / \`.toTools()\` interface makes it straightforward to surface entity methods as AI tools.
1256
1381
  `,
1257
1382
  "assistant-with-process-manager.md": `---
1258
1383
  title: "Assistant with ProcessManager Tools"
package/src/bus.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export type EventMap = Record<string, any[]>;
2
2
 
3
3
  type Listener<Args extends any[] = any[]> = (...args: Args) => void;
4
+ type WildcardListener = (event: string, ...args: any[]) => void;
4
5
 
5
6
  export interface EventStats {
6
7
  event: string;
@@ -12,10 +13,12 @@ export interface EventStats {
12
13
 
13
14
  export class Bus<T extends EventMap = EventMap> {
14
15
  private events: Map<string, Listener[]>;
16
+ private wildcardListeners: WildcardListener[];
15
17
  private stats: Map<string, { fireCount: number; lastFiredAt: number | null; timestamps: number[] }>;
16
18
 
17
19
  constructor() {
18
20
  this.events = new Map();
21
+ this.wildcardListeners = [];
19
22
  this.stats = new Map();
20
23
  }
21
24
 
@@ -64,12 +67,19 @@ export class Bus<T extends EventMap = EventMap> {
64
67
  emit<E extends string & keyof T>(event: E, ...args: T[E]): void {
65
68
  this.recordEmit(event);
66
69
  const listeners = this.events.get(event);
67
- if (!listeners) return;
68
-
69
- listeners.forEach(listener => listener(...args));
70
+ if (listeners) {
71
+ listeners.forEach(listener => listener(...args));
72
+ }
73
+ this.wildcardListeners.forEach(listener => listener(event, ...args));
70
74
  }
71
75
 
72
- on<E extends string & keyof T>(event: E, listener: (...args: T[E]) => void): void {
76
+ on(event: '*', listener: WildcardListener): void
77
+ on<E extends string & keyof T>(event: E, listener: (...args: T[E]) => void): void
78
+ on<E extends string & keyof T>(event: E | '*', listener: any): void {
79
+ if (event === '*') {
80
+ this.wildcardListeners.push(listener);
81
+ return;
82
+ }
73
83
  const listeners = this.events.get(event) || [];
74
84
  listeners.push(listener as Listener);
75
85
  this.events.set(event, listeners);
@@ -83,7 +93,19 @@ export class Bus<T extends EventMap = EventMap> {
83
93
  this.on(event, onceListener as any);
84
94
  }
85
95
 
86
- off<E extends string & keyof T>(event: E, listener?: (...args: T[E]) => void): void {
96
+ off(event: '*', listener?: WildcardListener): void
97
+ off<E extends string & keyof T>(event: E, listener?: (...args: T[E]) => void): void
98
+ off<E extends string & keyof T>(event: E | '*', listener?: any): void {
99
+ if (event === '*') {
100
+ if (!listener) {
101
+ this.wildcardListeners = [];
102
+ return;
103
+ }
104
+ const index = this.wildcardListeners.indexOf(listener);
105
+ if (index !== -1) this.wildcardListeners.splice(index, 1);
106
+ return;
107
+ }
108
+
87
109
  const listeners = this.events.get(event);
88
110
  if (!listeners) return;
89
111
 
@@ -1,4 +1,4 @@
1
1
  // Generated at compile time — do not edit manually
2
- export const BUILD_SHA = 'a3cadf8'
2
+ export const BUILD_SHA = '2d0d67e'
3
3
  export const BUILD_BRANCH = 'main'
4
- export const BUILD_DATE = '2026-03-28T06:19:50Z'
4
+ export const BUILD_DATE = '2026-04-03T01:24:54Z'
package/src/client.ts CHANGED
@@ -46,7 +46,7 @@ export class Client<
46
46
  static override eventsSchema = ClientEventsSchema
47
47
 
48
48
  /** Self-register a Client subclass from a static initialization block. */
49
- static register: (SubClass: typeof Client, id?: string) => typeof Client
49
+ static register: (SubClass: abstract new (options: any, context: any) => Client, id?: string) => abstract new (options: any, context: any) => Client
50
50
 
51
51
  static attach(container: Container & ClientsInterface): any {
52
52
  Object.assign(container, {
@@ -141,7 +141,7 @@ export const helperCache = new Map();
141
141
  * ```
142
142
  */
143
143
  Client.register = function registerClient(
144
- SubClass: typeof Client,
144
+ SubClass: abstract new (options: any, context: any) => Client,
145
145
  id?: string,
146
146
  ) {
147
147
  const registryId = id ?? SubClass.name[0]!.toLowerCase() + SubClass.name.slice(1)
@@ -3,6 +3,7 @@ import { ClientStateSchema, ClientOptionsSchema, ClientEventsSchema } from '@soe
3
3
  import { Client } from "@soederpop/luca/client";
4
4
  import { RestClient } from "../rest";
5
5
  import type { ContainerContext } from "@soederpop/luca/container";
6
+ import type { NodeContainer } from "../../node/container.js";
6
7
  import type { AxiosRequestConfig } from 'axios'
7
8
 
8
9
  declare module "@soederpop/luca/client" {
@@ -92,6 +93,10 @@ export class ElevenLabsClient extends RestClient<ElevenLabsClientState, ElevenLa
92
93
  super(options, context)
93
94
  }
94
95
 
96
+ override get container(): NodeContainer {
97
+ return super.container as unknown as NodeContainer
98
+ }
99
+
95
100
  /** The resolved API key from options or environment. */
96
101
  get apiKey(): string {
97
102
  return this.options.apiKey || process.env.ELEVENLABS_API_KEY || ''
@@ -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
  import { bootstrapFiles, bootstrapTemplates, bootstrapExamples, bootstrapTutorials } from '../bootstrap/generated.js'
6
7
  import { generateScaffold } from '../scaffolds/template.js'
7
8
 
@@ -17,7 +18,7 @@ export const argsSchema = CommandOptionsSchema.extend({
17
18
  })
18
19
 
19
20
  async function bootstrap(options: z.infer<typeof argsSchema>, context: ContainerContext) {
20
- const { container } = context
21
+ const container = context.container as unknown as NodeContainer
21
22
  const args = container.argv._ as string[]
22
23
  const fs = container.feature('fs')
23
24
  const ui = container.feature('ui')
@@ -186,6 +186,7 @@ export default async function chat(options: z.infer<typeof argsSchema>, context:
186
186
  const items = Array.isArray(options.use) ? options.use : [options.use]
187
187
  for (const item of items) {
188
188
  const [namepart, optStr] = item.split(':')
189
+ if (!namepart) continue
189
190
  const featureOpts: Record<string, any> = { enable: true }
190
191
  if (optStr) {
191
192
  for (const pair of optStr.split(';')) {
@@ -36,7 +36,7 @@ export default async function code(options: z.infer<typeof argsSchema>, context:
36
36
  if (options.prompt) {
37
37
  const resolved = container.paths.resolve(options.prompt)
38
38
  if (fs.exists(resolved)) {
39
- systemPrompt = fs.readFile(resolved)
39
+ systemPrompt = String(fs.readFile(resolved))
40
40
  } else if (!options.prompt.endsWith('.md')) {
41
41
  systemPrompt = options.prompt
42
42
  } else {
@@ -81,6 +81,8 @@ export default async function code(options: z.infer<typeof argsSchema>, context:
81
81
  model: options.model,
82
82
  local: options.local,
83
83
  skills: extraSkills,
84
+ maxTokens: 2048,
85
+ autoLoadLucaSkill: true,
84
86
  })
85
87
 
86
88
  // ── UI setup ───────────────────────────────────────────────────────────
@@ -319,7 +321,7 @@ export default async function code(options: z.infer<typeof argsSchema>, context:
319
321
 
320
322
  const featureContext: Record<string, any> = {}
321
323
  for (const fname of container.features.available) {
322
- try { featureContext[fname] = container.feature(fname) } catch {}
324
+ try { featureContext[fname] = (container as any).feature(fname) } catch {}
323
325
  }
324
326
 
325
327
  const replPrompt = ui.colors.magenta('console') + ui.colors.dim(' > ')
@@ -257,16 +257,16 @@ async function runParallel(
257
257
 
258
258
  function pushLines(idx: number, text: string) {
259
259
  const newLines = text.split('\n')
260
- promptStates[idx].lines.push(...newLines)
261
- if (promptStates[idx].lines.length > MAX_LINES) {
262
- promptStates[idx].lines = promptStates[idx].lines.slice(-MAX_LINES)
260
+ promptStates[idx]!.lines.push(...newLines)
261
+ if (promptStates[idx]!.lines.length > MAX_LINES) {
262
+ promptStates[idx]!.lines = promptStates[idx]!.lines.slice(-MAX_LINES)
263
263
  }
264
264
  }
265
265
 
266
266
  function pushToolLine(idx: number, text: string) {
267
- promptStates[idx].lines.push(text)
268
- if (promptStates[idx].lines.length > MAX_LINES) {
269
- promptStates[idx].lines.splice(0, 1)
267
+ promptStates[idx]!.lines.push(text)
268
+ if (promptStates[idx]!.lines.length > MAX_LINES) {
269
+ promptStates[idx]!.lines.splice(0, 1)
270
270
  }
271
271
  }
272
272
 
@@ -304,7 +304,7 @@ async function runParallel(
304
304
  if (!Array.isArray(content)) return
305
305
 
306
306
  const usage = message?.message?.usage ?? message?.usage
307
- if (usage?.output_tokens) promptStates[idx].outputTokens += usage.output_tokens
307
+ if (usage?.output_tokens) promptStates[idx]!.outputTokens += usage.output_tokens
308
308
 
309
309
  for (const block of content) {
310
310
  if (block.type === 'text' && block.text) {
@@ -321,33 +321,33 @@ async function runParallel(
321
321
  const idx = sessionMap.get(sessionId)
322
322
  if (idx === undefined) return
323
323
  if (event.type === 'assistant' || event.type === 'tool_result' || event.type === 'message' || event.type === 'function_call_output') {
324
- promptStates[idx].collectedEvents.push(event)
324
+ promptStates[idx]!.collectedEvents.push(event)
325
325
  }
326
326
  })
327
327
  }
328
328
 
329
329
  // Start all sessions — merge per-prompt agentOptions with shared runOptions
330
330
  for (let i = 0; i < prepared.length; i++) {
331
- const perPromptOptions = { ...prepared[i].agentOptions, ...runOptions }
331
+ const perPromptOptions = { ...prepared[i]!.agentOptions, ...runOptions }
332
332
  if (options.model) perPromptOptions.model = options.model
333
- const id = await feature.start(prepared[i].promptContent, perPromptOptions)
333
+ const id = await feature.start(prepared[i]!.promptContent, perPromptOptions)
334
334
  sessionMap.set(id, i)
335
335
  }
336
336
 
337
337
  const ids = [...sessionMap.keys()]
338
338
  sessionPromise = Promise.allSettled(ids.map((id) => feature.waitForSession(id))).then((results) => {
339
339
  results.forEach((r, ri) => {
340
- const id = ids[ri]
340
+ const id = ids[ri]!
341
341
  const idx = sessionMap.get(id)!
342
- promptStates[idx].durationMs = Date.now() - promptStates[idx].startTime
342
+ promptStates[idx]!.durationMs = Date.now() - promptStates[idx]!.startTime
343
343
  if (r.status === 'fulfilled' && r.value?.status === 'error') {
344
- promptStates[idx].status = 'error'
345
- promptStates[idx].error = r.value?.error || 'Session failed'
344
+ promptStates[idx]!.status = 'error'
345
+ promptStates[idx]!.error = r.value?.error || 'Session failed'
346
346
  } else if (r.status === 'rejected') {
347
- promptStates[idx].status = 'error'
348
- promptStates[idx].error = String(r.reason)
347
+ promptStates[idx]!.status = 'error'
348
+ promptStates[idx]!.error = String(r.reason)
349
349
  } else {
350
- promptStates[idx].status = 'done'
350
+ promptStates[idx]!.status = 'done'
351
351
  }
352
352
  })
353
353
  allDone = true
@@ -375,16 +375,16 @@ async function runParallel(
375
375
 
376
376
  assistant.on('chunk', (text: string) => {
377
377
  lineBuffers[i] += text
378
- const parts = lineBuffers[i].split('\n')
378
+ const parts = lineBuffers[i]!.split('\n')
379
379
  lineBuffers[i] = parts.pop() || ''
380
380
  if (parts.length) {
381
- promptStates[i].lines.push(...parts)
382
- if (promptStates[i].lines.length > MAX_LINES) {
383
- promptStates[i].lines = promptStates[i].lines.slice(-MAX_LINES)
381
+ promptStates[i]!.lines.push(...parts)
382
+ if (promptStates[i]!.lines.length > MAX_LINES) {
383
+ promptStates[i]!.lines = promptStates[i]!.lines.slice(-MAX_LINES)
384
384
  }
385
385
  }
386
386
  if (options['out-file']) {
387
- promptStates[i].collectedEvents.push({ type: 'assistant', message: { content: [{ type: 'text', text }] } })
387
+ promptStates[i]!.collectedEvents.push({ type: 'assistant', message: { content: [{ type: 'text', text }] } })
388
388
  }
389
389
  })
390
390
 
@@ -392,7 +392,7 @@ async function runParallel(
392
392
  const argsStr = JSON.stringify(args).slice(0, 80)
393
393
  pushToolLine(i, ` > ${toolName}(${argsStr})`)
394
394
  if (options['out-file']) {
395
- promptStates[i].collectedEvents.push({
395
+ promptStates[i]!.collectedEvents.push({
396
396
  type: 'assistant',
397
397
  message: { content: [{ type: 'tool_use', name: toolName, input: args }] },
398
398
  })
@@ -403,7 +403,7 @@ async function runParallel(
403
403
  const preview = typeof result === 'string' ? result.slice(0, 60) : JSON.stringify(result).slice(0, 60)
404
404
  pushToolLine(i, ` ✓ ${toolName} → ${preview}`)
405
405
  if (options['out-file']) {
406
- promptStates[i].collectedEvents.push({
406
+ promptStates[i]!.collectedEvents.push({
407
407
  type: 'tool_result',
408
408
  content: typeof result === 'string' ? result : JSON.stringify(result, null, 2),
409
409
  })
@@ -418,20 +418,20 @@ async function runParallel(
418
418
  return assistant
419
419
  })
420
420
 
421
- sessionPromise = Promise.allSettled(assistants.map((a, i) => a.ask(prepared[i].promptContent))).then(
421
+ sessionPromise = Promise.allSettled(assistants.map((a, i) => a.ask(prepared[i]!.promptContent))).then(
422
422
  (results) => {
423
423
  results.forEach((r, i) => {
424
- promptStates[i].durationMs = Date.now() - promptStates[i].startTime
424
+ promptStates[i]!.durationMs = Date.now() - promptStates[i]!.startTime
425
425
  // Flush remaining line buffer
426
426
  if (lineBuffers[i]) {
427
- promptStates[i].lines.push(lineBuffers[i])
427
+ promptStates[i]!.lines.push(lineBuffers[i]!)
428
428
  lineBuffers[i] = ''
429
429
  }
430
430
  if (r.status === 'rejected') {
431
- promptStates[i].status = 'error'
432
- promptStates[i].error = String(r.reason)
431
+ promptStates[i]!.status = 'error'
432
+ promptStates[i]!.error = String(r.reason)
433
433
  } else {
434
- promptStates[i].status = 'done'
434
+ promptStates[i]!.status = 'done'
435
435
  }
436
436
  })
437
437
  allDone = true
@@ -551,9 +551,9 @@ async function runParallel(
551
551
  const stem = dotIdx > 0 ? base.slice(0, dotIdx) : base
552
552
 
553
553
  for (let i = 0; i < promptStates.length; i++) {
554
- const ps = promptStates[i]
554
+ const ps = promptStates[i]!
555
555
  if (!ps.collectedEvents.length) continue
556
- const promptBasename = paths.basename(prepared[i].resolvedPath)
556
+ const promptBasename = paths.basename(prepared[i]!.resolvedPath)
557
557
  const promptStem = promptBasename.lastIndexOf('.') > 0 ? promptBasename.slice(0, promptBasename.lastIndexOf('.')) : promptBasename
558
558
  const outPath = paths.resolve(`${stem}-${promptStem}${ext}`)
559
559
  const markdown = formatSessionMarkdown(ps.collectedEvents, options['include-output'])
@@ -655,7 +655,7 @@ async function resolveInputs(
655
655
 
656
656
  // Build wizard questions for missing inputs
657
657
  const questions = missing.map((key) => {
658
- const def = inputDefs[key]
658
+ const def = inputDefs[key]!
659
659
  const q: Record<string, any> = {
660
660
  name: key,
661
661
  message: def.description || key,
@@ -920,7 +920,7 @@ export default async function prompt(options: z.infer<typeof argsSchema>, contex
920
920
  }
921
921
 
922
922
  // --- Single prompt mode ---
923
- const promptPath = allPaths[0]
923
+ const promptPath = allPaths[0]!
924
924
  const p = await preparePrompt(promptPath, options, container)
925
925
 
926
926
  if (!p) {