@better-openclaw/core 1.0.23 → 1.0.25

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 (335) hide show
  1. package/dist/addon-stack.cjs +673 -0
  2. package/dist/addon-stack.cjs.map +1 -0
  3. package/dist/addon-stack.d.cts +23 -0
  4. package/dist/addon-stack.d.cts.map +1 -0
  5. package/dist/addon-stack.d.mts +23 -0
  6. package/dist/addon-stack.d.mts.map +1 -0
  7. package/dist/addon-stack.mjs +671 -0
  8. package/dist/addon-stack.mjs.map +1 -0
  9. package/dist/addon-stack.test.cjs +349 -0
  10. package/dist/addon-stack.test.cjs.map +1 -0
  11. package/dist/addon-stack.test.d.cts +1 -0
  12. package/dist/addon-stack.test.d.mts +1 -0
  13. package/dist/addon-stack.test.mjs +349 -0
  14. package/dist/addon-stack.test.mjs.map +1 -0
  15. package/dist/bare-metal-partition.test.cjs +20 -21
  16. package/dist/bare-metal-partition.test.cjs.map +1 -1
  17. package/dist/bare-metal-partition.test.mjs +4 -5
  18. package/dist/bare-metal-partition.test.mjs.map +1 -1
  19. package/dist/composer.cjs +17 -1
  20. package/dist/composer.cjs.map +1 -1
  21. package/dist/composer.d.cts +24 -1
  22. package/dist/composer.d.cts.map +1 -1
  23. package/dist/composer.d.mts +24 -1
  24. package/dist/composer.d.mts.map +1 -1
  25. package/dist/composer.mjs +14 -2
  26. package/dist/composer.mjs.map +1 -1
  27. package/dist/composer.snapshot.test.cjs +20 -20
  28. package/dist/composer.snapshot.test.cjs.map +1 -1
  29. package/dist/composer.snapshot.test.mjs +2 -2
  30. package/dist/composer.test.cjs +53 -52
  31. package/dist/composer.test.cjs.map +1 -1
  32. package/dist/composer.test.mjs +4 -3
  33. package/dist/composer.test.mjs.map +1 -1
  34. package/dist/deployers/strip-host-ports.test.cjs +26 -26
  35. package/dist/deployers/strip-host-ports.test.cjs.map +1 -1
  36. package/dist/deployers/strip-host-ports.test.mjs +1 -1
  37. package/dist/generate.cjs +8 -4
  38. package/dist/generate.cjs.map +1 -1
  39. package/dist/generate.d.cts.map +1 -1
  40. package/dist/generate.d.mts.map +1 -1
  41. package/dist/generate.mjs +9 -5
  42. package/dist/generate.mjs.map +1 -1
  43. package/dist/generate.test.cjs +55 -55
  44. package/dist/generate.test.cjs.map +1 -1
  45. package/dist/generate.test.mjs +2 -2
  46. package/dist/generate.test.mjs.map +1 -1
  47. package/dist/generators/bare-metal-install.test.cjs +18 -18
  48. package/dist/generators/bare-metal-install.test.cjs.map +1 -1
  49. package/dist/generators/bare-metal-install.test.mjs +1 -1
  50. package/dist/generators/caddy.test.cjs +13 -13
  51. package/dist/generators/caddy.test.cjs.map +1 -1
  52. package/dist/generators/caddy.test.mjs +1 -1
  53. package/dist/generators/clone-repos.cjs +140 -0
  54. package/dist/generators/clone-repos.cjs.map +1 -0
  55. package/dist/generators/clone-repos.d.cts +11 -0
  56. package/dist/generators/clone-repos.d.cts.map +1 -0
  57. package/dist/generators/clone-repos.d.mts +11 -0
  58. package/dist/generators/clone-repos.d.mts.map +1 -0
  59. package/dist/generators/clone-repos.mjs +139 -0
  60. package/dist/generators/clone-repos.mjs.map +1 -0
  61. package/dist/generators/clone-repos.test.cjs +140 -0
  62. package/dist/generators/clone-repos.test.cjs.map +1 -0
  63. package/dist/generators/clone-repos.test.d.cts +1 -0
  64. package/dist/generators/clone-repos.test.d.mts +1 -0
  65. package/dist/generators/clone-repos.test.mjs +141 -0
  66. package/dist/generators/clone-repos.test.mjs.map +1 -0
  67. package/dist/generators/env.test.cjs +17 -17
  68. package/dist/generators/env.test.cjs.map +1 -1
  69. package/dist/generators/env.test.mjs +1 -1
  70. package/dist/generators/health-check.test.cjs +39 -39
  71. package/dist/generators/health-check.test.cjs.map +1 -1
  72. package/dist/generators/health-check.test.mjs +1 -1
  73. package/dist/generators/postgres-init.cjs +20 -0
  74. package/dist/generators/postgres-init.cjs.map +1 -1
  75. package/dist/generators/postgres-init.d.cts.map +1 -1
  76. package/dist/generators/postgres-init.d.mts.map +1 -1
  77. package/dist/generators/postgres-init.mjs +20 -0
  78. package/dist/generators/postgres-init.mjs.map +1 -1
  79. package/dist/generators/scripts.cjs +332 -3
  80. package/dist/generators/scripts.cjs.map +1 -1
  81. package/dist/generators/scripts.d.cts +3 -1
  82. package/dist/generators/scripts.d.cts.map +1 -1
  83. package/dist/generators/scripts.d.mts +3 -1
  84. package/dist/generators/scripts.d.mts.map +1 -1
  85. package/dist/generators/scripts.mjs +332 -3
  86. package/dist/generators/scripts.mjs.map +1 -1
  87. package/dist/generators/scripts.test.cjs +57 -23
  88. package/dist/generators/scripts.test.cjs.map +1 -1
  89. package/dist/generators/scripts.test.mjs +39 -5
  90. package/dist/generators/scripts.test.mjs.map +1 -1
  91. package/dist/generators/stack-manifest.cjs +1 -0
  92. package/dist/generators/stack-manifest.cjs.map +1 -1
  93. package/dist/generators/stack-manifest.d.cts +3 -2
  94. package/dist/generators/stack-manifest.d.cts.map +1 -1
  95. package/dist/generators/stack-manifest.d.mts +3 -2
  96. package/dist/generators/stack-manifest.d.mts.map +1 -1
  97. package/dist/generators/stack-manifest.mjs +1 -0
  98. package/dist/generators/stack-manifest.mjs.map +1 -1
  99. package/dist/generators/traefik.test.cjs +32 -32
  100. package/dist/generators/traefik.test.cjs.map +1 -1
  101. package/dist/generators/traefik.test.mjs +1 -1
  102. package/dist/index.cjs +28 -5
  103. package/dist/index.d.cts +7 -4
  104. package/dist/index.d.mts +7 -4
  105. package/dist/index.mjs +10 -7
  106. package/dist/migrations.test.cjs +16 -16
  107. package/dist/migrations.test.cjs.map +1 -1
  108. package/dist/migrations.test.mjs +1 -1
  109. package/dist/presets/registry.cjs.map +1 -1
  110. package/dist/presets/registry.d.cts.map +1 -1
  111. package/dist/presets/registry.d.mts.map +1 -1
  112. package/dist/presets/registry.mjs.map +1 -1
  113. package/dist/presets/registry.test.cjs +14 -14
  114. package/dist/presets/registry.test.cjs.map +1 -1
  115. package/dist/presets/registry.test.mjs +1 -1
  116. package/dist/resolver.cjs +8 -0
  117. package/dist/resolver.cjs.map +1 -1
  118. package/dist/resolver.mjs +9 -1
  119. package/dist/resolver.mjs.map +1 -1
  120. package/dist/resolver.test.cjs +125 -90
  121. package/dist/resolver.test.cjs.map +1 -1
  122. package/dist/resolver.test.mjs +47 -12
  123. package/dist/resolver.test.mjs.map +1 -1
  124. package/dist/{schema-B4c64P8N.d.cts → schema-CKBRu-Rt.d.cts} +355 -8
  125. package/dist/schema-CKBRu-Rt.d.cts.map +1 -0
  126. package/dist/{schema-CXNhYci1.d.mts → schema-Dn-_Jpb6.d.mts} +355 -8
  127. package/dist/schema-Dn-_Jpb6.d.mts.map +1 -0
  128. package/dist/schema.cjs +160 -5
  129. package/dist/schema.cjs.map +1 -1
  130. package/dist/schema.d.cts +2 -2
  131. package/dist/schema.d.mts +2 -2
  132. package/dist/schema.mjs +150 -6
  133. package/dist/schema.mjs.map +1 -1
  134. package/dist/schema.test.cjs +86 -86
  135. package/dist/schema.test.cjs.map +1 -1
  136. package/dist/schema.test.mjs +1 -1
  137. package/dist/services/definitions/apptension-saas.cjs +87 -0
  138. package/dist/services/definitions/apptension-saas.cjs.map +1 -0
  139. package/dist/services/definitions/apptension-saas.d.cts +7 -0
  140. package/dist/services/definitions/apptension-saas.d.cts.map +1 -0
  141. package/dist/services/definitions/apptension-saas.d.mts +7 -0
  142. package/dist/services/definitions/apptension-saas.d.mts.map +1 -0
  143. package/dist/services/definitions/apptension-saas.mjs +86 -0
  144. package/dist/services/definitions/apptension-saas.mjs.map +1 -0
  145. package/dist/services/definitions/boxyhq-saas.cjs +88 -0
  146. package/dist/services/definitions/boxyhq-saas.cjs.map +1 -0
  147. package/dist/services/definitions/boxyhq-saas.d.cts +7 -0
  148. package/dist/services/definitions/boxyhq-saas.d.cts.map +1 -0
  149. package/dist/services/definitions/boxyhq-saas.d.mts +7 -0
  150. package/dist/services/definitions/boxyhq-saas.d.mts.map +1 -0
  151. package/dist/services/definitions/boxyhq-saas.mjs +87 -0
  152. package/dist/services/definitions/boxyhq-saas.mjs.map +1 -0
  153. package/dist/services/definitions/browserless.cjs +4 -1
  154. package/dist/services/definitions/browserless.cjs.map +1 -1
  155. package/dist/services/definitions/browserless.mjs +4 -1
  156. package/dist/services/definitions/browserless.mjs.map +1 -1
  157. package/dist/services/definitions/cmsaas-starter.cjs +86 -0
  158. package/dist/services/definitions/cmsaas-starter.cjs.map +1 -0
  159. package/dist/services/definitions/cmsaas-starter.d.cts +7 -0
  160. package/dist/services/definitions/cmsaas-starter.d.cts.map +1 -0
  161. package/dist/services/definitions/cmsaas-starter.d.mts +7 -0
  162. package/dist/services/definitions/cmsaas-starter.d.mts.map +1 -0
  163. package/dist/services/definitions/cmsaas-starter.mjs +85 -0
  164. package/dist/services/definitions/cmsaas-starter.mjs.map +1 -0
  165. package/dist/services/definitions/convex.cjs +43 -1
  166. package/dist/services/definitions/convex.cjs.map +1 -1
  167. package/dist/services/definitions/convex.mjs +43 -1
  168. package/dist/services/definitions/convex.mjs.map +1 -1
  169. package/dist/services/definitions/grafana.cjs +11 -1
  170. package/dist/services/definitions/grafana.cjs.map +1 -1
  171. package/dist/services/definitions/grafana.mjs +11 -1
  172. package/dist/services/definitions/grafana.mjs.map +1 -1
  173. package/dist/services/definitions/index.cjs +51 -36
  174. package/dist/services/definitions/index.cjs.map +1 -1
  175. package/dist/services/definitions/index.d.cts +30 -25
  176. package/dist/services/definitions/index.d.cts.map +1 -1
  177. package/dist/services/definitions/index.d.mts +30 -25
  178. package/dist/services/definitions/index.d.mts.map +1 -1
  179. package/dist/services/definitions/index.mjs +47 -37
  180. package/dist/services/definitions/index.mjs.map +1 -1
  181. package/dist/services/definitions/ixartz-saas.cjs +88 -0
  182. package/dist/services/definitions/ixartz-saas.cjs.map +1 -0
  183. package/dist/services/definitions/ixartz-saas.d.cts +7 -0
  184. package/dist/services/definitions/ixartz-saas.d.cts.map +1 -0
  185. package/dist/services/definitions/ixartz-saas.d.mts +7 -0
  186. package/dist/services/definitions/ixartz-saas.d.mts.map +1 -0
  187. package/dist/services/definitions/ixartz-saas.mjs +87 -0
  188. package/dist/services/definitions/ixartz-saas.mjs.map +1 -0
  189. package/dist/services/definitions/meilisearch.cjs +11 -1
  190. package/dist/services/definitions/meilisearch.cjs.map +1 -1
  191. package/dist/services/definitions/meilisearch.mjs +11 -1
  192. package/dist/services/definitions/meilisearch.mjs.map +1 -1
  193. package/dist/services/definitions/minio.cjs +3 -1
  194. package/dist/services/definitions/minio.cjs.map +1 -1
  195. package/dist/services/definitions/minio.mjs +3 -1
  196. package/dist/services/definitions/minio.mjs.map +1 -1
  197. package/dist/services/definitions/mission-control.cjs +16 -2
  198. package/dist/services/definitions/mission-control.cjs.map +1 -1
  199. package/dist/services/definitions/mission-control.mjs +16 -2
  200. package/dist/services/definitions/mission-control.mjs.map +1 -1
  201. package/dist/services/definitions/n8n.cjs +11 -1
  202. package/dist/services/definitions/n8n.cjs.map +1 -1
  203. package/dist/services/definitions/n8n.mjs +11 -1
  204. package/dist/services/definitions/n8n.mjs.map +1 -1
  205. package/dist/services/definitions/ollama.cjs +3 -1
  206. package/dist/services/definitions/ollama.cjs.map +1 -1
  207. package/dist/services/definitions/ollama.mjs +3 -1
  208. package/dist/services/definitions/ollama.mjs.map +1 -1
  209. package/dist/services/definitions/open-saas.cjs +81 -0
  210. package/dist/services/definitions/open-saas.cjs.map +1 -0
  211. package/dist/services/definitions/open-saas.d.cts +7 -0
  212. package/dist/services/definitions/open-saas.d.cts.map +1 -0
  213. package/dist/services/definitions/open-saas.d.mts +7 -0
  214. package/dist/services/definitions/open-saas.d.mts.map +1 -0
  215. package/dist/services/definitions/open-saas.mjs +80 -0
  216. package/dist/services/definitions/open-saas.mjs.map +1 -0
  217. package/dist/services/definitions/qdrant.cjs +3 -1
  218. package/dist/services/definitions/qdrant.cjs.map +1 -1
  219. package/dist/services/definitions/qdrant.mjs +3 -1
  220. package/dist/services/definitions/qdrant.mjs.map +1 -1
  221. package/dist/services/definitions/searxng.cjs +8 -1
  222. package/dist/services/definitions/searxng.cjs.map +1 -1
  223. package/dist/services/definitions/searxng.mjs +8 -1
  224. package/dist/services/definitions/searxng.mjs.map +1 -1
  225. package/dist/services/definitions/uptime-kuma.cjs +8 -1
  226. package/dist/services/definitions/uptime-kuma.cjs.map +1 -1
  227. package/dist/services/definitions/uptime-kuma.mjs +8 -1
  228. package/dist/services/definitions/uptime-kuma.mjs.map +1 -1
  229. package/dist/services/registry.cjs +3 -0
  230. package/dist/services/registry.cjs.map +1 -1
  231. package/dist/services/registry.d.cts.map +1 -1
  232. package/dist/services/registry.d.mts.map +1 -1
  233. package/dist/services/registry.mjs +3 -0
  234. package/dist/services/registry.mjs.map +1 -1
  235. package/dist/services/registry.test.cjs +40 -33
  236. package/dist/services/registry.test.cjs.map +1 -1
  237. package/dist/services/registry.test.mjs +8 -1
  238. package/dist/services/registry.test.mjs.map +1 -1
  239. package/dist/{skill-manifest-BVUXU0__.mjs → skill-manifest-6XhrhWsG.mjs} +49 -1
  240. package/dist/{skill-manifest--IgY9REK.cjs.map → skill-manifest-6XhrhWsG.mjs.map} +1 -1
  241. package/dist/{skill-manifest--IgY9REK.cjs → skill-manifest-B8znSsym.cjs} +49 -1
  242. package/dist/{skill-manifest-BVUXU0__.mjs.map → skill-manifest-B8znSsym.cjs.map} +1 -1
  243. package/dist/skills/registry.cjs +3 -3
  244. package/dist/skills/registry.cjs.map +1 -1
  245. package/dist/skills/registry.mjs +3 -3
  246. package/dist/skills/registry.mjs.map +1 -1
  247. package/dist/skills/skill-manifest.cjs +1 -1
  248. package/dist/skills/skill-manifest.mjs +1 -1
  249. package/dist/{vi.2VT5v0um-DvC3SVNc.mjs → test.CTcmp4Su-ClCHJ3FA.mjs} +6793 -6403
  250. package/dist/test.CTcmp4Su-ClCHJ3FA.mjs.map +1 -0
  251. package/dist/{vi.2VT5v0um-CRqXre87.cjs → test.CTcmp4Su-DlzTarwH.cjs} +6793 -6403
  252. package/dist/test.CTcmp4Su-DlzTarwH.cjs.map +1 -0
  253. package/dist/track-analytics.cjs +50 -0
  254. package/dist/track-analytics.cjs.map +1 -0
  255. package/dist/track-analytics.d.cts +34 -0
  256. package/dist/track-analytics.d.cts.map +1 -0
  257. package/dist/track-analytics.d.mts +34 -0
  258. package/dist/track-analytics.d.mts.map +1 -0
  259. package/dist/track-analytics.mjs +48 -0
  260. package/dist/track-analytics.mjs.map +1 -0
  261. package/dist/track-analytics.test.cjs +91 -0
  262. package/dist/track-analytics.test.cjs.map +1 -0
  263. package/dist/track-analytics.test.d.cts +1 -0
  264. package/dist/track-analytics.test.d.mts +1 -0
  265. package/dist/track-analytics.test.mjs +92 -0
  266. package/dist/track-analytics.test.mjs.map +1 -0
  267. package/dist/types.cjs +7 -0
  268. package/dist/types.cjs.map +1 -1
  269. package/dist/types.d.cts +12 -2
  270. package/dist/types.d.cts.map +1 -1
  271. package/dist/types.d.mts +12 -2
  272. package/dist/types.d.mts.map +1 -1
  273. package/dist/types.mjs +7 -0
  274. package/dist/types.mjs.map +1 -1
  275. package/dist/validator.test.cjs +15 -15
  276. package/dist/validator.test.cjs.map +1 -1
  277. package/dist/validator.test.mjs +2 -2
  278. package/dist/version-manager.cjs +1 -1
  279. package/dist/version-manager.cjs.map +1 -1
  280. package/dist/version-manager.mjs +1 -1
  281. package/dist/version-manager.mjs.map +1 -1
  282. package/dist/version-manager.test.cjs +40 -38
  283. package/dist/version-manager.test.cjs.map +1 -1
  284. package/dist/version-manager.test.mjs +7 -5
  285. package/dist/version-manager.test.mjs.map +1 -1
  286. package/package.json +4 -4
  287. package/src/__snapshots__/composer.snapshot.test.ts.snap +160 -0
  288. package/src/addon-stack.test.ts +490 -0
  289. package/src/addon-stack.ts +998 -0
  290. package/src/bare-metal-partition.test.ts +4 -3
  291. package/src/composer.test.ts +4 -2
  292. package/src/composer.ts +24 -5
  293. package/src/generate.test.ts +2 -1
  294. package/src/generate.ts +10 -1
  295. package/src/generators/clone-repos.test.ts +154 -0
  296. package/src/generators/clone-repos.ts +159 -0
  297. package/src/generators/postgres-init.ts +17 -0
  298. package/src/generators/scripts.test.ts +52 -4
  299. package/src/generators/scripts.ts +351 -3
  300. package/src/generators/stack-manifest.ts +4 -2
  301. package/src/index.ts +28 -2
  302. package/src/presets/registry.ts +241 -329
  303. package/src/resolver.test.ts +53 -15
  304. package/src/resolver.ts +13 -1
  305. package/src/schema.ts +216 -4
  306. package/src/services/definitions/apptension-saas.ts +84 -0
  307. package/src/services/definitions/boxyhq-saas.ts +84 -0
  308. package/src/services/definitions/browserless.ts +3 -0
  309. package/src/services/definitions/cmsaas-starter.ts +84 -0
  310. package/src/services/definitions/convex.ts +31 -0
  311. package/src/services/definitions/grafana.ts +9 -0
  312. package/src/services/definitions/index.ts +90 -70
  313. package/src/services/definitions/ixartz-saas.ts +84 -0
  314. package/src/services/definitions/meilisearch.ts +9 -0
  315. package/src/services/definitions/minio.ts +2 -0
  316. package/src/services/definitions/mission-control.ts +19 -2
  317. package/src/services/definitions/n8n.ts +9 -0
  318. package/src/services/definitions/ollama.ts +2 -0
  319. package/src/services/definitions/open-saas.ts +79 -0
  320. package/src/services/definitions/qdrant.ts +2 -0
  321. package/src/services/definitions/searxng.ts +3 -0
  322. package/src/services/definitions/uptime-kuma.ts +3 -0
  323. package/src/services/registry.test.ts +8 -0
  324. package/src/services/registry.ts +7 -0
  325. package/src/skills/manifest.json +64 -0
  326. package/src/skills/registry.ts +3 -3
  327. package/src/track-analytics.test.ts +82 -0
  328. package/src/track-analytics.ts +76 -0
  329. package/src/types.ts +29 -0
  330. package/src/version-manager.test.ts +10 -5
  331. package/src/version-manager.ts +1 -1
  332. package/dist/schema-B4c64P8N.d.cts.map +0 -1
  333. package/dist/schema-CXNhYci1.d.mts.map +0 -1
  334. package/dist/vi.2VT5v0um-CRqXre87.cjs.map +0 -1
  335. package/dist/vi.2VT5v0um-DvC3SVNc.mjs.map +0 -1
