@better-openclaw/core 1.0.8 → 1.0.10
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.
- package/dist/bare-metal-partition.d.mts.map +1 -1
- package/dist/bare-metal-partition.mjs +1 -0
- package/dist/bare-metal-partition.mjs.map +1 -1
- package/dist/bare-metal-partition.test.mjs +1 -1
- package/dist/composer.d.mts.map +1 -1
- package/dist/composer.mjs +11 -1
- package/dist/composer.mjs.map +1 -1
- package/dist/composer.snapshot.test.mjs +1 -1
- package/dist/composer.test.mjs +1 -1
- package/dist/errors.d.mts +17 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +24 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/generate.d.mts +4 -3
- package/dist/generate.d.mts.map +1 -1
- package/dist/generate.mjs +13 -5
- package/dist/generate.mjs.map +1 -1
- package/dist/generate.test.mjs +1 -1
- package/dist/generators/bare-metal-install.test.mjs +1 -1
- package/dist/generators/traefik.d.mts +19 -0
- package/dist/generators/traefik.d.mts.map +1 -0
- package/dist/generators/traefik.mjs +86 -0
- package/dist/generators/traefik.mjs.map +1 -0
- package/dist/generators/traefik.test.d.mts +1 -0
- package/dist/generators/traefik.test.mjs +69 -0
- package/dist/generators/traefik.test.mjs.map +1 -0
- package/dist/index.d.mts +4 -2
- package/dist/index.mjs +4 -2
- package/dist/migrations.d.mts +14 -0
- package/dist/migrations.d.mts.map +1 -0
- package/dist/migrations.mjs +33 -0
- package/dist/migrations.mjs.map +1 -0
- package/dist/migrations.test.d.mts +1 -0
- package/dist/migrations.test.mjs +42 -0
- package/dist/migrations.test.mjs.map +1 -0
- package/dist/presets/registry.test.mjs +1 -1
- package/dist/resolver.d.mts +6 -1
- package/dist/resolver.d.mts.map +1 -1
- package/dist/resolver.mjs +21 -3
- package/dist/resolver.mjs.map +1 -1
- package/dist/resolver.test.mjs +1 -1
- package/dist/schema.d.mts +1 -0
- package/dist/schema.d.mts.map +1 -1
- package/dist/schema.mjs +1 -0
- package/dist/schema.mjs.map +1 -1
- package/dist/schema.test.mjs +1 -1
- package/dist/services/definitions/caddy.mjs +20 -1
- package/dist/services/definitions/caddy.mjs.map +1 -1
- package/dist/services/definitions/cal-com.d.mts +7 -0
- package/dist/services/definitions/cal-com.d.mts.map +1 -0
- package/dist/services/definitions/cal-com.mjs +88 -0
- package/dist/services/definitions/cal-com.mjs.map +1 -0
- package/dist/services/definitions/grafana.mjs +13 -1
- package/dist/services/definitions/grafana.mjs.map +1 -1
- package/dist/services/definitions/index.d.mts +4 -1
- package/dist/services/definitions/index.d.mts.map +1 -1
- package/dist/services/definitions/index.mjs +8 -2
- package/dist/services/definitions/index.mjs.map +1 -1
- package/dist/services/definitions/neo4j.d.mts +7 -0
- package/dist/services/definitions/neo4j.d.mts.map +1 -0
- package/dist/services/definitions/neo4j.mjs +91 -0
- package/dist/services/definitions/neo4j.mjs.map +1 -0
- package/dist/services/definitions/traefik.mjs +0 -1
- package/dist/services/definitions/traefik.mjs.map +1 -1
- package/dist/services/definitions/xyops.d.mts +7 -0
- package/dist/services/definitions/xyops.d.mts.map +1 -0
- package/dist/services/definitions/xyops.mjs +86 -0
- package/dist/services/definitions/xyops.mjs.map +1 -0
- package/dist/services/registry.test.mjs +1 -1
- package/dist/skills/registry.d.mts.map +1 -1
- package/dist/skills/registry.mjs +454 -6
- package/dist/skills/registry.mjs.map +1 -1
- package/dist/types.d.mts +8 -1
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/validator.mjs +11 -0
- package/dist/validator.mjs.map +1 -1
- package/dist/validator.test.mjs +1 -1
- package/dist/version-manager.d.mts +1 -1
- package/dist/version-manager.d.mts.map +1 -1
- package/dist/version-manager.mjs +11 -5
- package/dist/version-manager.mjs.map +1 -1
- package/dist/version-manager.test.d.mts +1 -0
- package/dist/version-manager.test.mjs +102 -0
- package/dist/version-manager.test.mjs.map +1 -0
- package/dist/{vi.2VT5v0um-Qk6MgAnK.mjs → vi.2VT5v0um-YSByewHe.mjs} +5 -5
- package/dist/{vi.2VT5v0um-Qk6MgAnK.mjs.map → vi.2VT5v0um-YSByewHe.mjs.map} +1 -1
- package/package.json +1 -1
- package/src/__snapshots__/composer.snapshot.test.ts.snap +15 -1
- package/src/bare-metal-partition.ts +1 -0
- package/src/composer.ts +22 -1
- package/src/errors.ts +23 -0
- package/src/generate.ts +22 -4
- package/src/generators/traefik.test.ts +97 -0
- package/src/generators/traefik.ts +104 -0
- package/src/index.ts +7 -1
- package/src/migrations.test.ts +36 -0
- package/src/migrations.ts +49 -0
- package/src/resolver.ts +37 -3
- package/src/schema.ts +1 -0
- package/src/services/definitions/caddy.ts +23 -1
- package/src/services/definitions/cal-com.ts +91 -0
- package/src/services/definitions/grafana.ts +16 -1
- package/src/services/definitions/index.ts +9 -0
- package/src/services/definitions/neo4j.ts +96 -0
- package/src/services/definitions/traefik.ts +0 -2
- package/src/services/definitions/xyops.ts +94 -0
- package/src/skills/registry.ts +352 -6
- package/src/types.ts +5 -1
- package/src/validator.ts +16 -0
- package/src/version-manager.test.ts +134 -0
- package/src/version-manager.ts +12 -5
package/src/skills/registry.ts
CHANGED
|
@@ -35,7 +35,13 @@ const skillPacks: SkillPack[] = [
|
|
|
35
35
|
name: "DevOps",
|
|
36
36
|
description: "Monitor services, automate workflows, and manage infrastructure alerts",
|
|
37
37
|
requiredServices: ["n8n", "redis", "uptime-kuma", "grafana", "prometheus"],
|
|
38
|
-
skills: [
|
|
38
|
+
skills: [
|
|
39
|
+
"n8n-trigger",
|
|
40
|
+
"redis-cache",
|
|
41
|
+
"grafana-dashboard",
|
|
42
|
+
"prometheus-query",
|
|
43
|
+
"uptime-kuma-monitor",
|
|
44
|
+
],
|
|
39
45
|
icon: "⚙️",
|
|
40
46
|
tags: ["devops", "monitoring", "automation"],
|
|
41
47
|
},
|
|
@@ -45,7 +51,7 @@ const skillPacks: SkillPack[] = [
|
|
|
45
51
|
description:
|
|
46
52
|
"Index documents with vector search and full-text search for comprehensive retrieval",
|
|
47
53
|
requiredServices: ["qdrant", "postgresql", "meilisearch"],
|
|
48
|
-
skills: ["qdrant-memory"],
|
|
54
|
+
skills: ["qdrant-memory", "postgresql-query", "meilisearch-index"],
|
|
49
55
|
icon: "📚",
|
|
50
56
|
tags: ["knowledge", "search", "indexing"],
|
|
51
57
|
},
|
|
@@ -64,7 +70,12 @@ const skillPacks: SkillPack[] = [
|
|
|
64
70
|
description:
|
|
65
71
|
"Full social media content pipeline with scheduling, media processing, analytics, and storage",
|
|
66
72
|
requiredServices: ["postiz", "ffmpeg", "minio", "redis", "postgresql"],
|
|
67
|
-
skills: [
|
|
73
|
+
skills: [
|
|
74
|
+
"ffmpeg-process",
|
|
75
|
+
"minio-storage",
|
|
76
|
+
"redis-cache",
|
|
77
|
+
"postiz-schedule",
|
|
78
|
+
],
|
|
68
79
|
icon: "📱",
|
|
69
80
|
tags: ["social-media", "content", "scheduling", "analytics"],
|
|
70
81
|
},
|
|
@@ -74,7 +85,7 @@ const skillPacks: SkillPack[] = [
|
|
|
74
85
|
description:
|
|
75
86
|
"Full AI experimentation stack with chat UIs, LLM gateway, local models, and document chat",
|
|
76
87
|
requiredServices: ["ollama", "open-webui", "litellm"],
|
|
77
|
-
skills: ["ollama-local-llm"],
|
|
88
|
+
skills: ["ollama-local-llm", "open-webui-chat", "litellm-gateway"],
|
|
78
89
|
icon: "🧪",
|
|
79
90
|
tags: ["ai", "llm", "playground", "experimentation"],
|
|
80
91
|
},
|
|
@@ -84,7 +95,7 @@ const skillPacks: SkillPack[] = [
|
|
|
84
95
|
description:
|
|
85
96
|
"AI-powered development environment with coding agents, Git hosting, and browser IDE",
|
|
86
97
|
requiredServices: ["claude-code", "gitea", "code-server"],
|
|
87
|
-
skills: [],
|
|
98
|
+
skills: ["claude-code-assist", "gitea-repo", "code-server-develop"],
|
|
88
99
|
icon: "💻",
|
|
89
100
|
tags: ["coding", "development", "ide", "git"],
|
|
90
101
|
},
|
|
@@ -94,12 +105,347 @@ const skillPacks: SkillPack[] = [
|
|
|
94
105
|
description:
|
|
95
106
|
"Enterprise knowledge management with wiki, document processing, analytics, and vector search",
|
|
96
107
|
requiredServices: ["outline", "paperless-ngx", "qdrant", "postgresql", "redis"],
|
|
97
|
-
skills: [
|
|
108
|
+
skills: [
|
|
109
|
+
"qdrant-memory",
|
|
110
|
+
"outline-wiki",
|
|
111
|
+
"paperless-archive",
|
|
112
|
+
"postgresql-query",
|
|
113
|
+
"redis-cache",
|
|
114
|
+
],
|
|
98
115
|
icon: "📚",
|
|
99
116
|
tags: ["knowledge", "wiki", "documents", "search"],
|
|
100
117
|
},
|
|
118
|
+
// ── New Skill Packs ───────────────────────────────────────────────
|
|
119
|
+
{
|
|
120
|
+
id: "data-engineer",
|
|
121
|
+
name: "Data Engineer",
|
|
122
|
+
description:
|
|
123
|
+
"Process and transform data with PostgreSQL, CSV/JSON/XML transforms, and PDF extraction",
|
|
124
|
+
requiredServices: ["postgresql"],
|
|
125
|
+
skills: [
|
|
126
|
+
"postgresql-query",
|
|
127
|
+
"csv-transform",
|
|
128
|
+
"json-transform",
|
|
129
|
+
"xml-parse",
|
|
130
|
+
"pdf-extract",
|
|
131
|
+
"excel-process",
|
|
132
|
+
"markdown-convert",
|
|
133
|
+
],
|
|
134
|
+
icon: "🔧",
|
|
135
|
+
tags: ["data", "etl", "transform", "processing"],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "nlp-pipeline",
|
|
139
|
+
name: "NLP Pipeline",
|
|
140
|
+
description:
|
|
141
|
+
"Natural language processing with summarization, translation, classification, and embeddings via Ollama",
|
|
142
|
+
requiredServices: ["ollama"],
|
|
143
|
+
skills: [
|
|
144
|
+
"text-summarize",
|
|
145
|
+
"text-translate",
|
|
146
|
+
"text-classify",
|
|
147
|
+
"text-embed",
|
|
148
|
+
"ollama-local-llm",
|
|
149
|
+
],
|
|
150
|
+
icon: "🧠",
|
|
151
|
+
tags: ["nlp", "text", "embeddings", "translation"],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: "image-processor",
|
|
155
|
+
name: "Image Processor",
|
|
156
|
+
description:
|
|
157
|
+
"Resize, convert, and OCR images with ImageMagick and Tesseract",
|
|
158
|
+
requiredServices: ["ffmpeg"],
|
|
159
|
+
skills: [
|
|
160
|
+
"image-resize",
|
|
161
|
+
"image-convert",
|
|
162
|
+
"image-ocr",
|
|
163
|
+
"ffmpeg-process",
|
|
164
|
+
],
|
|
165
|
+
icon: "🖼️",
|
|
166
|
+
tags: ["image", "ocr", "media", "conversion"],
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "api-integrator",
|
|
170
|
+
name: "API Integrator",
|
|
171
|
+
description:
|
|
172
|
+
"HTTP requests, webhooks, and GraphQL queries for external API integration",
|
|
173
|
+
requiredServices: [],
|
|
174
|
+
skills: [
|
|
175
|
+
"http-request",
|
|
176
|
+
"api-webhook",
|
|
177
|
+
"graphql-query",
|
|
178
|
+
],
|
|
179
|
+
icon: "🌐",
|
|
180
|
+
tags: ["api", "http", "webhook", "graphql"],
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: "security-ops",
|
|
184
|
+
name: "Security Ops",
|
|
185
|
+
description:
|
|
186
|
+
"JWT validation, hashing, SSL checks, port scanning, and network diagnostics",
|
|
187
|
+
requiredServices: [],
|
|
188
|
+
skills: [
|
|
189
|
+
"jwt-manage",
|
|
190
|
+
"hash-generate",
|
|
191
|
+
"ssl-check",
|
|
192
|
+
"dns-lookup",
|
|
193
|
+
"port-scan",
|
|
194
|
+
"ping-check",
|
|
195
|
+
],
|
|
196
|
+
icon: "🛡️",
|
|
197
|
+
tags: ["security", "networking", "diagnostics"],
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
id: "communication-hub",
|
|
201
|
+
name: "Communication Hub",
|
|
202
|
+
description:
|
|
203
|
+
"Multi-channel messaging with Matrix, Mattermost, Rocket.Chat, email, and push notifications",
|
|
204
|
+
requiredServices: ["matrix-synapse", "gotify"],
|
|
205
|
+
skills: [
|
|
206
|
+
"matrix-message",
|
|
207
|
+
"mattermost-post",
|
|
208
|
+
"rocketchat-send",
|
|
209
|
+
"gotify-notify",
|
|
210
|
+
"ntfy-publish",
|
|
211
|
+
"email-send",
|
|
212
|
+
],
|
|
213
|
+
icon: "📨",
|
|
214
|
+
tags: ["messaging", "notifications", "email", "chat"],
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: "analytics-suite",
|
|
218
|
+
name: "Analytics Suite",
|
|
219
|
+
description:
|
|
220
|
+
"Web and product analytics with Matomo, Umami, OpenPanel, Grafana, and Prometheus",
|
|
221
|
+
requiredServices: ["grafana", "prometheus"],
|
|
222
|
+
skills: [
|
|
223
|
+
"matomo-track",
|
|
224
|
+
"umami-analytics",
|
|
225
|
+
"openpanel-analyze",
|
|
226
|
+
"grafana-dashboard",
|
|
227
|
+
"prometheus-query",
|
|
228
|
+
],
|
|
229
|
+
icon: "📊",
|
|
230
|
+
tags: ["analytics", "monitoring", "metrics", "dashboards"],
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: "full-devops",
|
|
234
|
+
name: "Full DevOps",
|
|
235
|
+
description:
|
|
236
|
+
"Complete DevOps toolkit with Git hosting, container management, deployments, monitoring, and log viewing",
|
|
237
|
+
requiredServices: ["gitea", "portainer", "coolify", "grafana", "prometheus"],
|
|
238
|
+
skills: [
|
|
239
|
+
"gitea-repo",
|
|
240
|
+
"portainer-manage",
|
|
241
|
+
"coolify-deploy",
|
|
242
|
+
"dokploy-deploy",
|
|
243
|
+
"watchtower-update",
|
|
244
|
+
"dozzle-logs",
|
|
245
|
+
"grafana-dashboard",
|
|
246
|
+
"prometheus-query",
|
|
247
|
+
"uptime-kuma-monitor",
|
|
248
|
+
"beszel-monitor",
|
|
249
|
+
],
|
|
250
|
+
icon: "🏗️",
|
|
251
|
+
tags: ["devops", "ci-cd", "containers", "deployment"],
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: "document-manager",
|
|
255
|
+
name: "Document Manager",
|
|
256
|
+
description:
|
|
257
|
+
"Document processing pipeline with wiki, archival, OCR, Q&A, and PDF extraction",
|
|
258
|
+
requiredServices: ["outline", "paperless-ngx"],
|
|
259
|
+
skills: [
|
|
260
|
+
"outline-wiki",
|
|
261
|
+
"paperless-archive",
|
|
262
|
+
"docsgpt-ask",
|
|
263
|
+
"pdf-extract",
|
|
264
|
+
"image-ocr",
|
|
265
|
+
],
|
|
266
|
+
icon: "📑",
|
|
267
|
+
tags: ["documents", "wiki", "ocr", "archive"],
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
id: "ai-coding-team",
|
|
271
|
+
name: "AI Coding Team",
|
|
272
|
+
description:
|
|
273
|
+
"Multi-agent AI coding ensemble with Claude Code, Codex, Gemini CLI, OpenCode, and browser IDE",
|
|
274
|
+
requiredServices: ["code-server", "gitea"],
|
|
275
|
+
skills: [
|
|
276
|
+
"claude-code-assist",
|
|
277
|
+
"codex-generate",
|
|
278
|
+
"gemini-cli-query",
|
|
279
|
+
"opencode-develop",
|
|
280
|
+
"code-server-develop",
|
|
281
|
+
"gitea-repo",
|
|
282
|
+
],
|
|
283
|
+
icon: "🤖",
|
|
284
|
+
tags: ["ai-coding", "agents", "development", "ide"],
|
|
285
|
+
},
|
|
286
|
+
// ── Internet-Verified Skill Packs ────────────────────────────────
|
|
287
|
+
{
|
|
288
|
+
id: "rag-pipeline",
|
|
289
|
+
name: "RAG Pipeline",
|
|
290
|
+
description:
|
|
291
|
+
"Build retrieval-augmented generation systems with LangChain, LlamaIndex, Haystack, and vector databases",
|
|
292
|
+
requiredServices: ["milvus"],
|
|
293
|
+
skills: [
|
|
294
|
+
"langchain-agent",
|
|
295
|
+
"llamaindex-query",
|
|
296
|
+
"haystack-rag",
|
|
297
|
+
"ragflow-pipeline",
|
|
298
|
+
"milvus-vectors",
|
|
299
|
+
"firecrawl-scrape",
|
|
300
|
+
],
|
|
301
|
+
icon: "🧠",
|
|
302
|
+
tags: ["rag", "ai", "embeddings", "search", "llm"],
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: "self-hosted-cloud",
|
|
306
|
+
name: "Self-Hosted Cloud",
|
|
307
|
+
description:
|
|
308
|
+
"Complete self-hosted infrastructure with cloud storage, photos, media streaming, and password management",
|
|
309
|
+
requiredServices: ["nextcloud", "immich", "jellyfin", "vaultwarden"],
|
|
310
|
+
skills: [
|
|
311
|
+
"nextcloud-files",
|
|
312
|
+
"immich-photos",
|
|
313
|
+
"jellyfin-media",
|
|
314
|
+
"vaultwarden-manage",
|
|
315
|
+
],
|
|
316
|
+
icon: "☁️",
|
|
317
|
+
tags: ["self-hosted", "cloud", "storage", "media", "security"],
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
id: "ai-agent-orchestra",
|
|
321
|
+
name: "AI Agent Orchestra",
|
|
322
|
+
description:
|
|
323
|
+
"Multi-agent AI orchestration with CrewAI, AutoGPT, LangChain, Langflow, and Open Interpreter",
|
|
324
|
+
requiredServices: [],
|
|
325
|
+
skills: [
|
|
326
|
+
"crewai-orchestrate",
|
|
327
|
+
"autogpt-autonomous",
|
|
328
|
+
"langchain-agent",
|
|
329
|
+
"langflow-build",
|
|
330
|
+
"open-interpreter-run",
|
|
331
|
+
],
|
|
332
|
+
icon: "🎭",
|
|
333
|
+
tags: ["ai", "agents", "multi-agent", "orchestration", "autonomous"],
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
id: "cicd-pipeline",
|
|
337
|
+
name: "CI/CD Pipeline",
|
|
338
|
+
description:
|
|
339
|
+
"Full CI/CD pipeline with Jenkins, ArgoCD, Woodpecker, and infrastructure as code",
|
|
340
|
+
requiredServices: ["jenkins"],
|
|
341
|
+
skills: [
|
|
342
|
+
"jenkins-pipeline",
|
|
343
|
+
"argocd-deploy",
|
|
344
|
+
"woodpecker-ci",
|
|
345
|
+
"terraform-provision",
|
|
346
|
+
"ansible-configure",
|
|
347
|
+
],
|
|
348
|
+
icon: "🔄",
|
|
349
|
+
tags: ["ci-cd", "devops", "gitops", "infrastructure"],
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
id: "zero-trust-security",
|
|
353
|
+
name: "Zero-Trust Security",
|
|
354
|
+
description:
|
|
355
|
+
"Enterprise security with SSO, secrets management, VPN, intrusion detection, and feature flags",
|
|
356
|
+
requiredServices: ["authentik", "crowdsec"],
|
|
357
|
+
skills: [
|
|
358
|
+
"authentik-auth",
|
|
359
|
+
"keycloak-auth",
|
|
360
|
+
"vault-secrets",
|
|
361
|
+
"infisical-secrets",
|
|
362
|
+
"netbird-vpn",
|
|
363
|
+
"teleport-access",
|
|
364
|
+
"crowdsec-protect",
|
|
365
|
+
],
|
|
366
|
+
icon: "🔒",
|
|
367
|
+
tags: ["security", "zero-trust", "sso", "secrets", "vpn"],
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: "content-platform",
|
|
371
|
+
name: "Content Platform",
|
|
372
|
+
description:
|
|
373
|
+
"Publishing and CMS platform with Ghost, Strapi, Directus, and newsletter management",
|
|
374
|
+
requiredServices: ["ghost"],
|
|
375
|
+
skills: [
|
|
376
|
+
"ghost-publish",
|
|
377
|
+
"strapi-cms",
|
|
378
|
+
"directus-cms",
|
|
379
|
+
"listmonk-email",
|
|
380
|
+
"plausible-analytics",
|
|
381
|
+
],
|
|
382
|
+
icon: "📝",
|
|
383
|
+
tags: ["cms", "publishing", "blog", "newsletter", "analytics"],
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
id: "backend-platform",
|
|
387
|
+
name: "Backend Platform",
|
|
388
|
+
description:
|
|
389
|
+
"Backend-as-a-service with Supabase, Appwrite, PocketBase, and API gateway",
|
|
390
|
+
requiredServices: ["supabase"],
|
|
391
|
+
skills: [
|
|
392
|
+
"supabase-query",
|
|
393
|
+
"appwrite-backend",
|
|
394
|
+
"pocketbase-backend",
|
|
395
|
+
"kong-gateway",
|
|
396
|
+
"rabbitmq-queue",
|
|
397
|
+
],
|
|
398
|
+
icon: "⚡",
|
|
399
|
+
tags: ["backend", "baas", "api", "database", "messaging"],
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
id: "observability-stack",
|
|
403
|
+
name: "Observability Stack",
|
|
404
|
+
description:
|
|
405
|
+
"Full observability with Loki logs, SigNoz APM, Sentry errors, Gatus health, and Elasticsearch",
|
|
406
|
+
requiredServices: ["loki", "signoz"],
|
|
407
|
+
skills: [
|
|
408
|
+
"loki-logs",
|
|
409
|
+
"signoz-observe",
|
|
410
|
+
"sentry-errors",
|
|
411
|
+
"gatus-health",
|
|
412
|
+
"elasticsearch-search",
|
|
413
|
+
],
|
|
414
|
+
icon: "📡",
|
|
415
|
+
tags: ["observability", "logs", "apm", "errors", "health"],
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
id: "document-hub",
|
|
419
|
+
name: "Document Hub",
|
|
420
|
+
description:
|
|
421
|
+
"Document management with Paperless-ngx, BookStack wiki, Stirling PDF tools, and Excalidraw",
|
|
422
|
+
requiredServices: ["paperless-ngx"],
|
|
423
|
+
skills: [
|
|
424
|
+
"paperless-ngx-docs",
|
|
425
|
+
"bookstack-wiki",
|
|
426
|
+
"stirling-pdf-tools",
|
|
427
|
+
"excalidraw-draw",
|
|
428
|
+
],
|
|
429
|
+
icon: "📑",
|
|
430
|
+
tags: ["documents", "wiki", "pdf", "collaboration"],
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
id: "smart-home",
|
|
434
|
+
name: "Smart Home",
|
|
435
|
+
description:
|
|
436
|
+
"Home automation and event-driven workflows with Home Assistant, Huginn, and Activepieces",
|
|
437
|
+
requiredServices: ["homeassistant"],
|
|
438
|
+
skills: [
|
|
439
|
+
"home-assistant-automate",
|
|
440
|
+
"huginn-automate",
|
|
441
|
+
"activepieces-flow",
|
|
442
|
+
],
|
|
443
|
+
icon: "🏠",
|
|
444
|
+
tags: ["iot", "automation", "smart-home", "workflows"],
|
|
445
|
+
},
|
|
101
446
|
];
|
|
102
447
|
|
|
448
|
+
|
|
103
449
|
const packMap = new Map<string, SkillPack>();
|
|
104
450
|
for (const pack of skillPacks) {
|
|
105
451
|
if (packMap.has(pack.id)) {
|
package/src/types.ts
CHANGED
|
@@ -58,7 +58,10 @@ export type SkillPack = z.infer<typeof SkillPackSchema>;
|
|
|
58
58
|
export type Preset = z.infer<typeof PresetSchema>;
|
|
59
59
|
|
|
60
60
|
export type GenerationInput = z.infer<typeof GenerationInputSchema>;
|
|
61
|
-
export type ComposeOptions = z.infer<typeof ComposeOptionsSchema
|
|
61
|
+
export type ComposeOptions = z.infer<typeof ComposeOptionsSchema> & {
|
|
62
|
+
/** Dynamic Traefik labels per service, computed by the Traefik generator. */
|
|
63
|
+
traefikLabels?: Map<string, Record<string, string>>;
|
|
64
|
+
};
|
|
62
65
|
export type ResolvedService = z.infer<typeof ResolvedServiceSchema>;
|
|
63
66
|
export type AddedDependency = z.infer<typeof AddedDependencySchema>;
|
|
64
67
|
export type Warning = z.infer<typeof WarningSchema>;
|
|
@@ -78,6 +81,7 @@ export interface ResolverInput {
|
|
|
78
81
|
gpu?: boolean;
|
|
79
82
|
platform?: Platform;
|
|
80
83
|
monitoring?: boolean;
|
|
84
|
+
memoryThresholds?: { info: number; warning: number; critical: number };
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
export interface GeneratedFiles {
|
package/src/validator.ts
CHANGED
|
@@ -93,6 +93,22 @@ function checkEnvCompleteness(
|
|
|
93
93
|
message: `Secret "${envVar.key}" for "${svc.definition.name}" needs to be configured manually`,
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
|
+
if (envVar.validation && envVar.defaultValue) {
|
|
97
|
+
try {
|
|
98
|
+
const regex = new RegExp(envVar.validation);
|
|
99
|
+
if (!regex.test(envVar.defaultValue)) {
|
|
100
|
+
warnings.push({
|
|
101
|
+
type: "env_validation",
|
|
102
|
+
message: `Environment variable "${envVar.key}" for "${svc.definition.name}" default value does not match validation pattern: ${envVar.validation}`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
} catch {
|
|
106
|
+
warnings.push({
|
|
107
|
+
type: "env_validation",
|
|
108
|
+
message: `Environment variable "${envVar.key}" for "${svc.definition.name}" has invalid validation regex: ${envVar.validation}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
96
112
|
}
|
|
97
113
|
}
|
|
98
114
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { resolve } from "./resolver.js";
|
|
3
|
+
import { getAllServices, getServiceById } from "./services/registry.js";
|
|
4
|
+
import { checkCompatibility, getImageReference, getImageTag, pinImageTags } from "./version-manager.js";
|
|
5
|
+
|
|
6
|
+
describe("getImageTag", () => {
|
|
7
|
+
it("returns the tag for a known service", () => {
|
|
8
|
+
const tag = getImageTag("redis");
|
|
9
|
+
expect(tag).toBeDefined();
|
|
10
|
+
expect(typeof tag).toBe("string");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("returns undefined for an unknown service", () => {
|
|
14
|
+
expect(getImageTag("nonexistent-service-xyz")).toBeUndefined();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("getImageReference", () => {
|
|
19
|
+
it("returns image:tag for a known service", () => {
|
|
20
|
+
const ref = getImageReference("redis");
|
|
21
|
+
expect(ref).toBeDefined();
|
|
22
|
+
expect(ref).toContain(":");
|
|
23
|
+
expect(ref).toMatch(/^.+:.+$/);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("returns undefined for an unknown service", () => {
|
|
27
|
+
expect(getImageReference("nonexistent-service-xyz")).toBeUndefined();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("pinImageTags", () => {
|
|
32
|
+
it("pins image tags from the registry for all services", () => {
|
|
33
|
+
const resolved = resolve({
|
|
34
|
+
services: ["redis", "postgresql"],
|
|
35
|
+
skillPacks: [],
|
|
36
|
+
proxy: "none",
|
|
37
|
+
gpu: false,
|
|
38
|
+
platform: "linux/amd64",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const pinned = pinImageTags(resolved);
|
|
42
|
+
|
|
43
|
+
expect(pinned.services).toHaveLength(resolved.services.length);
|
|
44
|
+
|
|
45
|
+
for (const svc of pinned.services) {
|
|
46
|
+
expect(svc.definition.imageTag).toBeDefined();
|
|
47
|
+
expect(typeof svc.definition.imageTag).toBe("string");
|
|
48
|
+
expect(svc.definition.imageTag.length).toBeGreaterThan(0);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("does not mutate the original resolved output", () => {
|
|
53
|
+
const resolved = resolve({
|
|
54
|
+
services: ["redis"],
|
|
55
|
+
skillPacks: [],
|
|
56
|
+
proxy: "none",
|
|
57
|
+
gpu: false,
|
|
58
|
+
platform: "linux/amd64",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const originalTag = resolved.services[0]?.definition.imageTag;
|
|
62
|
+
pinImageTags(resolved);
|
|
63
|
+
|
|
64
|
+
expect(resolved.services[0]?.definition.imageTag).toBe(originalTag);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("preserves non-tag properties", () => {
|
|
68
|
+
const resolved = resolve({
|
|
69
|
+
services: ["redis"],
|
|
70
|
+
skillPacks: [],
|
|
71
|
+
proxy: "none",
|
|
72
|
+
gpu: false,
|
|
73
|
+
platform: "linux/amd64",
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const pinned = pinImageTags(resolved);
|
|
77
|
+
expect(pinned.services[0]?.definition.id).toBe("redis");
|
|
78
|
+
expect(pinned.services[0]?.definition.name).toBe("Redis");
|
|
79
|
+
expect(pinned.estimatedMemoryMB).toBe(resolved.estimatedMemoryMB);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe("checkCompatibility", () => {
|
|
84
|
+
it("warns when Redis and Valkey are both selected", () => {
|
|
85
|
+
const all = getAllServices();
|
|
86
|
+
const redis = all.find((s) => s.id === "redis");
|
|
87
|
+
const valkey = all.find((s) => s.id === "valkey");
|
|
88
|
+
|
|
89
|
+
if (redis && valkey) {
|
|
90
|
+
const warnings = checkCompatibility([redis, valkey]);
|
|
91
|
+
expect(warnings.some((w) => w.message.includes("Redis") && w.message.includes("Valkey"))).toBe(true);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("warns when Caddy and Traefik are both selected", () => {
|
|
96
|
+
const all = getAllServices();
|
|
97
|
+
const caddy = all.find((s) => s.id === "caddy");
|
|
98
|
+
const traefik = all.find((s) => s.id === "traefik");
|
|
99
|
+
|
|
100
|
+
if (caddy && traefik) {
|
|
101
|
+
const warnings = checkCompatibility([caddy, traefik]);
|
|
102
|
+
expect(warnings.some((w) => w.message.includes("Caddy") && w.message.includes("Traefik"))).toBe(true);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("warns about multiple vector databases", () => {
|
|
107
|
+
const all = getAllServices();
|
|
108
|
+
const qdrant = all.find((s) => s.id === "qdrant");
|
|
109
|
+
const chromadb = all.find((s) => s.id === "chromadb");
|
|
110
|
+
|
|
111
|
+
if (qdrant && chromadb) {
|
|
112
|
+
const warnings = checkCompatibility([qdrant, chromadb]);
|
|
113
|
+
expect(warnings.some((w) => w.message.includes("vector database"))).toBe(true);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("warns about GPU services", () => {
|
|
118
|
+
const all = getAllServices();
|
|
119
|
+
const gpuService = all.find((s) => s.gpuRequired);
|
|
120
|
+
|
|
121
|
+
if (gpuService) {
|
|
122
|
+
const warnings = checkCompatibility([gpuService]);
|
|
123
|
+
expect(warnings.some((w) => w.message.includes("GPU"))).toBe(true);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("returns no warnings for a single non-conflicting service", () => {
|
|
128
|
+
const redis = getServiceById("redis");
|
|
129
|
+
if (redis) {
|
|
130
|
+
const warnings = checkCompatibility([redis]);
|
|
131
|
+
expect(warnings.filter((w) => w.type === "compatibility" && !w.message.includes("GPU"))).toHaveLength(0);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
package/src/version-manager.ts
CHANGED
|
@@ -14,14 +14,21 @@ export function getImageReference(serviceId: string): string | undefined {
|
|
|
14
14
|
return `${svc.image}:${svc.imageTag}`;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
/** Pin all service image tags
|
|
17
|
+
/** Pin all service image tags to the registry-defined versions (returns a copy) */
|
|
18
18
|
export function pinImageTags(resolved: ResolverOutput): ResolverOutput {
|
|
19
19
|
return {
|
|
20
20
|
...resolved,
|
|
21
|
-
services: resolved.services.map((s) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
services: resolved.services.map((s) => {
|
|
22
|
+
const registryDef = getServiceById(s.definition.id);
|
|
23
|
+
const pinnedTag = registryDef?.imageTag ?? s.definition.imageTag;
|
|
24
|
+
return {
|
|
25
|
+
...s,
|
|
26
|
+
definition: {
|
|
27
|
+
...s.definition,
|
|
28
|
+
imageTag: pinnedTag,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}),
|
|
25
32
|
};
|
|
26
33
|
}
|
|
27
34
|
|