@better-openclaw/core 1.0.23 → 1.0.24

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 (254) hide show
  1. package/dist/bare-metal-partition.test.cjs +3 -4
  2. package/dist/bare-metal-partition.test.cjs.map +1 -1
  3. package/dist/bare-metal-partition.test.mjs +3 -4
  4. package/dist/bare-metal-partition.test.mjs.map +1 -1
  5. package/dist/composer.cjs +13 -1
  6. package/dist/composer.cjs.map +1 -1
  7. package/dist/composer.d.cts.map +1 -1
  8. package/dist/composer.d.mts.map +1 -1
  9. package/dist/composer.mjs +13 -1
  10. package/dist/composer.mjs.map +1 -1
  11. package/dist/composer.snapshot.test.cjs +1 -1
  12. package/dist/composer.snapshot.test.mjs +1 -1
  13. package/dist/composer.test.cjs +3 -2
  14. package/dist/composer.test.cjs.map +1 -1
  15. package/dist/composer.test.mjs +3 -2
  16. package/dist/composer.test.mjs.map +1 -1
  17. package/dist/deployers/strip-host-ports.test.cjs +1 -1
  18. package/dist/deployers/strip-host-ports.test.mjs +1 -1
  19. package/dist/generate.cjs +6 -2
  20. package/dist/generate.cjs.map +1 -1
  21. package/dist/generate.d.cts.map +1 -1
  22. package/dist/generate.d.mts.map +1 -1
  23. package/dist/generate.mjs +6 -2
  24. package/dist/generate.mjs.map +1 -1
  25. package/dist/generate.test.cjs +2 -2
  26. package/dist/generate.test.cjs.map +1 -1
  27. package/dist/generate.test.mjs +2 -2
  28. package/dist/generate.test.mjs.map +1 -1
  29. package/dist/generators/bare-metal-install.test.cjs +1 -1
  30. package/dist/generators/bare-metal-install.test.mjs +1 -1
  31. package/dist/generators/caddy.test.cjs +1 -1
  32. package/dist/generators/caddy.test.mjs +1 -1
  33. package/dist/generators/clone-repos.cjs +140 -0
  34. package/dist/generators/clone-repos.cjs.map +1 -0
  35. package/dist/generators/clone-repos.d.cts +11 -0
  36. package/dist/generators/clone-repos.d.cts.map +1 -0
  37. package/dist/generators/clone-repos.d.mts +11 -0
  38. package/dist/generators/clone-repos.d.mts.map +1 -0
  39. package/dist/generators/clone-repos.mjs +139 -0
  40. package/dist/generators/clone-repos.mjs.map +1 -0
  41. package/dist/generators/clone-repos.test.cjs +140 -0
  42. package/dist/generators/clone-repos.test.cjs.map +1 -0
  43. package/dist/generators/clone-repos.test.d.cts +1 -0
  44. package/dist/generators/clone-repos.test.d.mts +1 -0
  45. package/dist/generators/clone-repos.test.mjs +141 -0
  46. package/dist/generators/clone-repos.test.mjs.map +1 -0
  47. package/dist/generators/env.test.cjs +1 -1
  48. package/dist/generators/env.test.mjs +1 -1
  49. package/dist/generators/health-check.test.cjs +1 -1
  50. package/dist/generators/health-check.test.mjs +1 -1
  51. package/dist/generators/postgres-init.cjs +20 -0
  52. package/dist/generators/postgres-init.cjs.map +1 -1
  53. package/dist/generators/postgres-init.d.cts.map +1 -1
  54. package/dist/generators/postgres-init.d.mts.map +1 -1
  55. package/dist/generators/postgres-init.mjs +20 -0
  56. package/dist/generators/postgres-init.mjs.map +1 -1
  57. package/dist/generators/scripts.cjs +332 -3
  58. package/dist/generators/scripts.cjs.map +1 -1
  59. package/dist/generators/scripts.d.cts +3 -1
  60. package/dist/generators/scripts.d.cts.map +1 -1
  61. package/dist/generators/scripts.d.mts +3 -1
  62. package/dist/generators/scripts.d.mts.map +1 -1
  63. package/dist/generators/scripts.mjs +332 -3
  64. package/dist/generators/scripts.mjs.map +1 -1
  65. package/dist/generators/scripts.test.cjs +39 -5
  66. package/dist/generators/scripts.test.cjs.map +1 -1
  67. package/dist/generators/scripts.test.mjs +39 -5
  68. package/dist/generators/scripts.test.mjs.map +1 -1
  69. package/dist/generators/stack-manifest.cjs +1 -0
  70. package/dist/generators/stack-manifest.cjs.map +1 -1
  71. package/dist/generators/stack-manifest.d.cts +3 -2
  72. package/dist/generators/stack-manifest.d.cts.map +1 -1
  73. package/dist/generators/stack-manifest.d.mts +3 -2
  74. package/dist/generators/stack-manifest.d.mts.map +1 -1
  75. package/dist/generators/stack-manifest.mjs +1 -0
  76. package/dist/generators/stack-manifest.mjs.map +1 -1
  77. package/dist/generators/traefik.test.cjs +1 -1
  78. package/dist/generators/traefik.test.mjs +1 -1
  79. package/dist/index.cjs +8 -1
  80. package/dist/index.d.cts +5 -3
  81. package/dist/index.d.mts +5 -3
  82. package/dist/index.mjs +5 -3
  83. package/dist/migrations.test.cjs +1 -1
  84. package/dist/migrations.test.mjs +1 -1
  85. package/dist/presets/registry.cjs.map +1 -1
  86. package/dist/presets/registry.d.cts.map +1 -1
  87. package/dist/presets/registry.d.mts.map +1 -1
  88. package/dist/presets/registry.mjs.map +1 -1
  89. package/dist/presets/registry.test.cjs +1 -1
  90. package/dist/presets/registry.test.mjs +1 -1
  91. package/dist/resolver.cjs +8 -0
  92. package/dist/resolver.cjs.map +1 -1
  93. package/dist/resolver.mjs +9 -1
  94. package/dist/resolver.mjs.map +1 -1
  95. package/dist/resolver.test.cjs +47 -12
  96. package/dist/resolver.test.cjs.map +1 -1
  97. package/dist/resolver.test.mjs +47 -12
  98. package/dist/resolver.test.mjs.map +1 -1
  99. package/dist/{schema-B4c64P8N.d.cts → schema-eX44HhRp.d.mts} +62 -8
  100. package/dist/schema-eX44HhRp.d.mts.map +1 -0
  101. package/dist/{schema-CXNhYci1.d.mts → schema-tn5RK8CM.d.cts} +62 -8
  102. package/dist/schema-tn5RK8CM.d.cts.map +1 -0
  103. package/dist/schema.cjs +22 -4
  104. package/dist/schema.cjs.map +1 -1
  105. package/dist/schema.d.cts +2 -2
  106. package/dist/schema.d.mts +2 -2
  107. package/dist/schema.mjs +21 -5
  108. package/dist/schema.mjs.map +1 -1
  109. package/dist/schema.test.cjs +1 -1
  110. package/dist/schema.test.mjs +1 -1
  111. package/dist/services/definitions/apptension-saas.cjs +87 -0
  112. package/dist/services/definitions/apptension-saas.cjs.map +1 -0
  113. package/dist/services/definitions/apptension-saas.d.cts +7 -0
  114. package/dist/services/definitions/apptension-saas.d.cts.map +1 -0
  115. package/dist/services/definitions/apptension-saas.d.mts +7 -0
  116. package/dist/services/definitions/apptension-saas.d.mts.map +1 -0
  117. package/dist/services/definitions/apptension-saas.mjs +86 -0
  118. package/dist/services/definitions/apptension-saas.mjs.map +1 -0
  119. package/dist/services/definitions/boxyhq-saas.cjs +88 -0
  120. package/dist/services/definitions/boxyhq-saas.cjs.map +1 -0
  121. package/dist/services/definitions/boxyhq-saas.d.cts +7 -0
  122. package/dist/services/definitions/boxyhq-saas.d.cts.map +1 -0
  123. package/dist/services/definitions/boxyhq-saas.d.mts +7 -0
  124. package/dist/services/definitions/boxyhq-saas.d.mts.map +1 -0
  125. package/dist/services/definitions/boxyhq-saas.mjs +87 -0
  126. package/dist/services/definitions/boxyhq-saas.mjs.map +1 -0
  127. package/dist/services/definitions/cmsaas-starter.cjs +86 -0
  128. package/dist/services/definitions/cmsaas-starter.cjs.map +1 -0
  129. package/dist/services/definitions/cmsaas-starter.d.cts +7 -0
  130. package/dist/services/definitions/cmsaas-starter.d.cts.map +1 -0
  131. package/dist/services/definitions/cmsaas-starter.d.mts +7 -0
  132. package/dist/services/definitions/cmsaas-starter.d.mts.map +1 -0
  133. package/dist/services/definitions/cmsaas-starter.mjs +85 -0
  134. package/dist/services/definitions/cmsaas-starter.mjs.map +1 -0
  135. package/dist/services/definitions/index.cjs +51 -36
  136. package/dist/services/definitions/index.cjs.map +1 -1
  137. package/dist/services/definitions/index.d.cts +30 -25
  138. package/dist/services/definitions/index.d.cts.map +1 -1
  139. package/dist/services/definitions/index.d.mts +30 -25
  140. package/dist/services/definitions/index.d.mts.map +1 -1
  141. package/dist/services/definitions/index.mjs +47 -37
  142. package/dist/services/definitions/index.mjs.map +1 -1
  143. package/dist/services/definitions/ixartz-saas.cjs +88 -0
  144. package/dist/services/definitions/ixartz-saas.cjs.map +1 -0
  145. package/dist/services/definitions/ixartz-saas.d.cts +7 -0
  146. package/dist/services/definitions/ixartz-saas.d.cts.map +1 -0
  147. package/dist/services/definitions/ixartz-saas.d.mts +7 -0
  148. package/dist/services/definitions/ixartz-saas.d.mts.map +1 -0
  149. package/dist/services/definitions/ixartz-saas.mjs +87 -0
  150. package/dist/services/definitions/ixartz-saas.mjs.map +1 -0
  151. package/dist/services/definitions/mission-control.cjs +16 -2
  152. package/dist/services/definitions/mission-control.cjs.map +1 -1
  153. package/dist/services/definitions/mission-control.mjs +16 -2
  154. package/dist/services/definitions/mission-control.mjs.map +1 -1
  155. package/dist/services/definitions/open-saas.cjs +81 -0
  156. package/dist/services/definitions/open-saas.cjs.map +1 -0
  157. package/dist/services/definitions/open-saas.d.cts +7 -0
  158. package/dist/services/definitions/open-saas.d.cts.map +1 -0
  159. package/dist/services/definitions/open-saas.d.mts +7 -0
  160. package/dist/services/definitions/open-saas.d.mts.map +1 -0
  161. package/dist/services/definitions/open-saas.mjs +80 -0
  162. package/dist/services/definitions/open-saas.mjs.map +1 -0
  163. package/dist/services/registry.cjs +3 -0
  164. package/dist/services/registry.cjs.map +1 -1
  165. package/dist/services/registry.d.cts.map +1 -1
  166. package/dist/services/registry.d.mts.map +1 -1
  167. package/dist/services/registry.mjs +3 -0
  168. package/dist/services/registry.mjs.map +1 -1
  169. package/dist/services/registry.test.cjs +8 -1
  170. package/dist/services/registry.test.cjs.map +1 -1
  171. package/dist/services/registry.test.mjs +8 -1
  172. package/dist/services/registry.test.mjs.map +1 -1
  173. package/dist/{skill-manifest-BVUXU0__.mjs → skill-manifest-6XhrhWsG.mjs} +49 -1
  174. package/dist/{skill-manifest--IgY9REK.cjs.map → skill-manifest-6XhrhWsG.mjs.map} +1 -1
  175. package/dist/{skill-manifest--IgY9REK.cjs → skill-manifest-B8znSsym.cjs} +49 -1
  176. package/dist/{skill-manifest-BVUXU0__.mjs.map → skill-manifest-B8znSsym.cjs.map} +1 -1
  177. package/dist/skills/registry.cjs +3 -3
  178. package/dist/skills/registry.cjs.map +1 -1
  179. package/dist/skills/registry.mjs +3 -3
  180. package/dist/skills/registry.mjs.map +1 -1
  181. package/dist/skills/skill-manifest.cjs +1 -1
  182. package/dist/skills/skill-manifest.mjs +1 -1
  183. package/dist/track-analytics.cjs +50 -0
  184. package/dist/track-analytics.cjs.map +1 -0
  185. package/dist/track-analytics.d.cts +34 -0
  186. package/dist/track-analytics.d.cts.map +1 -0
  187. package/dist/track-analytics.d.mts +34 -0
  188. package/dist/track-analytics.d.mts.map +1 -0
  189. package/dist/track-analytics.mjs +48 -0
  190. package/dist/track-analytics.mjs.map +1 -0
  191. package/dist/track-analytics.test.cjs +91 -0
  192. package/dist/track-analytics.test.cjs.map +1 -0
  193. package/dist/track-analytics.test.d.cts +1 -0
  194. package/dist/track-analytics.test.d.mts +1 -0
  195. package/dist/track-analytics.test.mjs +92 -0
  196. package/dist/track-analytics.test.mjs.map +1 -0
  197. package/dist/types.cjs +7 -0
  198. package/dist/types.cjs.map +1 -1
  199. package/dist/types.d.cts +4 -2
  200. package/dist/types.d.cts.map +1 -1
  201. package/dist/types.d.mts +4 -2
  202. package/dist/types.d.mts.map +1 -1
  203. package/dist/types.mjs +7 -0
  204. package/dist/types.mjs.map +1 -1
  205. package/dist/validator.test.cjs +1 -1
  206. package/dist/validator.test.mjs +1 -1
  207. package/dist/version-manager.cjs +1 -1
  208. package/dist/version-manager.cjs.map +1 -1
  209. package/dist/version-manager.mjs +1 -1
  210. package/dist/version-manager.mjs.map +1 -1
  211. package/dist/version-manager.test.cjs +7 -5
  212. package/dist/version-manager.test.cjs.map +1 -1
  213. package/dist/version-manager.test.mjs +7 -5
  214. package/dist/version-manager.test.mjs.map +1 -1
  215. package/dist/{vi.2VT5v0um-DvC3SVNc.mjs → vi.2VT5v0um-C_jmO7m2.mjs} +5 -5
  216. package/dist/{vi.2VT5v0um-DvC3SVNc.mjs.map → vi.2VT5v0um-C_jmO7m2.mjs.map} +1 -1
  217. package/dist/{vi.2VT5v0um-CRqXre87.cjs → vi.2VT5v0um-iVBt6Fyq.cjs} +5 -5
  218. package/dist/{vi.2VT5v0um-CRqXre87.cjs.map → vi.2VT5v0um-iVBt6Fyq.cjs.map} +1 -1
  219. package/package.json +1 -1
  220. package/src/__snapshots__/composer.snapshot.test.ts.snap +155 -0
  221. package/src/bare-metal-partition.test.ts +4 -3
  222. package/src/composer.test.ts +4 -2
  223. package/src/composer.ts +20 -1
  224. package/src/generate.test.ts +2 -1
  225. package/src/generate.ts +10 -1
  226. package/src/generators/clone-repos.test.ts +154 -0
  227. package/src/generators/clone-repos.ts +159 -0
  228. package/src/generators/postgres-init.ts +17 -0
  229. package/src/generators/scripts.test.ts +52 -4
  230. package/src/generators/scripts.ts +351 -3
  231. package/src/generators/stack-manifest.ts +4 -2
  232. package/src/index.ts +8 -0
  233. package/src/presets/registry.ts +241 -329
  234. package/src/resolver.test.ts +53 -15
  235. package/src/resolver.ts +13 -1
  236. package/src/schema.ts +33 -4
  237. package/src/services/definitions/apptension-saas.ts +84 -0
  238. package/src/services/definitions/boxyhq-saas.ts +84 -0
  239. package/src/services/definitions/cmsaas-starter.ts +84 -0
  240. package/src/services/definitions/index.ts +90 -70
  241. package/src/services/definitions/ixartz-saas.ts +84 -0
  242. package/src/services/definitions/mission-control.ts +19 -2
  243. package/src/services/definitions/open-saas.ts +79 -0
  244. package/src/services/registry.test.ts +8 -0
  245. package/src/services/registry.ts +7 -0
  246. package/src/skills/manifest.json +64 -0
  247. package/src/skills/registry.ts +3 -3
  248. package/src/track-analytics.test.ts +82 -0
  249. package/src/track-analytics.ts +76 -0
  250. package/src/types.ts +11 -0
  251. package/src/version-manager.test.ts +10 -5
  252. package/src/version-manager.ts +1 -1
  253. package/dist/schema-B4c64P8N.d.cts.map +0 -1
  254. package/dist/schema-CXNhYci1.d.mts.map +0 -1
