@clawops/cli 1.7.8 → 2.0.0
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/README.md +412 -70
- package/dist/{apply-F3KY2HTB.js → apply-AM5HERE7.js} +8 -6
- package/dist/{aws-L4RR2LSE.js → aws-AMON7DA7.js} +20 -9
- package/dist/{azure-7OXQENQL.js → azure-T4G6OBJQ.js} +19 -8
- package/dist/{bootstrap-HL4DNUNG.js → bootstrap-DMRPWJGN.js} +28 -19
- package/dist/bootstrap.sh.tmpl +51 -31
- package/dist/channels-KBUR42IU.js +53 -0
- package/dist/{chunk-DQDAWNGB.js → chunk-3WYA2QDM.js} +1 -1
- package/dist/chunk-6TIYVHPX.js +152 -0
- package/dist/{chunk-3XK66DKK.js → chunk-AHAAEXWC.js} +41 -0
- package/dist/{chunk-QQNKBTYZ.js → chunk-AX74VXTV.js} +292 -94
- package/dist/{chunk-C5X375RO.js → chunk-CKSPROD5.js} +59 -15
- package/dist/{chunk-UKTP332Z.js → chunk-GAZPPSKU.js} +6 -7
- package/dist/{chunk-FNS56UQY.js → chunk-GYV4KNW7.js} +319 -252
- package/dist/{chunk-PVUVI35Y.js → chunk-JW5A7E3X.js} +5 -1
- package/dist/chunk-LT4XMO5D.js +50 -0
- package/dist/{chunk-P5LKWRPL.js → chunk-LU2V3LXA.js} +3 -3
- package/dist/chunk-N44K3LHE.js +140 -0
- package/dist/chunk-NUDIHZEH.js +55 -0
- package/dist/chunk-SBLQH2TJ.js +56 -0
- package/dist/chunk-UFRO4H5W.js +228 -0
- package/dist/{chunk-RAAONHW3.js → chunk-WHJMKDV7.js} +24 -4
- package/dist/chunk-YR3O2I3S.js +101 -0
- package/dist/cli.js +866 -577
- package/dist/config-validate-K2N6XLDX.js +76 -0
- package/dist/{context-5LCUG2QR.js → context-KHKWJJMC.js} +1 -1
- package/dist/{firewall-XQGO7HWK.js → firewall-T3NTPZJD.js} +10 -0
- package/dist/{gcp-UG6AWPIZ.js → gcp-2JBTD7ZM.js} +19 -8
- package/dist/{generate-ELD7QF5Z.js → generate-2XV2GSP2.js} +4 -4
- package/dist/{harden-URPXLSVF.js → harden-PCDK3UQ5.js} +48 -11
- package/dist/health-5CCOXYGG.js +11 -0
- package/dist/logs-P7YCKVF4.js +15 -0
- package/dist/{mcp-wire-ZMIVFAUC.js → mcp-wire-BFEY2Y6H.js} +23 -17
- package/dist/{package-QYZFN3FP.js → package-3HUW57XH.js} +3 -3
- package/dist/plugins-DTST3OER.js +49 -0
- package/dist/{pool-QGFQRMGU.js → pool-EX4ZTA5P.js} +2 -2
- package/dist/privileged-JFA6LLTV.js +17 -0
- package/dist/{remote-config-QDLN4UMG.js → remote-config-Z6IIZR3D.js} +3 -3
- package/dist/runtime-LZ7NA53V.js +42 -0
- package/dist/{server-FWTOSSZP.js → server-A5AB67GQ.js} +16 -12
- package/dist/spec-path-KQOOIQCA.js +9 -0
- package/dist/{ssh-CNJNLM3E.js → ssh-B3NZAU4I.js} +1 -1
- package/dist/upgrade-ULD4KFYC.js +88 -0
- package/dist/validate-BOQRWX4F.js +14 -0
- package/dist/{version-guard-VUCNZXQS.js → version-guard-GPSTCPT7.js} +3 -3
- package/dist/{versions-2UVAT6PQ.js → versions-W5LRQCAJ.js} +2 -2
- package/package.json +3 -3
- package/spec/deploy-plan.schema.json +114 -25
- package/spec/integrations.yaml +135 -28
- package/spec/mcp-tools.yaml +68 -35
- package/spec/models.yaml +9 -0
- package/spec/openclaw-2.0.config.schema.json +1 -0
- package/spec/openclaw-versions.yaml +116 -27
- package/dist/chunk-35WVQY3X.js +0 -122
- package/dist/chunk-6X45DDGH.js +0 -42
- package/dist/chunk-SEZMVVAS.js +0 -156
- package/dist/validate-CFQ4FH2T.js +0 -10
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/openclaw/upgrade.ts
|
|
4
|
+
function judgePreflight(report) {
|
|
5
|
+
const { targetVersion, foundVersion, status, reason } = report;
|
|
6
|
+
if (status === "indeterminate") {
|
|
7
|
+
return {
|
|
8
|
+
ok: false,
|
|
9
|
+
reason: reason ?? "the database schema could not be determined, so compatibility with the target release is unknown"
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (typeof foundVersion === "number" && typeof targetVersion === "number") {
|
|
13
|
+
if (foundVersion > targetVersion) {
|
|
14
|
+
return {
|
|
15
|
+
ok: false,
|
|
16
|
+
reason: `the state database is at schema ${foundVersion}, but the target release understands ${targetVersion}. This is a downgrade across a schema boundary: the older release would read a database written by a newer one. Restore a backup taken before the upgrade instead.`
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (foundVersion < targetVersion) {
|
|
20
|
+
return { ok: true, note: `state will migrate from schema ${foundVersion} to ${targetVersion}` };
|
|
21
|
+
}
|
|
22
|
+
return { ok: true };
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
ok: false,
|
|
26
|
+
reason: reason ?? `preflight returned no schema version (status: ${status ?? "unknown"})`
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function parsePreflight(stdout) {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(stdout.trim());
|
|
32
|
+
if (parsed !== null && typeof parsed === "object") return parsed;
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
function snapshotCommand(image, stateDir, repo) {
|
|
38
|
+
return `docker run --rm -v ${stateDir}:/home/node/.openclaw ${image} openclaw backup sqlite create --global --repository ${repo} --json`;
|
|
39
|
+
}
|
|
40
|
+
function preflightCommand(targetImage, stateDir, snapshotDb) {
|
|
41
|
+
return `docker run --rm -v ${stateDir}:/home/node/.openclaw ${targetImage} openclaw database preflight ${snapshotDb} --json`;
|
|
42
|
+
}
|
|
43
|
+
function snapshotPathFrom(stdout) {
|
|
44
|
+
try {
|
|
45
|
+
const parsed = JSON.parse(stdout.trim());
|
|
46
|
+
if (parsed.ok === true && typeof parsed.snapshotPath === "string") return parsed.snapshotPath;
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
function repairCommand(image, stateDir) {
|
|
52
|
+
return `docker run --rm -v ${stateDir}:/home/node/.openclaw ${image} openclaw doctor --fix --non-interactive --yes`;
|
|
53
|
+
}
|
|
54
|
+
function describeOutcome(o, version) {
|
|
55
|
+
switch (o.kind) {
|
|
56
|
+
case "started":
|
|
57
|
+
return `Gateway updated to ${version}.`;
|
|
58
|
+
case "repaired":
|
|
59
|
+
return `Gateway updated to ${version} after a one-shot repair (doctor --fix).`;
|
|
60
|
+
case "rolled-back":
|
|
61
|
+
return `Rolled back to ${o.to}: the gateway did not start on ${version} \u2014 ${o.reason}. The previous image is running again. If it also fails, restore the snapshot taken before the upgrade.`;
|
|
62
|
+
case "failed":
|
|
63
|
+
return `Upgrade to ${version} failed and the rollback did not come up either \u2014 ${o.reason}. The state snapshot taken before the upgrade is at ${o.snapshotPath}; restore it with \`openclaw backup sqlite restore\` before retrying.`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function resolveUpgrade(steps, ctx) {
|
|
67
|
+
const first = await steps.gate();
|
|
68
|
+
if (first.ok) return { kind: "started" };
|
|
69
|
+
await steps.repair();
|
|
70
|
+
await steps.run(ctx.version);
|
|
71
|
+
const second = await steps.gate();
|
|
72
|
+
if (second.ok) return { kind: "repaired" };
|
|
73
|
+
const reason = second.reason ?? first.reason ?? "unknown";
|
|
74
|
+
if (!ctx.previousVersion) return { kind: "failed", reason, snapshotPath: ctx.snapshotPath };
|
|
75
|
+
await steps.run(ctx.previousVersion);
|
|
76
|
+
const back = await steps.gate();
|
|
77
|
+
return back.ok ? { kind: "rolled-back", to: ctx.previousVersion, reason } : { kind: "failed", reason, snapshotPath: ctx.snapshotPath };
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
describeOutcome,
|
|
81
|
+
judgePreflight,
|
|
82
|
+
parsePreflight,
|
|
83
|
+
preflightCommand,
|
|
84
|
+
repairCommand,
|
|
85
|
+
resolveUpgrade,
|
|
86
|
+
snapshotCommand,
|
|
87
|
+
snapshotPathFrom
|
|
88
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
assertValidPlan,
|
|
4
|
+
validatePlan,
|
|
5
|
+
validatePlanConfig,
|
|
6
|
+
validatePlanNetwork
|
|
7
|
+
} from "./chunk-YR3O2I3S.js";
|
|
8
|
+
import "./chunk-JW5A7E3X.js";
|
|
9
|
+
export {
|
|
10
|
+
assertValidPlan,
|
|
11
|
+
validatePlan,
|
|
12
|
+
validatePlanConfig,
|
|
13
|
+
validatePlanNetwork
|
|
14
|
+
};
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
assertSupportedVersion,
|
|
4
4
|
loadVersionSpec
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-PVUVI35Y.js";
|
|
5
|
+
} from "./chunk-GAZPPSKU.js";
|
|
6
|
+
import "./chunk-JW5A7E3X.js";
|
|
8
7
|
import {
|
|
9
8
|
UsageError
|
|
10
9
|
} from "./chunk-KGXPLI7W.js";
|
|
10
|
+
import "./chunk-EI7CQQ7D.js";
|
|
11
11
|
|
|
12
12
|
// src/cli/version-guard.ts
|
|
13
13
|
async function defaultOpenclawVersion() {
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
isMovingTag,
|
|
10
10
|
loadVersionSpec,
|
|
11
11
|
resolveVersion
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GAZPPSKU.js";
|
|
13
|
+
import "./chunk-JW5A7E3X.js";
|
|
13
14
|
import "./chunk-EI7CQQ7D.js";
|
|
14
|
-
import "./chunk-PVUVI35Y.js";
|
|
15
15
|
export {
|
|
16
16
|
MOVING_TAGS,
|
|
17
17
|
_resetVersionSpecCache,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawops/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Deploy and manage self-hosted OpenClaw instances across clouds",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"test": "vitest run",
|
|
33
33
|
"test:pulumi": "vitest run tests/providers/aws/program.test.ts tests/providers/azure/program.test.ts",
|
|
34
34
|
"test:changed": "vitest --changed",
|
|
35
|
-
"test:mutation": "node scripts/dev/mutation-check.mjs",
|
|
36
35
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
37
36
|
"typecheck": "NODE_OPTIONS=--max-old-space-size=4096 tsc --noEmit",
|
|
38
37
|
"lint": "eslint --max-warnings=0 src tests scripts",
|
|
39
38
|
"gen:schemas": "tsx scripts/gen-schemas.ts",
|
|
40
39
|
"changeset": "changeset",
|
|
41
|
-
"release": "pnpm build && changeset publish"
|
|
40
|
+
"release": "pnpm build && changeset publish",
|
|
41
|
+
"test:mutation": "node scripts/dev/mutation-check.mjs"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@aws-sdk/client-cloudwatch-logs": "^3.1063.0",
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
"title": "DeployPlan",
|
|
5
5
|
"description": "The Maker plan artifact (borrowed from Clanker pattern). Generated by `clawops plan`, applied by `clawops apply`. Reviewable, diff-able, version-controllable.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"apiVersion",
|
|
9
|
+
"kind",
|
|
10
|
+
"metadata",
|
|
11
|
+
"spec"
|
|
12
|
+
],
|
|
8
13
|
"properties": {
|
|
9
14
|
"apiVersion": {
|
|
10
15
|
"const": "clawops.dev/v1",
|
|
@@ -15,7 +20,10 @@
|
|
|
15
20
|
},
|
|
16
21
|
"metadata": {
|
|
17
22
|
"type": "object",
|
|
18
|
-
"required": [
|
|
23
|
+
"required": [
|
|
24
|
+
"name",
|
|
25
|
+
"generatedAt"
|
|
26
|
+
],
|
|
19
27
|
"properties": {
|
|
20
28
|
"name": {
|
|
21
29
|
"type": "string",
|
|
@@ -38,7 +46,9 @@
|
|
|
38
46
|
},
|
|
39
47
|
"labels": {
|
|
40
48
|
"type": "object",
|
|
41
|
-
"additionalProperties": {
|
|
49
|
+
"additionalProperties": {
|
|
50
|
+
"type": "string"
|
|
51
|
+
},
|
|
42
52
|
"description": "User-supplied labels (env=prod, team=platform, etc.)"
|
|
43
53
|
},
|
|
44
54
|
"stackVersion": {
|
|
@@ -49,10 +59,21 @@
|
|
|
49
59
|
},
|
|
50
60
|
"spec": {
|
|
51
61
|
"type": "object",
|
|
52
|
-
"required": [
|
|
62
|
+
"required": [
|
|
63
|
+
"provider",
|
|
64
|
+
"stackName",
|
|
65
|
+
"instanceType",
|
|
66
|
+
"openclaw",
|
|
67
|
+
"network"
|
|
68
|
+
],
|
|
53
69
|
"properties": {
|
|
54
70
|
"provider": {
|
|
55
|
-
"enum": [
|
|
71
|
+
"enum": [
|
|
72
|
+
"aws",
|
|
73
|
+
"gcp",
|
|
74
|
+
"azure",
|
|
75
|
+
"local"
|
|
76
|
+
]
|
|
56
77
|
},
|
|
57
78
|
"region": {
|
|
58
79
|
"type": "string",
|
|
@@ -68,7 +89,9 @@
|
|
|
68
89
|
},
|
|
69
90
|
"openclaw": {
|
|
70
91
|
"type": "object",
|
|
71
|
-
"required": [
|
|
92
|
+
"required": [
|
|
93
|
+
"version"
|
|
94
|
+
],
|
|
72
95
|
"properties": {
|
|
73
96
|
"version": {
|
|
74
97
|
"type": "string",
|
|
@@ -81,7 +104,9 @@
|
|
|
81
104
|
"channels": {
|
|
82
105
|
"type": "object",
|
|
83
106
|
"description": "OpenClaw channel integrations keyed by provider name (e.g. {\"discord\":{\"botToken\":\"...\"}}). Values are provider-specific config objects. Sensitive fields must use $secret references.",
|
|
84
|
-
"additionalProperties": {
|
|
107
|
+
"additionalProperties": {
|
|
108
|
+
"type": "object"
|
|
109
|
+
}
|
|
85
110
|
}
|
|
86
111
|
}
|
|
87
112
|
},
|
|
@@ -90,11 +115,23 @@
|
|
|
90
115
|
"description": "Secret references (R6: never inline values)",
|
|
91
116
|
"items": {
|
|
92
117
|
"type": "object",
|
|
93
|
-
"required": [
|
|
118
|
+
"required": [
|
|
119
|
+
"name",
|
|
120
|
+
"source"
|
|
121
|
+
],
|
|
94
122
|
"properties": {
|
|
95
|
-
"name": {
|
|
123
|
+
"name": {
|
|
124
|
+
"type": "string"
|
|
125
|
+
},
|
|
96
126
|
"source": {
|
|
97
|
-
"enum": [
|
|
127
|
+
"enum": [
|
|
128
|
+
"env",
|
|
129
|
+
"aws-sm",
|
|
130
|
+
"aws-ssm",
|
|
131
|
+
"gcp-sm",
|
|
132
|
+
"azure-kv",
|
|
133
|
+
"file"
|
|
134
|
+
]
|
|
98
135
|
},
|
|
99
136
|
"ref": {
|
|
100
137
|
"type": "string",
|
|
@@ -105,26 +142,56 @@
|
|
|
105
142
|
},
|
|
106
143
|
"network": {
|
|
107
144
|
"type": "object",
|
|
108
|
-
"required": [
|
|
145
|
+
"required": [
|
|
146
|
+
"allowedSshCidrs",
|
|
147
|
+
"allowedGatewayCidrs"
|
|
148
|
+
],
|
|
109
149
|
"properties": {
|
|
110
150
|
"allowedSshCidrs": {
|
|
111
151
|
"type": "array",
|
|
112
|
-
"items": {
|
|
152
|
+
"items": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"format": "cidr"
|
|
155
|
+
},
|
|
113
156
|
"minItems": 0,
|
|
114
157
|
"description": "Empty array = no SSH access (unusual but allowed). Defaults applied at plan generation, not in schema"
|
|
115
158
|
},
|
|
116
159
|
"allowedGatewayCidrs": {
|
|
117
160
|
"type": "array",
|
|
118
|
-
"items": {
|
|
119
|
-
|
|
161
|
+
"items": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"format": "cidr"
|
|
164
|
+
},
|
|
165
|
+
"description": "CIDRs allowed to reach the gateway port. Only meaningful with publishGateway \"all\" — under \"loopback\" nothing listens on a routable interface, so these rules would admit traffic to a closed port. clawops refuses that combination rather than creating rules that do nothing."
|
|
166
|
+
},
|
|
167
|
+
"gatewayPort": {
|
|
168
|
+
"type": "integer",
|
|
169
|
+
"minimum": 1,
|
|
170
|
+
"maximum": 65535,
|
|
171
|
+
"default": 18789,
|
|
172
|
+
"description": "Host port the gateway is published on. Carried in the plan so the firewall rules, the container publish flag, the startup config and the gateway URL all come from one place; it used to be a constant redeclared in six files, which made a port change a six-file edit that could half-apply."
|
|
120
173
|
},
|
|
121
174
|
"tailscale": {
|
|
122
175
|
"type": "object",
|
|
123
176
|
"description": "Optional Tailscale sidecar (borrowed pattern from schmitthub)",
|
|
124
177
|
"properties": {
|
|
125
|
-
"enabled": {
|
|
126
|
-
|
|
178
|
+
"enabled": {
|
|
179
|
+
"type": "boolean"
|
|
180
|
+
},
|
|
181
|
+
"authKeyRef": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"description": "Reference to a secret containing the Tailscale auth key"
|
|
184
|
+
}
|
|
127
185
|
}
|
|
186
|
+
},
|
|
187
|
+
"publishGateway": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"enum": [
|
|
190
|
+
"loopback",
|
|
191
|
+
"all"
|
|
192
|
+
],
|
|
193
|
+
"default": "loopback",
|
|
194
|
+
"description": "Which interface the gateway container publishes on. \"loopback\" (default) binds 127.0.0.1 on the host, so the gateway is reachable only via `clawops tunnel` or a reverse proxy running on that host. \"all\" binds 0.0.0.0. Deliberately separate from allowedGatewayCidrs: a firewall rule says who may connect, this says whether the port is listening at all, and exposure should be an explicit choice rather than inherited from a CIDR chosen for SSH. \"all\" serves plaintext HTTP unless you front it with TLS."
|
|
128
195
|
}
|
|
129
196
|
}
|
|
130
197
|
},
|
|
@@ -135,12 +202,17 @@
|
|
|
135
202
|
"type": "string",
|
|
136
203
|
"description": "Public key contents (safe to inline). Private key never in plan"
|
|
137
204
|
},
|
|
138
|
-
"user": {
|
|
205
|
+
"user": {
|
|
206
|
+
"type": "string",
|
|
207
|
+
"default": "ubuntu"
|
|
208
|
+
}
|
|
139
209
|
}
|
|
140
210
|
},
|
|
141
211
|
"tags": {
|
|
142
212
|
"type": "object",
|
|
143
|
-
"additionalProperties": {
|
|
213
|
+
"additionalProperties": {
|
|
214
|
+
"type": "string"
|
|
215
|
+
},
|
|
144
216
|
"description": "Cloud-resource tags propagated to all created resources"
|
|
145
217
|
}
|
|
146
218
|
}
|
|
@@ -151,15 +223,23 @@
|
|
|
151
223
|
"properties": {
|
|
152
224
|
"create": {
|
|
153
225
|
"type": "array",
|
|
154
|
-
"items": {
|
|
226
|
+
"items": {
|
|
227
|
+
"$ref": "#/$defs/ResourceRef"
|
|
228
|
+
}
|
|
155
229
|
},
|
|
156
230
|
"update": {
|
|
157
231
|
"type": "array",
|
|
158
232
|
"items": {
|
|
159
233
|
"type": "object",
|
|
160
|
-
"required": [
|
|
234
|
+
"required": [
|
|
235
|
+
"resource",
|
|
236
|
+
"before",
|
|
237
|
+
"after"
|
|
238
|
+
],
|
|
161
239
|
"properties": {
|
|
162
|
-
"resource": {
|
|
240
|
+
"resource": {
|
|
241
|
+
"$ref": "#/$defs/ResourceRef"
|
|
242
|
+
},
|
|
163
243
|
"before": {},
|
|
164
244
|
"after": {}
|
|
165
245
|
}
|
|
@@ -167,16 +247,23 @@
|
|
|
167
247
|
},
|
|
168
248
|
"delete": {
|
|
169
249
|
"type": "array",
|
|
170
|
-
"items": {
|
|
250
|
+
"items": {
|
|
251
|
+
"$ref": "#/$defs/ResourceRef"
|
|
252
|
+
}
|
|
171
253
|
},
|
|
172
|
-
"totalChanges": {
|
|
254
|
+
"totalChanges": {
|
|
255
|
+
"type": "integer"
|
|
256
|
+
}
|
|
173
257
|
}
|
|
174
258
|
}
|
|
175
259
|
},
|
|
176
260
|
"$defs": {
|
|
177
261
|
"ResourceRef": {
|
|
178
262
|
"type": "object",
|
|
179
|
-
"required": [
|
|
263
|
+
"required": [
|
|
264
|
+
"urn",
|
|
265
|
+
"type"
|
|
266
|
+
],
|
|
180
267
|
"properties": {
|
|
181
268
|
"urn": {
|
|
182
269
|
"type": "string",
|
|
@@ -186,7 +273,9 @@
|
|
|
186
273
|
"type": "string",
|
|
187
274
|
"description": "Pulumi resource type token"
|
|
188
275
|
},
|
|
189
|
-
"name": {
|
|
276
|
+
"name": {
|
|
277
|
+
"type": "string"
|
|
278
|
+
}
|
|
190
279
|
}
|
|
191
280
|
}
|
|
192
281
|
}
|
package/spec/integrations.yaml
CHANGED
|
@@ -1,9 +1,44 @@
|
|
|
1
1
|
# spec/integrations.yaml — OpenClaw channel integration catalog for the setup wizard.
|
|
2
2
|
# Read at runtime by src/cli/commands/setup.ts — not compiled or code-generated.
|
|
3
3
|
#
|
|
4
|
-
# Each integration maps to a key in
|
|
4
|
+
# Each integration maps to a key in the `channels` object of OpenClaw's config.
|
|
5
5
|
# infraRequired: true means a publicly reachable webhook URL must be registered
|
|
6
6
|
# with the provider after the stack is deployed.
|
|
7
|
+
#
|
|
8
|
+
# ── Checked against OpenClaw 2026.9.2 (WO-60) ────────────────────────────────
|
|
9
|
+
#
|
|
10
|
+
# EVERY channel in 2.0 is an install-gated plugin. `openclaw channels list --all --json`
|
|
11
|
+
# reports all 31 as `origin: "installable"`, and none is bundled — the same shape as model
|
|
12
|
+
# providers (WO-43), which is why `plugin:` below carries the package to install.
|
|
13
|
+
#
|
|
14
|
+
# Configuring a channel without installing it produces a gateway that starts, reports
|
|
15
|
+
# healthy, and never connects to the channel.
|
|
16
|
+
#
|
|
17
|
+
# `dmPolicy` and `groupPolicy` are REQUIRED by the schema on every channel here, and Slack
|
|
18
|
+
# and WhatsApp require more. `defaults:` carries OpenClaw's own default for each of them, and
|
|
19
|
+
# the wizard writes them — a JSON Schema default does not satisfy `required`, so a config
|
|
20
|
+
# omitting them is REJECTED. Every channel the wizard wrote was invalid before this.
|
|
21
|
+
#
|
|
22
|
+
# Every credential field also accepts a SecretRef — `{source: env, provider, id}` — as well
|
|
23
|
+
# as a plain string, so a token need not be inlined into the config.
|
|
24
|
+
#
|
|
25
|
+
# The catalog was wrong in four ways before this pass, all of which would have produced a
|
|
26
|
+
# config OpenClaw rejects or ignores: the Teams key was `teams` (the schema has `msteams`),
|
|
27
|
+
# Discord's token field was `botToken` (it is `token`), WhatsApp's `phoneNumberId` and
|
|
28
|
+
# `accessToken` do not exist on that channel at all, and EVERY `envDefault` used an
|
|
29
|
+
# `OPENCLAW_*` name that OpenClaw does not read.
|
|
30
|
+
#
|
|
31
|
+
# `envVar` below is the variable `openclaw channels add --use-env` actually reads, taken from
|
|
32
|
+
# the binary's own error message. `useEnvSupported: false` means that flag is rejected for the
|
|
33
|
+
# channel outright — measured, not assumed.
|
|
34
|
+
#
|
|
35
|
+
# `plugin.version` is pinned to the runtime floor, and it is not decoration. Measured on
|
|
36
|
+
# 2026.9.2: `@openclaw/discord@2026.9.3` refuses to install with
|
|
37
|
+
#
|
|
38
|
+
# plugin "discord" requires plugin API >=2026.9.3, but this OpenClaw runtime exposes 2026.9.2
|
|
39
|
+
#
|
|
40
|
+
# The same drift that forced version pins on model providers in WO-43. `latest` would break
|
|
41
|
+
# the deploy the moment upstream publishes ahead of the runtime, which it already has.
|
|
7
42
|
|
|
8
43
|
integrations:
|
|
9
44
|
- id: discord
|
|
@@ -11,12 +46,21 @@ integrations:
|
|
|
11
46
|
displayName: Discord
|
|
12
47
|
description: Connect OpenClaw agents to a Discord server via bot
|
|
13
48
|
infraRequired: false
|
|
49
|
+
plugin:
|
|
50
|
+
package: "@openclaw/discord"
|
|
51
|
+
source: npm
|
|
52
|
+
version: "2026.9.2"
|
|
53
|
+
useEnvSupported: true
|
|
54
|
+
requiredConfig: [dmPolicy, groupPolicy]
|
|
55
|
+
defaults:
|
|
56
|
+
dmPolicy: pairing
|
|
57
|
+
groupPolicy: allowlist
|
|
14
58
|
fields:
|
|
15
|
-
- name:
|
|
59
|
+
- name: token
|
|
16
60
|
label: Bot token
|
|
17
61
|
description: Bot token from the Discord Developer Portal (Bot → Token)
|
|
18
62
|
sensitive: true
|
|
19
|
-
envDefault:
|
|
63
|
+
envDefault: DISCORD_BOT_TOKEN
|
|
20
64
|
setupUrl: https://discord.com/developers/applications
|
|
21
65
|
|
|
22
66
|
- id: telegram
|
|
@@ -24,33 +68,69 @@ integrations:
|
|
|
24
68
|
displayName: Telegram
|
|
25
69
|
description: Connect OpenClaw agents to a Telegram bot
|
|
26
70
|
infraRequired: false
|
|
71
|
+
# Bundled in the image: `channels add --channel telegram --use-env` succeeds with
|
|
72
|
+
# `--network none`, so there is nothing to download and no egress needed. It is listed
|
|
73
|
+
# as "installable" alongside the rest, which is why this looked unresolved at first.
|
|
74
|
+
plugin:
|
|
75
|
+
package: ""
|
|
76
|
+
source: bundled
|
|
77
|
+
useEnvSupported: true
|
|
78
|
+
requiredConfig: [dmPolicy, groupPolicy]
|
|
79
|
+
defaults:
|
|
80
|
+
dmPolicy: pairing
|
|
81
|
+
groupPolicy: allowlist
|
|
27
82
|
fields:
|
|
28
83
|
- name: botToken
|
|
29
84
|
label: Bot token
|
|
30
85
|
description: Token from @BotFather (/newbot)
|
|
31
86
|
sensitive: true
|
|
32
|
-
envDefault:
|
|
87
|
+
envDefault: TELEGRAM_BOT_TOKEN
|
|
33
88
|
setupUrl: https://t.me/BotFather
|
|
34
89
|
|
|
35
90
|
- id: slack
|
|
36
91
|
channelKey: slack
|
|
37
92
|
displayName: Slack
|
|
38
|
-
description: Connect OpenClaw agents to a Slack workspace via app
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
93
|
+
description: Connect OpenClaw agents to a Slack workspace via app (Socket Mode)
|
|
94
|
+
# Socket Mode, not a webhook. `mode` defaults to "socket" in OpenClaw and it is what
|
|
95
|
+
# `channels add --use-env` drives: the gateway opens an OUTBOUND WebSocket to Slack, so
|
|
96
|
+
# there is no public URL to register and no inbound rule to open.
|
|
97
|
+
#
|
|
98
|
+
# This entry said infraRequired: true — the `http` mode setup — while declaring the
|
|
99
|
+
# socket credentials incompletely. It described one setup while the tooling installed
|
|
100
|
+
# the other, and the config it produced failed validation either way.
|
|
101
|
+
#
|
|
102
|
+
# `mode: http` is still available: it needs a public webhook at `webhookPath` and a
|
|
103
|
+
# signingSecret to verify inbound requests. That is a deliberate choice, not the default,
|
|
104
|
+
# and clawops does not configure it.
|
|
105
|
+
infraRequired: false
|
|
106
|
+
plugin:
|
|
107
|
+
package: "@openclaw/slack"
|
|
108
|
+
source: npm
|
|
109
|
+
version: "2026.9.2"
|
|
110
|
+
# Socket Mode is what --use-env drives, and it demands SLACK_APP_TOKEN:
|
|
111
|
+
# "Slack Socket Mode requires SLACK_APP_TOKEN when using --use-env."
|
|
112
|
+
useEnvSupported: true
|
|
113
|
+
# Slack requires more than the two policies: the schema also demands postAs, mode,
|
|
114
|
+
# webhookPath and userTokenReadOnly.
|
|
115
|
+
requiredConfig: [dmPolicy, groupPolicy, postAs, mode, webhookPath, userTokenReadOnly]
|
|
116
|
+
defaults:
|
|
117
|
+
dmPolicy: pairing
|
|
118
|
+
groupPolicy: allowlist
|
|
119
|
+
postAs: bot
|
|
120
|
+
mode: socket
|
|
121
|
+
webhookPath: /slack/events
|
|
122
|
+
userTokenReadOnly: true
|
|
43
123
|
fields:
|
|
44
124
|
- name: botToken
|
|
45
125
|
label: Bot OAuth token
|
|
46
126
|
description: "Bot User OAuth Token (starts with xoxb-)"
|
|
47
127
|
sensitive: true
|
|
48
|
-
envDefault:
|
|
49
|
-
- name:
|
|
50
|
-
label:
|
|
51
|
-
description: App
|
|
128
|
+
envDefault: SLACK_BOT_TOKEN
|
|
129
|
+
- name: appToken
|
|
130
|
+
label: App-level token
|
|
131
|
+
description: "App-level token for Socket Mode (starts with xapp-), from Basic Information → App-Level Tokens"
|
|
52
132
|
sensitive: true
|
|
53
|
-
envDefault:
|
|
133
|
+
envDefault: SLACK_APP_TOKEN
|
|
54
134
|
setupUrl: https://api.slack.com/apps
|
|
55
135
|
|
|
56
136
|
- id: whatsapp
|
|
@@ -62,27 +142,49 @@ integrations:
|
|
|
62
142
|
After deployment, register the gateway webhook URL in the Meta Developer
|
|
63
143
|
Console (WhatsApp → Configuration → Webhook). The gateway URL is printed
|
|
64
144
|
at the end of setup.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
145
|
+
plugin:
|
|
146
|
+
package: "@openclaw/whatsapp"
|
|
147
|
+
source: npm
|
|
148
|
+
version: "2026.9.2"
|
|
149
|
+
# `openclaw channels add --use-env` answers: OpenClaw does not recognize option
|
|
150
|
+
# "--use-env". There is no non-interactive path for this channel.
|
|
151
|
+
useEnvSupported: false
|
|
152
|
+
requiredConfig: [dmPolicy, groupPolicy, mediaMaxMb]
|
|
153
|
+
defaults:
|
|
154
|
+
dmPolicy: pairing
|
|
155
|
+
groupPolicy: allowlist
|
|
156
|
+
mediaMaxMb: 50
|
|
157
|
+
# WhatsApp has no top-level credential fields in 2.0 — credentials live under
|
|
158
|
+
# `accounts.<name>`, with `defaultAccount` selecting one. The wizard cannot collect a
|
|
159
|
+
# flat token for it, so it is marked unsupported rather than collecting fields that go
|
|
160
|
+
# nowhere. `phoneNumberId` and `accessToken`, which this entry used to declare, are not
|
|
161
|
+
# properties of the whatsapp channel at all.
|
|
162
|
+
wizardSupported: false
|
|
163
|
+
unsupportedNote: >
|
|
164
|
+
WhatsApp uses per-account credentials (`channels.whatsapp.accounts.<name>`) rather
|
|
165
|
+
than a single token. Configure it with `openclaw channels add --channel whatsapp`
|
|
166
|
+
on the host after deployment.
|
|
167
|
+
fields: []
|
|
76
168
|
setupUrl: https://developers.facebook.com/apps
|
|
77
169
|
|
|
78
|
-
- id:
|
|
79
|
-
channelKey:
|
|
170
|
+
- id: msteams
|
|
171
|
+
channelKey: msteams
|
|
80
172
|
displayName: Microsoft Teams
|
|
81
173
|
description: Connect OpenClaw agents to a Microsoft Teams channel via bot
|
|
82
174
|
infraRequired: true
|
|
83
175
|
infraNote: >
|
|
84
176
|
After deployment, update the bot's messaging endpoint in Azure Bot Service
|
|
85
177
|
to the gateway webhook URL.
|
|
178
|
+
plugin:
|
|
179
|
+
package: "@openclaw/msteams"
|
|
180
|
+
source: npm
|
|
181
|
+
version: "2026.9.2"
|
|
182
|
+
# Same as WhatsApp: --use-env is rejected outright.
|
|
183
|
+
useEnvSupported: false
|
|
184
|
+
requiredConfig: [dmPolicy, groupPolicy]
|
|
185
|
+
defaults:
|
|
186
|
+
dmPolicy: pairing
|
|
187
|
+
groupPolicy: allowlist
|
|
86
188
|
fields:
|
|
87
189
|
- name: appId
|
|
88
190
|
label: App (client) ID
|
|
@@ -93,5 +195,10 @@ integrations:
|
|
|
93
195
|
label: App password
|
|
94
196
|
description: Client secret from the Azure app registration
|
|
95
197
|
sensitive: true
|
|
96
|
-
envDefault:
|
|
198
|
+
envDefault: "" # no --use-env path; collected interactively on the host
|
|
199
|
+
- name: tenantId
|
|
200
|
+
label: Directory (tenant) ID
|
|
201
|
+
description: Azure AD tenant ID for the app registration
|
|
202
|
+
sensitive: false
|
|
203
|
+
envDefault: ""
|
|
97
204
|
setupUrl: https://portal.azure.com/
|