@@ -50,4 +50,7 @@ export const uptimeKumaDefinition: ServiceDefinition = {
50
50
 
51
51
  minMemoryMB: 256,
52
52
  gpuRequired: false,
53
+ capDropCompatible: false,
54
+ proxyPath: "/uptime-kuma",
55
+ firstBootCapabilities: ["CHOWN", "SETGID", "SETUID"],
53
56
  };
@@ -31,6 +31,14 @@ describe("service registry", () => {
31
31
  expect(tailscale!.mandatory).toBe(true);
32
32
  });
33
33
 
34
+ it("finds mission-control and it is mandatory with gitSource", () => {
35
+ const mc = getServiceById("mission-control");
36
+ expect(mc).toBeDefined();
37
+ expect(mc!.mandatory).toBe(true);
38
+ expect(mc!.gitSource).toBeDefined();
39
+ expect(mc!.gitSource!.repoUrl).toContain("better-openclaw-mission-control");
40
+ });
41
+
34
42
  it("finds coolify, dokploy, livekit, and La Suite Meet services by ID", () => {
35
43
  expect(getServiceById("coolify")).toBeDefined();
36
44
  expect(getServiceById("dokploy")).toBeDefined();
@@ -10,6 +10,13 @@ for (const def of allServiceDefinitions) {
10
10
  `Duplicate service definition ID: "${def.id}". Each service must have a unique ID.`,
11
11
  );
12
12
  }
13
+ const hasImage = def.image && def.imageTag;
14
+ const hasGitSource = def.gitSource && def.buildContext;
15
+ if (!hasImage && !hasGitSource) {
16
+ throw new Error(
17
+ `Service "${def.id}" must specify either image+imageTag or gitSource+buildContext.`,
18
+ );
19
+ }
13
20
  registryMap.set(def.id, def);
14
21
  }
