@clawops/cli 1.5.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 +1 -0
- package/dist/{apply-5RREMN3L.js → apply-SI3JKS4Z.js} +2 -2
- 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-IVX62LFO.js → chunk-72FF7IK2.js} +2 -2
- package/dist/{chunk-R5S6IXBE.js → chunk-C5NDLOK2.js} +6 -5
- package/dist/{chunk-4U3LTLWZ.js → chunk-GJEF6UQA.js} +1 -0
- package/dist/{chunk-ZVOEQCNW.js → chunk-LCKD7L7X.js} +1 -1
- 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/cli.js +171 -55
- package/dist/{context-PSGEX2D7.js → context-KPKBOWOP.js} +1 -1
- package/dist/firewall-XQGO7HWK.js +51 -0
- package/dist/{gcp-BXDTC6EK.js → gcp-6FT2A45S.js} +14 -63
- package/dist/{generate-2QGKYR42.js → generate-YV7226Q7.js} +2 -2
- package/dist/{package-QLDA65A3.js → package-EW3FS257.js} +1 -1
- package/dist/{pool-FBFHATDG.js → pool-JZGKPP6K.js} +2 -2
- package/dist/{server-LOL2NUJ2.js → server-3DEZHUWB.js} +9 -9
- package/dist/{ssh-IQXNME3D.js → ssh-E2AMBPZY.js} +1 -1
- package/package.json +1 -1
- package/dist/firewall-YYDOWDDP.js +0 -36
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ 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,
|
|
@@ -14,10 +15,10 @@ import {
|
|
|
14
15
|
success,
|
|
15
16
|
validateOpenclawConfig,
|
|
16
17
|
warn
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-C5NDLOK2.js";
|
|
19
|
+
import "./chunk-QI75OVJK.js";
|
|
20
|
+
import "./chunk-LCKD7L7X.js";
|
|
21
|
+
import "./chunk-GJEF6UQA.js";
|
|
21
22
|
import "./chunk-ZFNPM2WG.js";
|
|
22
23
|
import "./chunk-A2I76FTA.js";
|
|
23
24
|
import {
|
|
@@ -32,7 +33,7 @@ import {
|
|
|
32
33
|
} from "./chunk-KGXPLI7W.js";
|
|
33
34
|
|
|
34
35
|
// src/cli/index.ts
|
|
35
|
-
import { defineCommand as
|
|
36
|
+
import { defineCommand as defineCommand22, runMain } from "citty";
|
|
36
37
|
|
|
37
38
|
// src/cli/commands/init.ts
|
|
38
39
|
import { defineCommand } from "citty";
|
|
@@ -204,7 +205,7 @@ var up_default = defineCommand2({
|
|
|
204
205
|
config: { type: "string", description: "Path to openclaw config overlay JSON (local provider only)" }
|
|
205
206
|
},
|
|
206
207
|
async run({ args }) {
|
|
207
|
-
const { buildContext } = await import("./context-
|
|
208
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
208
209
|
const ctx = buildContext(args);
|
|
209
210
|
const openclawVersion = typeof args["openclaw-version"] === "string" ? args["openclaw-version"] : "stable";
|
|
210
211
|
if (ctx.adapter.name === "local") {
|
|
@@ -215,7 +216,7 @@ var up_default = defineCommand2({
|
|
|
215
216
|
);
|
|
216
217
|
}
|
|
217
218
|
const { localOpts } = stackConfig;
|
|
218
|
-
const { localBootstrap } = await import("./bootstrap-
|
|
219
|
+
const { localBootstrap } = await import("./bootstrap-RY4VOSDJ.js");
|
|
219
220
|
const abortController = new AbortController();
|
|
220
221
|
process3.on("SIGINT", () => abortController.abort());
|
|
221
222
|
process3.on("SIGTERM", () => abortController.abort());
|
|
@@ -308,7 +309,7 @@ var up_default = defineCommand2({
|
|
|
308
309
|
}
|
|
309
310
|
});
|
|
310
311
|
async function applyLocalConfigOverlay(opts) {
|
|
311
|
-
const { connect } = await import("./ssh-
|
|
312
|
+
const { connect } = await import("./ssh-E2AMBPZY.js");
|
|
312
313
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
313
314
|
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
314
315
|
let overlay;
|
|
@@ -350,7 +351,7 @@ var down_default = defineCommand3({
|
|
|
350
351
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
351
352
|
},
|
|
352
353
|
async run({ args }) {
|
|
353
|
-
const { buildContext } = await import("./context-
|
|
354
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
354
355
|
const ctx = buildContext(args);
|
|
355
356
|
if (args["dry-run"]) {
|
|
356
357
|
info(`Dry run \u2014 would destroy stack "${ctx.stackName}"`);
|
|
@@ -414,7 +415,7 @@ var status_default = defineCommand4({
|
|
|
414
415
|
json: { type: "boolean", description: "Emit JSON" }
|
|
415
416
|
},
|
|
416
417
|
async run({ args }) {
|
|
417
|
-
const { buildContext } = await import("./context-
|
|
418
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
418
419
|
const ctx = buildContext(args);
|
|
419
420
|
if (ctx.adapter.name === "local") {
|
|
420
421
|
const state = ctx.localState;
|
|
@@ -486,8 +487,8 @@ var plan_default = defineCommand5({
|
|
|
486
487
|
out: { type: "string", description: "Write plan JSON to this absolute path (default: stdout)" }
|
|
487
488
|
},
|
|
488
489
|
async run({ args }) {
|
|
489
|
-
const { buildContext } = await import("./context-
|
|
490
|
-
const { generatePlan } = await import("./generate-
|
|
490
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
491
|
+
const { generatePlan } = await import("./generate-YV7226Q7.js");
|
|
491
492
|
const ctx = buildContext(args);
|
|
492
493
|
if (ctx.adapter.name === "local") {
|
|
493
494
|
throw new UsageError(
|
|
@@ -577,7 +578,7 @@ var apply_default = defineCommand6({
|
|
|
577
578
|
},
|
|
578
579
|
async run({ args }) {
|
|
579
580
|
const { validatePlan } = await import("./validate-T5M5EHSJ.js");
|
|
580
|
-
const { applyPlan } = await import("./apply-
|
|
581
|
+
const { applyPlan } = await import("./apply-SI3JKS4Z.js");
|
|
581
582
|
const planPath = args._?.[0];
|
|
582
583
|
if (!planPath) {
|
|
583
584
|
throw new UsageError("Usage: clawops apply <plan.json>");
|
|
@@ -693,7 +694,7 @@ var destroy_default = defineCommand7({
|
|
|
693
694
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
694
695
|
},
|
|
695
696
|
async run({ args }) {
|
|
696
|
-
const { buildContext } = await import("./context-
|
|
697
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
697
698
|
const ctx = buildContext(args);
|
|
698
699
|
if (ctx.adapter.name === "local") {
|
|
699
700
|
throw new UsageError(
|
|
@@ -760,8 +761,8 @@ var ssh_default = defineCommand8({
|
|
|
760
761
|
command: { type: "string", description: "Remote command to run (instead of interactive shell)" }
|
|
761
762
|
},
|
|
762
763
|
async run({ args }) {
|
|
763
|
-
const { buildContext } = await import("./context-
|
|
764
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
764
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
765
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
765
766
|
const ctx = buildContext(args);
|
|
766
767
|
let conn;
|
|
767
768
|
if (ctx.adapter.name === "local") {
|
|
@@ -847,9 +848,9 @@ var tunnel_default = defineCommand9({
|
|
|
847
848
|
"no-open": { type: "boolean", description: "Do not open browser after tunnel is ready" }
|
|
848
849
|
},
|
|
849
850
|
async run({ args }) {
|
|
850
|
-
const { buildContext } = await import("./context-
|
|
851
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
851
852
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
852
|
-
const { acquireSession } = await import("./pool-
|
|
853
|
+
const { acquireSession } = await import("./pool-JZGKPP6K.js");
|
|
853
854
|
const ctx = buildContext(args);
|
|
854
855
|
const stack = await ctx.getStack();
|
|
855
856
|
const outputMap = await stack.outputs();
|
|
@@ -915,9 +916,9 @@ var logs_default = defineCommand10({
|
|
|
915
916
|
since: { type: "string", description: "Show logs since duration (e.g. 5m, 1h)" }
|
|
916
917
|
},
|
|
917
918
|
async run({ args }) {
|
|
918
|
-
const { buildContext } = await import("./context-
|
|
919
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
919
920
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
920
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
921
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
921
922
|
const ctx = buildContext(args);
|
|
922
923
|
const stack = await ctx.getStack();
|
|
923
924
|
const outputMap = await stack.outputs();
|
|
@@ -1032,9 +1033,9 @@ var config_default = defineCommand11({
|
|
|
1032
1033
|
"dry-run": { type: "boolean", description: "Show what would change without writing" }
|
|
1033
1034
|
},
|
|
1034
1035
|
async run({ args }) {
|
|
1035
|
-
const { buildContext } = await import("./context-
|
|
1036
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1036
1037
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1037
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1038
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1038
1039
|
const [action, key, value] = args._ ?? [];
|
|
1039
1040
|
if (!action || !["get", "set", "unset", "validate"].includes(action)) {
|
|
1040
1041
|
failure("Usage: clawops config <get [key] | set key value | unset key | validate>");
|
|
@@ -1158,9 +1159,9 @@ var agents_default = defineCommand12({
|
|
|
1158
1159
|
json: { type: "boolean", description: "Emit JSON (for list)" }
|
|
1159
1160
|
},
|
|
1160
1161
|
async run({ args }) {
|
|
1161
|
-
const { buildContext } = await import("./context-
|
|
1162
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1162
1163
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1163
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1164
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1164
1165
|
const [action, name] = args._ ?? [];
|
|
1165
1166
|
if (!action || !["list", "restart", "logs"].includes(action)) {
|
|
1166
1167
|
failure("Usage: clawops agents <list | restart [name] | logs <name>>");
|
|
@@ -1262,9 +1263,9 @@ var gateway_default = defineCommand13({
|
|
|
1262
1263
|
json: { type: "boolean", description: "Emit JSON (for status)" }
|
|
1263
1264
|
},
|
|
1264
1265
|
async run({ args }) {
|
|
1265
|
-
const { buildContext } = await import("./context-
|
|
1266
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1266
1267
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1267
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1268
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1268
1269
|
const [action, versionArg] = args._ ?? [];
|
|
1269
1270
|
if (!action || !["status", "restart", "update"].includes(action)) {
|
|
1270
1271
|
failure("Usage: clawops gateway <status | restart | update [version]>");
|
|
@@ -1375,8 +1376,8 @@ var backup_default = defineCommand14({
|
|
|
1375
1376
|
yes: { type: "boolean", description: "[restore] Skip confirmation prompt" }
|
|
1376
1377
|
},
|
|
1377
1378
|
async run({ args }) {
|
|
1378
|
-
const { buildContext } = await import("./context-
|
|
1379
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1379
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1380
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1380
1381
|
const action = args.action;
|
|
1381
1382
|
if (action !== "create" && action !== "restore") {
|
|
1382
1383
|
throw new UsageError(`Unknown action: ${action}. Use "create" or "restore"`);
|
|
@@ -1548,7 +1549,7 @@ var stacks_default = defineCommand15({
|
|
|
1548
1549
|
let isDeployed = false;
|
|
1549
1550
|
if (!args.force) {
|
|
1550
1551
|
try {
|
|
1551
|
-
const { buildContext } = await import("./context-
|
|
1552
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1552
1553
|
const ctx = buildContext({ stack: name });
|
|
1553
1554
|
if (ctx.adapter.name === "local") {
|
|
1554
1555
|
isDeployed = !!ctx.localState;
|
|
@@ -1669,9 +1670,9 @@ var doctor_default = defineCommand16({
|
|
|
1669
1670
|
info("Credential checks skipped \u2014 no config");
|
|
1670
1671
|
} else {
|
|
1671
1672
|
const { getProvider } = await import("./providers-2OABPW2E.js");
|
|
1672
|
-
await import("./aws-
|
|
1673
|
-
await import("./gcp-
|
|
1674
|
-
await import("./azure-
|
|
1673
|
+
await import("./aws-D7Y6LCGK.js");
|
|
1674
|
+
await import("./gcp-6FT2A45S.js");
|
|
1675
|
+
await import("./azure-JQAMNVHN.js");
|
|
1675
1676
|
await import("./local-DXBEVZ5C.js");
|
|
1676
1677
|
const checkedProviders = /* @__PURE__ */ new Set();
|
|
1677
1678
|
for (const [stackName, stackCfg] of Object.entries(config.stacks)) {
|
|
@@ -1706,9 +1707,9 @@ var doctor_default = defineCommand16({
|
|
|
1706
1707
|
info("Remote health skipped \u2014 no config");
|
|
1707
1708
|
} else {
|
|
1708
1709
|
try {
|
|
1709
|
-
const { buildContext } = await import("./context-
|
|
1710
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1710
1711
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1711
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1712
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1712
1713
|
const ctx = buildContext({ stack: args.stack });
|
|
1713
1714
|
const stack = await ctx.getStack();
|
|
1714
1715
|
const outputMap = await stack.outputs();
|
|
@@ -1793,7 +1794,14 @@ var doctor_default = defineCommand16({
|
|
|
1793
1794
|
}
|
|
1794
1795
|
}
|
|
1795
1796
|
process18.stdout.write("\n");
|
|
1796
|
-
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
|
+
}
|
|
1797
1805
|
}
|
|
1798
1806
|
});
|
|
1799
1807
|
|
|
@@ -1814,7 +1822,7 @@ var serveCmd = defineCommand17({
|
|
|
1814
1822
|
inspector: { type: "boolean", description: "Enable MCP inspector" }
|
|
1815
1823
|
},
|
|
1816
1824
|
async run({ args }) {
|
|
1817
|
-
const { serveMcp } = await import("./server-
|
|
1825
|
+
const { serveMcp } = await import("./server-3DEZHUWB.js");
|
|
1818
1826
|
await serveMcp({
|
|
1819
1827
|
port: args.http ? Number(args.http) : void 0,
|
|
1820
1828
|
bind: args.bind,
|
|
@@ -1889,8 +1897,8 @@ var wireCmd = defineCommand17({
|
|
|
1889
1897
|
force: { type: "boolean", description: "Apply even if gateway version is below minimum" }
|
|
1890
1898
|
},
|
|
1891
1899
|
async run({ args }) {
|
|
1892
|
-
const { buildContext } = await import("./context-
|
|
1893
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
1900
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
1901
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
1894
1902
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1895
1903
|
const { wireGatewayMcp } = await import("./mcp-wire-ZWIYMLEW.js");
|
|
1896
1904
|
const ac = new AbortController();
|
|
@@ -2404,7 +2412,7 @@ var setup_default = defineCommand18({
|
|
|
2404
2412
|
default: false
|
|
2405
2413
|
}]);
|
|
2406
2414
|
if (applyNow) {
|
|
2407
|
-
const { applyPlan } = await import("./apply-
|
|
2415
|
+
const { applyPlan } = await import("./apply-SI3JKS4Z.js");
|
|
2408
2416
|
const plan = JSON.parse(readFileSync3(outputPath, "utf-8"));
|
|
2409
2417
|
try {
|
|
2410
2418
|
await applyPlan(plan, {
|
|
@@ -2427,8 +2435,8 @@ To deploy later: clawops apply ${outputPath}`);
|
|
|
2427
2435
|
});
|
|
2428
2436
|
async function runLocalDeploy(opts) {
|
|
2429
2437
|
const { setConfig: setConfig2, getConfig: getConfig2, getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
|
|
2430
|
-
const { localBootstrap } = await import("./bootstrap-
|
|
2431
|
-
const { connect } = await import("./ssh-
|
|
2438
|
+
const { localBootstrap } = await import("./bootstrap-RY4VOSDJ.js");
|
|
2439
|
+
const { connect } = await import("./ssh-E2AMBPZY.js");
|
|
2432
2440
|
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
2433
2441
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
2434
2442
|
const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
|
|
@@ -2510,7 +2518,7 @@ async function runLocalDeploy(opts) {
|
|
|
2510
2518
|
spin2.fail("Configuration failed");
|
|
2511
2519
|
throw err;
|
|
2512
2520
|
}
|
|
2513
|
-
const { drainPool } = await import("./pool-
|
|
2521
|
+
const { drainPool } = await import("./pool-JZGKPP6K.js");
|
|
2514
2522
|
drainPool();
|
|
2515
2523
|
const tokenPath = path3.join(os.homedir(), ".clawops", "secrets", `GATEWAY_TOKEN_${opts.stackName}`);
|
|
2516
2524
|
const dashboardUrl = `${state.gatewayUrl}?token=${opts.gatewayToken}`;
|
|
@@ -2648,7 +2656,7 @@ var DOCKER_CHECK_CMD = [
|
|
|
2648
2656
|
"echo NOT_RUNNING"
|
|
2649
2657
|
].join("; ");
|
|
2650
2658
|
async function checkDockerPreflight(opts) {
|
|
2651
|
-
const { acquireSession } = await import("./pool-
|
|
2659
|
+
const { acquireSession } = await import("./pool-JZGKPP6K.js");
|
|
2652
2660
|
const { ProviderError } = await import("./errors-OK47MQFD.js");
|
|
2653
2661
|
const spin = spinner("Checking Docker on target host...");
|
|
2654
2662
|
const timeoutSignal = AbortSignal.timeout(DOCKER_PREFLIGHT_TIMEOUT_MS);
|
|
@@ -2695,7 +2703,7 @@ async function checkDockerPreflight(opts) {
|
|
|
2695
2703
|
var DOCKER_POLL_MS = 3e3;
|
|
2696
2704
|
var DOCKER_TIMEOUT_MS = 9e4;
|
|
2697
2705
|
async function startRemoteDocker(opts, spin) {
|
|
2698
|
-
const { acquireSession } = await import("./pool-
|
|
2706
|
+
const { acquireSession } = await import("./pool-JZGKPP6K.js");
|
|
2699
2707
|
const { ProviderError } = await import("./errors-OK47MQFD.js");
|
|
2700
2708
|
spin.text = "Starting Docker on the remote server...";
|
|
2701
2709
|
const { session, release } = await acquireSession({
|
|
@@ -2899,7 +2907,7 @@ async function maybeWireGatewayMcp(opts) {
|
|
|
2899
2907
|
process20.stdout.write("\n");
|
|
2900
2908
|
const { wireGateway } = await inquirerPromptWire(opts.inquirer);
|
|
2901
2909
|
if (!wireGateway) return;
|
|
2902
|
-
const { connect } = await import("./ssh-
|
|
2910
|
+
const { connect } = await import("./ssh-E2AMBPZY.js");
|
|
2903
2911
|
const { getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
|
|
2904
2912
|
const { wireGatewayMcp } = await import("./mcp-wire-ZWIYMLEW.js");
|
|
2905
2913
|
const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
|
|
@@ -3164,10 +3172,10 @@ var rotateCmd = defineCommand19({
|
|
|
3164
3172
|
}
|
|
3165
3173
|
info(`Re-applying config overlay to stack "${targetStack}"\u2026`);
|
|
3166
3174
|
try {
|
|
3167
|
-
const { buildContext } = await import("./context-
|
|
3175
|
+
const { buildContext } = await import("./context-KPKBOWOP.js");
|
|
3168
3176
|
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
3169
3177
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
3170
|
-
const { acquireSession, drainPool } = await import("./pool-
|
|
3178
|
+
const { acquireSession, drainPool } = await import("./pool-JZGKPP6K.js");
|
|
3171
3179
|
const { localStateToConnectionInfo } = await import("./state-PRBIIN7I.js");
|
|
3172
3180
|
const ctx = buildContext({ stack: targetStack });
|
|
3173
3181
|
let conn;
|
|
@@ -3344,26 +3352,133 @@ ${dim("Run `clawops <command> --help` for command-specific flags.")}
|
|
|
3344
3352
|
}
|
|
3345
3353
|
});
|
|
3346
3354
|
|
|
3347
|
-
// src/cli/
|
|
3355
|
+
// src/cli/commands/bug.ts
|
|
3356
|
+
import { defineCommand as defineCommand21 } from "citty";
|
|
3348
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}
|
|
3457
|
+
`);
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
});
|
|
3461
|
+
|
|
3462
|
+
// src/cli/error-handler.ts
|
|
3463
|
+
import process23 from "process";
|
|
3349
3464
|
function handleError(err) {
|
|
3350
3465
|
if (err instanceof ClawopsError) {
|
|
3351
3466
|
failure(err.message);
|
|
3352
|
-
|
|
3467
|
+
process23.exit(err.exitCode);
|
|
3353
3468
|
}
|
|
3354
3469
|
if (err instanceof Error) {
|
|
3355
3470
|
failure(`Unexpected error: ${err.message}`);
|
|
3356
|
-
if (
|
|
3357
|
-
|
|
3471
|
+
if (process23.env["DEBUG"]) {
|
|
3472
|
+
process23.stderr.write(err.stack ?? "\n");
|
|
3358
3473
|
}
|
|
3359
|
-
|
|
3474
|
+
process23.exit(1);
|
|
3360
3475
|
}
|
|
3361
3476
|
failure(`Unknown error: ${String(err)}`);
|
|
3362
|
-
|
|
3477
|
+
process23.exit(1);
|
|
3363
3478
|
}
|
|
3364
3479
|
|
|
3365
3480
|
// src/cli/index.ts
|
|
3366
|
-
var main =
|
|
3481
|
+
var main = defineCommand22({
|
|
3367
3482
|
meta: {
|
|
3368
3483
|
name: "clawops",
|
|
3369
3484
|
description: "Deploy and manage self-hosted OpenClaw instances across clouds",
|
|
@@ -3399,7 +3514,8 @@ var main = defineCommand21({
|
|
|
3399
3514
|
setup: setup_default,
|
|
3400
3515
|
secret: secret_default,
|
|
3401
3516
|
monitor: monitor_default,
|
|
3402
|
-
help: help_default
|
|
3517
|
+
help: help_default,
|
|
3518
|
+
bug: bug_default
|
|
3403
3519
|
}
|
|
3404
3520
|
});
|
|
3405
3521
|
try {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/providers/firewall.ts
|
|
4
|
+
function resolveIngressCidrs(accessMode, allowedCidrs, portOverride, egressResult) {
|
|
5
|
+
if (portOverride.trim()) {
|
|
6
|
+
return portOverride.split(",").map((s) => s.trim()).filter(Boolean);
|
|
7
|
+
}
|
|
8
|
+
switch (accessMode) {
|
|
9
|
+
case "restricted": {
|
|
10
|
+
if (!allowedCidrs.trim()) return [];
|
|
11
|
+
return allowedCidrs.split(",").map((s) => s.trim()).filter(Boolean);
|
|
12
|
+
}
|
|
13
|
+
case "auto": {
|
|
14
|
+
if (!egressResult.ok) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`accessMode=auto: egress IP detection failed \u2014 ${egressResult.error}. Set allowedCidrs explicitly or use accessMode=restricted.`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
const ip = egressResult.ip.trim();
|
|
20
|
+
if (!ip) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`accessMode=auto: egress IP detection returned an empty address. Set allowedCidrs explicitly or use accessMode=restricted.`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return [ip.includes("/") ? ip : `${ip}/32`];
|
|
26
|
+
}
|
|
27
|
+
case "open":
|
|
28
|
+
return ["0.0.0.0/0"];
|
|
29
|
+
default:
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function detectEgressIp(checkUrl) {
|
|
34
|
+
try {
|
|
35
|
+
const res = await fetch(checkUrl, { signal: AbortSignal.timeout(3e3) });
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
return { ok: false, error: `HTTP ${res.status} from ${checkUrl}` };
|
|
38
|
+
}
|
|
39
|
+
const ip = (await res.text()).trim();
|
|
40
|
+
if (!ip) {
|
|
41
|
+
return { ok: false, error: `empty response from ${checkUrl}` };
|
|
42
|
+
}
|
|
43
|
+
return { ok: true, ip };
|
|
44
|
+
} catch (err) {
|
|
45
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
detectEgressIp,
|
|
50
|
+
resolveIngressCidrs
|
|
51
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
makeStartupScript
|
|
4
|
+
} from "./chunk-XKT42M34.js";
|
|
2
5
|
|
|
3
6
|
// src/providers/gcp/index.ts
|
|
4
7
|
import process2 from "process";
|
|
@@ -10,7 +13,7 @@ var gcpProgram = async () => {
|
|
|
10
13
|
const [pulumi, gcp, { resolveIngressCidrs, detectEgressIp }] = await Promise.all([
|
|
11
14
|
import("@pulumi/pulumi"),
|
|
12
15
|
import("@pulumi/gcp"),
|
|
13
|
-
import("./firewall-
|
|
16
|
+
import("./firewall-XQGO7HWK.js")
|
|
14
17
|
]);
|
|
15
18
|
const cfg = new pulumi.Config();
|
|
16
19
|
const instanceType = cfg.get("instanceType") ?? "e2-standard-2";
|
|
@@ -27,14 +30,14 @@ var gcpProgram = async () => {
|
|
|
27
30
|
'Stack config "sshPublicKey" is required for the GCP adapter. Set it with: pulumi config set --stack <name> sshPublicKey "ssh-ed25519 ..."'
|
|
28
31
|
);
|
|
29
32
|
}
|
|
30
|
-
const
|
|
33
|
+
const egressResult = accessMode === "auto" ? await detectEgressIp("https://ifconfig.me") : { ok: true, ip: "" };
|
|
31
34
|
if (accessMode === "open") {
|
|
32
35
|
process.stderr.write(
|
|
33
36
|
"[clawops] WARNING: accessMode=open allows 0.0.0.0/0 on SSH and gateway ports. Only use this for development/sandbox stacks.\n"
|
|
34
37
|
);
|
|
35
38
|
}
|
|
36
|
-
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs,
|
|
37
|
-
const gatewayIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, gatewayCidrs,
|
|
39
|
+
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs, egressResult);
|
|
40
|
+
const gatewayIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, gatewayCidrs, egressResult);
|
|
38
41
|
const network = new gcp.compute.Network("clawops-network", {
|
|
39
42
|
autoCreateSubnetworks: false,
|
|
40
43
|
description: "clawops managed network"
|
|
@@ -42,7 +45,7 @@ var gcpProgram = async () => {
|
|
|
42
45
|
const subnet = new gcp.compute.Subnetwork("clawops-subnet", {
|
|
43
46
|
ipCidrRange: "10.0.0.0/24",
|
|
44
47
|
region,
|
|
45
|
-
network: network.
|
|
48
|
+
network: network.selfLink
|
|
46
49
|
});
|
|
47
50
|
if (sshIngressCidrs.length > 0) {
|
|
48
51
|
new gcp.compute.Firewall("clawops-firewall-ssh", {
|
|
@@ -73,8 +76,8 @@ var gcpProgram = async () => {
|
|
|
73
76
|
},
|
|
74
77
|
networkInterfaces: [
|
|
75
78
|
{
|
|
76
|
-
network: network.
|
|
77
|
-
subnetwork: subnet.
|
|
79
|
+
network: network.selfLink,
|
|
80
|
+
subnetwork: subnet.selfLink,
|
|
78
81
|
accessConfigs: [
|
|
79
82
|
{
|
|
80
83
|
natIp: address.address,
|
|
@@ -86,7 +89,7 @@ var gcpProgram = async () => {
|
|
|
86
89
|
metadata: {
|
|
87
90
|
// GCP guest agent reads 'ssh-keys' and populates /home/<user>/.ssh/authorized_keys
|
|
88
91
|
"ssh-keys": `clawops:${sshPublicKey}`,
|
|
89
|
-
"startup-script": makeStartupScript(openclawVersion)
|
|
92
|
+
"startup-script": makeStartupScript({ openclawVersion, os: "debian" })
|
|
90
93
|
},
|
|
91
94
|
serviceAccount: {
|
|
92
95
|
scopes: ["https://www.googleapis.com/auth/cloud-platform"]
|
|
@@ -103,58 +106,6 @@ var gcpProgram = async () => {
|
|
|
103
106
|
provisionedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
104
107
|
};
|
|
105
108
|
};
|
|
106
|
-
function makeStartupScript(openclawVersion) {
|
|
107
|
-
return `#!/bin/bash
|
|
108
|
-
set -euo pipefail
|
|
109
|
-
|
|
110
|
-
# Create clawops user with SSH access
|
|
111
|
-
id -u clawops &>/dev/null || useradd -m -s /bin/bash clawops
|
|
112
|
-
mkdir -p /home/clawops/.ssh
|
|
113
|
-
chmod 700 /home/clawops/.ssh
|
|
114
|
-
|
|
115
|
-
# Install Docker if not present
|
|
116
|
-
if ! command -v docker &>/dev/null; then
|
|
117
|
-
apt-get update -q
|
|
118
|
-
apt-get install -y -q ca-certificates curl gnupg lsb-release
|
|
119
|
-
install -m 0755 -d /etc/apt/keyrings
|
|
120
|
-
curl -fsSL https://download.docker.com/linux/debian/gpg \\
|
|
121
|
-
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
122
|
-
chmod a+r /etc/apt/keyrings/docker.gpg
|
|
123
|
-
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \\
|
|
124
|
-
https://download.docker.com/linux/debian $(lsb_release -cs) stable" \\
|
|
125
|
-
> /etc/apt/sources.list.d/docker.list
|
|
126
|
-
apt-get update -q
|
|
127
|
-
apt-get install -y -q docker-ce docker-ce-cli containerd.io
|
|
128
|
-
systemctl enable --now docker
|
|
129
|
-
fi
|
|
130
|
-
|
|
131
|
-
usermod -aG docker clawops
|
|
132
|
-
|
|
133
|
-
# Pull OpenClaw image
|
|
134
|
-
OPENCLAW_VERSION="${openclawVersion}"
|
|
135
|
-
docker pull ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION}
|
|
136
|
-
|
|
137
|
-
# Create default openclaw.json if not present
|
|
138
|
-
OPENCLAW_CONFIG=/home/clawops/openclaw.json
|
|
139
|
-
if [ ! -f "\${OPENCLAW_CONFIG}" ]; then
|
|
140
|
-
cat > "\${OPENCLAW_CONFIG}" <<'OPENCLAWJSON'
|
|
141
|
-
{"meta":{"lastTouchedVersion":"2026.4"},"gateway":{"port":18789,"auth":{"mode":"token"}},"models":{},"channels":{}}
|
|
142
|
-
OPENCLAWJSON
|
|
143
|
-
chown clawops:clawops "\${OPENCLAW_CONFIG}"
|
|
144
|
-
fi
|
|
145
|
-
|
|
146
|
-
# Start OpenClaw container
|
|
147
|
-
docker stop openclaw 2>/dev/null || true
|
|
148
|
-
docker rm openclaw 2>/dev/null || true
|
|
149
|
-
docker run -d \\
|
|
150
|
-
--name openclaw \\
|
|
151
|
-
--restart unless-stopped \\
|
|
152
|
-
-p ${GATEWAY_PORT}:${GATEWAY_PORT} \\
|
|
153
|
-
-v "\${OPENCLAW_CONFIG}":/app/config.json:ro \\
|
|
154
|
-
ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION} \\
|
|
155
|
-
node openclaw.mjs gateway run --allow-unconfigured
|
|
156
|
-
`;
|
|
157
|
-
}
|
|
158
109
|
|
|
159
110
|
// src/providers/gcp/index.ts
|
|
160
111
|
var INSTANCE_TYPE_MAP = {
|
|
@@ -172,9 +123,9 @@ var gcpAdapter = {
|
|
|
172
123
|
},
|
|
173
124
|
getConnectionInfo(outputs) {
|
|
174
125
|
return {
|
|
175
|
-
host: String(outputs["sshHost"]),
|
|
176
|
-
port: Number(outputs["sshPort"]),
|
|
177
|
-
user: String(outputs["sshUser"]),
|
|
126
|
+
host: String(outputs["sshHost"] ?? ""),
|
|
127
|
+
port: Number(outputs["sshPort"] ?? 22),
|
|
128
|
+
user: String(outputs["sshUser"] ?? "clawops"),
|
|
178
129
|
privateKeyPath: String(outputs["privateKeyPath"] ?? ""),
|
|
179
130
|
knownHostsPath: String(outputs["knownHostsPath"] ?? "")
|
|
180
131
|
};
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
generatePlan,
|
|
4
4
|
planId
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-72FF7IK2.js";
|
|
6
6
|
import "./chunk-YTH4L2GN.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-QI75OVJK.js";
|
|
8
8
|
import "./chunk-A2I76FTA.js";
|
|
9
9
|
import "./chunk-CX5SL5HP.js";
|
|
10
10
|
import "./chunk-KGXPLI7W.js";
|