@soederpop/luca 0.1.2 → 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 (366) hide show
  1. package/CLAUDE.md +2 -0
  2. package/assistants/codingAssistant/hooks.ts +1 -5
  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/src/agi/feature.ts +13 -0
  300. package/src/agi/features/assistant.ts +36 -25
  301. package/src/agi/features/assistants-manager.ts +70 -5
  302. package/src/agi/features/autonomous-assistant.ts +1 -5
  303. package/src/agi/features/browser-use.ts +2 -2
  304. package/src/agi/features/claude-code.ts +165 -1
  305. package/src/agi/features/conversation-history.ts +2 -6
  306. package/src/agi/features/conversation.ts +95 -3
  307. package/src/agi/features/docs-reader.ts +2 -1
  308. package/src/agi/features/file-tools.ts +2 -2
  309. package/src/agi/features/luca-coder.ts +1 -5
  310. package/src/agi/features/openai-codex.ts +1 -1
  311. package/src/agi/features/openapi.ts +3 -3
  312. package/src/agi/features/skills-library.ts +87 -6
  313. package/src/agi/lib/interceptor-chain.ts +10 -0
  314. package/src/agi/lib/token-counter.ts +1 -1
  315. package/src/bootstrap/generated.ts +126 -1
  316. package/src/bus.ts +27 -5
  317. package/src/cli/build-info.ts +2 -2
  318. package/src/client.ts +2 -2
  319. package/src/clients/elevenlabs/index.ts +5 -0
  320. package/src/commands/bootstrap.ts +2 -1
  321. package/src/commands/chat.ts +1 -0
  322. package/src/commands/code.ts +4 -2
  323. package/src/commands/prompt.ts +34 -34
  324. package/src/commands/sandbox-mcp.ts +69 -163
  325. package/src/commands/save-api-docs.ts +10 -8
  326. package/src/commands/select.ts +8 -3
  327. package/src/container-describer.ts +70 -84
  328. package/src/container.ts +93 -3
  329. package/src/endpoint.ts +1 -1
  330. package/src/entity.ts +173 -0
  331. package/src/feature.ts +3 -3
  332. package/src/helper.ts +8 -4
  333. package/src/introspection/generated.agi.ts +1246 -798
  334. package/src/introspection/generated.node.ts +892 -798
  335. package/src/introspection/generated.web.ts +95 -3
  336. package/src/introspection/scan.ts +1 -1
  337. package/src/node/container.ts +1 -1
  338. package/src/node/features/content-db.ts +3 -3
  339. package/src/node/features/file-manager.ts +10 -9
  340. package/src/node/features/git.ts +5 -5
  341. package/src/node/features/helpers.ts +1 -1
  342. package/src/node/features/json-tree.ts +1 -1
  343. package/src/node/features/os.ts +3 -3
  344. package/src/node/features/package-finder.ts +1 -1
  345. package/src/node/features/process-manager.ts +1 -1
  346. package/src/node/features/python.ts +3 -3
  347. package/src/node/features/redis.ts +1 -1
  348. package/src/node/features/repl.ts +2 -2
  349. package/src/node/features/transpiler.ts +2 -2
  350. package/src/node/features/ui.ts +1 -1
  351. package/src/node/features/vm.ts +3 -3
  352. package/src/node/features/yaml-tree.ts +1 -1
  353. package/src/node.ts +1 -0
  354. package/src/python/generated.ts +1 -1
  355. package/src/scaffolds/generated.ts +1 -1
  356. package/src/selector.ts +74 -4
  357. package/src/server.ts +2 -2
  358. package/src/servers/mcp.ts +6 -6
  359. package/src/web/features/helpers.ts +1 -1
  360. package/src/web/features/network.ts +1 -0
  361. package/test/conversation.test.ts +220 -0
  362. package/tsconfig.build.json +12 -0
  363. package/tsconfig.json +1 -1
  364. package/scripts/examples/telegram-ink-ui.ts +0 -302
  365. package/scripts/examples/using-openai-codex.ts +0 -23
  366. package/scripts/examples/vm-loading-esm-modules.ts +0 -16
package/src/container.ts CHANGED
@@ -11,6 +11,7 @@ import { z } from 'zod'
11
11
  import { ContainerStateSchema, describeZodShape } from './schemas/base'
