@clawops/cli 1.7.0 → 1.7.2

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 (41) hide show
  1. package/README.md +62 -0
  2. package/dist/{apply-BTZFFGAD.js → apply-PZ5IIU7Z.js} +5 -4
  3. package/dist/{aws-D7Y6LCGK.js → aws-L4RR2LSE.js} +1 -1
  4. package/dist/{azure-JQAMNVHN.js → azure-7OXQENQL.js} +1 -1
  5. package/dist/{bootstrap-RY4VOSDJ.js → bootstrap-HL4DNUNG.js} +13 -4
  6. package/dist/bootstrap.sh.tmpl +204 -0
  7. package/dist/chunk-2YOP6N7X.js +126 -0
  8. package/dist/{chunk-GJEF6UQA.js → chunk-3XK66DKK.js} +100 -16
  9. package/dist/{chunk-ISFHLA4G.js → chunk-5SPESD5N.js} +8 -6
  10. package/dist/{chunk-YTH4L2GN.js → chunk-6X45DDGH.js} +5 -4
  11. package/dist/{chunk-XKT42M34.js → chunk-C5X375RO.js} +14 -1
  12. package/dist/{chunk-LCKD7L7X.js → chunk-DQDAWNGB.js} +1 -1
  13. package/dist/{chunk-CG3Y7Y2R.js → chunk-FSUWPL7Q.js} +9 -9
  14. package/dist/{chunk-ZFNPM2WG.js → chunk-O3F7OGH7.js} +40 -3
  15. package/dist/{chunk-3MFZ7E74.js → chunk-P5LKWRPL.js} +3 -3
  16. package/dist/chunk-PVUVI35Y.js +29 -0
  17. package/dist/{chunk-7KLLWDBA.js → chunk-SEABO2UU.js} +7 -4
  18. package/dist/cli.js +122 -68
  19. package/dist/{context-ALSJMTHE.js → context-5LCUG2QR.js} +1 -1
  20. package/dist/{gcp-6FT2A45S.js → gcp-UG6AWPIZ.js} +1 -1
  21. package/dist/{generate-ZTD4BVVI.js → generate-NIF6IBZC.js} +4 -3
  22. package/dist/{harden-BDVYW567.js → harden-URPXLSVF.js} +2 -2
  23. package/dist/{mcp-wire-ZWIYMLEW.js → mcp-wire-SLL4TLSC.js} +1 -1
  24. package/dist/{package-7WOZMHSO.js → package-TZ2HYF5C.js} +3 -2
  25. package/dist/{pool-JZGKPP6K.js → pool-QGFQRMGU.js} +2 -2
  26. package/dist/{remote-config-QF5TT7GU.js → remote-config-PFB66RPY.js} +3 -1
  27. package/dist/{server-EXBOOIEP.js → server-WM3AY4PJ.js} +19 -18
  28. package/dist/{ssh-E2AMBPZY.js → ssh-CNJNLM3E.js} +1 -1
  29. package/dist/{validate-T5M5EHSJ.js → validate-CFQ4FH2T.js} +2 -1
  30. package/dist/version-guard-MZAO4KHS.js +25 -0
  31. package/dist/versions-OEPAS2EL.js +24 -0
  32. package/package.json +3 -2
  33. package/spec/_gen-schemas.md +136 -0
  34. package/spec/deploy-plan.schema.json +193 -0
  35. package/spec/errors.yaml +175 -0
  36. package/spec/integrations.yaml +97 -0
  37. package/spec/invariants.yaml +81 -0
  38. package/spec/mcp-tools.yaml +532 -0
  39. package/spec/models.yaml +113 -0
  40. package/spec/openclaw-versions.yaml +67 -0
  41. package/spec/providers.schema.json +120 -0
@@ -42,6 +42,17 @@ usermod -aG docker clawops
42
42
  OPENCLAW_VERSION="${openclawVersion}"
43
43
  docker pull ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION}
44
44
 
