luca 1.1.2 → 3.0.0

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 (754) hide show
  1. package/.github/workflows/release.yaml +169 -0
  2. package/AGENTS.md +99 -0
  3. package/CLAUDE.md +115 -0
  4. package/CNAME +1 -0
  5. package/README.md +257 -8
  6. package/RUNME.md +56 -0
  7. package/assistants/codingAssistant/ABOUT.md +5 -0
  8. package/assistants/codingAssistant/CORE.md +28 -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 +2769 -0
  20. package/bunfig.toml +3 -0
  21. package/commands/audit-docs.ts +740 -0
  22. package/commands/build-bootstrap.ts +118 -0
  23. package/commands/build-python-bridge.ts +43 -0
  24. package/commands/build-scaffolds.ts +176 -0
  25. package/commands/generate-api-docs.ts +114 -0
  26. package/commands/inkbot.ts +874 -0
  27. package/commands/release.ts +80 -0
  28. package/commands/try-all-challenges.ts +543 -0
  29. package/commands/try-challenge.ts +100 -0
  30. package/dist/agi/container.server.d.ts +63 -0
  31. package/dist/agi/container.server.d.ts.map +1 -0
  32. package/dist/agi/endpoints/ask.d.ts +20 -0
  33. package/dist/agi/endpoints/ask.d.ts.map +1 -0
  34. package/dist/agi/endpoints/conversations/[id].d.ts +27 -0
  35. package/dist/agi/endpoints/conversations/[id].d.ts.map +1 -0
  36. package/dist/agi/endpoints/conversations.d.ts +18 -0
  37. package/dist/agi/endpoints/conversations.d.ts.map +1 -0
  38. package/dist/agi/endpoints/experts.d.ts +8 -0
  39. package/dist/agi/endpoints/experts.d.ts.map +1 -0
  40. package/dist/agi/feature.d.ts +9 -0
  41. package/dist/agi/feature.d.ts.map +1 -0
  42. package/dist/agi/features/assistant.d.ts +509 -0
  43. package/dist/agi/features/assistant.d.ts.map +1 -0
  44. package/dist/agi/features/assistants-manager.d.ts +236 -0
  45. package/dist/agi/features/assistants-manager.d.ts.map +1 -0
  46. package/dist/agi/features/autonomous-assistant.d.ts +281 -0
  47. package/dist/agi/features/autonomous-assistant.d.ts.map +1 -0
  48. package/dist/agi/features/browser-use.d.ts +479 -0
  49. package/dist/agi/features/browser-use.d.ts.map +1 -0
  50. package/dist/agi/features/claude-code.d.ts +824 -0
  51. package/dist/agi/features/claude-code.d.ts.map +1 -0
  52. package/dist/agi/features/conversation-history.d.ts +245 -0
  53. package/dist/agi/features/conversation-history.d.ts.map +1 -0
  54. package/dist/agi/features/conversation.d.ts +464 -0
  55. package/dist/agi/features/conversation.d.ts.map +1 -0
  56. package/dist/agi/features/docs-reader.d.ts +72 -0
  57. package/dist/agi/features/docs-reader.d.ts.map +1 -0
  58. package/dist/agi/features/file-tools.d.ts +110 -0
  59. package/dist/agi/features/file-tools.d.ts.map +1 -0
  60. package/dist/agi/features/luca-coder.d.ts +323 -0
  61. package/dist/agi/features/luca-coder.d.ts.map +1 -0
  62. package/dist/agi/features/openai-codex.d.ts +381 -0
  63. package/dist/agi/features/openai-codex.d.ts.map +1 -0
  64. package/dist/agi/features/openapi.d.ts +200 -0
  65. package/dist/agi/features/openapi.d.ts.map +1 -0
  66. package/dist/agi/features/skills-library.d.ts +167 -0
  67. package/dist/agi/features/skills-library.d.ts.map +1 -0
  68. package/dist/agi/index.d.ts +5 -0
  69. package/dist/agi/index.d.ts.map +1 -0
  70. package/dist/agi/lib/interceptor-chain.d.ts +44 -0
  71. package/dist/agi/lib/interceptor-chain.d.ts.map +1 -0
  72. package/dist/agi/lib/token-counter.d.ts +13 -0
  73. package/dist/agi/lib/token-counter.d.ts.map +1 -0
  74. package/dist/bootstrap/generated.d.ts +5 -0
  75. package/dist/bootstrap/generated.d.ts.map +1 -0
  76. package/dist/browser.d.ts +12 -0
  77. package/dist/browser.d.ts.map +1 -0
  78. package/dist/bus.d.ts +29 -0
  79. package/dist/bus.d.ts.map +1 -0
  80. package/dist/cli/build-info.d.ts +4 -0
  81. package/dist/cli/build-info.d.ts.map +1 -0
  82. package/dist/cli/cli.d.ts +3 -0
  83. package/dist/cli/cli.d.ts.map +1 -0
  84. package/dist/client.d.ts +60 -0
  85. package/dist/client.d.ts.map +1 -0
  86. package/dist/clients/civitai/index.d.ts +472 -0
  87. package/dist/clients/civitai/index.d.ts.map +1 -0
  88. package/dist/clients/client-template.d.ts +30 -0
  89. package/dist/clients/client-template.d.ts.map +1 -0
  90. package/dist/clients/comfyui/index.d.ts +281 -0
  91. package/dist/clients/comfyui/index.d.ts.map +1 -0
  92. package/dist/clients/elevenlabs/index.d.ts +197 -0
  93. package/dist/clients/elevenlabs/index.d.ts.map +1 -0
  94. package/dist/clients/graph.d.ts +64 -0
  95. package/dist/clients/graph.d.ts.map +1 -0
  96. package/dist/clients/openai/index.d.ts +247 -0
  97. package/dist/clients/openai/index.d.ts.map +1 -0
  98. package/dist/clients/rest.d.ts +92 -0
  99. package/dist/clients/rest.d.ts.map +1 -0
  100. package/dist/clients/supabase/index.d.ts +176 -0
  101. package/dist/clients/supabase/index.d.ts.map +1 -0
  102. package/dist/clients/websocket.d.ts +127 -0
  103. package/dist/clients/websocket.d.ts.map +1 -0
  104. package/dist/command.d.ts +163 -0
  105. package/dist/command.d.ts.map +1 -0
  106. package/dist/commands/bootstrap.d.ts +20 -0
  107. package/dist/commands/bootstrap.d.ts.map +1 -0
  108. package/dist/commands/chat.d.ts +37 -0
  109. package/dist/commands/chat.d.ts.map +1 -0
  110. package/dist/commands/code.d.ts +28 -0
  111. package/dist/commands/code.d.ts.map +1 -0
  112. package/dist/commands/console.d.ts +22 -0
  113. package/dist/commands/console.d.ts.map +1 -0
  114. package/dist/commands/describe.d.ts +50 -0
  115. package/dist/commands/describe.d.ts.map +1 -0
  116. package/dist/commands/eval.d.ts +23 -0
  117. package/dist/commands/eval.d.ts.map +1 -0
  118. package/dist/commands/help.d.ts +25 -0
  119. package/dist/commands/help.d.ts.map +1 -0
  120. package/dist/commands/index.d.ts +18 -0
  121. package/dist/commands/index.d.ts.map +1 -0
  122. package/dist/commands/introspect.d.ts +24 -0
  123. package/dist/commands/introspect.d.ts.map +1 -0
  124. package/dist/commands/mcp.d.ts +35 -0
  125. package/dist/commands/mcp.d.ts.map +1 -0
  126. package/dist/commands/prompt.d.ts +38 -0
  127. package/dist/commands/prompt.d.ts.map +1 -0
  128. package/dist/commands/run.d.ts +24 -0
  129. package/dist/commands/run.d.ts.map +1 -0
  130. package/dist/commands/sandbox-mcp.d.ts +34 -0
  131. package/dist/commands/sandbox-mcp.d.ts.map +1 -0
  132. package/dist/commands/save-api-docs.d.ts +21 -0
  133. package/dist/commands/save-api-docs.d.ts.map +1 -0
  134. package/dist/commands/scaffold.d.ts +24 -0
  135. package/dist/commands/scaffold.d.ts.map +1 -0
  136. package/dist/commands/select.d.ts +22 -0
  137. package/dist/commands/select.d.ts.map +1 -0
  138. package/dist/commands/serve.d.ts +29 -0
  139. package/dist/commands/serve.d.ts.map +1 -0
  140. package/dist/container-describer.d.ts +144 -0
  141. package/dist/container-describer.d.ts.map +1 -0
  142. package/dist/container.d.ts +451 -0
  143. package/dist/container.d.ts.map +1 -0
  144. package/dist/endpoint.d.ts +113 -0
  145. package/dist/endpoint.d.ts.map +1 -0
  146. package/dist/feature.d.ts +47 -0
  147. package/dist/feature.d.ts.map +1 -0
  148. package/dist/graft.d.ts +29 -0
  149. package/dist/graft.d.ts.map +1 -0
  150. package/dist/hash-object.d.ts +8 -0
  151. package/dist/hash-object.d.ts.map +1 -0
  152. package/dist/helper.d.ts +209 -0
  153. package/dist/helper.d.ts.map +1 -0
  154. package/dist/introspection/generated.node.d.ts +44623 -0
  155. package/dist/introspection/generated.node.d.ts.map +1 -0
  156. package/dist/introspection/generated.web.d.ts +1412 -0
  157. package/dist/introspection/generated.web.d.ts.map +1 -0
  158. package/dist/introspection/index.d.ts +156 -0
  159. package/dist/introspection/index.d.ts.map +1 -0
  160. package/dist/introspection/scan.d.ts +147 -0
  161. package/dist/introspection/scan.d.ts.map +1 -0
  162. package/dist/node/container.d.ts +256 -0
  163. package/dist/node/container.d.ts.map +1 -0
  164. package/dist/node/feature.d.ts +9 -0
  165. package/dist/node/feature.d.ts.map +1 -0
  166. package/dist/node/features/container-link.d.ts +213 -0
  167. package/dist/node/features/container-link.d.ts.map +1 -0
  168. package/dist/node/features/content-db.d.ts +354 -0
  169. package/dist/node/features/content-db.d.ts.map +1 -0
  170. package/dist/node/features/disk-cache.d.ts +236 -0
  171. package/dist/node/features/disk-cache.d.ts.map +1 -0
  172. package/dist/node/features/dns.d.ts +511 -0
  173. package/dist/node/features/dns.d.ts.map +1 -0
  174. package/dist/node/features/docker.d.ts +485 -0
  175. package/dist/node/features/docker.d.ts.map +1 -0
  176. package/dist/node/features/downloader.d.ts +73 -0
  177. package/dist/node/features/downloader.d.ts.map +1 -0
  178. package/dist/node/features/figlet-fonts.d.ts +4 -0
  179. package/dist/node/features/figlet-fonts.d.ts.map +1 -0
  180. package/dist/node/features/file-manager.d.ts +177 -0
  181. package/dist/node/features/file-manager.d.ts.map +1 -0
  182. package/dist/node/features/fs.d.ts +635 -0
  183. package/dist/node/features/fs.d.ts.map +1 -0
  184. package/dist/node/features/git.d.ts +329 -0
  185. package/dist/node/features/git.d.ts.map +1 -0
  186. package/dist/node/features/google-auth.d.ts +200 -0
  187. package/dist/node/features/google-auth.d.ts.map +1 -0
  188. package/dist/node/features/google-calendar.d.ts +194 -0
  189. package/dist/node/features/google-calendar.d.ts.map +1 -0
  190. package/dist/node/features/google-docs.d.ts +138 -0
  191. package/dist/node/features/google-docs.d.ts.map +1 -0
  192. package/dist/node/features/google-drive.d.ts +202 -0
  193. package/dist/node/features/google-drive.d.ts.map +1 -0
  194. package/dist/node/features/google-mail.d.ts +221 -0
  195. package/dist/node/features/google-mail.d.ts.map +1 -0
  196. package/dist/node/features/google-sheets.d.ts +157 -0
  197. package/dist/node/features/google-sheets.d.ts.map +1 -0
  198. package/dist/node/features/grep.d.ts +207 -0
  199. package/dist/node/features/grep.d.ts.map +1 -0
  200. package/dist/node/features/helpers.d.ts +236 -0
  201. package/dist/node/features/helpers.d.ts.map +1 -0
  202. package/dist/node/features/ink.d.ts +332 -0
  203. package/dist/node/features/ink.d.ts.map +1 -0
  204. package/dist/node/features/ipc-socket.d.ts +298 -0
  205. package/dist/node/features/ipc-socket.d.ts.map +1 -0
  206. package/dist/node/features/json-tree.d.ts +140 -0
  207. package/dist/node/features/json-tree.d.ts.map +1 -0
  208. package/dist/node/features/networking.d.ts +373 -0
  209. package/dist/node/features/networking.d.ts.map +1 -0
  210. package/dist/node/features/nlp.d.ts +125 -0
  211. package/dist/node/features/nlp.d.ts.map +1 -0
  212. package/dist/node/features/opener.d.ts +93 -0
  213. package/dist/node/features/opener.d.ts.map +1 -0
  214. package/dist/node/features/os.d.ts +168 -0
  215. package/dist/node/features/os.d.ts.map +1 -0
  216. package/dist/node/features/package-finder.d.ts +419 -0
  217. package/dist/node/features/package-finder.d.ts.map +1 -0
  218. package/dist/node/features/postgres.d.ts +173 -0
  219. package/dist/node/features/postgres.d.ts.map +1 -0
  220. package/dist/node/features/proc.d.ts +285 -0
  221. package/dist/node/features/proc.d.ts.map +1 -0
  222. package/dist/node/features/process-manager.d.ts +427 -0
  223. package/dist/node/features/process-manager.d.ts.map +1 -0
  224. package/dist/node/features/python.d.ts +477 -0
  225. package/dist/node/features/python.d.ts.map +1 -0
  226. package/dist/node/features/redis.d.ts +247 -0
  227. package/dist/node/features/redis.d.ts.map +1 -0
  228. package/dist/node/features/repl.d.ts +84 -0
  229. package/dist/node/features/repl.d.ts.map +1 -0
  230. package/dist/node/features/runpod.d.ts +527 -0
  231. package/dist/node/features/runpod.d.ts.map +1 -0
  232. package/dist/node/features/secure-shell.d.ts +145 -0
  233. package/dist/node/features/secure-shell.d.ts.map +1 -0
  234. package/dist/node/features/semantic-search.d.ts +207 -0
  235. package/dist/node/features/semantic-search.d.ts.map +1 -0
  236. package/dist/node/features/sqlite.d.ts +180 -0
  237. package/dist/node/features/sqlite.d.ts.map +1 -0
  238. package/dist/node/features/telegram.d.ts +173 -0
  239. package/dist/node/features/telegram.d.ts.map +1 -0
  240. package/dist/node/features/transpiler.d.ts +51 -0
  241. package/dist/node/features/transpiler.d.ts.map +1 -0
  242. package/dist/node/features/tts.d.ts +108 -0
  243. package/dist/node/features/tts.d.ts.map +1 -0
  244. package/dist/node/features/ui.d.ts +562 -0
  245. package/dist/node/features/ui.d.ts.map +1 -0
  246. package/dist/node/features/vault.d.ts +90 -0
  247. package/dist/node/features/vault.d.ts.map +1 -0
  248. package/dist/node/features/vm.d.ts +285 -0
  249. package/dist/node/features/vm.d.ts.map +1 -0
  250. package/dist/node/features/yaml-tree.d.ts +118 -0
  251. package/dist/node/features/yaml-tree.d.ts.map +1 -0
  252. package/dist/node/features/yaml.d.ts +127 -0
  253. package/dist/node/features/yaml.d.ts.map +1 -0
  254. package/dist/node.d.ts +67 -0
  255. package/dist/node.d.ts.map +1 -0
  256. package/dist/python/generated.d.ts +2 -0
  257. package/dist/python/generated.d.ts.map +1 -0
  258. package/dist/react/index.d.ts +36 -0
  259. package/dist/react/index.d.ts.map +1 -0
  260. package/dist/registry.d.ts +97 -0
  261. package/dist/registry.d.ts.map +1 -0
  262. package/dist/scaffolds/generated.d.ts +13 -0
  263. package/dist/scaffolds/generated.d.ts.map +1 -0
  264. package/dist/scaffolds/template.d.ts +11 -0
  265. package/dist/scaffolds/template.d.ts.map +1 -0
  266. package/dist/schemas/base.d.ts +254 -0
  267. package/dist/schemas/base.d.ts.map +1 -0
  268. package/dist/selector.d.ts +130 -0
  269. package/dist/selector.d.ts.map +1 -0
  270. package/dist/server.d.ts +89 -0
  271. package/dist/server.d.ts.map +1 -0
  272. package/dist/servers/express.d.ts +104 -0
  273. package/dist/servers/express.d.ts.map +1 -0
  274. package/dist/servers/mcp.d.ts +201 -0
  275. package/dist/servers/mcp.d.ts.map +1 -0
  276. package/dist/servers/socket.d.ts +121 -0
  277. package/dist/servers/socket.d.ts.map +1 -0
  278. package/dist/state.d.ts +24 -0
  279. package/dist/state.d.ts.map +1 -0
  280. package/dist/web/clients/socket.d.ts +37 -0
  281. package/dist/web/clients/socket.d.ts.map +1 -0
  282. package/dist/web/container.d.ts +55 -0
  283. package/dist/web/container.d.ts.map +1 -0
  284. package/dist/web/extension.d.ts +4 -0
  285. package/dist/web/extension.d.ts.map +1 -0
  286. package/dist/web/feature.d.ts +8 -0
  287. package/dist/web/feature.d.ts.map +1 -0
  288. package/dist/web/features/asset-loader.d.ts +35 -0
  289. package/dist/web/features/asset-loader.d.ts.map +1 -0
  290. package/dist/web/features/container-link.d.ts +167 -0
  291. package/dist/web/features/container-link.d.ts.map +1 -0
  292. package/dist/web/features/esbuild.d.ts +51 -0
  293. package/dist/web/features/esbuild.d.ts.map +1 -0
  294. package/dist/web/features/helpers.d.ts +140 -0
  295. package/dist/web/features/helpers.d.ts.map +1 -0
  296. package/dist/web/features/network.d.ts +69 -0
  297. package/dist/web/features/network.d.ts.map +1 -0
  298. package/dist/web/features/speech.d.ts +71 -0
  299. package/dist/web/features/speech.d.ts.map +1 -0
  300. package/dist/web/features/vault.d.ts +62 -0
  301. package/dist/web/features/vault.d.ts.map +1 -0
  302. package/dist/web/features/vm.d.ts +48 -0
  303. package/dist/web/features/vm.d.ts.map +1 -0
  304. package/dist/web/features/voice-recognition.d.ts +96 -0
  305. package/dist/web/features/voice-recognition.d.ts.map +1 -0
  306. package/dist/web/shims/isomorphic-vm.d.ts +22 -0
  307. package/dist/web/shims/isomorphic-vm.d.ts.map +1 -0
  308. package/docs/CLI.md +335 -0
  309. package/docs/CNAME +1 -0
  310. package/docs/README.md +60 -0
  311. package/docs/TABLE-OF-CONTENTS.md +183 -0
  312. package/docs/apis/clients/elevenlabs.md +308 -0
  313. package/docs/apis/clients/graph.md +107 -0
  314. package/docs/apis/clients/openai.md +429 -0
  315. package/docs/apis/clients/rest.md +161 -0
  316. package/docs/apis/clients/websocket.md +174 -0
  317. package/docs/apis/features/agi/assistant.md +625 -0
  318. package/docs/apis/features/agi/assistants-manager.md +282 -0
  319. package/docs/apis/features/agi/auto-assistant.md +279 -0
  320. package/docs/apis/features/agi/browser-use.md +802 -0
  321. package/docs/apis/features/agi/claude-code.md +884 -0
  322. package/docs/apis/features/agi/conversation-history.md +364 -0
  323. package/docs/apis/features/agi/conversation.md +548 -0
  324. package/docs/apis/features/agi/docs-reader.md +99 -0
  325. package/docs/apis/features/agi/file-tools.md +163 -0
  326. package/docs/apis/features/agi/luca-coder.md +407 -0
  327. package/docs/apis/features/agi/openai-codex.md +396 -0
  328. package/docs/apis/features/agi/openapi.md +138 -0
  329. package/docs/apis/features/agi/semantic-search.md +387 -0
  330. package/docs/apis/features/agi/skills-library.md +239 -0
  331. package/docs/apis/features/node/container-link.md +192 -0
  332. package/docs/apis/features/node/content-db.md +450 -0
  333. package/docs/apis/features/node/disk-cache.md +379 -0
  334. package/docs/apis/features/node/dns.md +652 -0
  335. package/docs/apis/features/node/docker.md +706 -0
  336. package/docs/apis/features/node/downloader.md +81 -0
  337. package/docs/apis/features/node/esbuild.md +60 -0
  338. package/docs/apis/features/node/file-manager.md +191 -0
  339. package/docs/apis/features/node/fs.md +1217 -0
  340. package/docs/apis/features/node/git.md +371 -0
  341. package/docs/apis/features/node/google-auth.md +193 -0
  342. package/docs/apis/features/node/google-calendar.md +202 -0
  343. package/docs/apis/features/node/google-docs.md +173 -0
  344. package/docs/apis/features/node/google-drive.md +246 -0
  345. package/docs/apis/features/node/google-mail.md +214 -0
  346. package/docs/apis/features/node/google-sheets.md +194 -0
  347. package/docs/apis/features/node/grep.md +292 -0
  348. package/docs/apis/features/node/helpers.md +164 -0
  349. package/docs/apis/features/node/ink.md +334 -0
  350. package/docs/apis/features/node/ipc-socket.md +249 -0
  351. package/docs/apis/features/node/json-tree.md +86 -0
  352. package/docs/apis/features/node/networking.md +316 -0
  353. package/docs/apis/features/node/nlp.md +133 -0
  354. package/docs/apis/features/node/opener.md +97 -0
  355. package/docs/apis/features/node/os.md +146 -0
  356. package/docs/apis/features/node/package-finder.md +392 -0
  357. package/docs/apis/features/node/postgres.md +234 -0
  358. package/docs/apis/features/node/proc.md +399 -0
  359. package/docs/apis/features/node/process-manager.md +305 -0
  360. package/docs/apis/features/node/python.md +604 -0
  361. package/docs/apis/features/node/redis.md +380 -0
  362. package/docs/apis/features/node/repl.md +88 -0
  363. package/docs/apis/features/node/runpod.md +674 -0
  364. package/docs/apis/features/node/secure-shell.md +176 -0
  365. package/docs/apis/features/node/semantic-search.md +408 -0
  366. package/docs/apis/features/node/sqlite.md +233 -0
  367. package/docs/apis/features/node/telegram.md +279 -0
  368. package/docs/apis/features/node/transpiler.md +74 -0
  369. package/docs/apis/features/node/tts.md +133 -0
  370. package/docs/apis/features/node/ui.md +701 -0
  371. package/docs/apis/features/node/vault.md +59 -0
  372. package/docs/apis/features/node/vm.md +75 -0
  373. package/docs/apis/features/node/yaml-tree.md +85 -0
  374. package/docs/apis/features/node/yaml.md +176 -0
  375. package/docs/apis/features/web/asset-loader.md +59 -0
  376. package/docs/apis/features/web/container-link.md +192 -0
  377. package/docs/apis/features/web/esbuild.md +54 -0
  378. package/docs/apis/features/web/helpers.md +164 -0
  379. package/docs/apis/features/web/network.md +44 -0
  380. package/docs/apis/features/web/speech.md +69 -0
  381. package/docs/apis/features/web/vault.md +59 -0
  382. package/docs/apis/features/web/vm.md +75 -0
  383. package/docs/apis/features/web/voice.md +84 -0
  384. package/docs/apis/servers/express.md +171 -0
  385. package/docs/apis/servers/mcp.md +238 -0
  386. package/docs/apis/servers/websocket.md +170 -0
  387. package/docs/bootstrap/CLAUDE.md +101 -0
  388. package/docs/bootstrap/SKILL.md +341 -0
  389. package/docs/bootstrap/templates/about-command.ts +41 -0
  390. package/docs/bootstrap/templates/docs-models.ts +22 -0
  391. package/docs/bootstrap/templates/docs-readme.md +43 -0
  392. package/docs/bootstrap/templates/example-feature.ts +53 -0
  393. package/docs/bootstrap/templates/health-endpoint.ts +15 -0
  394. package/docs/bootstrap/templates/luca-cli.ts +30 -0
  395. package/docs/bootstrap/templates/runme.md +54 -0
  396. package/docs/challenges/caching-proxy.md +16 -0
  397. package/docs/challenges/content-db-round-trip.md +14 -0
  398. package/docs/challenges/custom-command.md +9 -0
  399. package/docs/challenges/file-watcher-pipeline.md +11 -0
  400. package/docs/challenges/grep-audit-report.md +15 -0
  401. package/docs/challenges/multi-feature-dashboard.md +14 -0
  402. package/docs/challenges/process-orchestrator.md +17 -0
  403. package/docs/challenges/rest-api-server-with-client.md +12 -0
  404. package/docs/challenges/script-runner-with-vm.md +11 -0
  405. package/docs/challenges/simple-rest-api.md +15 -0
  406. package/docs/challenges/websocket-serve-and-client.md +11 -0
  407. package/docs/challenges/yaml-config-system.md +14 -0
  408. package/docs/command-system-overhaul.md +94 -0
  409. package/docs/documentation-audit.md +134 -0
  410. package/docs/examples/assistant/CORE.md +18 -0
  411. package/docs/examples/assistant/hooks.ts +3 -0
  412. package/docs/examples/assistant/tools.ts +10 -0
  413. package/docs/examples/assistant-hooks-reference.ts +171 -0
  414. package/docs/examples/assistant-with-process-manager.md +84 -0
  415. package/docs/examples/content-db.md +77 -0
  416. package/docs/examples/disk-cache.md +83 -0
  417. package/docs/examples/docker.md +101 -0
  418. package/docs/examples/downloader.md +70 -0
  419. package/docs/examples/entity.md +124 -0
  420. package/docs/examples/esbuild.md +80 -0
  421. package/docs/examples/feature-as-tool-provider.md +143 -0
  422. package/docs/examples/file-manager.md +82 -0
  423. package/docs/examples/fs.md +83 -0
  424. package/docs/examples/git.md +85 -0
  425. package/docs/examples/google-auth.md +88 -0
  426. package/docs/examples/google-calendar.md +94 -0
  427. package/docs/examples/google-docs.md +82 -0
  428. package/docs/examples/google-drive.md +96 -0
  429. package/docs/examples/google-sheets.md +95 -0
  430. package/docs/examples/grep.md +85 -0
  431. package/docs/examples/ink-blocks.md +75 -0
  432. package/docs/examples/ink-renderer.md +41 -0
  433. package/docs/examples/ink.md +103 -0
  434. package/docs/examples/ipc-socket.md +103 -0
  435. package/docs/examples/json-tree.md +91 -0
  436. package/docs/examples/networking.md +58 -0
  437. package/docs/examples/nlp.md +91 -0
  438. package/docs/examples/opener.md +78 -0
  439. package/docs/examples/os.md +72 -0
  440. package/docs/examples/package-finder.md +89 -0
  441. package/docs/examples/postgres.md +91 -0
  442. package/docs/examples/proc.md +81 -0
  443. package/docs/examples/process-manager.md +79 -0
  444. package/docs/examples/python.md +132 -0
  445. package/docs/examples/repl.md +93 -0
  446. package/docs/examples/runpod.md +119 -0
  447. package/docs/examples/secure-shell.md +92 -0
  448. package/docs/examples/sqlite.md +86 -0
  449. package/docs/examples/structured-output-with-assistants.md +144 -0
  450. package/docs/examples/telegram.md +77 -0
  451. package/docs/examples/tts.md +86 -0
  452. package/docs/examples/ui.md +80 -0
  453. package/docs/examples/vault.md +70 -0
  454. package/docs/examples/vm.md +86 -0
  455. package/docs/examples/websocket-ask-and-reply-example.md +128 -0
  456. package/docs/examples/yaml-tree.md +93 -0
  457. package/docs/examples/yaml.md +104 -0
  458. package/docs/ideas/assistant-factory-pattern.md +142 -0
  459. package/docs/in-memory-fs.md +4 -0
  460. package/docs/introspection-audit.md +49 -0
  461. package/docs/introspection.md +164 -0
  462. package/docs/mcp/readme.md +162 -0
  463. package/docs/models.ts +41 -0
  464. package/docs/philosophy.md +86 -0
  465. package/docs/principles.md +7 -0
  466. package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
  467. package/docs/prompts/check-for-undocumented-features.md +27 -0
  468. package/docs/prompts/mcp-test-easy-command.md +27 -0
  469. package/docs/scaffolds/client.md +149 -0
  470. package/docs/scaffolds/command.md +120 -0
  471. package/docs/scaffolds/endpoint.md +171 -0
  472. package/docs/scaffolds/feature.md +158 -0
  473. package/docs/scaffolds/selector.md +91 -0
  474. package/docs/scaffolds/server.md +196 -0
  475. package/docs/selectors.md +115 -0
  476. package/docs/sessions/custom-command/attempt-log-2.md +195 -0
  477. package/docs/sessions/file-watcher-pipeline/attempt-log-1.md +728 -0
  478. package/docs/sessions/file-watcher-pipeline/attempt-log-2.md +555 -0
  479. package/docs/sessions/grep-audit-report/attempt-log-1.md +289 -0
  480. package/docs/sessions/multi-feature-dashboard/attempt-log-2.md +679 -0
  481. package/docs/sessions/rest-api-server-with-client/attempt-log-1.md +1 -0
  482. package/docs/sessions/rest-api-server-with-client/attempt-log-3.md +920 -0
  483. package/docs/sessions/simple-rest-api/attempt-log-1.md +593 -0
  484. package/docs/sessions/websocket-serve-and-client/attempt-log-2.md +995 -0
  485. package/docs/tutorials/00-bootstrap.md +166 -0
  486. package/docs/tutorials/01-getting-started.md +106 -0
  487. package/docs/tutorials/02-container.md +210 -0
  488. package/docs/tutorials/03-scripts.md +194 -0
  489. package/docs/tutorials/04-features-overview.md +196 -0
  490. package/docs/tutorials/05-state-and-events.md +171 -0
  491. package/docs/tutorials/06-servers.md +157 -0
  492. package/docs/tutorials/07-endpoints.md +198 -0
  493. package/docs/tutorials/08-commands.md +252 -0
  494. package/docs/tutorials/09-clients.md +162 -0
  495. package/docs/tutorials/10-creating-features.md +203 -0
  496. package/docs/tutorials/11-contentbase.md +191 -0
  497. package/docs/tutorials/12-assistants.md +215 -0
  498. package/docs/tutorials/13-introspection.md +157 -0
  499. package/docs/tutorials/14-type-system.md +174 -0
  500. package/docs/tutorials/15-project-patterns.md +222 -0
  501. package/docs/tutorials/16-google-features.md +534 -0
  502. package/docs/tutorials/17-tui-blocks.md +530 -0
  503. package/docs/tutorials/18-semantic-search.md +334 -0
  504. package/docs/tutorials/19-python-sessions.md +401 -0
  505. package/docs/tutorials/20-browser-esm.md +234 -0
  506. package/index.html +1430 -0
  507. package/index.ts +1 -0
  508. package/install.sh +84 -0
  509. package/luca.cli.ts +16 -0
  510. package/luca.console.ts +9 -0
  511. package/main.py +6 -0
  512. package/package.json +219 -66
  513. package/public/index.html +1430 -0
  514. package/public/slides-ai-native.html +902 -0
  515. package/public/slides-intro.html +974 -0
  516. package/pyproject.toml +7 -0
  517. package/scripts/build-web.ts +28 -0
  518. package/scripts/examples/ask-luca-expert.ts +42 -0
  519. package/scripts/examples/assistant-questions.ts +12 -0
  520. package/scripts/examples/excalidraw-expert.ts +75 -0
  521. package/scripts/examples/expert-chat.ts +0 -0
  522. package/scripts/examples/file-manager.ts +14 -0
  523. package/scripts/examples/ideas.ts +12 -0
  524. package/scripts/examples/interactive-chat.ts +20 -0
  525. package/scripts/examples/openai-tool-calls.ts +113 -0
  526. package/scripts/examples/opening-a-web-browser.ts +5 -0
  527. package/scripts/examples/telegram-bot.ts +79 -0
  528. package/scripts/examples/using-assistant-with-mcp.ts +555 -0
  529. package/scripts/examples/using-claude-code.ts +10 -0
  530. package/scripts/examples/using-contentdb.ts +35 -0
  531. package/scripts/examples/using-conversations.ts +35 -0
  532. package/scripts/examples/using-disk-cache.ts +10 -0
  533. package/scripts/examples/using-docker-shell.ts +75 -0
  534. package/scripts/examples/using-elevenlabs.ts +25 -0
  535. package/scripts/examples/using-google-calendar.ts +57 -0
  536. package/scripts/examples/using-google-docs.ts +74 -0
  537. package/scripts/examples/using-google-drive.ts +74 -0
  538. package/scripts/examples/using-google-sheets.ts +89 -0
  539. package/scripts/examples/using-nlp.ts +55 -0
  540. package/scripts/examples/using-ollama.ts +11 -0
  541. package/scripts/examples/using-postgres.ts +55 -0
  542. package/scripts/examples/using-runpod.ts +32 -0
  543. package/scripts/examples/using-tts.ts +40 -0
  544. package/scripts/scaffold.ts +391 -0
  545. package/scripts/scratch.ts +15 -0
  546. package/scripts/stamp-build.sh +12 -0
  547. package/scripts/test-assistant-hooks.ts +13 -0
  548. package/scripts/test-docs-reader.ts +10 -0
  549. package/scripts/test-linux-binary.sh +80 -0
  550. package/scripts/update-introspection-data.ts +58 -0
  551. package/src/agi/README.md +14 -0
  552. package/src/agi/container.server.ts +152 -0
  553. package/src/agi/endpoints/ask.ts +60 -0
  554. package/src/agi/endpoints/conversations/[id].ts +45 -0
  555. package/src/agi/endpoints/conversations.ts +31 -0
  556. package/src/agi/endpoints/experts.ts +37 -0
  557. package/src/agi/feature.ts +13 -0
  558. package/src/agi/features/agent-memory.ts +694 -0
  559. package/src/agi/features/assistant.ts +1624 -0
  560. package/src/agi/features/assistants-manager.ts +418 -0
  561. package/src/agi/features/autonomous-assistant.ts +431 -0
  562. package/src/agi/features/browser-use.ts +653 -0
  563. package/src/agi/features/claude-code.ts +1538 -0
  564. package/src/agi/features/coding-tools.ts +175 -0
  565. package/src/agi/features/conversation-history.ts +495 -0
  566. package/src/agi/features/conversation.ts +1323 -0
  567. package/src/agi/features/docs-reader.ts +167 -0
  568. package/src/agi/features/file-tools.ts +293 -0
  569. package/src/agi/features/luca-coder.ts +639 -0
  570. package/src/agi/features/openai-codex.ts +651 -0
  571. package/src/agi/features/openapi.ts +445 -0
  572. package/src/agi/features/skills-library.ts +478 -0
  573. package/src/agi/index.ts +6 -0
  574. package/src/agi/lib/interceptor-chain.ts +89 -0
  575. package/src/agi/lib/token-counter.ts +122 -0
  576. package/src/bootstrap/generated.ts +9792 -0
  577. package/src/browser.ts +25 -0
  578. package/src/bus.ts +122 -0
  579. package/src/cli/build-info.ts +4 -0
  580. package/src/cli/cli.ts +355 -0
  581. package/src/client.ts +170 -0
  582. package/src/clients/civitai/index.ts +537 -0
  583. package/src/clients/client-template.ts +41 -0
  584. package/src/clients/comfyui/index.ts +604 -0
  585. package/src/clients/elevenlabs/index.ts +317 -0
  586. package/src/clients/graph.ts +87 -0
  587. package/src/clients/openai/index.ts +456 -0
  588. package/src/clients/rest.ts +207 -0
  589. package/src/clients/supabase/index.ts +357 -0
  590. package/src/clients/voicebox/index.ts +300 -0
  591. package/src/clients/websocket.ts +251 -0
  592. package/src/command.ts +505 -0
  593. package/src/commands/bootstrap.ts +244 -0
  594. package/src/commands/chat.ts +308 -0
  595. package/src/commands/code.ts +371 -0
  596. package/src/commands/console.ts +189 -0
  597. package/src/commands/describe.ts +243 -0
  598. package/src/commands/eval.ts +121 -0
  599. package/src/commands/help.ts +240 -0
  600. package/src/commands/index.ts +19 -0
  601. package/src/commands/introspect.ts +218 -0
  602. package/src/commands/mcp.ts +64 -0
  603. package/src/commands/prompt.ts +982 -0
  604. package/src/commands/run.ts +278 -0
  605. package/src/commands/sandbox-mcp.ts +343 -0
  606. package/src/commands/save-api-docs.ts +51 -0
  607. package/src/commands/scaffold.ts +225 -0
  608. package/src/commands/select.ts +99 -0
  609. package/src/commands/serve.ts +208 -0
  610. package/src/container-describer.ts +1084 -0
  611. package/src/container.ts +1186 -0
  612. package/src/endpoint.ts +365 -0
  613. package/src/entity.ts +173 -0
  614. package/src/feature.ts +118 -0
  615. package/src/graft.ts +181 -0
  616. package/src/hash-object.ts +97 -0
  617. package/src/helper.ts +849 -0
  618. package/src/introspection/generated.agi.ts +40208 -0
  619. package/src/introspection/generated.node.ts +28686 -0
  620. package/src/introspection/generated.web.ts +2251 -0
  621. package/src/introspection/index.ts +296 -0
  622. package/src/introspection/scan.ts +1131 -0
  623. package/src/node/container.ts +409 -0
  624. package/src/node/feature.ts +13 -0
  625. package/src/node/features/container-link.ts +559 -0
  626. package/src/node/features/content-db.ts +812 -0
  627. package/src/node/features/disk-cache.ts +388 -0
  628. package/src/node/features/dns.ts +669 -0
  629. package/src/node/features/docker.ts +921 -0
  630. package/src/node/features/downloader.ts +79 -0
  631. package/src/node/features/figlet-fonts.ts +600 -0
  632. package/src/node/features/file-manager.ts +535 -0
  633. package/src/node/features/fs.ts +1050 -0
  634. package/src/node/features/git.ts +592 -0
  635. package/src/node/features/google-auth.ts +504 -0
  636. package/src/node/features/google-calendar.ts +306 -0
  637. package/src/node/features/google-docs.ts +412 -0
  638. package/src/node/features/google-drive.ts +346 -0
  639. package/src/node/features/google-mail.ts +540 -0
  640. package/src/node/features/google-sheets.ts +286 -0
  641. package/src/node/features/grep.ts +427 -0
  642. package/src/node/features/helpers.ts +735 -0
  643. package/src/node/features/ink.ts +490 -0
  644. package/src/node/features/ipc-socket.ts +649 -0
  645. package/src/node/features/json-tree.ts +170 -0
  646. package/src/node/features/networking.ts +961 -0
  647. package/src/node/features/nlp.ts +212 -0
  648. package/src/node/features/opener.ts +180 -0
  649. package/src/node/features/os.ts +403 -0
  650. package/src/node/features/package-finder.ts +540 -0
  651. package/src/node/features/postgres.ts +289 -0
  652. package/src/node/features/proc.ts +503 -0
  653. package/src/node/features/process-manager.ts +844 -0
  654. package/src/node/features/python.ts +906 -0
  655. package/src/node/features/redis.ts +446 -0
  656. package/src/node/features/repl.ts +212 -0
  657. package/src/node/features/runpod.ts +811 -0
  658. package/src/node/features/secure-shell.ts +267 -0
  659. package/src/node/features/semantic-search.ts +935 -0
  660. package/src/node/features/sqlite.ts +289 -0
  661. package/src/node/features/telegram.ts +343 -0
  662. package/src/node/features/transpiler.ts +161 -0
  663. package/src/node/features/tts.ts +185 -0
  664. package/src/node/features/ui.ts +786 -0
  665. package/src/node/features/vault.ts +153 -0
  666. package/src/node/features/vm.ts +462 -0
  667. package/src/node/features/yaml-tree.ts +148 -0
  668. package/src/node/features/yaml.ts +133 -0
  669. package/src/node.ts +76 -0
  670. package/src/python/bridge.py +220 -0
  671. package/src/python/generated.ts +227 -0
  672. package/src/react/index.ts +175 -0
  673. package/src/registry.ts +210 -0
  674. package/src/scaffolds/generated.ts +1815 -0
  675. package/src/scaffolds/template.ts +46 -0
  676. package/src/schemas/base.ts +296 -0
  677. package/src/selector.ts +352 -0
  678. package/src/server.ts +229 -0
  679. package/src/servers/express.ts +283 -0
  680. package/src/servers/mcp.ts +802 -0
  681. package/src/servers/socket.ts +258 -0
  682. package/src/state.ts +101 -0
  683. package/src/web/clients/socket.ts +99 -0
  684. package/src/web/container.ts +75 -0
  685. package/src/web/extension.ts +30 -0
  686. package/src/web/feature.ts +12 -0
  687. package/src/web/features/asset-loader.ts +72 -0
  688. package/src/web/features/container-link.ts +382 -0
  689. package/src/web/features/esbuild.ts +93 -0
  690. package/src/web/features/helpers.ts +269 -0
  691. package/src/web/features/network.ts +85 -0
  692. package/src/web/features/speech.ts +104 -0
  693. package/src/web/features/vault.ts +207 -0
  694. package/src/web/features/vm.ts +85 -0
  695. package/src/web/features/voice-recognition.ts +161 -0
  696. package/src/web/shims/isomorphic-vm.ts +149 -0
  697. package/test/assistant-hooks.test.ts +306 -0
  698. package/test/assistant.test.ts +81 -0
  699. package/test/bus.test.ts +134 -0
  700. package/test/clients-servers.test.ts +217 -0
  701. package/test/command.test.ts +267 -0
  702. package/test/container-link.test.ts +274 -0
  703. package/test/conversation.test.ts +220 -0
  704. package/test/features.test.ts +160 -0
  705. package/test/fork-and-research.test.ts +450 -0
  706. package/test/integration.test.ts +787 -0
  707. package/test/interceptor-chain.test.ts +61 -0
  708. package/test/node-container.test.ts +121 -0
  709. package/test/python-session.test.ts +105 -0
  710. package/test/rate-limit.test.ts +272 -0
  711. package/test/semantic-search.test.ts +550 -0
  712. package/test/state.test.ts +121 -0
  713. package/test/vm-context.test.ts +146 -0
  714. package/test/vm-loadmodule.test.ts +213 -0
  715. package/test/websocket-ask.test.ts +101 -0
  716. package/test-integration/assistant.test.ts +138 -0
  717. package/test-integration/assistants-manager.test.ts +113 -0
  718. package/test-integration/claude-code.test.ts +98 -0
  719. package/test-integration/conversation-history.test.ts +205 -0
  720. package/test-integration/conversation.test.ts +137 -0
  721. package/test-integration/elevenlabs.test.ts +55 -0
  722. package/test-integration/google-services.test.ts +80 -0
  723. package/test-integration/helpers.ts +89 -0
  724. package/test-integration/memory.test.ts +204 -0
  725. package/test-integration/openai-codex.test.ts +93 -0
  726. package/test-integration/runpod.test.ts +58 -0
  727. package/test-integration/server-endpoints.test.ts +97 -0
  728. package/test-integration/telegram.test.ts +46 -0
  729. package/tsconfig.build.json +12 -0
  730. package/tsconfig.json +58 -0
  731. package/uv.lock +8 -0
  732. package/LICENSE +0 -21
  733. package/dist/cli/index.d.ts +0 -2
  734. package/dist/cli/index.js +0 -5
  735. package/dist/cli/run.d.ts +0 -12
  736. package/dist/cli/run.js +0 -42
  737. package/dist/config/consts.d.ts +0 -2
  738. package/dist/config/consts.js +0 -29
  739. package/dist/config/default.d.ts +0 -8
  740. package/dist/config/default.js +0 -15
  741. package/dist/config/initConfig.d.ts +0 -1
  742. package/dist/config/initConfig.js +0 -52
  743. package/dist/config/openConfig.d.ts +0 -2
  744. package/dist/config/openConfig.js +0 -24
  745. package/dist/config/runConfig.d.ts +0 -3
  746. package/dist/config/runConfig.js +0 -117
  747. package/dist/config/types.d.ts +0 -13
  748. package/dist/config/types.js +0 -2
  749. package/dist/index.d.ts +0 -1
  750. package/dist/index.js +0 -5
  751. package/dist/utils/common.d.ts +0 -2
  752. package/dist/utils/common.js +0 -52
  753. package/dist/utils/index.d.ts +0 -1
  754. package/dist/utils/index.js +0 -17