12
12
  import { getContainerBuildTimeData, type ContainerIntrospection, type RegistryIntrospection, type IntrospectionSection } from './introspection/index'
13
13
  import { ContainerDescriber } from './container-describer'
14
+ import { createEntityObject, type Entity, type EventMap as EntityEventMap } from './entity'
14
15
 
15
16
  export { z }
16
17
 
@@ -23,7 +24,24 @@ export type { AvailableFeatures }
23
24
  // I want the InstanceType of each value of AvailableFeatures, AvailableClients, whatever
24
25
  export type AvailableInstanceTypes<T> = {
25
26
  [K in keyof T]: T[K] extends new (...args: any) => any ? InstanceType<T[K]> : never
26
- }
27
+ }
28
+
29
+ /**
30
+ * Maps a feature registry to the INPUT type of each feature's optionsSchema.
31
+ * This allows feature() to accept partial/optional options (e.g. omitting fields
32
+ * that have .default() on them) rather than requiring the fully-parsed OUTPUT type.
33
+ *
34
+ * For any feature class that exposes a static `optionsSchema`, we use `z.input<S>` so
35
+ * that callers can omit fields that have `.default(...)` — Zod's output type marks
36
+ * defaulted fields as required, but the input type correctly makes them optional.
37
+ */
38
+ export type FeatureInputOptions<Features> = {
39
+ [K in keyof Features]: Features[K] extends { optionsSchema: infer S extends z.ZodType }
40
+ ? z.input<S>
41
+ : Features[K] extends new (options: infer O, ...args: any[]) => any
42
+ ? O
43
+ : Record<string, unknown>
44
+ }
27
45
 
28
46
  /**
29
47
  * You'll want to use module augmentation to add your own options to the ContainerArgv interface
@@ -53,6 +71,7 @@ export interface ContainerUtils {
53
71
 
54
72
  export interface ContainerContext<T extends AvailableFeatures = any> {
55
73
  container: Container<T>
74
+ [key: string]: unknown
56
75
  }
57
76
 
58
77
  /**
@@ -429,6 +448,7 @@ export class Container<Features extends AvailableFeatures = AvailableFeatures, C
429
448
 
430
449
  const instance = new (BaseClass as any)(helperOptions, context || this.context)
431
450
  cache.set(cacheKey, instance)
451
+ uuidCache.set(instance.uuid, instance)
432
452
  return instance
433
453
  }
434
454
 
@@ -445,7 +465,7 @@ export class Container<Features extends AvailableFeatures = AvailableFeatures, C
445
465
  */
446
466
  feature<T extends keyof Features>(
447
467
  id: T,
448
- options?: ConstructorParameters<Features[T]>[0]
468
+ options?: FeatureInputOptions<Features>[T] | Record<string, unknown>
449
469
  ): InstanceType<Features[T]> {
450
470
  const BaseClass = this.features.lookup(id as string) as Features[T]
451
471
 
@@ -459,7 +479,75 @@ export class Container<Features extends AvailableFeatures = AvailableFeatures, C
459
479
  context: { container: this },
460
480
  }) as InstanceType<Features[T]>
461
481
  }
