@clawops/cli 1.7.9 → 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-GZN7PKP4.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-A4QR4TXW.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-OAGYT3VH.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-7E5JQY47.js → mcp-wire-BFEY2Y6H.js} +23 -17
- package/dist/{package-5AR4ZPK4.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-FIZCOLHL.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,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
compareVersions
|
|
4
|
+
} from "./chunk-GAZPPSKU.js";
|
|
5
|
+
import "./chunk-JW5A7E3X.js";
|
|
6
|
+
import "./chunk-EI7CQQ7D.js";
|
|
7
|
+
|
|
8
|
+
// src/openclaw/config-validate.ts
|
|
9
|
+
var cached;
|
|
10
|
+
async function getValidator() {
|
|
11
|
+
if (cached) return cached;
|
|
12
|
+
const [{ default: Ajv }, { default: addFormats }, { readFileSync }, { join }, { resolveSpecDir }] = await Promise.all([
|
|
13
|
+
import("ajv"),
|
|
14
|
+
import("ajv-formats"),
|
|
15
|
+
import("fs"),
|
|
16
|
+
import("path"),
|
|
17
|
+
import("./spec-path-KQOOIQCA.js")
|
|
18
|
+
]);
|
|
19
|
+
const schema = JSON.parse(
|
|
20
|
+
readFileSync(join(resolveSpecDir(), "openclaw-2.0.config.schema.json"), "utf-8")
|
|
21
|
+
);
|
|
22
|
+
const ajv = new Ajv({ strict: false, allErrors: true });
|
|
23
|
+
addFormats(ajv);
|
|
24
|
+
cached = ajv.compile(schema);
|
|
25
|
+
return cached;
|
|
26
|
+
}
|
|
27
|
+
function isUnknownKey(e) {
|
|
28
|
+
return e.keyword === "additionalProperties";
|
|
29
|
+
}
|
|
30
|
+
function dotPath(instancePath) {
|
|
31
|
+
if (!instancePath) return "(root)";
|
|
32
|
+
return instancePath.slice(1).split("/").map((seg) => seg.replace(/~1/g, "/").replace(/~0/g, "~")).join(".");
|
|
33
|
+
}
|
|
34
|
+
function describe(e) {
|
|
35
|
+
const where = dotPath(e.instancePath);
|
|
36
|
+
if (isUnknownKey(e)) {
|
|
37
|
+
const extra = e.params.additionalProperty;
|
|
38
|
+
return `${where}: unknown key "${extra}"`;
|
|
39
|
+
}
|
|
40
|
+
return `${where}: ${e.message ?? "invalid"}`;
|
|
41
|
+
}
|
|
42
|
+
function deploymentContractErrors(cfg) {
|
|
43
|
+
const errors = [];
|
|
44
|
+
if (cfg === null || typeof cfg !== "object") return errors;
|
|
45
|
+
const gateway = cfg["gateway"];
|
|
46
|
+
const mode = gateway !== null && typeof gateway === "object" ? gateway["mode"] : void 0;
|
|
47
|
+
if (mode === void 0) {
|
|
48
|
+
errors.push(
|
|
49
|
+
'gateway.mode: required by clawops. OpenClaw treats it as optional only because --allow-unconfigured can bypass the check; clawops does not pass that flag, so a config without gateway.mode exits 78 with "Gateway start blocked". Set it to "local".'
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return errors;
|
|
53
|
+
}
|
|
54
|
+
async function validateConfig(cfg, opts = {}) {
|
|
55
|
+
const validate = await getValidator();
|
|
56
|
+
const contract = deploymentContractErrors(cfg);
|
|
57
|
+
if (validate(cfg)) return { errors: contract, warnings: [] };
|
|
58
|
+
const { openclawVersion, schemaCapturedFrom } = opts;
|
|
59
|
+
const runtimeIsNewer = openclawVersion !== void 0 && schemaCapturedFrom !== void 0 && compareVersions(openclawVersion, schemaCapturedFrom) > 0;
|
|
60
|
+
const errors = [...contract];
|
|
61
|
+
const warnings = [];
|
|
62
|
+
for (const e of validate.errors ?? []) {
|
|
63
|
+
const text = describe(e);
|
|
64
|
+
if (isUnknownKey(e) && runtimeIsNewer) {
|
|
65
|
+
warnings.push(
|
|
66
|
+
`${text} \u2014 not in the schema captured from OpenClaw ${schemaCapturedFrom}; you are deploying ${openclawVersion}, so this may be a newer setting clawops does not know about yet.`
|
|
67
|
+
);
|
|
68
|
+
} else {
|
|
69
|
+
errors.push(text);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return { errors, warnings };
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
validateConfig
|
|
76
|
+
};
|
|
@@ -45,7 +45,17 @@ async function detectEgressIp(checkUrl) {
|
|
|
45
45
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
+
function resolveGatewayIngressCidrs(publishGateway, accessMode, allowedCidrs, portOverride, egressResult) {
|
|
49
|
+
if (publishGateway !== "all") return [];
|
|
50
|
+
return resolveIngressCidrs(accessMode, allowedCidrs, portOverride, egressResult);
|
|
51
|
+
}
|
|
52
|
+
function resolveGatewayPort(raw, fallback) {
|
|
53
|
+
const port = Number(raw);
|
|
54
|
+
return Number.isInteger(port) && port > 0 && port < 65536 ? port : fallback;
|
|
55
|
+
}
|
|
48
56
|
export {
|
|
49
57
|
detectEgressIp,
|
|
58
|
+
resolveGatewayIngressCidrs,
|
|
59
|
+
resolveGatewayPort,
|
|
50
60
|
resolveIngressCidrs
|
|
51
61
|
};
|
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
makeStartupScript
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CKSPROD5.js";
|
|
5
|
+
import {
|
|
6
|
+
GATEWAY_PORT
|
|
7
|
+
} from "./chunk-6TIYVHPX.js";
|
|
8
|
+
import "./chunk-EI7CQQ7D.js";
|
|
5
9
|
|
|
6
10
|
// src/providers/gcp/index.ts
|
|
7
11
|
import process2 from "process";
|
|
8
12
|
|
|
9
13
|
// src/providers/gcp/program.ts
|
|
10
|
-
var GATEWAY_PORT = 18789;
|
|
11
14
|
var SSH_PORT = 22;
|
|
12
15
|
var gcpProgram = async () => {
|
|
13
|
-
const [pulumi, gcp, { resolveIngressCidrs, detectEgressIp }] = await Promise.all([
|
|
16
|
+
const [pulumi, gcp, { resolveIngressCidrs, resolveGatewayIngressCidrs, resolveGatewayPort, detectEgressIp }] = await Promise.all([
|
|
14
17
|
import("@pulumi/pulumi"),
|
|
15
18
|
import("@pulumi/gcp"),
|
|
16
|
-
import("./firewall-
|
|
19
|
+
import("./firewall-T3NTPZJD.js")
|
|
17
20
|
]);
|
|
18
21
|
const cfg = new pulumi.Config();
|
|
19
22
|
const instanceType = cfg.get("instanceType") ?? "e2-standard-2";
|
|
20
23
|
const region = cfg.get("region") ?? "us-central1";
|
|
21
24
|
const openclawVersion = cfg.get("openclawVersion") ?? "latest";
|
|
25
|
+
const publishGateway = cfg.get("publishGateway") === "all" ? "all" : "loopback";
|
|
26
|
+
const gatewayPort = resolveGatewayPort(cfg.get("gatewayPort"), GATEWAY_PORT);
|
|
22
27
|
const zone = cfg.get("zone") ?? `${region}-a`;
|
|
23
28
|
const accessMode = cfg.get("accessMode") ?? "restricted";
|
|
24
29
|
const allowedCidrs = cfg.get("allowedCidrs") ?? "";
|
|
@@ -37,7 +42,13 @@ var gcpProgram = async () => {
|
|
|
37
42
|
);
|
|
38
43
|
}
|
|
39
44
|
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs, egressResult);
|
|
40
|
-
const gatewayIngressCidrs =
|
|
45
|
+
const gatewayIngressCidrs = resolveGatewayIngressCidrs(
|
|
46
|
+
publishGateway,
|
|
47
|
+
accessMode,
|
|
48
|
+
allowedCidrs,
|
|
49
|
+
gatewayCidrs,
|
|
50
|
+
egressResult
|
|
51
|
+
);
|
|
41
52
|
const network = new gcp.compute.Network("clawops-network", {
|
|
42
53
|
autoCreateSubnetworks: false,
|
|
43
54
|
description: "clawops managed network"
|
|
@@ -58,7 +69,7 @@ var gcpProgram = async () => {
|
|
|
58
69
|
if (gatewayIngressCidrs.length > 0) {
|
|
59
70
|
new gcp.compute.Firewall("clawops-firewall-gateway", {
|
|
60
71
|
network: network.selfLink,
|
|
61
|
-
allows: [{ protocol: "tcp", ports: [String(
|
|
72
|
+
allows: [{ protocol: "tcp", ports: [String(gatewayPort)] }],
|
|
62
73
|
sourceRanges: gatewayIngressCidrs,
|
|
63
74
|
targetTags: ["clawops"]
|
|
64
75
|
});
|
|
@@ -89,7 +100,7 @@ var gcpProgram = async () => {
|
|
|
89
100
|
metadata: {
|
|
90
101
|
// GCP guest agent reads 'ssh-keys' and populates /home/<user>/.ssh/authorized_keys
|
|
91
102
|
"ssh-keys": `clawops:${sshPublicKey}`,
|
|
92
|
-
"startup-script": makeStartupScript({ openclawVersion, os: "debian" })
|
|
103
|
+
"startup-script": makeStartupScript({ openclawVersion, os: "debian", publishGateway, gatewayPort })
|
|
93
104
|
},
|
|
94
105
|
serviceAccount: {
|
|
95
106
|
scopes: ["https://www.googleapis.com/auth/cloud-platform"]
|
|
@@ -98,7 +109,7 @@ var gcpProgram = async () => {
|
|
|
98
109
|
return {
|
|
99
110
|
instanceId: instance.id,
|
|
100
111
|
publicIp: address.address,
|
|
101
|
-
gatewayUrl: pulumi.interpolate`https://${address.address}:${
|
|
112
|
+
gatewayUrl: pulumi.interpolate`https://${address.address}:${gatewayPort}`,
|
|
102
113
|
sshHost: address.address,
|
|
103
114
|
sshPort: SSH_PORT,
|
|
104
115
|
sshUser: "clawops",
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
generatePlan,
|
|
4
4
|
planId
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-WHJMKDV7.js";
|
|
6
|
+
import "./chunk-YR3O2I3S.js";
|
|
7
|
+
import "./chunk-LU2V3LXA.js";
|
|
8
|
+
import "./chunk-JW5A7E3X.js";
|
|
9
9
|
import "./chunk-A2I76FTA.js";
|
|
10
10
|
import "./chunk-CX5SL5HP.js";
|
|
11
11
|
import "./chunk-KGXPLI7W.js";
|
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
acquireSession,
|
|
4
4
|
drainPool
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-3WYA2QDM.js";
|
|
6
|
+
import "./chunk-AHAAEXWC.js";
|
|
7
7
|
import "./chunk-KGXPLI7W.js";
|
|
8
|
+
import {
|
|
9
|
+
GATEWAY_PORT,
|
|
10
|
+
PUBLISH_INSPECT_CMD,
|
|
11
|
+
publishForRestart,
|
|
12
|
+
publishedGatewayPort
|
|
13
|
+
} from "./chunk-6TIYVHPX.js";
|
|
14
|
+
import "./chunk-EI7CQQ7D.js";
|
|
8
15
|
|
|
9
16
|
// src/harden/types.ts
|
|
10
17
|
var SENTINEL_DIR = "/etc/clawops/hardening";
|
|
@@ -154,7 +161,11 @@ var sshModule = {
|
|
|
154
161
|
|
|
155
162
|
// src/harden/modules/ufw.ts
|
|
156
163
|
var SENTINEL2 = `${SENTINEL_DIR}/ufw.applied`;
|
|
157
|
-
|
|
164
|
+
async function publishedGateway(exec) {
|
|
165
|
+
const { stdout } = await exec(`${PUBLISH_INSPECT_CMD} 2>/dev/null || true`);
|
|
166
|
+
if (publishForRestart(stdout) !== "all") return { exposed: false };
|
|
167
|
+
return { exposed: true, port: publishedGatewayPort(stdout) };
|
|
168
|
+
}
|
|
158
169
|
function makeUfwModule(sshPort = 22) {
|
|
159
170
|
return {
|
|
160
171
|
id: "ufw",
|
|
@@ -176,14 +187,24 @@ function makeUfwModule(sshPort = 22) {
|
|
|
176
187
|
return { status: "missing", detail: "UFW installed but not active" };
|
|
177
188
|
},
|
|
178
189
|
async apply(exec) {
|
|
190
|
+
const gateway = await publishedGateway(exec);
|
|
191
|
+
const rules = [`ufw allow ${sshPort}/tcp comment "clawops SSH"`];
|
|
192
|
+
let gatewayNote;
|
|
193
|
+
if (!gateway.exposed) {
|
|
194
|
+
gatewayNote = "gateway port not opened (published on 127.0.0.1 \u2014 reach it with `clawops tunnel`)";
|
|
195
|
+
} else if (gateway.port === void 0) {
|
|
196
|
+
gatewayNote = "gateway published on every interface but its port could not be read \u2014 no rule added; run `clawops doctor --stack <name>` and open it yourself if that is intended";
|
|
197
|
+
} else {
|
|
198
|
+
rules.push(`ufw allow ${gateway.port}/tcp comment "OpenClaw gateway"`);
|
|
199
|
+
gatewayNote = `allow ${gateway.port}/tcp`;
|
|
200
|
+
}
|
|
179
201
|
const script = [
|
|
180
202
|
`mkdir -p ${SENTINEL_DIR}`,
|
|
181
203
|
"apt-get install -y -q ufw",
|
|
182
204
|
"ufw --force reset",
|
|
183
205
|
"ufw default deny incoming",
|
|
184
206
|
"ufw default allow outgoing",
|
|
185
|
-
|
|
186
|
-
`ufw allow ${GATEWAY_PORT}/tcp comment "OpenClaw gateway"`,
|
|
207
|
+
...rules,
|
|
187
208
|
"ufw --force enable",
|
|
188
209
|
`touch ${SENTINEL2}`
|
|
189
210
|
].join(" && ");
|
|
@@ -191,7 +212,10 @@ function makeUfwModule(sshPort = 22) {
|
|
|
191
212
|
if (code !== 0) {
|
|
192
213
|
throw new Error(`UFW setup failed (exit ${code}): ${stderr.slice(0, 200)}`);
|
|
193
214
|
}
|
|
194
|
-
return {
|
|
215
|
+
return {
|
|
216
|
+
changed: true,
|
|
217
|
+
detail: `UFW enabled: deny-all in, allow ${sshPort}/tcp; ${gatewayNote}`
|
|
218
|
+
};
|
|
195
219
|
}
|
|
196
220
|
};
|
|
197
221
|
}
|
|
@@ -473,7 +497,14 @@ var sysctlModule = {
|
|
|
473
497
|
};
|
|
474
498
|
|
|
475
499
|
// src/harden/modules/aws-sg-audit.ts
|
|
476
|
-
var
|
|
500
|
+
var WORLD = /* @__PURE__ */ new Set(["0.0.0.0/0"]);
|
|
501
|
+
var WORLD_V6 = /* @__PURE__ */ new Set(["::/0"]);
|
|
502
|
+
var NAMED_PORTS = { 22: "SSH", [GATEWAY_PORT]: "the OpenClaw gateway" };
|
|
503
|
+
function describe(fromPort, toPort) {
|
|
504
|
+
const range = fromPort === toPort ? `port ${fromPort}` : `ports ${fromPort}-${toPort}`;
|
|
505
|
+
const named = NAMED_PORTS[fromPort];
|
|
506
|
+
return named && fromPort === toPort ? `${range} (${named})` : range;
|
|
507
|
+
}
|
|
477
508
|
var awsSgAuditModule = {
|
|
478
509
|
id: "aws-sg-audit",
|
|
479
510
|
label: "AWS SG audit (check-only)",
|
|
@@ -492,19 +523,25 @@ var awsSgAuditModule = {
|
|
|
492
523
|
for (const rule of sg.IpPermissions ?? []) {
|
|
493
524
|
const fromPort = rule.FromPort ?? 0;
|
|
494
525
|
const toPort = rule.ToPort ?? 65535;
|
|
526
|
+
const where = describe(fromPort, toPort);
|
|
495
527
|
for (const range of rule.IpRanges ?? []) {
|
|
496
|
-
if (range.CidrIp
|
|
497
|
-
openRules.push(
|
|
528
|
+
if (range.CidrIp && WORLD.has(range.CidrIp)) {
|
|
529
|
+
openRules.push(`${where} open to ${range.CidrIp} in ${sg.GroupId}`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
for (const range of rule.Ipv6Ranges ?? []) {
|
|
533
|
+
if (range.CidrIpv6 && WORLD_V6.has(range.CidrIpv6)) {
|
|
534
|
+
openRules.push(`${where} open to ${range.CidrIpv6} in ${sg.GroupId}`);
|
|
498
535
|
}
|
|
499
536
|
}
|
|
500
537
|
}
|
|
501
538
|
}
|
|
502
539
|
if (openRules.length === 0) {
|
|
503
|
-
return { status: "applied", detail: "No
|
|
540
|
+
return { status: "applied", detail: "No ingress rule admits the whole internet" };
|
|
504
541
|
}
|
|
505
542
|
return {
|
|
506
543
|
status: "drifted",
|
|
507
|
-
detail: `
|
|
544
|
+
detail: `Ingress open to the internet: ${openRules.join("; ")}`
|
|
508
545
|
};
|
|
509
546
|
} catch (err) {
|
|
510
547
|
return {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
GATEWAY_LOGS_PROBE,
|
|
4
|
+
agentAuditCommand,
|
|
5
|
+
chooseLogSource,
|
|
6
|
+
containerLogsCommand,
|
|
7
|
+
gatewayLogsCommand
|
|
8
|
+
} from "./chunk-SBLQH2TJ.js";
|
|
9
|
+
export {
|
|
10
|
+
GATEWAY_LOGS_PROBE,
|
|
11
|
+
agentAuditCommand,
|
|
12
|
+
chooseLogSource,
|
|
13
|
+
containerLogsCommand,
|
|
14
|
+
gatewayLogsCommand
|
|
15
|
+
};
|
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
MCP_HTTP_PORT
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-AX74VXTV.js";
|
|
5
|
+
import "./chunk-UFRO4H5W.js";
|
|
6
|
+
import "./chunk-N44K3LHE.js";
|
|
7
|
+
import "./chunk-3QJBNAHW.js";
|
|
8
|
+
import "./chunk-WHJMKDV7.js";
|
|
9
|
+
import "./chunk-YR3O2I3S.js";
|
|
6
10
|
import "./chunk-6ZFIFDBJ.js";
|
|
11
|
+
import "./chunk-3WYA2QDM.js";
|
|
12
|
+
import "./chunk-AHAAEXWC.js";
|
|
7
13
|
import "./chunk-BOPSG2LI.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-PVUVI35Y.js";
|
|
17
|
-
import "./chunk-3XK66DKK.js";
|
|
14
|
+
import "./chunk-LU2V3LXA.js";
|
|
15
|
+
import "./chunk-GYV4KNW7.js";
|
|
16
|
+
import "./chunk-SBLQH2TJ.js";
|
|
17
|
+
import "./chunk-LT4XMO5D.js";
|
|
18
|
+
import {
|
|
19
|
+
execPrivileged
|
|
20
|
+
} from "./chunk-NUDIHZEH.js";
|
|
21
|
+
import "./chunk-JW5A7E3X.js";
|
|
18
22
|
import "./chunk-Q7NQY5HV.js";
|
|
19
23
|
import "./chunk-A2I76FTA.js";
|
|
20
24
|
import "./chunk-CX5SL5HP.js";
|
|
21
25
|
import "./chunk-KGXPLI7W.js";
|
|
26
|
+
import "./chunk-6TIYVHPX.js";
|
|
27
|
+
import "./chunk-EI7CQQ7D.js";
|
|
22
28
|
|
|
23
29
|
// src/cli/mcp-wire.ts
|
|
24
30
|
var GATEWAY_MCP_NAME = "clawops";
|
|
@@ -30,17 +36,17 @@ function shellQuote(value) {
|
|
|
30
36
|
}
|
|
31
37
|
var OC = "docker exec openclaw openclaw mcp";
|
|
32
38
|
async function supportsMcpAdd(session, signal) {
|
|
33
|
-
const help = await session
|
|
39
|
+
const help = await execPrivileged(session, `${OC} add --help`, signal);
|
|
34
40
|
return help.code === 0;
|
|
35
41
|
}
|
|
36
42
|
async function wireGatewayMcp(session, signal, opts = {}) {
|
|
37
43
|
const url = opts.url ?? defaultGatewayMcpUrl();
|
|
38
44
|
if (!await supportsMcpAdd(session, signal)) return { status: "unsupported", url };
|
|
39
|
-
const existing = await session
|
|
45
|
+
const existing = await execPrivileged(session, `${OC} show ${GATEWAY_MCP_NAME}`, signal);
|
|
40
46
|
const alreadyWired = existing.code === 0;
|
|
41
47
|
if (alreadyWired && !opts.rewire) return { status: "exists", url };
|
|
42
48
|
if (alreadyWired) {
|
|
43
|
-
const removed = await session
|
|
49
|
+
const removed = await execPrivileged(session, `${OC} unset ${GATEWAY_MCP_NAME}`, signal);
|
|
44
50
|
if (removed.code !== 0) {
|
|
45
51
|
return {
|
|
46
52
|
status: "probe-failed",
|
|
@@ -54,7 +60,7 @@ async function wireGatewayMcp(session, signal, opts = {}) {
|
|
|
54
60
|
`--url ${shellQuote(url)}`,
|
|
55
61
|
...opts.token ? [`--header ${shellQuote(`Authorization=Bearer ${opts.token}`)}`] : []
|
|
56
62
|
].join(" ");
|
|
57
|
-
const added = await session
|
|
63
|
+
const added = await execPrivileged(session, `${OC} add ${GATEWAY_MCP_NAME} ${flags}`, signal);
|
|
58
64
|
if (added.code !== 0) {
|
|
59
65
|
return {
|
|
60
66
|
status: "probe-failed",
|
|
@@ -62,7 +68,7 @@ async function wireGatewayMcp(session, signal, opts = {}) {
|
|
|
62
68
|
url
|
|
63
69
|
};
|
|
64
70
|
}
|
|
65
|
-
await session
|
|
71
|
+
await execPrivileged(session, `${OC} reload`, signal);
|
|
66
72
|
return { status: "wired", rewired: alreadyWired, url };
|
|
67
73
|
}
|
|
68
74
|
export {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// package.json
|
|
4
4
|
var name = "@clawops/cli";
|
|
5
|
-
var version = "
|
|
5
|
+
var version = "2.0.0";
|
|
6
6
|
var description = "Deploy and manage self-hosted OpenClaw instances across clouds";
|
|
7
7
|
var type = "module";
|
|
8
8
|
var bin = {
|
|
@@ -35,13 +35,13 @@ var scripts = {
|
|
|
35
35
|
test: "vitest run",
|
|
36
36
|
"test:pulumi": "vitest run tests/providers/aws/program.test.ts tests/providers/azure/program.test.ts",
|
|
37
37
|
"test:changed": "vitest --changed",
|
|
38
|
-
"test:mutation": "node scripts/dev/mutation-check.mjs",
|
|
39
38
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
40
39
|
typecheck: "NODE_OPTIONS=--max-old-space-size=4096 tsc --noEmit",
|
|
41
40
|
lint: "eslint --max-warnings=0 src tests scripts",
|
|
42
41
|
"gen:schemas": "tsx scripts/gen-schemas.ts",
|
|
43
42
|
changeset: "changeset",
|
|
44
|
-
release: "pnpm build && changeset publish"
|
|
43
|
+
release: "pnpm build && changeset publish",
|
|
44
|
+
"test:mutation": "node scripts/dev/mutation-check.mjs"
|
|
45
45
|
};
|
|
46
46
|
var dependencies = {
|
|
47
47
|
"@aws-sdk/client-cloudwatch-logs": "^3.1063.0",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/openclaw/plugins.ts
|
|
4
|
+
function providerIdOf(p) {
|
|
5
|
+
return p.configPath?.split(".").pop() ?? p.id;
|
|
6
|
+
}
|
|
7
|
+
function requiredPlugins(cfg, catalog) {
|
|
8
|
+
if (cfg === null || typeof cfg !== "object") return [];
|
|
9
|
+
const models = cfg["models"];
|
|
10
|
+
if (models === null || typeof models !== "object") return [];
|
|
11
|
+
const providers = models["providers"];
|
|
12
|
+
if (providers === null || typeof providers !== "object") return [];
|
|
13
|
+
const configured = new Set(Object.keys(providers));
|
|
14
|
+
const out = [];
|
|
15
|
+
for (const entry of catalog.providers) {
|
|
16
|
+
if (!entry.plugin) continue;
|
|
17
|
+
const id = providerIdOf(entry);
|
|
18
|
+
if (configured.has(id)) {
|
|
19
|
+
out.push({ providerId: id, package: entry.plugin.package, version: entry.plugin.version });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
function installCommand(plugin, image, stateDir) {
|
|
25
|
+
return `docker run --rm -v ${stateDir}:/home/node/.openclaw ${image} openclaw plugins install 'clawhub:${plugin.package}@${plugin.version}' --accept-capabilities`;
|
|
26
|
+
}
|
|
27
|
+
function missingProviders(cfg, pluginsListJson) {
|
|
28
|
+
let loaded = /* @__PURE__ */ new Set();
|
|
29
|
+
try {
|
|
30
|
+
const parsed = JSON.parse(pluginsListJson);
|
|
31
|
+
const list = Array.isArray(parsed) ? parsed : parsed.plugins ?? [];
|
|
32
|
+
loaded = new Set(
|
|
33
|
+
list.filter((p) => p.enabled !== false && p.status !== "error").flatMap((p) => p.providerIds ?? [])
|
|
34
|
+
);
|
|
35
|
+
} catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
if (cfg === null || typeof cfg !== "object") return [];
|
|
39
|
+
const models = cfg["models"];
|
|
40
|
+
if (models === null || typeof models !== "object") return [];
|
|
41
|
+
const providers = models["providers"];
|
|
42
|
+
if (providers === null || typeof providers !== "object") return [];
|
|
43
|
+
return Object.keys(providers).filter((id) => !loaded.has(id));
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
installCommand,
|
|
47
|
+
missingProviders,
|
|
48
|
+
requiredPlugins
|
|
49
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
execPrivileged,
|
|
4
|
+
execPrivilegedWithInput,
|
|
5
|
+
resetPrivilegeCache,
|
|
6
|
+
shellQuote,
|
|
7
|
+
streamPrivileged,
|
|
8
|
+
sudoWrap
|
|
9
|
+
} from "./chunk-NUDIHZEH.js";
|
|
10
|
+
export {
|
|
11
|
+
execPrivileged,
|
|
12
|
+
execPrivilegedWithInput,
|
|
13
|
+
resetPrivilegeCache,
|
|
14
|
+
shellQuote,
|
|
15
|
+
streamPrivileged,
|
|
16
|
+
sudoWrap
|
|
17
|
+
};
|
|
@@ -6,10 +6,11 @@ import {
|
|
|
6
6
|
OPENCLAW_TMP,
|
|
7
7
|
atomicWriteConfig,
|
|
8
8
|
deepMerge,
|
|
9
|
-
normaliseGatewayPort,
|
|
10
9
|
readRemoteConfig,
|
|
11
10
|
restartGateway
|
|
12
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-N44K3LHE.js";
|
|
12
|
+
import "./chunk-NUDIHZEH.js";
|
|
13
|
+
import "./chunk-6TIYVHPX.js";
|
|
13
14
|
import "./chunk-EI7CQQ7D.js";
|
|
14
15
|
export {
|
|
15
16
|
OPENCLAW_CONFIG,
|
|
@@ -18,7 +19,6 @@ export {
|
|
|
18
19
|
OPENCLAW_TMP,
|
|
19
20
|
atomicWriteConfig,
|
|
20
21
|
deepMerge,
|
|
21
|
-
normaliseGatewayPort,
|
|
22
22
|
readRemoteConfig,
|
|
23
23
|
restartGateway
|
|
24
24
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ADD_HOST_FLAG,
|
|
4
|
+
CONFIG_FILENAME,
|
|
5
|
+
CONFIG_MOUNT_PATH,
|
|
6
|
+
CONTAINER_UID,
|
|
7
|
+
ENV_FILE_PATH,
|
|
8
|
+
GATEWAY_PORT,
|
|
9
|
+
PUBLISH_INSPECT_CMD,
|
|
10
|
+
SECURITY_FLAGS,
|
|
11
|
+
STATE_DIR_CONTAINER,
|
|
12
|
+
STATE_DIR_HOST_LINUX,
|
|
13
|
+
STATE_DIR_HOST_MACOS,
|
|
14
|
+
SUPERVISOR_ENV,
|
|
15
|
+
configPathForOS,
|
|
16
|
+
gatewayRunArgs,
|
|
17
|
+
gatewayRunCommand,
|
|
18
|
+
publishForRestart,
|
|
19
|
+
publishedGatewayPort,
|
|
20
|
+
stateDirForOS
|
|
21
|
+
} from "./chunk-6TIYVHPX.js";
|
|
22
|
+
import "./chunk-EI7CQQ7D.js";
|
|
23
|
+
export {
|
|
24
|
+
ADD_HOST_FLAG,
|
|
25
|
+
CONFIG_FILENAME,
|
|
26
|
+
CONFIG_MOUNT_PATH,
|
|
27
|
+
CONTAINER_UID,
|
|
28
|
+
ENV_FILE_PATH,
|
|
29
|
+
GATEWAY_PORT,
|
|
30
|
+
PUBLISH_INSPECT_CMD,
|
|
31
|
+
SECURITY_FLAGS,
|
|
32
|
+
STATE_DIR_CONTAINER,
|
|
33
|
+
STATE_DIR_HOST_LINUX,
|
|
34
|
+
STATE_DIR_HOST_MACOS,
|
|
35
|
+
SUPERVISOR_ENV,
|
|
36
|
+
configPathForOS,
|
|
37
|
+
gatewayRunArgs,
|
|
38
|
+
gatewayRunCommand,
|
|
39
|
+
publishForRestart,
|
|
40
|
+
publishedGatewayPort,
|
|
41
|
+
stateDirForOS
|
|
42
|
+
};
|
|
@@ -5,24 +5,28 @@ import {
|
|
|
5
5
|
bearerFrom,
|
|
6
6
|
isLoopbackBind,
|
|
7
7
|
serveMcp
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-AX74VXTV.js";
|
|
9
|
+
import "./chunk-UFRO4H5W.js";
|
|
10
|
+
import "./chunk-N44K3LHE.js";
|
|
11
|
+
import "./chunk-3QJBNAHW.js";
|
|
12
|
+
import "./chunk-WHJMKDV7.js";
|
|
13
|
+
import "./chunk-YR3O2I3S.js";
|
|
10
14
|
import "./chunk-6ZFIFDBJ.js";
|
|
15
|
+
import "./chunk-3WYA2QDM.js";
|
|
16
|
+
import "./chunk-AHAAEXWC.js";
|
|
11
17
|
import "./chunk-BOPSG2LI.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-P5LKWRPL.js";
|
|
19
|
-
import "./chunk-EI7CQQ7D.js";
|
|
20
|
-
import "./chunk-PVUVI35Y.js";
|
|
21
|
-
import "./chunk-3XK66DKK.js";
|
|
18
|
+
import "./chunk-LU2V3LXA.js";
|
|
19
|
+
import "./chunk-GYV4KNW7.js";
|
|
20
|
+
import "./chunk-SBLQH2TJ.js";
|
|
21
|
+
import "./chunk-LT4XMO5D.js";
|
|
22
|
+
import "./chunk-NUDIHZEH.js";
|
|
23
|
+
import "./chunk-JW5A7E3X.js";
|
|
22
24
|
import "./chunk-Q7NQY5HV.js";
|
|
23
25
|
import "./chunk-A2I76FTA.js";
|
|
24
26
|
import "./chunk-CX5SL5HP.js";
|
|
25
27
|
import "./chunk-KGXPLI7W.js";
|
|
28
|
+
import "./chunk-6TIYVHPX.js";
|
|
29
|
+
import "./chunk-EI7CQQ7D.js";
|
|
26
30
|
export {
|
|
27
31
|
MCP_HTTP_PORT,
|
|
28
32
|
authRequirement,
|