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,291 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
3
+ import { Feature } from '../feature.js'
4
+ import { Client } from '../../client.js'
5
+ import { allHelperInstances } from '../../container.js'
6
+ import type { Helper } from '../../helper.js'
7
+ import type { Registry } from '../../registry.js'
8
+ import type { AssetLoader } from './asset-loader.js'
9
+
10
+ export const HelpersStateSchema = FeatureStateSchema.extend({
11
+ discovered: z.record(z.string(), z.boolean()).default({}).describe('Which registry types have been discovered'),
12
+ registered: z.array(z.string()).default([]).describe('Names of project-level helpers that were discovered (type.name)'),
13
+ manifestLoaded: z.boolean().default(false).describe('Whether the manifest has been fetched'),
14
+ })
15
+
16
+ export type HelpersState = z.infer<typeof HelpersStateSchema>
17
+
18
+ export const HelpersOptionsSchema = FeatureOptionsSchema.extend({
19
+ manifestURL: z.string().optional().describe('URL to fetch the helpers manifest from. Defaults to /.well-known/luca.manifest.json'),
20
+ })
21
+
22
+ export type HelpersOptions = z.infer<typeof HelpersOptionsSchema>
23
+
24
+ export const HelpersEventsSchema = FeatureEventsSchema.extend({
25
+ discovered: z.tuple([
26
+ z.string().describe('Registry type that was discovered'),
27
+ z.array(z.string()).describe('Names of newly registered helpers'),
28
+ ]).describe('Emitted after a registry type has been discovered'),
29
+ registered: z.tuple([
30
+ z.string().describe('Registry type'),
31
+ z.string().describe('Helper name'),
32
+ ]).describe('Emitted when a single helper is registered'),
33
+ manifestLoaded: z.tuple([
34
+ z.any().describe('The parsed manifest object'),
35
+ ]).describe('Emitted when the manifest is successfully fetched'),
36
+ manifestError: z.tuple([
37
+ z.any().describe('The error that occurred'),
38
+ ]).describe('Emitted when the manifest fetch fails'),
39
+ })
40
+
41
+ type RegistryType = 'features' | 'clients'
42
+
43
+ interface ManifestEntry {
44
+ id: string
45
+ description?: string
46
+ url: string
47
+ }
48
+
49
+ interface Manifest {
50
+ features?: Record<string, ManifestEntry>
51
+ clients?: Record<string, ManifestEntry>
52
+ }
53
+
54
+ /**
55
+ * The Helpers feature discovers and loads project-level helpers from a JSON manifest
56
+ * served over HTTP. Scripts are injected via AssetLoader and self-register into
57
+ * the container's registries.
58
+ *
59
+ * This is the web equivalent of the node Helpers feature, which scans the filesystem.
60
+ * Instead of filesystem scanning, this feature fetches a manifest from a well-known URL
61
+ * and uses AssetLoader.loadScript() to inject each helper's script tag.
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const helpers = container.feature('helpers', { enable: true })
66
+ *
67
+ * // Discover all helper types from the manifest
68
+ * await helpers.discoverAll()
69
+ *
70
+ * // Discover a specific type
71
+ * await helpers.discover('features')
72
+ *
73
+ * // Unified view of all available helpers
74
+ * console.log(helpers.available)
75
+ * ```
76
+ */
77
+ export class Helpers extends Feature<HelpersState, HelpersOptions> {
78
+ static override shortcut = 'features.helpers' as const
79
+ static override description = 'Unified gateway for discovering and registering project-level helpers via HTTP manifest'
80
+ static override stateSchema = HelpersStateSchema
81
+ static override optionsSchema = HelpersOptionsSchema
82
+ static override eventsSchema = HelpersEventsSchema
83
+
84
+ static { Feature.register(this as any, 'helpers') }
85
+
86
+ private _manifest: Manifest | null = null
87
+
88
+ private get registryMap(): Record<RegistryType, { registry: Registry<any> }> {
89
+ return {
90
+ features: { registry: this.container.features as any },
91
+ clients: { registry: (this.container as any).clients as Registry<any> },
92
+ }
93
+ }
94
+
95
+ /** The URL to fetch the helpers manifest from. */
96
+ get manifestURL(): string {
97
+ return this.options.manifestURL || '/.well-known/luca.manifest.json'
98
+ }
99
+
100
+ /**
101
+ * Set a new manifest URL. Invalidates any cached manifest.
102
+ *
103
+ * @param url - The new URL to fetch the manifest from
104
+ */
105
+ setManifestURL(url: string) {
106
+ this.options.manifestURL = url
107
+ this._manifest = null
108
+ this.state.set('manifestLoaded', false)
109
+ }
110
+
111
+ /**
112
+ * Returns all instantiated helper instances across all types, optionally filtered by class.
113
+ *
114
+ * @param FilterClass - When provided, only instances of this class are returned.
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * // All instances of any type
119
+ * container.helpers.getInstances()
120
+ *
121
+ * // All Assistant instances
122
+ * const assistants = container.helpers.getInstances(Assistant)
123
+ * ```
124
+ */
125
+ getInstances(): Helper[]
126
+ getInstances<T extends Helper>(FilterClass: new (...args: any[]) => T): T[]
127
+ getInstances<T extends Helper>(FilterClass?: new (...args: any[]) => T): Helper[] | T[] {
128
+ return FilterClass ? allHelperInstances(FilterClass) : allHelperInstances()
129
+ }
130
+
131
+ /**
132
+ * Returns a unified view of all available helpers across all registries.
133
+ * Each key is a registry type, each value is the list of helper names in that registry.
134
+ */
135
+ get available(): Record<string, string[]> {
136
+ const result: Record<string, string[]> = {}
137
+ for (const [type, { registry }] of Object.entries(this.registryMap)) {
138
+ result[type] = registry.available
139
+ }
140
+ return result
141
+ }
142
+
143
+ /**
144
+ * Fetch and cache the manifest JSON. Returns cached version on subsequent calls
145
+ * unless invalidated by setManifestURL().
146
+ */
147
+ private async fetchManifest(): Promise<Manifest> {
148
+ if (this._manifest) {
149
+ return this._manifest
150
+ }
151
+
152
+ try {
153
+ const response = await fetch(this.manifestURL)
154
+
155
+ if (!response.ok) {
156
+ const err = new Error(`Manifest fetch failed: ${response.status} ${response.statusText}`)
157
+ this.emit('manifestError' as any, err)
158
+ return {}
159
+ }
160
+
161
+ const manifest = await response.json() as Manifest
162
+ this._manifest = manifest
163
+ this.state.set('manifestLoaded', true)
164
+ this.emit('manifestLoaded' as any, manifest)
165
+ return manifest
166
+ } catch (err: any) {
167
+ this.emit('manifestError' as any, err)
168
+ return {}
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Get the AssetLoader instance from the container.
174
+ */
175
+ private get assetLoader(): AssetLoader {
176
+ return this.container.feature('assetLoader') as unknown as AssetLoader
177
+ }
178
+
179
+ /**
180
+ * Discover and register helpers of the given type from the manifest.
181
+ *
182
+ * Fetches the manifest, then for each entry of the requested type,
183
+ * loads the script via AssetLoader and checks what got newly registered.
184
+ *
185
+ * @param type - Which type of helpers to discover ('features' or 'clients')
186
+ * @returns Names of helpers that were discovered and registered
187
+ */
188
+ async discover(type: RegistryType): Promise<string[]> {
189
+ const discovered = this.state.get('discovered') || {}
190
+
191
+ if (discovered[type]) {
192
+ return []
193
+ }
194
+
195
+ const manifest = await this.fetchManifest()
196
+ const entries = manifest[type] || {}
197
+ const { registry } = this.registryMap[type]
198
+ const newNames: string[] = []
199
+
200
+ for (const [name, entry] of Object.entries(entries)) {
201
+ const beforeNames = new Set(registry.available)
202
+
203
+ try {
204
+ await this.assetLoader.loadScript(entry.url)
205
+ } catch (err: any) {
206
+ console.warn(`Helpers: failed to load ${type}/${name} from ${entry.url}: ${err.message}`)
207
+ continue
208
+ }
209
+
210
+ const afterNames = registry.available
211
+ const added = afterNames.filter((n: string) => !beforeNames.has(n))
212
+
213
+ if (added.length > 0) {
214
+ for (const addedName of added) {
215
+ newNames.push(addedName)
216
+ this.emit('registered' as any, type, addedName)
217
+ }
218
+ } else if (registry.has(name)) {
219
+ // Script may have already been registered under the expected name
220
+ if (!beforeNames.has(name)) {
221
+ newNames.push(name)
222
+ this.emit('registered' as any, type, name)
223
+ }
224
+ }
225
+ }
226
+
227
+ this.state.set('discovered', { ...this.state.get('discovered'), [type]: true })
228
+
229
+ const existing = this.state.get('registered') || []
230
+ this.state.set('registered', [...existing, ...newNames.map(n => `${type}.${n}`)])
231
+
232
+ this.emit('discovered' as any, type, newNames)
233
+
234
+ return newNames
235
+ }
236
+
237
+ /**
238
+ * Discover all helper types from the manifest.
239
+ *
240
+ * @returns Map of registry type to discovered helper names
241
+ */
242
+ async discoverAll(): Promise<Record<string, string[]>> {
243
+ const results: Record<string, string[]> = {}
244
+
245
+ for (const type of ['features', 'clients'] as RegistryType[]) {
246
+ results[type] = await this.discover(type)
247
+ }
248
+
249
+ return results
250
+ }
251
+
252
+ /**
253
+ * Convenience method to discover only features.
254
+ */
255
+ async discoverFeatures(): Promise<string[]> {
256
+ return this.discover('features')
257
+ }
258
+
259
+ /**
260
+ * Convenience method to discover only clients.
261
+ */
262
+ async discoverClients(): Promise<string[]> {
263
+ return this.discover('clients')
264
+ }
265
+
266
+ /**
267
+ * Look up a helper class by type and name.
268
+ *
269
+ * @param type - The registry type
270
+ * @param name - The helper name within that registry
271
+ * @returns The helper constructor
272
+ */
273
+ lookup(type: RegistryType, name: string): any {
274
+ const { registry } = this.registryMap[type]
275
+ return registry.lookup(name)
276
+ }
277
+
278
+ /**
279
+ * Get the introspection description for a specific helper.
280
+ *
281
+ * @param type - The registry type
282
+ * @param name - The helper name
283
+ * @returns Markdown description of the helper's interface
284
+ */
285
+ describe(type: RegistryType, name: string): string {
286
+ const { registry } = this.registryMap[type]
287
+ return registry.describe(name)
288
+ }
289
+ }
290
+
291
+ export default Helpers
@@ -0,0 +1,85 @@
1
+ /// <reference lib="dom" />
2
+ import { z } from 'zod'
3
+ import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
4
+ import { Feature } from "../feature.js";
5
+ import type { ContainerContext } from "../container.js";
6
+
7
+ export const NetworkStateSchema = FeatureStateSchema.extend({
8
+ offline: z.boolean().describe('Whether the browser is currently offline'),
9
+ })
10
+
11
+ export const NetworkOptionsSchema = FeatureOptionsSchema.extend({})
12
+
13
+ export const NetworkEventsSchema = FeatureEventsSchema.extend({
14
+ online: z.tuple([]).describe('Fires when the browser regains network connectivity'),
15
+ offline: z.tuple([]).describe('Fires when the browser loses network connectivity'),
16
+ }).describe('Network events')
17
+
18
+ export type NetworkState = z.infer<typeof NetworkStateSchema>
19
+ export type NetworkOptions = z.infer<typeof NetworkOptionsSchema>
20
+
21
+ /**
22
+ * Tracks browser online/offline connectivity state.
23
+ *
24
+ * Listens for the browser's `online` and `offline` events and keeps the
25
+ * feature state in sync. Other features can observe the `offline` state
26
+ * value or listen for change events to react to connectivity changes.
27
+ *
28
+ * @extends Feature
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const network = container.feature('network')
33
+ * console.log(network.state.get('offline')) // false when online
34
+ *
35
+ * network.on('stateChanged', ({ offline }) => {
36
+ * console.log(offline ? 'Went offline' : 'Back online')
37
+ * })
38
+ * ```
39
+ */
40
+ export class Network<
41
+ T extends NetworkState = NetworkState,
42
+ K extends NetworkOptions = NetworkOptions
43
+ > extends Feature<T, K> {
44
+ static override stateSchema = NetworkStateSchema
45
+ static override optionsSchema = NetworkOptionsSchema
46
+ static override eventsSchema = NetworkEventsSchema
47
+ static override shortcut = "features.network" as const
48
+
49
+ static { Feature.register(this as any, 'network') }
50
+
51
+ constructor(options: K, context: ContainerContext) {
52
+ super(options, context);
53
+ this.state.set("offline", !navigator.onLine);
54
+ }
55
+
56
+ /** Whether the browser is currently offline. */
57
+ get isOffline() {
58
+ return this.state.get("offline") === true;
59
+ }
60
+
61
+ /** Whether the browser is currently online. */
62
+ get isOnline() {
63
+ return this.state.get("offline") === false;
64
+ }
65
+
66
+ private handleConnectionChange = () => {
67
+ const isOffline = !navigator.onLine;
68
+ this.state.set('offline', isOffline)
69
+ this.emit(isOffline ? "offline" : "online");
70
+ };
71
+
72
+ start() {
73
+ window.addEventListener("online", this.handleConnectionChange);
74
+ window.addEventListener("offline", this.handleConnectionChange);
75
+ return this
76
+ }
77
+
78
+ disable() {
79
+ window.removeEventListener("online", this.handleConnectionChange);
80
+ window.removeEventListener("offline", this.handleConnectionChange);
81
+ return this
82
+ }
83
+ }
84
+
85
+ export default Network
@@ -0,0 +1,104 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
3
+ import { Feature } from "../feature.js";
4
+ import { type ContainerContext } from "../container.js";
5
+
6
+ export const SpeechOptionsSchema = FeatureOptionsSchema.extend({
7
+ voice: z.string().optional().describe('The voice to use for the speech'),
8
+ })
9
+
10
+ export const SpeechStateSchema = FeatureStateSchema.extend({
11
+ defaultVoice: z.string().describe('Name of the currently selected default voice'),
12
+ voices: z.array(z.any().describe('Voice object')).optional().describe('Available speech synthesis voices'),
13
+ })
14
+
15
+ export type SpeechOptions = z.infer<typeof SpeechOptionsSchema>
16
+ export type SpeechState = z.infer<typeof SpeechStateSchema>
17
+
18
+ type Voice = {
19
+ voiceURI: string;
20
+ name: string;
21
+ lang: string;
22
+ localService: boolean;
23
+ default: boolean;
24
+ };
25
+
26
+ /**
27
+ * Text-to-speech synthesis using the Web Speech API (SpeechSynthesis).
28
+ *
29
+ * Wraps the browser's built-in speech synthesis, providing voice selection,
30
+ * queue management, and state tracking. Voices are discovered on init and
31
+ * exposed via state for UI binding.
32
+ *
33
+ * @extends Feature
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const speech = container.feature('speech')
38
+ * speech.say('Hello from the browser!')
39
+ *
40
+ * // Choose a specific voice
41
+ * const speech = container.feature('speech', { voice: 'Google UK English Female' })
42
+ * speech.say('Cheerio!')
43
+ * ```
44
+ */
45
+ export class Speech<
46
+ T extends SpeechState = SpeechState,
47
+ K extends SpeechOptions = SpeechOptions
48
+ > extends Feature<T, K> {
49
+
50
+ static override stateSchema = SpeechStateSchema
51
+ static override optionsSchema = SpeechOptionsSchema
52
+ static override shortcut = "features.speech" as const
53
+
54
+ static { Feature.register(this as any, 'speech') }
55
+
56
+ constructor(options: K, context: ContainerContext) {
57
+ super(options,context)
58
+
59
+ if(options.voice) {
60
+ this.state.set("defaultVoice", options.voice)
61
+ }
62
+
63
+ this.loadVoices()
64
+ }
65
+
66
+ /** Returns the array of available speech synthesis voices. */
67
+ get voices() {
68
+ return this.state.get('voices') || []
69
+ }
70
+
71
+ /** Returns the Voice object matching the currently selected default voice name. */
72
+ get defaultVoice() {
73
+ return this.voices.find(v => v.name === this.state.get("defaultVoice"))
74
+ }
75
+
76
+ loadVoices() {
77
+ const voices = speechSynthesis.getVoices();
78
+ this.state.set("voices", voices);
79
+
80
+ if (!this.state.get("defaultVoice") && voices.length > 0) {
81
+ const defaultVoice = voices.find(v => v.default)!
82
+ this.state.set("defaultVoice", defaultVoice.name);
83
+ }
84
+ }
85
+
86
+ setDefaultVoice(name: string) {
87
+ const voice = this.voices.find(v => v.name === name)!
88
+ this.state.set("defaultVoice", voice.name);
89
+ }
90
+
91
+ cancel() {
92
+ speechSynthesis.cancel()
93
+ return this
94
+ }
95
+
96
+ say(text: string, options: { voice?: Voice } = {}) {
97
+ const utterance = new SpeechSynthesisUtterance(text);
98
+ const voice = options.voice || this.defaultVoice
99
+ utterance.voice = voice || this.voices[0]!
100
+ speechSynthesis.speak(utterance);
101
+ }
102
+ }
103
+
104
+ export default Speech;
@@ -0,0 +1,207 @@
1
+ // @ts-nocheck
2
+ import { z } from 'zod'
3
+ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
4
+ import { Feature } from '../feature.js'
5
+
6
+ export const WebVaultStateSchema = FeatureStateSchema.extend({
7
+ secret: z.string().optional().describe('Base64-encoded AES-GCM encryption secret key'),
8
+ })
9
+
10
+ export const WebVaultOptionsSchema = FeatureOptionsSchema.extend({
11
+ secret: z.string().optional().describe('Pre-existing base64-encoded secret key to use'),
12
+ })
13
+
14
+ export type WebVaultState = z.infer<typeof WebVaultStateSchema>
15
+ export type WebVaultOptions = z.infer<typeof WebVaultOptionsSchema>
16
+
17
+ /**
18
+ * AES-256-GCM encryption and decryption for the browser using the Web Crypto API.
19
+ *
20
+ * Generates or accepts a secret key and provides `encrypt()` / `decrypt()` methods
21
+ * that work entirely client-side. Keys are stored as base64-encoded state so they
22
+ * can persist across sessions when needed.
23
+ *
24
+ * @extends Feature
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const vault = container.feature('vault')
29
+ * const encrypted = await vault.encrypt('secret data')
30
+ * const decrypted = await vault.decrypt(encrypted)
31
+ * console.log(decrypted) // 'secret data'
32
+ * ```
33
+ */
34
+ export class WebVault extends Feature<WebVaultState, WebVaultOptions> {
35
+ static override stateSchema = WebVaultStateSchema
36
+ static override optionsSchema = WebVaultOptionsSchema
37
+ static override shortcut = "features.vault" as const
38
+
39
+ static { Feature.register(this, 'vault') }
40
+
41
+ async secret({ refresh = false, set = true } = {}) : Promise<ArrayBuffer> {
42
+ if (!this.state.get('secret') && this.options.secret) {
43
+ this.state.set('secret', this.options.secret)
44
+ }
45
+
46
+ if (!refresh && this.state.get('secret')) {
47
+ return base64ToArrayBuffer(this.state.get('secret')!)
48
+ }
49
+
50
+ const val = await generateSecretKey()
51
+ const asString = arrayBufferToBase64(val)
52
+
53
+ if(set && !this.state.get('secret')) {
54
+ this.state.set('secret', asString)
55
+ }
56
+
57
+ return val
58
+ }
59
+
60
+ async decrypt(payload: string) {
61
+ const parts = payload.split("\n------\n")
62
+ const iv = base64ToUint8Array(parts[1]!)
63
+ const ciphertext = base64ToArrayBuffer(parts[0]!)
64
+ const secret = await this.secret()
65
+
66
+ console.log(ciphertext, secret, iv)
67
+ return await decrypt(ciphertext, secret, iv)
68
+ }
69
+
70
+ async encrypt(payload: string) {
71
+ const secret = await this.secret()
72
+ console.log("encrypting", payload, secret)
73
+ const { iv, ciphertext, } = await encrypt(payload, secret)
74
+
75
+ return [
76
+ arrayBufferToBase64(ciphertext),
77
+ uint8ArrayToBase64(iv)
78
+ ].join("\n------\n")
79
+ }
80
+
81
+ utils = {
82
+ arrayToString: arrayBufferToBase64,
83
+ stringToArray: base64ToArrayBuffer,
84
+ uintToString: uint8ArrayToBase64,
85
+ }
86
+ }
87
+
88
+ export default WebVault
89
+
90
+ async function generateSecretKey(): Promise<ArrayBuffer> {
91
+ const key = await crypto.subtle.generateKey(
92
+ { name: "AES-GCM", length: 256 },
93
+ true,
94
+ ["encrypt", "decrypt"]
95
+ );
96
+ const secretKey = await crypto.subtle.exportKey("raw", key);
97
+ return secretKey;
98
+ }
99
+
100
+ async function encrypt(plaintext: string, secretKey: ArrayBuffer): Promise<{ iv: Uint8Array; ciphertext: ArrayBuffer }> {
101
+ const encoder = new TextEncoder();
102
+ const encodedText = encoder.encode(plaintext);
103
+ const key = await crypto.subtle.importKey(
104
+ "raw",
105
+ secretKey,
106
+ { name: "AES-GCM" },
107
+ false,
108
+ ["encrypt", "decrypt"]
109
+ );
110
+ const iv = crypto.getRandomValues(new Uint8Array(12));
111
+ const ciphertext = await crypto.subtle.encrypt(
112
+ { name: "AES-GCM", iv },
113
+ key,
114
+ encodedText
115
+ );
116
+ return { iv, ciphertext };
117
+ }
118
+
119
+ async function decrypt(ciphertext: ArrayBuffer, secretKey: ArrayBuffer, iv: Uint8Array): Promise<string> {
120
+ const key = await crypto.subtle.importKey(
121
+ "raw",
122
+ secretKey,
123
+ { name: "AES-GCM" },
124
+ false,
125
+ ["encrypt", "decrypt"]
126
+ );
127
+ const plaintextArrayBuffer = await crypto.subtle.decrypt(
128
+ { name: "AES-GCM", iv },
129
+ key,
130
+ ciphertext
131
+ );
132
+ const decoder = new TextDecoder();
133
+ const plaintext = decoder.decode(plaintextArrayBuffer);
134
+ return plaintext;
135
+ }
136
+
137
+ function arrayBufferToBase64(buffer: ArrayBuffer): string {
138
+ const bytes = new Uint8Array(buffer);
139
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
140
+ let base64 = "";
141
+
142
+ for (let i = 0; i < bytes.byteLength; i += 3) {
143
+ const a = bytes[i];
144
+ const b = bytes[i + 1];
145
+ const c = bytes[i + 2];
146
+
147
+ const index1 = a >> 2;
148
+ const index2 = ((a & 0x03) << 4) | (b >> 4);
149
+ const index3 = isNaN(b!) ? 64 : ((b & 0x0f) << 2) | (c >> 6);
150
+ const index4 = isNaN(b!) || isNaN(c!) ? 64 : c & 0x3f;
151
+
152
+ base64 += chars[index1] + chars[index2] + chars[index3] + chars[index4];
153
+ }
154
+
155
+ return base64.replace('undefined', '==');
156
+ }
157
+
158
+ function uint8ArrayToBase64(u: Uint8Array): string {
159
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
160
+ let base64 = "";
161
+
162
+ for (let i = 0; i < u.byteLength; i += 3) {
163
+ const a = u[i];
164
+ const b = u[i + 1];
165
+ const c = u[i + 2];
166
+
167
+ const index1 = a >> 2;
168
+ const index2 = ((a & 0x03) << 4) | (b >> 4);
169
+ const index3 = isNaN(b!) ? 64 : ((b & 0x0f) << 2) | (c >> 6);
170
+ const index4 = isNaN(b!) || isNaN(c!) ? 64 : c & 0x3f;
171
+
172
+ base64 += chars[index1]! + chars[index2]! + chars[index3]! + chars[index4]!;
173
+ }
174
+
175
+ return base64;
176
+ }
177
+
178
+ function base64ToArrayBuffer(base64: string): ArrayBuffer {
179
+ const uint8Array = base64ToUint8Array(base64)!;
180
+ return uint8Array.buffer as ArrayBuffer;
181
+ }
182
+
183
+ function base64ToUint8Array(base64: string): Uint8Array {
184
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
185
+ const lookup = new Uint8Array(256);
186
+
187
+ for (let i = 0; i < chars.length; i++) {
188
+ lookup[chars.charCodeAt(i)] = i;
189
+ }
190
+
191
+ const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
192
+ const length = (base64.length * 3 / 4) - padding;
193
+ const bytes = new Uint8Array(length);
194
+
195
+ for (let i = 0, j = 0; i < base64.length; i += 4, j += 3) {
196
+ const index1 = lookup[base64.charCodeAt(i)];
197
+ const index2 = lookup[base64.charCodeAt(i + 1)];
198
+ const index3 = lookup[base64.charCodeAt(i + 2)];
199
+ const index4 = lookup[base64.charCodeAt(i + 3)];
200
+
201
+ bytes[j] = (index1 << 2) | (index2 >> 4);
202
+ if (j + 1 < length) bytes[j + 1] = ((index2 & 0x0f) << 4) | (index3 >> 2);
203
+ if (j + 2 < length) bytes[j + 2] = ((index3 & 0x03) << 6) | index4;
204
+ }
205
+
206
+ return bytes;
207
+ }