@@ -0,0 +1,735 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
3
+ import { Feature } from '../feature.js'
4
+ import { Feature as UniversalFeature } from '../../feature.js'
5
+ import { Client, clients } from '../../client.js'
6
+ import { RestClient } from '../../clients/rest.js'
7
+ import { GraphClient } from '../../clients/graph.js'
8
+ import { WebSocketClient } from '../../clients/websocket.js'
9
+ import { Server, servers } from '../../server.js'
10
+ import { ExpressServer } from '../../servers/express.js'
11
+ import { WebsocketServer } from '../../servers/socket.js'
12
+ import { Command, commands } from '../../command.js'
13
+ import { graftModule, isNativeHelperClass } from '../../graft.js'
14
+ import { endpoints } from '../../endpoint.js'
15
+ import { Selector, selectors } from '../../selector.js'
16
+ import type { Registry } from '../../registry.js'
17
+ import type { FileManager } from './file-manager.js'
18
+ import type { VM } from './vm.js'
19
+ import { resolve, parse } from 'path'
20
+ import { existsSync } from 'fs'
21
+
22
+ export const HelpersStateSchema = FeatureStateSchema.extend({
23
+ discovered: z.record(z.string(), z.boolean()).default({}).describe('Which registry types have been discovered'),
24
+ registered: z.array(z.string()).default([]).describe('Names of project-level helpers that were discovered (type.name)'),
25
+ })
26
+
27
+ export type HelpersState = z.infer<typeof HelpersStateSchema>
28
+
29
+ export const HelpersOptionsSchema = FeatureOptionsSchema.extend({
30
+ rootDir: z.string().optional().describe('Root directory to scan for helper folders. Defaults to container.cwd'),
31
+ })
32
+
33
+ export type HelpersOptions = z.infer<typeof HelpersOptionsSchema>
34
+
35
+ export const HelpersEventsSchema = FeatureEventsSchema.extend({
36
+ discovered: z.tuple([
37
+ z.string().describe('Registry type that was discovered'),
38
+ z.array(z.string()).describe('Names of newly registered helpers'),
39
+ ]).describe('Emitted after a registry type has been discovered'),
40
+ registered: z.tuple([
41
+ z.string().describe('Registry type'),
42
+ z.string().describe('Helper name'),
43
+ z.any().describe('The helper class or module'),
44
+ ]).describe('Emitted when a single helper is registered'),
45
+ })
46
+
47
+ type RegistryType = 'features' | 'clients' | 'servers' | 'commands' | 'endpoints' | 'selectors'
48
+
49
+ const CLASS_BASED: RegistryType[] = ['features', 'clients', 'servers']
50
+
51
+ /**
52
+ * The Helpers feature is a unified gateway for discovering and registering
53
+ * project-level helpers from conventional folder locations.
54
+ *
55
+ * It scans known folder names (features/, clients/, servers/, commands/, endpoints/, selectors/)
56
+ * and handles registration differently based on the helper type:
57
+ *
58
+ * - Class-based (features, clients, servers): Dynamic import, validate subclass, register
59
+ * - Config-based (commands, endpoints, selectors): Delegate to existing discovery mechanisms
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const helpers = container.feature('helpers', { enable: true })
64
+ *
65
+ * // Discover all helper types
66
+ * await helpers.discoverAll()
67
+ *
68
+ * // Discover a specific type
69
+ * await helpers.discover('features')
70
+ *
71
+ * // Unified view of all available helpers
72
+ * console.log(helpers.available)
73
+ * ```
74
+ */
75
+ export class Helpers extends Feature<HelpersState, HelpersOptions> {
76
+ static override shortcut = 'features.helpers' as const
77
+ static override description = 'Unified gateway for discovering and registering project-level helpers'
78
+ static override stateSchema = HelpersStateSchema
79
+ static override optionsSchema = HelpersOptionsSchema
80
+ static override eventsSchema = HelpersEventsSchema
81
+ static { Feature.register(this, 'helpers') }
82
+
83
+ /** In-flight or completed discovery promises, keyed by registry type */
84
+ private _discoveryPromises: Map<string, Promise<string[]>> = new Map()
85
+ /** Cached results from completed discoveries */
86
+ private _discoveryResults: Map<string, string[]> = new Map()
87
+ /** In-flight or completed discoverAll promise */
88
+ private _discoverAllPromise: Promise<Record<string, string[]>> | null = null
89
+
90
+ /**
91
+ * Returns a mapping from registry type name to its registry singleton, base class, and conventional folder candidates.
92
+ */
93
+ private get registryMap(): Record<RegistryType, { registry: Registry<any>, baseClass: any, folders: string[] }> {
94
+ return {
95
+ features: { registry: this.container.features as any, baseClass: UniversalFeature, folders: ['features'] },
96
+ clients: { registry: clients, baseClass: Client, folders: ['clients'] },
97
+ servers: { registry: servers, baseClass: Server, folders: ['servers'] },
98
+ commands: { registry: commands, baseClass: null, folders: ['commands'] },
99
+ endpoints: { registry: endpoints, baseClass: null, folders: ['endpoints'] },
100
+ selectors: { registry: selectors, baseClass: null, folders: ['selectors'] },
101
+ }
102
+ }
103
+
104
+ /** The root directory to scan for helper folders. */
105
+ get rootDir(): string {
106
+ return this.options.rootDir || this.container.cwd
107
+ }
108
+
109
+ /**
110
+ * Whether to use native `import()` for loading project helpers.
111
+ * True only if `@soederpop/luca` is actually resolvable in `node_modules`.
112
+ * Warns when `node_modules` exists but the package is missing.
113
+ */
114
+ get useNativeImport(): boolean {
115
+ const hasNodeModules = existsSync(resolve(this.rootDir, 'node_modules'))
116
+ const hasLuca = hasNodeModules && existsSync(resolve(this.rootDir, 'node_modules', '@soederpop', 'luca'))
117
+
118
+ // VM bundling handles missing @soederpop/luca gracefully — no warning needed
119
+
120
+ return hasLuca
121
+ }
122
+
123
+
124
+ /** Track whether we've seeded the VM with virtual modules */
125
+ private _vmSeeded = false
126
+
127
+ /**
128
+ * Seeds the VM feature with virtual modules so that project-level files
129
+ * can `import` / `require('@soederpop/luca')`, `zod`, etc. without
130
+ * needing them in `node_modules`.
131
+ *
132
+ * Called automatically when `useNativeImport` is false.
133
+ * Can also be called externally (e.g. from the CLI) to pre-seed before discovery.
134
+ */
135
+ seedVirtualModules(): void {
136
+ if (this._vmSeeded) return
137
+ this._vmSeeded = true
138
+
139
+ const vm = this.container.feature('vm') as unknown as VM
140
+
141
+ // Provide the full @soederpop/luca barrel — everything node.ts exports
142
+ // We build the exports object from the already-loaded modules in memory
143
+ const lucaExports: Record<string, any> = {
144
+ // Core classes
145
+ Feature: UniversalFeature,
146
+ Container: this.container.constructor,
147
+ Helper: Object.getPrototypeOf(UniversalFeature.prototype).constructor,
148
+ Client,
149
+ Server,
150
+ Command,
151
+ Registry: Object.getPrototypeOf(this.container.features).constructor,
152
+
153
+ // Utilities
154
+ graftModule,
155
+ isNativeHelperClass,
156
+
157
+ // Registries
158
+ features: this.container.features,
159
+ clients,
160
+ servers,
161
+ commands,
162
+ endpoints,
163
+ selectors,
164
+
165
+ // Registry classes
166
+ ClientsRegistry: clients.constructor,
167
+ CommandsRegistry: commands.constructor,
168
+ EndpointsRegistry: endpoints.constructor,
169
+ ServersRegistry: servers.constructor,
170
+ SelectorsRegistry: selectors.constructor,
171
+ FeaturesRegistry: this.container.features.constructor,
172
+
173
+ // Helper subclasses
174
+ Selector,
175
+ RestClient,
176
+ GraphClient,
177
+ WebSocketClient,
178
+ ExpressServer,
179
+ WebsocketServer,
180
+
181
+ // The singleton container
182
+ default: this.container,
183
+
184
+ // Convenient feature instances
185
+ fs: this.container.feature('fs'),
186
+ ui: this.container.feature('ui'),
187
+ vm,
188
+ proc: this.container.feature('proc'),
189
+
190
+ // Zod re-export
191
+ z,
192
+ }
193
+
194
+ // Schemas
195
+ const schemasModule: Record<string, any> = { CommandOptionsSchema: commands.baseClass?.optionsSchema || z.object({}) }
196
+ try {
197
+ // Pull all base schemas from the already-loaded schemas/base module
198
+ const baseSchemas = require('../../schemas/base.js')
199
+ Object.assign(lucaExports, baseSchemas)
200
+ Object.assign(schemasModule, baseSchemas)
201
+ } catch {
202
+ // Fallback: provide the essentials
203
+ lucaExports.FeatureStateSchema = FeatureStateSchema
204
+ lucaExports.FeatureOptionsSchema = FeatureOptionsSchema
205
+ lucaExports.FeatureEventsSchema = FeatureEventsSchema
206
+ schemasModule.FeatureStateSchema = FeatureStateSchema
207
+ schemasModule.FeatureOptionsSchema = FeatureOptionsSchema
208
+ schemasModule.FeatureEventsSchema = FeatureEventsSchema
209
+ }
210
+
211
+ vm.defineModule('@soederpop/luca', lucaExports)
212
+ vm.defineModule('@soederpop/luca/schemas', schemasModule)
213
+ vm.defineModule('@soederpop/luca/node', lucaExports)
214
+
215
+ // Deep import paths AIs and developers might reach for
216
+ vm.defineModule('@soederpop/luca/client', { Client, ClientsRegistry: clients.constructor, default: Client })
217
+ vm.defineModule('@soederpop/luca/server', { Server, ServersRegistry: servers.constructor, default: Server })
218
+ vm.defineModule('@soederpop/luca/clients/rest', { RestClient, default: RestClient })
219
+ vm.defineModule('@soederpop/luca/clients/graph', { GraphClient, default: GraphClient })
220
+ vm.defineModule('@soederpop/luca/clients/websocket', { WebSocketClient, default: WebSocketClient })
221
+ vm.defineModule('@soederpop/luca/servers/express', { ExpressServer, default: ExpressServer })
222
+ vm.defineModule('@soederpop/luca/servers/socket', { WebsocketServer, default: WebsocketServer })
223
+
224
+ vm.defineModule('zod', { z, default: { z } })
225
+ }
226
+
227
+ /**
228
+ * Returns a unified view of all available helpers across all registries.
229
+ * Each key is a registry type, each value is the list of helper names in that registry.
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * container.helpers.available
234
+ * // { features: ['fs', 'git', ...], clients: ['rest', 'websocket'], ... }
235
+ * ```
236
+ */
237
+ get available(): Record<string, string[]> {
238
+ const result: Record<string, string[]> = {}
239
+ for (const [type, { registry }] of Object.entries(this.registryMap)) {
240
+ result[type] = registry.available
241
+ }
242
+ return result
243
+ }
244
+
245
+ /**
246
+ * Ensures the fileManager feature is started before using it for discovery.
247
+ *
248
+ * @returns The started fileManager instance
249
+ */
250
+ private async ensureFileManager(): Promise<FileManager> {
251
+ const fm = this.container.feature('fileManager', { enable: true }) as unknown as FileManager
252
+ if (!fm.isStarted) {
253
+ await fm.start()
254
+ }
255
+ return fm
256
+ }
257
+
258
+ /**
259
+ * Resolves which conventional folder path exists for a given registry type.
260
+ * Tries each candidate folder in order and returns the first one that exists.
261
+ *
262
+ * @param type - The registry type to resolve the folder for
263
+ * @returns Absolute path to the folder, or null if none exist
264
+ */
265
+ private resolveFolderPath(type: RegistryType): string | null {
266
+ const { folders } = this.registryMap[type]
267
+ const { fs } = this.container
268
+
269
+ for (const candidate of folders) {
270
+ const dir = resolve(this.rootDir, candidate)
271
+ if (fs.exists(dir)) {
272
+ return dir
273
+ }
274
+ }
275
+
276
+ return null
277
+ }
278
+
279
+ /**
280
+ * Discover and register project-level helpers of the given type.
281
+ *
282
+ * Idempotent: the first caller triggers the actual scan. Subsequent callers
283
+ * receive the cached results. If discovery is in-flight, callers await the
284
+ * same promise — no duplicate work.
285
+ *
286
+ * @param type - Which type of helpers to discover
287
+ * @param options - Optional overrides
288
+ * @param options.directory - Override the directory to scan
289
+ * @returns Names of helpers that were discovered and registered
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * const names = await container.helpers.discover('features')
294
+ * console.log(names) // ['myCustomFeature']
295
+ * ```
296
+ */
297
+ async discover(type: RegistryType, options: { directory?: string } = {}): Promise<string[]> {
298
+ // Key by type + resolved directory so that different directories
299
+ // (e.g. project commands/ vs ~/.luca/commands/) are discovered independently
300
+ // while concurrent calls to the same directory coalesce on one promise.
301
+ const dir = options.directory || this.resolveFolderPath(type)
302
+ const cacheKey = dir ? `${type}:${dir}` : type
303
+
304
+ // Return cached results if already completed
305
+ if (this._discoveryResults.has(cacheKey)) {
306
+ return this._discoveryResults.get(cacheKey)!
307
+ }
308
+
309
+ // If in-flight, await the same promise
310
+ if (this._discoveryPromises.has(cacheKey)) {
311
+ return this._discoveryPromises.get(cacheKey)!
312
+ }
313
+
314
+ // First caller — start the work and store the promise
315
+ const promise = this._doDiscover(type, { directory: dir || undefined })
316
+ this._discoveryPromises.set(cacheKey, promise)
317
+
318
+ const names = await promise
319
+
320
+ // Cache the final results
321
+ this._discoveryResults.set(cacheKey, names)
322
+
323
+ return names
324
+ }
325
+
326
+ /** Internal: performs the actual discovery work for a single type. */
327
+ private async _doDiscover(type: RegistryType, options: { directory?: string } = {}): Promise<string[]> {
328
+ const dir = options.directory || this.resolveFolderPath(type)
329
+
330
+ if (!dir) {
331
+ return []
332
+ }
333
+
334
+ let names: string[]
335
+
336
+ if (CLASS_BASED.includes(type)) {
337
+ names = await this.discoverClassBased(type, dir)
338
+ } else {
339
+ names = await this.discoverConfigBased(type, dir)
340
+ }
341
+
342
+ // Update state for observability
343
+ const discovered = this.state.get('discovered') || {}
344
+ this.state.set('discovered', { ...discovered, [type]: true })
345
+
346
+ const existing = this.state.get('registered') || []
347
+ this.state.set('registered', [...existing, ...names.map(n => `${type}.${n}`)])
348
+
349
+ this.emit('discovered' as any, type, names)
350
+
351
+ return names
352
+ }
353
+
354
+ /**
355
+ * Discover all helper types from their conventional folder locations.
356
+ *
357
+ * Idempotent: safe to call from multiple places (luca.cli.ts, commands, etc.).
358
+ * The first caller triggers discovery; all others receive the same results.
359
+ *
360
+ * @returns Map of registry type to discovered helper names
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * const results = await container.helpers.discoverAll()
365
+ * // { features: ['myFeature'], clients: [], servers: [], commands: ['deploy'], endpoints: [] }
366
+ * ```
367
+ */
368
+ async discoverAll(): Promise<Record<string, string[]>> {
369
+ if (this._discoverAllPromise) {
370
+ return this._discoverAllPromise
371
+ }
372
+
373
+ this._discoverAllPromise = this._doDiscoverAll()
374
+ return this._discoverAllPromise
375
+ }
376
+
377
+ /** Internal: performs the actual discoverAll work. */
378
+ private async _doDiscoverAll(): Promise<Record<string, string[]>> {
379
+ const results: Record<string, string[]> = {}
380
+
381
+ for (const type of ['features', 'clients', 'servers', 'commands', 'endpoints', 'selectors'] as RegistryType[]) {
382
+ results[type] = await this.discover(type)
383
+ }
384
+
385
+ return results
386
+ }
387
+
388
+ /**
389
+ * Look up a helper class by type and name.
390
+ *
391
+ * @param type - The registry type (features, clients, servers, commands, endpoints)
392
+ * @param name - The helper name within that registry
393
+ * @returns The helper constructor
394
+ *
395
+ * @example
396
+ * ```typescript
397
+ * const FsClass = container.helpers.lookup('features', 'fs')
398
+ * ```
399
+ */
400
+ lookup(type: RegistryType, name: string): any {
401
+ const { registry } = this.registryMap[type]
402
+ return registry.lookup(name)
403
+ }
404
+
405
+ /**
406
+ * Get the introspection description for a specific helper.
407
+ *
408
+ * @param type - The registry type
409
+ * @param name - The helper name
410
+ * @returns Markdown description of the helper's interface
411
+ */
412
+ describe(type: RegistryType, name: string): string {
413
+ const { registry } = this.registryMap[type]
414
+ return registry.describe(name)
415
+ }
416
+
417
+ /**
418
+ * Load a module either via native `import()` or the VM's virtual module system.
419
+ * Uses the same `useNativeImport` check as discovery to decide the loading strategy.
420
+ *
421
+ * @param absPath - Absolute path to the module file
422
+ * @param options - Optional settings
423
+ * @param options.cacheBust - When true, appends a timestamp query to bypass the native import cache (useful for hot reload)
424
+ * @returns The module's exports
425
+ */
426
+ async loadModuleExports(absPath: string, options?: { cacheBust?: boolean }): Promise<Record<string, any>> {
427
+ if (this.useNativeImport) {
428
+ const importPath = options?.cacheBust ? `${absPath}?t=${Date.now()}` : absPath
429
+ const mod = await import(importPath)
430
+ return mod
431
+ }
432
+
433
+ this.seedVirtualModules()
434
+ const vm = this.container.feature('vm') as unknown as VM
435
+ return vm.loadModule(absPath)
436
+ }
437
+
438
+ /**
439
+ * Discovers class-based helpers (features, clients, servers) from a directory.
440
+ * Uses fileManager when available (fast in git repos), falls back to Glob.
441
+ */
442
+ private async discoverClassBased(type: RegistryType, dir: string): Promise<string[]> {
443
+ const { registry, baseClass } = this.registryMap[type]
444
+ const discovered: string[] = []
445
+
446
+ // Load build-time introspection data before importing helpers so that
447
+ // interceptRegistration() can merge JSDoc descriptions from the generated file.
448
+ const introspectionFile = resolve(dir, 'introspection.generated.ts')
449
+ try {
450
+ if (existsSync(introspectionFile)) {
451
+ await import(introspectionFile)
452
+ }
453
+ } catch {}
454
+
455
+ // Try fileManager first (faster in git repos, and now symlink-aware),
456
+ // fall back to fs.walk which also follows symlinks natively.
457
+ let files: string[] = []
458
+ try {
459
+ const fm = await this.ensureFileManager()
460
+ const absPatterns = [`${dir}/*.ts`, `${dir}/**/*.ts`]
461
+ const relPatterns = [`${type}/*.ts`, `${type}/**/*.ts`]
462
+ const matched = fm.match([...absPatterns, ...relPatterns])
463
+ files = matched.map((f: string) => f.startsWith('/') ? f : resolve(this.rootDir, f))
464
+ } catch {}
465
+
466
+ // Fall back to fs.walk if fileManager found nothing
467
+ if (files.length === 0) {
468
+ const { fs } = this.container
469
+ const walked = fs.walk(dir, { include: ['**/*.ts'] })
470
+ files = walked.files
471
+ }
472
+
473
+ for (const absPath of files) {
474
+ const { name: fileName } = parse(absPath)
475
+
476
+ if (fileName.includes('.test.') || fileName.includes('.spec.') || fileName.includes('.generated')) {
477
+ continue
478
+ }
479
+ try {
480
+ const mod = await this.loadModuleExports(absPath)
481
+ const ExportedClass = mod.default || mod
482
+
483
+ // Class-based: default export is a subclass of the base
484
+ if (typeof ExportedClass === 'function' && isNativeHelperClass(ExportedClass, baseClass)) {
485
+ const shortcut = ExportedClass.shortcut as string | undefined
486
+ const registryName = shortcut
487
+ ? shortcut.replace(`${type}.`, '')
488
+ : this.fileNameToRegistryName(fileName)
489
+
490
+ discovered.push(registryName)
491
+
492
+ if (!registry.has(registryName)) {
493
+ registry.register(registryName, ExportedClass)
494
+ this.emit('registered' as any, type, registryName, ExportedClass)
495
+ }
496
+ } else {
497
+ // Module-based: graft exports onto a generated subclass
498
+ const moduleExports = mod.default && typeof mod.default === 'object' ? mod.default : mod
499
+ const isGraftable = (
500
+ moduleExports.description !== undefined ||
501
+ moduleExports.stateSchema !== undefined ||
502
+ moduleExports.optionsSchema !== undefined ||
503
+ typeof moduleExports.run === 'function' ||
504
+ typeof moduleExports.handler === 'function'
505
+ )
506
+
507
+ if (isGraftable) {
508
+ const registryName = this.fileNameToRegistryName(fileName)
509
+ const GraftedClass = graftModule(baseClass, moduleExports, registryName, type as any)
510
+
511
+ discovered.push(registryName)
512
+
513
+ if (!registry.has(registryName)) {
514
+ registry.register(registryName, GraftedClass as any)
515
+ this.emit('registered' as any, type, registryName, GraftedClass)
516
+ }
517
+ }
518
+ }
519
+
520
+ } catch (err: any) {
521
+ if (err.message?.includes('name collision')) {
522
+ throw err
523
+ }
524
+ console.warn(`Helpers gateway: failed to load ${type} from ${absPath}: ${err.message}`)
525
+ }
526
+ }
527
+
528
+ return discovered
529
+ }
530
+
531
+ /**
532
+ * Discovers config-based helpers (commands, endpoints) by delegating
533
+ * to existing discovery mechanisms.
534
+ */
535
+ private async discoverConfigBased(type: RegistryType, dir: string): Promise<string[]> {
536
+ const { registry } = this.registryMap[type]
537
+ const beforeNames = new Set(registry.available)
538
+
539
+ if (type === 'commands') {
540
+ if (this.useNativeImport) {
541
+ await commands.discover({ directory: dir })
542
+ } else {
543
+ await this.discoverCommandsViaVM(dir)
544
+ }
545
+ } else if (type === 'endpoints') {
546
+ await this.discoverEndpoints(dir)
547
+ } else if (type === 'selectors') {
548
+ if (this.useNativeImport) {
549
+ await selectors.discover({ directory: dir })
550
+ } else {
551
+ await this.discoverSelectorsViaVM(dir)
552
+ }
553
+ }
554
+
555
+ const afterNames = new Set(registry.available)
556
+ return [...afterNames].filter(n => !beforeNames.has(n))
557
+ }
558
+
559
+ /**
560
+ * Discovers commands using the VM's virtual module system.
561
+ * Mirrors CommandsRegistry.discover() but uses vm.loadModule() instead of import().
562
+ */
563
+ private async discoverCommandsViaVM(dir: string): Promise<void> {
564
+ this.seedVirtualModules()
565
+ const { fs } = this.container
566
+ // Commands are top-level only (not recursive) — walk and filter to *.ts in the immediate dir
567
+ const walked = fs.walk(dir, { include: ['*.ts'] })
568
+ const tsFiles = walked.files
569
+ .map(f => parse(f))
570
+ .filter(p => p.dir === dir) // top-level only
571
+ .map(p => p.base)
572
+
573
+ for (const file of tsFiles) {
574
+ if (file === 'index.ts') continue
575
+
576
+ const absPath = resolve(dir, file)
577
+ const name = file.replace(/\.ts$/, '')
578
+
579
+ if (commands.has(name)) continue
580
+
581
+ try {
582
+ const mod = await this.loadModuleExports(absPath)
583
+
584
+ // 1. Class-based: default export extends Command
585
+ if (isNativeHelperClass(mod.default, Command)) {
586
+ const ExportedClass = mod.default
587
+ if (!ExportedClass.shortcut || ExportedClass.shortcut === 'commands.base') {
588
+ ExportedClass.shortcut = `commands.${name}`
589
+ }
590
+ if (!ExportedClass.commandDescription && ExportedClass.description) {
591
+ ExportedClass.commandDescription = ExportedClass.description
592
+ }
593
+ commands.register(name, ExportedClass)
594
+ continue
595
+ }
596
+
597
+ const commandModule = mod.default || mod
598
+
599
+ // 2. Module-based with `run` export (new SimpleCommand pattern)
600
+ if (typeof commandModule.run === 'function') {
601
+ const Grafted = graftModule(Command as any, commandModule, name, 'commands')
602
+ commands.register(name, Grafted as any)
603
+ continue
604
+ }
605
+
606
+ // 3. Legacy: `handler` export
607
+ if (typeof commandModule.handler === 'function') {
608
+ const Grafted = graftModule(Command as any, {
609
+ description: commandModule.description,
610
+ argsSchema: commandModule.argsSchema,
611
+ handler: commandModule.handler,
612
+ }, name, 'commands')
613
+ commands.register(name, Grafted as any)
614
+ continue
615
+ }
616
+
617
+ // 4. Plain default-exported function: export default async function name(options, context)
618
+ if (typeof mod.default === 'function' && !isNativeHelperClass(mod.default, Command)) {
619
+ const Grafted = graftModule(Command as any, {
620
+ description: mod.description || '',
621
+ argsSchema: mod.argsSchema,
622
+ positionals: mod.positionals,
623
+ handler: mod.default,
624
+ }, name, 'commands')
625
+ commands.register(name, Grafted as any)
626
+ }
627
+ } catch (err: any) {
628
+ console.warn(`Helpers gateway: failed to load command from ${absPath}: ${err.message}`)
629
+ }
630
+ }
631
+ }
632
+
633
+ /**
634
+ * Discovers selectors using the VM's virtual module system.
635
+ * Mirrors discoverCommandsViaVM but uses selectors registry and Selector base class.
636
+ */
637
+ private async discoverSelectorsViaVM(dir: string): Promise<void> {
638
+ this.seedVirtualModules()
639
+ const { fs } = this.container
640
+ const walked = fs.walk(dir, { include: ['*.ts'] })
641
+ const tsFiles = walked.files
642
+ .map(f => parse(f))
643
+ .filter(p => p.dir === dir)
644
+ .map(p => p.base)
645
+
646
+ for (const file of tsFiles) {
647
+ if (file === 'index.ts') continue
648
+
649
+ const absPath = resolve(dir, file)
650
+ const name = file.replace(/\.ts$/, '')
651
+
652
+ if (selectors.has(name)) continue
653
+
654
+ try {
655
+ const mod = await this.loadModuleExports(absPath)
656
+
657
+ // 1. Class-based: default export extends Selector
658
+ if (isNativeHelperClass(mod.default, Selector)) {
659
+ const ExportedClass = mod.default
660
+ if (!ExportedClass.shortcut || ExportedClass.shortcut === 'selectors.base') {
661
+ ExportedClass.shortcut = `selectors.${name}`
662
+ }
663
+ selectors.register(name, ExportedClass)
664
+ continue
665
+ }
666
+
667
+ const selectorModule = mod.default || mod
668
+
669
+ // 2. Module-based with `run` export
670
+ if (typeof selectorModule.run === 'function') {
671
+ const Grafted = graftModule(Selector as any, selectorModule, name, 'selectors')
672
+ selectors.register(name, Grafted as any)
673
+ }
674
+ } catch (err: any) {
675
+ console.warn(`Helpers gateway: failed to load selector from ${absPath}: ${err.message}`)
676
+ }
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Discovers endpoints from a directory, registering them for discoverability.
682
+ * Actual mounting to an express server is handled separately by ExpressServer.useEndpoints().
683
+ */
684
+ private async discoverEndpoints(dir: string): Promise<void> {
685
+ const { fs } = this.container
686
+ const walked = fs.walk(dir, { include: ['**/*.ts'] })
687
+
688
+ for (const file of walked.files) {
689
+ try {
690
+ const mod = await this.loadModuleExports(file)
691
+ const endpointModule = mod.default || mod
692
+
693
+ if (endpointModule.path && typeof endpointModule.path === 'string') {
694
+ const name = endpointModule.path.replace(/^\//, '').replace(/\//g, '_') || parse(file).name
695
+
696
+ if (!endpoints.has(name)) {
697
+ // Import the module so it's available, but don't mount it to a server
698
+ // The express server's useEndpoints() handles the actual mounting
699
+ }
700
+ }
701
+ } catch (err: any) {
702
+ console.warn(`Helpers gateway: failed to load endpoint from ${file}: ${err.message}`)
703
+ }
704
+ }
705
+ }
706
+
707
+ /**
708
+ * Check if a class is a subclass of a given base class by walking the prototype chain.
709
+ * Uses identity comparison first, then falls back to name comparison to handle
710
+ * cross-module boundaries (e.g. compiled binary vs dynamically imported modules
711
+ * that resolve to separate module instances of the same class).
712
+ */
713
+ private isSubclassOf(candidate: any, base: any): boolean {
714
+ if (!candidate || !base) return false
715
+ if (candidate === base) return true
716
+
717
+ let proto = Object.getPrototypeOf(candidate)
718
+ while (proto) {
719
+ if (proto === base || (base.name && proto.name === base.name)) return true
720
+ proto = Object.getPrototypeOf(proto)
721
+ }
722
+ return false
723
+ }
724
+
725
+ /**
726
+ * Convert a kebab-case or snake_case filename to a camelCase registry name.
727
+ */
728
+ private fileNameToRegistryName(fileName: string): string {
729
+ return fileName
730
+ .replace(/[-_](.)/g, (_, c: string) => c.toUpperCase())
731
+ .replace(/^(.)/, (_, c: string) => c.toLowerCase())
732
+ }
733
+ }
734
+
735
+ export default Helpers