@@ -5,7 +5,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
5
5
  *
6
6
  * Returns a map of file paths (relative to project root) to file contents.
7
7
  */
8
- function generateScripts() {
8
+ function generateScripts(options) {
9
+ const hasGit = options?.hasGitServices ?? false;
9
10
  const files = {};
10
11
  files["scripts/start.sh"] = `#!/usr/bin/env bash
11
12
  set -euo pipefail
@@ -135,6 +136,14 @@ if [ "$EMPTY_SECRETS" -gt 0 ]; then
135
136
  echo ""
136
137
  fi
137
138
 
139
+ # ── Clone git-based repositories (if any) ────────────────────────────────────
140
+
141
+ if [ -f "$SCRIPT_DIR/clone-repos.sh" ]; then
142
+ info "Cloning/updating SaaS boilerplate repositories..."
143
+ bash "$SCRIPT_DIR/clone-repos.sh"
144
+ ok "Repositories ready."
145
+ fi
146
+
138
147
  # ── Pull and start ───────────────────────────────────────────────────────────
139
148
 
140
149
  echo ""
@@ -143,7 +152,7 @@ docker compose pull --quiet 2>/dev/null || docker compose pull
143
152
 
144
153
  echo ""
145
154
  info "Starting services..."
146
- docker compose up -d --remove-orphans
155
+ docker compose up -d --remove-orphans${hasGit ? " --build" : ""}
147
156
 
148
157
  # ── Health-check loop ────────────────────────────────────────────────────────
149
158
 
@@ -236,13 +245,19 @@ cd "$PROJECT_DIR"
236
245
  echo "🐾 OpenClaw — Updating services..."
237
246
  echo ""
238
247
 
248
+ # Update git-based repositories (if any)
249
+ if [ -f "$SCRIPT_DIR/clone-repos.sh" ]; then
250
+ echo "📂 Updating SaaS boilerplate repositories..."
251
+ bash "$SCRIPT_DIR/clone-repos.sh"
252
+ fi
253
+
239
254
  # Pull latest images
240
255
  echo "📦 Pulling latest images..."
241
256
  docker compose pull
242
257
 
243
258
  echo ""
244
259
  echo "🔄 Restarting services with new images..."
245
- docker compose up -d --remove-orphans
260
+ docker compose up -d --remove-orphans${hasGit ? " --build" : ""}
246
261
 
247
262
  echo ""
248
263
  echo "⏳ Waiting for services to stabilize..."
@@ -343,6 +358,320 @@ echo "── Network ───────────────────
343
358
  echo ""
344
359
 
345
360
  docker network ls --filter "name=openclaw" --format "table {{.Name}}\\t{{.Driver}}\\t{{.Scope}}" 2>/dev/null || true
361
+ `;
362
+ files["scripts/start.ps1"] = `#Requires -Version 5.1
363
+ <#
364
+ .SYNOPSIS
365
+ OpenClaw Start Script — validates prerequisites, auto-generates secrets,
366
+ creates required directories, and starts all services via Docker Compose.
367
+ #>
368
+
369
+ $ErrorActionPreference = 'Stop'
370
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
371
+ $ProjectDir = Split-Path -Parent $ScriptDir
372
+ Set-Location $ProjectDir
373
+
374
+ function Info { param($Msg) Write-Host " i $Msg" -ForegroundColor Cyan }
375
+ function Ok { param($Msg) Write-Host " + $Msg" -ForegroundColor Green }
376
+ function Warn { param($Msg) Write-Host " ! $Msg" -ForegroundColor Yellow }
377
+ function Err { param($Msg) Write-Host " x $Msg" -ForegroundColor Red }
378
+
379
+ Write-Host ""
380
+ Write-Host "OpenClaw - Starting services..." -ForegroundColor White
381
+ Write-Host ""
382
+
383
+ # ── Prerequisite checks ─────────────────────────────────────────────────
384
+ if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
385
+ Err "Docker is not installed. Please install Docker Desktop."
386
+ Write-Host " https://docs.docker.com/desktop/install/windows-install/"
387
+ exit 1
388
+ }
389
+
390
+ $composeCheck = docker compose version 2>&1
391
+ if ($LASTEXITCODE -ne 0) {
392
+ Err "Docker Compose (v2) is not available."
393
+ Write-Host " https://docs.docker.com/compose/install/"
394
+ exit 1
395
+ }
396
+
397
+ $dockerInfo = docker info 2>&1
398
+ if ($LASTEXITCODE -ne 0) {
399
+ Err "Docker daemon is not running. Please start Docker Desktop."
400
+ exit 1
401
+ }
402
+
403
+ # ── Source .env if it exists ─────────────────────────────────────────────
404
+ if (Test-Path ".env") {
405
+ Info "Loading existing .env file..."
406
+ Get-Content ".env" | ForEach-Object {
407
+ if ($_ -match '^([^#=]+)=(.*)$') {
408
+ [Environment]::SetEnvironmentVariable($Matches[1].Trim(), $Matches[2].Trim(), 'Process')
409
+ }
410
+ }
411
+ } else {
412
+ Warn ".env file not found - will create one from .env.example if available."
413
+ if (Test-Path ".env.example") {
414
+ Copy-Item ".env.example" ".env"
415
+ Info "Created .env from .env.example"
416
+ Get-Content ".env" | ForEach-Object {
417
+ if ($_ -match '^([^#=]+)=(.*)$') {
418
+ [Environment]::SetEnvironmentVariable($Matches[1].Trim(), $Matches[2].Trim(), 'Process')
419
+ }
420
+ }
421
+ }
422
+ }
423
+
424
+ # ── Auto-generate OPENCLAW_GATEWAY_TOKEN if missing ──────────────────────
425
+ if (-not $env:OPENCLAW_GATEWAY_TOKEN) {
426
+ Info "Generating OPENCLAW_GATEWAY_TOKEN..."
427
+ $bytes = New-Object byte[] 32
428
+ [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
429
+ $env:OPENCLAW_GATEWAY_TOKEN = ($bytes | ForEach-Object { $_.ToString("x2") }) -join ''
430
+
431
+ if (Test-Path ".env") {
432
+ $envContent = Get-Content ".env" -Raw
433
+ if ($envContent -match '(?m)^OPENCLAW_GATEWAY_TOKEN=') {
434
+ $envContent = $envContent -replace '(?m)^OPENCLAW_GATEWAY_TOKEN=.*', "OPENCLAW_GATEWAY_TOKEN=$($env:OPENCLAW_GATEWAY_TOKEN)"
435
+ Set-Content ".env" $envContent -NoNewline
436
+ } else {
437
+ Add-Content ".env" "OPENCLAW_GATEWAY_TOKEN=$($env:OPENCLAW_GATEWAY_TOKEN)"
438
+ }
439
+ }
440
+ Ok "Gateway token generated and saved."
441
+ }
442
+
443
+ # ── Apply defaults ───────────────────────────────────────────────────────
444
+ if (-not $env:OPENCLAW_VERSION) { $env:OPENCLAW_VERSION = "latest" }
445
+ if (-not $env:OPENCLAW_GATEWAY_PORT) { $env:OPENCLAW_GATEWAY_PORT = "18789" }
446
+ if (-not $env:OPENCLAW_BRIDGE_PORT) { $env:OPENCLAW_BRIDGE_PORT = "18790" }
447
+ if (-not $env:OPENCLAW_GATEWAY_BIND) { $env:OPENCLAW_GATEWAY_BIND = "lan" }
448
+ if (-not $env:OPENCLAW_CONFIG_DIR) { $env:OPENCLAW_CONFIG_DIR = "./openclaw/config" }
449
+ if (-not $env:OPENCLAW_WORKSPACE_DIR) { $env:OPENCLAW_WORKSPACE_DIR = "./openclaw/workspace" }
450
+
451
+ # ── Create required host directories ────────────────────────────────────
452
+ Info "Ensuring host directories exist..."
453
+ New-Item -ItemType Directory -Force -Path $env:OPENCLAW_CONFIG_DIR | Out-Null
454
+ New-Item -ItemType Directory -Force -Path $env:OPENCLAW_WORKSPACE_DIR | Out-Null
455
+ Ok "Directories ready: $($env:OPENCLAW_CONFIG_DIR), $($env:OPENCLAW_WORKSPACE_DIR)"
456
+
457
+ # ── Clone git-based repositories (if any) ─────────────────────────────
458
+ $cloneScript = Join-Path $ScriptDir "clone-repos.ps1"
459
+ if (Test-Path $cloneScript) {
460
+ Info "Cloning/updating SaaS boilerplate repositories..."
461
+ & $cloneScript
462
+ Ok "Repositories ready."
463
+ }
464
+
465
+ # ── Pull and start ───────────────────────────────────────────────────────
466
+ Write-Host ""
467
+ Info "Pulling latest images..."
468
+ docker compose pull 2>$null
469
+ if ($LASTEXITCODE -ne 0) { docker compose pull }
470
+
471
+ Write-Host ""
472
+ Info "Starting services..."
473
+ docker compose up -d --remove-orphans${hasGit ? " --build" : ""}
474
+
475
+ # ── Health-check loop ────────────────────────────────────────────────────
476
+ Write-Host ""
477
+ Info "Waiting for services to become healthy..."
478
+ Start-Sleep -Seconds 5
479
+
480
+ $retries = 0
481
+ $maxRetries = 30
482
+ while ($retries -lt $maxRetries) {
483
+ $psOutput = docker compose ps --format json 2>$null
484
+ $unhealthy = ($psOutput | Select-String -Pattern '"unhealthy"' -SimpleMatch).Count
485
+ $starting = ($psOutput | Select-String -Pattern '"starting"' -SimpleMatch).Count
486
+ if ($unhealthy -eq 0 -and $starting -eq 0) { break }
487
+ $retries++
488
+ Start-Sleep -Seconds 2
489
+ }
490
+
491
+ Write-Host ""
492
+ docker compose ps
493
+ Write-Host ""
494
+
495
+ if ($retries -ge $maxRetries) {
496
+ Warn "Some services may still be starting. Check: docker compose ps"
497
+ } else {
498
+ Ok "All services are running!"
499
+ }
500
+
501
+ # ── Print service URLs & token ───────────────────────────────────────────
502
+ $gatewayHost = if ($env:OPENCLAW_GATEWAY_BIND -eq "lan") { "0.0.0.0" } else { "localhost" }
503
+
504
+ Write-Host ""
505
+ Write-Host "==============================================================================="
506
+ Write-Host " OpenClaw is ready!"
507
+ Write-Host "==============================================================================="
508
+ Write-Host ""
509
+ Write-Host " Gateway URL: http://\${gatewayHost}:$($env:OPENCLAW_GATEWAY_PORT)"
510
+ Write-Host " Bridge (WebSocket): ws://\${gatewayHost}:$($env:OPENCLAW_BRIDGE_PORT)"
511
+ Write-Host " Config directory: $($env:OPENCLAW_CONFIG_DIR)"
512
+ Write-Host " Workspace directory: $($env:OPENCLAW_WORKSPACE_DIR)"
513
+ Write-Host ""
514
+ Write-Host " Gateway Token: $($env:OPENCLAW_GATEWAY_TOKEN)"
515
+ Write-Host ""
516
+ Write-Host " Manage:"
517
+ Write-Host " Stop: .\\scripts\\stop.ps1"
518
+ Write-Host " Status: .\\scripts\\status.ps1"
519
+ Write-Host " Update: .\\scripts\\update.ps1"
520
+ Write-Host " Logs: docker compose logs -f"
521
+ Write-Host ""
522
+ Write-Host "==============================================================================="
523
+ `;
524
+ files["scripts/stop.ps1"] = `#Requires -Version 5.1
525
+ <#
526
+ .SYNOPSIS
527
+ OpenClaw Stop Script — gracefully stops all services.
528
+ #>
529
+
530
+ $ErrorActionPreference = 'Stop'
531
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
532
+ $ProjectDir = Split-Path -Parent $ScriptDir
533
+ Set-Location $ProjectDir
534
+
535
+ Write-Host ""
536
+ Write-Host "OpenClaw - Stopping services..." -ForegroundColor White
537
+ Write-Host ""
538
+
539
+ docker compose down --timeout 30
540
+
541
+ Write-Host ""
542
+ Write-Host " + All services stopped." -ForegroundColor Green
543
+ `;
544
+ files["scripts/update.ps1"] = `#Requires -Version 5.1
545
+ <#
546
+ .SYNOPSIS
547
+ OpenClaw Update Script — pulls latest images and restarts services.
548
+ #>
549
+
550
+ $ErrorActionPreference = 'Stop'
551
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
552
+ $ProjectDir = Split-Path -Parent $ScriptDir
553
+ Set-Location $ProjectDir
554
+
555
+ Write-Host ""
556
+ Write-Host "OpenClaw - Updating services..." -ForegroundColor White
557
+ Write-Host ""
558
+
559
+ # Update git-based repositories (if any)
560
+ $cloneScript = Join-Path $ScriptDir "clone-repos.ps1"
561
+ if (Test-Path $cloneScript) {
562
+ Write-Host " Updating SaaS boilerplate repositories..." -ForegroundColor Cyan
563
+ & $cloneScript
564
+ }
565
+
566
+ Write-Host " Pulling latest images..." -ForegroundColor Cyan
567
+ docker compose pull
568
+
569
+ Write-Host ""
570
+ Write-Host " Restarting services with new images..." -ForegroundColor Cyan
571
+ docker compose up -d --remove-orphans${hasGit ? " --build" : ""}
572
+
573
+ Write-Host ""
574
+ Write-Host " Waiting for services to stabilize..." -ForegroundColor Cyan
575
+ Start-Sleep -Seconds 10
576
+
577
+ docker compose ps
578
+
579
+ Write-Host ""
580
+ Write-Host " + Update complete!" -ForegroundColor Green
581
+ `;
582
+ files["scripts/backup.ps1"] = `#Requires -Version 5.1
583
+ <#
584
+ .SYNOPSIS
585
+ OpenClaw Backup Script — backs up all named Docker volumes to a timestamped directory.
586
+ #>
587
+
588
+ $ErrorActionPreference = 'Stop'
589
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
590
+ $ProjectDir = Split-Path -Parent $ScriptDir
591
+ Set-Location $ProjectDir
592
+
593
+ $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
594
+ $backupDir = Join-Path $ProjectDir "backups\\$timestamp"
595
+ New-Item -ItemType Directory -Force -Path $backupDir | Out-Null
596
+
597
+ Write-Host ""
598
+ Write-Host "OpenClaw - Backing up volumes..." -ForegroundColor White
599
+ Write-Host " Backup directory: $backupDir"
600
+ Write-Host ""
601
+
602
+ # Get project name from docker compose
603
+ $projectName = "openclaw"
604
+ try {
605
+ $configJson = docker compose config --format json 2>$null | ConvertFrom-Json
606
+ if ($configJson.name) { $projectName = $configJson.name }
607
+ } catch {}
608
+
609
+ # List all volumes for this project
610
+ $volumes = docker volume ls --filter "name=$projectName" --format "{{.Name}}" 2>$null
611
+ if (-not $volumes) {
612
+ Write-Host " ! No volumes found for project: $projectName" -ForegroundColor Yellow
613
+ Write-Host " Trying to list all openclaw volumes..."
614
+ $volumes = docker volume ls --filter "name=openclaw" --format "{{.Name}}" 2>$null
615
+ }
616
+
617
+ if (-not $volumes) {
618
+ Write-Host " x No volumes found to back up." -ForegroundColor Red
619
+ exit 1
620
+ }
621
+
622
+ $backedUp = 0
623
+ foreach ($volume in $volumes) {
624
+ $vol = $volume.Trim()
625
+ if (-not $vol) { continue }
626
+ Write-Host " Backing up: $vol" -ForegroundColor Cyan
627
+ docker run --rm -v "\${vol}:/source:ro" -v "\${backupDir}:/backup" alpine tar czf "/backup/$vol.tar.gz" -C /source .
628
+ $size = (Get-Item (Join-Path $backupDir "$vol.tar.gz")).Length / 1MB
629
+ Write-Host " + $vol ($([math]::Round($size, 1))MB)" -ForegroundColor Green
630
+ $backedUp++
631
+ }
632
+
633
+ $totalSize = ((Get-ChildItem $backupDir -Recurse | Measure-Object -Property Length -Sum).Sum) / 1MB
634
+ Write-Host ""
635
+ Write-Host " + Backed up $backedUp volume(s) ($([math]::Round($totalSize, 1))MB total)" -ForegroundColor Green
636
+ Write-Host " Location: $backupDir"
637
+ `;
638
+ files["scripts/status.ps1"] = `#Requires -Version 5.1
639
+ <#
640
+ .SYNOPSIS
641
+ OpenClaw Status Script — shows the current status of all services.
642
+ #>
643
+
644
+ $ErrorActionPreference = 'Stop'
645
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
646
+ $ProjectDir = Split-Path -Parent $ScriptDir
647
+ Set-Location $ProjectDir
648
+
649
+ Write-Host ""
650
+ Write-Host "OpenClaw - Service Status" -ForegroundColor White
651
+ Write-Host ""
652
+
653
+ # Show compose status
654
+ docker compose ps
655
+
656
+ Write-Host ""
657
+ Write-Host "-- Resource Usage ----------------------------------------------------------"
658
+ Write-Host ""
659
+
660
+ try { docker compose top 2>$null } catch {}
661
+
662
+ Write-Host ""
663
+ Write-Host "-- Disk Usage --------------------------------------------------------------"
664
+ Write-Host ""
665
+
666
+ try { docker system df 2>$null } catch {}
667
+
668
+ Write-Host ""
669
+ Write-Host "-- Network -----------------------------------------------------------------"
670
+ Write-Host ""
671
+
672
+ try {
673
+ docker network ls --filter "name=openclaw" --format "table {{.Name}}\\t{{.Driver}}\\t{{.Scope}}" 2>$null
674
+ } catch {}
346
675
  `;
347
676
  return files;
348
677
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scripts.cjs","names":[],"sources":["../../src/generators/scripts.ts"],"sourcesContent":["/**\n * Generates helper shell scripts for managing the OpenClaw Docker Compose stack.\n *\n * Returns a map of file paths (relative to project root) to file contents.\n */\nexport function generateScripts(): Record<string, string> {\n\tconst files: Record<string, string> = {};\n\n\t// ── scripts/start.sh ────────────────────────────────────────────────────\n\n\tfiles[\"scripts/start.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Start Script ──────────────────────────────────────────────────\n# Production-quality bootstrap: validates prerequisites, auto-generates secrets,\n# creates required directories, and starts all services via Docker Compose.\n# Modelled after the official docker-setup.sh patterns.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Starting services...\"\necho \"\"\n\n# ── Colour helpers (no-op when not a TTY) ────────────────────────────────────\nif [ -t 1 ]; then\n RED='\\\\033[0;31m'; GREEN='\\\\033[0;32m'; YELLOW='\\\\033[1;33m'; CYAN='\\\\033[0;36m'; NC='\\\\033[0m'\nelse\n RED=''; GREEN=''; YELLOW=''; CYAN=''; NC=''\nfi\n\ninfo() { echo -e \"\\${CYAN}ℹ $*\\${NC}\"; }\nok() { echo -e \"\\${GREEN}✅ $*\\${NC}\"; }\nwarn() { echo -e \"\\${YELLOW}⚠️ $*\\${NC}\"; }\nerr() { echo -e \"\\${RED}❌ $*\\${NC}\" >&2; }\n\n# ── Prerequisite checks ─────────────────────────────────────────────────────\n\nif ! command -v docker &> /dev/null; then\n err \"Docker is not installed. Please install Docker first.\"\n echo \" https://docs.docker.com/get-docker/\"\n exit 1\nfi\n\nif ! docker compose version &> /dev/null; then\n err \"Docker Compose (v2) is not available.\"\n echo \" https://docs.docker.com/compose/install/\"\n exit 1\nfi\n\nif ! docker info &> /dev/null 2>&1; then\n err \"Docker daemon is not running. Please start Docker.\"\n exit 1\nfi\n\n# ── Source .env if it exists ─────────────────────────────────────────────────\n\nif [ -f \".env\" ]; then\n info \"Loading existing .env file...\"\n set -a\n # shellcheck disable=SC1091\n source .env\n set +a\nelse\n warn \".env file not found — will create one from .env.example if available.\"\n if [ -f \".env.example\" ]; then\n cp .env.example .env\n info \"Created .env from .env.example\"\n set -a\n # shellcheck disable=SC1091\n source .env\n set +a\n fi\nfi\n\n# ── Auto-generate OPENCLAW_GATEWAY_TOKEN if missing ──────────────────────────\n\nif [ -z \"\\${OPENCLAW_GATEWAY_TOKEN:-}\" ]; then\n info \"Generating OPENCLAW_GATEWAY_TOKEN...\"\n if command -v openssl &> /dev/null; then\n OPENCLAW_GATEWAY_TOKEN=\"$(openssl rand -hex 32)\"\n elif command -v python3 &> /dev/null; then\n OPENCLAW_GATEWAY_TOKEN=\"$(python3 -c 'import secrets; print(secrets.token_hex(32))')\"\n elif command -v python &> /dev/null; then\n OPENCLAW_GATEWAY_TOKEN=\"$(python -c 'import secrets; print(secrets.token_hex(32))')\"\n else\n err \"Cannot generate token: neither openssl nor python3 found.\"\n exit 1\n fi\n export OPENCLAW_GATEWAY_TOKEN\n\n # Persist into .env\n if [ -f \".env\" ]; then\n if grep -q \"^OPENCLAW_GATEWAY_TOKEN=\" .env 2>/dev/null; then\n sed -i.bak \"s|^OPENCLAW_GATEWAY_TOKEN=.*|OPENCLAW_GATEWAY_TOKEN=\\${OPENCLAW_GATEWAY_TOKEN}|\" .env && rm -f .env.bak\n else\n echo \"OPENCLAW_GATEWAY_TOKEN=\\${OPENCLAW_GATEWAY_TOKEN}\" >> .env\n fi\n fi\n ok \"Gateway token generated and saved.\"\nfi\n\n# ── Apply defaults for optional variables ────────────────────────────────────\n\nexport OPENCLAW_VERSION=\"\\${OPENCLAW_VERSION:-latest}\"\nexport OPENCLAW_GATEWAY_PORT=\"\\${OPENCLAW_GATEWAY_PORT:-18789}\"\nexport OPENCLAW_BRIDGE_PORT=\"\\${OPENCLAW_BRIDGE_PORT:-18790}\"\nexport OPENCLAW_GATEWAY_BIND=\"\\${OPENCLAW_GATEWAY_BIND:-lan}\"\nexport OPENCLAW_CONFIG_DIR=\"\\${OPENCLAW_CONFIG_DIR:-./openclaw/config}\"\nexport OPENCLAW_WORKSPACE_DIR=\"\\${OPENCLAW_WORKSPACE_DIR:-./openclaw/workspace}\"\n\n# ── Create required host directories ────────────────────────────────────────\n\ninfo \"Ensuring host directories exist...\"\nmkdir -p \"\\${OPENCLAW_CONFIG_DIR}\"\nmkdir -p \"\\${OPENCLAW_WORKSPACE_DIR}\"\nok \"Directories ready: \\${OPENCLAW_CONFIG_DIR}, \\${OPENCLAW_WORKSPACE_DIR}\"\n\n# ── Check for empty secret values ────────────────────────────────────────────\n\nEMPTY_SECRETS=0\nwhile IFS='=' read -r key value; do\n [[ \"$key\" =~ ^#.*$ ]] && continue\n [[ -z \"$key\" ]] && continue\n if [[ \"$key\" =~ (PASSWORD|TOKEN|SECRET|SESSION_KEY|COOKIE) ]] && [[ -z \"\\${value:-}\" ]]; then\n warn \"Warning: $key is empty in .env\"\n EMPTY_SECRETS=$((EMPTY_SECRETS + 1))\n fi\ndone < .env 2>/dev/null || true\n\nif [ \"$EMPTY_SECRETS\" -gt 0 ]; then\n echo \"\"\n warn \"$EMPTY_SECRETS secret(s) are empty. Some services may not function until they are set.\"\n echo \"\"\nfi\n\n# ── Pull and start ───────────────────────────────────────────────────────────\n\necho \"\"\ninfo \"Pulling latest images...\"\ndocker compose pull --quiet 2>/dev/null || docker compose pull\n\necho \"\"\ninfo \"Starting services...\"\ndocker compose up -d --remove-orphans\n\n# ── Health-check loop ────────────────────────────────────────────────────────\n\necho \"\"\ninfo \"Waiting for services to become healthy...\"\nsleep 5\n\nRETRIES=0\nMAX_RETRIES=30\nwhile [ $RETRIES -lt $MAX_RETRIES ]; do\n UNHEALTHY=$(docker compose ps --format json 2>/dev/null | grep -c '\"unhealthy\"' || true)\n STARTING=$(docker compose ps --format json 2>/dev/null | grep -c '\"starting\"' || true)\n\n if [ \"$UNHEALTHY\" -eq 0 ] && [ \"$STARTING\" -eq 0 ]; then\n break\n fi\n\n RETRIES=$((RETRIES + 1))\n sleep 2\ndone\n\necho \"\"\ndocker compose ps\necho \"\"\n\nif [ $RETRIES -ge $MAX_RETRIES ]; then\n warn \"Some services may still be starting. Check: docker compose ps\"\nelse\n ok \"All services are running!\"\nfi\n\n# ── Print service URLs & token ───────────────────────────────────────────────\n\nGATEWAY_HOST=\"localhost\"\nif [ \"\\${OPENCLAW_GATEWAY_BIND}\" = \"lan\" ]; then\n GATEWAY_HOST=\"0.0.0.0\"\nfi\n\necho \"\"\necho \"═══════════════════════════════════════════════════════════════════════════════\"\necho \" 🐾 OpenClaw is ready!\"\necho \"═══════════════════════════════════════════════════════════════════════════════\"\necho \"\"\necho \" Gateway URL: http://\\${GATEWAY_HOST}:\\${OPENCLAW_GATEWAY_PORT}\"\necho \" Bridge (WebSocket): ws://\\${GATEWAY_HOST}:\\${OPENCLAW_BRIDGE_PORT}\"\necho \" Config directory: \\${OPENCLAW_CONFIG_DIR}\"\necho \" Workspace directory:\\${OPENCLAW_WORKSPACE_DIR}\"\necho \"\"\necho \" Gateway Token: \\${OPENCLAW_GATEWAY_TOKEN}\"\necho \"\"\necho \" Manage:\"\necho \" Stop: ./scripts/stop.sh\"\necho \" Status: ./scripts/status.sh\"\necho \" Update: ./scripts/update.sh\"\necho \" Logs: docker compose logs -f\"\necho \"\"\necho \"═══════════════════════════════════════════════════════════════════════════════\"\n`;\n\n\t// ── scripts/stop.sh ─────────────────────────────────────────────────────\n\n\tfiles[\"scripts/stop.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Stop Script ───────────────────────────────────────────────────\n# Gracefully stops all services.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Stopping services...\"\necho \"\"\n\n# Graceful shutdown with timeout\ndocker compose down --timeout 30\n\necho \"\"\necho \"✅ All services stopped.\"\n`;\n\n\t// ── scripts/update.sh ───────────────────────────────────────────────────\n\n\tfiles[\"scripts/update.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Update Script ─────────────────────────────────────────────────\n# Pulls latest images and restarts services.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Updating services...\"\necho \"\"\n\n# Pull latest images\necho \"📦 Pulling latest images...\"\ndocker compose pull\n\necho \"\"\necho \"🔄 Restarting services with new images...\"\ndocker compose up -d --remove-orphans\n\necho \"\"\necho \"⏳ Waiting for services to stabilize...\"\nsleep 10\n\ndocker compose ps\n\necho \"\"\necho \"✅ Update complete!\"\n`;\n\n\t// ── scripts/backup.sh ───────────────────────────────────────────────────\n\n\tfiles[\"scripts/backup.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Backup Script ─────────────────────────────────────────────────\n# Backs up all named Docker volumes to a timestamped directory.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\nTIMESTAMP=$(date +%Y%m%d_%H%M%S)\nBACKUP_DIR=\"$PROJECT_DIR/backups/$TIMESTAMP\"\nmkdir -p \"$BACKUP_DIR\"\n\necho \"🐾 OpenClaw — Backing up volumes...\"\necho \" Backup directory: $BACKUP_DIR\"\necho \"\"\n\n# Get project name from docker compose\nPROJECT_NAME=$(docker compose config --format json 2>/dev/null | grep -o '\"name\":\"[^\"]*\"' | head -1 | cut -d'\"' -f4 || echo \"openclaw\")\n\n# List all volumes for this project\nVOLUMES=$(docker volume ls --filter \"name=\\${PROJECT_NAME}\" --format \"{{.Name}}\" 2>/dev/null || true)\n\nif [ -z \"$VOLUMES\" ]; then\n echo \"⚠️ No volumes found for project: $PROJECT_NAME\"\n echo \" Trying to list all openclaw volumes...\"\n VOLUMES=$(docker volume ls --filter \"name=openclaw\" --format \"{{.Name}}\" 2>/dev/null || true)\nfi\n\nif [ -z \"$VOLUMES\" ]; then\n echo \"❌ No volumes found to back up.\"\n exit 1\nfi\n\nBACKED_UP=0\nfor VOLUME in $VOLUMES; do\n echo \"📦 Backing up: $VOLUME\"\n docker run --rm \\\\\n -v \"\\${VOLUME}:/source:ro\" \\\\\n -v \"$BACKUP_DIR:/backup\" \\\\\n alpine tar czf \"/backup/\\${VOLUME}.tar.gz\" -C /source .\n\n SIZE=$(du -sh \"$BACKUP_DIR/\\${VOLUME}.tar.gz\" | cut -f1)\n echo \" ✓ $VOLUME ($SIZE)\"\n BACKED_UP=$((BACKED_UP + 1))\ndone\n\nTOTAL_SIZE=$(du -sh \"$BACKUP_DIR\" | cut -f1)\necho \"\"\necho \"✅ Backed up $BACKED_UP volume(s) ($TOTAL_SIZE total)\"\necho \" Location: $BACKUP_DIR\"\n`;\n\n\t// ── scripts/status.sh ───────────────────────────────────────────────────\n\n\tfiles[\"scripts/status.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Status Script ─────────────────────────────────────────────────\n# Shows the current status of all services.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Service Status\"\necho \"\"\n\n# Show compose status\ndocker compose ps\n\necho \"\"\necho \"── Resource Usage ──────────────────────────────────────────────────────\"\necho \"\"\n\n# Show resource usage\ndocker compose top 2>/dev/null || true\n\necho \"\"\necho \"── Disk Usage ─────────────────────────────────────────────────────────\"\necho \"\"\n\n# Show volume sizes\ndocker system df -v 2>/dev/null | head -30 || docker system df 2>/dev/null || true\n\necho \"\"\necho \"── Network ────────────────────────────────────────────────────────────\"\necho \"\"\n\ndocker network ls --filter \"name=openclaw\" --format \"table {{.Name}}\\\\t{{.Driver}}\\\\t{{.Scope}}\" 2>/dev/null || true\n`;\n\n\treturn files;\n}\n"],"mappings":";;;;;;;AAKA,SAAgB,kBAA0C;CACzD,MAAM,QAAgC,EAAE;AAIxC,OAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsM5B,OAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;AAuB3B,OAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkC7B,OAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyD7B,OAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsC7B,QAAO"}
1
+ {"version":3,"file":"scripts.cjs","names":[],"sources":["../../src/generators/scripts.ts"],"sourcesContent":["/**\n * Generates helper shell scripts for managing the OpenClaw Docker Compose stack.\n *\n * Returns a map of file paths (relative to project root) to file contents.\n */\nexport function generateScripts(options?: { hasGitServices?: boolean }): Record<string, string> {\n\tconst hasGit = options?.hasGitServices ?? false;\n\tconst files: Record<string, string> = {};\n\n\t// ── scripts/start.sh ────────────────────────────────────────────────────\n\n\tfiles[\"scripts/start.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Start Script ──────────────────────────────────────────────────\n# Production-quality bootstrap: validates prerequisites, auto-generates secrets,\n# creates required directories, and starts all services via Docker Compose.\n# Modelled after the official docker-setup.sh patterns.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Starting services...\"\necho \"\"\n\n# ── Colour helpers (no-op when not a TTY) ────────────────────────────────────\nif [ -t 1 ]; then\n RED='\\\\033[0;31m'; GREEN='\\\\033[0;32m'; YELLOW='\\\\033[1;33m'; CYAN='\\\\033[0;36m'; NC='\\\\033[0m'\nelse\n RED=''; GREEN=''; YELLOW=''; CYAN=''; NC=''\nfi\n\ninfo() { echo -e \"\\${CYAN}ℹ $*\\${NC}\"; }\nok() { echo -e \"\\${GREEN}✅ $*\\${NC}\"; }\nwarn() { echo -e \"\\${YELLOW}⚠️ $*\\${NC}\"; }\nerr() { echo -e \"\\${RED}❌ $*\\${NC}\" >&2; }\n\n# ── Prerequisite checks ─────────────────────────────────────────────────────\n\nif ! command -v docker &> /dev/null; then\n err \"Docker is not installed. Please install Docker first.\"\n echo \" https://docs.docker.com/get-docker/\"\n exit 1\nfi\n\nif ! docker compose version &> /dev/null; then\n err \"Docker Compose (v2) is not available.\"\n echo \" https://docs.docker.com/compose/install/\"\n exit 1\nfi\n\nif ! docker info &> /dev/null 2>&1; then\n err \"Docker daemon is not running. Please start Docker.\"\n exit 1\nfi\n\n# ── Source .env if it exists ─────────────────────────────────────────────────\n\nif [ -f \".env\" ]; then\n info \"Loading existing .env file...\"\n set -a\n # shellcheck disable=SC1091\n source .env\n set +a\nelse\n warn \".env file not found — will create one from .env.example if available.\"\n if [ -f \".env.example\" ]; then\n cp .env.example .env\n info \"Created .env from .env.example\"\n set -a\n # shellcheck disable=SC1091\n source .env\n set +a\n fi\nfi\n\n# ── Auto-generate OPENCLAW_GATEWAY_TOKEN if missing ──────────────────────────\n\nif [ -z \"\\${OPENCLAW_GATEWAY_TOKEN:-}\" ]; then\n info \"Generating OPENCLAW_GATEWAY_TOKEN...\"\n if command -v openssl &> /dev/null; then\n OPENCLAW_GATEWAY_TOKEN=\"$(openssl rand -hex 32)\"\n elif command -v python3 &> /dev/null; then\n OPENCLAW_GATEWAY_TOKEN=\"$(python3 -c 'import secrets; print(secrets.token_hex(32))')\"\n elif command -v python &> /dev/null; then\n OPENCLAW_GATEWAY_TOKEN=\"$(python -c 'import secrets; print(secrets.token_hex(32))')\"\n else\n err \"Cannot generate token: neither openssl nor python3 found.\"\n exit 1\n fi\n export OPENCLAW_GATEWAY_TOKEN\n\n # Persist into .env\n if [ -f \".env\" ]; then\n if grep -q \"^OPENCLAW_GATEWAY_TOKEN=\" .env 2>/dev/null; then\n sed -i.bak \"s|^OPENCLAW_GATEWAY_TOKEN=.*|OPENCLAW_GATEWAY_TOKEN=\\${OPENCLAW_GATEWAY_TOKEN}|\" .env && rm -f .env.bak\n else\n echo \"OPENCLAW_GATEWAY_TOKEN=\\${OPENCLAW_GATEWAY_TOKEN}\" >> .env\n fi\n fi\n ok \"Gateway token generated and saved.\"\nfi\n\n# ── Apply defaults for optional variables ────────────────────────────────────\n\nexport OPENCLAW_VERSION=\"\\${OPENCLAW_VERSION:-latest}\"\nexport OPENCLAW_GATEWAY_PORT=\"\\${OPENCLAW_GATEWAY_PORT:-18789}\"\nexport OPENCLAW_BRIDGE_PORT=\"\\${OPENCLAW_BRIDGE_PORT:-18790}\"\nexport OPENCLAW_GATEWAY_BIND=\"\\${OPENCLAW_GATEWAY_BIND:-lan}\"\nexport OPENCLAW_CONFIG_DIR=\"\\${OPENCLAW_CONFIG_DIR:-./openclaw/config}\"\nexport OPENCLAW_WORKSPACE_DIR=\"\\${OPENCLAW_WORKSPACE_DIR:-./openclaw/workspace}\"\n\n# ── Create required host directories ────────────────────────────────────────\n\ninfo \"Ensuring host directories exist...\"\nmkdir -p \"\\${OPENCLAW_CONFIG_DIR}\"\nmkdir -p \"\\${OPENCLAW_WORKSPACE_DIR}\"\nok \"Directories ready: \\${OPENCLAW_CONFIG_DIR}, \\${OPENCLAW_WORKSPACE_DIR}\"\n\n# ── Check for empty secret values ────────────────────────────────────────────\n\nEMPTY_SECRETS=0\nwhile IFS='=' read -r key value; do\n [[ \"$key\" =~ ^#.*$ ]] && continue\n [[ -z \"$key\" ]] && continue\n if [[ \"$key\" =~ (PASSWORD|TOKEN|SECRET|SESSION_KEY|COOKIE) ]] && [[ -z \"\\${value:-}\" ]]; then\n warn \"Warning: $key is empty in .env\"\n EMPTY_SECRETS=$((EMPTY_SECRETS + 1))\n fi\ndone < .env 2>/dev/null || true\n\nif [ \"$EMPTY_SECRETS\" -gt 0 ]; then\n echo \"\"\n warn \"$EMPTY_SECRETS secret(s) are empty. Some services may not function until they are set.\"\n echo \"\"\nfi\n\n# ── Clone git-based repositories (if any) ────────────────────────────────────\n\nif [ -f \"$SCRIPT_DIR/clone-repos.sh\" ]; then\n info \"Cloning/updating SaaS boilerplate repositories...\"\n bash \"$SCRIPT_DIR/clone-repos.sh\"\n ok \"Repositories ready.\"\nfi\n\n# ── Pull and start ───────────────────────────────────────────────────────────\n\necho \"\"\ninfo \"Pulling latest images...\"\ndocker compose pull --quiet 2>/dev/null || docker compose pull\n\necho \"\"\ninfo \"Starting services...\"\ndocker compose up -d --remove-orphans${hasGit ? \" --build\" : \"\"}\n\n# ── Health-check loop ────────────────────────────────────────────────────────\n\necho \"\"\ninfo \"Waiting for services to become healthy...\"\nsleep 5\n\nRETRIES=0\nMAX_RETRIES=30\nwhile [ $RETRIES -lt $MAX_RETRIES ]; do\n UNHEALTHY=$(docker compose ps --format json 2>/dev/null | grep -c '\"unhealthy\"' || true)\n STARTING=$(docker compose ps --format json 2>/dev/null | grep -c '\"starting\"' || true)\n\n if [ \"$UNHEALTHY\" -eq 0 ] && [ \"$STARTING\" -eq 0 ]; then\n break\n fi\n\n RETRIES=$((RETRIES + 1))\n sleep 2\ndone\n\necho \"\"\ndocker compose ps\necho \"\"\n\nif [ $RETRIES -ge $MAX_RETRIES ]; then\n warn \"Some services may still be starting. Check: docker compose ps\"\nelse\n ok \"All services are running!\"\nfi\n\n# ── Print service URLs & token ───────────────────────────────────────────────\n\nGATEWAY_HOST=\"localhost\"\nif [ \"\\${OPENCLAW_GATEWAY_BIND}\" = \"lan\" ]; then\n GATEWAY_HOST=\"0.0.0.0\"\nfi\n\necho \"\"\necho \"═══════════════════════════════════════════════════════════════════════════════\"\necho \" 🐾 OpenClaw is ready!\"\necho \"═══════════════════════════════════════════════════════════════════════════════\"\necho \"\"\necho \" Gateway URL: http://\\${GATEWAY_HOST}:\\${OPENCLAW_GATEWAY_PORT}\"\necho \" Bridge (WebSocket): ws://\\${GATEWAY_HOST}:\\${OPENCLAW_BRIDGE_PORT}\"\necho \" Config directory: \\${OPENCLAW_CONFIG_DIR}\"\necho \" Workspace directory:\\${OPENCLAW_WORKSPACE_DIR}\"\necho \"\"\necho \" Gateway Token: \\${OPENCLAW_GATEWAY_TOKEN}\"\necho \"\"\necho \" Manage:\"\necho \" Stop: ./scripts/stop.sh\"\necho \" Status: ./scripts/status.sh\"\necho \" Update: ./scripts/update.sh\"\necho \" Logs: docker compose logs -f\"\necho \"\"\necho \"═══════════════════════════════════════════════════════════════════════════════\"\n`;\n\n\t// ── scripts/stop.sh ─────────────────────────────────────────────────────\n\n\tfiles[\"scripts/stop.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Stop Script ───────────────────────────────────────────────────\n# Gracefully stops all services.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Stopping services...\"\necho \"\"\n\n# Graceful shutdown with timeout\ndocker compose down --timeout 30\n\necho \"\"\necho \"✅ All services stopped.\"\n`;\n\n\t// ── scripts/update.sh ───────────────────────────────────────────────────\n\n\tfiles[\"scripts/update.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Update Script ─────────────────────────────────────────────────\n# Pulls latest images and restarts services.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Updating services...\"\necho \"\"\n\n# Update git-based repositories (if any)\nif [ -f \"$SCRIPT_DIR/clone-repos.sh\" ]; then\n echo \"📂 Updating SaaS boilerplate repositories...\"\n bash \"$SCRIPT_DIR/clone-repos.sh\"\nfi\n\n# Pull latest images\necho \"📦 Pulling latest images...\"\ndocker compose pull\n\necho \"\"\necho \"🔄 Restarting services with new images...\"\ndocker compose up -d --remove-orphans${hasGit ? \" --build\" : \"\"}\n\necho \"\"\necho \"⏳ Waiting for services to stabilize...\"\nsleep 10\n\ndocker compose ps\n\necho \"\"\necho \"✅ Update complete!\"\n`;\n\n\t// ── scripts/backup.sh ───────────────────────────────────────────────────\n\n\tfiles[\"scripts/backup.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Backup Script ─────────────────────────────────────────────────\n# Backs up all named Docker volumes to a timestamped directory.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\nTIMESTAMP=$(date +%Y%m%d_%H%M%S)\nBACKUP_DIR=\"$PROJECT_DIR/backups/$TIMESTAMP\"\nmkdir -p \"$BACKUP_DIR\"\n\necho \"🐾 OpenClaw — Backing up volumes...\"\necho \" Backup directory: $BACKUP_DIR\"\necho \"\"\n\n# Get project name from docker compose\nPROJECT_NAME=$(docker compose config --format json 2>/dev/null | grep -o '\"name\":\"[^\"]*\"' | head -1 | cut -d'\"' -f4 || echo \"openclaw\")\n\n# List all volumes for this project\nVOLUMES=$(docker volume ls --filter \"name=\\${PROJECT_NAME}\" --format \"{{.Name}}\" 2>/dev/null || true)\n\nif [ -z \"$VOLUMES\" ]; then\n echo \"⚠️ No volumes found for project: $PROJECT_NAME\"\n echo \" Trying to list all openclaw volumes...\"\n VOLUMES=$(docker volume ls --filter \"name=openclaw\" --format \"{{.Name}}\" 2>/dev/null || true)\nfi\n\nif [ -z \"$VOLUMES\" ]; then\n echo \"❌ No volumes found to back up.\"\n exit 1\nfi\n\nBACKED_UP=0\nfor VOLUME in $VOLUMES; do\n echo \"📦 Backing up: $VOLUME\"\n docker run --rm \\\\\n -v \"\\${VOLUME}:/source:ro\" \\\\\n -v \"$BACKUP_DIR:/backup\" \\\\\n alpine tar czf \"/backup/\\${VOLUME}.tar.gz\" -C /source .\n\n SIZE=$(du -sh \"$BACKUP_DIR/\\${VOLUME}.tar.gz\" | cut -f1)\n echo \" ✓ $VOLUME ($SIZE)\"\n BACKED_UP=$((BACKED_UP + 1))\ndone\n\nTOTAL_SIZE=$(du -sh \"$BACKUP_DIR\" | cut -f1)\necho \"\"\necho \"✅ Backed up $BACKED_UP volume(s) ($TOTAL_SIZE total)\"\necho \" Location: $BACKUP_DIR\"\n`;\n\n\t// ── scripts/status.sh ───────────────────────────────────────────────────\n\n\tfiles[\"scripts/status.sh\"] = `#!/usr/bin/env bash\nset -euo pipefail\n\n# ─── OpenClaw Status Script ─────────────────────────────────────────────────\n# Shows the current status of all services.\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_DIR=\"$(dirname \"$SCRIPT_DIR\")\"\n\ncd \"$PROJECT_DIR\"\n\necho \"🐾 OpenClaw — Service Status\"\necho \"\"\n\n# Show compose status\ndocker compose ps\n\necho \"\"\necho \"── Resource Usage ──────────────────────────────────────────────────────\"\necho \"\"\n\n# Show resource usage\ndocker compose top 2>/dev/null || true\n\necho \"\"\necho \"── Disk Usage ─────────────────────────────────────────────────────────\"\necho \"\"\n\n# Show volume sizes\ndocker system df -v 2>/dev/null | head -30 || docker system df 2>/dev/null || true\n\necho \"\"\necho \"── Network ────────────────────────────────────────────────────────────\"\necho \"\"\n\ndocker network ls --filter \"name=openclaw\" --format \"table {{.Name}}\\\\t{{.Driver}}\\\\t{{.Scope}}\" 2>/dev/null || true\n`;\n\n\t// ═══════════════════════════════════════════════════════════════════════\n\t// PowerShell equivalents\n\t// ═══════════════════════════════════════════════════════════════════════\n\n\t// ── scripts/start.ps1 ───────────────────────────────────────────────────\n\n\tfiles[\"scripts/start.ps1\"] = `#Requires -Version 5.1\n<#\n.SYNOPSIS\n OpenClaw Start Script — validates prerequisites, auto-generates secrets,\n creates required directories, and starts all services via Docker Compose.\n#>\n\n$ErrorActionPreference = 'Stop'\n$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path\n$ProjectDir = Split-Path -Parent $ScriptDir\nSet-Location $ProjectDir\n\nfunction Info { param($Msg) Write-Host \" i $Msg\" -ForegroundColor Cyan }\nfunction Ok { param($Msg) Write-Host \" + $Msg\" -ForegroundColor Green }\nfunction Warn { param($Msg) Write-Host \" ! $Msg\" -ForegroundColor Yellow }\nfunction Err { param($Msg) Write-Host \" x $Msg\" -ForegroundColor Red }\n\nWrite-Host \"\"\nWrite-Host \"OpenClaw - Starting services...\" -ForegroundColor White\nWrite-Host \"\"\n\n# ── Prerequisite checks ─────────────────────────────────────────────────\nif (-not (Get-Command docker -ErrorAction SilentlyContinue)) {\n Err \"Docker is not installed. Please install Docker Desktop.\"\n Write-Host \" https://docs.docker.com/desktop/install/windows-install/\"\n exit 1\n}\n\n$composeCheck = docker compose version 2>&1\nif ($LASTEXITCODE -ne 0) {\n Err \"Docker Compose (v2) is not available.\"\n Write-Host \" https://docs.docker.com/compose/install/\"\n exit 1\n}\n\n$dockerInfo = docker info 2>&1\nif ($LASTEXITCODE -ne 0) {\n Err \"Docker daemon is not running. Please start Docker Desktop.\"\n exit 1\n}\n\n# ── Source .env if it exists ─────────────────────────────────────────────\nif (Test-Path \".env\") {\n Info \"Loading existing .env file...\"\n Get-Content \".env\" | ForEach-Object {\n if ($_ -match '^([^#=]+)=(.*)$') {\n [Environment]::SetEnvironmentVariable($Matches[1].Trim(), $Matches[2].Trim(), 'Process')\n }\n }\n} else {\n Warn \".env file not found - will create one from .env.example if available.\"\n if (Test-Path \".env.example\") {\n Copy-Item \".env.example\" \".env\"\n Info \"Created .env from .env.example\"\n Get-Content \".env\" | ForEach-Object {\n if ($_ -match '^([^#=]+)=(.*)$') {\n [Environment]::SetEnvironmentVariable($Matches[1].Trim(), $Matches[2].Trim(), 'Process')\n }\n }\n }\n}\n\n# ── Auto-generate OPENCLAW_GATEWAY_TOKEN if missing ──────────────────────\nif (-not $env:OPENCLAW_GATEWAY_TOKEN) {\n Info \"Generating OPENCLAW_GATEWAY_TOKEN...\"\n $bytes = New-Object byte[] 32\n [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)\n $env:OPENCLAW_GATEWAY_TOKEN = ($bytes | ForEach-Object { $_.ToString(\"x2\") }) -join ''\n\n if (Test-Path \".env\") {\n $envContent = Get-Content \".env\" -Raw\n if ($envContent -match '(?m)^OPENCLAW_GATEWAY_TOKEN=') {\n $envContent = $envContent -replace '(?m)^OPENCLAW_GATEWAY_TOKEN=.*', \"OPENCLAW_GATEWAY_TOKEN=$($env:OPENCLAW_GATEWAY_TOKEN)\"\n Set-Content \".env\" $envContent -NoNewline\n } else {\n Add-Content \".env\" \"OPENCLAW_GATEWAY_TOKEN=$($env:OPENCLAW_GATEWAY_TOKEN)\"\n }\n }\n Ok \"Gateway token generated and saved.\"\n}\n\n# ── Apply defaults ───────────────────────────────────────────────────────\nif (-not $env:OPENCLAW_VERSION) { $env:OPENCLAW_VERSION = \"latest\" }\nif (-not $env:OPENCLAW_GATEWAY_PORT) { $env:OPENCLAW_GATEWAY_PORT = \"18789\" }\nif (-not $env:OPENCLAW_BRIDGE_PORT) { $env:OPENCLAW_BRIDGE_PORT = \"18790\" }\nif (-not $env:OPENCLAW_GATEWAY_BIND) { $env:OPENCLAW_GATEWAY_BIND = \"lan\" }\nif (-not $env:OPENCLAW_CONFIG_DIR) { $env:OPENCLAW_CONFIG_DIR = \"./openclaw/config\" }\nif (-not $env:OPENCLAW_WORKSPACE_DIR) { $env:OPENCLAW_WORKSPACE_DIR = \"./openclaw/workspace\" }\n\n# ── Create required host directories ────────────────────────────────────\nInfo \"Ensuring host directories exist...\"\nNew-Item -ItemType Directory -Force -Path $env:OPENCLAW_CONFIG_DIR | Out-Null\nNew-Item -ItemType Directory -Force -Path $env:OPENCLAW_WORKSPACE_DIR | Out-Null\nOk \"Directories ready: $($env:OPENCLAW_CONFIG_DIR), $($env:OPENCLAW_WORKSPACE_DIR)\"\n\n# ── Clone git-based repositories (if any) ─────────────────────────────\n$cloneScript = Join-Path $ScriptDir \"clone-repos.ps1\"\nif (Test-Path $cloneScript) {\n Info \"Cloning/updating SaaS boilerplate repositories...\"\n & $cloneScript\n Ok \"Repositories ready.\"\n}\n\n# ── Pull and start ───────────────────────────────────────────────────────\nWrite-Host \"\"\nInfo \"Pulling latest images...\"\ndocker compose pull 2>$null\nif ($LASTEXITCODE -ne 0) { docker compose pull }\n\nWrite-Host \"\"\nInfo \"Starting services...\"\ndocker compose up -d --remove-orphans${hasGit ? \" --build\" : \"\"}\n\n# ── Health-check loop ────────────────────────────────────────────────────\nWrite-Host \"\"\nInfo \"Waiting for services to become healthy...\"\nStart-Sleep -Seconds 5\n\n$retries = 0\n$maxRetries = 30\nwhile ($retries -lt $maxRetries) {\n $psOutput = docker compose ps --format json 2>$null\n $unhealthy = ($psOutput | Select-String -Pattern '\"unhealthy\"' -SimpleMatch).Count\n $starting = ($psOutput | Select-String -Pattern '\"starting\"' -SimpleMatch).Count\n if ($unhealthy -eq 0 -and $starting -eq 0) { break }\n $retries++\n Start-Sleep -Seconds 2\n}\n\nWrite-Host \"\"\ndocker compose ps\nWrite-Host \"\"\n\nif ($retries -ge $maxRetries) {\n Warn \"Some services may still be starting. Check: docker compose ps\"\n} else {\n Ok \"All services are running!\"\n}\n\n# ── Print service URLs & token ───────────────────────────────────────────\n$gatewayHost = if ($env:OPENCLAW_GATEWAY_BIND -eq \"lan\") { \"0.0.0.0\" } else { \"localhost\" }\n\nWrite-Host \"\"\nWrite-Host \"===============================================================================\"\nWrite-Host \" OpenClaw is ready!\"\nWrite-Host \"===============================================================================\"\nWrite-Host \"\"\nWrite-Host \" Gateway URL: http://\\${gatewayHost}:$($env:OPENCLAW_GATEWAY_PORT)\"\nWrite-Host \" Bridge (WebSocket): ws://\\${gatewayHost}:$($env:OPENCLAW_BRIDGE_PORT)\"\nWrite-Host \" Config directory: $($env:OPENCLAW_CONFIG_DIR)\"\nWrite-Host \" Workspace directory: $($env:OPENCLAW_WORKSPACE_DIR)\"\nWrite-Host \"\"\nWrite-Host \" Gateway Token: $($env:OPENCLAW_GATEWAY_TOKEN)\"\nWrite-Host \"\"\nWrite-Host \" Manage:\"\nWrite-Host \" Stop: .\\\\scripts\\\\stop.ps1\"\nWrite-Host \" Status: .\\\\scripts\\\\status.ps1\"\nWrite-Host \" Update: .\\\\scripts\\\\update.ps1\"\nWrite-Host \" Logs: docker compose logs -f\"\nWrite-Host \"\"\nWrite-Host \"===============================================================================\"\n`;\n\n\t// ── scripts/stop.ps1 ────────────────────────────────────────────────────\n\n\tfiles[\"scripts/stop.ps1\"] = `#Requires -Version 5.1\n<#\n.SYNOPSIS\n OpenClaw Stop Script — gracefully stops all services.\n#>\n\n$ErrorActionPreference = 'Stop'\n$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path\n$ProjectDir = Split-Path -Parent $ScriptDir\nSet-Location $ProjectDir\n\nWrite-Host \"\"\nWrite-Host \"OpenClaw - Stopping services...\" -ForegroundColor White\nWrite-Host \"\"\n\ndocker compose down --timeout 30\n\nWrite-Host \"\"\nWrite-Host \" + All services stopped.\" -ForegroundColor Green\n`;\n\n\t// ── scripts/update.ps1 ──────────────────────────────────────────────────\n\n\tfiles[\"scripts/update.ps1\"] = `#Requires -Version 5.1\n<#\n.SYNOPSIS\n OpenClaw Update Script — pulls latest images and restarts services.\n#>\n\n$ErrorActionPreference = 'Stop'\n$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path\n$ProjectDir = Split-Path -Parent $ScriptDir\nSet-Location $ProjectDir\n\nWrite-Host \"\"\nWrite-Host \"OpenClaw - Updating services...\" -ForegroundColor White\nWrite-Host \"\"\n\n# Update git-based repositories (if any)\n$cloneScript = Join-Path $ScriptDir \"clone-repos.ps1\"\nif (Test-Path $cloneScript) {\n Write-Host \" Updating SaaS boilerplate repositories...\" -ForegroundColor Cyan\n & $cloneScript\n}\n\nWrite-Host \" Pulling latest images...\" -ForegroundColor Cyan\ndocker compose pull\n\nWrite-Host \"\"\nWrite-Host \" Restarting services with new images...\" -ForegroundColor Cyan\ndocker compose up -d --remove-orphans${hasGit ? \" --build\" : \"\"}\n\nWrite-Host \"\"\nWrite-Host \" Waiting for services to stabilize...\" -ForegroundColor Cyan\nStart-Sleep -Seconds 10\n\ndocker compose ps\n\nWrite-Host \"\"\nWrite-Host \" + Update complete!\" -ForegroundColor Green\n`;\n\n\t// ── scripts/backup.ps1 ──────────────────────────────────────────────────\n\n\tfiles[\"scripts/backup.ps1\"] = `#Requires -Version 5.1\n<#\n.SYNOPSIS\n OpenClaw Backup Script — backs up all named Docker volumes to a timestamped directory.\n#>\n\n$ErrorActionPreference = 'Stop'\n$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path\n$ProjectDir = Split-Path -Parent $ScriptDir\nSet-Location $ProjectDir\n\n$timestamp = Get-Date -Format \"yyyyMMdd_HHmmss\"\n$backupDir = Join-Path $ProjectDir \"backups\\\\$timestamp\"\nNew-Item -ItemType Directory -Force -Path $backupDir | Out-Null\n\nWrite-Host \"\"\nWrite-Host \"OpenClaw - Backing up volumes...\" -ForegroundColor White\nWrite-Host \" Backup directory: $backupDir\"\nWrite-Host \"\"\n\n# Get project name from docker compose\n$projectName = \"openclaw\"\ntry {\n $configJson = docker compose config --format json 2>$null | ConvertFrom-Json\n if ($configJson.name) { $projectName = $configJson.name }\n} catch {}\n\n# List all volumes for this project\n$volumes = docker volume ls --filter \"name=$projectName\" --format \"{{.Name}}\" 2>$null\nif (-not $volumes) {\n Write-Host \" ! No volumes found for project: $projectName\" -ForegroundColor Yellow\n Write-Host \" Trying to list all openclaw volumes...\"\n $volumes = docker volume ls --filter \"name=openclaw\" --format \"{{.Name}}\" 2>$null\n}\n\nif (-not $volumes) {\n Write-Host \" x No volumes found to back up.\" -ForegroundColor Red\n exit 1\n}\n\n$backedUp = 0\nforeach ($volume in $volumes) {\n $vol = $volume.Trim()\n if (-not $vol) { continue }\n Write-Host \" Backing up: $vol\" -ForegroundColor Cyan\n docker run --rm -v \"\\${vol}:/source:ro\" -v \"\\${backupDir}:/backup\" alpine tar czf \"/backup/$vol.tar.gz\" -C /source .\n $size = (Get-Item (Join-Path $backupDir \"$vol.tar.gz\")).Length / 1MB\n Write-Host \" + $vol ($([math]::Round($size, 1))MB)\" -ForegroundColor Green\n $backedUp++\n}\n\n$totalSize = ((Get-ChildItem $backupDir -Recurse | Measure-Object -Property Length -Sum).Sum) / 1MB\nWrite-Host \"\"\nWrite-Host \" + Backed up $backedUp volume(s) ($([math]::Round($totalSize, 1))MB total)\" -ForegroundColor Green\nWrite-Host \" Location: $backupDir\"\n`;\n\n\t// ── scripts/status.ps1 ──────────────────────────────────────────────────\n\n\tfiles[\"scripts/status.ps1\"] = `#Requires -Version 5.1\n<#\n.SYNOPSIS\n OpenClaw Status Script — shows the current status of all services.\n#>\n\n$ErrorActionPreference = 'Stop'\n$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path\n$ProjectDir = Split-Path -Parent $ScriptDir\nSet-Location $ProjectDir\n\nWrite-Host \"\"\nWrite-Host \"OpenClaw - Service Status\" -ForegroundColor White\nWrite-Host \"\"\n\n# Show compose status\ndocker compose ps\n\nWrite-Host \"\"\nWrite-Host \"-- Resource Usage ----------------------------------------------------------\"\nWrite-Host \"\"\n\ntry { docker compose top 2>$null } catch {}\n\nWrite-Host \"\"\nWrite-Host \"-- Disk Usage --------------------------------------------------------------\"\nWrite-Host \"\"\n\ntry { docker system df 2>$null } catch {}\n\nWrite-Host \"\"\nWrite-Host \"-- Network -----------------------------------------------------------------\"\nWrite-Host \"\"\n\ntry {\n docker network ls --filter \"name=openclaw\" --format \"table {{.Name}}\\\\t{{.Driver}}\\\\t{{.Scope}}\" 2>$null\n} catch {}\n`;\n\n\treturn files;\n}\n"],"mappings":";;;;;;;AAKA,SAAgB,gBAAgB,SAAgE;CAC/F,MAAM,SAAS,SAAS,kBAAkB;CAC1C,MAAM,QAAgC,EAAE;AAIxC,OAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAgJU,SAAS,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8D/D,OAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;AAuB3B,OAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;uCA0BS,SAAS,aAAa,GAAG;;;;;;;;;;;AAc/D,OAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyD7B,OAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4C7B,OAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCA+GS,SAAS,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsD/D,OAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;AAuB5B,OAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;uCA2BQ,SAAS,aAAa,GAAG;;;;;;;;;;;AAc/D,OAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2D9B,OAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuC9B,QAAO"}
@@ -4,7 +4,9 @@
4
4
  *
5
5
  * Returns a map of file paths (relative to project root) to file contents.
6
6
  */
7
- declare function generateScripts(): Record<string, string>;
7
+ declare function generateScripts(options?: {
8
+ hasGitServices?: boolean;
9
+ }): Record<string, string>;
8
10
  //#endregion
9
11
  export { generateScripts };
10
12
  //# sourceMappingURL=scripts.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scripts.d.cts","names":[],"sources":["../../src/generators/scripts.ts"],"mappings":";;AAKA;;;;iBAAgB,eAAA,CAAA,GAAmB,MAAA"}
1
+ {"version":3,"file":"scripts.d.cts","names":[],"sources":["../../src/generators/scripts.ts"],"mappings":";;AAKA;;;;iBAAgB,eAAA,CAAgB,OAAA;EAAY,cAAA;AAAA,IAA6B,MAAA"}
@@ -4,7 +4,9 @@
4
4
  *
5
5
  * Returns a map of file paths (relative to project root) to file contents.
6
6
  */
7
- declare function generateScripts(): Record<string, string>;
7
+ declare function generateScripts(options?: {
8
+ hasGitServices?: boolean;
9
+ }): Record<string, string>;
8
10
  //#endregion
9
11
  export { generateScripts };
10
12
  //# sourceMappingURL=scripts.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scripts.d.mts","names":[],"sources":["../../src/generators/scripts.ts"],"mappings":";;AAKA;;;;iBAAgB,eAAA,CAAA,GAAmB,MAAA"}
1
+ {"version":3,"file":"scripts.d.mts","names":[],"sources":["../../src/generators/scripts.ts"],"mappings":";;AAKA;;;;iBAAgB,eAAA,CAAgB,OAAA;EAAY,cAAA;AAAA,IAA6B,MAAA"}