15
22
 
@@ -1445,6 +1445,70 @@
1445
1445
  "services": [
1446
1446
  "headscale"
1447
1447
  ]
1448
+ },
1449
+ {
1450
+ "id": "langfuse-trace",
1451
+ "path": "langfuse-trace/SKILL.md",
1452
+ "emoji": "📊",
1453
+ "services": [
1454
+ "langfuse"
1455
+ ]
1456
+ },
1457
+ {
1458
+ "id": "twenty-crm",
1459
+ "path": "twenty-crm/SKILL.md",
1460
+ "emoji": "📇",
1461
+ "services": [
1462
+ "twenty"
1463
+ ]
1464
+ },
1465
+ {
1466
+ "id": "mautic-campaign",
1467
+ "path": "mautic-campaign/SKILL.md",
1468
+ "emoji": "📬",
1469
+ "services": [
1470
+ "mautic"
1471
+ ]
1472
+ },
1473
+ {
1474
+ "id": "airflow-dag",
1475
+ "path": "airflow-dag/SKILL.md",
1476
+ "emoji": "🌪️",
1477
+ "services": [
1478
+ "airflow"
1479
+ ]
1480
+ },
1481
+ {
1482
+ "id": "airbyte-sync",
1483
+ "path": "airbyte-sync/SKILL.md",
1484
+ "emoji": "🔗",
1485
+ "services": [
1486
+ "airbyte"
1487
+ ]
1488
+ },
1489
+ {
1490
+ "id": "fonoster-voice",
1491
+ "path": "fonoster-voice/SKILL.md",
1492
+ "emoji": "📞",
1493
+ "services": [
1494
+ "fonoster"
1495
+ ]
1496
+ },
1497
+ {
1498
+ "id": "medusa-commerce",
1499
+ "path": "medusa-commerce/SKILL.md",
1500
+ "emoji": "🛒",
1501
+ "services": [
1502
+ "medusa"
1503
+ ]
1504
+ },
1505
+ {
1506
+ "id": "axolotl-finetune",
1507
+ "path": "axolotl-finetune/SKILL.md",
1508
+ "emoji": "🦎",
1509
+ "services": [
1510
+ "axolotl"
1511
+ ]
1448
1512
  }