45
+ # \u2500\u2500 Gateway auth token \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
46
+ # OpenClaw refuses a non-loopback bind without auth, and in a container it always
47
+ # binds 0.0.0.0. Without a token the gateway exits 78 and restart-loops.
48
+ OPENCLAW_ENV_FILE=/home/clawops/openclaw.env
49
+ if [ ! -s "\${OPENCLAW_ENV_FILE}" ]; then
50
+ OPENCLAW_TOKEN=$(openssl rand -hex 32 2>/dev/null || head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \\n')
51
+ printf 'OPENCLAW_GATEWAY_TOKEN=%s\\n' "\${OPENCLAW_TOKEN}" > "\${OPENCLAW_ENV_FILE}"
52
+ chmod 600 "\${OPENCLAW_ENV_FILE}"
53
+ chown clawops:clawops "\${OPENCLAW_ENV_FILE}"
54
+ fi
55
+
45
56
  # \u2500\u2500 Default config (apply.ts will overwrite with plan overlay) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
46
57
  OPENCLAW_CONFIG=/home/clawops/openclaw.json
47
58
  if [ ! -f "\${OPENCLAW_CONFIG}" ]; then
@@ -58,9 +69,11 @@ docker run -d \\
58
69
  --name openclaw \\
59
70
  --restart unless-stopped \\
60
71
  -p 18789:18789 \\
72
+ -e OPENCLAW_CONFIG_PATH=/app/config.json --add-host=host.docker.internal:host-gateway \\
73
+ --env-file "\${OPENCLAW_ENV_FILE}" \\
61
74
  -v "\${OPENCLAW_CONFIG}":/app/config.json:ro \\
62
75
  ${bedrockEnvBlock} ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION} \\
