@clawops/cli 1.4.0 → 1.6.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 +40 -0
- package/dist/{apply-5RREMN3L.js → apply-SI3JKS4Z.js} +2 -2
- package/dist/automation-RULUSJBW.js +0 -0
- package/dist/{aws-FRE2JVAZ.js → aws-D7Y6LCGK.js} +52 -90
- package/dist/{azure-PVC3AQVC.js → azure-JQAMNVHN.js} +15 -56
- package/dist/{bootstrap-G4UZ2FKH.js → bootstrap-RY4VOSDJ.js} +2 -2
- package/dist/chunk-3QJBNAHW.js +0 -0
- package/dist/chunk-6ZFIFDBJ.js +0 -0
- package/dist/{chunk-UAA6YOOP.js → chunk-72FF7IK2.js} +2 -2
- package/dist/chunk-A2I76FTA.js +0 -0
- package/dist/chunk-BOPSG2LI.js +0 -0
- package/dist/{chunk-JYQZJMD3.js → chunk-C5NDLOK2.js} +41 -33
- package/dist/chunk-CX5SL5HP.js +0 -0
- package/dist/{chunk-4U3LTLWZ.js → chunk-GJEF6UQA.js} +1 -0
- package/dist/chunk-KGXPLI7W.js +0 -0
- package/dist/{chunk-ZVOEQCNW.js → chunk-LCKD7L7X.js} +1 -1
- package/dist/chunk-OIGTOLB3.js +0 -0
- package/dist/{chunk-ZONXY3C6.js → chunk-QHGFENYR.js} +2 -2
- package/dist/{chunk-T5EX55GP.js → chunk-QI75OVJK.js} +3 -3
- package/dist/chunk-XKT42M34.js +72 -0
- package/dist/chunk-YTH4L2GN.js +0 -0
- package/dist/chunk-ZFNPM2WG.js +0 -0
- package/dist/cli.js +311 -54
- package/dist/{context-PSGEX2D7.js → context-KPKBOWOP.js} +1 -1
- package/dist/errors-OK47MQFD.js +0 -0
- package/dist/firewall-XQGO7HWK.js +51 -0
- package/dist/{gcp-BXDTC6EK.js → gcp-6FT2A45S.js} +14 -63
- package/dist/{generate-Z7DBMANX.js → generate-YV7226Q7.js} +2 -2
- package/dist/js-yaml-PTEEG4FO.js +0 -0
- package/dist/local-DXBEVZ5C.js +0 -0
- package/dist/mcp-apps-KY44ED3Y.js +0 -0
- package/dist/mcp-wire-ZWIYMLEW.js +45 -0
- package/dist/outputs-DJHBY7EE.js +0 -0
- package/dist/overlay-store-ADZPD7EU.js +0 -0
- package/dist/{package-WAJRGBBM.js → package-EW3FS257.js} +1 -1
- package/dist/{pool-FBFHATDG.js → pool-JZGKPP6K.js} +2 -2
- package/dist/providers-2OABPW2E.js +0 -0
- package/dist/remote-config-QF5TT7GU.js +0 -0
- package/dist/secrets-SVZWNAPK.js +0 -0
- package/dist/{server-IWLZJ4EU.js → server-3DEZHUWB.js} +9 -9
- package/dist/{ssh-IQXNME3D.js → ssh-E2AMBPZY.js} +1 -1
- package/dist/state-PRBIIN7I.js +0 -0
- package/dist/store-SDUR52Z5.js +0 -0
- package/dist/validate-T5M5EHSJ.js +0 -0
- package/package.json +26 -14
- package/dist/firewall-YYDOWDDP.js +0 -36
package/dist/cli.js
CHANGED
|
@@ -5,18 +5,20 @@ import {
|
|
|
5
5
|
writeAppConfigs
|
|
6
6
|
} from "./chunk-OIGTOLB3.js";
|
|
7
7
|
import {
|
|
8
|
+
REPO_URL,
|
|
8
9
|
chalk,
|
|
9
10
|
failure,
|
|
10
11
|
info,
|
|
11
12
|
monitor_default,
|
|
13
|
+
printCta,
|
|
12
14
|
spinner,
|
|
13
15
|
success,
|
|
14
16
|
validateOpenclawConfig,
|
|
15
17
|
warn
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-C5NDLOK2.js";
|
|
19
|
+
import "./chunk-QI75OVJK.js";
|
|
20
|
+
import "./chunk-LCKD7L7X.js";
|
|
21
|
+
import "./chunk-GJEF6UQA.js";
|
|
20
22
|
import "./chunk-ZFNPM2WG.js";
|
|
21
23
|
import "./chunk-A2I76FTA.js";
|
|
22
24
|
import {
|
|
@@ -31,7 +33,7 @@ import {
|
|
|
31
33
|
} from "./chunk-KGXPLI7W.js";
|
|
32
34
|
|
|
33
35
|
// src/cli/index.ts
|
|
34
|
-
import { defineCommand as
|
|
36
|
+
import { defineCommand as defineCommand22, runMain } from "citty";
|
|
35
37
|
|
|
36
38
|
// src/cli/commands/init.ts
|
|
37
39
|
import { defineCommand } from "citty";
|
|
@@ -203,7 +205,7 @@ var up_default = defineCommand2({
|
|
|
203
205
|
config: { type: "string", description: "Path to openclaw config overlay JSON (local provider only)" }
|
|
204
206
|
},
|
|
205
207
|
async run({ args }) {
|
|
206
|
-
const { buildContext } = await import("./context-
|
|
208
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
207
209
|
const ctx = buildContext(args);
|
|
208
210
|
const openclawVersion = typeof args["openclaw-version"] === "string" ? args["openclaw-version"] : "stable";
|
|
209
211
|
if (ctx.adapter.name === "local") {
|
|
@@ -214,7 +216,7 @@ var up_default = defineCommand2({
|
|
|
214
216
|
);
|
|
215
217
|
}
|
|
216
218
|
const { localOpts } = stackConfig;
|
|
217
|
-
const { localBootstrap } = await import("./bootstrap-
|
|
219
|
+
const { localBootstrap } = await import("./bootstrap-RY4VOSDJ.js");
|
|
218
220
|
const abortController = new AbortController();
|
|
219
221
|
process3.on("SIGINT", () => abortController.abort());
|
|
220
222
|
process3.on("SIGTERM", () => abortController.abort());
|
|
@@ -307,7 +309,7 @@ var up_default = defineCommand2({
|
|
|
307
309
|
}
|
|
308
310
|
});
|
|
309
311
|
async function applyLocalConfigOverlay(opts) {
|
|
310
|
-
const { connect } = await import("./ssh-
|
|
312
|
+
const { connect } = await import("./ssh-E2AMBPZY.js");
|
|
311
313
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
312
314
|
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
313
315
|
let overlay;
|
|
@@ -349,7 +351,7 @@ var down_default = defineCommand3({
|
|
|
349
351
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
350
352
|
},
|
|
351
353
|
async run({ args }) {
|
|
352
|
-
const { buildContext } = await import("./context-
|
|
354
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
353
355
|
const ctx = buildContext(args);
|
|
354
356
|
if (args["dry-run"]) {
|
|
355
357
|
info(`Dry run \u2014 would destroy stack "${ctx.stackName}"`);
|
|
@@ -413,7 +415,7 @@ var status_default = defineCommand4({
|
|
|
413
415
|
json: { type: "boolean", description: "Emit JSON" }
|
|
414
416
|
},
|
|
415
417
|
async run({ args }) {
|
|
416
|
-
const { buildContext } = await import("./context-
|
|
418
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
417
419
|
const ctx = buildContext(args);
|
|
418
420
|
if (ctx.adapter.name === "local") {
|
|
419
421
|
const state = ctx.localState;
|
|
@@ -485,8 +487,8 @@ var plan_default = defineCommand5({
|
|
|
485
487
|
out: { type: "string", description: "Write plan JSON to this absolute path (default: stdout)" }
|
|
486
488
|
},
|
|
487
489
|
async run({ args }) {
|
|
488
|
-
const { buildContext } = await import("./context-
|
|
489
|
-
const { generatePlan } = await import("./generate-
|
|
490
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
491
|
+
const { generatePlan } = await import("./generate-YV7226Q7.js");
|
|
490
492
|
const ctx = buildContext(args);
|
|
491
493
|
if (ctx.adapter.name === "local") {
|
|
492
494
|
throw new UsageError(
|
|
@@ -576,7 +578,7 @@ var apply_default = defineCommand6({
|
|
|
576
578
|
},
|
|
577
579
|
async run({ args }) {
|
|
578
580
|
const { validatePlan } = await import("./validate-T5M5EHSJ.js");
|
|
579
|
-
const { applyPlan } = await import("./apply-
|
|
581
|
+
const { applyPlan } = await import("./apply-SI3JKS4Z.js");
|
|
580
582
|
const planPath = args._?.[0];
|
|
581
583
|
if (!planPath) {
|
|
582
584
|
throw new UsageError("Usage: clawops apply <plan.json>");
|
|
@@ -692,7 +694,7 @@ var destroy_default = defineCommand7({
|
|
|
692
694
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
693
695
|
},
|
|
694
696
|
async run({ args }) {
|
|
695
|
-
const { buildContext } = await import("./context-
|
|
697
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
696
698
|
const ctx = buildContext(args);
|
|
697
699
|
if (ctx.adapter.name === "local") {
|
|
698
700
|
throw new UsageError(
|
|
@@ -759,8 +761,8 @@ var ssh_default = defineCommand8({
|
|
|
759
761
|
command: { type: "string", description: "Remote command to run (instead of interactive shell)" }
|
|
760
762
|
},
|
|
761
763
|
async run({ args }) {
|
|
762
|
-
const { buildContext } = await import("./context-
|
|
763
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
764
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
765
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
764
766
|
const ctx = buildContext(args);
|
|
765
767
|
let conn;
|
|
766
768
|
if (ctx.adapter.name === "local") {
|
|
@@ -846,9 +848,9 @@ var tunnel_default = defineCommand9({
|
|
|
846
848
|
"no-open": { type: "boolean", description: "Do not open browser after tunnel is ready" }
|
|
847
849
|
},
|
|
848
850
|
async run({ args }) {
|
|
849
|
-
const { buildContext } = await import("./context-
|
|
851
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
850
852
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
851
|
-
const { acquireSession } = await import("./pool-
|
|
853
|
+
const { acquireSession } = await import("./pool-JZGKPP6K.js");
|
|
852
854
|
const ctx = buildContext(args);
|
|
853
855
|
const stack = await ctx.getStack();
|
|
854
856
|
const outputMap = await stack.outputs();
|
|
@@ -914,9 +916,9 @@ var logs_default = defineCommand10({
|
|
|
914
916
|
since: { type: "string", description: "Show logs since duration (e.g. 5m, 1h)" }
|
|
915
917
|
},
|
|
916
918
|
async run({ args }) {
|
|
917
|
-
const { buildContext } = await import("./context-
|
|
919
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
918
920
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
919
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
921
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
920
922
|
const ctx = buildContext(args);
|
|
921
923
|
const stack = await ctx.getStack();
|
|
922
924
|
const outputMap = await stack.outputs();
|
|
@@ -1031,9 +1033,9 @@ var config_default = defineCommand11({
|
|
|
1031
1033
|
"dry-run": { type: "boolean", description: "Show what would change without writing" }
|
|
1032
1034
|
},
|
|
1033
1035
|
async run({ args }) {
|
|
1034
|
-
const { buildContext } = await import("./context-
|
|
1036
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1035
1037
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1036
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1038
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1037
1039
|
const [action, key, value] = args._ ?? [];
|
|
1038
1040
|
if (!action || !["get", "set", "unset", "validate"].includes(action)) {
|
|
1039
1041
|
failure("Usage: clawops config <get [key] | set key value | unset key | validate>");
|
|
@@ -1157,9 +1159,9 @@ var agents_default = defineCommand12({
|
|
|
1157
1159
|
json: { type: "boolean", description: "Emit JSON (for list)" }
|
|
1158
1160
|
},
|
|
1159
1161
|
async run({ args }) {
|
|
1160
|
-
const { buildContext } = await import("./context-
|
|
1162
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1161
1163
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1162
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1164
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1163
1165
|
const [action, name] = args._ ?? [];
|
|
1164
1166
|
if (!action || !["list", "restart", "logs"].includes(action)) {
|
|
1165
1167
|
failure("Usage: clawops agents <list | restart [name] | logs <name>>");
|
|
@@ -1261,9 +1263,9 @@ var gateway_default = defineCommand13({
|
|
|
1261
1263
|
json: { type: "boolean", description: "Emit JSON (for status)" }
|
|
1262
1264
|
},
|
|
1263
1265
|
async run({ args }) {
|
|
1264
|
-
const { buildContext } = await import("./context-
|
|
1266
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1265
1267
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1266
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1268
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1267
1269
|
const [action, versionArg] = args._ ?? [];
|
|
1268
1270
|
if (!action || !["status", "restart", "update"].includes(action)) {
|
|
1269
1271
|
failure("Usage: clawops gateway <status | restart | update [version]>");
|
|
@@ -1374,8 +1376,8 @@ var backup_default = defineCommand14({
|
|
|
1374
1376
|
yes: { type: "boolean", description: "[restore] Skip confirmation prompt" }
|
|
1375
1377
|
},
|
|
1376
1378
|
async run({ args }) {
|
|
1377
|
-
const { buildContext } = await import("./context-
|
|
1378
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1379
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1380
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1379
1381
|
const action = args.action;
|
|
1380
1382
|
if (action !== "create" && action !== "restore") {
|
|
1381
1383
|
throw new UsageError(`Unknown action: ${action}. Use "create" or "restore"`);
|
|
@@ -1547,7 +1549,7 @@ var stacks_default = defineCommand15({
|
|
|
1547
1549
|
let isDeployed = false;
|
|
1548
1550
|
if (!args.force) {
|
|
1549
1551
|
try {
|
|
1550
|
-
const { buildContext } = await import("./context-
|
|
1552
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1551
1553
|
const ctx = buildContext({ stack: name });
|
|
1552
1554
|
if (ctx.adapter.name === "local") {
|
|
1553
1555
|
isDeployed = !!ctx.localState;
|
|
@@ -1668,9 +1670,9 @@ var doctor_default = defineCommand16({
|
|
|
1668
1670
|
info("Credential checks skipped \u2014 no config");
|
|
1669
1671
|
} else {
|
|
1670
1672
|
const { getProvider } = await import("./providers-2OABPW2E.js");
|
|
1671
|
-
await import("./aws-
|
|
1672
|
-
await import("./gcp-
|
|
1673
|
-
await import("./azure-
|
|
1673
|
+
await import("./aws-D7Y6LCGK.js");
|
|
1674
|
+
await import("./gcp-6FT2A45S.js");
|
|
1675
|
+
await import("./azure-JQAMNVHN.js");
|
|
1674
1676
|
await import("./local-DXBEVZ5C.js");
|
|
1675
1677
|
const checkedProviders = /* @__PURE__ */ new Set();
|
|
1676
1678
|
for (const [stackName, stackCfg] of Object.entries(config.stacks)) {
|
|
@@ -1705,9 +1707,9 @@ var doctor_default = defineCommand16({
|
|
|
1705
1707
|
info("Remote health skipped \u2014 no config");
|
|
1706
1708
|
} else {
|
|
1707
1709
|
try {
|
|
1708
|
-
const { buildContext } = await import("./context-
|
|
1710
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1709
1711
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1710
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1712
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1711
1713
|
const ctx = buildContext({ stack: args.stack });
|
|
1712
1714
|
const stack = await ctx.getStack();
|
|
1713
1715
|
const outputMap = await stack.outputs();
|
|
@@ -1792,7 +1794,14 @@ var doctor_default = defineCommand16({
|
|
|
1792
1794
|
}
|
|
1793
1795
|
}
|
|
1794
1796
|
process18.stdout.write("\n");
|
|
1795
|
-
if (!nodeOk)
|
|
1797
|
+
if (!nodeOk) {
|
|
1798
|
+
process18.stdout.write(
|
|
1799
|
+
`Run \`clawops bug\` to open a pre-filled issue at ${REPO_URL}/issues
|
|
1800
|
+
|
|
1801
|
+
`
|
|
1802
|
+
);
|
|
1803
|
+
process18.exit(1);
|
|
1804
|
+
}
|
|
1796
1805
|
}
|
|
1797
1806
|
});
|
|
1798
1807
|
|
|
@@ -1813,7 +1822,7 @@ var serveCmd = defineCommand17({
|
|
|
1813
1822
|
inspector: { type: "boolean", description: "Enable MCP inspector" }
|
|
1814
1823
|
},
|
|
1815
1824
|
async run({ args }) {
|
|
1816
|
-
const { serveMcp } = await import("./server-
|
|
1825
|
+
const { serveMcp } = await import("./server-3DEZHUWB.js");
|
|
1817
1826
|
await serveMcp({
|
|
1818
1827
|
port: args.http ? Number(args.http) : void 0,
|
|
1819
1828
|
bind: args.bind,
|
|
@@ -1878,6 +1887,85 @@ var installCmd = defineCommand17({
|
|
|
1878
1887
|
}
|
|
1879
1888
|
}
|
|
1880
1889
|
});
|
|
1890
|
+
var wireCmd = defineCommand17({
|
|
1891
|
+
meta: {
|
|
1892
|
+
name: "wire",
|
|
1893
|
+
description: "Wire the gateway AI as an MCP client of clawops (WO-28)"
|
|
1894
|
+
},
|
|
1895
|
+
args: {
|
|
1896
|
+
stack: { type: "string", description: "Target stack name" },
|
|
1897
|
+
force: { type: "boolean", description: "Apply even if gateway version is below minimum" }
|
|
1898
|
+
},
|
|
1899
|
+
async run({ args }) {
|
|
1900
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1901
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1902
|
+
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1903
|
+
const { wireGatewayMcp } = await import("./mcp-wire-ZWIYMLEW.js");
|
|
1904
|
+
const ac = new AbortController();
|
|
1905
|
+
process19.on("SIGINT", () => {
|
|
1906
|
+
ac.abort();
|
|
1907
|
+
process19.exit(130);
|
|
1908
|
+
});
|
|
1909
|
+
process19.on("SIGTERM", () => {
|
|
1910
|
+
ac.abort();
|
|
1911
|
+
process19.exit(143);
|
|
1912
|
+
});
|
|
1913
|
+
const ctx = buildContext({ stack: args.stack });
|
|
1914
|
+
let conn;
|
|
1915
|
+
if (ctx.adapter.name === "local") {
|
|
1916
|
+
if (!ctx.localState) {
|
|
1917
|
+
failure("Stack is not deployed. Run `clawops up` first.");
|
|
1918
|
+
process19.exit(1);
|
|
1919
|
+
}
|
|
1920
|
+
const ls = ctx.localState;
|
|
1921
|
+
conn = { host: ls.sshHost, port: ls.sshPort, user: ls.sshUser, privateKeyPath: ls.privateKeyPath, knownHostsPath: ls.knownHostsPath };
|
|
1922
|
+
} else {
|
|
1923
|
+
const stack = await ctx.getStack();
|
|
1924
|
+
const outputMap = await stack.outputs();
|
|
1925
|
+
const outputs = Object.fromEntries(
|
|
1926
|
+
Object.entries(outputMap).map(([k, v]) => [k, v.value])
|
|
1927
|
+
);
|
|
1928
|
+
if (!outputs["publicIp"]) {
|
|
1929
|
+
failure("Stack has no outputs. Run `clawops up` first.");
|
|
1930
|
+
process19.exit(1);
|
|
1931
|
+
}
|
|
1932
|
+
const base = extractBaseOutputs(outputs);
|
|
1933
|
+
conn = {
|
|
1934
|
+
host: base.publicIp,
|
|
1935
|
+
port: base.sshPort ?? 22,
|
|
1936
|
+
user: base.sshUser ?? "ubuntu",
|
|
1937
|
+
privateKeyPath: ctx.config.ssh.keyPath,
|
|
1938
|
+
knownHostsPath: ctx.config.ssh.knownHostsPath
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
const spin = spinner(`Connecting to ${conn.host}...`);
|
|
1942
|
+
const { session, release } = await acquireSession({ ...conn, signal: ac.signal });
|
|
1943
|
+
try {
|
|
1944
|
+
spin.text = "Reading gateway config...";
|
|
1945
|
+
const result = await wireGatewayMcp(session, ac.signal, { force: Boolean(args.force) });
|
|
1946
|
+
if (result.status === "version-blocked") {
|
|
1947
|
+
spin.fail("Gateway version is too old for MCP client support.");
|
|
1948
|
+
warn(`Gateway version ${result.version} requires at least 2026.4 for MCP client support.`);
|
|
1949
|
+
info("Upgrade OpenClaw and re-run, or bypass with: clawops mcp wire --force");
|
|
1950
|
+
process19.exit(1);
|
|
1951
|
+
}
|
|
1952
|
+
if (result.rewired) {
|
|
1953
|
+
spin.succeed("Re-wiring clawops MCP client \u2014 previous entry replaced.");
|
|
1954
|
+
} else {
|
|
1955
|
+
spin.succeed("Gateway MCP client wired.");
|
|
1956
|
+
}
|
|
1957
|
+
success("The gateway's AI can now run clawops commands.");
|
|
1958
|
+
info('Try asking it: "check if my stack is healthy"');
|
|
1959
|
+
} catch (err) {
|
|
1960
|
+
spin.fail("Failed to wire gateway MCP client.");
|
|
1961
|
+
failure(err instanceof Error ? err.message : String(err));
|
|
1962
|
+
process19.exit(1);
|
|
1963
|
+
} finally {
|
|
1964
|
+
release();
|
|
1965
|
+
drainPool();
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
});
|
|
1881
1969
|
var mcp_default = defineCommand17({
|
|
1882
1970
|
meta: {
|
|
1883
1971
|
name: "mcp",
|
|
@@ -1886,7 +1974,8 @@ var mcp_default = defineCommand17({
|
|
|
1886
1974
|
args: {},
|
|
1887
1975
|
subCommands: {
|
|
1888
1976
|
serve: serveCmd,
|
|
1889
|
-
install: installCmd
|
|
1977
|
+
install: installCmd,
|
|
1978
|
+
wire: wireCmd
|
|
1890
1979
|
}
|
|
1891
1980
|
});
|
|
1892
1981
|
|
|
@@ -2296,6 +2385,15 @@ var setup_default = defineCommand18({
|
|
|
2296
2385
|
signal: ac.signal,
|
|
2297
2386
|
inquirer
|
|
2298
2387
|
});
|
|
2388
|
+
await maybeWireGatewayMcp({
|
|
2389
|
+
stackName: stackAnswers.stackName,
|
|
2390
|
+
host: localHost,
|
|
2391
|
+
port: localPort,
|
|
2392
|
+
user: localUser,
|
|
2393
|
+
keyPath: localKeyPath,
|
|
2394
|
+
signal: ac.signal,
|
|
2395
|
+
inquirer
|
|
2396
|
+
});
|
|
2299
2397
|
} else {
|
|
2300
2398
|
const { getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
|
|
2301
2399
|
const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
|
|
@@ -2314,7 +2412,7 @@ var setup_default = defineCommand18({
|
|
|
2314
2412
|
default: false
|
|
2315
2413
|
}]);
|
|
2316
2414
|
if (applyNow) {
|
|
2317
|
-
const { applyPlan } = await import("./apply-
|
|
2415
|
+
const { applyPlan } = await import("./apply-SI3JKS4Z.js");
|
|
2318
2416
|
const plan = JSON.parse(readFileSync3(outputPath, "utf-8"));
|
|
2319
2417
|
try {
|
|
2320
2418
|
await applyPlan(plan, {
|
|
@@ -2327,6 +2425,7 @@ var setup_default = defineCommand18({
|
|
|
2327
2425
|
failure(err instanceof Error ? err.message : String(err));
|
|
2328
2426
|
process20.exit(1);
|
|
2329
2427
|
}
|
|
2428
|
+
await maybeWireGatewayMcpCloud({ stackName: stackAnswers.stackName, signal: ac.signal, inquirer });
|
|
2330
2429
|
} else {
|
|
2331
2430
|
info(`
|
|
2332
2431
|
To deploy later: clawops apply ${outputPath}`);
|
|
@@ -2336,8 +2435,8 @@ To deploy later: clawops apply ${outputPath}`);
|
|
|
2336
2435
|
});
|
|
2337
2436
|
async function runLocalDeploy(opts) {
|
|
2338
2437
|
const { setConfig: setConfig2, getConfig: getConfig2, getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
|
|
2339
|
-
const { localBootstrap } = await import("./bootstrap-
|
|
2340
|
-
const { connect } = await import("./ssh-
|
|
2438
|
+
const { localBootstrap } = await import("./bootstrap-RY4VOSDJ.js");
|
|
2439
|
+
const { connect } = await import("./ssh-E2AMBPZY.js");
|
|
2341
2440
|
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
2342
2441
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
2343
2442
|
const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
|
|
@@ -2419,7 +2518,7 @@ async function runLocalDeploy(opts) {
|
|
|
2419
2518
|
spin2.fail("Configuration failed");
|
|
2420
2519
|
throw err;
|
|
2421
2520
|
}
|
|
2422
|
-
const { drainPool } = await import("./pool-
|
|
2521
|
+
const { drainPool } = await import("./pool-JZGKPP6K.js");
|
|
2423
2522
|
drainPool();
|
|
2424
2523
|
const tokenPath = path3.join(os.homedir(), ".clawops", "secrets", `GATEWAY_TOKEN_${opts.stackName}`);
|
|
2425
2524
|
const dashboardUrl = `${state.gatewayUrl}?token=${opts.gatewayToken}`;
|
|
@@ -2431,6 +2530,7 @@ async function runLocalDeploy(opts) {
|
|
|
2431
2530
|
info(`Token saved to ${tokenPath}`);
|
|
2432
2531
|
info(`
|
|
2433
2532
|
Run clawops doctor --stack ${opts.stackName} to check everything is healthy`);
|
|
2533
|
+
printCta();
|
|
2434
2534
|
}
|
|
2435
2535
|
var CLOUD_AUTH = {
|
|
2436
2536
|
aws: {
|
|
@@ -2556,7 +2656,7 @@ var DOCKER_CHECK_CMD = [
|
|
|
2556
2656
|
"echo NOT_RUNNING"
|
|
2557
2657
|
].join("; ");
|
|
2558
2658
|
async function checkDockerPreflight(opts) {
|
|
2559
|
-
const { acquireSession } = await import("./pool-
|
|
2659
|
+
const { acquireSession } = await import("./pool-JZGKPP6K.js");
|
|
2560
2660
|
const { ProviderError } = await import("./errors-OK47MQFD.js");
|
|
2561
2661
|
const spin = spinner("Checking Docker on target host...");
|
|
2562
2662
|
const timeoutSignal = AbortSignal.timeout(DOCKER_PREFLIGHT_TIMEOUT_MS);
|
|
@@ -2603,7 +2703,7 @@ async function checkDockerPreflight(opts) {
|
|
|
2603
2703
|
var DOCKER_POLL_MS = 3e3;
|
|
2604
2704
|
var DOCKER_TIMEOUT_MS = 9e4;
|
|
2605
2705
|
async function startRemoteDocker(opts, spin) {
|
|
2606
|
-
const { acquireSession } = await import("./pool-
|
|
2706
|
+
const { acquireSession } = await import("./pool-JZGKPP6K.js");
|
|
2607
2707
|
const { ProviderError } = await import("./errors-OK47MQFD.js");
|
|
2608
2708
|
spin.text = "Starting Docker on the remote server...";
|
|
2609
2709
|
const { session, release } = await acquireSession({
|
|
@@ -2803,6 +2903,55 @@ function printMcpSnippet() {
|
|
|
2803
2903
|
}
|
|
2804
2904
|
}, null, 2) + "\n\n");
|
|
2805
2905
|
}
|
|
2906
|
+
async function maybeWireGatewayMcp(opts) {
|
|
2907
|
+
process20.stdout.write("\n");
|
|
2908
|
+
const { wireGateway } = await inquirerPromptWire(opts.inquirer);
|
|
2909
|
+
if (!wireGateway) return;
|
|
2910
|
+
const { connect } = await import("./ssh-E2AMBPZY.js");
|
|
2911
|
+
const { getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
|
|
2912
|
+
const { wireGatewayMcp } = await import("./mcp-wire-ZWIYMLEW.js");
|
|
2913
|
+
const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
|
|
2914
|
+
const spin = spinner("Wiring gateway MCP client...");
|
|
2915
|
+
const session = await connect({
|
|
2916
|
+
host: opts.host,
|
|
2917
|
+
port: opts.port,
|
|
2918
|
+
user: opts.user,
|
|
2919
|
+
privateKeyPath: opts.keyPath,
|
|
2920
|
+
knownHostsPath,
|
|
2921
|
+
signal: opts.signal
|
|
2922
|
+
});
|
|
2923
|
+
try {
|
|
2924
|
+
const result = await wireGatewayMcp(session, opts.signal ?? AbortSignal.timeout(3e4));
|
|
2925
|
+
if (result.status === "version-blocked") {
|
|
2926
|
+
spin.warn(`Gateway version ${result.version} is too old for MCP client support (requires \u2265 2026.4).`);
|
|
2927
|
+
info("Upgrade OpenClaw and run: clawops mcp wire --stack " + opts.stackName);
|
|
2928
|
+
} else {
|
|
2929
|
+
spin.succeed(result.rewired ? "Gateway MCP client re-wired." : "Gateway MCP client wired.");
|
|
2930
|
+
success("The gateway's AI can now run clawops commands.");
|
|
2931
|
+
info('Try asking it: "check if my stack is healthy"');
|
|
2932
|
+
}
|
|
2933
|
+
} catch (err) {
|
|
2934
|
+
spin.fail("Failed to wire gateway MCP client.");
|
|
2935
|
+
failure(err instanceof Error ? err.message : String(err));
|
|
2936
|
+
info("You can retry later: clawops mcp wire --stack " + opts.stackName);
|
|
2937
|
+
} finally {
|
|
2938
|
+
session.close();
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
async function maybeWireGatewayMcpCloud(opts) {
|
|
2942
|
+
process20.stdout.write("\n");
|
|
2943
|
+
const { wireGateway } = await inquirerPromptWire(opts.inquirer);
|
|
2944
|
+
if (!wireGateway) return;
|
|
2945
|
+
info(`Run this after the server is ready: clawops mcp wire --stack ${opts.stackName}`);
|
|
2946
|
+
}
|
|
2947
|
+
async function inquirerPromptWire(inquirer) {
|
|
2948
|
+
return inquirer.prompt([{
|
|
2949
|
+
type: "confirm",
|
|
2950
|
+
name: "wireGateway",
|
|
2951
|
+
message: "Should the OpenClaw gateway's AI also be able to manage this stack? (adds clawops MCP client to gateway)",
|
|
2952
|
+
default: false
|
|
2953
|
+
}]);
|
|
2954
|
+
}
|
|
2806
2955
|
function loadCatalogs(yaml) {
|
|
2807
2956
|
const specDir = path3.join(path3.dirname(fileURLToPath(import.meta.url)), "../../../spec");
|
|
2808
2957
|
try {
|
|
@@ -3023,10 +3172,10 @@ var rotateCmd = defineCommand19({
|
|
|
3023
3172
|
}
|
|
3024
3173
|
info(`Re-applying config overlay to stack "${targetStack}"\u2026`);
|
|
3025
3174
|
try {
|
|
3026
|
-
const { buildContext } = await import("./context-
|
|
3175
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
3027
3176
|
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
3028
3177
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
3029
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
3178
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
3030
3179
|
const { localStateToConnectionInfo } = await import("./state-PRBIIN7I.js");
|
|
3031
3180
|
const ctx = buildContext({ stack: targetStack });
|
|
3032
3181
|
let conn;
|
|
@@ -3151,7 +3300,7 @@ var COMMANDS = [
|
|
|
3151
3300
|
["backup", "Create or restore an OpenClaw state backup"],
|
|
3152
3301
|
["stacks", "List named stacks and their state"],
|
|
3153
3302
|
["doctor", "Check Node version, config, SSH key, provider credentials, and Pulumi home"],
|
|
3154
|
-
["mcp", "MCP server operations (mcp serve | mcp install)"],
|
|
3303
|
+
["mcp", "MCP server operations (mcp serve | mcp install | mcp wire)"],
|
|
3155
3304
|
["secret", "Manage secrets (secret list | set | delete | rotate | audit)"],
|
|
3156
3305
|
["monitor", "Live dashboard: gateway health, container status, resource usage, log tail"],
|
|
3157
3306
|
["help", "Show this help message"]
|
|
@@ -3198,31 +3347,138 @@ ${bold("Global flags:")}
|
|
|
3198
3347
|
}
|
|
3199
3348
|
process.stdout.write(`
|
|
3200
3349
|
${dim("Run `clawops <command> --help` for command-specific flags.")}
|
|
3350
|
+
`);
|
|
3351
|
+
printCta();
|
|
3352
|
+
}
|
|
3353
|
+
});
|
|
3201
3354
|
|
|
3355
|
+
// src/cli/commands/bug.ts
|
|
3356
|
+
import { defineCommand as defineCommand21 } from "citty";
|
|
3357
|
+
import process22 from "process";
|
|
3358
|
+
import { accessSync as accessSync2, constants as constants2 } from "fs";
|
|
3359
|
+
import { execSync as execSync2 } from "child_process";
|
|
3360
|
+
var ISSUES_URL = `${REPO_URL}/issues/new`;
|
|
3361
|
+
var BODY_CAP = 2e3;
|
|
3362
|
+
var VERSION = true ? "1.6.0" : "dev";
|
|
3363
|
+
async function collectContext() {
|
|
3364
|
+
const nodeVersion = process22.version;
|
|
3365
|
+
const os3 = `${process22.platform} ${process22.arch}`;
|
|
3366
|
+
let provider = "unknown";
|
|
3367
|
+
let stackCount = 0;
|
|
3368
|
+
let sshKey = "unknown";
|
|
3369
|
+
try {
|
|
3370
|
+
const { getConfig: getConfig2 } = await import("./store-SDUR52Z5.js");
|
|
3371
|
+
const config = getConfig2();
|
|
3372
|
+
if (config) {
|
|
3373
|
+
const stacks = Object.values(config.stacks);
|
|
3374
|
+
stackCount = stacks.length;
|
|
3375
|
+
provider = stacks[0]?.provider ?? "none";
|
|
3376
|
+
const keyPath = config.ssh.keyPath.replace(/^~/, process22.env["HOME"] ?? "~");
|
|
3377
|
+
try {
|
|
3378
|
+
accessSync2(keyPath, constants2.R_OK);
|
|
3379
|
+
sshKey = "present";
|
|
3380
|
+
} catch {
|
|
3381
|
+
sshKey = "missing";
|
|
3382
|
+
}
|
|
3383
|
+
} else {
|
|
3384
|
+
provider = "not configured";
|
|
3385
|
+
sshKey = "not configured";
|
|
3386
|
+
}
|
|
3387
|
+
} catch {
|
|
3388
|
+
}
|
|
3389
|
+
return [
|
|
3390
|
+
`**clawops version:** ${VERSION}`,
|
|
3391
|
+
`**Node:** ${nodeVersion}`,
|
|
3392
|
+
`**OS:** ${os3}`,
|
|
3393
|
+
`**Provider:** ${provider}`,
|
|
3394
|
+
`**Stacks:** ${stackCount}`,
|
|
3395
|
+
`**SSH key:** ${sshKey}`
|
|
3396
|
+
].join("\n");
|
|
3397
|
+
}
|
|
3398
|
+
function buildIssueUrl(title, command, context) {
|
|
3399
|
+
const body = [
|
|
3400
|
+
context,
|
|
3401
|
+
"",
|
|
3402
|
+
"**Description:**",
|
|
3403
|
+
title,
|
|
3404
|
+
"",
|
|
3405
|
+
command ? `**Command:**
|
|
3406
|
+
\`${command}\`` : "",
|
|
3407
|
+
"",
|
|
3408
|
+
"**Steps to reproduce:**",
|
|
3409
|
+
"<!-- Please describe what you did -->\n"
|
|
3410
|
+
].filter((l) => l !== void 0).join("\n").slice(0, BODY_CAP);
|
|
3411
|
+
const params = new URLSearchParams({ title, body });
|
|
3412
|
+
return `${ISSUES_URL}?${params.toString()}`;
|
|
3413
|
+
}
|
|
3414
|
+
function openBrowser2(url) {
|
|
3415
|
+
try {
|
|
3416
|
+
const cmd = process22.platform === "darwin" ? "open" : "xdg-open";
|
|
3417
|
+
execSync2(`${cmd} "${url}"`, { stdio: "ignore" });
|
|
3418
|
+
return true;
|
|
3419
|
+
} catch {
|
|
3420
|
+
return false;
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
var bug_default = defineCommand21({
|
|
3424
|
+
meta: {
|
|
3425
|
+
name: "bug",
|
|
3426
|
+
description: "Open a pre-filled GitHub issue with system context from clawops doctor"
|
|
3427
|
+
},
|
|
3428
|
+
args: {
|
|
3429
|
+
json: { type: "boolean", description: "Emit issue URL as JSON without opening a browser" }
|
|
3430
|
+
},
|
|
3431
|
+
async run({ args }) {
|
|
3432
|
+
const context = await collectContext();
|
|
3433
|
+
let title = "";
|
|
3434
|
+
let command = "";
|
|
3435
|
+
if (!args.json) {
|
|
3436
|
+
const { createInterface: createInterface3 } = await import("readline/promises");
|
|
3437
|
+
const rl = createInterface3({ input: process22.stdin, output: process22.stdout });
|
|
3438
|
+
try {
|
|
3439
|
+
title = (await rl.question("Describe the issue in one line: ")).trim();
|
|
3440
|
+
command = (await rl.question("Which command triggered it? (optional): ")).trim();
|
|
3441
|
+
} finally {
|
|
3442
|
+
rl.close();
|
|
3443
|
+
}
|
|
3444
|
+
}
|
|
3445
|
+
const url = buildIssueUrl(title, command, context);
|
|
3446
|
+
if (args.json) {
|
|
3447
|
+
printJson(jsonOk({ url }));
|
|
3448
|
+
return;
|
|
3449
|
+
}
|
|
3450
|
+
process22.stdout.write("\n");
|
|
3451
|
+
info(`Opening: ${url}`);
|
|
3452
|
+
process22.stdout.write("\n");
|
|
3453
|
+
const opened = openBrowser2(url);
|
|
3454
|
+
if (!opened) {
|
|
3455
|
+
process22.stdout.write(`Open this URL to file the issue:
|
|
3456
|
+
${url}
|
|
3202
3457
|
`);
|
|
3458
|
+
}
|
|
3203
3459
|
}
|
|
3204
3460
|
});
|
|
3205
3461
|
|
|
3206
3462
|
// src/cli/error-handler.ts
|
|
3207
|
-
import
|
|
3463
|
+
import process23 from "process";
|
|
3208
3464
|
function handleError(err) {
|
|
3209
3465
|
if (err instanceof ClawopsError) {
|
|
3210
3466
|
failure(err.message);
|
|
3211
|
-
|
|
3467
|
+
process23.exit(err.exitCode);
|
|
3212
3468
|
}
|
|
3213
3469
|
if (err instanceof Error) {
|
|
3214
3470
|
failure(`Unexpected error: ${err.message}`);
|
|
3215
|
-
if (
|
|
3216
|
-
|
|
3471
|
+
if (process23.env["DEBUG"]) {
|
|
3472
|
+
process23.stderr.write(err.stack ?? "\n");
|
|
3217
3473
|
}
|
|
3218
|
-
|
|
3474
|
+
process23.exit(1);
|
|
3219
3475
|
}
|
|
3220
3476
|
failure(`Unknown error: ${String(err)}`);
|
|
3221
|
-
|
|
3477
|
+
process23.exit(1);
|
|
3222
3478
|
}
|
|
3223
3479
|
|
|
3224
3480
|
// src/cli/index.ts
|
|
3225
|
-
var main =
|
|
3481
|
+
var main = defineCommand22({
|
|
3226
3482
|
meta: {
|
|
3227
3483
|
name: "clawops",
|
|
3228
3484
|
description: "Deploy and manage self-hosted OpenClaw instances across clouds",
|
|
@@ -3258,7 +3514,8 @@ var main = defineCommand21({
|
|
|
3258
3514
|
setup: setup_default,
|
|
3259
3515
|
secret: secret_default,
|
|
3260
3516
|
monitor: monitor_default,
|
|
3261
|
-
help: help_default
|
|
3517
|
+
help: help_default,
|
|
3518
|
+
bug: bug_default
|
|
3262
3519
|
}
|
|
3263
3520
|
});
|
|
3264
3521
|
try {
|
package/dist/errors-OK47MQFD.js
CHANGED
|
File without changes
|