1449
1513
  ]
1450
1514
  }
@@ -473,7 +473,7 @@ const skillPacks: SkillPack[] = [
473
473
  description:
474
474
  "AI-powered helpdesk with live chat, LLM observability, and ticket management across channels",
475
475
  requiredServices: ["chatwoot", "langfuse", "postgresql", "redis"],
476
- skills: ["chatwoot-inbox", "langfuse-trace", "postgresql-query", "redis-cache"],
476
+ skills: ["chatwoot-support", "langfuse-trace", "postgresql-query", "redis-cache"],
477
477
  icon: "💬",
478
478
  tags: ["support", "chat", "helpdesk", "tickets", "customer-service"],
479
479
  },
@@ -483,7 +483,7 @@ const skillPacks: SkillPack[] = [
483
483
  description:
484
484
  "CRM-driven sales pipeline with email marketing, newsletter management, and lead nurturing",
485
485
  requiredServices: ["twenty", "mautic", "listmonk", "postgresql"],
486
- skills: ["twenty-crm", "mautic-campaign", "listmonk-newsletter", "postgresql-query"],
486
+ skills: ["twenty-crm", "mautic-campaign", "listmonk-email", "postgresql-query"],
487
487
  icon: "📈",
488
488
  tags: ["sales", "crm", "email", "leads", "marketing"],
489
489
  },