462
-
482
+
483
+ /**
484
+ * Creates a lightweight entity object with observable state, a typed event bus, and
485
+ * access to the container. Same id + options always returns the same cached base instance.
486
+ *
487
+ * An optional third argument auto-extends the entity with functions and getters.
488
+ * All extended methods and getters can access the entity (state, options, container,
489
+ * on/off/emit, etc.) via `this`.
490
+ *
491
+ * @param id - Stable identifier for this entity (included in cache key)
492
+ * @param options - Arbitrary options stored on `entity.options` (included in cache key)
493
+ * @param extensions - Optional object of functions/getters to graft onto the entity
494
+ *
495
+ * @example
496
+ * ```ts
497
+ * // Basic entity with typed state and events
498
+ * const counter = container.entity<{ count: number }>('counter')
499
+ * counter.setState({ count: 0 })
500
+ * counter.on('tick', () => counter.setState(s => ({ count: s.count + 1 })))
501
+ *
502
+ * // With options and auto-extension
503
+ * const user = container.entity('user:42', { name: 'Alice' }, {
504
+ * greet() { return `Hello ${this.options.name}` },
505
+ * get label() { return `User: ${this.options.name}` },
506
+ * })
507
+ * user.greet() // "Hello Alice"
508
+ * ```
509
+ */
510
+ entity<
511
+ TState extends Record<string, any> = Record<string, any>,
512
+ TOptions extends Record<string, any> = Record<string, any>,
513
+ TEvents extends EntityEventMap = EntityEventMap,
514
+ Ext extends Record<string, any> = {},
515
+ >(
516
+ id: string,
517
+ options?: TOptions,
518
+ extensions?: Ext & ThisType<Entity<TState, TOptions, TEvents> & Ext>
519
+ ): Entity<TState, TOptions, TEvents> & Ext {
520
+ const normalizedOptions = (options || {}) as TOptions
521
+ const cacheKey = this.buildHelperCacheKey('entity', id, normalizedOptions)
522
+
523
+ let base = entityCache.get(cacheKey)
524
+ if (!base) {
525
+ base = createEntityObject<TState, TOptions, TEvents>(id, this, normalizedOptions)
526
+ entityCache.set(cacheKey, base)
527
+ }
528
+
529
+ return extensions ? base.extend(extensions) : base
530
+ }
531
+
532
+ /**
533
+ * Look up any helper instance (feature, client, server) by its UUID.
534
+ * Returns undefined if the UUID is unknown or the instance was never created.
535
+ *
536
+ * @param uuid - The `instance.uuid` value assigned at construction time
537
+ * @returns The helper instance, or undefined
538
+ *
539
+ * @example
540
+ * ```ts
541
+ * const assistant = container.feature('assistant')
542
+ * const { uuid } = assistant
543
+ * // ... later ...
544
+ * const same = container.getHelperByUUID(uuid) // === assistant
545
+ * ```
546
+ */
547
+ getHelperByUUID(uuid: string): Helper | undefined {
548
+ return uuidCache.get(uuid)
549
+ }
550
+
463
551
  /**
464
552
  * Start the container. Emits the 'started' event and sets `state.started` to true.
465
553
  * Plugins and features can listen for this event to perform initialization.
@@ -822,6 +910,8 @@ export class Container<Features extends AvailableFeatures = AvailableFeatures, C
822
910
  }
823
911
 
824
912
  const helperCache = new Map()
913
+ const entityCache = new Map()
914
+ const uuidCache = new Map<string, Helper>()
825
915
  const featureIdToHelperCacheKeyMap= new Map()
826
916
  const contextMap = new WeakMap()
827
917
 
package/src/endpoint.ts CHANGED
@@ -82,7 +82,7 @@ class RateLimiter {
82
82
  }
83
83
 
84
84
  // Prune timestamps outside the window
85
- while (timestamps.length > 0 && timestamps[0] <= now - windowMs) {
85
+ while (timestamps.length > 0 && (timestamps[0] ?? 0) <= now - windowMs) {
86
86
  timestamps.shift()
87
87
  }
88
88
 
package/src/entity.ts ADDED
@@ -0,0 +1,173 @@
1
+ import { Bus, type EventMap } from './bus.js'
2
+ import { State, type SetStateValue } from './state.js'
3
+ import type { Container } from './container.js'
4
+ import uuid from 'node-uuid'
5
+ import { z } from 'zod'
6
+
7
+ /**
8
+ * An Entity is a lightweight, composable object with observable state, a typed event bus,
9
+ * and a reference to the container. Unlike Helpers, Entities are not class-based — they
10
+ * are plain objects created directly via `container.entity()` and extended via `.extend()`.
11
+ *
12
+ * Same id + options always returns the same underlying state/bus instance (cached).
13
+ *
14
+ * @template TState - Shape of the entity's observable state
15
+ * @template TOptions - Shape of the options passed at construction
16
+ * @template TEvents - Event map for the typed event bus
17
+ */
18
+ export type Entity<
19
+ TState extends Record<string, any> = Record<string, any>,
20
+ TOptions extends Record<string, any> = Record<string, any>,
21
+ TEvents extends EventMap = EventMap,
22
+ > = {
23
+ /** The id passed to container.entity() */
24
+ readonly id: string
25
+ /** Per-instance UUID */
26
+ readonly uuid: string
27
+ /** The options the entity was created with */
28
+ readonly options: TOptions
29
+ /** Observable state */
30
+ readonly state: State<TState>
31
+ /** The container this entity belongs to */
32
+ readonly container: Container<any>
33
+
34
+ on<E extends keyof TEvents>(event: E, listener: (...args: TEvents[E]) => void): void
35
+ off<E extends keyof TEvents>(event: E, listener?: (...args: TEvents[E]) => void): void
36
+ once<E extends keyof TEvents>(event: E, listener: (...args: TEvents[E]) => void): void
37
+ emit<E extends keyof TEvents>(event: E, ...args: TEvents[E]): void
38
+ waitFor<E extends keyof TEvents>(event: E): Promise<TEvents[E]>
39
+ setState(value: SetStateValue<TState>): void
40
+
41
+ /**
42
+ * Graft an object of functions and getters onto this entity, returning a new type-safe
43
+ * object. The base entity (state, events, container, options) is accessible via `this`
44
+ * in all grafted methods and getters. Chaining `.extend()` on the result works correctly —
45
+ * each layer has access to everything in the layers below it.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const session = container.entity('session:abc', { userId: '42' })
50
+ * const rich = session.extend({
51
+ * greet() { return `Hello user ${this.options.userId}` },
52
+ * get label() { return `Session ${this.id}` },
53
+ * })
54
+ * rich.greet() // "Hello user 42"
55
+ * ```
56
+ */
57
+ extend<Ext extends Record<string, any>>(
58
+ extensions: Ext & ThisType<Entity<TState, TOptions, TEvents> & Ext>
59
+ ): Entity<TState, TOptions, TEvents> & Ext
60
+
61
+ /**
62
+ * Register a method on this entity as an AI tool with the given Zod schema.
63
+ * Chainable — returns `this` so you can stack multiple `.expose()` calls.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * const agent = container.entity('agent', {})
68
+ * .extend({ search({ query }: { query: string }) { ... } })
69
+ * .expose('search', z.object({ query: z.string() }))
70
+ *
71
+ * assistant.addTools(agent)
72
+ * ```
73
+ */
74
+ expose(functionName: string, schema: z.ZodType): this
75
+
76
+ /**
77
+ * Returns `{ schemas, handlers }` for all tools registered via `.expose()`.
78
+ * Compatible with `assistant.addTools()` and the standard `toTools` contract.
79
+ */
80
+ toTools(): { schemas: Record<string, z.ZodType>; handlers: Record<string, Function> }
81
+ }
82
+
83
+ /** @internal */
84
+ export function createEntityObject<
85
+ TState extends Record<string, any> = Record<string, any>,
86
+ TOptions extends Record<string, any> = Record<string, any>,
87
+ TEvents extends EventMap = EventMap,
88
+ >(
89
+ id: string,
90
+ container: Container<any>,
91
+ options: TOptions,
92
+ ): Entity<TState, TOptions, TEvents> {
93
+ const _events = new Bus<TEvents>()
94
+ const _state = new State<TState>()
95
+
96
+ const _exposed = new Map<string, z.ZodType>()
97
+
98
+ const entity: Entity<TState, TOptions, TEvents> = {
99
+ id,
100
+ uuid: (uuid as any).v4(),
101
+ options,
102
+ state: _state,
103
+ container,
104
+ on(event: any, listener: any) { _events.on(event, listener) },
105
+ off(event: any, listener?: any) { _events.off(event, listener) },
106
+ once(event: any, listener: any) { _events.once(event, listener) },
107
+ emit(event: any, ...args: any[]) { _events.emit(event, ...args) },
108
+ waitFor(event: any) { return _events.waitFor(event) },
109
+ setState(value: any) { _state.setState(value) },
110
+ extend(extensions: any) { return applyExtensions(this as any, extensions) },
111
+ expose(functionName: string, schema: z.ZodType) {
112
+ // Each prototype layer gets its own _exposed map (lazy-created on write)
113
+ if (!Object.prototype.hasOwnProperty.call(this, '_exposed')) {
114
+ ;(this as any)._exposed = new Map<string, z.ZodType>()
115
+ }
116
+ ;(this as any)._exposed.set(functionName, schema)
117
+ return this
118
+ },
119
+ toTools() {
120
+ const schemas: Record<string, z.ZodType> = {}
121
+ const handlers: Record<string, Function> = {}
122
+
123
+ // Walk the prototype chain collecting _exposed maps; shallower layers win
124
+ let obj: any = this
125
+ while (obj !== null) {
126
+ if (Object.prototype.hasOwnProperty.call(obj, '_exposed')) {
127
+ for (const [name, schema] of (obj._exposed as Map<string, z.ZodType>)) {
128
+ if (!(name in schemas)) {
129
+ schemas[name] = schema
130
+ handlers[name] = (args: any) => (this as any)[name](args)
131
+ }
132
+ }
133
+ }
134
+ obj = Object.getPrototypeOf(obj)
135
+ }
136
+
137
+ return { schemas, handlers }
138
+ },
139
+ }
140
+
141
+ ;(entity as any)._exposed = _exposed
142
+
143
+ return entity
144
+ }
145
+
146
+ /**
147
+ * Graft extensions onto an entity via prototype delegation.
148
+ *
149
+ * The extended object's prototype is `base`, so all base properties (state, container,
150
+ * on/off/emit, etc.) are reachable through `this` in any grafted method or getter.
151
+ * Calling `.extend()` on the result correctly uses the extended object as the new base.
152
+ */
153
+ function applyExtensions<
154
+ TState extends Record<string, any>,
155
+ TOptions extends Record<string, any>,
156
+ TEvents extends EventMap,
157
+ Ext extends Record<string, any>,
158
+ >(
159
+ base: Entity<TState, TOptions, TEvents>,
160
+ extensions: Ext,
161
+ ): Entity<TState, TOptions, TEvents> & Ext {
162
+ const extended = Object.create(base) as Entity<TState, TOptions, TEvents> & Ext
163
+
164
+ for (const key of Object.getOwnPropertyNames(extensions)) {
165
+ const descriptor = Object.getOwnPropertyDescriptor(extensions, key)!
166
+ Object.defineProperty(extended, key, {
167
+ ...descriptor,
168
+ configurable: true,
169
+ })
170
+ }
171
+
172
+ return extended
173
+ }
package/src/feature.ts CHANGED
@@ -23,9 +23,9 @@ export abstract class Feature<T extends FeatureState = FeatureState, K extends F
23
23
  static override eventsSchema = FeatureEventsSchema
