luca 2.0.0 → 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 (763) 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 -9
  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 -12
  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 -58
  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/cli.js +0 -48
  734. package/dist/cli/common.d.ts +0 -2
  735. package/dist/cli/common.js +0 -6
  736. package/dist/cli/index.d.ts +0 -2
  737. package/dist/cli/index.js +0 -5
  738. package/dist/cli/run.d.ts +0 -1
  739. package/dist/cli/run.js +0 -38
  740. package/dist/core/index.d.ts +0 -4
  741. package/dist/core/index.js +0 -32
  742. package/dist/core/read.d.ts +0 -2
  743. package/dist/core/read.js +0 -29
  744. package/dist/core/request.d.ts +0 -1
  745. package/dist/core/request.js +0 -2
  746. package/dist/core/write.d.ts +0 -2
  747. package/dist/core/write.js +0 -21
  748. package/dist/index.d.ts +0 -1
  749. package/dist/index.js +0 -5
  750. package/dist/utils/common.d.ts +0 -9
  751. package/dist/utils/common.js +0 -57
  752. package/dist/utils/consts.d.ts +0 -3
  753. package/dist/utils/consts.js +0 -11
  754. package/dist/utils/dict.d.ts +0 -1
  755. package/dist/utils/dict.js +0 -7
  756. package/dist/utils/index.d.ts +0 -5
  757. package/dist/utils/index.js +0 -21
  758. package/dist/utils/log.d.ts +0 -1
  759. package/dist/utils/log.js +0 -5
  760. package/dist/utils/types.d.ts +0 -1
  761. package/dist/utils/types.js +0 -2
  762. package/dist/utils/utils.test.d.ts +0 -1
  763. package/dist/utils/utils.test.js +0 -7