@@ -543,7 +543,7 @@ const skillPacks: SkillPack[] = [
543
543
  description:
544
544
  "Full marketing stack with blogging, email automation, newsletter management, and web analytics",
545
545
  requiredServices: ["ghost", "mautic", "listmonk", "umami"],
546
- skills: ["ghost-publish", "mautic-campaign", "listmonk-newsletter", "umami-analytics"],
546
+ skills: ["ghost-publish", "mautic-campaign", "listmonk-email", "umami-analytics"],
547
547
  icon: "📣",
548
548
  tags: ["marketing", "blog", "email", "analytics", "content"],
549
549
  },
@@ -0,0 +1,82 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildAnalyticsPayload } from "./track-analytics.js";
3
+ import type { GenerationInput, GenerationMetadata } from "./types.js";
4
+
5
+ const baseInput: GenerationInput = {
6
+ projectName: "test-stack",
7
+ services: ["postgresql", "redis", "n8n"],
8
+ skillPacks: ["research-agent"],
9
+ aiProviders: ["openai"],
10
+ gsdRuntimes: [],
11
+ proxy: "caddy",
12
+ domain: "example.com",
13
+ gpu: false,
14
+ platform: "linux/amd64",
15
+ deployment: "local",
16
+ deploymentType: "docker",
17
+ generateSecrets: true,
18
+ openclawVersion: "latest",
19
+ monitoring: true,
20
+ openclawImage: "official",
21
+ openclawInstallMethod: "docker",
22
+ hardened: true,
23
+ deployTarget: "local",
24
+ };
25
+
26
+ const baseMetadata: GenerationMetadata = {
27
+ serviceCount: 5,
28
+ skillCount: 1,
29
+ estimatedMemoryMB: 2048,
30
+ resolvedServices: ["postgresql", "redis", "n8n", "caddy", "searxng"],
31
+ generatedAt: "2026-03-09T00:00:00.000Z",
32
+ };
33
+
34
+ describe("buildAnalyticsPayload", () => {
35
+ it("builds payload for a preset-based CLI generation", () => {
36
+ const payload = buildAnalyticsPayload(baseInput, baseMetadata, "cli", "researcher");
37
+
38
+ expect(payload.source).toBe("cli");
39
+ expect(payload.buildMethod).toBe("preset");
40
+ expect(payload.presetId).toBe("researcher");
41
+ expect(payload.services).toEqual(["postgresql", "redis", "n8n"]);
42
+ expect(payload.skillPacks).toEqual(["research-agent"]);
43
+ expect(payload.serviceCount).toBe(5);
44
+ expect(payload.proxy).toBe("caddy");
45
+ expect(payload.deployment).toBe("local");
46
+ expect(payload.deploymentType).toBe("docker");
47
+ expect(payload.platform).toBe("linux/amd64");
48
+ expect(payload.gpu).toBe(false);
49
+ expect(payload.monitoring).toBe(true);
50
+ expect(payload.hasDomain).toBe(true);
51
+ expect(payload.openclawImage).toBe("official");
52
+ expect(payload.estimatedMemoryMB).toBe(2048);
53
+ });
54
+
55
+ it("sets buildMethod to custom when no presetId", () => {
56
+ const payload = buildAnalyticsPayload(baseInput, baseMetadata, "web");
57
+
58
+ expect(payload.buildMethod).toBe("custom");
59
+ expect(payload.presetId).toBeNull();
60
+ });
61
+
62
+ it("sets buildMethod to custom when presetId is null", () => {
63
+ const payload = buildAnalyticsPayload(baseInput, baseMetadata, "api", null);
64
+
65
+ expect(payload.buildMethod).toBe("custom");
66
+ expect(payload.presetId).toBeNull();
67
+ });
68
+
69
+ it("sets hasDomain to false when no domain in input", () => {
70
+ const noDomainInput = { ...baseInput, domain: undefined };
71
+ const payload = buildAnalyticsPayload(noDomainInput, baseMetadata, "mcp");
72
+
73
+ expect(payload.hasDomain).toBe(false);
74
+ });
75
+
76
+ it("preserves all source types", () => {
77
+ for (const source of ["cli", "web", "api", "mcp"] as const) {
78
+ const payload = buildAnalyticsPayload(baseInput, baseMetadata, source);
79
+ expect(payload.source).toBe(source);
80
+ }
81
+ });
82
+ });
@@ -0,0 +1,76 @@
1
+ import type { GenerationInput, GenerationMetadata } from "./types.js";
2
+
3
+ export interface AnalyticsPayload {
4
+ source: "cli" | "web" | "api" | "mcp";
5
+ buildMethod: "preset" | "custom";
6
+ presetId: string | null;
7
+ services: string[];
8
+ skillPacks: string[];
9
+ serviceCount: number;
10
+ proxy: string;
11
+ deployment: string;
12
+ deploymentType: string;
13
+ platform: string;
14
+ gpu: boolean;
15
+ monitoring: boolean;
16
+ hasDomain: boolean;
17
+ openclawImage: string;
18
+ estimatedMemoryMB: number;
19
+ }
20
+
21
+ /**
22
+ * Build an analytics payload from generation input and metadata.
23
+ * Pure function — does not send anything.
24
+ */
25
+ export function buildAnalyticsPayload(
26
+ input: GenerationInput,
27
+ metadata: GenerationMetadata,
28
+ source: AnalyticsPayload["source"],
29
+ presetId?: string | null,
30
+ ): AnalyticsPayload {
31
+ return {
32
+ source,
33
+ buildMethod: presetId ? "preset" : "custom",
34
+ presetId: presetId ?? null,
35
+ services: input.services,
36
+ skillPacks: input.skillPacks,
37
+ serviceCount: metadata.serviceCount,
38
+ proxy: input.proxy,
39
+ deployment: input.deployment,
40
+ deploymentType: input.deploymentType,
41
+ platform: input.platform,
42
+ gpu: input.gpu,
43
+ monitoring: input.monitoring,
44
+ hasDomain: Boolean(input.domain),
45
+ openclawImage: input.openclawImage,
46
+ estimatedMemoryMB: metadata.estimatedMemoryMB,
47
+ };
48
+ }
49
+
50
+ const DEFAULT_API_URL = "https://better-openclaw.dev/api/v1/analytics/event";
51
+
52
+ /**
53
+ * Fire-and-forget POST to the analytics endpoint.
54
+ * Respects DISABLE_ANALYTICS=true env var.
55
+ * Silently catches all errors — tracking must never crash the main flow.
56
+ */
57
+ export async function trackAnalytics(
58
+ payload: AnalyticsPayload,
59
+ apiUrl: string = DEFAULT_API_URL,
60
+ ): Promise<void> {
61
+ if (process.env.DISABLE_ANALYTICS === "true") return;
62
+
63
+ try {
64
+ const controller = new AbortController();
65
+ const timeout = setTimeout(() => controller.abort(), 5000);
66
+ await fetch(apiUrl, {
67
+ method: "POST",
68
+ headers: { "Content-Type": "application/json" },
69
+ body: JSON.stringify(payload),
70
+ signal: controller.signal,
71
+ });
72
+ clearTimeout(timeout);
73
+ } catch {
74
+ // Silent — tracking must never block or crash generation
75
+ }
76
+ }
package/src/types.ts CHANGED
@@ -1,16 +1,24 @@
1
1
  import type { z } from "zod";