24
24
 
25
25
  /** Self-register a Feature subclass from a static initialization block. */
26
- static register: (SubClass: typeof Feature, id?: string) => typeof Feature
26
+ static register: (SubClass: abstract new (options: any, context: any) => Feature, id?: string) => abstract new (options: any, context: any) => Feature
27
27
 
28
- get shortcut() {
28
+ override get shortcut() {
29
29
  return (this.constructor as any).shortcut as string
30
30
  }
31
31
 
@@ -92,7 +92,7 @@ export const features = new FeaturesRegistry()
92
92
  * ```
93
93
  */
94
94
  Feature.register = function registerFeature(
95
- SubClass: typeof Feature,
95
+ SubClass: abstract new (options: any, context: any) => Feature,
96
96
  id?: string,
97
97
  ) {
98
98
  const registryId = id ?? SubClass.name[0]!.toLowerCase() + SubClass.name.slice(1)
package/src/helper.ts CHANGED
@@ -322,13 +322,17 @@ export abstract class Helper<T extends HelperState = HelperState, K extends Help
322
322
  return this
323
323
  }
324
324
 
325
- on<Ev extends string & keyof E>(event: Ev, listener: (...args: E[Ev]) => void) {
326
- this._events.on(event, listener)
325
+ on(event: '*', listener: (event: string, ...args: any[]) => void): this
326
+ on<Ev extends string & keyof E>(event: Ev, listener: (...args: E[Ev]) => void): this
327
+ on<Ev extends string & keyof E>(event: Ev | '*', listener: any) {
328
+ this._events.on(event as any, listener)
327
329
  return this
328
330
  }
329
331
 
330
- off<Ev extends string & keyof E>(event: Ev, listener?: (...args: E[Ev]) => void) {
331
- this._events.off(event, listener)
332
+ off(event: '*', listener?: (event: string, ...args: any[]) => void): this
333
+ off<Ev extends string & keyof E>(event: Ev, listener?: (...args: E[Ev]) => void): this
334
+ off<Ev extends string & keyof E>(event: Ev | '*', listener?: any) {
335
+ this._events.off(event as any, listener)
332
336
  return this
333
337
  }
334
338