63
- node openclaw.mjs gateway run --allow-unconfigured
76
+ node openclaw.mjs gateway run --allow-unconfigured --port 18789
64
77
  `;
65
78
  }
66
79
  function makeBedrockEnvBlock() {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  connect
4
- } from "./chunk-GJEF6UQA.js";
4
+ } from "./chunk-3XK66DKK.js";
5
5
  import {
6
6
  NetworkError
7
7
  } from "./chunk-KGXPLI7W.js";
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ acquireSession,
4
+ drainPool
5
+ } from "./chunk-DQDAWNGB.js";
2
6
  import {
3
7
  OPENCLAW_CONFIG,
4
8
  atomicWriteConfig,
5
9
  restartGateway
6
- } from "./chunk-ZFNPM2WG.js";
10
+ } from "./chunk-O3F7OGH7.js";
7
11
  import {
8
12
  buildContext
9
- } from "./chunk-3MFZ7E74.js";
10
- import {
11
- acquireSession,
12
- drainPool
13
- } from "./chunk-LCKD7L7X.js";
13
+ } from "./chunk-P5LKWRPL.js";
14
14
  import {
15
15
  chalk,
16
16
  failure
@@ -131,7 +131,7 @@ function renderSnapshot(snap, opts) {
131
131
  return lines.join("\n");
132
132
  }
133
133
  async function probeEntries() {
134
- const { buildContext: buildContext2 } = await import("./context-ALSJMTHE.js");
134
+ const { buildContext: buildContext2 } = await import("./context-5LCUG2QR.js");
135
135
  const { getConfig } = await import("./store-SDUR52Z5.js");
136
136
  const config = getConfig();
137
137
  if (!config) return [];
@@ -358,8 +358,8 @@ var monitor_default = defineCommand({
358
358
  const tailLines = Math.max(1, parseInt(String(args.tail ?? "10"), 10) || 10);
359
359
  const isTTY = Boolean(process.stdout.isTTY);
360
360
  const noColor = Boolean(args["no-color"]) || !isTTY;
361
- const { buildContext: buildContext2 } = await import("./context-ALSJMTHE.js");
362
- const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-JZGKPP6K.js");
361
+ const { buildContext: buildContext2 } = await import("./context-5LCUG2QR.js");
362
+ const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-QGFQRMGU.js");
363
363
  const ac = new AbortController();
364
364
  process.on("SIGINT", () => ac.abort());
365
365
  process.on("SIGTERM", () => ac.abort());
@@ -1,5 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/openclaw/run-flags.ts
4
+ var CONFIG_MOUNT_PATH = "/app/config.json";
5
+ var GATEWAY_PORT = 18789;
6
+ var CONFIG_PATH_ENV = `-e OPENCLAW_CONFIG_PATH=${CONFIG_MOUNT_PATH}`;
7
+ var ADD_HOST_FLAG = "--add-host=host.docker.internal:host-gateway";
8
+ var PORT_PIN = `--port ${GATEWAY_PORT}`;
9
+ var COMMON_RUN_FLAGS = `${CONFIG_PATH_ENV} ${ADD_HOST_FLAG}`;
10
+
3
11
  // src/plan/remote-config.ts
4
12
  var OPENCLAW_CONFIG_LINUX = "/home/clawops/openclaw.json";
5
13
  var OPENCLAW_CONFIG_MACOS = "~/.config/openclaw/config.json";
@@ -30,6 +38,18 @@ async function readRemoteConfig(session, signal) {
30
38
  throw new Error(`Cannot parse ${configPath}: invalid JSON`);
31
39
  }
32
40
  }
41
+ function normaliseGatewayPort(cfg) {
42
+ const gateway = cfg["gateway"];
43
+ if (!gateway || typeof gateway !== "object" || Array.isArray(gateway)) return void 0;
44
+ const g = gateway;
45
+ const current = g["port"];
46
+ if (typeof current === "number" && current !== GATEWAY_PORT) {
47
+ g["port"] = GATEWAY_PORT;
48
+ return current;
49
+ }
50
+ if (current === void 0) g["port"] = GATEWAY_PORT;
51
+ return void 0;
52
+ }
33
53
  async function atomicWriteConfig(session, cfg, signal) {
34
54
  const os = await detectOS(session, signal);
35
55
  const configPath = configPathForOS(os);
@@ -50,25 +70,41 @@ async function restartGateway(session, signal) {
50
70
  const imgResult = os === "Darwin" ? await session.exec(imgCmd, signal) : await execWithFallbackSudo(session, imgCmd, signal);
51
71
  const image = imgResult.stdout.trim();
52
72
  const cfgResult = await session.exec(`cat ${configPath}`, signal);
53
- let gatewayCmd = "node openclaw.mjs gateway run --allow-unconfigured";
73
+ let gatewayCmd = `node openclaw.mjs gateway run --allow-unconfigured ${PORT_PIN}`;
54
74
  try {
55
75
  const cfg = JSON.parse(cfgResult.stdout);
56
76
  const token = cfg?.["gateway"]?.["auth"];
57
77
  const tokenVal = token?.["token"];
58
78
  if (tokenVal) {
59
- gatewayCmd = `node openclaw.mjs gateway run --allow-unconfigured --token '${tokenVal}'`;
79
+ gatewayCmd = `node openclaw.mjs gateway run --allow-unconfigured ${PORT_PIN} --token '${tokenVal}'`;
60
80
  }
61
81
  } catch {
62
82
  }
63
83
  const restartCmd = pathPrefix + [
64
84
  "docker stop openclaw 2>/dev/null || true",
65
85
  "docker rm openclaw 2>/dev/null || true",
66
- `docker run -d --name openclaw --restart unless-stopped -p 18789:18789 -v ${configPath}:/app/config.json:ro ${image} ${gatewayCmd}`
86
+ `docker run -d --name openclaw --restart unless-stopped -p ${GATEWAY_PORT}:${GATEWAY_PORT} ${COMMON_RUN_FLAGS} -v ${configPath}:/app/config.json:ro ${image} ${gatewayCmd}`
67
87
  ].join(" && ");
68
88
  const result = os === "Darwin" ? await session.exec(restartCmd, signal) : await execWithFallbackSudo(session, restartCmd, signal);
69
89
  if (result.code !== 0) {
70
90
  throw new Error(`Gateway restart failed: ${result.stderr}`);
71
91
  }
92
+ const healthy = await waitForGateway(session, pathPrefix, signal);
93
+ if (!healthy) {
94
+ throw new Error(
95
+ `Gateway restarted but did not become healthy on port ${GATEWAY_PORT}. The previous container has already been replaced; inspect it with \`docker logs openclaw\`. If the newly-applied config is at fault, revert it and restart \u2014 before v1.7.2 this config was never applied, so a value that has sat unused may now be taking effect.`
96
+ );
97
+ }
98
+ }
99
+ async function waitForGateway(session, pathPrefix, signal, attempts = 15) {
100
+ const probe = `${pathPrefix}curl -fsS -m 3 http://127.0.0.1:${GATEWAY_PORT}/healthz >/dev/null 2>&1 && echo ok || echo waiting`;
101
+ for (let i = 0; i < attempts; i++) {
102
+ if (signal?.aborted) return false;
103
+ const r = await session.exec(probe, signal);
104
+ if (r.stdout.trim().endsWith("ok")) return true;
105
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
106
+ }
107
+ return false;
72
108
  }