@@ -0,0 +1,921 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
3
+ import { Feature } from '../feature.js'
4
+
5
+ export const DockerContainerSchema = z.object({
6
+ /** Container ID */
7
+ id: z.string().describe('Container ID'),
8
+ /** Container name */
9
+ name: z.string().describe('Container name'),
10
+ /** Image used to create the container */
11
+ image: z.string().describe('Image used to create the container'),
12
+ /** Current container status (e.g. running, exited) */
13
+ status: z.string().describe('Current container status (e.g. running, exited)'),
14
+ /** Published port mappings */
15
+ ports: z.array(z.string()).describe('Published port mappings'),
16
+ /** Container creation timestamp */
17
+ created: z.string().describe('Container creation timestamp'),
18
+ })
19
+ export type DockerContainer = z.infer<typeof DockerContainerSchema>
20
+
21
+ export const DockerImageSchema = z.object({
22
+ /** Image ID */
23
+ id: z.string().describe('Image ID'),
24
+ /** Image repository name */
25
+ repository: z.string().describe('Image repository name'),
26
+ /** Image tag */
27
+ tag: z.string().describe('Image tag'),
28
+ /** Image size */
29
+ size: z.string().describe('Image size'),
30
+ /** Image creation timestamp */
31
+ created: z.string().describe('Image creation timestamp'),
32
+ })
33
+ export type DockerImage = z.infer<typeof DockerImageSchema>
34
+
35
+ export const DockerStateSchema = FeatureStateSchema.extend({
36
+ /** List of known Docker containers */
37
+ containers: z.array(DockerContainerSchema).describe('List of known Docker containers'),
38
+ /** List of known Docker images */
39
+ images: z.array(DockerImageSchema).describe('List of known Docker images'),
40
+ /** Whether Docker CLI is available on this system */
41
+ isDockerAvailable: z.boolean().describe('Whether Docker CLI is available on this system'),
42
+ /** Last error message from a Docker operation */
43
+ lastError: z.string().optional().describe('Last error message from a Docker operation'),
44
+ })
45
+ export type DockerState = z.infer<typeof DockerStateSchema>
46
+
47
+ export const DockerOptionsSchema = FeatureOptionsSchema.extend({
48
+ /** Path to docker executable */
49
+ dockerPath: z.string().optional().describe('Path to docker executable'),
50
+ /** Command timeout in ms */
51
+ timeout: z.number().optional().describe('Command timeout in milliseconds'),
52
+ /** Auto refresh containers/images on operations */
53
+ autoRefresh: z.boolean().optional().describe('Auto refresh containers/images after operations'),
54
+ })
55
+ export type DockerOptions = z.infer<typeof DockerOptionsSchema>
56
+
57
+ /** Shell-like interface for executing commands against a Docker container */
58
+ export interface DockerShell {
59
+ /** The ID of the container being targeted */
60
+ readonly containerId: string
61
+ /** The result of the most recently executed command, or null if no command has been run */
62
+ readonly last: { stdout: string; stderr: string; exitCode: number } | null
63
+ /** Execute a command string in the container via sh -c */
64
+ run(command: string): Promise<{ stdout: string; stderr: string; exitCode: number }>
65
+ /** Destroy the shell container (only needed when volumes created a new container) */
66
+ destroy(): Promise<void>
67
+ }
68
+
69
+ /**
70
+ * Docker CLI interface feature for managing containers, images, and executing Docker commands.
71
+ *
72
+ * Provides comprehensive Docker operations including:
73
+ * - Container management (list, start, stop, create, remove)
74
+ * - Image management (list, pull, build, remove)
75
+ * - Command execution inside containers
76
+ * - Docker system information
77
+ *
78
+ * @extends Feature
79
+ * @example
80
+ * ```typescript
81
+ * const docker = container.feature('docker', { enable: true })
82
+ * await docker.checkDockerAvailability()
83
+ * const containers = await docker.listContainers({ all: true })
84
+ * ```
85
+ */
86
+ export class Docker extends Feature<DockerState, DockerOptions> {
87
+ static override shortcut = 'features.docker' as const
88
+ static override stateSchema = DockerStateSchema
89
+ static override optionsSchema = DockerOptionsSchema
90
+ static { Feature.register(this, 'docker') }
91
+
92
+ override get initialState(): DockerState {
93
+ return {
94
+ ...super.initialState,
95
+ containers: [],
96
+ images: [],
97
+ isDockerAvailable: false
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Get the proc feature for executing shell commands
103
+ */
104
+ private _resolvedDockerPath: string | null = null
105
+
106
+ get proc() {
107
+ return this.container.feature('proc')
108
+ }
109
+
110
+ /** Resolve the docker binary path, caching the result. Options take precedence. */
111
+ get dockerPath(): string {
112
+ if (this.options.dockerPath) return this.options.dockerPath
113
+ if (this._resolvedDockerPath) return this._resolvedDockerPath
114
+ this._resolvedDockerPath = this.container.feature('os').whichCommand('docker')
115
+ return this._resolvedDockerPath
116
+ }
117
+
118
+ /**
119
+ * Check if Docker is available and working.
120
+ *
121
+ * @returns Promise resolving to true if Docker CLI is accessible, false otherwise
122
+ * @example
123
+ * ```typescript
124
+ * const available = await docker.checkDockerAvailability()
125
+ * if (!available) console.log('Docker is not installed or not running')
126
+ * ```
127
+ */
128
+ async checkDockerAvailability(): Promise<boolean> {
129
+ try {
130
+ const result = await this.proc.spawnAndCapture(this.dockerPath, ['--version'])
131
+
132
+ if (result.exitCode === 0) {
133
+ this.setState({ isDockerAvailable: true, lastError: undefined })
134
+ return true
135
+ } else {
136
+ this.setState({ isDockerAvailable: false, lastError: 'Docker command failed' })
137
+ return false
138
+ }
139
+ } catch (error) {
140
+ this.setState({
141
+ isDockerAvailable: false,
142
+ lastError: error instanceof Error ? error.message : 'Unknown error'
143
+ })
144
+ return false
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Execute a Docker command and return the result.
150
+ *
151
+ * @param args - Array of CLI arguments to pass to the docker binary
152
+ * @returns Promise resolving to an object with stdout, stderr, and exitCode
153
+ * @throws Error if Docker is not available
154
+ */
155
+ private async executeDockerCommand(args: string[]): Promise<{ stdout: string; stderr: string; exitCode: number }> {
156
+ if (!this.state.current.isDockerAvailable) {
157
+ const available = await this.checkDockerAvailability()
158
+ if (!available) {
159
+ throw new Error('Docker is not available')
160
+ }
161
+ }
162
+
163
+ try {
164
+ const result = await this.proc.spawnAndCapture(this.dockerPath, args)
165
+
166
+ if (result.exitCode !== 0) {
167
+ this.setState({ lastError: result.stderr })
168
+ }
169
+
170
+ return result
171
+ } catch (error) {
172
+ const message = error instanceof Error ? error.message : 'Unknown error'
173
+ this.setState({ lastError: message })
174
+ throw error
175
+ }
176
+ }
177
+
178
+ /**
179
+ * List all containers (running and stopped).
180
+ *
181
+ * @param options - Listing options
182
+ * @param options.all - Include stopped containers (default: false)
183
+ * @returns Promise resolving to an array of DockerContainer objects
184
+ * @throws Error if the docker ps command fails
185
+ * @example
186
+ * ```typescript
187
+ * const running = await docker.listContainers()
188
+ * const all = await docker.listContainers({ all: true })
189
+ * ```
190
+ */
191
+ async listContainers(options: { all?: boolean } = {}): Promise<DockerContainer[]> {
192
+ const args = ['ps', '--format', 'json']
193
+ if (options.all) {
194
+ args.push('--all')
195
+ }
196
+
197
+ const result = await this.executeDockerCommand(args)
198
+
199
+ if (result.exitCode === 0) {
200
+ const containers: DockerContainer[] = []
201
+ const lines = result.stdout.trim().split(/\r?\n/).filter(line => line.trim())
202
+
203
+ for (const line of lines) {
204
+ try {
205
+ const containerData = JSON.parse(line)
206
+ containers.push({
207
+ id: containerData.ID,
208
+ name: containerData.Names,
209
+ image: containerData.Image,
210
+ status: containerData.Status,
211
+ ports: containerData.Ports ? containerData.Ports.split(',').map((p: string) => p.trim()) : [],
212
+ created: containerData.CreatedAt
213
+ })
214
+ } catch (e) {
215
+ // Skip invalid JSON lines
216
+ }
217
+ }
218
+
219
+ if (this.options.autoRefresh) {
220
+ this.setState({ containers })
221
+ }
222
+
223
+ return containers
224
+ }
225
+
226
+ throw new Error(`Failed to list containers: ${result.stderr}`)
227
+ }
228
+
229
+ /**
230
+ * List all images available locally.
231
+ *
232
+ * @returns Promise resolving to an array of DockerImage objects
233
+ * @throws Error if the docker images command fails
234
+ * @example
235
+ * ```typescript
236
+ * const images = await docker.listImages()
237
+ * console.log(images.map(i => `${i.repository}:${i.tag}`))
238
+ * ```
239
+ */
240
+ async listImages(): Promise<DockerImage[]> {
241
+ const result = await this.executeDockerCommand(['images', '--format', 'json'])
242
+
243
+ if (result.exitCode === 0) {
244
+ const images: DockerImage[] = []
245
+ const lines = result.stdout.trim().split(/\r?\n/).filter(line => line.trim())
246
+
247
+ for (const line of lines) {
248
+ try {
249
+ const imageData = JSON.parse(line)
250
+ images.push({
251
+ id: imageData.ID,
252
+ repository: imageData.Repository,
253
+ tag: imageData.Tag,
254
+ size: imageData.Size,
255
+ created: imageData.CreatedAt
256
+ })
257
+ } catch (e) {
258
+ // Skip invalid JSON lines
259
+ }
260
+ }
261
+
262
+ if (this.options.autoRefresh) {
263
+ this.setState({ images })
264
+ }
265
+
266
+ return images
267
+ }
268
+
269
+ throw new Error(`Failed to list images: ${result.stderr}`)
270
+ }
271
+
272
+ /**
273
+ * Start a stopped container.
274
+ *
275
+ * @param containerIdOrName - Container ID or name to start
276
+ * @returns Promise that resolves when the container is started
277
+ * @throws Error if the container cannot be started
278
+ * @example
279
+ * ```typescript
280
+ * await docker.startContainer('my-app')
281
+ * ```
282
+ */
283
+ async startContainer(containerIdOrName: string): Promise<void> {
284
+ const result = await this.executeDockerCommand(['start', containerIdOrName])
285
+
286
+ if (result.exitCode !== 0) {
287
+ throw new Error(`Failed to start container: ${result.stderr}`)
288
+ }
289
+
290
+ if (this.options.autoRefresh) {
291
+ await this.listContainers({ all: true })
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Stop a running container.
297
+ *
298
+ * @param containerIdOrName - Container ID or name to stop
299
+ * @param timeout - Seconds to wait before killing the container
300
+ * @returns Promise that resolves when the container is stopped
301
+ * @throws Error if the container cannot be stopped
302
+ * @example
303
+ * ```typescript
304
+ * await docker.stopContainer('my-app')
305
+ * await docker.stopContainer('my-app', 30) // wait up to 30s
306
+ * ```
307
+ */
308
+ async stopContainer(containerIdOrName: string, timeout?: number): Promise<void> {
309
+ const args = ['stop']
310
+ if (timeout) {
311
+ args.push('--time', timeout.toString())
312
+ }
313
+ args.push(containerIdOrName)
314
+
315
+ const result = await this.executeDockerCommand(args)
316
+
317
+ if (result.exitCode !== 0) {
318
+ throw new Error(`Failed to stop container: ${result.stderr}`)
319
+ }
320
+
321
+ if (this.options.autoRefresh) {
322
+ await this.listContainers({ all: true })
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Remove a container.
328
+ *
329
+ * @param containerIdOrName - Container ID or name to remove
330
+ * @param options - Removal options
331
+ * @param options.force - Force removal of a running container
332
+ * @returns Promise that resolves when the container is removed
333
+ * @throws Error if the container cannot be removed
334
+ * @example
335
+ * ```typescript
336
+ * await docker.removeContainer('old-container')
337
+ * await docker.removeContainer('stubborn-container', { force: true })
338
+ * ```
339
+ */
340
+ async removeContainer(containerIdOrName: string, options: { force?: boolean } = {}): Promise<void> {
341
+ const args = ['rm']
342
+ if (options.force) {
343
+ args.push('--force')
344
+ }
345
+ args.push(containerIdOrName)
346
+
347
+ const result = await this.executeDockerCommand(args)
348
+
349
+ if (result.exitCode !== 0) {
350
+ throw new Error(`Failed to remove container: ${result.stderr}`)
351
+ }
352
+
353
+ if (this.options.autoRefresh) {
354
+ await this.listContainers({ all: true })
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Create and run a new container from the given image.
360
+ *
361
+ * @param image - Docker image to run (e.g. 'nginx:latest')
362
+ * @param options - Container run options
363
+ * @param options.name - Assign a name to the container
364
+ * @param options.ports - Port mappings in 'host:container' format (e.g. ['8080:80'])
365
+ * @param options.volumes - Volume mounts in 'host:container' format (e.g. ['./data:/app/data'])
366
+ * @param options.environment - Environment variables as key-value pairs
367
+ * @param options.detach - Run the container in the background
368
+ * @param options.interactive - Keep STDIN open
369
+ * @param options.tty - Allocate a pseudo-TTY
370
+ * @param options.command - Command and arguments to run inside the container
371
+ * @param options.workdir - Working directory inside the container
372
+ * @param options.user - Username or UID to run as
373
+ * @param options.entrypoint - Override the default entrypoint
374
+ * @param options.network - Connect the container to a network
375
+ * @param options.restart - Restart policy (e.g. 'always', 'on-failure')
376
+ * @returns Promise resolving to the container ID
377
+ * @throws Error if the container cannot be started
378
+ * @example
379
+ * ```typescript
380
+ * const containerId = await docker.runContainer('nginx:latest', {
381
+ * name: 'web',
382
+ * ports: ['8080:80'],
383
+ * detach: true,
384
+ * environment: { NODE_ENV: 'production' }
385
+ * })
386
+ * ```
387
+ */
388
+ async runContainer(
389
+ image: string,
390
+ options: {
391
+ /** Assign a name to the container */
392
+ name?: string
393
+ /** Port mappings in 'host:container' format */
394
+ ports?: string[]
395
+ /** Volume mounts in 'host:container' format */
396
+ volumes?: string[]
397
+ /** Environment variables as key-value pairs */
398
+ environment?: Record<string, string>
399
+ /** Run the container in the background */
400
+ detach?: boolean
401
+ /** Keep STDIN open */
402
+ interactive?: boolean
403
+ /** Allocate a pseudo-TTY */
404
+ tty?: boolean
405
+ /** Command and arguments to run inside the container */
406
+ command?: string[]
407
+ /** Working directory inside the container */
408
+ workdir?: string
409
+ /** Username or UID to run as */
410
+ user?: string
411
+ /** Override the default entrypoint */
412
+ entrypoint?: string
413
+ /** Connect the container to a network */
414
+ network?: string
415
+ /** Restart policy (e.g. 'always', 'on-failure') */
416
+ restart?: string
417
+ } = {}
418
+ ): Promise<string> {
419
+ const args = ['run']
420
+
421
+ if (options.detach) args.push('--detach')
422
+ if (options.interactive) args.push('--interactive')
423
+ if (options.tty) args.push('--tty')
424
+ if (options.name) args.push('--name', options.name)
425
+ if (options.workdir) args.push('--workdir', options.workdir)
426
+ if (options.user) args.push('--user', options.user)
427
+ if (options.entrypoint) args.push('--entrypoint', options.entrypoint)
428
+ if (options.network) args.push('--network', options.network)
429
+ if (options.restart) args.push('--restart', options.restart)
430
+
431
+ if (options.ports) {
432
+ for (const port of options.ports) {
433
+ args.push('--publish', port)
434
+ }
435
+ }
436
+
437
+ if (options.volumes) {
438
+ for (const volume of options.volumes) {
439
+ args.push('--volume', volume)
440
+ }
441
+ }
442
+
443
+ if (options.environment) {
444
+ for (const [key, value] of Object.entries(options.environment)) {
445
+ args.push('--env', `${key}=${value}`)
446
+ }
447
+ }
448
+
449
+ args.push(image)
450
+
451
+ if (options.command) {
452
+ args.push(...options.command)
453
+ }
454
+
455
+ const result = await this.executeDockerCommand(args)
456
+
457
+ if (result.exitCode !== 0) {
458
+ throw new Error(`Failed to run container: ${result.stderr}`)
459
+ }
460
+
461
+ if (this.options.autoRefresh) {
462
+ await this.listContainers({ all: true })
463
+ }
464
+
465
+ return result.stdout.trim()
466
+ }
467
+
468
+ /**
469
+ * Execute a command inside a running container.
470
+ *
471
+ * When volumes are specified, uses `docker run --rm` with the container's image
472
+ * instead of `docker exec`, since exec does not support volume mounts.
473
+ *
474
+ * @param containerIdOrName - Container ID or name to execute in
475
+ * @param command - Command and arguments array (e.g. ['ls', '-la'])
476
+ * @param options - Execution options
477
+ * @param options.interactive - Keep STDIN open
478
+ * @param options.tty - Allocate a pseudo-TTY
479
+ * @param options.user - Username or UID to run as
480
+ * @param options.workdir - Working directory inside the container
481
+ * @param options.detach - Run the command in the background
482
+ * @param options.environment - Environment variables as key-value pairs
483
+ * @param options.volumes - Volume mounts; triggers a docker run --rm fallback
484
+ * @returns Promise resolving to an object with stdout, stderr, and exitCode
485
+ * @example
486
+ * ```typescript
487
+ * const result = await docker.execCommand('my-app', ['ls', '-la', '/app'])
488
+ * console.log(result.stdout)
489
+ * ```
490
+ */
491
+ async execCommand(
492
+ containerIdOrName: string,
493
+ command: string[],
494
+ options: {
495
+ /** Keep STDIN open */
496
+ interactive?: boolean
497
+ /** Allocate a pseudo-TTY */
498
+ tty?: boolean
499
+ /** Username or UID to run as */
500
+ user?: string
501
+ /** Working directory inside the container */
502
+ workdir?: string
503
+ /** Run the command in the background */
504
+ detach?: boolean
505
+ /** Environment variables as key-value pairs */
506
+ environment?: Record<string, string>
507
+ /** Volume mounts; triggers a docker run --rm fallback */
508
+ volumes?: string[]
509
+ } = {}
510
+ ): Promise<{ stdout: string; stderr: string; exitCode: number }> {
511
+ // docker exec does not support volume mounts; fall back to docker run --rm
512
+ if (options.volumes?.length) {
513
+ const image = await this.getContainerImage(containerIdOrName)
514
+
515
+ const args = ['run', '--rm']
516
+ for (const vol of options.volumes) { args.push('--volume', vol) }
517
+ if (options.interactive) args.push('--interactive')
518
+ if (options.tty) args.push('--tty')
519
+ if (options.user) args.push('--user', options.user)
520
+ if (options.workdir) args.push('--workdir', options.workdir)
521
+ if (options.environment) {
522
+ for (const [key, value] of Object.entries(options.environment)) {
523
+ args.push('--env', `${key}=${value}`)
524
+ }
525
+ }
526
+ args.push(image, ...command)
527
+ return this.executeDockerCommand(args)
528
+ }
529
+
530
+ const args = ['exec']
531
+
532
+ if (options.interactive) args.push('--interactive')
533
+ if (options.tty) args.push('--tty')
534
+ if (options.user) args.push('--user', options.user)
535
+ if (options.workdir) args.push('--workdir', options.workdir)
536
+ if (options.detach) args.push('--detach')
537
+ if (options.environment) {
538
+ for (const [key, value] of Object.entries(options.environment)) {
539
+ args.push('--env', `${key}=${value}`)
540
+ }
541
+ }
542
+
543
+ args.push(containerIdOrName, ...command)
544
+
545
+ const result = await this.executeDockerCommand(args)
546
+ return result
547
+ }
548
+
549
+ /**
550
+ * Look up the image name for a running container via docker inspect.
551
+ *
552
+ * @param containerIdOrName - Container ID or name to inspect
553
+ * @returns Promise resolving to the image name string
554
+ * @throws Error if the container cannot be inspected
555
+ */
556
+ private async getContainerImage(containerIdOrName: string): Promise<string> {
557
+ const result = await this.executeDockerCommand([
558
+ 'inspect', '--format', '{{.Config.Image}}', containerIdOrName
559
+ ])
560
+ if (result.exitCode !== 0) {
561
+ throw new Error(`Failed to inspect container ${containerIdOrName}: ${result.stderr}`)
562
+ }
563
+ return result.stdout.trim()
564
+ }
565
+
566
+ /**
567
+ * Create a shell-like wrapper for executing multiple commands against a container.
568
+ *
569
+ * When volume mounts are specified, a new long-running container is created from
570
+ * the same image with the mounts applied (since docker exec does not support volumes).
571
+ * Call `destroy()` when finished to clean up the helper container.
572
+ *
573
+ * Returns an object with:
574
+ * - `run(command)` — execute a shell command string via `sh -c`
575
+ * - `last` — getter for the most recent command result
576
+ * - `destroy()` — stop the helper container (no-op when no volumes were needed)
577
+ */
578
+ async createShell(
579
+ containerIdOrName: string,
580
+ options: {
581
+ volumes?: string[]
582
+ workdir?: string
583
+ user?: string
584
+ environment?: Record<string, string>
585
+ } = {}
586
+ ): Promise<DockerShell> {
587
+ const docker = this
588
+ let targetContainer = containerIdOrName
589
+ let createdContainer: string | null = null
590
+
591
+ if (options.volumes?.length) {
592
+ const image = await this.getContainerImage(containerIdOrName)
593
+
594
+ const runArgs = ['run', '-d', '--rm']
595
+ for (const vol of options.volumes) { runArgs.push('--volume', vol) }
596
+ if (options.workdir) runArgs.push('--workdir', options.workdir)
597
+ if (options.user) runArgs.push('--user', options.user)
598
+ if (options.environment) {
599
+ for (const [key, value] of Object.entries(options.environment)) {
600
+ runArgs.push('--env', `${key}=${value}`)
601
+ }
602
+ }
603
+ runArgs.push(image, 'sleep', 'infinity')
604
+
605
+ const runResult = await this.executeDockerCommand(runArgs)
606
+ if (runResult.exitCode !== 0) {
607
+ throw new Error(`Failed to create shell container: ${runResult.stderr}`)
608
+ }
609
+ targetContainer = runResult.stdout.trim()
610
+ createdContainer = targetContainer
611
+ }
612
+
613
+ // Only pass workdir/user to exec when we didn't bake them into the container
614
+ const execOpts: { workdir?: string; user?: string } = {}
615
+ if (!createdContainer) {
616
+ if (options.workdir) execOpts.workdir = options.workdir
617
+ if (options.user) execOpts.user = options.user
618
+ }
619
+
620
+ let _last: { stdout: string; stderr: string; exitCode: number } | null = null
621
+
622
+ return {
623
+ get containerId() { return targetContainer },
624
+ get last() { return _last },
625
+ run: async (command: string) => {
626
+ _last = await docker.execCommand(targetContainer, ['sh', '-c', command], execOpts)
627
+ return _last
628
+ },
629
+ destroy: async () => {
630
+ if (createdContainer) {
631
+ await docker.executeDockerCommand(['stop', createdContainer])
632
+ createdContainer = null
633
+ }
634
+ }
635
+ }
636
+ }
637
+
638
+ /**
639
+ * Pull an image from a registry.
640
+ *
641
+ * @param image - Full image reference (e.g. 'nginx:latest', 'ghcr.io/org/repo:tag')
642
+ * @returns Promise that resolves when the pull is complete
643
+ * @throws Error if the pull fails
644
+ * @example
645
+ * ```typescript
646
+ * await docker.pullImage('node:20-alpine')
647
+ * ```
648
+ */
649
+ async pullImage(image: string): Promise<void> {
650
+ const result = await this.executeDockerCommand(['pull', image])
651
+
652
+ if (result.exitCode !== 0) {
653
+ throw new Error(`Failed to pull image: ${result.stderr}`)
654
+ }
655
+
656
+ if (this.options.autoRefresh) {
657
+ await this.listImages()
658
+ }
659
+ }
660
+
661
+ /**
662
+ * Remove an image from the local store.
663
+ *
664
+ * @param imageIdOrName - Image ID, repository, or repository:tag to remove
665
+ * @param options - Removal options
666
+ * @param options.force - Force removal even if the image is in use
667
+ * @returns Promise that resolves when the image is removed
668
+ * @throws Error if the image cannot be removed
669
+ * @example
670
+ * ```typescript
671
+ * await docker.removeImage('nginx:latest')
672
+ * await docker.removeImage('old-image', { force: true })
673
+ * ```
674
+ */
675
+ async removeImage(imageIdOrName: string, options: { force?: boolean } = {}): Promise<void> {
676
+ const args = ['rmi']
677
+ if (options.force) {
678
+ args.push('--force')
679
+ }
680
+ args.push(imageIdOrName)
681
+
682
+ const result = await this.executeDockerCommand(args)
683
+
684
+ if (result.exitCode !== 0) {
685
+ throw new Error(`Failed to remove image: ${result.stderr}`)
686
+ }
687
+
688
+ if (this.options.autoRefresh) {
689
+ await this.listImages()
690
+ }
691
+ }
692
+
693
+ /**
694
+ * Build an image from a Dockerfile.
695
+ *
696
+ * @param contextPath - Path to the build context directory
697
+ * @param options - Build options
698
+ * @param options.tag - Tag the resulting image (e.g. 'my-app:latest')
699
+ * @param options.dockerfile - Path to an alternate Dockerfile
700
+ * @param options.buildArgs - Build-time variables as key-value pairs
701
+ * @param options.target - Target build stage in a multi-stage Dockerfile
702
+ * @param options.nocache - Do not use cache when building the image
703
+ * @returns Promise that resolves when the build is complete
704
+ * @throws Error if the build fails
705
+ * @example
706
+ * ```typescript
707
+ * await docker.buildImage('./project', {
708
+ * tag: 'my-app:latest',
709
+ * buildArgs: { NODE_ENV: 'production' }
710
+ * })
711
+ * ```
712
+ */
713
+ async buildImage(
714
+ contextPath: string,
715
+ options: {
716
+ /** Tag the resulting image (e.g. 'my-app:latest') */
717
+ tag?: string
718
+ /** Path to an alternate Dockerfile */
719
+ dockerfile?: string
720
+ /** Build-time variables as key-value pairs */
721
+ buildArgs?: Record<string, string>
722
+ /** Target build stage in a multi-stage Dockerfile */
723
+ target?: string
724
+ /** Do not use cache when building the image */
725
+ nocache?: boolean
726
+ } = {}
727
+ ): Promise<void> {
728
+ const args = ['build']
729
+
730
+ if (options.tag) args.push('--tag', options.tag)
731
+ if (options.dockerfile) args.push('--file', options.dockerfile)
732
+ if (options.target) args.push('--target', options.target)
733
+ if (options.nocache) args.push('--no-cache')
734
+
735
+ if (options.buildArgs) {
736
+ for (const [key, value] of Object.entries(options.buildArgs)) {
737
+ args.push('--build-arg', `${key}=${value}`)
738
+ }
739
+ }
740
+
741
+ args.push(contextPath)
742
+
743
+ const result = await this.executeDockerCommand(args)
744
+
745
+ if (result.exitCode !== 0) {
746
+ throw new Error(`Failed to build image: ${result.stderr}`)
747
+ }
748
+
749
+ if (this.options.autoRefresh) {
750
+ await this.listImages()
751
+ }
752
+ }
753
+
754
+ /**
755
+ * Get container logs.
756
+ *
757
+ * @param containerIdOrName - Container ID or name to fetch logs from
758
+ * @param options - Log retrieval options
759
+ * @param options.follow - Follow log output (stream)
760
+ * @param options.tail - Number of lines to show from the end of the logs
761
+ * @param options.since - Show logs since a timestamp or relative time (e.g. '10m', '2024-01-01T00:00:00')
762
+ * @param options.timestamps - Prepend a timestamp to each log line
763
+ * @returns Promise resolving to the log output string
764
+ * @throws Error if logs cannot be retrieved
765
+ * @example
766
+ * ```typescript
767
+ * const logs = await docker.getLogs('my-app', { tail: 100, timestamps: true })
768
+ * console.log(logs)
769
+ * ```
770
+ */
771
+ async getLogs(
772
+ containerIdOrName: string,
773
+ options: {
774
+ /** Follow log output (stream) */
775
+ follow?: boolean
776
+ /** Number of lines to show from the end of the logs */
777
+ tail?: number
778
+ /** Show logs since a timestamp or relative time */
779
+ since?: string
780
+ /** Prepend a timestamp to each log line */
781
+ timestamps?: boolean
782
+ } = {}
783
+ ): Promise<string> {
784
+ const args = ['logs']
785
+
786
+ if (options.follow) args.push('--follow')
787
+ if (options.tail) args.push('--tail', options.tail.toString())
788
+ if (options.since) args.push('--since', options.since)
789
+ if (options.timestamps) args.push('--timestamps')
790
+
791
+ args.push(containerIdOrName)
792
+
793
+ const result = await this.executeDockerCommand(args)
794
+
795
+ if (result.exitCode !== 0) {
796
+ throw new Error(`Failed to get logs: ${result.stderr}`)
797
+ }
798
+
799
+ return result.stdout
800
+ }
801
+
802
+ /**
803
+ * Get Docker system information (engine version, storage driver, OS, etc.).
804
+ *
805
+ * @returns Promise resolving to the parsed JSON system info object
806
+ * @throws Error if the system info command fails
807
+ * @example
808
+ * ```typescript
809
+ * const info = await docker.getSystemInfo()
810
+ * console.log(info.ServerVersion)
811
+ * ```
812
+ */
813
+ async getSystemInfo(): Promise<any> {
814
+ const result = await this.executeDockerCommand(['system', 'info', '--format', 'json'])
815
+
816
+ if (result.exitCode !== 0) {
817
+ throw new Error(`Failed to get system info: ${result.stderr}`)
818
+ }
819
+
820
+ return JSON.parse(result.stdout)
821
+ }
822
+
823
+ /**
824
+ * Prune unused Docker resources.
825
+ *
826
+ * When no specific resource type is selected, falls back to `docker system prune`.
827
+ *
828
+ * @param options - Pruning options
829
+ * @param options.containers - Prune stopped containers
830
+ * @param options.images - Prune dangling images
831
+ * @param options.volumes - Prune unused volumes
832
+ * @param options.networks - Prune unused networks
833
+ * @param options.all - Prune all resource types (containers, images, volumes, networks)
834
+ * @param options.force - Skip confirmation prompts for image pruning
835
+ * @returns Promise that resolves when pruning is complete
836
+ * @example
837
+ * ```typescript
838
+ * await docker.prune({ all: true })
839
+ * await docker.prune({ containers: true, images: true })
840
+ * ```
841
+ */
842
+ async prune(options: {
843
+ /** Prune stopped containers */
844
+ containers?: boolean
845
+ /** Prune dangling images */
846
+ images?: boolean
847
+ /** Prune unused volumes */
848
+ volumes?: boolean
849
+ /** Prune unused networks */
850
+ networks?: boolean
851
+ /** Prune all resource types */
852
+ all?: boolean
853
+ /** Skip confirmation prompts for image pruning */
854
+ force?: boolean
855
+ } = {}): Promise<void> {
856
+ const commands = []
857
+
858
+ if (options.containers || options.all) {
859
+ commands.push(['container', 'prune', '--force'])
860
+ }
861
+
862
+ if (options.images || options.all) {
863
+ const args = ['image', 'prune']
864
+ if (options.force) args.push('--force')
865
+ commands.push(args)
866
+ }
867
+
868
+ if (options.volumes || options.all) {
869
+ commands.push(['volume', 'prune', '--force'])
870
+ }
871
+
872
+ if (options.networks || options.all) {
873
+ commands.push(['network', 'prune', '--force'])
874
+ }
875
+
876
+ if (commands.length === 0) {
877
+ commands.push(['system', 'prune', '--force'])
878
+ }
879
+
880
+ for (const command of commands) {
881
+ await this.executeDockerCommand(command)
882
+ }
883
+
884
+ if (this.options.autoRefresh) {
885
+ await Promise.all([
886
+ this.listContainers({ all: true }),
887
+ this.listImages()
888
+ ])
889
+ }
890
+ }
891
+
892
+ /**
893
+ * Initialize the Docker feature by checking availability and optionally refreshing state.
894
+ *
895
+ * @param options - Enable options passed to the base Feature
896
+ * @returns Promise resolving to this Docker instance
897
+ */
898
+ override async enable(options: any = {}): Promise<this> {
899
+ await super.enable(options)
900
+
901
+ // Check Docker availability on enable
902
+ await this.checkDockerAvailability()
903
+
904
+ // Initial refresh of containers and images if Docker is available
905
+ if (this.state.current.isDockerAvailable && this.options.autoRefresh) {
906
+ try {
907
+ await Promise.all([
908
+ this.listContainers({ all: true }),
909
+ this.listImages()
910
+ ])
911
+ } catch (error) {
912
+ // Don't fail enable if we can't list initially
913
+ this.setState({ lastError: error instanceof Error ? error.message : 'Unknown error' })
914
+ }
915
+ }
916
+
917
+ return this
918
+ }
919
+ }
920
+
921
+ export default Docker