2
2
  import type {
3
+ AddonStackInputSchema,
4
+ AddonStackResultSchema,
5
+ AddonStackUpdateInputSchema,
6
+ AddonStackUpdateResultSchema,
3
7
  AddedDependencySchema,
4
8
  AiProviderSchema,
5
9
  ApiErrorSchema,
10
+ BuildContextSchema,
6
11
  ComposeOptionsSchema,
7
12
  DeploymentTargetSchema,
8
13
  DeploymentTypeSchema,
9
14
  DeploySchema,
10
15
  DeployTargetSchema,
16
+ EnvQuirkFixSchema,
17
+ EnvQuirkSchema,
11
18
  EnvVariableSchema,
12
19
  ErrorSchema,
13
20
  GenerationInputSchema,
21
+ GitSourceSchema,
14
22
  GsdRuntimeSchema,
15
23
  HealthCheckSchema,
16
24
  MaturitySchema,
@@ -22,6 +30,7 @@ import type {
22
30
  PlatformSchema,
23
31
  PortMappingSchema,
24
32
  PresetSchema,
33
+ ProxyRouteSchema,
25
34
  ProxyTypeSchema,
26
35
  ResolvedServiceSchema,
27
36
  ResolverOutputSchema,
@@ -31,6 +40,7 @@ import type {
31
40
  ServiceDefinitionSchema,
32
41
  SkillBindingSchema,
33
42
  SkillPackSchema,
43
+ SkippedServiceSchema,
34
44
  ValidateRequestSchema,
35
45
  ValidateResponseSchema,
36
46
  VolumeMappingSchema,
@@ -50,6 +60,8 @@ export type DeploymentTarget = z.infer<typeof DeploymentTargetSchema>;
50
60
  export type DeploymentType = z.infer<typeof DeploymentTypeSchema>;
51
61
  export type NativePlatform = z.infer<typeof NativePlatformSchema>;
52
62
  export type NativeRecipe = z.infer<typeof NativeRecipeSchema>;
63
+ export type GitSource = z.infer<typeof GitSourceSchema>;
64
+ export type BuildContext = z.infer<typeof BuildContextSchema>;
53
65
  export type OutputFormat = z.infer<typeof OutputFormatSchema>;
54
66
  export type OpenclawImageVariant = z.infer<typeof OpenclawImageVariantSchema>;
55
67
  export type OpenclawInstallMethod = z.infer<typeof OpenclawInstallMethodSchema>;
@@ -82,6 +94,16 @@ export type ValidateRequest = z.infer<typeof ValidateRequestSchema>;
82
94
  export type ValidateResponse = z.infer<typeof ValidateResponseSchema>;
83
95
  export type ApiError = z.infer<typeof ApiErrorSchema>;
84
96
 
97
+ // Addon Stack (Clawexa)
98
+ export type EnvQuirkFix = z.infer<typeof EnvQuirkFixSchema>;
99
+ export type EnvQuirk = z.infer<typeof EnvQuirkSchema>;
100
+ export type ProxyRoute = z.infer<typeof ProxyRouteSchema>;
101
+ export type SkippedService = z.infer<typeof SkippedServiceSchema>;
102
+ export type AddonStackInput = z.infer<typeof AddonStackInputSchema>;
103
+ export type AddonStackResult = z.infer<typeof AddonStackResultSchema>;
104
+ export type AddonStackUpdateInput = z.infer<typeof AddonStackUpdateInputSchema>;
105
+ export type AddonStackUpdateResult = z.infer<typeof AddonStackUpdateResultSchema>;
106
+
85
107
  // ─── Additional Types ───────────────────────────────────────────────────────
86
108
 
87
109
  export interface ResolverInput {
@@ -369,4 +391,11 @@ export const SERVICE_CATEGORIES: CategoryInfo[] = [
369
391
  label: "IoT & Edge",
370
392
  icon: "📡",
371
393
  },
394
+ {
395
+ id: "saas-boilerplate",
396
+ name: "SaaS Boilerplates",
397
+ description: "Full-stack SaaS starter kits and boilerplates",
398
+ label: "SaaS Boilerplates",
399
+ icon: "🚀",
400
+ },
372
401
  ];
@@ -48,9 +48,11 @@ describe("pinImageTags", () => {
48
48
  expect(pinned.services).toHaveLength(resolved.services.length);
49
49
 
50
50
  for (const svc of pinned.services) {
51
+ // Git-based services (e.g., mission-control) don't have imageTag
52
+ if (svc.definition.gitSource) continue;
51
53
  expect(svc.definition.imageTag).toBeDefined();
52
54
  expect(typeof svc.definition.imageTag).toBe("string");
53
- expect(svc.definition.imageTag.length).toBeGreaterThan(0);
55
+ expect(svc.definition.imageTag!.length).toBeGreaterThan(0);
54
56
  }
55
57
  });
56
58
 
@@ -63,10 +65,12 @@ describe("pinImageTags", () => {
63
65
  platform: "linux/amd64",
64
66
  });
65
67
 
66
- const originalTag = resolved.services[0]?.definition.imageTag;
68
+ const redis = resolved.services.find((s) => s.definition.id === "redis");
69
+ const originalTag = redis?.definition.imageTag;
67
70
  pinImageTags(resolved);
68
71
 
69
- expect(resolved.services[0]?.definition.imageTag).toBe(originalTag);
72
+ const redisAfter = resolved.services.find((s) => s.definition.id === "redis");
73
+ expect(redisAfter?.definition.imageTag).toBe(originalTag);
70
74
  });
71
75
 
72
76
  it("preserves non-tag properties", () => {
@@ -79,8 +83,9 @@ describe("pinImageTags", () => {
79
83
  });
80
84
 
81
85
  const pinned = pinImageTags(resolved);
82
- expect(pinned.services[0]?.definition.id).toBe("redis");
83
- expect(pinned.services[0]?.definition.name).toBe("Redis");
86
+ const redis = pinned.services.find((s) => s.definition.id === "redis");
87
+ expect(redis).toBeDefined();
88
+ expect(redis!.definition.name).toBe("Redis");
84
89
  expect(pinned.estimatedMemoryMB).toBe(resolved.estimatedMemoryMB);
85
90
  });
86
91
  });
@@ -10,7 +10,7 @@ export function getImageTag(serviceId: string): string | undefined {
10
10
  /** Get the full image reference (image:tag) for a service */
11
11
  export function getImageReference(serviceId: string): string | undefined {
12
12
  const svc = getServiceById(serviceId);
13
- if (!svc) return undefined;
13
+ if (!svc || !svc.image || !svc.imageTag) return undefined;
14
14
  return `${svc.image}:${svc.imageTag}`;
15
15
  }
16
16
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema-B4c64P8N.d.cts","names":[],"sources":["../src/schema.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema-CXNhYci1.d.mts","names":[],"sources":["../src/schema.ts"],"mappings":"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"}