73
109
  function deepMerge(base, overlay) {
74
110
  const result = { ...base };
@@ -91,6 +127,7 @@ export {
91
127
  OPENCLAW_CONFIG,
92
128
  OPENCLAW_TMP,
93
129
  readRemoteConfig,
130
+ normaliseGatewayPort,
94
131
  atomicWriteConfig,
95
132
  restartGateway,
96
133
  deepMerge
@@ -56,17 +56,17 @@ function makeProviderProxy(name) {
56
56
  if (resolved) return resolved;
57
57
  switch (name) {
58
58
  case "gcp": {
59
- const mod = await import("./gcp-6FT2A45S.js");
59
+ const mod = await import("./gcp-UG6AWPIZ.js");
60
60
  resolved = mod.default;
61
61
  return resolved;
62
62
  }
63
63
  case "aws": {
64
- const mod = await import("./aws-D7Y6LCGK.js");
64
+ const mod = await import("./aws-L4RR2LSE.js");
65
65
  resolved = mod.default;
66
66
  return resolved;
67
67
  }
68
68
  case "azure": {
69
- const mod = await import("./azure-JQAMNVHN.js");
69
+ const mod = await import("./azure-7OXQENQL.js");
70
70
  resolved = mod.default;
71
71
  return resolved;
72
72
  }
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/spec-path.ts
4
+ import { existsSync } from "fs";
5
+ import { fileURLToPath } from "url";
6
+ import { dirname, join, parse } from "path";
7
+ var MARKER = "openclaw-versions.yaml";
8
+ var _cached;
9
+ function resolveSpecDir(startUrl = import.meta.url) {
10
+ if (_cached) return _cached;
11
+ let dir = dirname(fileURLToPath(startUrl));
12
+ const { root } = parse(dir);
13
+ while (true) {
14
+ const candidate = join(dir, "spec");
15
+ if (existsSync(join(candidate, MARKER))) {
16
+ _cached = candidate;
17
+ return candidate;
18
+ }
19
+ if (dir === root) break;
20
+ dir = dirname(dir);
21
+ }
22
+ throw new Error(
23
+ `Cannot locate the spec/ directory (searched upward from ${dirname(fileURLToPath(startUrl))}). If this is an installed package, spec/ may be missing from the published files.`
24
+ );
25
+ }
26
+
27
+ export {
28
+ resolveSpecDir
29
+ };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  validatePlan
4
- } from "./chunk-YTH4L2GN.js";
4
+ } from "./chunk-6X45DDGH.js";
5
5
  import {
6
6
  buildContext
7
- } from "./chunk-3MFZ7E74.js";
7
+ } from "./chunk-P5LKWRPL.js";
8
8
  import {
9
9
  getConfig
10
10
  } from "./chunk-CX5SL5HP.js";
@@ -45,10 +45,13 @@ async function generatePlan(intent, _opts) {
45
45
  "plan/apply is not supported for the local provider. Use `clawops up` directly."
46
46
  );
47
47
  }
48
- const { version } = await import("./package-7WOZMHSO.js");
48
+ const { version } = await import("./package-TZ2HYF5C.js");
49
49
  const config = getConfig();
50
50
  const instanceType = intent.instanceType ?? "small";
51
- const openclawVersion = intent.openclawVersion ?? "latest";
51
+ const { guardOpenclawVersion, defaultOpenclawVersion } = await import("./version-guard-MZAO4KHS.js");
52
+ const openclawVersion = await guardOpenclawVersion(
53
+ intent.openclawVersion ?? await defaultOpenclawVersion()
54
+ );
52
55
  const network = intent.network ?? {
53
56
  allowedSshCidrs: [],
54
57
  allowedGatewayCidrs: []