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,649 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureEventsSchema } from '../../schemas/base.js'
3
+ import { Feature } from "../feature.js";
4
+ import { NodeContainer } from "../container.js";
5
+ import { Server, Socket } from "net";
6
+ import { existsSync } from "fs";
7
+
8
+ /**
9
+ * Zod schema for the IpcSocket feature state.
10
+ * Tracks the operational mode of the IPC socket (server or client).
11
+ */
12
+ export const IpcStateSchema = FeatureStateSchema.extend({
13
+ /** The current mode of the IPC socket - either 'server' or 'client' */
14
+ mode: z.enum(['server', 'client']).optional().describe('The current mode of the IPC socket - either server or client'),
15
+ /** The socket path this instance is listening on or connected to */
16
+ socketPath: z.string().optional().describe('The socket path this instance is bound to'),
17
+ })
18
+ export type IpcState = z.infer<typeof IpcStateSchema>
19
+
20
+ export const IpcEventsSchema = FeatureEventsSchema.extend({
21
+ connection: z.tuple([
22
+ z.string().describe('The client ID assigned to the connection'),
23
+ z.any().describe('The connected net.Socket instance'),
24
+ ]).describe('Emitted on the server when a new client connects (clientId, socket)'),
25
+ disconnection: z.tuple([
26
+ z.string().describe('The client ID that disconnected'),
27
+ ]).describe('Emitted on the server when a client disconnects'),
28
+ message: z.tuple([
29
+ z.any().describe('The parsed JSON message object received over the socket'),
30
+ z.string().optional().describe('The client ID of the sender (server mode only)'),
31
+ ]).describe('Emitted when a complete JSON message is received (data, clientId?)'),
32
+ })
33
+
34
+ /** Tracks a pending request awaiting a reply */
35
+ type PendingRequest = {
36
+ resolve: (value: any) => void
37
+ reject: (reason: any) => void
38
+ timer: ReturnType<typeof setTimeout>
39
+ }
40
+
41
+ /** Metadata for a connected client */
42
+ type ClientInfo = {
43
+ socket: Socket
44
+ id: string
45
+ name?: string
46
+ connectedAt: number
47
+ }
48
+
49
+ /**
50
+ * IpcSocket Feature - Inter-Process Communication via Unix Domain Sockets
51
+ *
52
+ * This feature provides robust IPC (Inter-Process Communication) capabilities using Unix domain sockets.
53
+ * It supports both server and client modes, allowing processes to communicate efficiently through
54
+ * file system-based socket connections.
55
+ *
56
+ * **Key Features:**
57
+ * - Hub-and-spoke: one server, many named clients with identity tracking
58
+ * - Targeted messaging: sendTo(clientId), broadcast(msg, excludeId)
59
+ * - Request/reply: ask() + reply() with timeout-based correlation
60
+ * - Auto-reconnect: clients reconnect with exponential backoff
61
+ * - Stale socket detection: probeSocket() before listen()
62
+ * - Clean shutdown: stopServer() removes socket file
63
+ *
64
+ * **Server (Hub):**
65
+ * ```typescript
66
+ * const ipc = container.feature('ipcSocket');
67
+ * await ipc.listen('/tmp/hub.sock', true);
68
+ *
69
+ * ipc.on('connection', (clientId, socket) => {
70
+ * console.log('Client joined:', clientId);
71
+ * });
72
+ *
73
+ * ipc.on('message', (data, clientId) => {
74
+ * console.log(`From ${clientId}:`, data);
75
+ * // Reply to sender, or ask and wait
76
+ * ipc.sendTo(clientId, { ack: true });
77
+ * });
78
+ * ```
79
+ *
80
+ * **Client (Spoke):**
81
+ * ```typescript
82
+ * const ipc = container.feature('ipcSocket');
83
+ * await ipc.connect('/tmp/hub.sock', { reconnect: true, name: 'worker-1' });
84
+ *
85
+ * // Fire and forget
86
+ * await ipc.send({ type: 'status', ready: true });
87
+ *
88
+ * // Request/reply
89
+ * ipc.on('message', (data) => {
90
+ * if (data.requestId) ipc.reply(data.requestId, { result: 42 });
91
+ * });
92
+ * ```
93
+ *
94
+ * @template T - The state type, defaults to IpcState
95
+ * @extends {Feature<T>}
96
+ */
97
+ export class IpcSocket<T extends IpcState = IpcState> extends Feature<T> {
98
+ static { Feature.register(this, 'ipcSocket') }
99
+ /** The shortcut path for accessing this feature */
100
+ static override shortcut = "features.ipcSocket" as const
101
+ static override stateSchema = IpcStateSchema
102
+ static override eventsSchema = IpcEventsSchema
103
+
104
+ /** The Node.js net Server instance (when in server mode) */
105
+ server?: Server;
106
+
107
+ /** Connected clients keyed by client ID (server mode only) */
108
+ protected clients = new Map<string, ClientInfo>();
109
+
110
+ /** Reverse lookup: socket → clientId */
111
+ private _socketToClient = new WeakMap<Socket, string>();
112
+
113
+ /** Per-socket NDJSON read buffers for accumulating partial lines */
114
+ private _buffers = new WeakMap<Socket, string>();
115
+
116
+ /** Pending request/reply correlation map */
117
+ private _pending = new Map<string, PendingRequest>();
118
+
119
+ /** Default timeout for ask() calls in ms */
120
+ requestTimeoutMs = 10000;
121
+
122
+ /** Reconnection config (client mode) */
123
+ private _reconnect = { enabled: false, attempts: 0, maxAttempts: 10, delayMs: 1000, maxDelayMs: 30000, timer: null as ReturnType<typeof setTimeout> | null }
124
+ private _socketPath?: string;
125
+
126
+ /**
127
+ * Attaches the IpcSocket feature to a NodeContainer instance.
128
+ * Registers the feature and creates an auto-enabled instance.
129
+ *
130
+ * @param container - The NodeContainer to attach to
131
+ * @returns The container for method chaining
132
+ */
133
+ static attach(container: NodeContainer & { ipcSocket?: IpcSocket }) {
134
+ container.ipcSocket = container.feature("ipcSocket", { enable: true });
135
+ }
136
+
137
+ /**
138
+ * Checks if the IPC socket is operating in client mode.
139
+ *
140
+ * @returns True if the socket is configured as a client
141
+ */
142
+ get isClient(): boolean {
143
+ return this.state.get('mode') === 'client'
144
+ }
145
+
146
+ /**
147
+ * Checks if the IPC socket is operating in server mode.
148
+ *
149
+ * @returns True if the socket is configured as a server
150
+ */
151
+ get isServer(): boolean {
152
+ return this.state.get('mode') === 'server'
153
+ }
154
+
155
+ /**
156
+ * Returns the number of currently connected clients (server mode).
157
+ */
158
+ get clientCount(): number {
159
+ return this.clients.size
160
+ }
161
+
162
+ /**
163
+ * Returns info about all connected clients (server mode).
164
+ */
165
+ get connectedClients(): Array<{ id: string; name?: string; connectedAt: number }> {
166
+ return Array.from(this.clients.values()).map(({ id, name, connectedAt }) => ({ id, name, connectedAt }))
167
+ }
168
+
169
+ /**
170
+ * Starts the IPC server listening on the specified socket path.
171
+ *
172
+ * This method sets up a Unix domain socket server that can accept multiple client connections.
173
+ * Each connected client is tracked, and the server automatically handles connection lifecycle
174
+ * events. Messages received from clients are JSON-parsed and emitted as 'message' events.
175
+ *
176
+ * **Server Behavior:**
177
+ * - Tracks all connected clients in the sockets Set
178
+ * - Automatically removes clients when they disconnect
179
+ * - JSON-parses incoming messages and emits 'message' events
180
+ * - Emits 'connection' events when clients connect
181
+ * - Prevents starting multiple servers on the same instance
182
+ *
183
+ * **Socket File Management:**
184
+ * - Resolves the socket path relative to the container's working directory
185
+ * - Optionally removes existing socket files to prevent "address in use" errors
186
+ * - Throws error if socket file exists and removeLock is false
187
+ *
188
+ * @param socketPath - The file system path for the Unix domain socket
189
+ * @param removeLock - Whether to remove existing socket file (default: false)
190
+ * @returns Promise resolving to the created Node.js Server instance
191
+ *
192
+ * @throws {Error} When already in client mode, server already running, or socket file exists
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * // Basic server setup
197
+ * const server = await ipc.listen('/tmp/myapp.sock');
198
+ *
199
+ * // With automatic lock removal
200
+ * const server = await ipc.listen('/tmp/myapp.sock', true);
201
+ *
202
+ * // Handle connections and messages
203
+ * ipc.on('connection', (socket) => {
204
+ * console.log('New client connected');
205
+ * });
206
+ *
207
+ * ipc.on('message', (data) => {
208
+ * console.log('Received message:', data);
209
+ * // Echo back to all clients
210
+ * ipc.broadcast({ echo: data });
211
+ * });
212
+ * ```
213
+ */
214
+ async listen(socketPath: string, removeLock = false): Promise<Server> {
215
+ socketPath = this.container.paths.resolve(socketPath)
216
+
217
+ if (existsSync(socketPath)) {
218
+ if (removeLock) {
219
+ const alive = await this.probeSocket(socketPath)
220
+ if (alive) {
221
+ throw new Error(`Socket ${socketPath} is already in use by a live process`)
222
+ }
223
+ await this.container.fs.rm(socketPath)
224
+ } else {
225
+ throw new Error('Lock already exists')
226
+ }
227
+ }
228
+
229
+ if(this.isClient) {
230
+ throw new Error("Cannot listen on a client socket.");
231
+ }
232
+
233
+ this.state.set('mode', 'server')
234
+ this.state.set('socketPath', socketPath)
235
+ this._socketPath = socketPath
236
+
237
+ if (this.server) {
238
+ throw new Error("An IPC server is already running.");
239
+ }
240
+
241
+ this.server = new Server((socket) => {
242
+ const clientId = this.container.utils.uuid()
243
+ const clientInfo: ClientInfo = { socket, id: clientId, connectedAt: Date.now() }
244
+ this.clients.set(clientId, clientInfo)
245
+ this._socketToClient.set(socket, clientId)
246
+ this._buffers.set(socket, '');
247
+
248
+ // Send the client its assigned ID
249
+ socket.write(JSON.stringify({ type: '__ipc:welcome', clientId }) + '\n')
250
+
251
+ socket.on("close", () => {
252
+ this.clients.delete(clientId);
253
+ this.emit('disconnection', clientId)
254
+ });
255
+
256
+ socket.on('data', (chunk) => {
257
+ this._handleChunk(socket, chunk)
258
+ })
259
+
260
+ this.emit('connection', clientId, socket)
261
+ });
262
+
263
+ this.server.listen(socketPath);
264
+
265
+ return this.server;
266
+ }
267
+
268
+ /**
269
+ * Stops the IPC server and cleans up all connections.
270
+ *
271
+ * This method gracefully shuts down the server by:
272
+ * 1. Closing the server listener
273
+ * 2. Destroying all active client connections
274
+ * 3. Clearing the sockets tracking set
275
+ * 4. Resetting the server instance
276
+ *
277
+ * @returns Promise that resolves when the server is fully stopped
278
+ *
279
+ * @throws {Error} When no server is currently running
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * // Graceful shutdown
284
+ * try {
285
+ * await ipc.stopServer();
286
+ * console.log('IPC server stopped successfully');
287
+ * } catch (error) {
288
+ * console.error('Failed to stop server:', error.message);
289
+ * }
290
+ * ```
291
+ */
292
+ stopServer(): Promise<void> {
293
+ return new Promise((resolve, reject) => {
294
+ if (!this.server) {
295
+ reject(new Error("No IPC server is running."));
296
+ return;
297
+ }
298
+
299
+ this.server.close((err) => {
300
+ // Clean up socket file
301
+ if (this._socketPath && existsSync(this._socketPath)) {
302
+ try { this.container.fs.rm(this._socketPath) } catch {}
303
+ }
304
+ if (err) {
305
+ reject(err);
306
+ } else {
307
+ resolve();
308
+ }
309
+ });
310
+
311
+ for (const { socket } of this.clients.values()) {
312
+ socket.destroy()
313
+ }
314
+ this.clients.clear();
315
+ this._pending.forEach(({ timer }) => clearTimeout(timer))
316
+ this._pending.clear()
317
+ this.server = undefined;
318
+ });
319
+ }
320
+
321
+ /** The client connection socket (client mode only) */
322
+ _connection?: Socket
323
+
324
+ /**
325
+ * Gets the current client connection socket.
326
+ *
327
+ * @returns The active Socket connection, or undefined if not connected
328
+ */
329
+ get connection(): Socket | undefined {
330
+ return this._connection
331
+ }
332
+
333
+ /**
334
+ * Broadcasts a message to all connected clients (server mode only).
335
+ *
336
+ * @param message - The message object to broadcast
337
+ * @param exclude - Optional client ID to exclude from broadcast
338
+ * @returns This instance for method chaining
339
+ */
340
+ broadcast(message: any, exclude?: string): this {
341
+ const envelope = JSON.stringify({
342
+ data: message,
343
+ id: this.container.utils.uuid()
344
+ }) + '\n'
345
+
346
+ for (const [clientId, { socket }] of this.clients) {
347
+ if (clientId === exclude) continue
348
+ if (!socket.writable) continue
349
+ socket.write(envelope)
350
+ }
351
+
352
+ return this
353
+ }
354
+
355
+ /**
356
+ * Sends a message to a specific client by ID (server mode only).
357
+ *
358
+ * @param clientId - The target client ID
359
+ * @param message - The message to send
360
+ * @returns True if the message was sent, false if client not found or not writable
361
+ */
362
+ sendTo(clientId: string, message: any): boolean {
363
+ const client = this.clients.get(clientId)
364
+ if (!client || !client.socket.writable) return false
365
+
366
+ client.socket.write(JSON.stringify({
367
+ data: message,
368
+ id: this.container.utils.uuid()
369
+ }) + '\n')
370
+
371
+ return true
372
+ }
373
+
374
+ /**
375
+ * Fire-and-forget: sends a message to the server (client mode only).
376
+ * For server→client, use sendTo() or broadcast().
377
+ *
378
+ * @param message - The message to send
379
+ */
380
+ async send(message: any): Promise<void> {
381
+ if(!this._connection) {
382
+ throw new Error("No connection.")
383
+ }
384
+
385
+ const id = this.container.utils.uuid()
386
+ this._connection.write(JSON.stringify({ id, data: message }) + '\n')
387
+ }
388
+
389
+ /**
390
+ * Sends a message and waits for a correlated reply.
391
+ * Works in both client and server mode.
392
+ *
393
+ * The recipient should call `reply(requestId, response)` to respond.
394
+ *
395
+ * @param message - The message to send
396
+ * @param options - Optional: clientId (server mode target), timeoutMs
397
+ * @returns The reply data
398
+ */
399
+ async ask(message: any, options?: { clientId?: string; timeoutMs?: number }): Promise<any> {
400
+ const requestId = this.container.utils.uuid()
401
+ const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs
402
+
403
+ return new Promise((resolve, reject) => {
404
+ const timer = setTimeout(() => {
405
+ this._pending.delete(requestId)
406
+ reject(new Error(`IPC ask timed out after ${timeoutMs}ms`))
407
+ }, timeoutMs)
408
+
409
+ this._pending.set(requestId, { resolve, reject, timer })
410
+
411
+ const envelope = JSON.stringify({
412
+ id: requestId,
413
+ data: message,
414
+ requestId,
415
+ }) + '\n'
416
+
417
+ if (this.isServer) {
418
+ const clientId = options?.clientId
419
+ if (!clientId) {
420
+ clearTimeout(timer)
421
+ this._pending.delete(requestId)
422
+ reject(new Error('ask() in server mode requires options.clientId'))
423
+ return
424
+ }
425
+ const client = this.clients.get(clientId)
426
+ if (!client || !client.socket.writable) {
427
+ clearTimeout(timer)
428
+ this._pending.delete(requestId)
429
+ reject(new Error(`Client ${clientId} not found or not writable`))
430
+ return
431
+ }
432
+ client.socket.write(envelope)
433
+ } else {
434
+ if (!this._connection) {
435
+ clearTimeout(timer)
436
+ this._pending.delete(requestId)
437
+ reject(new Error('No connection'))
438
+ return
439
+ }
440
+ this._connection.write(envelope)
441
+ }
442
+ })
443
+ }
444
+
445
+ /**
446
+ * Sends a reply to a previous ask() call, correlated by requestId.
447
+ *
448
+ * @param requestId - The requestId from the incoming message
449
+ * @param data - The reply payload
450
+ * @param clientId - Target client (server mode; for client mode, omit)
451
+ */
452
+ reply(requestId: string, data: any, clientId?: string): void {
453
+ const envelope = JSON.stringify({
454
+ id: this.container.utils.uuid(),
455
+ data,
456
+ replyTo: requestId,
457
+ }) + '\n'
458
+
459
+ if (this.isServer && clientId) {
460
+ const client = this.clients.get(clientId)
461
+ if (client?.socket.writable) {
462
+ client.socket.write(envelope)
463
+ }
464
+ } else if (this._connection) {
465
+ this._connection.write(envelope)
466
+ }
467
+ }
468
+
469
+ /** The server-assigned client ID (client mode only) */
470
+ clientId?: string;
471
+
472
+ /**
473
+ * Connects to an IPC server at the specified socket path (client mode).
474
+ *
475
+ * @param socketPath - Path to the server's Unix domain socket
476
+ * @param options - Optional: reconnect (enable auto-reconnect), name (identify this client)
477
+ * @returns The established Socket connection
478
+ */
479
+ async connect(socketPath: string, options?: { reconnect?: boolean; name?: string }): Promise<Socket> {
480
+ if(this.isServer) {
481
+ throw new Error("Cannot connect on a server socket.")
482
+ }
483
+
484
+ if(this._connection) {
485
+ return this._connection
486
+ }
487
+
488
+ this._socketPath = socketPath
489
+ this.state.set('socketPath', socketPath)
490
+
491
+ if (options?.reconnect !== undefined) {
492
+ this._reconnect.enabled = options.reconnect
493
+ }
494
+
495
+ const connection: Socket = await this._doConnect(socketPath)
496
+
497
+ connection.on("close", () => {
498
+ this._connection = undefined
499
+ this.clientId = undefined
500
+ if (this._reconnect.enabled) {
501
+ this._scheduleReconnect()
502
+ }
503
+ })
504
+
505
+ this._buffers.set(connection, '');
506
+ connection.on("data", (chunk) => {
507
+ this._handleChunk(connection, chunk)
508
+ })
509
+
510
+ this._connection = connection
511
+ this._reconnect.attempts = 0
512
+
513
+ // Send identity if a name was provided
514
+ if (options?.name) {
515
+ connection.write(JSON.stringify({
516
+ id: this.container.utils.uuid(),
517
+ data: { type: '__ipc:identify', name: options.name }
518
+ }) + '\n')
519
+ }
520
+
521
+ return connection
522
+ }
523
+
524
+ private _doConnect(socketPath: string): Promise<Socket> {
525
+ return new Promise((resolve, reject) => {
526
+ const socket = new Socket();
527
+ socket.connect(socketPath, () => resolve(socket));
528
+ socket.on("error", (err) => reject(err));
529
+ })
530
+ }
531
+
532
+ private _scheduleReconnect() {
533
+ if (this._reconnect.timer) return
534
+ if (this._reconnect.attempts >= this._reconnect.maxAttempts) {
535
+ this.emit('message', { type: '__ipc:reconnect_failed', attempts: this._reconnect.attempts })
536
+ return
537
+ }
538
+
539
+ const delay = Math.min(
540
+ this._reconnect.delayMs * Math.pow(2, this._reconnect.attempts),
541
+ this._reconnect.maxDelayMs
542
+ )
543
+ this._reconnect.attempts++
544
+
545
+ this._reconnect.timer = setTimeout(async () => {
546
+ this._reconnect.timer = null
547
+ if (!this._socketPath) return
548
+
549
+ try {
550
+ await this.connect(this._socketPath)
551
+ } catch {
552
+ this._scheduleReconnect()
553
+ }
554
+ }, delay)
555
+ }
556
+
557
+ /**
558
+ * Disconnects the client and stops any reconnection attempts.
559
+ */
560
+ disconnect(): void {
561
+ this._reconnect.enabled = false
562
+ if (this._reconnect.timer) {
563
+ clearTimeout(this._reconnect.timer)
564
+ this._reconnect.timer = null
565
+ }
566
+ if (this._connection) {
567
+ this._connection.destroy()
568
+ this._connection = undefined
569
+ }
570
+ this._pending.forEach(({ timer }) => clearTimeout(timer))
571
+ this._pending.clear()
572
+ }
573
+
574
+ /**
575
+ * Probe an existing socket to see if a live listener is behind it.
576
+ * Attempts a quick connect — if it succeeds, someone is listening.
577
+ */
578
+ probeSocket(socketPath: string): Promise<boolean> {
579
+ if (!existsSync(socketPath)) return Promise.resolve(false)
580
+ return new Promise<boolean>((resolve) => {
581
+ const probe = new Socket()
582
+ const timer = setTimeout(() => {
583
+ probe.destroy()
584
+ resolve(false)
585
+ }, 500)
586
+
587
+ probe.once('connect', () => {
588
+ clearTimeout(timer)
589
+ probe.destroy()
590
+ resolve(true)
591
+ })
592
+
593
+ probe.once('error', () => {
594
+ clearTimeout(timer)
595
+ probe.destroy()
596
+ resolve(false)
597
+ })
598
+
599
+ probe.connect(socketPath)
600
+ })
601
+ }
602
+
603
+ private _handleChunk(socket: Socket, chunk: Buffer): void {
604
+ let buffer = (this._buffers.get(socket) || '') + chunk.toString()
605
+ const lines = buffer.split(/\r?\n/)
606
+ this._buffers.set(socket, lines.pop() || '')
607
+
608
+ for (const line of lines) {
609
+ if (!line.trim()) continue
610
+ try {
611
+ const parsed = JSON.parse(line)
612
+
613
+ // Handle protocol messages
614
+ if (parsed.type === '__ipc:welcome' && parsed.clientId) {
615
+ this.clientId = parsed.clientId
616
+ this.state.set('mode', 'client')
617
+ continue
618
+ }
619
+
620
+ if (parsed.data?.type === '__ipc:identify' && this.isServer) {
621
+ const clientId = this._socketToClient.get(socket)
622
+ if (clientId) {
623
+ const client = this.clients.get(clientId)
624
+ if (client) client.name = parsed.data.name
625
+ }
626
+ continue
627
+ }
628
+
629
+ // Handle reply correlation
630
+ const replyTo = parsed.replyTo
631
+ if (replyTo && this._pending.has(replyTo)) {
632
+ const pending = this._pending.get(replyTo)!
633
+ this._pending.delete(replyTo)
634
+ clearTimeout(pending.timer)
635
+ pending.resolve(parsed.data)
636
+ continue
637
+ }
638
+
639
+ // Regular message — include sender clientId in server mode
640
+ const clientId = this._socketToClient.get(socket)
641
+ this.emit('message', parsed.data ?? parsed, clientId)
642
+ } catch {
643
+ // Malformed JSON line — skip
644
+ }
645
+ }
646
+ }
647
+ }
648
+
649
+ export default IpcSocket