@better-openclaw/core 1.0.20 → 1.0.22

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 (975) hide show
  1. package/.github/workflows/publish-core.yml +1 -1
  2. package/dist/bare-metal-partition.cjs +2 -3
  3. package/dist/bare-metal-partition.cjs.map +1 -1
  4. package/dist/bare-metal-partition.d.mts.map +1 -1
  5. package/dist/bare-metal-partition.mjs +1 -1
  6. package/dist/bare-metal-partition.test.cjs +4 -5
  7. package/dist/bare-metal-partition.test.cjs.map +1 -1
  8. package/dist/bare-metal-partition.test.mjs +3 -4
  9. package/dist/bare-metal-partition.test.mjs.map +1 -1
  10. package/dist/compose-validation.test.cjs +5 -6
  11. package/dist/compose-validation.test.cjs.map +1 -1
  12. package/dist/compose-validation.test.mjs +2 -3
  13. package/dist/compose-validation.test.mjs.map +1 -1
  14. package/dist/composer.cjs +4 -5
  15. package/dist/composer.cjs.map +1 -1
  16. package/dist/composer.d.mts.map +1 -1
  17. package/dist/composer.mjs +1 -2
  18. package/dist/composer.mjs.map +1 -1
  19. package/dist/composer.snapshot.test.cjs +4 -5
  20. package/dist/composer.snapshot.test.cjs.map +1 -1
  21. package/dist/composer.snapshot.test.mjs +3 -4
  22. package/dist/composer.snapshot.test.mjs.map +1 -1
  23. package/dist/composer.test.cjs +5 -6
  24. package/dist/composer.test.cjs.map +1 -1
  25. package/dist/composer.test.mjs +3 -4
  26. package/dist/composer.test.mjs.map +1 -1
  27. package/dist/coolify-BVGGcMrT.d.mts +18 -0
  28. package/dist/coolify-BVGGcMrT.d.mts.map +1 -0
  29. package/dist/coolify-vlb1G9V2.d.cts +18 -0
  30. package/dist/coolify-vlb1G9V2.d.cts.map +1 -0
  31. package/dist/deployers/coolify.cjs +63 -53
  32. package/dist/deployers/coolify.cjs.map +1 -1
  33. package/dist/deployers/coolify.d.cts +2 -25
  34. package/dist/deployers/coolify.d.mts +2 -25
  35. package/dist/deployers/coolify.mjs +62 -51
  36. package/dist/deployers/coolify.mjs.map +1 -1
  37. package/dist/deployers/dokploy.cjs +108 -32
  38. package/dist/deployers/dokploy.cjs.map +1 -1
  39. package/dist/deployers/dokploy.d.cts +2 -24
  40. package/dist/deployers/dokploy.d.mts +2 -24
  41. package/dist/deployers/dokploy.mjs +107 -30
  42. package/dist/deployers/dokploy.mjs.map +1 -1
  43. package/dist/deployers/index.cjs +4 -5
  44. package/dist/deployers/index.cjs.map +1 -1
  45. package/dist/deployers/index.d.cts +4 -4
  46. package/dist/deployers/index.d.cts.map +1 -1
  47. package/dist/deployers/index.d.mts +4 -4
  48. package/dist/deployers/index.d.mts.map +1 -1
  49. package/dist/deployers/index.mjs +1 -2
  50. package/dist/deployers/index.mjs.map +1 -1
  51. package/dist/deployers/strip-host-ports.cjs +137 -0
  52. package/dist/deployers/strip-host-ports.cjs.map +1 -0
  53. package/dist/deployers/strip-host-ports.d.cts +62 -0
  54. package/dist/deployers/strip-host-ports.d.cts.map +1 -0
  55. package/dist/deployers/strip-host-ports.d.mts +62 -0
  56. package/dist/deployers/strip-host-ports.d.mts.map +1 -0
  57. package/dist/deployers/strip-host-ports.mjs +132 -0
  58. package/dist/deployers/strip-host-ports.mjs.map +1 -0
  59. package/dist/deployers/strip-host-ports.test.cjs +88 -0
  60. package/dist/deployers/strip-host-ports.test.cjs.map +1 -0
  61. package/dist/deployers/strip-host-ports.test.d.cts +1 -0
  62. package/dist/deployers/strip-host-ports.test.d.mts +1 -0
  63. package/dist/deployers/strip-host-ports.test.mjs +89 -0
  64. package/dist/deployers/strip-host-ports.test.mjs.map +1 -0
  65. package/dist/deployers/types.d.cts +2 -72
  66. package/dist/deployers/types.d.mts +2 -72
  67. package/dist/deployers/types.mjs +1 -1
  68. package/dist/dokploy-8cbrxUun.d.cts +25 -0
  69. package/dist/dokploy-8cbrxUun.d.cts.map +1 -0
  70. package/dist/dokploy-BTflLhTM.d.mts +25 -0
  71. package/dist/dokploy-BTflLhTM.d.mts.map +1 -0
  72. package/dist/errors.cjs +2 -3
  73. package/dist/errors.cjs.map +1 -1
  74. package/dist/errors.mjs +1 -1
  75. package/dist/errors.mjs.map +1 -1
  76. package/dist/generate.cjs +27 -28
  77. package/dist/generate.cjs.map +1 -1
  78. package/dist/generate.d.mts.map +1 -1
  79. package/dist/generate.mjs +1 -2
  80. package/dist/generate.mjs.map +1 -1
  81. package/dist/generate.test.cjs +4 -5
  82. package/dist/generate.test.cjs.map +1 -1
  83. package/dist/generate.test.mjs +3 -4
  84. package/dist/generate.test.mjs.map +1 -1
  85. package/dist/generators/bare-metal-install.cjs +2 -3
  86. package/dist/generators/bare-metal-install.cjs.map +1 -1
  87. package/dist/generators/bare-metal-install.d.mts.map +1 -1
  88. package/dist/generators/bare-metal-install.mjs +1 -1
  89. package/dist/generators/bare-metal-install.test.cjs +3 -4
  90. package/dist/generators/bare-metal-install.test.cjs.map +1 -1
  91. package/dist/generators/bare-metal-install.test.mjs +3 -4
  92. package/dist/generators/bare-metal-install.test.mjs.map +1 -1
  93. package/dist/generators/caddy.cjs +2 -3
  94. package/dist/generators/caddy.cjs.map +1 -1
  95. package/dist/generators/caddy.d.mts.map +1 -1
  96. package/dist/generators/caddy.mjs +1 -1
  97. package/dist/generators/caddy.test.cjs +3 -4
  98. package/dist/generators/caddy.test.cjs.map +1 -1
  99. package/dist/generators/caddy.test.mjs +3 -4
  100. package/dist/generators/caddy.test.mjs.map +1 -1
  101. package/dist/generators/cloud-init.cjs +2 -3
  102. package/dist/generators/cloud-init.cjs.map +1 -1
  103. package/dist/generators/cloud-init.mjs +1 -1
  104. package/dist/generators/env.cjs +4 -5
  105. package/dist/generators/env.cjs.map +1 -1
  106. package/dist/generators/env.d.mts.map +1 -1
  107. package/dist/generators/env.mjs +1 -2
  108. package/dist/generators/env.mjs.map +1 -1
  109. package/dist/generators/env.test.cjs +3 -4
  110. package/dist/generators/env.test.cjs.map +1 -1
  111. package/dist/generators/env.test.mjs +3 -4
  112. package/dist/generators/env.test.mjs.map +1 -1
  113. package/dist/generators/get-shit-done.cjs +2 -3
  114. package/dist/generators/get-shit-done.cjs.map +1 -1
  115. package/dist/generators/get-shit-done.mjs +1 -1
  116. package/dist/generators/grafana.cjs +2 -3
  117. package/dist/generators/grafana.cjs.map +1 -1
  118. package/dist/generators/grafana.mjs +1 -1
  119. package/dist/generators/health-check.cjs +2 -3
  120. package/dist/generators/health-check.cjs.map +1 -1
  121. package/dist/generators/health-check.d.mts.map +1 -1
  122. package/dist/generators/health-check.mjs +1 -1
  123. package/dist/generators/health-check.test.cjs +3 -4
  124. package/dist/generators/health-check.test.cjs.map +1 -1
  125. package/dist/generators/health-check.test.mjs +3 -4
  126. package/dist/generators/health-check.test.mjs.map +1 -1
  127. package/dist/generators/n8n-workflows.cjs +2 -3
  128. package/dist/generators/n8n-workflows.cjs.map +1 -1
  129. package/dist/generators/n8n-workflows.d.mts.map +1 -1
  130. package/dist/generators/n8n-workflows.mjs +1 -1
  131. package/dist/generators/native-services.cjs +2 -3
  132. package/dist/generators/native-services.cjs.map +1 -1
  133. package/dist/generators/native-services.mjs +1 -1
  134. package/dist/generators/openclaw-install-script.cjs +2 -3
  135. package/dist/generators/openclaw-install-script.cjs.map +1 -1
  136. package/dist/generators/openclaw-install-script.mjs +1 -1
  137. package/dist/generators/openclaw-json.cjs +2 -3
  138. package/dist/generators/openclaw-json.cjs.map +1 -1
  139. package/dist/generators/openclaw-json.mjs +1 -1
  140. package/dist/generators/postgres-init.cjs +32 -3
  141. package/dist/generators/postgres-init.cjs.map +1 -1
  142. package/dist/generators/postgres-init.d.cts.map +1 -1
  143. package/dist/generators/postgres-init.d.mts.map +1 -1
  144. package/dist/generators/postgres-init.mjs +31 -1
  145. package/dist/generators/postgres-init.mjs.map +1 -1
  146. package/dist/generators/prometheus.cjs +2 -3
  147. package/dist/generators/prometheus.cjs.map +1 -1
  148. package/dist/generators/prometheus.d.mts.map +1 -1
  149. package/dist/generators/prometheus.mjs +1 -1
  150. package/dist/generators/readme.cjs +2 -3
  151. package/dist/generators/readme.cjs.map +1 -1
  152. package/dist/generators/readme.d.mts.map +1 -1
  153. package/dist/generators/readme.mjs +1 -1
  154. package/dist/generators/scripts.cjs +2 -3
  155. package/dist/generators/scripts.cjs.map +1 -1
  156. package/dist/generators/scripts.mjs +1 -1
  157. package/dist/generators/scripts.test.cjs +3 -4
  158. package/dist/generators/scripts.test.cjs.map +1 -1
  159. package/dist/generators/scripts.test.mjs +3 -4
  160. package/dist/generators/scripts.test.mjs.map +1 -1
  161. package/dist/generators/skills.cjs +3 -590
  162. package/dist/generators/skills.d.mts.map +1 -1
  163. package/dist/generators/skills.mjs +1 -2
  164. package/dist/generators/skills.mjs.map +1 -1
  165. package/dist/generators/stack-manifest.cjs +2 -3
  166. package/dist/generators/stack-manifest.cjs.map +1 -1
  167. package/dist/generators/stack-manifest.mjs +1 -1
  168. package/dist/generators/traefik.cjs +2 -3
  169. package/dist/generators/traefik.cjs.map +1 -1
  170. package/dist/generators/traefik.mjs +1 -1
  171. package/dist/generators/traefik.test.cjs +4 -5
  172. package/dist/generators/traefik.test.cjs.map +1 -1
  173. package/dist/generators/traefik.test.mjs +3 -4
  174. package/dist/generators/traefik.test.mjs.map +1 -1
  175. package/dist/index.cjs +35 -36
  176. package/dist/index.d.cts +5 -5
  177. package/dist/index.d.mts +5 -5
  178. package/dist/index.mjs +2 -3
  179. package/dist/{magic-string.es-D2agHT3I.cjs → magic-string.es-CJq41xdM.cjs} +2 -4
  180. package/dist/{magic-string.es-CfFonO_S.mjs.map → magic-string.es-CJq41xdM.cjs.map} +1 -1
  181. package/dist/{magic-string.es-CfFonO_S.mjs → magic-string.es-CoDyF8pj.mjs} +2 -3
  182. package/dist/{magic-string.es-D2agHT3I.cjs.map → magic-string.es-CoDyF8pj.mjs.map} +1 -1
  183. package/dist/migrations.cjs +5 -6
  184. package/dist/migrations.cjs.map +1 -1
  185. package/dist/migrations.mjs +4 -4
  186. package/dist/migrations.mjs.map +1 -1
  187. package/dist/migrations.test.cjs +6 -7
  188. package/dist/migrations.test.cjs.map +1 -1
  189. package/dist/migrations.test.mjs +7 -8
  190. package/dist/migrations.test.mjs.map +1 -1
  191. package/dist/port-scanner.cjs +2 -3
  192. package/dist/port-scanner.cjs.map +1 -1
  193. package/dist/port-scanner.d.mts.map +1 -1
  194. package/dist/port-scanner.mjs +1 -1
  195. package/dist/presets/presets.test.cjs +11 -8
  196. package/dist/presets/presets.test.cjs.map +1 -1
  197. package/dist/presets/presets.test.mjs +7 -4
  198. package/dist/presets/presets.test.mjs.map +1 -1
  199. package/dist/presets/registry.cjs +152 -3
  200. package/dist/presets/registry.cjs.map +1 -1
  201. package/dist/presets/registry.d.cts.map +1 -1
  202. package/dist/presets/registry.d.mts.map +1 -1
  203. package/dist/presets/registry.mjs +151 -1
  204. package/dist/presets/registry.mjs.map +1 -1
  205. package/dist/presets/registry.test.cjs +3 -4
  206. package/dist/presets/registry.test.cjs.map +1 -1
  207. package/dist/presets/registry.test.mjs +3 -4
  208. package/dist/presets/registry.test.mjs.map +1 -1
  209. package/dist/resolver.cjs +4 -5
  210. package/dist/resolver.cjs.map +1 -1
  211. package/dist/resolver.d.mts.map +1 -1
  212. package/dist/resolver.mjs +1 -2
  213. package/dist/resolver.mjs.map +1 -1
  214. package/dist/resolver.test.cjs +3 -4
  215. package/dist/resolver.test.cjs.map +1 -1
  216. package/dist/resolver.test.mjs +3 -4
  217. package/dist/resolver.test.mjs.map +1 -1
  218. package/dist/schema-C_hc7e4k.d.cts +898 -0
  219. package/dist/schema-C_hc7e4k.d.cts.map +1 -0
  220. package/dist/schema-CaesJaS2.d.mts +898 -0
  221. package/dist/schema-CaesJaS2.d.mts.map +1 -0
  222. package/dist/schema.cjs +15 -5
  223. package/dist/schema.cjs.map +1 -1
  224. package/dist/schema.d.cts +2 -854
  225. package/dist/schema.d.mts +2 -854
  226. package/dist/schema.mjs +13 -3
  227. package/dist/schema.mjs.map +1 -1
  228. package/dist/schema.test.cjs +3 -4
  229. package/dist/schema.test.cjs.map +1 -1
  230. package/dist/schema.test.mjs +3 -4
  231. package/dist/schema.test.mjs.map +1 -1
  232. package/dist/services/definitions/airbyte.cjs +76 -0
  233. package/dist/services/definitions/airbyte.cjs.map +1 -0
  234. package/dist/services/definitions/airbyte.d.cts +7 -0
  235. package/dist/services/definitions/airbyte.d.cts.map +1 -0
  236. package/dist/services/definitions/airbyte.d.mts +7 -0
  237. package/dist/services/definitions/airbyte.d.mts.map +1 -0
  238. package/dist/services/definitions/airbyte.mjs +75 -0
  239. package/dist/services/definitions/airbyte.mjs.map +1 -0
  240. package/dist/services/definitions/airflow.cjs +109 -0
  241. package/dist/services/definitions/airflow.cjs.map +1 -0
  242. package/dist/services/definitions/airflow.d.cts +7 -0
  243. package/dist/services/definitions/airflow.d.cts.map +1 -0
  244. package/dist/services/definitions/airflow.d.mts +7 -0
  245. package/dist/services/definitions/airflow.d.mts.map +1 -0
  246. package/dist/services/definitions/airflow.mjs +108 -0
  247. package/dist/services/definitions/airflow.mjs.map +1 -0
  248. package/dist/services/definitions/anything-llm.cjs +2 -3
  249. package/dist/services/definitions/anything-llm.cjs.map +1 -1
  250. package/dist/services/definitions/anything-llm.mjs +1 -1
  251. package/dist/services/definitions/appflowy.cjs +2 -3
  252. package/dist/services/definitions/appflowy.cjs.map +1 -1
  253. package/dist/services/definitions/appflowy.mjs +1 -1
  254. package/dist/services/definitions/appwrite.cjs +190 -0
  255. package/dist/services/definitions/appwrite.cjs.map +1 -0
  256. package/dist/services/definitions/appwrite.d.cts +7 -0
  257. package/dist/services/definitions/appwrite.d.cts.map +1 -0
  258. package/dist/services/definitions/appwrite.d.mts +7 -0
  259. package/dist/services/definitions/appwrite.d.mts.map +1 -0
  260. package/dist/services/definitions/appwrite.mjs +189 -0
  261. package/dist/services/definitions/appwrite.mjs.map +1 -0
  262. package/dist/services/definitions/authelia.cjs +145 -0
  263. package/dist/services/definitions/authelia.cjs.map +1 -0
  264. package/dist/services/definitions/authelia.d.cts +7 -0
  265. package/dist/services/definitions/authelia.d.cts.map +1 -0
  266. package/dist/services/definitions/authelia.d.mts +7 -0
  267. package/dist/services/definitions/authelia.d.mts.map +1 -0
  268. package/dist/services/definitions/authelia.mjs +144 -0
  269. package/dist/services/definitions/authelia.mjs.map +1 -0
  270. package/dist/services/definitions/authentik.cjs +2 -3
  271. package/dist/services/definitions/authentik.cjs.map +1 -1
  272. package/dist/services/definitions/authentik.mjs +1 -1
  273. package/dist/services/definitions/axolotl.cjs +67 -0
  274. package/dist/services/definitions/axolotl.cjs.map +1 -0
  275. package/dist/services/definitions/axolotl.d.cts +7 -0
  276. package/dist/services/definitions/axolotl.d.cts.map +1 -0
  277. package/dist/services/definitions/axolotl.d.mts +7 -0
  278. package/dist/services/definitions/axolotl.d.mts.map +1 -0
  279. package/dist/services/definitions/axolotl.mjs +66 -0
  280. package/dist/services/definitions/axolotl.mjs.map +1 -0
  281. package/dist/services/definitions/beszel.cjs +2 -3
  282. package/dist/services/definitions/beszel.cjs.map +1 -1
  283. package/dist/services/definitions/beszel.mjs +1 -1
  284. package/dist/services/definitions/browserless.cjs +2 -3
  285. package/dist/services/definitions/browserless.cjs.map +1 -1
  286. package/dist/services/definitions/browserless.mjs +1 -1
  287. package/dist/services/definitions/caddy.cjs +2 -3
  288. package/dist/services/definitions/caddy.cjs.map +1 -1
  289. package/dist/services/definitions/caddy.mjs +1 -1
  290. package/dist/services/definitions/cal-com.cjs +2 -3
  291. package/dist/services/definitions/cal-com.cjs.map +1 -1
  292. package/dist/services/definitions/cal-com.mjs +1 -1
  293. package/dist/services/definitions/chatwoot-worker.cjs +95 -0
  294. package/dist/services/definitions/chatwoot-worker.cjs.map +1 -0
  295. package/dist/services/definitions/chatwoot-worker.d.cts +7 -0
  296. package/dist/services/definitions/chatwoot-worker.d.cts.map +1 -0
  297. package/dist/services/definitions/chatwoot-worker.d.mts +7 -0
  298. package/dist/services/definitions/chatwoot-worker.d.mts.map +1 -0
  299. package/dist/services/definitions/chatwoot-worker.mjs +94 -0
  300. package/dist/services/definitions/chatwoot-worker.mjs.map +1 -0
  301. package/dist/services/definitions/chatwoot.cjs +112 -0
  302. package/dist/services/definitions/chatwoot.cjs.map +1 -0
  303. package/dist/services/definitions/chatwoot.d.cts +7 -0
  304. package/dist/services/definitions/chatwoot.d.cts.map +1 -0
  305. package/dist/services/definitions/chatwoot.d.mts +7 -0
  306. package/dist/services/definitions/chatwoot.d.mts.map +1 -0
  307. package/dist/services/definitions/chatwoot.mjs +111 -0
  308. package/dist/services/definitions/chatwoot.mjs.map +1 -0
  309. package/dist/services/definitions/chromadb.cjs +2 -3
  310. package/dist/services/definitions/chromadb.cjs.map +1 -1
  311. package/dist/services/definitions/chromadb.mjs +1 -1
  312. package/dist/services/definitions/claude-code.cjs +2 -3
  313. package/dist/services/definitions/claude-code.cjs.map +1 -1
  314. package/dist/services/definitions/claude-code.mjs +1 -1
  315. package/dist/services/definitions/code-server.cjs +2 -3
  316. package/dist/services/definitions/code-server.cjs.map +1 -1
  317. package/dist/services/definitions/code-server.mjs +1 -1
  318. package/dist/services/definitions/codex.cjs +2 -3
  319. package/dist/services/definitions/codex.cjs.map +1 -1
  320. package/dist/services/definitions/codex.mjs +1 -1
  321. package/dist/services/definitions/comfyui.cjs +2 -3
  322. package/dist/services/definitions/comfyui.cjs.map +1 -1
  323. package/dist/services/definitions/comfyui.mjs +1 -1
  324. package/dist/services/definitions/convex-dashboard.cjs +2 -3
  325. package/dist/services/definitions/convex-dashboard.cjs.map +1 -1
  326. package/dist/services/definitions/convex-dashboard.mjs +1 -1
  327. package/dist/services/definitions/convex.cjs +2 -3
  328. package/dist/services/definitions/convex.cjs.map +1 -1
  329. package/dist/services/definitions/convex.mjs +1 -1
  330. package/dist/services/definitions/coolify.cjs +2 -3
  331. package/dist/services/definitions/coolify.cjs.map +1 -1
  332. package/dist/services/definitions/coolify.mjs +1 -1
  333. package/dist/services/definitions/crowdsec.cjs +2 -3
  334. package/dist/services/definitions/crowdsec.cjs.map +1 -1
  335. package/dist/services/definitions/crowdsec.mjs +1 -1
  336. package/dist/services/definitions/dagster.cjs +83 -0
  337. package/dist/services/definitions/dagster.cjs.map +1 -0
  338. package/dist/services/definitions/dagster.d.cts +7 -0
  339. package/dist/services/definitions/dagster.d.cts.map +1 -0
  340. package/dist/services/definitions/dagster.d.mts +7 -0
  341. package/dist/services/definitions/dagster.d.mts.map +1 -0
  342. package/dist/services/definitions/dagster.mjs +82 -0
  343. package/dist/services/definitions/dagster.mjs.map +1 -0
  344. package/dist/services/definitions/desktop-environment.cjs +2 -3
  345. package/dist/services/definitions/desktop-environment.cjs.map +1 -1
  346. package/dist/services/definitions/desktop-environment.mjs +1 -1
  347. package/dist/services/definitions/dify.cjs +2 -3
  348. package/dist/services/definitions/dify.cjs.map +1 -1
  349. package/dist/services/definitions/dify.mjs +1 -1
  350. package/dist/services/definitions/directus.cjs +115 -0
  351. package/dist/services/definitions/directus.cjs.map +1 -0
  352. package/dist/services/definitions/directus.d.cts +7 -0
  353. package/dist/services/definitions/directus.d.cts.map +1 -0
  354. package/dist/services/definitions/directus.d.mts +7 -0
  355. package/dist/services/definitions/directus.d.mts.map +1 -0
  356. package/dist/services/definitions/directus.mjs +114 -0
  357. package/dist/services/definitions/directus.mjs.map +1 -0
  358. package/dist/services/definitions/docsgpt.cjs +2 -3
  359. package/dist/services/definitions/docsgpt.cjs.map +1 -1
  360. package/dist/services/definitions/docsgpt.mjs +1 -1
  361. package/dist/services/definitions/dokploy.cjs +2 -3
  362. package/dist/services/definitions/dokploy.cjs.map +1 -1
  363. package/dist/services/definitions/dokploy.mjs +1 -1
  364. package/dist/services/definitions/dozzle.cjs +2 -3
  365. package/dist/services/definitions/dozzle.cjs.map +1 -1
  366. package/dist/services/definitions/dozzle.mjs +1 -1
  367. package/dist/services/definitions/duplicati.cjs +76 -0
  368. package/dist/services/definitions/duplicati.cjs.map +1 -0
  369. package/dist/services/definitions/duplicati.d.cts +7 -0
  370. package/dist/services/definitions/duplicati.d.cts.map +1 -0
  371. package/dist/services/definitions/duplicati.d.mts +7 -0
  372. package/dist/services/definitions/duplicati.d.mts.map +1 -0
  373. package/dist/services/definitions/duplicati.mjs +75 -0
  374. package/dist/services/definitions/duplicati.mjs.map +1 -0
  375. package/dist/services/definitions/excalidraw.cjs +48 -0
  376. package/dist/services/definitions/excalidraw.cjs.map +1 -0
  377. package/dist/services/definitions/excalidraw.d.cts +7 -0
  378. package/dist/services/definitions/excalidraw.d.cts.map +1 -0
  379. package/dist/services/definitions/excalidraw.d.mts +7 -0
  380. package/dist/services/definitions/excalidraw.d.mts.map +1 -0
  381. package/dist/services/definitions/excalidraw.mjs +47 -0
  382. package/dist/services/definitions/excalidraw.mjs.map +1 -0
  383. package/dist/services/definitions/ffmpeg.cjs +2 -3
  384. package/dist/services/definitions/ffmpeg.cjs.map +1 -1
  385. package/dist/services/definitions/ffmpeg.mjs +1 -1
  386. package/dist/services/definitions/firecrawl-playwright.cjs +61 -0
  387. package/dist/services/definitions/firecrawl-playwright.cjs.map +1 -0
  388. package/dist/services/definitions/firecrawl-playwright.d.cts +7 -0
  389. package/dist/services/definitions/firecrawl-playwright.d.cts.map +1 -0
  390. package/dist/services/definitions/firecrawl-playwright.d.mts +7 -0
  391. package/dist/services/definitions/firecrawl-playwright.d.mts.map +1 -0
  392. package/dist/services/definitions/firecrawl-playwright.mjs +60 -0
  393. package/dist/services/definitions/firecrawl-playwright.mjs.map +1 -0
  394. package/dist/services/definitions/firecrawl.cjs +163 -0
  395. package/dist/services/definitions/firecrawl.cjs.map +1 -0
  396. package/dist/services/definitions/firecrawl.d.cts +7 -0
  397. package/dist/services/definitions/firecrawl.d.cts.map +1 -0
  398. package/dist/services/definitions/firecrawl.d.mts +7 -0
  399. package/dist/services/definitions/firecrawl.d.mts.map +1 -0
  400. package/dist/services/definitions/firecrawl.mjs +162 -0
  401. package/dist/services/definitions/firecrawl.mjs.map +1 -0
  402. package/dist/services/definitions/flagsmith.cjs +77 -0
  403. package/dist/services/definitions/flagsmith.cjs.map +1 -0
  404. package/dist/services/definitions/flagsmith.d.cts +7 -0
  405. package/dist/services/definitions/flagsmith.d.cts.map +1 -0
  406. package/dist/services/definitions/flagsmith.d.mts +7 -0
  407. package/dist/services/definitions/flagsmith.d.mts.map +1 -0
  408. package/dist/services/definitions/flagsmith.mjs +76 -0
  409. package/dist/services/definitions/flagsmith.mjs.map +1 -0
  410. package/dist/services/definitions/flowise.cjs +2 -3
  411. package/dist/services/definitions/flowise.cjs.map +1 -1
  412. package/dist/services/definitions/flowise.mjs +1 -1
  413. package/dist/services/definitions/fonoster.cjs +66 -0
  414. package/dist/services/definitions/fonoster.cjs.map +1 -0
  415. package/dist/services/definitions/fonoster.d.cts +7 -0
  416. package/dist/services/definitions/fonoster.d.cts.map +1 -0
  417. package/dist/services/definitions/fonoster.d.mts +7 -0
  418. package/dist/services/definitions/fonoster.d.mts.map +1 -0
  419. package/dist/services/definitions/fonoster.mjs +65 -0
  420. package/dist/services/definitions/fonoster.mjs.map +1 -0
  421. package/dist/services/definitions/formbricks.cjs +75 -0
  422. package/dist/services/definitions/formbricks.cjs.map +1 -0
  423. package/dist/services/definitions/formbricks.d.cts +7 -0
  424. package/dist/services/definitions/formbricks.d.cts.map +1 -0
  425. package/dist/services/definitions/formbricks.d.mts +7 -0
  426. package/dist/services/definitions/formbricks.d.mts.map +1 -0
  427. package/dist/services/definitions/formbricks.mjs +74 -0
  428. package/dist/services/definitions/formbricks.mjs.map +1 -0
  429. package/dist/services/definitions/gemini-cli.cjs +2 -3
  430. package/dist/services/definitions/gemini-cli.cjs.map +1 -1
  431. package/dist/services/definitions/gemini-cli.mjs +1 -1
  432. package/dist/services/definitions/ghost.cjs +2 -3
  433. package/dist/services/definitions/ghost.cjs.map +1 -1
  434. package/dist/services/definitions/ghost.mjs +1 -1
  435. package/dist/services/definitions/gitea.cjs +2 -3
  436. package/dist/services/definitions/gitea.cjs.map +1 -1
  437. package/dist/services/definitions/gitea.mjs +1 -1
  438. package/dist/services/definitions/gotify.cjs +2 -3
  439. package/dist/services/definitions/gotify.cjs.map +1 -1
  440. package/dist/services/definitions/gotify.mjs +1 -1
  441. package/dist/services/definitions/grafana.cjs +2 -3
  442. package/dist/services/definitions/grafana.cjs.map +1 -1
  443. package/dist/services/definitions/grafana.mjs +1 -1
  444. package/dist/services/definitions/headscale.cjs +2 -3
  445. package/dist/services/definitions/headscale.cjs.map +1 -1
  446. package/dist/services/definitions/headscale.mjs +1 -1
  447. package/dist/services/definitions/hedgedoc.cjs +82 -0
  448. package/dist/services/definitions/hedgedoc.cjs.map +1 -0
  449. package/dist/services/definitions/hedgedoc.d.cts +7 -0
  450. package/dist/services/definitions/hedgedoc.d.cts.map +1 -0
  451. package/dist/services/definitions/hedgedoc.d.mts +7 -0
  452. package/dist/services/definitions/hedgedoc.d.mts.map +1 -0
  453. package/dist/services/definitions/hedgedoc.mjs +81 -0
  454. package/dist/services/definitions/hedgedoc.mjs.map +1 -0
  455. package/dist/services/definitions/hexstrike.cjs +2 -3
  456. package/dist/services/definitions/hexstrike.cjs.map +1 -1
  457. package/dist/services/definitions/hexstrike.mjs +1 -1
  458. package/dist/services/definitions/heyform.cjs +64 -0
  459. package/dist/services/definitions/heyform.cjs.map +1 -0
  460. package/dist/services/definitions/heyform.d.cts +7 -0
  461. package/dist/services/definitions/heyform.d.cts.map +1 -0
  462. package/dist/services/definitions/heyform.d.mts +7 -0
  463. package/dist/services/definitions/heyform.d.mts.map +1 -0
  464. package/dist/services/definitions/heyform.mjs +63 -0
  465. package/dist/services/definitions/heyform.mjs.map +1 -0
  466. package/dist/services/definitions/homeassistant.cjs +2 -3
  467. package/dist/services/definitions/homeassistant.cjs.map +1 -1
  468. package/dist/services/definitions/homeassistant.mjs +1 -1
  469. package/dist/services/definitions/hoppscotch.cjs +76 -0
  470. package/dist/services/definitions/hoppscotch.cjs.map +1 -0
  471. package/dist/services/definitions/hoppscotch.d.cts +7 -0
  472. package/dist/services/definitions/hoppscotch.d.cts.map +1 -0
  473. package/dist/services/definitions/hoppscotch.d.mts +7 -0
  474. package/dist/services/definitions/hoppscotch.d.mts.map +1 -0
  475. package/dist/services/definitions/hoppscotch.mjs +75 -0
  476. package/dist/services/definitions/hoppscotch.mjs.map +1 -0
  477. package/dist/services/definitions/immich.cjs +2 -3
  478. package/dist/services/definitions/immich.cjs.map +1 -1
  479. package/dist/services/definitions/immich.mjs +1 -1
  480. package/dist/services/definitions/index.cjs +220 -98
  481. package/dist/services/definitions/index.cjs.map +1 -1
  482. package/dist/services/definitions/index.d.cts +42 -1
  483. package/dist/services/definitions/index.d.cts.map +1 -1
  484. package/dist/services/definitions/index.d.mts +42 -1
  485. package/dist/services/definitions/index.d.mts.map +1 -1
  486. package/dist/services/definitions/index.mjs +85 -4
  487. package/dist/services/definitions/index.mjs.map +1 -1
  488. package/dist/services/definitions/infisical.cjs +99 -0
  489. package/dist/services/definitions/infisical.cjs.map +1 -0
  490. package/dist/services/definitions/infisical.d.cts +7 -0
  491. package/dist/services/definitions/infisical.d.cts.map +1 -0
  492. package/dist/services/definitions/infisical.d.mts +7 -0
  493. package/dist/services/definitions/infisical.d.mts.map +1 -0
  494. package/dist/services/definitions/infisical.mjs +98 -0
  495. package/dist/services/definitions/infisical.mjs.map +1 -0
  496. package/dist/services/definitions/jellyfin.cjs +2 -3
  497. package/dist/services/definitions/jellyfin.cjs.map +1 -1
  498. package/dist/services/definitions/jellyfin.mjs +1 -1
  499. package/dist/services/definitions/jenkins.cjs +2 -3
  500. package/dist/services/definitions/jenkins.cjs.map +1 -1
  501. package/dist/services/definitions/jenkins.mjs +1 -1
  502. package/dist/services/definitions/keycloak.cjs +122 -0
  503. package/dist/services/definitions/keycloak.cjs.map +1 -0
  504. package/dist/services/definitions/keycloak.d.cts +7 -0
  505. package/dist/services/definitions/keycloak.d.cts.map +1 -0
  506. package/dist/services/definitions/keycloak.d.mts +7 -0
  507. package/dist/services/definitions/keycloak.d.mts.map +1 -0
  508. package/dist/services/definitions/keycloak.mjs +121 -0
  509. package/dist/services/definitions/keycloak.mjs.map +1 -0
  510. package/dist/services/definitions/kimi.cjs +2 -3
  511. package/dist/services/definitions/kimi.cjs.map +1 -1
  512. package/dist/services/definitions/kimi.mjs +1 -1
  513. package/dist/services/definitions/kong.cjs +121 -0
  514. package/dist/services/definitions/kong.cjs.map +1 -0
  515. package/dist/services/definitions/kong.d.cts +7 -0
  516. package/dist/services/definitions/kong.d.cts.map +1 -0
  517. package/dist/services/definitions/kong.d.mts +7 -0
  518. package/dist/services/definitions/kong.d.mts.map +1 -0
  519. package/dist/services/definitions/kong.mjs +120 -0
  520. package/dist/services/definitions/kong.mjs.map +1 -0
  521. package/dist/services/definitions/lago.cjs +95 -0
  522. package/dist/services/definitions/lago.cjs.map +1 -0
  523. package/dist/services/definitions/lago.d.cts +7 -0
  524. package/dist/services/definitions/lago.d.cts.map +1 -0
  525. package/dist/services/definitions/lago.d.mts +7 -0
  526. package/dist/services/definitions/lago.d.mts.map +1 -0
  527. package/dist/services/definitions/lago.mjs +94 -0
  528. package/dist/services/definitions/lago.mjs.map +1 -0
  529. package/dist/services/definitions/langflow.cjs +88 -0
  530. package/dist/services/definitions/langflow.cjs.map +1 -0
  531. package/dist/services/definitions/langflow.d.cts +7 -0
  532. package/dist/services/definitions/langflow.d.cts.map +1 -0
  533. package/dist/services/definitions/langflow.d.mts +7 -0
  534. package/dist/services/definitions/langflow.d.mts.map +1 -0
  535. package/dist/services/definitions/langflow.mjs +87 -0
  536. package/dist/services/definitions/langflow.mjs.map +1 -0
  537. package/dist/services/definitions/langfuse.cjs +79 -0
  538. package/dist/services/definitions/langfuse.cjs.map +1 -0
  539. package/dist/services/definitions/langfuse.d.cts +7 -0
  540. package/dist/services/definitions/langfuse.d.cts.map +1 -0
  541. package/dist/services/definitions/langfuse.d.mts +7 -0
  542. package/dist/services/definitions/langfuse.d.mts.map +1 -0
  543. package/dist/services/definitions/langfuse.mjs +78 -0
  544. package/dist/services/definitions/langfuse.mjs.map +1 -0
  545. package/dist/services/definitions/lasuite-meet-agents.cjs +2 -3
  546. package/dist/services/definitions/lasuite-meet-agents.cjs.map +1 -1
  547. package/dist/services/definitions/lasuite-meet-agents.mjs +1 -1
  548. package/dist/services/definitions/lasuite-meet-backend.cjs +2 -3
  549. package/dist/services/definitions/lasuite-meet-backend.cjs.map +1 -1
  550. package/dist/services/definitions/lasuite-meet-backend.mjs +1 -1
  551. package/dist/services/definitions/lasuite-meet-frontend.cjs +2 -3
  552. package/dist/services/definitions/lasuite-meet-frontend.cjs.map +1 -1
  553. package/dist/services/definitions/lasuite-meet-frontend.mjs +1 -1
  554. package/dist/services/definitions/librechat.cjs +2 -3
  555. package/dist/services/definitions/librechat.cjs.map +1 -1
  556. package/dist/services/definitions/librechat.mjs +1 -1
  557. package/dist/services/definitions/lightpanda.cjs +2 -3
  558. package/dist/services/definitions/lightpanda.cjs.map +1 -1
  559. package/dist/services/definitions/lightpanda.mjs +1 -1
  560. package/dist/services/definitions/listmonk.cjs +118 -0
  561. package/dist/services/definitions/listmonk.cjs.map +1 -0
  562. package/dist/services/definitions/listmonk.d.cts +7 -0
  563. package/dist/services/definitions/listmonk.d.cts.map +1 -0
  564. package/dist/services/definitions/listmonk.d.mts +7 -0
  565. package/dist/services/definitions/listmonk.d.mts.map +1 -0
  566. package/dist/services/definitions/listmonk.mjs +117 -0
  567. package/dist/services/definitions/listmonk.mjs.map +1 -0
  568. package/dist/services/definitions/litellm.cjs +2 -3
  569. package/dist/services/definitions/litellm.cjs.map +1 -1
  570. package/dist/services/definitions/litellm.mjs +1 -1
  571. package/dist/services/definitions/livekit.cjs +2 -3
  572. package/dist/services/definitions/livekit.cjs.map +1 -1
  573. package/dist/services/definitions/livekit.mjs +1 -1
  574. package/dist/services/definitions/loki.cjs +2 -3
  575. package/dist/services/definitions/loki.cjs.map +1 -1
  576. package/dist/services/definitions/loki.mjs +1 -1
  577. package/dist/services/definitions/mariadb.cjs +81 -0
  578. package/dist/services/definitions/mariadb.cjs.map +1 -0
  579. package/dist/services/definitions/mariadb.d.cts +7 -0
  580. package/dist/services/definitions/mariadb.d.cts.map +1 -0
  581. package/dist/services/definitions/mariadb.d.mts +7 -0
  582. package/dist/services/definitions/mariadb.d.mts.map +1 -0
  583. package/dist/services/definitions/mariadb.mjs +80 -0
  584. package/dist/services/definitions/mariadb.mjs.map +1 -0
  585. package/dist/services/definitions/matomo.cjs +2 -3
  586. package/dist/services/definitions/matomo.cjs.map +1 -1
  587. package/dist/services/definitions/matomo.mjs +1 -1
  588. package/dist/services/definitions/matrix-synapse.cjs +2 -3
  589. package/dist/services/definitions/matrix-synapse.cjs.map +1 -1
  590. package/dist/services/definitions/matrix-synapse.mjs +1 -1
  591. package/dist/services/definitions/mattermost.cjs +2 -3
  592. package/dist/services/definitions/mattermost.cjs.map +1 -1
  593. package/dist/services/definitions/mattermost.mjs +1 -1
  594. package/dist/services/definitions/mautic.cjs +83 -0
  595. package/dist/services/definitions/mautic.cjs.map +1 -0
  596. package/dist/services/definitions/mautic.d.cts +7 -0
  597. package/dist/services/definitions/mautic.d.cts.map +1 -0
  598. package/dist/services/definitions/mautic.d.mts +7 -0
  599. package/dist/services/definitions/mautic.d.mts.map +1 -0
  600. package/dist/services/definitions/mautic.mjs +82 -0
  601. package/dist/services/definitions/mautic.mjs.map +1 -0
  602. package/dist/services/definitions/medusa.cjs +83 -0
  603. package/dist/services/definitions/medusa.cjs.map +1 -0
  604. package/dist/services/definitions/medusa.d.cts +7 -0
  605. package/dist/services/definitions/medusa.d.cts.map +1 -0
  606. package/dist/services/definitions/medusa.d.mts +7 -0
  607. package/dist/services/definitions/medusa.d.mts.map +1 -0
  608. package/dist/services/definitions/medusa.mjs +82 -0
  609. package/dist/services/definitions/medusa.mjs.map +1 -0
  610. package/dist/services/definitions/meilisearch.cjs +2 -3
  611. package/dist/services/definitions/meilisearch.cjs.map +1 -1
  612. package/dist/services/definitions/meilisearch.mjs +1 -1
  613. package/dist/services/definitions/milvus.cjs +2 -3
  614. package/dist/services/definitions/milvus.cjs.map +1 -1
  615. package/dist/services/definitions/milvus.mjs +1 -1
  616. package/dist/services/definitions/minio.cjs +2 -3
  617. package/dist/services/definitions/minio.cjs.map +1 -1
  618. package/dist/services/definitions/minio.mjs +1 -1
  619. package/dist/services/definitions/mission-control.cjs +2 -3
  620. package/dist/services/definitions/mission-control.cjs.map +1 -1
  621. package/dist/services/definitions/mission-control.mjs +1 -1
  622. package/dist/services/definitions/mixpost.cjs +2 -3
  623. package/dist/services/definitions/mixpost.cjs.map +1 -1
  624. package/dist/services/definitions/mixpost.mjs +1 -1
  625. package/dist/services/definitions/motion-canvas.cjs +2 -3
  626. package/dist/services/definitions/motion-canvas.cjs.map +1 -1
  627. package/dist/services/definitions/motion-canvas.mjs +1 -1
  628. package/dist/services/definitions/mysql.cjs +81 -0
  629. package/dist/services/definitions/mysql.cjs.map +1 -0
  630. package/dist/services/definitions/mysql.d.cts +7 -0
  631. package/dist/services/definitions/mysql.d.cts.map +1 -0
  632. package/dist/services/definitions/mysql.d.mts +7 -0
  633. package/dist/services/definitions/mysql.d.mts.map +1 -0
  634. package/dist/services/definitions/mysql.mjs +80 -0
  635. package/dist/services/definitions/mysql.mjs.map +1 -0
  636. package/dist/services/definitions/n8n.cjs +2 -3
  637. package/dist/services/definitions/n8n.cjs.map +1 -1
  638. package/dist/services/definitions/n8n.mjs +1 -1
  639. package/dist/services/definitions/neo4j.cjs +2 -3
  640. package/dist/services/definitions/neo4j.cjs.map +1 -1
  641. package/dist/services/definitions/neo4j.mjs +1 -1
  642. package/dist/services/definitions/nextcloud.cjs +2 -3
  643. package/dist/services/definitions/nextcloud.cjs.map +1 -1
  644. package/dist/services/definitions/nextcloud.mjs +1 -1
  645. package/dist/services/definitions/nocodb.cjs +2 -3
  646. package/dist/services/definitions/nocodb.cjs.map +1 -1
  647. package/dist/services/definitions/nocodb.mjs +1 -1
  648. package/dist/services/definitions/ntfy.cjs +2 -3
  649. package/dist/services/definitions/ntfy.cjs.map +1 -1
  650. package/dist/services/definitions/ntfy.mjs +1 -1
  651. package/dist/services/definitions/ollama.cjs +2 -3
  652. package/dist/services/definitions/ollama.cjs.map +1 -1
  653. package/dist/services/definitions/ollama.mjs +1 -1
  654. package/dist/services/definitions/open-webui.cjs +2 -3
  655. package/dist/services/definitions/open-webui.cjs.map +1 -1
  656. package/dist/services/definitions/open-webui.mjs +1 -1
  657. package/dist/services/definitions/opencode.cjs +2 -3
  658. package/dist/services/definitions/opencode.cjs.map +1 -1
  659. package/dist/services/definitions/opencode.mjs +1 -1
  660. package/dist/services/definitions/openhands.cjs +58 -0
  661. package/dist/services/definitions/openhands.cjs.map +1 -0
  662. package/dist/services/definitions/openhands.d.cts +7 -0
  663. package/dist/services/definitions/openhands.d.cts.map +1 -0
  664. package/dist/services/definitions/openhands.d.mts +7 -0
  665. package/dist/services/definitions/openhands.d.mts.map +1 -0
  666. package/dist/services/definitions/openhands.mjs +57 -0
  667. package/dist/services/definitions/openhands.mjs.map +1 -0
  668. package/dist/services/definitions/openpanel.cjs +2 -3
  669. package/dist/services/definitions/openpanel.cjs.map +1 -1
  670. package/dist/services/definitions/openpanel.mjs +1 -1
  671. package/dist/services/definitions/opensearch.cjs +94 -0
  672. package/dist/services/definitions/opensearch.cjs.map +1 -0
  673. package/dist/services/definitions/opensearch.d.cts +7 -0
  674. package/dist/services/definitions/opensearch.d.cts.map +1 -0
  675. package/dist/services/definitions/opensearch.d.mts +7 -0
  676. package/dist/services/definitions/opensearch.d.mts.map +1 -0
  677. package/dist/services/definitions/opensearch.mjs +93 -0
  678. package/dist/services/definitions/opensearch.mjs.map +1 -0
  679. package/dist/services/definitions/outline.cjs +2 -3
  680. package/dist/services/definitions/outline.cjs.map +1 -1
  681. package/dist/services/definitions/outline.mjs +1 -1
  682. package/dist/services/definitions/paperless-ngx.cjs +2 -3
  683. package/dist/services/definitions/paperless-ngx.cjs.map +1 -1
  684. package/dist/services/definitions/paperless-ngx.mjs +1 -1
  685. package/dist/services/definitions/pentagi.cjs +2 -3
  686. package/dist/services/definitions/pentagi.cjs.map +1 -1
  687. package/dist/services/definitions/pentagi.mjs +1 -1
  688. package/dist/services/definitions/pentestagent.cjs +2 -3
  689. package/dist/services/definitions/pentestagent.cjs.map +1 -1
  690. package/dist/services/definitions/pentestagent.mjs +1 -1
  691. package/dist/services/definitions/playwright-server.cjs +2 -3
  692. package/dist/services/definitions/playwright-server.cjs.map +1 -1
  693. package/dist/services/definitions/playwright-server.mjs +1 -1
  694. package/dist/services/definitions/pocketbase.cjs +61 -0
  695. package/dist/services/definitions/pocketbase.cjs.map +1 -0
  696. package/dist/services/definitions/pocketbase.d.cts +7 -0
  697. package/dist/services/definitions/pocketbase.d.cts.map +1 -0
  698. package/dist/services/definitions/pocketbase.d.mts +7 -0
  699. package/dist/services/definitions/pocketbase.d.mts.map +1 -0
  700. package/dist/services/definitions/pocketbase.mjs +60 -0
  701. package/dist/services/definitions/pocketbase.mjs.map +1 -0
  702. package/dist/services/definitions/portainer.cjs +2 -3
  703. package/dist/services/definitions/portainer.cjs.map +1 -1
  704. package/dist/services/definitions/portainer.mjs +1 -1
  705. package/dist/services/definitions/postgresql.cjs +2 -3
  706. package/dist/services/definitions/postgresql.cjs.map +1 -1
  707. package/dist/services/definitions/postgresql.mjs +1 -1
  708. package/dist/services/definitions/postiz.cjs +2 -3
  709. package/dist/services/definitions/postiz.cjs.map +1 -1
  710. package/dist/services/definitions/postiz.mjs +1 -1
  711. package/dist/services/definitions/prometheus.cjs +2 -3
  712. package/dist/services/definitions/prometheus.cjs.map +1 -1
  713. package/dist/services/definitions/prometheus.mjs +1 -1
  714. package/dist/services/definitions/qdrant.cjs +2 -3
  715. package/dist/services/definitions/qdrant.cjs.map +1 -1
  716. package/dist/services/definitions/qdrant.mjs +1 -1
  717. package/dist/services/definitions/rabbitmq.cjs +80 -0
  718. package/dist/services/definitions/rabbitmq.cjs.map +1 -0
  719. package/dist/services/definitions/rabbitmq.d.cts +7 -0
  720. package/dist/services/definitions/rabbitmq.d.cts.map +1 -0
  721. package/dist/services/definitions/rabbitmq.d.mts +7 -0
  722. package/dist/services/definitions/rabbitmq.d.mts.map +1 -0
  723. package/dist/services/definitions/rabbitmq.mjs +79 -0
  724. package/dist/services/definitions/rabbitmq.mjs.map +1 -0
  725. package/dist/services/definitions/ragflow.cjs +192 -0
  726. package/dist/services/definitions/ragflow.cjs.map +1 -0
  727. package/dist/services/definitions/ragflow.d.cts +7 -0
  728. package/dist/services/definitions/ragflow.d.cts.map +1 -0
  729. package/dist/services/definitions/ragflow.d.mts +7 -0
  730. package/dist/services/definitions/ragflow.d.mts.map +1 -0
  731. package/dist/services/definitions/ragflow.mjs +191 -0
  732. package/dist/services/definitions/ragflow.mjs.map +1 -0
  733. package/dist/services/definitions/redis.cjs +2 -3
  734. package/dist/services/definitions/redis.cjs.map +1 -1
  735. package/dist/services/definitions/redis.mjs +1 -1
  736. package/dist/services/definitions/remotion.cjs +2 -3
  737. package/dist/services/definitions/remotion.cjs.map +1 -1
  738. package/dist/services/definitions/remotion.mjs +1 -1
  739. package/dist/services/definitions/restic.cjs +58 -0
  740. package/dist/services/definitions/restic.cjs.map +1 -0
  741. package/dist/services/definitions/restic.d.cts +7 -0
  742. package/dist/services/definitions/restic.d.cts.map +1 -0
  743. package/dist/services/definitions/restic.d.mts +7 -0
  744. package/dist/services/definitions/restic.d.mts.map +1 -0
  745. package/dist/services/definitions/restic.mjs +57 -0
  746. package/dist/services/definitions/restic.mjs.map +1 -0
  747. package/dist/services/definitions/rocketchat.cjs +2 -3
  748. package/dist/services/definitions/rocketchat.cjs.map +1 -1
  749. package/dist/services/definitions/rocketchat.mjs +1 -1
  750. package/dist/services/definitions/saleor.cjs +76 -0
  751. package/dist/services/definitions/saleor.cjs.map +1 -0
  752. package/dist/services/definitions/saleor.d.cts +7 -0
  753. package/dist/services/definitions/saleor.d.cts.map +1 -0
  754. package/dist/services/definitions/saleor.d.mts +7 -0
  755. package/dist/services/definitions/saleor.d.mts.map +1 -0
  756. package/dist/services/definitions/saleor.mjs +75 -0
  757. package/dist/services/definitions/saleor.mjs.map +1 -0
  758. package/dist/services/definitions/scrapling.cjs +2 -3
  759. package/dist/services/definitions/scrapling.cjs.map +1 -1
  760. package/dist/services/definitions/scrapling.mjs +1 -1
  761. package/dist/services/definitions/searxng.cjs +2 -3
  762. package/dist/services/definitions/searxng.cjs.map +1 -1
  763. package/dist/services/definitions/searxng.mjs +1 -1
  764. package/dist/services/definitions/signoz.cjs +2 -3
  765. package/dist/services/definitions/signoz.cjs.map +1 -1
  766. package/dist/services/definitions/signoz.mjs +1 -1
  767. package/dist/services/definitions/solidityguard.cjs +2 -3
  768. package/dist/services/definitions/solidityguard.cjs.map +1 -1
  769. package/dist/services/definitions/solidityguard.mjs +1 -1
  770. package/dist/services/definitions/stable-diffusion.cjs +2 -3
  771. package/dist/services/definitions/stable-diffusion.cjs.map +1 -1
  772. package/dist/services/definitions/stable-diffusion.mjs +1 -1
  773. package/dist/services/definitions/steel-browser.cjs +2 -3
  774. package/dist/services/definitions/steel-browser.cjs.map +1 -1
  775. package/dist/services/definitions/steel-browser.mjs +1 -1
  776. package/dist/services/definitions/stirling-pdf.cjs +74 -0
  777. package/dist/services/definitions/stirling-pdf.cjs.map +1 -0
  778. package/dist/services/definitions/stirling-pdf.d.cts +7 -0
  779. package/dist/services/definitions/stirling-pdf.d.cts.map +1 -0
  780. package/dist/services/definitions/stirling-pdf.d.mts +7 -0
  781. package/dist/services/definitions/stirling-pdf.d.mts.map +1 -0
  782. package/dist/services/definitions/stirling-pdf.mjs +73 -0
  783. package/dist/services/definitions/stirling-pdf.mjs.map +1 -0
  784. package/dist/services/definitions/strapi.cjs +124 -0
  785. package/dist/services/definitions/strapi.cjs.map +1 -0
  786. package/dist/services/definitions/strapi.d.cts +7 -0
  787. package/dist/services/definitions/strapi.d.cts.map +1 -0
  788. package/dist/services/definitions/strapi.d.mts +7 -0
  789. package/dist/services/definitions/strapi.d.mts.map +1 -0
  790. package/dist/services/definitions/strapi.mjs +123 -0
  791. package/dist/services/definitions/strapi.mjs.map +1 -0
  792. package/dist/services/definitions/stream-gateway.cjs +2 -3
  793. package/dist/services/definitions/stream-gateway.cjs.map +1 -1
  794. package/dist/services/definitions/stream-gateway.mjs +1 -1
  795. package/dist/services/definitions/supabase.cjs +2 -3
  796. package/dist/services/definitions/supabase.cjs.map +1 -1
  797. package/dist/services/definitions/supabase.mjs +1 -1
  798. package/dist/services/definitions/tailscale.cjs +2 -3
  799. package/dist/services/definitions/tailscale.cjs.map +1 -1
  800. package/dist/services/definitions/tailscale.mjs +1 -1
  801. package/dist/services/definitions/temporal.cjs +2 -3
  802. package/dist/services/definitions/temporal.cjs.map +1 -1
  803. package/dist/services/definitions/temporal.mjs +1 -1
  804. package/dist/services/definitions/traefik.cjs +2 -3
  805. package/dist/services/definitions/traefik.cjs.map +1 -1
  806. package/dist/services/definitions/traefik.mjs +1 -1
  807. package/dist/services/definitions/twenty.cjs +83 -0
  808. package/dist/services/definitions/twenty.cjs.map +1 -0
  809. package/dist/services/definitions/twenty.d.cts +7 -0
  810. package/dist/services/definitions/twenty.d.cts.map +1 -0
  811. package/dist/services/definitions/twenty.d.mts +7 -0
  812. package/dist/services/definitions/twenty.d.mts.map +1 -0
  813. package/dist/services/definitions/twenty.mjs +82 -0
  814. package/dist/services/definitions/twenty.mjs.map +1 -0
  815. package/dist/services/definitions/umami.cjs +2 -3
  816. package/dist/services/definitions/umami.cjs.map +1 -1
  817. package/dist/services/definitions/umami.mjs +1 -1
  818. package/dist/services/definitions/uptime-kuma.cjs +2 -3
  819. package/dist/services/definitions/uptime-kuma.cjs.map +1 -1
  820. package/dist/services/definitions/uptime-kuma.mjs +1 -1
  821. package/dist/services/definitions/usesend.cjs +2 -3
  822. package/dist/services/definitions/usesend.cjs.map +1 -1
  823. package/dist/services/definitions/usesend.mjs +1 -1
  824. package/dist/services/definitions/valkey.cjs +2 -3
  825. package/dist/services/definitions/valkey.cjs.map +1 -1
  826. package/dist/services/definitions/valkey.mjs +1 -1
  827. package/dist/services/definitions/vault.cjs +71 -0
  828. package/dist/services/definitions/vault.cjs.map +1 -0
  829. package/dist/services/definitions/vault.d.cts +7 -0
  830. package/dist/services/definitions/vault.d.cts.map +1 -0
  831. package/dist/services/definitions/vault.d.mts +7 -0
  832. package/dist/services/definitions/vault.d.mts.map +1 -0
  833. package/dist/services/definitions/vault.mjs +70 -0
  834. package/dist/services/definitions/vault.mjs.map +1 -0
  835. package/dist/services/definitions/vaultwarden.cjs +2 -3
  836. package/dist/services/definitions/vaultwarden.cjs.map +1 -1
  837. package/dist/services/definitions/vaultwarden.mjs +1 -1
  838. package/dist/services/definitions/watchtower.cjs +2 -3
  839. package/dist/services/definitions/watchtower.cjs.map +1 -1
  840. package/dist/services/definitions/watchtower.mjs +1 -1
  841. package/dist/services/definitions/weaviate.cjs +2 -3
  842. package/dist/services/definitions/weaviate.cjs.map +1 -1
  843. package/dist/services/definitions/weaviate.mjs +1 -1
  844. package/dist/services/definitions/whisper.cjs +2 -3
  845. package/dist/services/definitions/whisper.cjs.map +1 -1
  846. package/dist/services/definitions/whisper.mjs +1 -1
  847. package/dist/services/definitions/xyops.cjs +2 -3
  848. package/dist/services/definitions/xyops.cjs.map +1 -1
  849. package/dist/services/definitions/xyops.mjs +1 -1
  850. package/dist/services/registry.cjs +3 -4
  851. package/dist/services/registry.cjs.map +1 -1
  852. package/dist/services/registry.d.mts.map +1 -1
  853. package/dist/services/registry.mjs +1 -2
  854. package/dist/services/registry.mjs.map +1 -1
  855. package/dist/services/registry.test.cjs +3 -4
  856. package/dist/services/registry.test.cjs.map +1 -1
  857. package/dist/services/registry.test.mjs +3 -4
  858. package/dist/services/registry.test.mjs.map +1 -1
  859. package/dist/{manifest-4uLbISXV.cjs → skill-manifest--IgY9REK.cjs} +40 -10
  860. package/dist/skill-manifest--IgY9REK.cjs.map +1 -0
  861. package/dist/{manifest-B8UDsVlR.mjs → skill-manifest-BVUXU0__.mjs} +24 -5
  862. package/dist/skill-manifest-BVUXU0__.mjs.map +1 -0
  863. package/dist/skills/registry.cjs +262 -3
  864. package/dist/skills/registry.cjs.map +1 -1
  865. package/dist/skills/registry.d.cts.map +1 -1
  866. package/dist/skills/registry.d.mts.map +1 -1
  867. package/dist/skills/registry.mjs +261 -1
  868. package/dist/skills/registry.mjs.map +1 -1
  869. package/dist/skills/skill-manifest.cjs +5 -23
  870. package/dist/skills/skill-manifest.mjs +1 -19
  871. package/dist/skills-BlzpHmpH.cjs +620 -0
  872. package/dist/skills-BlzpHmpH.cjs.map +1 -0
  873. package/dist/types-CR83OJiq.d.cts +243 -0
  874. package/dist/types-CR83OJiq.d.cts.map +1 -0
  875. package/dist/types-zYjGTuyn.d.mts +243 -0
  876. package/dist/types-zYjGTuyn.d.mts.map +1 -0
  877. package/dist/types.cjs +79 -3
  878. package/dist/types.cjs.map +1 -1
  879. package/dist/types.d.cts +1 -1
  880. package/dist/types.d.mts +1 -1
  881. package/dist/types.mjs +78 -1
  882. package/dist/types.mjs.map +1 -1
  883. package/dist/validator.cjs +3 -4
  884. package/dist/validator.cjs.map +1 -1
  885. package/dist/validator.mjs +1 -2
  886. package/dist/validator.mjs.map +1 -1
  887. package/dist/validator.test.cjs +5 -6
  888. package/dist/validator.test.cjs.map +1 -1
  889. package/dist/validator.test.mjs +3 -4
  890. package/dist/validator.test.mjs.map +1 -1
  891. package/dist/version-manager.cjs +3 -4
  892. package/dist/version-manager.cjs.map +1 -1
  893. package/dist/version-manager.d.mts.map +1 -1
  894. package/dist/version-manager.mjs +1 -2
  895. package/dist/version-manager.mjs.map +1 -1
  896. package/dist/version-manager.test.cjs +5 -6
  897. package/dist/version-manager.test.cjs.map +1 -1
  898. package/dist/version-manager.test.mjs +3 -4
  899. package/dist/version-manager.test.mjs.map +1 -1
  900. package/dist/{vi.2VT5v0um-BmRMvymT.cjs → vi.2VT5v0um-CRqXre87.cjs} +82 -202
  901. package/dist/{vi.2VT5v0um-CFyDIn0m.mjs.map → vi.2VT5v0um-CRqXre87.cjs.map} +1 -1
  902. package/dist/{vi.2VT5v0um-CFyDIn0m.mjs → vi.2VT5v0um-DvC3SVNc.mjs} +67 -186
  903. package/dist/{vi.2VT5v0um-BmRMvymT.cjs.map → vi.2VT5v0um-DvC3SVNc.mjs.map} +1 -1
  904. package/package.json +4 -3
  905. package/src/deployers/coolify.ts +198 -103
  906. package/src/deployers/dokploy.ts +209 -55
  907. package/src/deployers/index.ts +1 -0
  908. package/src/deployers/strip-host-ports.test.ts +100 -0
  909. package/src/deployers/strip-host-ports.ts +187 -0
  910. package/src/deployers/types.ts +185 -1
  911. package/src/generators/postgres-init.ts +6 -0
  912. package/src/index.ts +19 -4
  913. package/src/presets/presets.test.ts +4 -0
  914. package/src/presets/registry.ts +88 -0
  915. package/src/schema.ts +11 -0
  916. package/src/services/definitions/airbyte.ts +75 -0
  917. package/src/services/definitions/airflow.ts +109 -0
  918. package/src/services/definitions/appwrite.ts +181 -0
  919. package/src/services/definitions/authelia.ts +145 -0
  920. package/src/services/definitions/axolotl.ts +65 -0
  921. package/src/services/definitions/chatwoot-worker.ts +93 -0
  922. package/src/services/definitions/chatwoot.ts +106 -0
  923. package/src/services/definitions/dagster.ts +82 -0
  924. package/src/services/definitions/directus.ts +115 -0
  925. package/src/services/definitions/duplicati.ts +77 -0
  926. package/src/services/definitions/excalidraw.ts +46 -0
  927. package/src/services/definitions/firecrawl-playwright.ts +62 -0
  928. package/src/services/definitions/firecrawl.ts +146 -0
  929. package/src/services/definitions/flagsmith.ts +76 -0
  930. package/src/services/definitions/fonoster.ts +67 -0
  931. package/src/services/definitions/formbricks.ts +75 -0
  932. package/src/services/definitions/hedgedoc.ts +81 -0
  933. package/src/services/definitions/heyform.ts +67 -0
  934. package/src/services/definitions/hoppscotch.ts +74 -0
  935. package/src/services/definitions/index.ts +124 -0
  936. package/src/services/definitions/infisical.ts +97 -0
  937. package/src/services/definitions/keycloak.ts +119 -0
  938. package/src/services/definitions/kong.ts +116 -0
  939. package/src/services/definitions/lago.ts +95 -0
  940. package/src/services/definitions/langflow.ts +82 -0
  941. package/src/services/definitions/langfuse.ts +76 -0
  942. package/src/services/definitions/listmonk.ts +118 -0
  943. package/src/services/definitions/mariadb.ts +82 -0
  944. package/src/services/definitions/mautic.ts +82 -0
  945. package/src/services/definitions/medusa.ts +82 -0
  946. package/src/services/definitions/mysql.ts +82 -0
  947. package/src/services/definitions/openhands.ts +60 -0
  948. package/src/services/definitions/opensearch.ts +95 -0
  949. package/src/services/definitions/pocketbase.ts +62 -0
  950. package/src/services/definitions/rabbitmq.ts +81 -0
  951. package/src/services/definitions/ragflow.ts +175 -0
  952. package/src/services/definitions/restic.ts +60 -0
  953. package/src/services/definitions/saleor.ts +75 -0
  954. package/src/services/definitions/stirling-pdf.ts +73 -0
  955. package/src/services/definitions/strapi.ts +124 -0
  956. package/src/services/definitions/twenty.ts +82 -0
  957. package/src/services/definitions/vault.ts +74 -0
  958. package/src/skills/manifest.json +8 -0
  959. package/src/skills/registry.ts +119 -0
  960. package/src/types.ts +91 -2
  961. package/tsconfig.tsbuildinfo +1 -0
  962. package/dist/chunk-C0xms8kb.cjs +0 -34
  963. package/dist/deployers/coolify.d.cts.map +0 -1
  964. package/dist/deployers/coolify.d.mts.map +0 -1
  965. package/dist/deployers/dokploy.d.cts.map +0 -1
  966. package/dist/deployers/dokploy.d.mts.map +0 -1
  967. package/dist/deployers/types.d.cts.map +0 -1
  968. package/dist/deployers/types.d.mts.map +0 -1
  969. package/dist/generators/skills.cjs.map +0 -1
  970. package/dist/manifest-4uLbISXV.cjs.map +0 -1
  971. package/dist/manifest-B8UDsVlR.mjs.map +0 -1
  972. package/dist/schema.d.cts.map +0 -1
  973. package/dist/schema.d.mts.map +0 -1
  974. package/dist/skills/skill-manifest.cjs.map +0 -1
  975. package/dist/skills/skill-manifest.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"composer.mjs","names":[],"sources":["../src/composer.ts"],"sourcesContent":["import { Scalar, stringify } from \"yaml\";\nimport { getDbRequirements } from \"./generators/postgres-init.js\";\nimport type {\n\tComposeOptions,\n\tOpenclawImageVariant,\n\tResolverOutput,\n\tServiceCategory,\n} from \"./types.js\";\n\n/** Maps image variant to the Docker image string. */\nconst IMAGE_VARIANTS: Record<OpenclawImageVariant, string> = {\n\tofficial: \"ghcr.io/openclaw/openclaw\",\n\tcoolify: \"coollabsio/openclaw\",\n\talpine: \"alpine/openclaw\",\n};\n\n/** Returns the OpenClaw image string with version tag for a given variant. */\nfunction getOpenclawImage(variant: OpenclawImageVariant, version: string): string {\n\tconst base = IMAGE_VARIANTS[variant];\n\t// Coolify and alpine images use :latest by default\n\tconst tag = variant === \"official\" ? version : \"latest\";\n\treturn `${base}:${tag}`;\n}\n\n/** Creates a YAML scalar that is always quoted — avoids YAML 1.1 bare `no` → false. */\nfunction quotedStr(value: string): Scalar {\n\tconst s = new Scalar(value);\n\ts.type = Scalar.QUOTE_DOUBLE;\n\treturn s;\n}\n\n// ── Public Types ────────────────────────────────────────────────────────────\n\nexport interface ComposeResult {\n\tfiles: Record<string, string>; // filename -> YAML content\n\tmainFile: string; // \"docker-compose.yml\"\n\tprofiles: string[]; // list of profiles used\n}\n\n// ── Category → Profile Mapping ──────────────────────────────────────────────\n\nconst CATEGORY_PROFILE_MAP: Partial<Record<ServiceCategory, { file: string; profile: string }>> = {\n\tai: { file: \"docker-compose.ai.yml\", profile: \"ai\" },\n\t\"ai-platform\": { file: \"docker-compose.ai.yml\", profile: \"ai\" },\n\tmedia: { file: \"docker-compose.media.yml\", profile: \"media\" },\n\tmonitoring: { file: \"docker-compose.monitoring.yml\", profile: \"monitoring\" },\n\tanalytics: { file: \"docker-compose.monitoring.yml\", profile: \"monitoring\" },\n\t\"dev-tools\": { file: \"docker-compose.tools.yml\", profile: \"tools\" },\n\t\"coding-agent\": { file: \"docker-compose.tools.yml\", profile: \"tools\" },\n\t\"social-media\": { file: \"docker-compose.social.yml\", profile: \"social\" },\n\tknowledge: { file: \"docker-compose.knowledge.yml\", profile: \"knowledge\" },\n\tcommunication: { file: \"docker-compose.communication.yml\", profile: \"communication\" },\n};\n\nconst YAML_OPTIONS = { lineWidth: 120, nullStr: \"\" };\n\n// ── Shared Gateway Builder ──────────────────────────────────────────────────\n\ninterface GatewayBuildResult {\n\tgatewayService: Record<string, unknown>;\n\tcliService: Record<string, unknown>;\n\tallVolumes: Set<string>;\n}\n\n/**\n * Builds the OpenClaw gateway and CLI service entries.\n * Matches the real OpenClaw docker-compose.yml structure:\n * - Bridge port 18790 for ACP/WebSocket\n * - Bind-mount volumes (not named volumes)\n * - Claude web-provider session env vars\n * - Gateway bind mode (--bind lan)\n * - CLI companion service with stdin/tty\n */\nfunction buildGatewayServices(\n\tresolved: ResolverOutput,\n\toptions: ComposeOptions,\n\tdependsOn?: Record<string, { condition: string }>,\n): GatewayBuildResult {\n\tconst allVolumes = new Set<string>();\n\n\t// Gateway environment\n\tconst gatewayEnv: Record<string, string> = {\n\t\tHOME: \"/home/node\",\n\t\tTERM: \"xterm-256color\",\n\t\tOPENCLAW_GATEWAY_TOKEN: \"${OPENCLAW_GATEWAY_TOKEN}\",\n\t\t// Claude web-provider session vars (optional, user fills in .env)\n\t\tCLAUDE_AI_SESSION_KEY: \"${CLAUDE_AI_SESSION_KEY}\",\n\t\tCLAUDE_WEB_SESSION_KEY: \"${CLAUDE_WEB_SESSION_KEY}\",\n\t\tCLAUDE_WEB_COOKIE: \"${CLAUDE_WEB_COOKIE}\",\n\t};\n\n\t// Add AI provider API keys to gateway environment\n\tconst providerKeys = [\n\t\t\"OPENAI_API_KEY\",\n\t\t\"ANTHROPIC_API_KEY\",\n\t\t\"GOOGLE_API_KEY\",\n\t\t\"XAI_API_KEY\",\n\t\t\"DEEPSEEK_API_KEY\",\n\t\t\"GROQ_API_KEY\",\n\t\t\"OPENROUTER_API_KEY\",\n\t\t\"MISTRAL_API_KEY\",\n\t\t\"TOGETHER_API_KEY\",\n\t\t\"OLLAMA_API_KEY\",\n\t];\n\tfor (const key of providerKeys) {\n\t\tgatewayEnv[key] = `\\${${key}}`;\n\t}\n\n\t// Gateway volumes (bind-mount style matching real docker-setup.sh)\n\tconst gatewayVolumes: string[] = [\n\t\t\"${OPENCLAW_CONFIG_DIR:-./openclaw/config}:/home/node/.openclaw\",\n\t\t\"${OPENCLAW_WORKSPACE_DIR:-./openclaw/workspace}:/home/node/.openclaw/workspace\",\n\t];\n\n\t// Collect env vars and volume mounts from companion services\n\tfor (const { definition: def } of resolved.services) {\n\t\tfor (const env of def.openclawEnvVars) {\n\t\t\tgatewayEnv[env.key] = env.secret ? `\\${${env.key}}` : env.defaultValue;\n\t\t}\n\t\tif (def.openclawVolumeMounts) {\n\t\t\tfor (const vol of def.openclawVolumeMounts) {\n\t\t\t\tconst isBindMount =\n\t\t\t\t\tvol.name.startsWith(\"./\") || vol.name.startsWith(\"/\") || vol.name.startsWith(\"~\");\n\t\t\t\tif (!isBindMount) {\n\t\t\t\t\tallVolumes.add(vol.name);\n\t\t\t\t}\n\t\t\t\tgatewayVolumes.push(`${vol.name}:${vol.containerPath}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Gateway service\n\tconst defaultImage = getOpenclawImage(\n\t\toptions.openclawImage ?? \"official\",\n\t\toptions.openclawVersion,\n\t);\n\tconst gateway: Record<string, unknown> = {\n\t\timage: `\\${OPENCLAW_IMAGE:-${defaultImage}}`,\n\t\tenvironment: gatewayEnv,\n\t\tvolumes: gatewayVolumes,\n\t\tports: [\"${OPENCLAW_GATEWAY_PORT:-18789}:18789\", \"${OPENCLAW_BRIDGE_PORT:-18790}:18790\"],\n\t\tnetworks: [\"openclaw-network\"],\n\t\tinit: true,\n\t\trestart: \"unless-stopped\",\n\t\tcommand: [\n\t\t\t\"node\",\n\t\t\t\"dist/index.js\",\n\t\t\t\"gateway\",\n\t\t\t\"--bind\",\n\t\t\t\"${OPENCLAW_GATEWAY_BIND:-lan}\",\n\t\t\t\"--port\",\n\t\t\t\"18789\",\n\t\t],\n\t};\n\n\t// Traefik labels for the gateway\n\tconst gwTraefikLabels = options.traefikLabels?.get(\"openclaw-gateway\");\n\tif (gwTraefikLabels) {\n\t\tgateway.labels = gwTraefikLabels;\n\t}\n\n\tif (options.bareMetalNativeHost) {\n\t\tgateway.extra_hosts = [\"host.docker.internal:host-gateway\"];\n\t}\n\n\tif (dependsOn && Object.keys(dependsOn).length > 0) {\n\t\tgateway.depends_on = dependsOn;\n\t}\n\n\t// CLI companion service (matching real OpenClaw docker-compose.yml)\n\t// Build CLI environment with same keys as gateway for consistency\n\tconst cliEnv: Record<string, string> = {\n\t\tHOME: \"/home/node\",\n\t\tTERM: \"xterm-256color\",\n\t\tOPENCLAW_GATEWAY_TOKEN: \"${OPENCLAW_GATEWAY_TOKEN}\",\n\t\t// Gateway connection: use Docker service name so CLI can reach the gateway over the bridge network\n\t\tOPENCLAW_GATEWAY_HOST: \"openclaw-gateway\",\n\t\tOPENCLAW_GATEWAY_PORT: \"18789\",\n\t\tBROWSER: \"echo\",\n\t\tCLAUDE_AI_SESSION_KEY: \"${CLAUDE_AI_SESSION_KEY}\",\n\t\tCLAUDE_WEB_SESSION_KEY: \"${CLAUDE_WEB_SESSION_KEY}\",\n\t\tCLAUDE_WEB_COOKIE: \"${CLAUDE_WEB_COOKIE}\",\n\t};\n\n\t// Add same AI provider API keys to CLI for direct AI interactions\n\tfor (const key of providerKeys) {\n\t\tcliEnv[key] = `\\${${key}}`;\n\t}\n\n\tconst cliService: Record<string, unknown> = {\n\t\timage: `\\${OPENCLAW_IMAGE:-${defaultImage}}`,\n\t\tenvironment: cliEnv,\n\t\tvolumes: [\n\t\t\t\"${OPENCLAW_CONFIG_DIR:-./openclaw/config}:/home/node/.openclaw\",\n\t\t\t\"${OPENCLAW_WORKSPACE_DIR:-./openclaw/workspace}:/home/node/.openclaw/workspace\",\n\t\t],\n\t\tstdin_open: true,\n\t\ttty: true,\n\t\tinit: true,\n\t\tnetworks: [\"openclaw-network\"],\n\t\tentrypoint: [\"node\", \"dist/index.js\"],\n\t\t// CLI is interactive — don't auto-restart, but wait for gateway to be ready\n\t\trestart: \"no\",\n\t\tdepends_on: {\n\t\t\t\"openclaw-gateway\": { condition: \"service_started\" },\n\t\t},\n\t};\n\n\treturn { gatewayService: gateway, cliService: cliService, allVolumes };\n}\n\n// ── Shared Companion Service Builder ────────────────────────────────────────\n\nfunction buildCompanionService(\n\tdef: ResolverOutput[\"services\"][number][\"definition\"],\n\tresolved: ResolverOutput,\n\toptions: ComposeOptions,\n\tallVolumes: Set<string>,\n): { entry: Record<string, unknown>; volumeNames: string[] } {\n\tconst svc: Record<string, unknown> = {};\n\tconst volumeNames: string[] = [];\n\n\tsvc.image = `${def.image}:${def.imageTag}`;\n\n\tif (def.environment.length > 0) {\n\t\tconst env: Record<string, string> = {};\n\t\tfor (const e of def.environment) {\n\t\t\tenv[e.key] = e.secret ? `\\${${e.key}}` : e.defaultValue;\n\t\t}\n\t\tsvc.environment = env;\n\t}\n\n\tconst exposedPorts = def.ports.filter((p) => p.exposed);\n\tif (exposedPorts.length > 0) {\n\t\tconst prefix = def.id.toUpperCase().replace(/-/g, \"_\");\n\t\tsvc.ports = exposedPorts.map((p, i) => {\n\t\t\tconst suffix = exposedPorts.length > 1 ? `_${i}` : \"\";\n\t\t\tlet defaultPort = p.host;\n\n\t\t\t// Override proxy ports if custom ports are specified\n\t\t\tif (\n\t\t\t\t(def.id === \"caddy\" || def.id === \"traefik\") &&\n\t\t\t\toptions.proxyHttpPort !== undefined &&\n\t\t\t\tp.container === 80\n\t\t\t) {\n\t\t\t\tdefaultPort = options.proxyHttpPort;\n\t\t\t}\n\t\t\tif (\n\t\t\t\t(def.id === \"caddy\" || def.id === \"traefik\") &&\n\t\t\t\toptions.proxyHttpsPort !== undefined &&\n\t\t\t\tp.container === 443\n\t\t\t) {\n\t\t\t\tdefaultPort = options.proxyHttpsPort;\n\t\t\t}\n\n\t\t\t// Apply global port overrides if specified\n\t\t\tif (options.portOverrides?.[def.id]?.[p.host] !== undefined) {\n\t\t\t\tdefaultPort = options.portOverrides?.[def.id]?.[p.host] || p.host;\n\t\t\t}\n\n\t\t\t// Use _EXTERNAL_PORT to avoid colliding with openclawEnvVars _PORT keys.\n\t\t\t// openclawEnvVars define the container port (e.g. GRAFANA_PORT=3000 for\n\t\t\t// internal Docker networking), while these are host port mappings (e.g. 3150).\n\t\t\t// Without this, GRAFANA_PORT=3000 from .env would override the default\n\t\t\t// 3150 in ${GRAFANA_PORT:-3150}:3000, mapping host port 3000 instead.\n\t\t\treturn `\\${${prefix}_EXTERNAL_PORT${suffix}:-${defaultPort}}:${p.container}`;\n\t\t});\n\t}\n\n\tif (def.volumes.length > 0) {\n\t\tsvc.volumes = def.volumes.map((v) => {\n\t\t\tconst isBindMount =\n\t\t\t\tv.name.startsWith(\"./\") || v.name.startsWith(\"/\") || v.name.startsWith(\"~\");\n\n\t\t\tif (!isBindMount) {\n\t\t\t\tallVolumes.add(v.name);\n\t\t\t\tvolumeNames.push(v.name);\n\t\t\t}\n\t\t\treturn `${v.name}:${v.containerPath}`;\n\t\t});\n\t}\n\n\t// PostgreSQL: mount the init script and pass per-service DB passwords\n\tif (def.id === \"postgresql\") {\n\t\tif (!svc.volumes) svc.volumes = [];\n\t\t(svc.volumes as string[]).push(\n\t\t\t\"./postgres/init-databases.sh:/docker-entrypoint-initdb.d/init-databases.sh:ro\",\n\t\t);\n\n\t\t// Pass per-service database password env vars so the init script can use them\n\t\tconst dbReqs = getDbRequirements(resolved);\n\t\tif (dbReqs.length > 0) {\n\t\t\tconst env = (svc.environment ?? {}) as Record<string, string>;\n\t\t\tfor (const req of dbReqs) {\n\t\t\t\tenv[req.passwordEnvVar] = `\\${${req.passwordEnvVar}}`;\n\t\t\t}\n\t\t\tsvc.environment = env;\n\t\t}\n\t}\n\n\tif (def.healthcheck) {\n\t\tconst hc: Record<string, unknown> = {\n\t\t\ttest: [\"CMD-SHELL\", def.healthcheck.test],\n\t\t\tinterval: def.healthcheck.interval,\n\t\t\ttimeout: def.healthcheck.timeout,\n\t\t\tretries: def.healthcheck.retries,\n\t\t};\n\t\tif (def.healthcheck.startPeriod) {\n\t\t\thc.start_period = def.healthcheck.startPeriod;\n\t\t}\n\t\tsvc.healthcheck = hc;\n\t}\n\n\tsvc.restart = def.restartPolicy;\n\tsvc.networks = def.networks;\n\n\tif (def.command) svc.command = def.command;\n\tif (def.entrypoint) svc.entrypoint = def.entrypoint;\n\n\t// Labels: merge static definition labels with dynamic Traefik labels\n\tconst mergedLabels: Record<string, string> = {};\n\tif (def.labels) Object.assign(mergedLabels, def.labels);\n\tconst traefikLabels = options.traefikLabels?.get(def.id);\n\tif (traefikLabels) Object.assign(mergedLabels, traefikLabels);\n\tif (Object.keys(mergedLabels).length > 0) svc.labels = mergedLabels;\n\n\t// Traefik: bind-mount static config and Docker socket\n\tif (def.id === \"traefik\" && options.traefikLabels) {\n\t\tif (!svc.volumes) svc.volumes = [];\n\t\t(svc.volumes as string[]).push(\n\t\t\t\"./traefik/traefik.yml:/etc/traefik/traefik.yml:ro\",\n\t\t\t\"/var/run/docker.sock:/var/run/docker.sock:ro\",\n\t\t);\n\t}\n\n\tlet deploy: Record<string, unknown> | undefined;\n\tif (def.deploy) {\n\t\tdeploy = JSON.parse(JSON.stringify(def.deploy)) as Record<string, unknown>;\n\t}\n\tif (options.gpu && def.gpuRequired) {\n\t\tconst base = deploy ?? {};\n\t\tconst resources = (base.resources ?? {}) as Record<string, unknown>;\n\t\tdeploy = {\n\t\t\t...base,\n\t\t\tresources: {\n\t\t\t\t...resources,\n\t\t\t\treservations: {\n\t\t\t\t\t...((resources.reservations as Record<string, unknown>) ?? {}),\n\t\t\t\t\tdevices: [{ driver: \"nvidia\", count: \"all\", capabilities: [\"gpu\"] }],\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\t// Memory limits from estimatedMemoryMB\n\tif (def.minMemoryMB && options.hardened) {\n\t\tconst base = deploy ?? {};\n\t\tconst resources = (base.resources ?? {}) as Record<string, unknown>;\n\t\tconst limits = (resources.limits as Record<string, unknown>) ?? {};\n\t\tdeploy = {\n\t\t\t...base,\n\t\t\tresources: {\n\t\t\t\t...resources,\n\t\t\t\tlimits: {\n\t\t\t\t\t...limits,\n\t\t\t\t\tmemory: `${def.minMemoryMB * 2}m`, // 2x min as safe limit\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\tif (deploy) svc.deploy = deploy;\n\n\t// Security hardening (when enabled)\n\tif (options.hardened) {\n\t\tsvc.cap_drop = [\"ALL\"];\n\t\tsvc.security_opt = [\"no-new-privileges:true\"];\n\n\t\t// Services that need specific capabilities\n\t\tconst capAddMap: Record<string, string[]> = {\n\t\t\tcaddy: [\"NET_BIND_SERVICE\"],\n\t\t\ttraefik: [\"NET_BIND_SERVICE\"],\n\t\t\tcrowdsec: [\"NET_BIND_SERVICE\", \"DAC_READ_SEARCH\"],\n\t\t};\n\t\tif (capAddMap[def.id]) {\n\t\t\tsvc.cap_add = capAddMap[def.id];\n\t\t}\n\t}\n\n\t// Merge both dependsOn and requires to ensure proper Docker startup ordering\n\tconst depIds = [...new Set([...def.dependsOn, ...def.requires])].filter((id) =>\n\t\tresolved.services.some((s) => s.definition.id === id),\n\t);\n\tif (depIds.length > 0) {\n\t\tconst dependsOn: Record<string, { condition: string }> = {};\n\t\tfor (const depId of depIds) {\n\t\t\tconst dep = resolved.services.find((s) => s.definition.id === depId);\n\t\t\tdependsOn[depId] = {\n\t\t\t\tcondition: dep?.definition.healthcheck ? \"service_healthy\" : \"service_started\",\n\t\t\t};\n\t\t}\n\t\tsvc.depends_on = dependsOn;\n\t}\n\n\treturn { entry: svc, volumeNames };\n}\n\n// ── PostgreSQL Setup Init Container ─────────────────────────────────────────\n\n/**\n * Builds a one-shot init container that creates databases and users for\n * services that need their own PostgreSQL database. Runs AFTER PostgreSQL\n * is healthy, on every `docker compose up`, and is idempotent.\n *\n * Uses standard PG* environment variables (PGHOST, PGUSER, PGDATABASE,\n * PGPASSWORD) so psql/createuser/createdb automatically connect without\n * needing explicit -h/-U/-d flags — simpler and avoids YAML escaping issues.\n *\n * Returns null when no setup is needed (no PostgreSQL or no DB requirements).\n */\nfunction buildPostgresSetup(resolved: ResolverOutput): Record<string, unknown> | null {\n\tconst hasPostgres = resolved.services.some((s) => s.definition.id === \"postgresql\");\n\tif (!hasPostgres) return null;\n\n\tconst dbReqs = getDbRequirements(resolved);\n\tif (dbReqs.length === 0) return null;\n\n\t// Build a shell script with one command per line.\n\t// Uses $$ to escape $ from Docker Compose's variable substitution —\n\t// Docker Compose converts $$ → $ before passing to the container.\n\t// NO set -e: we handle errors explicitly so one failed service doesn't block others.\n\tconst scriptLines = [\"echo '=== PostgreSQL database setup ==='\", \"FAILED=0\"];\n\n\tfor (const req of dbReqs) {\n\t\t// Each service's setup is wrapped so a failure doesn't block the others.\n\t\t// Uses psql -v ON_ERROR_STOP=0 so SQL errors don't abort psql.\n\t\tscriptLines.push(\n\t\t\t`echo \"Setting up database '${req.dbName}' with user '${req.dbUser}'...\"`,\n\t\t\t// Create user if not exists (pure SQL, no createuser binary quirks)\n\t\t\t`psql -c \"SELECT 1 FROM pg_roles WHERE rolname='${req.dbUser}'\" | grep -q 1 || psql -c \"CREATE ROLE ${req.dbUser} WITH LOGIN PASSWORD '$$${req.passwordEnvVar}'\"`,\n\t\t\t// Always sync the password to match current env\n\t\t\t`psql -c \"ALTER ROLE ${req.dbUser} WITH LOGIN PASSWORD '$$${req.passwordEnvVar}'\"`,\n\t\t\t// Create database if not exists\n\t\t\t`psql -tc \"SELECT 1 FROM pg_database WHERE datname='${req.dbName}'\" | grep -q 1 || psql -c \"CREATE DATABASE ${req.dbName} OWNER ${req.dbUser}\"`,\n\t\t\t// Grant privileges (idempotent)\n\t\t\t`psql -c \"GRANT ALL PRIVILEGES ON DATABASE ${req.dbName} TO ${req.dbUser}\" || FAILED=1`,\n\t\t\t`echo \" Done: ${req.dbName}\"`,\n\t\t);\n\t}\n\n\tscriptLines.push(\"echo '=== All databases ready ==='\", \"exit $$FAILED\");\n\n\t// Standard PG* env vars: psql/createuser/createdb use these automatically\n\tconst env: Record<string, string> = {\n\t\tPGHOST: \"postgresql\",\n\t\tPGUSER: \"${POSTGRES_USER:-openclaw}\",\n\t\tPGDATABASE: \"${POSTGRES_DB:-openclaw}\",\n\t\tPGPASSWORD: \"${POSTGRES_PASSWORD}\",\n\t};\n\tfor (const req of dbReqs) {\n\t\tenv[req.passwordEnvVar] = `\\${${req.passwordEnvVar}}`;\n\t}\n\n\treturn {\n\t\timage: \"postgres:17-alpine\",\n\t\tdepends_on: {\n\t\t\tpostgresql: { condition: \"service_healthy\" },\n\t\t},\n\t\tenvironment: env,\n\t\t// command MUST be a single-element array so the entire script is passed\n\t\t// as ONE argument to `sh -c`. A plain string gets shlex-split by Docker\n\t\t// Compose into multiple args, breaking multi-line scripts.\n\t\tentrypoint: [\"/bin/sh\", \"-c\"],\n\t\tcommand: [scriptLines.join(\"\\n\")],\n\t\trestart: quotedStr(\"no\"),\n\t\tnetworks: [\"openclaw-network\"],\n\t};\n}\n\n// ── Single-File Compose ─────────────────────────────────────────────────────\n\n/**\n * Generates a single Docker Compose YAML string with ALL services.\n * Backward-compatible signature.\n */\nexport function compose(resolved: ResolverOutput, options: ComposeOptions): string {\n\tconst isDirectInstall = options.openclawInstallMethod === \"direct\";\n\n\t// Build depends_on for ALL companion services\n\tconst gatewayDependsOn: Record<string, { condition: string }> = {};\n\tfor (const { definition: def } of resolved.services) {\n\t\tgatewayDependsOn[def.id] = {\n\t\t\tcondition: def.healthcheck ? \"service_healthy\" : \"service_started\",\n\t\t};\n\t}\n\n\tconst services: Record<string, Record<string, unknown>> = {};\n\tlet allVolumes = new Set<string>();\n\n\tif (!isDirectInstall) {\n\t\tconst {\n\t\t\tgatewayService,\n\t\t\tcliService,\n\t\t\tallVolumes: gwVolumes,\n\t\t} = buildGatewayServices(resolved, options, gatewayDependsOn);\n\t\tallVolumes = gwVolumes;\n\t\tservices[\"openclaw-gateway\"] = gatewayService;\n\t\t// CLI service added after companions\n\t\t// Determine which services need DB setup so we can redirect their depends_on\n\t\tconst dbReqs = getDbRequirements(resolved);\n\t\tconst dbServiceIds = new Set(dbReqs.map((r) => r.serviceId));\n\n\t\tfor (const { definition: def } of resolved.services) {\n\t\t\tconst { entry } = buildCompanionService(def, resolved, options, allVolumes);\n\t\t\tif (dbServiceIds.has(def.id) && entry.depends_on) {\n\t\t\t\tconst deps = entry.depends_on as Record<string, { condition: string }>;\n\t\t\t\tif (deps.postgresql) {\n\t\t\t\t\tdelete deps.postgresql;\n\t\t\t\t\tdeps[\"postgres-setup\"] = { condition: \"service_completed_successfully\" };\n\t\t\t\t}\n\t\t\t}\n\t\t\tservices[def.id] = entry;\n\t\t}\n\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tservices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\n\t\tservices[\"openclaw-cli\"] = cliService;\n\t} else {\n\t\t// Direct install: no gateway/CLI containers, just companion services\n\t\tconst dbReqs = getDbRequirements(resolved);\n\t\tconst dbServiceIds = new Set(dbReqs.map((r) => r.serviceId));\n\n\t\tfor (const { definition: def } of resolved.services) {\n\t\t\tconst { entry } = buildCompanionService(def, resolved, options, allVolumes);\n\t\t\tif (dbServiceIds.has(def.id) && entry.depends_on) {\n\t\t\t\tconst deps = entry.depends_on as Record<string, { condition: string }>;\n\t\t\t\tif (deps.postgresql) {\n\t\t\t\t\tdelete deps.postgresql;\n\t\t\t\t\tdeps[\"postgres-setup\"] = { condition: \"service_completed_successfully\" };\n\t\t\t\t}\n\t\t\t}\n\t\t\tservices[def.id] = entry;\n\t\t}\n\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tservices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\t}\n\n\tconst volumes: Record<string, null> = {};\n\tfor (const v of [...allVolumes].sort()) {\n\t\tvolumes[v] = null;\n\t}\n\n\tconst networks = { \"openclaw-network\": { driver: \"bridge\" } };\n\n\treturn stringify({ services, volumes, networks }, YAML_OPTIONS);\n}\n\n// ── Multi-File Compose ──────────────────────────────────────────────────────\n\ninterface ServiceInfo {\n\tid: string;\n\tcategory: ServiceCategory;\n\tentry: Record<string, unknown>;\n\tvolumeNames: string[];\n}\n\n/**\n * Generates multiple Docker Compose files, splitting services into profile-based\n * override files by category.\n */\nexport function composeMultiFile(resolved: ResolverOutput, options: ComposeOptions): ComposeResult {\n\tconst isDirectInstall = options.openclawInstallMethod === \"direct\";\n\tconst allVolumes = new Set<string>();\n\n\t// Build all companion service entries & classify by category\n\tconst serviceInfos: ServiceInfo[] = [];\n\tconst dbReqs = getDbRequirements(resolved);\n\tconst dbServiceIds = new Set(dbReqs.map((r) => r.serviceId));\n\n\tfor (const { definition: def } of resolved.services) {\n\t\tconst { entry, volumeNames } = buildCompanionService(def, resolved, options, allVolumes);\n\t\t// Redirect DB-dependent services to depend on postgres-setup\n\t\tif (dbServiceIds.has(def.id) && entry.depends_on) {\n\t\t\tconst deps = entry.depends_on as Record<string, { condition: string }>;\n\t\t\tif (deps.postgresql) {\n\t\t\t\tdelete deps.postgresql;\n\t\t\t\tdeps[\"postgres-setup\"] = { condition: \"service_completed_successfully\" };\n\t\t\t}\n\t\t}\n\t\tserviceInfos.push({ id: def.id, category: def.category, entry, volumeNames });\n\t}\n\n\t// Partition services into base vs. profile files\n\tconst baseServiceIds = new Set<string>();\n\tconst profileFileMap: Record<string, { profile: string; services: ServiceInfo[] }> = {};\n\n\tfor (const info of serviceInfos) {\n\t\tconst mapping = CATEGORY_PROFILE_MAP[info.category];\n\t\tif (mapping) {\n\t\t\tif (!profileFileMap[mapping.file]) {\n\t\t\t\tprofileFileMap[mapping.file] = { profile: mapping.profile, services: [] };\n\t\t\t}\n\t\t\tprofileFileMap[mapping.file]!.services.push(info);\n\t\t} else {\n\t\t\tbaseServiceIds.add(info.id);\n\t\t}\n\t}\n\n\tconst baseServices: Record<string, Record<string, unknown>> = {};\n\n\tif (!isDirectInstall) {\n\t\t// Gateway depends_on (only base services)\n\t\tconst gatewayDependsOn: Record<string, { condition: string }> = {};\n\t\tfor (const { definition: def } of resolved.services) {\n\t\t\tif (baseServiceIds.has(def.id)) {\n\t\t\t\tgatewayDependsOn[def.id] = {\n\t\t\t\t\tcondition: def.healthcheck ? \"service_healthy\" : \"service_started\",\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tconst {\n\t\t\tgatewayService,\n\t\t\tcliService,\n\t\t\tallVolumes: gwVolumes,\n\t\t} = buildGatewayServices(resolved, options, gatewayDependsOn);\n\n\t\t// Merge gateway volumes into allVolumes\n\t\tfor (const v of gwVolumes) allVolumes.add(v);\n\n\t\tbaseServices[\"openclaw-gateway\"] = gatewayService;\n\n\t\tfor (const info of serviceInfos) {\n\t\t\tif (baseServiceIds.has(info.id)) {\n\t\t\t\tbaseServices[info.id] = info.entry;\n\t\t\t}\n\t\t}\n\n\t\t// Add postgres-setup init container if needed\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tbaseServices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\n\t\tbaseServices[\"openclaw-cli\"] = cliService;\n\t} else {\n\t\t// Direct install: no gateway/CLI containers\n\t\tfor (const info of serviceInfos) {\n\t\t\tif (baseServiceIds.has(info.id)) {\n\t\t\t\tbaseServices[info.id] = info.entry;\n\t\t\t}\n\t\t}\n\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tbaseServices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\t}\n\n\tconst sortedAllVolumes: Record<string, null> = {};\n\tfor (const v of [...allVolumes].sort()) {\n\t\tsortedAllVolumes[v] = null;\n\t}\n\n\tconst networks = { \"openclaw-network\": { driver: \"bridge\" } };\n\n\tconst files: Record<string, string> = {};\n\tfiles[\"docker-compose.yml\"] = stringify(\n\t\t{ services: baseServices, volumes: sortedAllVolumes, networks },\n\t\tYAML_OPTIONS,\n\t);\n\n\t// Profile override files\n\tconst usedProfiles = new Set<string>();\n\n\tfor (const [fileName, { profile, services }] of Object.entries(profileFileMap)) {\n\t\tusedProfiles.add(profile);\n\n\t\tconst profileServices: Record<string, Record<string, unknown>> = {};\n\t\tconst profileVolumes = new Set<string>();\n\n\t\tfor (const info of services) {\n\t\t\tprofileServices[info.id] = { ...info.entry, profiles: [profile] };\n\t\t\tfor (const vName of info.volumeNames) {\n\t\t\t\tprofileVolumes.add(vName);\n\t\t\t}\n\t\t}\n\n\t\tconst fileContent: Record<string, unknown> = { services: profileServices };\n\n\t\tif (profileVolumes.size > 0) {\n\t\t\tconst sortedProfileVolumes: Record<string, null> = {};\n\t\t\tfor (const v of [...profileVolumes].sort()) {\n\t\t\t\tsortedProfileVolumes[v] = null;\n\t\t\t}\n\t\t\tfileContent.volumes = sortedProfileVolumes;\n\t\t}\n\n\t\tfiles[fileName] = stringify(fileContent, YAML_OPTIONS);\n\t}\n\n\treturn {\n\t\tfiles,\n\t\tmainFile: \"docker-compose.yml\",\n\t\tprofiles: [...usedProfiles].sort(),\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"composer.mjs","names":[],"sources":["../src/composer.ts"],"sourcesContent":["import { Scalar, stringify } from \"yaml\";\nimport { getDbRequirements } from \"./generators/postgres-init.js\";\nimport type {\n\tComposeOptions,\n\tOpenclawImageVariant,\n\tResolverOutput,\n\tServiceCategory,\n} from \"./types.js\";\n\n/** Maps image variant to the Docker image string. */\nconst IMAGE_VARIANTS: Record<OpenclawImageVariant, string> = {\n\tofficial: \"ghcr.io/openclaw/openclaw\",\n\tcoolify: \"coollabsio/openclaw\",\n\talpine: \"alpine/openclaw\",\n};\n\n/** Returns the OpenClaw image string with version tag for a given variant. */\nfunction getOpenclawImage(variant: OpenclawImageVariant, version: string): string {\n\tconst base = IMAGE_VARIANTS[variant];\n\t// Coolify and alpine images use :latest by default\n\tconst tag = variant === \"official\" ? version : \"latest\";\n\treturn `${base}:${tag}`;\n}\n\n/** Creates a YAML scalar that is always quoted — avoids YAML 1.1 bare `no` → false. */\nfunction quotedStr(value: string): Scalar {\n\tconst s = new Scalar(value);\n\ts.type = Scalar.QUOTE_DOUBLE;\n\treturn s;\n}\n\n// ── Public Types ────────────────────────────────────────────────────────────\n\nexport interface ComposeResult {\n\tfiles: Record<string, string>; // filename -> YAML content\n\tmainFile: string; // \"docker-compose.yml\"\n\tprofiles: string[]; // list of profiles used\n}\n\n// ── Category → Profile Mapping ──────────────────────────────────────────────\n\nconst CATEGORY_PROFILE_MAP: Partial<Record<ServiceCategory, { file: string; profile: string }>> = {\n\tai: { file: \"docker-compose.ai.yml\", profile: \"ai\" },\n\t\"ai-platform\": { file: \"docker-compose.ai.yml\", profile: \"ai\" },\n\tmedia: { file: \"docker-compose.media.yml\", profile: \"media\" },\n\tmonitoring: { file: \"docker-compose.monitoring.yml\", profile: \"monitoring\" },\n\tanalytics: { file: \"docker-compose.monitoring.yml\", profile: \"monitoring\" },\n\t\"dev-tools\": { file: \"docker-compose.tools.yml\", profile: \"tools\" },\n\t\"coding-agent\": { file: \"docker-compose.tools.yml\", profile: \"tools\" },\n\t\"social-media\": { file: \"docker-compose.social.yml\", profile: \"social\" },\n\tknowledge: { file: \"docker-compose.knowledge.yml\", profile: \"knowledge\" },\n\tcommunication: { file: \"docker-compose.communication.yml\", profile: \"communication\" },\n};\n\nconst YAML_OPTIONS = { lineWidth: 120, nullStr: \"\" };\n\n// ── Shared Gateway Builder ──────────────────────────────────────────────────\n\ninterface GatewayBuildResult {\n\tgatewayService: Record<string, unknown>;\n\tcliService: Record<string, unknown>;\n\tallVolumes: Set<string>;\n}\n\n/**\n * Builds the OpenClaw gateway and CLI service entries.\n * Matches the real OpenClaw docker-compose.yml structure:\n * - Bridge port 18790 for ACP/WebSocket\n * - Bind-mount volumes (not named volumes)\n * - Claude web-provider session env vars\n * - Gateway bind mode (--bind lan)\n * - CLI companion service with stdin/tty\n */\nfunction buildGatewayServices(\n\tresolved: ResolverOutput,\n\toptions: ComposeOptions,\n\tdependsOn?: Record<string, { condition: string }>,\n): GatewayBuildResult {\n\tconst allVolumes = new Set<string>();\n\n\t// Gateway environment\n\tconst gatewayEnv: Record<string, string> = {\n\t\tHOME: \"/home/node\",\n\t\tTERM: \"xterm-256color\",\n\t\tOPENCLAW_GATEWAY_TOKEN: \"${OPENCLAW_GATEWAY_TOKEN}\",\n\t\t// Claude web-provider session vars (optional, user fills in .env)\n\t\tCLAUDE_AI_SESSION_KEY: \"${CLAUDE_AI_SESSION_KEY}\",\n\t\tCLAUDE_WEB_SESSION_KEY: \"${CLAUDE_WEB_SESSION_KEY}\",\n\t\tCLAUDE_WEB_COOKIE: \"${CLAUDE_WEB_COOKIE}\",\n\t};\n\n\t// Add AI provider API keys to gateway environment\n\tconst providerKeys = [\n\t\t\"OPENAI_API_KEY\",\n\t\t\"ANTHROPIC_API_KEY\",\n\t\t\"GOOGLE_API_KEY\",\n\t\t\"XAI_API_KEY\",\n\t\t\"DEEPSEEK_API_KEY\",\n\t\t\"GROQ_API_KEY\",\n\t\t\"OPENROUTER_API_KEY\",\n\t\t\"MISTRAL_API_KEY\",\n\t\t\"TOGETHER_API_KEY\",\n\t\t\"OLLAMA_API_KEY\",\n\t];\n\tfor (const key of providerKeys) {\n\t\tgatewayEnv[key] = `\\${${key}}`;\n\t}\n\n\t// Gateway volumes (bind-mount style matching real docker-setup.sh)\n\tconst gatewayVolumes: string[] = [\n\t\t\"${OPENCLAW_CONFIG_DIR:-./openclaw/config}:/home/node/.openclaw\",\n\t\t\"${OPENCLAW_WORKSPACE_DIR:-./openclaw/workspace}:/home/node/.openclaw/workspace\",\n\t];\n\n\t// Collect env vars and volume mounts from companion services\n\tfor (const { definition: def } of resolved.services) {\n\t\tfor (const env of def.openclawEnvVars) {\n\t\t\tgatewayEnv[env.key] = env.secret ? `\\${${env.key}}` : env.defaultValue;\n\t\t}\n\t\tif (def.openclawVolumeMounts) {\n\t\t\tfor (const vol of def.openclawVolumeMounts) {\n\t\t\t\tconst isBindMount =\n\t\t\t\t\tvol.name.startsWith(\"./\") || vol.name.startsWith(\"/\") || vol.name.startsWith(\"~\");\n\t\t\t\tif (!isBindMount) {\n\t\t\t\t\tallVolumes.add(vol.name);\n\t\t\t\t}\n\t\t\t\tgatewayVolumes.push(`${vol.name}:${vol.containerPath}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Gateway service\n\tconst defaultImage = getOpenclawImage(\n\t\toptions.openclawImage ?? \"official\",\n\t\toptions.openclawVersion,\n\t);\n\tconst gateway: Record<string, unknown> = {\n\t\timage: `\\${OPENCLAW_IMAGE:-${defaultImage}}`,\n\t\tenvironment: gatewayEnv,\n\t\tvolumes: gatewayVolumes,\n\t\tports: [\"${OPENCLAW_GATEWAY_PORT:-18789}:18789\", \"${OPENCLAW_BRIDGE_PORT:-18790}:18790\"],\n\t\tnetworks: [\"openclaw-network\"],\n\t\tinit: true,\n\t\trestart: \"unless-stopped\",\n\t\tcommand: [\n\t\t\t\"node\",\n\t\t\t\"dist/index.js\",\n\t\t\t\"gateway\",\n\t\t\t\"--bind\",\n\t\t\t\"${OPENCLAW_GATEWAY_BIND:-lan}\",\n\t\t\t\"--port\",\n\t\t\t\"18789\",\n\t\t],\n\t};\n\n\t// Traefik labels for the gateway\n\tconst gwTraefikLabels = options.traefikLabels?.get(\"openclaw-gateway\");\n\tif (gwTraefikLabels) {\n\t\tgateway.labels = gwTraefikLabels;\n\t}\n\n\tif (options.bareMetalNativeHost) {\n\t\tgateway.extra_hosts = [\"host.docker.internal:host-gateway\"];\n\t}\n\n\tif (dependsOn && Object.keys(dependsOn).length > 0) {\n\t\tgateway.depends_on = dependsOn;\n\t}\n\n\t// CLI companion service (matching real OpenClaw docker-compose.yml)\n\t// Build CLI environment with same keys as gateway for consistency\n\tconst cliEnv: Record<string, string> = {\n\t\tHOME: \"/home/node\",\n\t\tTERM: \"xterm-256color\",\n\t\tOPENCLAW_GATEWAY_TOKEN: \"${OPENCLAW_GATEWAY_TOKEN}\",\n\t\t// Gateway connection: use Docker service name so CLI can reach the gateway over the bridge network\n\t\tOPENCLAW_GATEWAY_HOST: \"openclaw-gateway\",\n\t\tOPENCLAW_GATEWAY_PORT: \"18789\",\n\t\tBROWSER: \"echo\",\n\t\tCLAUDE_AI_SESSION_KEY: \"${CLAUDE_AI_SESSION_KEY}\",\n\t\tCLAUDE_WEB_SESSION_KEY: \"${CLAUDE_WEB_SESSION_KEY}\",\n\t\tCLAUDE_WEB_COOKIE: \"${CLAUDE_WEB_COOKIE}\",\n\t};\n\n\t// Add same AI provider API keys to CLI for direct AI interactions\n\tfor (const key of providerKeys) {\n\t\tcliEnv[key] = `\\${${key}}`;\n\t}\n\n\tconst cliService: Record<string, unknown> = {\n\t\timage: `\\${OPENCLAW_IMAGE:-${defaultImage}}`,\n\t\tenvironment: cliEnv,\n\t\tvolumes: [\n\t\t\t\"${OPENCLAW_CONFIG_DIR:-./openclaw/config}:/home/node/.openclaw\",\n\t\t\t\"${OPENCLAW_WORKSPACE_DIR:-./openclaw/workspace}:/home/node/.openclaw/workspace\",\n\t\t],\n\t\tstdin_open: true,\n\t\ttty: true,\n\t\tinit: true,\n\t\tnetworks: [\"openclaw-network\"],\n\t\tentrypoint: [\"node\", \"dist/index.js\"],\n\t\t// CLI is interactive — don't auto-restart, but wait for gateway to be ready\n\t\trestart: \"no\",\n\t\tdepends_on: {\n\t\t\t\"openclaw-gateway\": { condition: \"service_started\" },\n\t\t},\n\t};\n\n\treturn { gatewayService: gateway, cliService: cliService, allVolumes };\n}\n\n// ── Shared Companion Service Builder ────────────────────────────────────────\n\nfunction buildCompanionService(\n\tdef: ResolverOutput[\"services\"][number][\"definition\"],\n\tresolved: ResolverOutput,\n\toptions: ComposeOptions,\n\tallVolumes: Set<string>,\n): { entry: Record<string, unknown>; volumeNames: string[] } {\n\tconst svc: Record<string, unknown> = {};\n\tconst volumeNames: string[] = [];\n\n\tsvc.image = `${def.image}:${def.imageTag}`;\n\n\tif (def.environment.length > 0) {\n\t\tconst env: Record<string, string> = {};\n\t\tfor (const e of def.environment) {\n\t\t\tenv[e.key] = e.secret ? `\\${${e.key}}` : e.defaultValue;\n\t\t}\n\t\tsvc.environment = env;\n\t}\n\n\tconst exposedPorts = def.ports.filter((p) => p.exposed);\n\tif (exposedPorts.length > 0) {\n\t\tconst prefix = def.id.toUpperCase().replace(/-/g, \"_\");\n\t\tsvc.ports = exposedPorts.map((p, i) => {\n\t\t\tconst suffix = exposedPorts.length > 1 ? `_${i}` : \"\";\n\t\t\tlet defaultPort = p.host;\n\n\t\t\t// Override proxy ports if custom ports are specified\n\t\t\tif (\n\t\t\t\t(def.id === \"caddy\" || def.id === \"traefik\") &&\n\t\t\t\toptions.proxyHttpPort !== undefined &&\n\t\t\t\tp.container === 80\n\t\t\t) {\n\t\t\t\tdefaultPort = options.proxyHttpPort;\n\t\t\t}\n\t\t\tif (\n\t\t\t\t(def.id === \"caddy\" || def.id === \"traefik\") &&\n\t\t\t\toptions.proxyHttpsPort !== undefined &&\n\t\t\t\tp.container === 443\n\t\t\t) {\n\t\t\t\tdefaultPort = options.proxyHttpsPort;\n\t\t\t}\n\n\t\t\t// Apply global port overrides if specified\n\t\t\tif (options.portOverrides?.[def.id]?.[p.host] !== undefined) {\n\t\t\t\tdefaultPort = options.portOverrides?.[def.id]?.[p.host] || p.host;\n\t\t\t}\n\n\t\t\t// Use _EXTERNAL_PORT to avoid colliding with openclawEnvVars _PORT keys.\n\t\t\t// openclawEnvVars define the container port (e.g. GRAFANA_PORT=3000 for\n\t\t\t// internal Docker networking), while these are host port mappings (e.g. 3150).\n\t\t\t// Without this, GRAFANA_PORT=3000 from .env would override the default\n\t\t\t// 3150 in ${GRAFANA_PORT:-3150}:3000, mapping host port 3000 instead.\n\t\t\treturn `\\${${prefix}_EXTERNAL_PORT${suffix}:-${defaultPort}}:${p.container}`;\n\t\t});\n\t}\n\n\tif (def.volumes.length > 0) {\n\t\tsvc.volumes = def.volumes.map((v) => {\n\t\t\tconst isBindMount =\n\t\t\t\tv.name.startsWith(\"./\") || v.name.startsWith(\"/\") || v.name.startsWith(\"~\");\n\n\t\t\tif (!isBindMount) {\n\t\t\t\tallVolumes.add(v.name);\n\t\t\t\tvolumeNames.push(v.name);\n\t\t\t}\n\t\t\treturn `${v.name}:${v.containerPath}`;\n\t\t});\n\t}\n\n\t// PostgreSQL: mount the init script and pass per-service DB passwords\n\tif (def.id === \"postgresql\") {\n\t\tif (!svc.volumes) svc.volumes = [];\n\t\t(svc.volumes as string[]).push(\n\t\t\t\"./postgres/init-databases.sh:/docker-entrypoint-initdb.d/init-databases.sh:ro\",\n\t\t);\n\n\t\t// Pass per-service database password env vars so the init script can use them\n\t\tconst dbReqs = getDbRequirements(resolved);\n\t\tif (dbReqs.length > 0) {\n\t\t\tconst env = (svc.environment ?? {}) as Record<string, string>;\n\t\t\tfor (const req of dbReqs) {\n\t\t\t\tenv[req.passwordEnvVar] = `\\${${req.passwordEnvVar}}`;\n\t\t\t}\n\t\t\tsvc.environment = env;\n\t\t}\n\t}\n\n\tif (def.healthcheck) {\n\t\tconst hc: Record<string, unknown> = {\n\t\t\ttest: [\"CMD-SHELL\", def.healthcheck.test],\n\t\t\tinterval: def.healthcheck.interval,\n\t\t\ttimeout: def.healthcheck.timeout,\n\t\t\tretries: def.healthcheck.retries,\n\t\t};\n\t\tif (def.healthcheck.startPeriod) {\n\t\t\thc.start_period = def.healthcheck.startPeriod;\n\t\t}\n\t\tsvc.healthcheck = hc;\n\t}\n\n\tsvc.restart = def.restartPolicy;\n\tsvc.networks = def.networks;\n\n\tif (def.command) svc.command = def.command;\n\tif (def.entrypoint) svc.entrypoint = def.entrypoint;\n\n\t// Labels: merge static definition labels with dynamic Traefik labels\n\tconst mergedLabels: Record<string, string> = {};\n\tif (def.labels) Object.assign(mergedLabels, def.labels);\n\tconst traefikLabels = options.traefikLabels?.get(def.id);\n\tif (traefikLabels) Object.assign(mergedLabels, traefikLabels);\n\tif (Object.keys(mergedLabels).length > 0) svc.labels = mergedLabels;\n\n\t// Traefik: bind-mount static config and Docker socket\n\tif (def.id === \"traefik\" && options.traefikLabels) {\n\t\tif (!svc.volumes) svc.volumes = [];\n\t\t(svc.volumes as string[]).push(\n\t\t\t\"./traefik/traefik.yml:/etc/traefik/traefik.yml:ro\",\n\t\t\t\"/var/run/docker.sock:/var/run/docker.sock:ro\",\n\t\t);\n\t}\n\n\tlet deploy: Record<string, unknown> | undefined;\n\tif (def.deploy) {\n\t\tdeploy = JSON.parse(JSON.stringify(def.deploy)) as Record<string, unknown>;\n\t}\n\tif (options.gpu && def.gpuRequired) {\n\t\tconst base = deploy ?? {};\n\t\tconst resources = (base.resources ?? {}) as Record<string, unknown>;\n\t\tdeploy = {\n\t\t\t...base,\n\t\t\tresources: {\n\t\t\t\t...resources,\n\t\t\t\treservations: {\n\t\t\t\t\t...((resources.reservations as Record<string, unknown>) ?? {}),\n\t\t\t\t\tdevices: [{ driver: \"nvidia\", count: \"all\", capabilities: [\"gpu\"] }],\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\t// Memory limits from estimatedMemoryMB\n\tif (def.minMemoryMB && options.hardened) {\n\t\tconst base = deploy ?? {};\n\t\tconst resources = (base.resources ?? {}) as Record<string, unknown>;\n\t\tconst limits = (resources.limits as Record<string, unknown>) ?? {};\n\t\tdeploy = {\n\t\t\t...base,\n\t\t\tresources: {\n\t\t\t\t...resources,\n\t\t\t\tlimits: {\n\t\t\t\t\t...limits,\n\t\t\t\t\tmemory: `${def.minMemoryMB * 2}m`, // 2x min as safe limit\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\tif (deploy) svc.deploy = deploy;\n\n\t// Security hardening (when enabled)\n\tif (options.hardened) {\n\t\tsvc.cap_drop = [\"ALL\"];\n\t\tsvc.security_opt = [\"no-new-privileges:true\"];\n\n\t\t// Services that need specific capabilities\n\t\tconst capAddMap: Record<string, string[]> = {\n\t\t\tcaddy: [\"NET_BIND_SERVICE\"],\n\t\t\ttraefik: [\"NET_BIND_SERVICE\"],\n\t\t\tcrowdsec: [\"NET_BIND_SERVICE\", \"DAC_READ_SEARCH\"],\n\t\t};\n\t\tif (capAddMap[def.id]) {\n\t\t\tsvc.cap_add = capAddMap[def.id];\n\t\t}\n\t}\n\n\t// Merge both dependsOn and requires to ensure proper Docker startup ordering\n\tconst depIds = [...new Set([...def.dependsOn, ...def.requires])].filter((id) =>\n\t\tresolved.services.some((s) => s.definition.id === id),\n\t);\n\tif (depIds.length > 0) {\n\t\tconst dependsOn: Record<string, { condition: string }> = {};\n\t\tfor (const depId of depIds) {\n\t\t\tconst dep = resolved.services.find((s) => s.definition.id === depId);\n\t\t\tdependsOn[depId] = {\n\t\t\t\tcondition: dep?.definition.healthcheck ? \"service_healthy\" : \"service_started\",\n\t\t\t};\n\t\t}\n\t\tsvc.depends_on = dependsOn;\n\t}\n\n\treturn { entry: svc, volumeNames };\n}\n\n// ── PostgreSQL Setup Init Container ─────────────────────────────────────────\n\n/**\n * Builds a one-shot init container that creates databases and users for\n * services that need their own PostgreSQL database. Runs AFTER PostgreSQL\n * is healthy, on every `docker compose up`, and is idempotent.\n *\n * Uses standard PG* environment variables (PGHOST, PGUSER, PGDATABASE,\n * PGPASSWORD) so psql/createuser/createdb automatically connect without\n * needing explicit -h/-U/-d flags — simpler and avoids YAML escaping issues.\n *\n * Returns null when no setup is needed (no PostgreSQL or no DB requirements).\n */\nfunction buildPostgresSetup(resolved: ResolverOutput): Record<string, unknown> | null {\n\tconst hasPostgres = resolved.services.some((s) => s.definition.id === \"postgresql\");\n\tif (!hasPostgres) return null;\n\n\tconst dbReqs = getDbRequirements(resolved);\n\tif (dbReqs.length === 0) return null;\n\n\t// Build a shell script with one command per line.\n\t// Uses $$ to escape $ from Docker Compose's variable substitution —\n\t// Docker Compose converts $$ → $ before passing to the container.\n\t// NO set -e: we handle errors explicitly so one failed service doesn't block others.\n\tconst scriptLines = [\"echo '=== PostgreSQL database setup ==='\", \"FAILED=0\"];\n\n\tfor (const req of dbReqs) {\n\t\t// Each service's setup is wrapped so a failure doesn't block the others.\n\t\t// Uses psql -v ON_ERROR_STOP=0 so SQL errors don't abort psql.\n\t\tscriptLines.push(\n\t\t\t`echo \"Setting up database '${req.dbName}' with user '${req.dbUser}'...\"`,\n\t\t\t// Create user if not exists (pure SQL, no createuser binary quirks)\n\t\t\t`psql -c \"SELECT 1 FROM pg_roles WHERE rolname='${req.dbUser}'\" | grep -q 1 || psql -c \"CREATE ROLE ${req.dbUser} WITH LOGIN PASSWORD '$$${req.passwordEnvVar}'\"`,\n\t\t\t// Always sync the password to match current env\n\t\t\t`psql -c \"ALTER ROLE ${req.dbUser} WITH LOGIN PASSWORD '$$${req.passwordEnvVar}'\"`,\n\t\t\t// Create database if not exists\n\t\t\t`psql -tc \"SELECT 1 FROM pg_database WHERE datname='${req.dbName}'\" | grep -q 1 || psql -c \"CREATE DATABASE ${req.dbName} OWNER ${req.dbUser}\"`,\n\t\t\t// Grant privileges (idempotent)\n\t\t\t`psql -c \"GRANT ALL PRIVILEGES ON DATABASE ${req.dbName} TO ${req.dbUser}\" || FAILED=1`,\n\t\t\t`echo \" Done: ${req.dbName}\"`,\n\t\t);\n\t}\n\n\tscriptLines.push(\"echo '=== All databases ready ==='\", \"exit $$FAILED\");\n\n\t// Standard PG* env vars: psql/createuser/createdb use these automatically\n\tconst env: Record<string, string> = {\n\t\tPGHOST: \"postgresql\",\n\t\tPGUSER: \"${POSTGRES_USER:-openclaw}\",\n\t\tPGDATABASE: \"${POSTGRES_DB:-openclaw}\",\n\t\tPGPASSWORD: \"${POSTGRES_PASSWORD}\",\n\t};\n\tfor (const req of dbReqs) {\n\t\tenv[req.passwordEnvVar] = `\\${${req.passwordEnvVar}}`;\n\t}\n\n\treturn {\n\t\timage: \"postgres:17-alpine\",\n\t\tdepends_on: {\n\t\t\tpostgresql: { condition: \"service_healthy\" },\n\t\t},\n\t\tenvironment: env,\n\t\t// command MUST be a single-element array so the entire script is passed\n\t\t// as ONE argument to `sh -c`. A plain string gets shlex-split by Docker\n\t\t// Compose into multiple args, breaking multi-line scripts.\n\t\tentrypoint: [\"/bin/sh\", \"-c\"],\n\t\tcommand: [scriptLines.join(\"\\n\")],\n\t\trestart: quotedStr(\"no\"),\n\t\tnetworks: [\"openclaw-network\"],\n\t};\n}\n\n// ── Single-File Compose ─────────────────────────────────────────────────────\n\n/**\n * Generates a single Docker Compose YAML string with ALL services.\n * Backward-compatible signature.\n */\nexport function compose(resolved: ResolverOutput, options: ComposeOptions): string {\n\tconst isDirectInstall = options.openclawInstallMethod === \"direct\";\n\n\t// Build depends_on for ALL companion services\n\tconst gatewayDependsOn: Record<string, { condition: string }> = {};\n\tfor (const { definition: def } of resolved.services) {\n\t\tgatewayDependsOn[def.id] = {\n\t\t\tcondition: def.healthcheck ? \"service_healthy\" : \"service_started\",\n\t\t};\n\t}\n\n\tconst services: Record<string, Record<string, unknown>> = {};\n\tlet allVolumes = new Set<string>();\n\n\tif (!isDirectInstall) {\n\t\tconst {\n\t\t\tgatewayService,\n\t\t\tcliService,\n\t\t\tallVolumes: gwVolumes,\n\t\t} = buildGatewayServices(resolved, options, gatewayDependsOn);\n\t\tallVolumes = gwVolumes;\n\t\tservices[\"openclaw-gateway\"] = gatewayService;\n\t\t// CLI service added after companions\n\t\t// Determine which services need DB setup so we can redirect their depends_on\n\t\tconst dbReqs = getDbRequirements(resolved);\n\t\tconst dbServiceIds = new Set(dbReqs.map((r) => r.serviceId));\n\n\t\tfor (const { definition: def } of resolved.services) {\n\t\t\tconst { entry } = buildCompanionService(def, resolved, options, allVolumes);\n\t\t\tif (dbServiceIds.has(def.id) && entry.depends_on) {\n\t\t\t\tconst deps = entry.depends_on as Record<string, { condition: string }>;\n\t\t\t\tif (deps.postgresql) {\n\t\t\t\t\tdelete deps.postgresql;\n\t\t\t\t\tdeps[\"postgres-setup\"] = { condition: \"service_completed_successfully\" };\n\t\t\t\t}\n\t\t\t}\n\t\t\tservices[def.id] = entry;\n\t\t}\n\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tservices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\n\t\tservices[\"openclaw-cli\"] = cliService;\n\t} else {\n\t\t// Direct install: no gateway/CLI containers, just companion services\n\t\tconst dbReqs = getDbRequirements(resolved);\n\t\tconst dbServiceIds = new Set(dbReqs.map((r) => r.serviceId));\n\n\t\tfor (const { definition: def } of resolved.services) {\n\t\t\tconst { entry } = buildCompanionService(def, resolved, options, allVolumes);\n\t\t\tif (dbServiceIds.has(def.id) && entry.depends_on) {\n\t\t\t\tconst deps = entry.depends_on as Record<string, { condition: string }>;\n\t\t\t\tif (deps.postgresql) {\n\t\t\t\t\tdelete deps.postgresql;\n\t\t\t\t\tdeps[\"postgres-setup\"] = { condition: \"service_completed_successfully\" };\n\t\t\t\t}\n\t\t\t}\n\t\t\tservices[def.id] = entry;\n\t\t}\n\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tservices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\t}\n\n\tconst volumes: Record<string, null> = {};\n\tfor (const v of [...allVolumes].sort()) {\n\t\tvolumes[v] = null;\n\t}\n\n\tconst networks = { \"openclaw-network\": { driver: \"bridge\" } };\n\n\treturn stringify({ services, volumes, networks }, YAML_OPTIONS);\n}\n\n// ── Multi-File Compose ──────────────────────────────────────────────────────\n\ninterface ServiceInfo {\n\tid: string;\n\tcategory: ServiceCategory;\n\tentry: Record<string, unknown>;\n\tvolumeNames: string[];\n}\n\n/**\n * Generates multiple Docker Compose files, splitting services into profile-based\n * override files by category.\n */\nexport function composeMultiFile(resolved: ResolverOutput, options: ComposeOptions): ComposeResult {\n\tconst isDirectInstall = options.openclawInstallMethod === \"direct\";\n\tconst allVolumes = new Set<string>();\n\n\t// Build all companion service entries & classify by category\n\tconst serviceInfos: ServiceInfo[] = [];\n\tconst dbReqs = getDbRequirements(resolved);\n\tconst dbServiceIds = new Set(dbReqs.map((r) => r.serviceId));\n\n\tfor (const { definition: def } of resolved.services) {\n\t\tconst { entry, volumeNames } = buildCompanionService(def, resolved, options, allVolumes);\n\t\t// Redirect DB-dependent services to depend on postgres-setup\n\t\tif (dbServiceIds.has(def.id) && entry.depends_on) {\n\t\t\tconst deps = entry.depends_on as Record<string, { condition: string }>;\n\t\t\tif (deps.postgresql) {\n\t\t\t\tdelete deps.postgresql;\n\t\t\t\tdeps[\"postgres-setup\"] = { condition: \"service_completed_successfully\" };\n\t\t\t}\n\t\t}\n\t\tserviceInfos.push({ id: def.id, category: def.category, entry, volumeNames });\n\t}\n\n\t// Partition services into base vs. profile files\n\tconst baseServiceIds = new Set<string>();\n\tconst profileFileMap: Record<string, { profile: string; services: ServiceInfo[] }> = {};\n\n\tfor (const info of serviceInfos) {\n\t\tconst mapping = CATEGORY_PROFILE_MAP[info.category];\n\t\tif (mapping) {\n\t\t\tif (!profileFileMap[mapping.file]) {\n\t\t\t\tprofileFileMap[mapping.file] = { profile: mapping.profile, services: [] };\n\t\t\t}\n\t\t\tprofileFileMap[mapping.file]!.services.push(info);\n\t\t} else {\n\t\t\tbaseServiceIds.add(info.id);\n\t\t}\n\t}\n\n\tconst baseServices: Record<string, Record<string, unknown>> = {};\n\n\tif (!isDirectInstall) {\n\t\t// Gateway depends_on (only base services)\n\t\tconst gatewayDependsOn: Record<string, { condition: string }> = {};\n\t\tfor (const { definition: def } of resolved.services) {\n\t\t\tif (baseServiceIds.has(def.id)) {\n\t\t\t\tgatewayDependsOn[def.id] = {\n\t\t\t\t\tcondition: def.healthcheck ? \"service_healthy\" : \"service_started\",\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tconst {\n\t\t\tgatewayService,\n\t\t\tcliService,\n\t\t\tallVolumes: gwVolumes,\n\t\t} = buildGatewayServices(resolved, options, gatewayDependsOn);\n\n\t\t// Merge gateway volumes into allVolumes\n\t\tfor (const v of gwVolumes) allVolumes.add(v);\n\n\t\tbaseServices[\"openclaw-gateway\"] = gatewayService;\n\n\t\tfor (const info of serviceInfos) {\n\t\t\tif (baseServiceIds.has(info.id)) {\n\t\t\t\tbaseServices[info.id] = info.entry;\n\t\t\t}\n\t\t}\n\n\t\t// Add postgres-setup init container if needed\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tbaseServices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\n\t\tbaseServices[\"openclaw-cli\"] = cliService;\n\t} else {\n\t\t// Direct install: no gateway/CLI containers\n\t\tfor (const info of serviceInfos) {\n\t\t\tif (baseServiceIds.has(info.id)) {\n\t\t\t\tbaseServices[info.id] = info.entry;\n\t\t\t}\n\t\t}\n\n\t\tconst pgSetup = buildPostgresSetup(resolved);\n\t\tif (pgSetup) {\n\t\t\tbaseServices[\"postgres-setup\"] = pgSetup;\n\t\t}\n\t}\n\n\tconst sortedAllVolumes: Record<string, null> = {};\n\tfor (const v of [...allVolumes].sort()) {\n\t\tsortedAllVolumes[v] = null;\n\t}\n\n\tconst networks = { \"openclaw-network\": { driver: \"bridge\" } };\n\n\tconst files: Record<string, string> = {};\n\tfiles[\"docker-compose.yml\"] = stringify(\n\t\t{ services: baseServices, volumes: sortedAllVolumes, networks },\n\t\tYAML_OPTIONS,\n\t);\n\n\t// Profile override files\n\tconst usedProfiles = new Set<string>();\n\n\tfor (const [fileName, { profile, services }] of Object.entries(profileFileMap)) {\n\t\tusedProfiles.add(profile);\n\n\t\tconst profileServices: Record<string, Record<string, unknown>> = {};\n\t\tconst profileVolumes = new Set<string>();\n\n\t\tfor (const info of services) {\n\t\t\tprofileServices[info.id] = { ...info.entry, profiles: [profile] };\n\t\t\tfor (const vName of info.volumeNames) {\n\t\t\t\tprofileVolumes.add(vName);\n\t\t\t}\n\t\t}\n\n\t\tconst fileContent: Record<string, unknown> = { services: profileServices };\n\n\t\tif (profileVolumes.size > 0) {\n\t\t\tconst sortedProfileVolumes: Record<string, null> = {};\n\t\t\tfor (const v of [...profileVolumes].sort()) {\n\t\t\t\tsortedProfileVolumes[v] = null;\n\t\t\t}\n\t\t\tfileContent.volumes = sortedProfileVolumes;\n\t\t}\n\n\t\tfiles[fileName] = stringify(fileContent, YAML_OPTIONS);\n\t}\n\n\treturn {\n\t\tfiles,\n\t\tmainFile: \"docker-compose.yml\",\n\t\tprofiles: [...usedProfiles].sort(),\n\t};\n}\n"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- const require_vi_2VT5v0um = require('./vi.2VT5v0um-BmRMvymT.cjs');
2
- const require_resolver = require('./resolver.cjs');
3
- const require_composer = require('./composer.cjs');
4
-
1
+ const require_vi_2VT5v0um = require("./vi.2VT5v0um-CRqXre87.cjs");
2
+ const require_resolver = require("./resolver.cjs");
3
+ const require_composer = require("./composer.cjs");
5
4
  //#region src/composer.snapshot.test.ts
6
5
  function generateForPreset(services, skillPacks = []) {
7
6
  return require_composer.composeMultiFile(require_resolver.resolve({
@@ -86,6 +85,6 @@ require_vi_2VT5v0um.describe("compose snapshot tests", () => {
86
85
  if (result.files["docker-compose.monitoring.yml"]) require_vi_2VT5v0um.globalExpect(result.files["docker-compose.monitoring.yml"]).toContain("profiles:");
87
86
  });
88
87
  });
89
-
90
88
  //#endregion
89
+
91
90
  //# sourceMappingURL=composer.snapshot.test.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"composer.snapshot.test.cjs","names":["composeMultiFile","resolve","describe"],"sources":["../src/composer.snapshot.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { composeMultiFile } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\n\nfunction generateForPreset(services: string[], skillPacks: string[] = []) {\n\tconst resolved = resolve({ services, skillPacks });\n\treturn composeMultiFile(resolved, {\n\t\tprojectName: \"test-stack\",\n\t\tproxy: \"none\",\n\t\tgpu: false,\n\t\tplatform: \"linux/amd64\",\n\t\tdeployment: \"local\",\n\t\topenclawVersion: \"latest\",\n\t});\n}\n\ndescribe(\"compose snapshot tests\", () => {\n\tit(\"minimal preset (redis only)\", () => {\n\t\tconst result = generateForPreset([\"redis\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"creator preset (ffmpeg + remotion + minio + redis)\", () => {\n\t\tconst result = generateForPreset([\"ffmpeg\", \"remotion\", \"minio\", \"redis\"], [\"video-creator\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.media.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.media.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"researcher preset (qdrant + searxng + browserless + redis)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"qdrant\", \"searxng\", \"browserless\", \"redis\"],\n\t\t\t[\"research-agent\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"devops preset (n8n + postgresql + redis + monitoring)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"n8n\", \"postgresql\", \"redis\", \"uptime-kuma\", \"grafana\", \"prometheus\"],\n\t\t\t[\"dev-ops\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"full preset (many services)\", () => {\n\t\tconst result = generateForPreset([\n\t\t\t\"redis\",\n\t\t\t\"postgresql\",\n\t\t\t\"qdrant\",\n\t\t\t\"n8n\",\n\t\t\t\"ffmpeg\",\n\t\t\t\"remotion\",\n\t\t\t\"minio\",\n\t\t\t\"caddy\",\n\t\t\t\"browserless\",\n\t\t\t\"searxng\",\n\t\t\t\"meilisearch\",\n\t\t\t\"uptime-kuma\",\n\t\t\t\"grafana\",\n\t\t\t\"prometheus\",\n\t\t\t\"ollama\",\n\t\t\t\"whisper\",\n\t\t\t\"gotify\",\n\t\t]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\texpect(result.profiles.length).toBeGreaterThan(0);\n\t\t// Verify multiple compose files were created\n\t\texpect(Object.keys(result.files).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"multi-file output has correct profile assignments\", () => {\n\t\tconst result = generateForPreset([\"redis\", \"ollama\", \"open-webui\", \"grafana\", \"prometheus\"]);\n\t\t// AI services should be in the ai profile file\n\t\tif (result.files[\"docker-compose.ai.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.ai.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t\t// Monitoring should be in the monitoring profile file\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t});\n});\n"],"mappings":";;;;;AAIA,SAAS,kBAAkB,UAAoB,aAAuB,EAAE,EAAE;AAEzE,QAAOA,kCADUC,yBAAQ;EAAE;EAAU;EAAY,CAAC,EAChB;EACjC,aAAa;EACb,OAAO;EACP,KAAK;EACL,UAAU;EACV,YAAY;EACZ,iBAAiB;EACjB,CAAC;;AAGHC,6BAAS,gCAAgC;AACxC,wBAAG,qCAAqC;AAEvC,mCADe,kBAAkB,CAAC,QAAQ,CAAC,CAC7B,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,wBAAG,4DAA4D;EAC9D,MAAM,SAAS,kBAAkB;GAAC;GAAU;GAAY;GAAS;GAAQ,EAAE,CAAC,gBAAgB,CAAC;AAC7F,mCAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,4BAChB,kCAAO,OAAO,MAAM,4BAA4B,CAAC,iBAAiB;GAElE;AAEF,wBAAG,oEAAoE;AAKtE,mCAJe,kBACd;GAAC;GAAU;GAAW;GAAe;GAAQ,EAC7C,CAAC,iBAAiB,CAClB,CACa,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,wBAAG,+DAA+D;EACjE,MAAM,SAAS,kBACd;GAAC;GAAO;GAAc;GAAS;GAAe;GAAW;GAAa,EACtE,CAAC,UAAU,CACX;AACD,mCAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,iCAChB,kCAAO,OAAO,MAAM,iCAAiC,CAAC,iBAAiB;GAEvE;AAEF,wBAAG,qCAAqC;EACvC,MAAM,SAAS,kBAAkB;GAChC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,CAAC;AACF,mCAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,mCAAO,OAAO,SAAS,OAAO,CAAC,gBAAgB,EAAE;AAEjD,mCAAO,OAAO,KAAK,OAAO,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE;GAC1D;AAEF,wBAAG,2DAA2D;EAC7D,MAAM,SAAS,kBAAkB;GAAC;GAAS;GAAU;GAAc;GAAW;GAAa,CAAC;AAE5F,MAAI,OAAO,MAAM,yBAChB,kCAAO,OAAO,MAAM,yBAAyB,CAAC,UAAU,YAAY;AAGrE,MAAI,OAAO,MAAM,iCAChB,kCAAO,OAAO,MAAM,iCAAiC,CAAC,UAAU,YAAY;GAE5E;EACD"}
1
+ {"version":3,"file":"composer.snapshot.test.cjs","names":["composeMultiFile","resolve","describe"],"sources":["../src/composer.snapshot.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { composeMultiFile } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\n\nfunction generateForPreset(services: string[], skillPacks: string[] = []) {\n\tconst resolved = resolve({ services, skillPacks });\n\treturn composeMultiFile(resolved, {\n\t\tprojectName: \"test-stack\",\n\t\tproxy: \"none\",\n\t\tgpu: false,\n\t\tplatform: \"linux/amd64\",\n\t\tdeployment: \"local\",\n\t\topenclawVersion: \"latest\",\n\t});\n}\n\ndescribe(\"compose snapshot tests\", () => {\n\tit(\"minimal preset (redis only)\", () => {\n\t\tconst result = generateForPreset([\"redis\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"creator preset (ffmpeg + remotion + minio + redis)\", () => {\n\t\tconst result = generateForPreset([\"ffmpeg\", \"remotion\", \"minio\", \"redis\"], [\"video-creator\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.media.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.media.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"researcher preset (qdrant + searxng + browserless + redis)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"qdrant\", \"searxng\", \"browserless\", \"redis\"],\n\t\t\t[\"research-agent\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"devops preset (n8n + postgresql + redis + monitoring)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"n8n\", \"postgresql\", \"redis\", \"uptime-kuma\", \"grafana\", \"prometheus\"],\n\t\t\t[\"dev-ops\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"full preset (many services)\", () => {\n\t\tconst result = generateForPreset([\n\t\t\t\"redis\",\n\t\t\t\"postgresql\",\n\t\t\t\"qdrant\",\n\t\t\t\"n8n\",\n\t\t\t\"ffmpeg\",\n\t\t\t\"remotion\",\n\t\t\t\"minio\",\n\t\t\t\"caddy\",\n\t\t\t\"browserless\",\n\t\t\t\"searxng\",\n\t\t\t\"meilisearch\",\n\t\t\t\"uptime-kuma\",\n\t\t\t\"grafana\",\n\t\t\t\"prometheus\",\n\t\t\t\"ollama\",\n\t\t\t\"whisper\",\n\t\t\t\"gotify\",\n\t\t]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\texpect(result.profiles.length).toBeGreaterThan(0);\n\t\t// Verify multiple compose files were created\n\t\texpect(Object.keys(result.files).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"multi-file output has correct profile assignments\", () => {\n\t\tconst result = generateForPreset([\"redis\", \"ollama\", \"open-webui\", \"grafana\", \"prometheus\"]);\n\t\t// AI services should be in the ai profile file\n\t\tif (result.files[\"docker-compose.ai.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.ai.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t\t// Monitoring should be in the monitoring profile file\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t});\n});\n"],"mappings":";;;;AAIA,SAAS,kBAAkB,UAAoB,aAAuB,EAAE,EAAE;AAEzE,QAAOA,iBAAAA,iBADUC,iBAAAA,QAAQ;EAAE;EAAU;EAAY,CAAC,EAChB;EACjC,aAAa;EACb,OAAO;EACP,KAAK;EACL,UAAU;EACV,YAAY;EACZ,iBAAiB;EACjB,CAAC;;AAGHC,oBAAAA,SAAS,gCAAgC;AACxC,qBAAA,GAAG,qCAAqC;AAEvC,sBAAA,aADe,kBAAkB,CAAC,QAAQ,CAAC,CAC7B,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,qBAAA,GAAG,4DAA4D;EAC9D,MAAM,SAAS,kBAAkB;GAAC;GAAU;GAAY;GAAS;GAAQ,EAAE,CAAC,gBAAgB,CAAC;AAC7F,sBAAA,aAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,4BAChB,qBAAA,aAAO,OAAO,MAAM,4BAA4B,CAAC,iBAAiB;GAElE;AAEF,qBAAA,GAAG,oEAAoE;AAKtE,sBAAA,aAJe,kBACd;GAAC;GAAU;GAAW;GAAe;GAAQ,EAC7C,CAAC,iBAAiB,CAClB,CACa,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,qBAAA,GAAG,+DAA+D;EACjE,MAAM,SAAS,kBACd;GAAC;GAAO;GAAc;GAAS;GAAe;GAAW;GAAa,EACtE,CAAC,UAAU,CACX;AACD,sBAAA,aAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,iCAChB,qBAAA,aAAO,OAAO,MAAM,iCAAiC,CAAC,iBAAiB;GAEvE;AAEF,qBAAA,GAAG,qCAAqC;EACvC,MAAM,SAAS,kBAAkB;GAChC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,CAAC;AACF,sBAAA,aAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,sBAAA,aAAO,OAAO,SAAS,OAAO,CAAC,gBAAgB,EAAE;AAEjD,sBAAA,aAAO,OAAO,KAAK,OAAO,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE;GAC1D;AAEF,qBAAA,GAAG,2DAA2D;EAC7D,MAAM,SAAS,kBAAkB;GAAC;GAAS;GAAU;GAAc;GAAW;GAAa,CAAC;AAE5F,MAAI,OAAO,MAAM,yBAChB,qBAAA,aAAO,OAAO,MAAM,yBAAyB,CAAC,UAAU,YAAY;AAGrE,MAAI,OAAO,MAAM,iCAChB,qBAAA,aAAO,OAAO,MAAM,iCAAiC,CAAC,UAAU,YAAY;GAE5E;EACD"}
@@ -1,7 +1,6 @@
1
- import { n as describe, r as it, t as globalExpect } from "./vi.2VT5v0um-CFyDIn0m.mjs";
1
+ import { n as describe, r as it, t as globalExpect } from "./vi.2VT5v0um-DvC3SVNc.mjs";
2
2
  import { resolve } from "./resolver.mjs";
3
3
  import { composeMultiFile } from "./composer.mjs";
4
-
5
4
  //#region src/composer.snapshot.test.ts
6
5
  function generateForPreset(services, skillPacks = []) {
7
6
  return composeMultiFile(resolve({
@@ -86,7 +85,7 @@ describe("compose snapshot tests", () => {
86
85
  if (result.files["docker-compose.monitoring.yml"]) globalExpect(result.files["docker-compose.monitoring.yml"]).toContain("profiles:");
87
86
  });
88
87
  });
89
-
90
88
  //#endregion
91
- export { };
89
+ export {};
90
+
92
91
  //# sourceMappingURL=composer.snapshot.test.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"composer.snapshot.test.mjs","names":[],"sources":["../src/composer.snapshot.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { composeMultiFile } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\n\nfunction generateForPreset(services: string[], skillPacks: string[] = []) {\n\tconst resolved = resolve({ services, skillPacks });\n\treturn composeMultiFile(resolved, {\n\t\tprojectName: \"test-stack\",\n\t\tproxy: \"none\",\n\t\tgpu: false,\n\t\tplatform: \"linux/amd64\",\n\t\tdeployment: \"local\",\n\t\topenclawVersion: \"latest\",\n\t});\n}\n\ndescribe(\"compose snapshot tests\", () => {\n\tit(\"minimal preset (redis only)\", () => {\n\t\tconst result = generateForPreset([\"redis\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"creator preset (ffmpeg + remotion + minio + redis)\", () => {\n\t\tconst result = generateForPreset([\"ffmpeg\", \"remotion\", \"minio\", \"redis\"], [\"video-creator\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.media.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.media.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"researcher preset (qdrant + searxng + browserless + redis)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"qdrant\", \"searxng\", \"browserless\", \"redis\"],\n\t\t\t[\"research-agent\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"devops preset (n8n + postgresql + redis + monitoring)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"n8n\", \"postgresql\", \"redis\", \"uptime-kuma\", \"grafana\", \"prometheus\"],\n\t\t\t[\"dev-ops\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"full preset (many services)\", () => {\n\t\tconst result = generateForPreset([\n\t\t\t\"redis\",\n\t\t\t\"postgresql\",\n\t\t\t\"qdrant\",\n\t\t\t\"n8n\",\n\t\t\t\"ffmpeg\",\n\t\t\t\"remotion\",\n\t\t\t\"minio\",\n\t\t\t\"caddy\",\n\t\t\t\"browserless\",\n\t\t\t\"searxng\",\n\t\t\t\"meilisearch\",\n\t\t\t\"uptime-kuma\",\n\t\t\t\"grafana\",\n\t\t\t\"prometheus\",\n\t\t\t\"ollama\",\n\t\t\t\"whisper\",\n\t\t\t\"gotify\",\n\t\t]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\texpect(result.profiles.length).toBeGreaterThan(0);\n\t\t// Verify multiple compose files were created\n\t\texpect(Object.keys(result.files).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"multi-file output has correct profile assignments\", () => {\n\t\tconst result = generateForPreset([\"redis\", \"ollama\", \"open-webui\", \"grafana\", \"prometheus\"]);\n\t\t// AI services should be in the ai profile file\n\t\tif (result.files[\"docker-compose.ai.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.ai.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t\t// Monitoring should be in the monitoring profile file\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t});\n});\n"],"mappings":";;;;;AAIA,SAAS,kBAAkB,UAAoB,aAAuB,EAAE,EAAE;AAEzE,QAAO,iBADU,QAAQ;EAAE;EAAU;EAAY,CAAC,EAChB;EACjC,aAAa;EACb,OAAO;EACP,KAAK;EACL,UAAU;EACV,YAAY;EACZ,iBAAiB;EACjB,CAAC;;AAGH,SAAS,gCAAgC;AACxC,IAAG,qCAAqC;AAEvC,eADe,kBAAkB,CAAC,QAAQ,CAAC,CAC7B,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,IAAG,4DAA4D;EAC9D,MAAM,SAAS,kBAAkB;GAAC;GAAU;GAAY;GAAS;GAAQ,EAAE,CAAC,gBAAgB,CAAC;AAC7F,eAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,4BAChB,cAAO,OAAO,MAAM,4BAA4B,CAAC,iBAAiB;GAElE;AAEF,IAAG,oEAAoE;AAKtE,eAJe,kBACd;GAAC;GAAU;GAAW;GAAe;GAAQ,EAC7C,CAAC,iBAAiB,CAClB,CACa,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,IAAG,+DAA+D;EACjE,MAAM,SAAS,kBACd;GAAC;GAAO;GAAc;GAAS;GAAe;GAAW;GAAa,EACtE,CAAC,UAAU,CACX;AACD,eAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,iCAChB,cAAO,OAAO,MAAM,iCAAiC,CAAC,iBAAiB;GAEvE;AAEF,IAAG,qCAAqC;EACvC,MAAM,SAAS,kBAAkB;GAChC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,CAAC;AACF,eAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,eAAO,OAAO,SAAS,OAAO,CAAC,gBAAgB,EAAE;AAEjD,eAAO,OAAO,KAAK,OAAO,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE;GAC1D;AAEF,IAAG,2DAA2D;EAC7D,MAAM,SAAS,kBAAkB;GAAC;GAAS;GAAU;GAAc;GAAW;GAAa,CAAC;AAE5F,MAAI,OAAO,MAAM,yBAChB,cAAO,OAAO,MAAM,yBAAyB,CAAC,UAAU,YAAY;AAGrE,MAAI,OAAO,MAAM,iCAChB,cAAO,OAAO,MAAM,iCAAiC,CAAC,UAAU,YAAY;GAE5E;EACD"}
1
+ {"version":3,"file":"composer.snapshot.test.mjs","names":[],"sources":["../src/composer.snapshot.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { composeMultiFile } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\n\nfunction generateForPreset(services: string[], skillPacks: string[] = []) {\n\tconst resolved = resolve({ services, skillPacks });\n\treturn composeMultiFile(resolved, {\n\t\tprojectName: \"test-stack\",\n\t\tproxy: \"none\",\n\t\tgpu: false,\n\t\tplatform: \"linux/amd64\",\n\t\tdeployment: \"local\",\n\t\topenclawVersion: \"latest\",\n\t});\n}\n\ndescribe(\"compose snapshot tests\", () => {\n\tit(\"minimal preset (redis only)\", () => {\n\t\tconst result = generateForPreset([\"redis\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"creator preset (ffmpeg + remotion + minio + redis)\", () => {\n\t\tconst result = generateForPreset([\"ffmpeg\", \"remotion\", \"minio\", \"redis\"], [\"video-creator\"]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.media.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.media.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"researcher preset (qdrant + searxng + browserless + redis)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"qdrant\", \"searxng\", \"browserless\", \"redis\"],\n\t\t\t[\"research-agent\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t});\n\n\tit(\"devops preset (n8n + postgresql + redis + monitoring)\", () => {\n\t\tconst result = generateForPreset(\n\t\t\t[\"n8n\", \"postgresql\", \"redis\", \"uptime-kuma\", \"grafana\", \"prometheus\"],\n\t\t\t[\"dev-ops\"],\n\t\t);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toMatchSnapshot();\n\t\t}\n\t});\n\n\tit(\"full preset (many services)\", () => {\n\t\tconst result = generateForPreset([\n\t\t\t\"redis\",\n\t\t\t\"postgresql\",\n\t\t\t\"qdrant\",\n\t\t\t\"n8n\",\n\t\t\t\"ffmpeg\",\n\t\t\t\"remotion\",\n\t\t\t\"minio\",\n\t\t\t\"caddy\",\n\t\t\t\"browserless\",\n\t\t\t\"searxng\",\n\t\t\t\"meilisearch\",\n\t\t\t\"uptime-kuma\",\n\t\t\t\"grafana\",\n\t\t\t\"prometheus\",\n\t\t\t\"ollama\",\n\t\t\t\"whisper\",\n\t\t\t\"gotify\",\n\t\t]);\n\t\texpect(result.files[\"docker-compose.yml\"]).toMatchSnapshot();\n\t\texpect(result.profiles.length).toBeGreaterThan(0);\n\t\t// Verify multiple compose files were created\n\t\texpect(Object.keys(result.files).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"multi-file output has correct profile assignments\", () => {\n\t\tconst result = generateForPreset([\"redis\", \"ollama\", \"open-webui\", \"grafana\", \"prometheus\"]);\n\t\t// AI services should be in the ai profile file\n\t\tif (result.files[\"docker-compose.ai.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.ai.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t\t// Monitoring should be in the monitoring profile file\n\t\tif (result.files[\"docker-compose.monitoring.yml\"]) {\n\t\t\texpect(result.files[\"docker-compose.monitoring.yml\"]).toContain(\"profiles:\");\n\t\t}\n\t});\n});\n"],"mappings":";;;;AAIA,SAAS,kBAAkB,UAAoB,aAAuB,EAAE,EAAE;AAEzE,QAAO,iBADU,QAAQ;EAAE;EAAU;EAAY,CAAC,EAChB;EACjC,aAAa;EACb,OAAO;EACP,KAAK;EACL,UAAU;EACV,YAAY;EACZ,iBAAiB;EACjB,CAAC;;AAGH,SAAS,gCAAgC;AACxC,IAAG,qCAAqC;AAEvC,eADe,kBAAkB,CAAC,QAAQ,CAAC,CAC7B,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,IAAG,4DAA4D;EAC9D,MAAM,SAAS,kBAAkB;GAAC;GAAU;GAAY;GAAS;GAAQ,EAAE,CAAC,gBAAgB,CAAC;AAC7F,eAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,4BAChB,cAAO,OAAO,MAAM,4BAA4B,CAAC,iBAAiB;GAElE;AAEF,IAAG,oEAAoE;AAKtE,eAJe,kBACd;GAAC;GAAU;GAAW;GAAe;GAAQ,EAC7C,CAAC,iBAAiB,CAClB,CACa,MAAM,sBAAsB,CAAC,iBAAiB;GAC3D;AAEF,IAAG,+DAA+D;EACjE,MAAM,SAAS,kBACd;GAAC;GAAO;GAAc;GAAS;GAAe;GAAW;GAAa,EACtE,CAAC,UAAU,CACX;AACD,eAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,MAAI,OAAO,MAAM,iCAChB,cAAO,OAAO,MAAM,iCAAiC,CAAC,iBAAiB;GAEvE;AAEF,IAAG,qCAAqC;EACvC,MAAM,SAAS,kBAAkB;GAChC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,CAAC;AACF,eAAO,OAAO,MAAM,sBAAsB,CAAC,iBAAiB;AAC5D,eAAO,OAAO,SAAS,OAAO,CAAC,gBAAgB,EAAE;AAEjD,eAAO,OAAO,KAAK,OAAO,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE;GAC1D;AAEF,IAAG,2DAA2D;EAC7D,MAAM,SAAS,kBAAkB;GAAC;GAAS;GAAU;GAAc;GAAW;GAAa,CAAC;AAE5F,MAAI,OAAO,MAAM,yBAChB,cAAO,OAAO,MAAM,yBAAyB,CAAC,UAAU,YAAY;AAGrE,MAAI,OAAO,MAAM,iCAChB,cAAO,OAAO,MAAM,iCAAiC,CAAC,UAAU,YAAY;GAE5E;EACD"}
@@ -1,9 +1,8 @@
1
- const require_chunk = require('./chunk-C0xms8kb.cjs');
2
- const require_vi_2VT5v0um = require('./vi.2VT5v0um-BmRMvymT.cjs');
3
- const require_resolver = require('./resolver.cjs');
4
- const require_composer = require('./composer.cjs');
1
+ require("./skills-BlzpHmpH.cjs");
2
+ const require_vi_2VT5v0um = require("./vi.2VT5v0um-CRqXre87.cjs");
3
+ const require_resolver = require("./resolver.cjs");
4
+ const require_composer = require("./composer.cjs");
5
5
  let yaml = require("yaml");
6
-
7
6
  //#region src/composer.test.ts
8
7
  const defaultOptions = {
9
8
  projectName: "test-project",
@@ -161,6 +160,6 @@ require_vi_2VT5v0um.describe("compose", () => {
161
160
  require_vi_2VT5v0um.globalExpect(Object.keys(parsed.services)[0]).toBe("openclaw-gateway");
162
161
  });
163
162
  });
164
-
165
163
  //#endregion
164
+
166
165
  //# sourceMappingURL=composer.test.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"composer.test.cjs","names":["describe","compose","resolve","yaml"],"sources":["../src/composer.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { parse } from \"yaml\";\nimport { compose } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\nimport type { ComposeOptions, ResolverOutput } from \"./types.js\";\n\nconst defaultOptions: ComposeOptions = {\n\tprojectName: \"test-project\",\n\tproxy: \"none\",\n\tgpu: false,\n\tplatform: \"linux/amd64\",\n\tdeployment: \"local\",\n\topenclawVersion: \"latest\",\n};\n\ndescribe(\"compose\", () => {\n\tit(\"generates minimal stack with just OpenClaw gateway when no companions\", () => {\n\t\tconst resolved = resolve({ services: [], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have the gateway service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].image).toContain(\"ghcr.io/openclaw/openclaw\");\n\n\t\t// Gateway should have core environment\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.HOME).toBe(\"/home/node\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.TERM).toBe(\"xterm-256color\");\n\n\t\t// Gateway uses bind-mount volumes (not named volumes in top-level volumes section)\n\t\tconst gwVolumes = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVolumes.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\n\t\t// Should have network\n\t\texpect(parsed.networks).toHaveProperty(\"openclaw-network\");\n\t\texpect(parsed.networks[\"openclaw-network\"].driver).toBe(\"bridge\");\n\n\t\t// Should have CLI companion service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-cli\");\n\n\t\t// Gateway should have no depends_on (no companions)\n\t\texpect(parsed.services[\"openclaw-gateway\"]).not.toHaveProperty(\"depends_on\");\n\n\t\t// Gateway should have restart policy\n\t\texpect(parsed.services[\"openclaw-gateway\"].restart).toBe(\"unless-stopped\");\n\t});\n\n\tit(\"generates Redis companion with proper gateway depends_on\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have gateway and redis services\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\n\t\t// Redis service should have correct image\n\t\texpect(parsed.services.redis.image).toBe(\"redis:8-alpine\");\n\n\t\t// Gateway depends_on should include redis with service_healthy (redis has healthcheck)\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on).toHaveProperty(\"redis\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on.redis.condition).toBe(\"service_healthy\");\n\n\t\t// Redis should have a healthcheck\n\t\texpect(parsed.services.redis.healthcheck).toBeDefined();\n\t\texpect(parsed.services.redis.healthcheck.test).toContain(\"redis-cli ping\");\n\n\t\t// Redis should have restart policy\n\t\texpect(parsed.services.redis.restart).toBe(\"unless-stopped\");\n\n\t\t// Redis should be on openclaw-network\n\t\texpect(parsed.services.redis.networks).toContain(\"openclaw-network\");\n\n\t\t// Gateway environment should include redis-related openclawEnvVars\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment).toHaveProperty(\"REDIS_HOST\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.REDIS_HOST).toBe(\"redis\");\n\t});\n\n\tit(\"generates parseable YAML for a multi-service stack\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\n\t\t// Should not throw when parsing\n\t\texpect(() => parse(yaml)).not.toThrow();\n\n\t\tconst parsed = parse(yaml);\n\t\texpect(parsed).toHaveProperty(\"services\");\n\t\texpect(parsed).toHaveProperty(\"volumes\");\n\t\texpect(parsed).toHaveProperty(\"networks\");\n\n\t\t// Should have gateway + redis + n8n + postgresql (n8n requires postgresql)\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\t\texpect(parsed.services).toHaveProperty(\"n8n\");\n\t\texpect(parsed.services).toHaveProperty(\"postgresql\");\n\t});\n\n\tit(\"includes all service volumes in top-level volumes section\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Collect all volume names from all resolved services\n\t\tconst serviceVolumeNames = new Set<string>();\n\t\tfor (const rs of resolved.services) {\n\t\t\tfor (const vol of rs.definition.volumes) {\n\t\t\t\tserviceVolumeNames.add(vol.name);\n\t\t\t}\n\t\t}\n\n\t\t// All service volumes must appear in top-level volumes\n\t\tfor (const volName of serviceVolumeNames) {\n\t\t\texpect(parsed.volumes).toHaveProperty(volName);\n\t\t}\n\n\t\t// Gateway uses bind-mount volumes (not in top-level volumes section)\n\t\tconst gwVols = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVols.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\t});\n\n\tit(\"includes GPU passthrough when gpu=true and service requires it\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Modify resolved output to simulate a GPU-required service\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: true });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Ollama service should have GPU device reservation\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy).toBeDefined();\n\t\texpect(ollamaService.deploy.resources.reservations.devices).toEqual([\n\t\t\t{\n\t\t\t\tdriver: \"nvidia\",\n\t\t\t\tcount: \"all\",\n\t\t\t\tcapabilities: [\"gpu\"],\n\t\t\t},\n\t\t]);\n\t});\n\n\tit(\"does not include GPU passthrough when gpu=false\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Even if service requires GPU, gpu option is false\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: false });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should NOT have deploy with GPU devices\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy?.resources?.reservations?.devices).toBeUndefined();\n\t});\n\n\tit(\"does not map internal-only ports to host\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\n\t\t// Modify redis to have an internal-only port\n\t\tconst modifiedResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: {\n\t\t\t\t\t...s.definition,\n\t\t\t\t\tports: [\n\t\t\t\t\t\t...s.definition.ports,\n\t\t\t\t\t\t{ host: 16379, container: 16379, description: \"Redis cluster bus\", exposed: false },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(modifiedResolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should only have the exposed port, not the internal one\n\t\tconst redisPorts = parsed.services.redis.ports;\n\t\texpect(redisPorts).toHaveLength(1);\n\t\texpect(redisPorts[0]).toContain(\"6379\");\n\t\texpect(redisPorts[0]).not.toContain(\"16379\");\n\t});\n\n\tit(\"uses service_started condition for services without healthcheck\", () => {\n\t\tconst resolved = resolve({ services: [\"minio\"], skillPacks: [] });\n\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Minio may or may not have a healthcheck – the gateway depends_on\n\t\t// condition should reflect the definition accurately\n\t\tconst gatewayDeps = parsed.services[\"openclaw-gateway\"].depends_on;\n\t\tfor (const [id, dep] of Object.entries(gatewayDeps)) {\n\t\t\tconst svc = resolved.services.find((s) => s.definition.id === id);\n\t\t\tif (svc?.definition.healthcheck) {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_healthy\");\n\t\t\t} else {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_started\");\n\t\t\t}\n\t\t}\n\t});\n\n\tit(\"gateway is always the first service in the output\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"ollama\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// First key in services should be openclaw-gateway\n\t\tconst serviceKeys = Object.keys(parsed.services);\n\t\texpect(serviceKeys[0]).toBe(\"openclaw-gateway\");\n\t});\n});\n"],"mappings":";;;;;;;AAMA,MAAM,iBAAiC;CACtC,aAAa;CACb,OAAO;CACP,KAAK;CACL,UAAU;CACV,YAAY;CACZ,iBAAiB;CACjB;AAEDA,6BAAS,iBAAiB;AACzB,wBAAG,+EAA+E;EAGjF,MAAM,yBADOC,yBADIC,yBAAQ;GAAE,UAAU,EAAE;GAAE,YAAY,EAAE;GAAE,CAAC,EAC3B,eAAe,CACpB;AAG1B,mCAAO,OAAO,SAAS,CAAC,eAAe,mBAAmB;AAC1D,mCAAO,OAAO,SAAS,oBAAoB,MAAM,CAAC,UAAU,4BAA4B;AAGxF,mCAAO,OAAO,SAAS,oBAAoB,YAAY,KAAK,CAAC,KAAK,aAAa;AAC/E,mCAAO,OAAO,SAAS,oBAAoB,YAAY,KAAK,CAAC,KAAK,iBAAiB;EAGnF,MAAM,YAAY,OAAO,SAAS,oBAAoB;AACtD,mCAAO,UAAU,MAAM,MAAc,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,KAAK,KAAK;AAGzE,mCAAO,OAAO,SAAS,CAAC,eAAe,mBAAmB;AAC1D,mCAAO,OAAO,SAAS,oBAAoB,OAAO,CAAC,KAAK,SAAS;AAGjE,mCAAO,OAAO,SAAS,CAAC,eAAe,eAAe;AAGtD,mCAAO,OAAO,SAAS,oBAAoB,CAAC,IAAI,eAAe,aAAa;AAG5E,mCAAO,OAAO,SAAS,oBAAoB,QAAQ,CAAC,KAAK,iBAAiB;GACzE;AAEF,wBAAG,kEAAkE;EAGpE,MAAM,yBADOD,yBADIC,yBAAQ;GAAE,UAAU,CAAC,QAAQ;GAAE,YAAY,EAAE;GAAE,CAAC,EAClC,eAAe,CACpB;AAG1B,mCAAO,OAAO,SAAS,CAAC,eAAe,mBAAmB;AAC1D,mCAAO,OAAO,SAAS,CAAC,eAAe,QAAQ;AAG/C,mCAAO,OAAO,SAAS,MAAM,MAAM,CAAC,KAAK,iBAAiB;AAG1D,mCAAO,OAAO,SAAS,oBAAoB,WAAW,CAAC,eAAe,QAAQ;AAC9E,mCAAO,OAAO,SAAS,oBAAoB,WAAW,MAAM,UAAU,CAAC,KAAK,kBAAkB;AAG9F,mCAAO,OAAO,SAAS,MAAM,YAAY,CAAC,aAAa;AACvD,mCAAO,OAAO,SAAS,MAAM,YAAY,KAAK,CAAC,UAAU,iBAAiB;AAG1E,mCAAO,OAAO,SAAS,MAAM,QAAQ,CAAC,KAAK,iBAAiB;AAG5D,mCAAO,OAAO,SAAS,MAAM,SAAS,CAAC,UAAU,mBAAmB;AAGpE,mCAAO,OAAO,SAAS,oBAAoB,YAAY,CAAC,eAAe,aAAa;AACpF,mCAAO,OAAO,SAAS,oBAAoB,YAAY,WAAW,CAAC,KAAK,QAAQ;GAC/E;AAEF,wBAAG,4DAA4D;EAE9D,MAAMC,SAAOF,yBADIC,yBAAQ;GAAE,UAAU,CAAC,SAAS,MAAM;GAAE,YAAY,EAAE;GAAE,CAAC,EACzC,eAAe;AAG9C,yDAAmBC,OAAK,CAAC,CAAC,IAAI,SAAS;EAEvC,MAAM,yBAAeA,OAAK;AAC1B,mCAAO,OAAO,CAAC,eAAe,WAAW;AACzC,mCAAO,OAAO,CAAC,eAAe,UAAU;AACxC,mCAAO,OAAO,CAAC,eAAe,WAAW;AAGzC,mCAAO,OAAO,SAAS,CAAC,eAAe,mBAAmB;AAC1D,mCAAO,OAAO,SAAS,CAAC,eAAe,QAAQ;AAC/C,mCAAO,OAAO,SAAS,CAAC,eAAe,MAAM;AAC7C,mCAAO,OAAO,SAAS,CAAC,eAAe,aAAa;GACnD;AAEF,wBAAG,mEAAmE;EACrE,MAAM,WAAWD,yBAAQ;GAAE,UAAU,CAAC,SAAS,MAAM;GAAE,YAAY,EAAE;GAAE,CAAC;EAExE,MAAM,yBADOD,yBAAQ,UAAU,eAAe,CACpB;EAG1B,MAAM,qCAAqB,IAAI,KAAa;AAC5C,OAAK,MAAM,MAAM,SAAS,SACzB,MAAK,MAAM,OAAO,GAAG,WAAW,QAC/B,oBAAmB,IAAI,IAAI,KAAK;AAKlC,OAAK,MAAM,WAAW,mBACrB,kCAAO,OAAO,QAAQ,CAAC,eAAe,QAAQ;EAI/C,MAAM,SAAS,OAAO,SAAS,oBAAoB;AACnD,mCAAO,OAAO,MAAM,MAAc,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,KAAK,KAAK;GACrE;AAEF,wBAAG,wEAAwE;EAC1E,MAAM,WAAWC,yBAAQ;GAAE,UAAU,CAAC,SAAS;GAAE,YAAY,EAAE;GAAE,CAAC;EAelE,MAAM,gCAJOD,yBARuB;GACnC,GAAG;GACH,UAAU,SAAS,SAAS,KAAK,OAAO;IACvC,GAAG;IACH,YAAY;KAAE,GAAG,EAAE;KAAY,aAAa;KAAM;IAClD,EAAE;GACH,EAEiC;GAAE,GAAG;GAAgB,KAAK;GAAM,CAAC,CACzC,CAGG,SAAS;AACtC,mCAAO,cAAc,OAAO,CAAC,aAAa;AAC1C,mCAAO,cAAc,OAAO,UAAU,aAAa,QAAQ,CAAC,QAAQ,CACnE;GACC,QAAQ;GACR,OAAO;GACP,cAAc,CAAC,MAAM;GACrB,CACD,CAAC;GACD;AAEF,wBAAG,yDAAyD;EAC3D,MAAM,WAAWC,yBAAQ;GAAE,UAAU,CAAC,SAAS;GAAE,YAAY,EAAE;GAAE,CAAC;EAelE,MAAM,gCAJOD,yBARuB;GACnC,GAAG;GACH,UAAU,SAAS,SAAS,KAAK,OAAO;IACvC,GAAG;IACH,YAAY;KAAE,GAAG,EAAE;KAAY,aAAa;KAAM;IAClD,EAAE;GACH,EAEiC;GAAE,GAAG;GAAgB,KAAK;GAAO,CAAC,CAC1C,CAGG,SAAS;AACtC,mCAAO,cAAc,QAAQ,WAAW,cAAc,QAAQ,CAAC,eAAe;GAC7E;AAEF,wBAAG,kDAAkD;EACpD,MAAM,WAAWC,yBAAQ;GAAE,UAAU,CAAC,QAAQ;GAAE,YAAY,EAAE;GAAE,CAAC;EAqBjE,MAAM,6BAJOD,yBAd4B;GACxC,GAAG;GACH,UAAU,SAAS,SAAS,KAAK,OAAO;IACvC,GAAG;IACH,YAAY;KACX,GAAG,EAAE;KACL,OAAO,CACN,GAAG,EAAE,WAAW,OAChB;MAAE,MAAM;MAAO,WAAW;MAAO,aAAa;MAAqB,SAAS;MAAO,CACnF;KACD;IACD,EAAE;GACH,EAEsC,eAAe,CAC5B,CAGA,SAAS,MAAM;AACzC,mCAAO,WAAW,CAAC,aAAa,EAAE;AAClC,mCAAO,WAAW,GAAG,CAAC,UAAU,OAAO;AACvC,mCAAO,WAAW,GAAG,CAAC,IAAI,UAAU,QAAQ;GAC3C;AAEF,wBAAG,yEAAyE;EAC3E,MAAM,WAAWC,yBAAQ;GAAE,UAAU,CAAC,QAAQ;GAAE,YAAY,EAAE;GAAE,CAAC;EAOjE,MAAM,8BALOD,yBAAQ,UAAU,eAAe,CACpB,CAIC,SAAS,oBAAoB;AACxD,OAAK,MAAM,CAAC,IAAI,QAAQ,OAAO,QAAQ,YAAY,CAElD,KADY,SAAS,SAAS,MAAM,MAAM,EAAE,WAAW,OAAO,GAAG,EACxD,WAAW,YACnB,kCAAQ,IAA8B,UAAU,CAAC,KAAK,kBAAkB;MAExE,kCAAQ,IAA8B,UAAU,CAAC,KAAK,kBAAkB;GAGzE;AAEF,wBAAG,2DAA2D;EAG7D,MAAM,yBADOA,yBADIC,yBAAQ;GAAE,UAAU,CAAC,SAAS,SAAS;GAAE,YAAY,EAAE;GAAE,CAAC,EAC5C,eAAe,CACpB;AAI1B,mCADoB,OAAO,KAAK,OAAO,SAAS,CAC7B,GAAG,CAAC,KAAK,mBAAmB;GAC9C;EACD"}
1
+ {"version":3,"file":"composer.test.cjs","names":["describe","compose","resolve","yaml"],"sources":["../src/composer.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { parse } from \"yaml\";\nimport { compose } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\nimport type { ComposeOptions, ResolverOutput } from \"./types.js\";\n\nconst defaultOptions: ComposeOptions = {\n\tprojectName: \"test-project\",\n\tproxy: \"none\",\n\tgpu: false,\n\tplatform: \"linux/amd64\",\n\tdeployment: \"local\",\n\topenclawVersion: \"latest\",\n};\n\ndescribe(\"compose\", () => {\n\tit(\"generates minimal stack with just OpenClaw gateway when no companions\", () => {\n\t\tconst resolved = resolve({ services: [], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have the gateway service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].image).toContain(\"ghcr.io/openclaw/openclaw\");\n\n\t\t// Gateway should have core environment\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.HOME).toBe(\"/home/node\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.TERM).toBe(\"xterm-256color\");\n\n\t\t// Gateway uses bind-mount volumes (not named volumes in top-level volumes section)\n\t\tconst gwVolumes = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVolumes.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\n\t\t// Should have network\n\t\texpect(parsed.networks).toHaveProperty(\"openclaw-network\");\n\t\texpect(parsed.networks[\"openclaw-network\"].driver).toBe(\"bridge\");\n\n\t\t// Should have CLI companion service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-cli\");\n\n\t\t// Gateway should have no depends_on (no companions)\n\t\texpect(parsed.services[\"openclaw-gateway\"]).not.toHaveProperty(\"depends_on\");\n\n\t\t// Gateway should have restart policy\n\t\texpect(parsed.services[\"openclaw-gateway\"].restart).toBe(\"unless-stopped\");\n\t});\n\n\tit(\"generates Redis companion with proper gateway depends_on\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have gateway and redis services\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\n\t\t// Redis service should have correct image\n\t\texpect(parsed.services.redis.image).toBe(\"redis:8-alpine\");\n\n\t\t// Gateway depends_on should include redis with service_healthy (redis has healthcheck)\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on).toHaveProperty(\"redis\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on.redis.condition).toBe(\"service_healthy\");\n\n\t\t// Redis should have a healthcheck\n\t\texpect(parsed.services.redis.healthcheck).toBeDefined();\n\t\texpect(parsed.services.redis.healthcheck.test).toContain(\"redis-cli ping\");\n\n\t\t// Redis should have restart policy\n\t\texpect(parsed.services.redis.restart).toBe(\"unless-stopped\");\n\n\t\t// Redis should be on openclaw-network\n\t\texpect(parsed.services.redis.networks).toContain(\"openclaw-network\");\n\n\t\t// Gateway environment should include redis-related openclawEnvVars\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment).toHaveProperty(\"REDIS_HOST\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.REDIS_HOST).toBe(\"redis\");\n\t});\n\n\tit(\"generates parseable YAML for a multi-service stack\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\n\t\t// Should not throw when parsing\n\t\texpect(() => parse(yaml)).not.toThrow();\n\n\t\tconst parsed = parse(yaml);\n\t\texpect(parsed).toHaveProperty(\"services\");\n\t\texpect(parsed).toHaveProperty(\"volumes\");\n\t\texpect(parsed).toHaveProperty(\"networks\");\n\n\t\t// Should have gateway + redis + n8n + postgresql (n8n requires postgresql)\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\t\texpect(parsed.services).toHaveProperty(\"n8n\");\n\t\texpect(parsed.services).toHaveProperty(\"postgresql\");\n\t});\n\n\tit(\"includes all service volumes in top-level volumes section\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Collect all volume names from all resolved services\n\t\tconst serviceVolumeNames = new Set<string>();\n\t\tfor (const rs of resolved.services) {\n\t\t\tfor (const vol of rs.definition.volumes) {\n\t\t\t\tserviceVolumeNames.add(vol.name);\n\t\t\t}\n\t\t}\n\n\t\t// All service volumes must appear in top-level volumes\n\t\tfor (const volName of serviceVolumeNames) {\n\t\t\texpect(parsed.volumes).toHaveProperty(volName);\n\t\t}\n\n\t\t// Gateway uses bind-mount volumes (not in top-level volumes section)\n\t\tconst gwVols = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVols.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\t});\n\n\tit(\"includes GPU passthrough when gpu=true and service requires it\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Modify resolved output to simulate a GPU-required service\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: true });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Ollama service should have GPU device reservation\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy).toBeDefined();\n\t\texpect(ollamaService.deploy.resources.reservations.devices).toEqual([\n\t\t\t{\n\t\t\t\tdriver: \"nvidia\",\n\t\t\t\tcount: \"all\",\n\t\t\t\tcapabilities: [\"gpu\"],\n\t\t\t},\n\t\t]);\n\t});\n\n\tit(\"does not include GPU passthrough when gpu=false\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Even if service requires GPU, gpu option is false\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: false });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should NOT have deploy with GPU devices\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy?.resources?.reservations?.devices).toBeUndefined();\n\t});\n\n\tit(\"does not map internal-only ports to host\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\n\t\t// Modify redis to have an internal-only port\n\t\tconst modifiedResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: {\n\t\t\t\t\t...s.definition,\n\t\t\t\t\tports: [\n\t\t\t\t\t\t...s.definition.ports,\n\t\t\t\t\t\t{ host: 16379, container: 16379, description: \"Redis cluster bus\", exposed: false },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(modifiedResolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should only have the exposed port, not the internal one\n\t\tconst redisPorts = parsed.services.redis.ports;\n\t\texpect(redisPorts).toHaveLength(1);\n\t\texpect(redisPorts[0]).toContain(\"6379\");\n\t\texpect(redisPorts[0]).not.toContain(\"16379\");\n\t});\n\n\tit(\"uses service_started condition for services without healthcheck\", () => {\n\t\tconst resolved = resolve({ services: [\"minio\"], skillPacks: [] });\n\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Minio may or may not have a healthcheck – the gateway depends_on\n\t\t// condition should reflect the definition accurately\n\t\tconst gatewayDeps = parsed.services[\"openclaw-gateway\"].depends_on;\n\t\tfor (const [id, dep] of Object.entries(gatewayDeps)) {\n\t\t\tconst svc = resolved.services.find((s) => s.definition.id === id);\n\t\t\tif (svc?.definition.healthcheck) {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_healthy\");\n\t\t\t} else {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_started\");\n\t\t\t}\n\t\t}\n\t});\n\n\tit(\"gateway is always the first service in the output\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"ollama\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// First key in services should be openclaw-gateway\n\t\tconst serviceKeys = Object.keys(parsed.services);\n\t\texpect(serviceKeys[0]).toBe(\"openclaw-gateway\");\n\t});\n});\n"],"mappings":"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"}
@@ -1,8 +1,7 @@
1
- import { n as describe, r as it, t as globalExpect } from "./vi.2VT5v0um-CFyDIn0m.mjs";
1
+ import { n as describe, r as it, t as globalExpect } from "./vi.2VT5v0um-DvC3SVNc.mjs";
2
2
  import { resolve } from "./resolver.mjs";
3
3
  import { compose } from "./composer.mjs";
4
4
  import { parse } from "yaml";
5
-
6
5
  //#region src/composer.test.ts
7
6
  const defaultOptions = {
8
7
  projectName: "test-project",
@@ -160,7 +159,7 @@ describe("compose", () => {
160
159
  globalExpect(Object.keys(parsed.services)[0]).toBe("openclaw-gateway");
161
160
  });
162
161
  });
163
-
164
162
  //#endregion
165
- export { };
163
+ export {};
164
+
166
165
  //# sourceMappingURL=composer.test.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"composer.test.mjs","names":[],"sources":["../src/composer.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { parse } from \"yaml\";\nimport { compose } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\nimport type { ComposeOptions, ResolverOutput } from \"./types.js\";\n\nconst defaultOptions: ComposeOptions = {\n\tprojectName: \"test-project\",\n\tproxy: \"none\",\n\tgpu: false,\n\tplatform: \"linux/amd64\",\n\tdeployment: \"local\",\n\topenclawVersion: \"latest\",\n};\n\ndescribe(\"compose\", () => {\n\tit(\"generates minimal stack with just OpenClaw gateway when no companions\", () => {\n\t\tconst resolved = resolve({ services: [], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have the gateway service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].image).toContain(\"ghcr.io/openclaw/openclaw\");\n\n\t\t// Gateway should have core environment\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.HOME).toBe(\"/home/node\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.TERM).toBe(\"xterm-256color\");\n\n\t\t// Gateway uses bind-mount volumes (not named volumes in top-level volumes section)\n\t\tconst gwVolumes = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVolumes.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\n\t\t// Should have network\n\t\texpect(parsed.networks).toHaveProperty(\"openclaw-network\");\n\t\texpect(parsed.networks[\"openclaw-network\"].driver).toBe(\"bridge\");\n\n\t\t// Should have CLI companion service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-cli\");\n\n\t\t// Gateway should have no depends_on (no companions)\n\t\texpect(parsed.services[\"openclaw-gateway\"]).not.toHaveProperty(\"depends_on\");\n\n\t\t// Gateway should have restart policy\n\t\texpect(parsed.services[\"openclaw-gateway\"].restart).toBe(\"unless-stopped\");\n\t});\n\n\tit(\"generates Redis companion with proper gateway depends_on\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have gateway and redis services\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\n\t\t// Redis service should have correct image\n\t\texpect(parsed.services.redis.image).toBe(\"redis:8-alpine\");\n\n\t\t// Gateway depends_on should include redis with service_healthy (redis has healthcheck)\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on).toHaveProperty(\"redis\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on.redis.condition).toBe(\"service_healthy\");\n\n\t\t// Redis should have a healthcheck\n\t\texpect(parsed.services.redis.healthcheck).toBeDefined();\n\t\texpect(parsed.services.redis.healthcheck.test).toContain(\"redis-cli ping\");\n\n\t\t// Redis should have restart policy\n\t\texpect(parsed.services.redis.restart).toBe(\"unless-stopped\");\n\n\t\t// Redis should be on openclaw-network\n\t\texpect(parsed.services.redis.networks).toContain(\"openclaw-network\");\n\n\t\t// Gateway environment should include redis-related openclawEnvVars\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment).toHaveProperty(\"REDIS_HOST\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.REDIS_HOST).toBe(\"redis\");\n\t});\n\n\tit(\"generates parseable YAML for a multi-service stack\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\n\t\t// Should not throw when parsing\n\t\texpect(() => parse(yaml)).not.toThrow();\n\n\t\tconst parsed = parse(yaml);\n\t\texpect(parsed).toHaveProperty(\"services\");\n\t\texpect(parsed).toHaveProperty(\"volumes\");\n\t\texpect(parsed).toHaveProperty(\"networks\");\n\n\t\t// Should have gateway + redis + n8n + postgresql (n8n requires postgresql)\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\t\texpect(parsed.services).toHaveProperty(\"n8n\");\n\t\texpect(parsed.services).toHaveProperty(\"postgresql\");\n\t});\n\n\tit(\"includes all service volumes in top-level volumes section\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Collect all volume names from all resolved services\n\t\tconst serviceVolumeNames = new Set<string>();\n\t\tfor (const rs of resolved.services) {\n\t\t\tfor (const vol of rs.definition.volumes) {\n\t\t\t\tserviceVolumeNames.add(vol.name);\n\t\t\t}\n\t\t}\n\n\t\t// All service volumes must appear in top-level volumes\n\t\tfor (const volName of serviceVolumeNames) {\n\t\t\texpect(parsed.volumes).toHaveProperty(volName);\n\t\t}\n\n\t\t// Gateway uses bind-mount volumes (not in top-level volumes section)\n\t\tconst gwVols = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVols.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\t});\n\n\tit(\"includes GPU passthrough when gpu=true and service requires it\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Modify resolved output to simulate a GPU-required service\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: true });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Ollama service should have GPU device reservation\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy).toBeDefined();\n\t\texpect(ollamaService.deploy.resources.reservations.devices).toEqual([\n\t\t\t{\n\t\t\t\tdriver: \"nvidia\",\n\t\t\t\tcount: \"all\",\n\t\t\t\tcapabilities: [\"gpu\"],\n\t\t\t},\n\t\t]);\n\t});\n\n\tit(\"does not include GPU passthrough when gpu=false\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Even if service requires GPU, gpu option is false\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: false });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should NOT have deploy with GPU devices\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy?.resources?.reservations?.devices).toBeUndefined();\n\t});\n\n\tit(\"does not map internal-only ports to host\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\n\t\t// Modify redis to have an internal-only port\n\t\tconst modifiedResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: {\n\t\t\t\t\t...s.definition,\n\t\t\t\t\tports: [\n\t\t\t\t\t\t...s.definition.ports,\n\t\t\t\t\t\t{ host: 16379, container: 16379, description: \"Redis cluster bus\", exposed: false },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(modifiedResolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should only have the exposed port, not the internal one\n\t\tconst redisPorts = parsed.services.redis.ports;\n\t\texpect(redisPorts).toHaveLength(1);\n\t\texpect(redisPorts[0]).toContain(\"6379\");\n\t\texpect(redisPorts[0]).not.toContain(\"16379\");\n\t});\n\n\tit(\"uses service_started condition for services without healthcheck\", () => {\n\t\tconst resolved = resolve({ services: [\"minio\"], skillPacks: [] });\n\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Minio may or may not have a healthcheck – the gateway depends_on\n\t\t// condition should reflect the definition accurately\n\t\tconst gatewayDeps = parsed.services[\"openclaw-gateway\"].depends_on;\n\t\tfor (const [id, dep] of Object.entries(gatewayDeps)) {\n\t\t\tconst svc = resolved.services.find((s) => s.definition.id === id);\n\t\t\tif (svc?.definition.healthcheck) {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_healthy\");\n\t\t\t} else {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_started\");\n\t\t\t}\n\t\t}\n\t});\n\n\tit(\"gateway is always the first service in the output\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"ollama\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// First key in services should be openclaw-gateway\n\t\tconst serviceKeys = Object.keys(parsed.services);\n\t\texpect(serviceKeys[0]).toBe(\"openclaw-gateway\");\n\t});\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"composer.test.mjs","names":[],"sources":["../src/composer.test.ts"],"sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { parse } from \"yaml\";\nimport { compose } from \"./composer.js\";\nimport { resolve } from \"./resolver.js\";\nimport type { ComposeOptions, ResolverOutput } from \"./types.js\";\n\nconst defaultOptions: ComposeOptions = {\n\tprojectName: \"test-project\",\n\tproxy: \"none\",\n\tgpu: false,\n\tplatform: \"linux/amd64\",\n\tdeployment: \"local\",\n\topenclawVersion: \"latest\",\n};\n\ndescribe(\"compose\", () => {\n\tit(\"generates minimal stack with just OpenClaw gateway when no companions\", () => {\n\t\tconst resolved = resolve({ services: [], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have the gateway service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].image).toContain(\"ghcr.io/openclaw/openclaw\");\n\n\t\t// Gateway should have core environment\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.HOME).toBe(\"/home/node\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.TERM).toBe(\"xterm-256color\");\n\n\t\t// Gateway uses bind-mount volumes (not named volumes in top-level volumes section)\n\t\tconst gwVolumes = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVolumes.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\n\t\t// Should have network\n\t\texpect(parsed.networks).toHaveProperty(\"openclaw-network\");\n\t\texpect(parsed.networks[\"openclaw-network\"].driver).toBe(\"bridge\");\n\n\t\t// Should have CLI companion service\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-cli\");\n\n\t\t// Gateway should have no depends_on (no companions)\n\t\texpect(parsed.services[\"openclaw-gateway\"]).not.toHaveProperty(\"depends_on\");\n\n\t\t// Gateway should have restart policy\n\t\texpect(parsed.services[\"openclaw-gateway\"].restart).toBe(\"unless-stopped\");\n\t});\n\n\tit(\"generates Redis companion with proper gateway depends_on\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should have gateway and redis services\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\n\t\t// Redis service should have correct image\n\t\texpect(parsed.services.redis.image).toBe(\"redis:8-alpine\");\n\n\t\t// Gateway depends_on should include redis with service_healthy (redis has healthcheck)\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on).toHaveProperty(\"redis\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].depends_on.redis.condition).toBe(\"service_healthy\");\n\n\t\t// Redis should have a healthcheck\n\t\texpect(parsed.services.redis.healthcheck).toBeDefined();\n\t\texpect(parsed.services.redis.healthcheck.test).toContain(\"redis-cli ping\");\n\n\t\t// Redis should have restart policy\n\t\texpect(parsed.services.redis.restart).toBe(\"unless-stopped\");\n\n\t\t// Redis should be on openclaw-network\n\t\texpect(parsed.services.redis.networks).toContain(\"openclaw-network\");\n\n\t\t// Gateway environment should include redis-related openclawEnvVars\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment).toHaveProperty(\"REDIS_HOST\");\n\t\texpect(parsed.services[\"openclaw-gateway\"].environment.REDIS_HOST).toBe(\"redis\");\n\t});\n\n\tit(\"generates parseable YAML for a multi-service stack\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\n\t\t// Should not throw when parsing\n\t\texpect(() => parse(yaml)).not.toThrow();\n\n\t\tconst parsed = parse(yaml);\n\t\texpect(parsed).toHaveProperty(\"services\");\n\t\texpect(parsed).toHaveProperty(\"volumes\");\n\t\texpect(parsed).toHaveProperty(\"networks\");\n\n\t\t// Should have gateway + redis + n8n + postgresql (n8n requires postgresql)\n\t\texpect(parsed.services).toHaveProperty(\"openclaw-gateway\");\n\t\texpect(parsed.services).toHaveProperty(\"redis\");\n\t\texpect(parsed.services).toHaveProperty(\"n8n\");\n\t\texpect(parsed.services).toHaveProperty(\"postgresql\");\n\t});\n\n\tit(\"includes all service volumes in top-level volumes section\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"n8n\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Collect all volume names from all resolved services\n\t\tconst serviceVolumeNames = new Set<string>();\n\t\tfor (const rs of resolved.services) {\n\t\t\tfor (const vol of rs.definition.volumes) {\n\t\t\t\tserviceVolumeNames.add(vol.name);\n\t\t\t}\n\t\t}\n\n\t\t// All service volumes must appear in top-level volumes\n\t\tfor (const volName of serviceVolumeNames) {\n\t\t\texpect(parsed.volumes).toHaveProperty(volName);\n\t\t}\n\n\t\t// Gateway uses bind-mount volumes (not in top-level volumes section)\n\t\tconst gwVols = parsed.services[\"openclaw-gateway\"].volumes as string[];\n\t\texpect(gwVols.some((v: string) => v.includes(\".openclaw\"))).toBe(true);\n\t});\n\n\tit(\"includes GPU passthrough when gpu=true and service requires it\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Modify resolved output to simulate a GPU-required service\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: true });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Ollama service should have GPU device reservation\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy).toBeDefined();\n\t\texpect(ollamaService.deploy.resources.reservations.devices).toEqual([\n\t\t\t{\n\t\t\t\tdriver: \"nvidia\",\n\t\t\t\tcount: \"all\",\n\t\t\t\tcapabilities: [\"gpu\"],\n\t\t\t},\n\t\t]);\n\t});\n\n\tit(\"does not include GPU passthrough when gpu=false\", () => {\n\t\tconst resolved = resolve({ services: [\"ollama\"], skillPacks: [] });\n\n\t\t// Even if service requires GPU, gpu option is false\n\t\tconst gpuResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: { ...s.definition, gpuRequired: true },\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(gpuResolved, { ...defaultOptions, gpu: false });\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should NOT have deploy with GPU devices\n\t\tconst ollamaService = parsed.services.ollama;\n\t\texpect(ollamaService.deploy?.resources?.reservations?.devices).toBeUndefined();\n\t});\n\n\tit(\"does not map internal-only ports to host\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\"], skillPacks: [] });\n\n\t\t// Modify redis to have an internal-only port\n\t\tconst modifiedResolved: ResolverOutput = {\n\t\t\t...resolved,\n\t\t\tservices: resolved.services.map((s) => ({\n\t\t\t\t...s,\n\t\t\t\tdefinition: {\n\t\t\t\t\t...s.definition,\n\t\t\t\t\tports: [\n\t\t\t\t\t\t...s.definition.ports,\n\t\t\t\t\t\t{ host: 16379, container: 16379, description: \"Redis cluster bus\", exposed: false },\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t})),\n\t\t};\n\n\t\tconst yaml = compose(modifiedResolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Should only have the exposed port, not the internal one\n\t\tconst redisPorts = parsed.services.redis.ports;\n\t\texpect(redisPorts).toHaveLength(1);\n\t\texpect(redisPorts[0]).toContain(\"6379\");\n\t\texpect(redisPorts[0]).not.toContain(\"16379\");\n\t});\n\n\tit(\"uses service_started condition for services without healthcheck\", () => {\n\t\tconst resolved = resolve({ services: [\"minio\"], skillPacks: [] });\n\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// Minio may or may not have a healthcheck – the gateway depends_on\n\t\t// condition should reflect the definition accurately\n\t\tconst gatewayDeps = parsed.services[\"openclaw-gateway\"].depends_on;\n\t\tfor (const [id, dep] of Object.entries(gatewayDeps)) {\n\t\t\tconst svc = resolved.services.find((s) => s.definition.id === id);\n\t\t\tif (svc?.definition.healthcheck) {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_healthy\");\n\t\t\t} else {\n\t\t\t\texpect((dep as { condition: string }).condition).toBe(\"service_started\");\n\t\t\t}\n\t\t}\n\t});\n\n\tit(\"gateway is always the first service in the output\", () => {\n\t\tconst resolved = resolve({ services: [\"redis\", \"ollama\"], skillPacks: [] });\n\t\tconst yaml = compose(resolved, defaultOptions);\n\t\tconst parsed = parse(yaml);\n\n\t\t// First key in services should be openclaw-gateway\n\t\tconst serviceKeys = Object.keys(parsed.services);\n\t\texpect(serviceKeys[0]).toBe(\"openclaw-gateway\");\n\t});\n});\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { d as PaasDeployer, i as DeployTarget, n as DeployResult, t as DeployInput } from "./types-zYjGTuyn.mjs";
2
+
3
+ //#region src/deployers/coolify.d.ts
4
+ declare class CoolifyDeployer implements PaasDeployer {
5
+ readonly name = "Coolify";
6
+ readonly id = "coolify";
7
+ testConnection(target: DeployTarget): Promise<{
8
+ ok: boolean;
9
+ error?: undefined;
10
+ } | {
11
+ ok: boolean;
12
+ error: string;
13
+ }>;
14
+ deploy(input: DeployInput): Promise<DeployResult>;
15
+ }
16
+ //#endregion
17
+ export { CoolifyDeployer as t };
18
+ //# sourceMappingURL=coolify-BVGGcMrT.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coolify-BVGGcMrT.d.mts","names":[],"sources":["../src/deployers/coolify.ts"],"mappings":";;;cAuIa,eAAA,YAA2B,YAAA;EAAA,SAC9B,IAAA;EAAA,SACA,EAAA;EAEH,cAAA,CAAe,MAAA,EAAQ,YAAA,GAAY,OAAA;;;;;;;EAanC,MAAA,CAAO,KAAA,EAAO,WAAA,GAAc,OAAA,CAAQ,YAAA;AAAA"}
@@ -0,0 +1,18 @@
1
+ import { d as PaasDeployer, i as DeployTarget, n as DeployResult, t as DeployInput } from "./types-CR83OJiq.cjs";
2
+
3
+ //#region src/deployers/coolify.d.ts
4
+ declare class CoolifyDeployer implements PaasDeployer {
5
+ readonly name = "Coolify";
6
+ readonly id = "coolify";
7
+ testConnection(target: DeployTarget): Promise<{
8
+ ok: boolean;
9
+ error?: undefined;
10
+ } | {
11
+ ok: boolean;
12
+ error: string;
13
+ }>;
14
+ deploy(input: DeployInput): Promise<DeployResult>;
15
+ }
16
+ //#endregion
17
+ export { CoolifyDeployer as t };
18
+ //# sourceMappingURL=coolify-vlb1G9V2.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coolify-vlb1G9V2.d.cts","names":[],"sources":["../src/deployers/coolify.ts"],"mappings":";;;cAuIa,eAAA,YAA2B,YAAA;EAAA,SAC9B,IAAA;EAAA,SACA,EAAA;EAEH,cAAA,CAAe,MAAA,EAAQ,YAAA,GAAY,OAAA;;;;;;;EAanC,MAAA,CAAO,KAAA,EAAO,WAAA,GAAc,OAAA,CAAQ,YAAA;AAAA"}