@clawops/cli 1.3.0 → 1.4.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 +97 -0
- package/dist/{apply-DLNE2JYZ.js → apply-5RREMN3L.js} +3 -3
- package/dist/{aws-KQBWY43W.js → aws-FRE2JVAZ.js} +9 -4
- package/dist/{azure-4EJFVJZL.js → azure-PVC3AQVC.js} +11 -4
- package/dist/chunk-JYQZJMD3.js +764 -0
- package/dist/{chunk-JDN6PLH2.js → chunk-T5EX55GP.js} +3 -3
- package/dist/{chunk-ZDPBBYYV.js → chunk-UAA6YOOP.js} +2 -2
- package/dist/{chunk-UDNZUSKA.js → chunk-ZFNPM2WG.js} +1 -1
- package/dist/{chunk-JCUZU5BH.js → chunk-ZONXY3C6.js} +2 -2
- package/dist/cli.js +63 -50
- package/dist/{context-M2RMDHX6.js → context-PSGEX2D7.js} +1 -1
- package/dist/{gcp-SKURG3L6.js → gcp-BXDTC6EK.js} +60 -17
- package/dist/{generate-U7PJ5LRG.js → generate-Z7DBMANX.js} +2 -2
- package/dist/{package-AFUTH62F.js → package-WAJRGBBM.js} +2 -1
- package/dist/{remote-config-JQ77SRC2.js → remote-config-QF5TT7GU.js} +1 -1
- package/dist/{server-I62UES5V.js → server-IWLZJ4EU.js} +92 -19
- package/package.json +2 -1
- package/dist/chunk-LVIIYY27.js +0 -266
|
@@ -56,17 +56,17 @@ function makeProviderProxy(name) {
|
|
|
56
56
|
if (resolved) return resolved;
|
|
57
57
|
switch (name) {
|
|
58
58
|
case "gcp": {
|
|
59
|
-
const mod = await import("./gcp-
|
|
59
|
+
const mod = await import("./gcp-BXDTC6EK.js");
|
|
60
60
|
resolved = mod.default;
|
|
61
61
|
return resolved;
|
|
62
62
|
}
|
|
63
63
|
case "aws": {
|
|
64
|
-
const mod = await import("./aws-
|
|
64
|
+
const mod = await import("./aws-FRE2JVAZ.js");
|
|
65
65
|
resolved = mod.default;
|
|
66
66
|
return resolved;
|
|
67
67
|
}
|
|
68
68
|
case "azure": {
|
|
69
|
-
const mod = await import("./azure-
|
|
69
|
+
const mod = await import("./azure-PVC3AQVC.js");
|
|
70
70
|
resolved = mod.default;
|
|
71
71
|
return resolved;
|
|
72
72
|
}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-YTH4L2GN.js";
|
|
5
5
|
import {
|
|
6
6
|
buildContext
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-T5EX55GP.js";
|
|
8
8
|
import {
|
|
9
9
|
getConfig
|
|
10
10
|
} from "./chunk-CX5SL5HP.js";
|
|
@@ -45,7 +45,7 @@ async function generatePlan(intent, _opts) {
|
|
|
45
45
|
"plan/apply is not supported for the local provider. Use `clawops up` directly."
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
|
-
const { version } = await import("./package-
|
|
48
|
+
const { version } = await import("./package-WAJRGBBM.js");
|
|
49
49
|
const config = getConfig();
|
|
50
50
|
const instanceType = intent.instanceType ?? "small";
|
|
51
51
|
const openclawVersion = intent.openclawVersion ?? "latest";
|
|
@@ -20,7 +20,7 @@ async function execWithFallbackSudo(session, cmd, signal) {
|
|
|
20
20
|
async function readRemoteConfig(session, signal) {
|
|
21
21
|
const os = await detectOS(session, signal);
|
|
22
22
|
const configPath = configPathForOS(os);
|
|
23
|
-
const result = await session.exec(`cat ${configPath}`, signal);
|
|
23
|
+
const result = os === "Darwin" ? await session.exec(`cat ${configPath}`, signal) : await execWithFallbackSudo(session, `cat ${configPath}`, signal);
|
|
24
24
|
if (result.code !== 0) {
|
|
25
25
|
throw new Error(`Cannot read ${configPath}: ${result.stderr}`);
|
|
26
26
|
}
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
} from "./chunk-BOPSG2LI.js";
|
|
11
11
|
import {
|
|
12
12
|
buildContext
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-T5EX55GP.js";
|
|
14
14
|
import {
|
|
15
15
|
atomicWriteConfig,
|
|
16
16
|
deepMerge,
|
|
17
17
|
readRemoteConfig,
|
|
18
18
|
restartGateway
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-ZFNPM2WG.js";
|
|
20
20
|
import {
|
|
21
21
|
UsageError
|
|
22
22
|
} from "./chunk-KGXPLI7W.js";
|
package/dist/cli.js
CHANGED
|
@@ -5,12 +5,19 @@ import {
|
|
|
5
5
|
writeAppConfigs
|
|
6
6
|
} from "./chunk-OIGTOLB3.js";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
chalk,
|
|
9
|
+
failure,
|
|
10
|
+
info,
|
|
11
|
+
monitor_default,
|
|
12
|
+
spinner,
|
|
13
|
+
success,
|
|
14
|
+
validateOpenclawConfig,
|
|
15
|
+
warn
|
|
16
|
+
} from "./chunk-JYQZJMD3.js";
|
|
17
|
+
import "./chunk-T5EX55GP.js";
|
|
11
18
|
import "./chunk-ZVOEQCNW.js";
|
|
12
19
|
import "./chunk-4U3LTLWZ.js";
|
|
13
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-ZFNPM2WG.js";
|
|
14
21
|
import "./chunk-A2I76FTA.js";
|
|
15
22
|
import {
|
|
16
23
|
getConfig,
|
|
@@ -32,27 +39,6 @@ import { generateKeyPairSync } from "crypto";
|
|
|
32
39
|
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
33
40
|
import path from "path";
|
|
34
41
|
import process2 from "process";
|
|
35
|
-
|
|
36
|
-
// src/output/human.ts
|
|
37
|
-
import chalk from "chalk";
|
|
38
|
-
import ora from "ora";
|
|
39
|
-
function success(msg) {
|
|
40
|
-
console.log(chalk.green("\u2713") + " " + msg);
|
|
41
|
-
}
|
|
42
|
-
function failure(msg) {
|
|
43
|
-
console.error(chalk.red("\u2717") + " " + msg);
|
|
44
|
-
}
|
|
45
|
-
function warn(msg) {
|
|
46
|
-
console.warn(chalk.yellow("\u26A0") + " " + msg);
|
|
47
|
-
}
|
|
48
|
-
function info(msg) {
|
|
49
|
-
console.log(chalk.blue("\u2139") + " " + msg);
|
|
50
|
-
}
|
|
51
|
-
function spinner(text) {
|
|
52
|
-
return ora(text).start();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// src/cli/commands/init.ts
|
|
56
42
|
var SUPPORTED_PROVIDERS = ["gcp", "aws", "azure", "local"];
|
|
57
43
|
var PROVIDER_DEFAULTS = {
|
|
58
44
|
gcp: { region: "us-central1", credEnv: "GOOGLE_APPLICATION_CREDENTIALS", stateScheme: "gs://" },
|
|
@@ -217,7 +203,7 @@ var up_default = defineCommand2({
|
|
|
217
203
|
config: { type: "string", description: "Path to openclaw config overlay JSON (local provider only)" }
|
|
218
204
|
},
|
|
219
205
|
async run({ args }) {
|
|
220
|
-
const { buildContext } = await import("./context-
|
|
206
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
221
207
|
const ctx = buildContext(args);
|
|
222
208
|
const openclawVersion = typeof args["openclaw-version"] === "string" ? args["openclaw-version"] : "stable";
|
|
223
209
|
if (ctx.adapter.name === "local") {
|
|
@@ -323,7 +309,7 @@ var up_default = defineCommand2({
|
|
|
323
309
|
async function applyLocalConfigOverlay(opts) {
|
|
324
310
|
const { connect } = await import("./ssh-IQXNME3D.js");
|
|
325
311
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
326
|
-
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-
|
|
312
|
+
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
327
313
|
let overlay;
|
|
328
314
|
try {
|
|
329
315
|
overlay = JSON.parse(readFileSync(opts.configPath, "utf-8"));
|
|
@@ -363,7 +349,7 @@ var down_default = defineCommand3({
|
|
|
363
349
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
364
350
|
},
|
|
365
351
|
async run({ args }) {
|
|
366
|
-
const { buildContext } = await import("./context-
|
|
352
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
367
353
|
const ctx = buildContext(args);
|
|
368
354
|
if (args["dry-run"]) {
|
|
369
355
|
info(`Dry run \u2014 would destroy stack "${ctx.stackName}"`);
|
|
@@ -427,7 +413,7 @@ var status_default = defineCommand4({
|
|
|
427
413
|
json: { type: "boolean", description: "Emit JSON" }
|
|
428
414
|
},
|
|
429
415
|
async run({ args }) {
|
|
430
|
-
const { buildContext } = await import("./context-
|
|
416
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
431
417
|
const ctx = buildContext(args);
|
|
432
418
|
if (ctx.adapter.name === "local") {
|
|
433
419
|
const state = ctx.localState;
|
|
@@ -499,8 +485,8 @@ var plan_default = defineCommand5({
|
|
|
499
485
|
out: { type: "string", description: "Write plan JSON to this absolute path (default: stdout)" }
|
|
500
486
|
},
|
|
501
487
|
async run({ args }) {
|
|
502
|
-
const { buildContext } = await import("./context-
|
|
503
|
-
const { generatePlan } = await import("./generate-
|
|
488
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
489
|
+
const { generatePlan } = await import("./generate-Z7DBMANX.js");
|
|
504
490
|
const ctx = buildContext(args);
|
|
505
491
|
if (ctx.adapter.name === "local") {
|
|
506
492
|
throw new UsageError(
|
|
@@ -590,7 +576,7 @@ var apply_default = defineCommand6({
|
|
|
590
576
|
},
|
|
591
577
|
async run({ args }) {
|
|
592
578
|
const { validatePlan } = await import("./validate-T5M5EHSJ.js");
|
|
593
|
-
const { applyPlan } = await import("./apply-
|
|
579
|
+
const { applyPlan } = await import("./apply-5RREMN3L.js");
|
|
594
580
|
const planPath = args._?.[0];
|
|
595
581
|
if (!planPath) {
|
|
596
582
|
throw new UsageError("Usage: clawops apply <plan.json>");
|
|
@@ -706,7 +692,7 @@ var destroy_default = defineCommand7({
|
|
|
706
692
|
"dry-run": { type: "boolean", description: "Show what would be destroyed without destroying" }
|
|
707
693
|
},
|
|
708
694
|
async run({ args }) {
|
|
709
|
-
const { buildContext } = await import("./context-
|
|
695
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
710
696
|
const ctx = buildContext(args);
|
|
711
697
|
if (ctx.adapter.name === "local") {
|
|
712
698
|
throw new UsageError(
|
|
@@ -773,7 +759,7 @@ var ssh_default = defineCommand8({
|
|
|
773
759
|
command: { type: "string", description: "Remote command to run (instead of interactive shell)" }
|
|
774
760
|
},
|
|
775
761
|
async run({ args }) {
|
|
776
|
-
const { buildContext } = await import("./context-
|
|
762
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
777
763
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
778
764
|
const ctx = buildContext(args);
|
|
779
765
|
let conn;
|
|
@@ -860,7 +846,7 @@ var tunnel_default = defineCommand9({
|
|
|
860
846
|
"no-open": { type: "boolean", description: "Do not open browser after tunnel is ready" }
|
|
861
847
|
},
|
|
862
848
|
async run({ args }) {
|
|
863
|
-
const { buildContext } = await import("./context-
|
|
849
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
864
850
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
865
851
|
const { acquireSession } = await import("./pool-FBFHATDG.js");
|
|
866
852
|
const ctx = buildContext(args);
|
|
@@ -928,7 +914,7 @@ var logs_default = defineCommand10({
|
|
|
928
914
|
since: { type: "string", description: "Show logs since duration (e.g. 5m, 1h)" }
|
|
929
915
|
},
|
|
930
916
|
async run({ args }) {
|
|
931
|
-
const { buildContext } = await import("./context-
|
|
917
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
932
918
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
933
919
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
934
920
|
const ctx = buildContext(args);
|
|
@@ -1045,7 +1031,7 @@ var config_default = defineCommand11({
|
|
|
1045
1031
|
"dry-run": { type: "boolean", description: "Show what would change without writing" }
|
|
1046
1032
|
},
|
|
1047
1033
|
async run({ args }) {
|
|
1048
|
-
const { buildContext } = await import("./context-
|
|
1034
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
1049
1035
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1050
1036
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
1051
1037
|
const [action, key, value] = args._ ?? [];
|
|
@@ -1171,7 +1157,7 @@ var agents_default = defineCommand12({
|
|
|
1171
1157
|
json: { type: "boolean", description: "Emit JSON (for list)" }
|
|
1172
1158
|
},
|
|
1173
1159
|
async run({ args }) {
|
|
1174
|
-
const { buildContext } = await import("./context-
|
|
1160
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
1175
1161
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1176
1162
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
1177
1163
|
const [action, name] = args._ ?? [];
|
|
@@ -1275,7 +1261,7 @@ var gateway_default = defineCommand13({
|
|
|
1275
1261
|
json: { type: "boolean", description: "Emit JSON (for status)" }
|
|
1276
1262
|
},
|
|
1277
1263
|
async run({ args }) {
|
|
1278
|
-
const { buildContext } = await import("./context-
|
|
1264
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
1279
1265
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1280
1266
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
1281
1267
|
const [action, versionArg] = args._ ?? [];
|
|
@@ -1388,7 +1374,7 @@ var backup_default = defineCommand14({
|
|
|
1388
1374
|
yes: { type: "boolean", description: "[restore] Skip confirmation prompt" }
|
|
1389
1375
|
},
|
|
1390
1376
|
async run({ args }) {
|
|
1391
|
-
const { buildContext } = await import("./context-
|
|
1377
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
1392
1378
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
1393
1379
|
const action = args.action;
|
|
1394
1380
|
if (action !== "create" && action !== "restore") {
|
|
@@ -1500,7 +1486,7 @@ var stacks_default = defineCommand15({
|
|
|
1500
1486
|
args: {
|
|
1501
1487
|
json: { type: "boolean", description: "Emit JSON (for list)" },
|
|
1502
1488
|
yes: { type: "boolean", description: "Skip confirmation prompt on delete" },
|
|
1503
|
-
force: { type: "boolean", description: "
|
|
1489
|
+
force: { type: "boolean", description: "Skip safety checks (allow deleting default or still-deployed stacks)" }
|
|
1504
1490
|
},
|
|
1505
1491
|
async run({ args }) {
|
|
1506
1492
|
const [action, name] = args._ ?? [];
|
|
@@ -1558,6 +1544,31 @@ var stacks_default = defineCommand15({
|
|
|
1558
1544
|
`"${name}" is the default stack. Use --force to delete it (clawops will switch the default to another stack).`
|
|
1559
1545
|
);
|
|
1560
1546
|
}
|
|
1547
|
+
let isDeployed = false;
|
|
1548
|
+
if (!args.force) {
|
|
1549
|
+
try {
|
|
1550
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
1551
|
+
const ctx = buildContext({ stack: name });
|
|
1552
|
+
if (ctx.adapter.name === "local") {
|
|
1553
|
+
isDeployed = !!ctx.localState;
|
|
1554
|
+
} else {
|
|
1555
|
+
const stack = await ctx.getStack();
|
|
1556
|
+
const outputMap = await stack.outputs();
|
|
1557
|
+
const outputs = Object.fromEntries(
|
|
1558
|
+
Object.entries(outputMap).map(([k, v]) => [k, v.value])
|
|
1559
|
+
);
|
|
1560
|
+
isDeployed = !!outputs["publicIp"];
|
|
1561
|
+
}
|
|
1562
|
+
} catch {
|
|
1563
|
+
warn(`Could not verify deployment status for "${name}" \u2014 proceeding anyway.`);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
if (isDeployed) {
|
|
1567
|
+
failure(
|
|
1568
|
+
`Stack "${name}" is still deployed. Run \`clawops down --stack ${name}\` first to destroy cloud resources, or pass --force to remove from registry only.`
|
|
1569
|
+
);
|
|
1570
|
+
process17.exit(1);
|
|
1571
|
+
}
|
|
1561
1572
|
warn(
|
|
1562
1573
|
`This removes "${name}" from clawops config only. Cloud resources are NOT destroyed. Run \`clawops destroy --stack ` + name + "` first if you want to remove cloud resources."
|
|
1563
1574
|
);
|
|
@@ -1657,9 +1668,9 @@ var doctor_default = defineCommand16({
|
|
|
1657
1668
|
info("Credential checks skipped \u2014 no config");
|
|
1658
1669
|
} else {
|
|
1659
1670
|
const { getProvider } = await import("./providers-2OABPW2E.js");
|
|
1660
|
-
await import("./aws-
|
|
1661
|
-
await import("./gcp-
|
|
1662
|
-
await import("./azure-
|
|
1671
|
+
await import("./aws-FRE2JVAZ.js");
|
|
1672
|
+
await import("./gcp-BXDTC6EK.js");
|
|
1673
|
+
await import("./azure-PVC3AQVC.js");
|
|
1663
1674
|
await import("./local-DXBEVZ5C.js");
|
|
1664
1675
|
const checkedProviders = /* @__PURE__ */ new Set();
|
|
1665
1676
|
for (const [stackName, stackCfg] of Object.entries(config.stacks)) {
|
|
@@ -1694,7 +1705,7 @@ var doctor_default = defineCommand16({
|
|
|
1694
1705
|
info("Remote health skipped \u2014 no config");
|
|
1695
1706
|
} else {
|
|
1696
1707
|
try {
|
|
1697
|
-
const { buildContext } = await import("./context-
|
|
1708
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
1698
1709
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
1699
1710
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
1700
1711
|
const ctx = buildContext({ stack: args.stack });
|
|
@@ -1802,7 +1813,7 @@ var serveCmd = defineCommand17({
|
|
|
1802
1813
|
inspector: { type: "boolean", description: "Enable MCP inspector" }
|
|
1803
1814
|
},
|
|
1804
1815
|
async run({ args }) {
|
|
1805
|
-
const { serveMcp } = await import("./server-
|
|
1816
|
+
const { serveMcp } = await import("./server-IWLZJ4EU.js");
|
|
1806
1817
|
await serveMcp({
|
|
1807
1818
|
port: args.http ? Number(args.http) : void 0,
|
|
1808
1819
|
bind: args.bind,
|
|
@@ -2303,7 +2314,7 @@ var setup_default = defineCommand18({
|
|
|
2303
2314
|
default: false
|
|
2304
2315
|
}]);
|
|
2305
2316
|
if (applyNow) {
|
|
2306
|
-
const { applyPlan } = await import("./apply-
|
|
2317
|
+
const { applyPlan } = await import("./apply-5RREMN3L.js");
|
|
2307
2318
|
const plan = JSON.parse(readFileSync3(outputPath, "utf-8"));
|
|
2308
2319
|
try {
|
|
2309
2320
|
await applyPlan(plan, {
|
|
@@ -2327,7 +2338,7 @@ async function runLocalDeploy(opts) {
|
|
|
2327
2338
|
const { setConfig: setConfig2, getConfig: getConfig2, getConfigDir: getConfigDir2 } = await import("./store-SDUR52Z5.js");
|
|
2328
2339
|
const { localBootstrap } = await import("./bootstrap-G4UZ2FKH.js");
|
|
2329
2340
|
const { connect } = await import("./ssh-IQXNME3D.js");
|
|
2330
|
-
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-
|
|
2341
|
+
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
2331
2342
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
2332
2343
|
const knownHostsPath = path3.join(getConfigDir2(), "known_hosts");
|
|
2333
2344
|
const existing = getConfig2();
|
|
@@ -3012,8 +3023,8 @@ var rotateCmd = defineCommand19({
|
|
|
3012
3023
|
}
|
|
3013
3024
|
info(`Re-applying config overlay to stack "${targetStack}"\u2026`);
|
|
3014
3025
|
try {
|
|
3015
|
-
const { buildContext } = await import("./context-
|
|
3016
|
-
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-
|
|
3026
|
+
const { buildContext } = await import("./context-PSGEX2D7.js");
|
|
3027
|
+
const { readRemoteConfig, atomicWriteConfig, restartGateway, deepMerge } = await import("./remote-config-QF5TT7GU.js");
|
|
3017
3028
|
const { resolveSecrets } = await import("./secrets-SVZWNAPK.js");
|
|
3018
3029
|
const { acquireSession, drainPool } = await import("./pool-FBFHATDG.js");
|
|
3019
3030
|
const { localStateToConnectionInfo } = await import("./state-PRBIIN7I.js");
|
|
@@ -3142,6 +3153,7 @@ var COMMANDS = [
|
|
|
3142
3153
|
["doctor", "Check Node version, config, SSH key, provider credentials, and Pulumi home"],
|
|
3143
3154
|
["mcp", "MCP server operations (mcp serve | mcp install)"],
|
|
3144
3155
|
["secret", "Manage secrets (secret list | set | delete | rotate | audit)"],
|
|
3156
|
+
["monitor", "Live dashboard: gateway health, container status, resource usage, log tail"],
|
|
3145
3157
|
["help", "Show this help message"]
|
|
3146
3158
|
];
|
|
3147
3159
|
var GLOBAL_FLAGS = [
|
|
@@ -3245,6 +3257,7 @@ var main = defineCommand21({
|
|
|
3245
3257
|
mcp: mcp_default,
|
|
3246
3258
|
setup: setup_default,
|
|
3247
3259
|
secret: secret_default,
|
|
3260
|
+
monitor: monitor_default,
|
|
3248
3261
|
help: help_default
|
|
3249
3262
|
}
|
|
3250
3263
|
});
|
|
@@ -1,21 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/providers/gcp/index.ts
|
|
4
|
-
import
|
|
4
|
+
import process2 from "process";
|
|
5
5
|
|
|
6
6
|
// src/providers/gcp/program.ts
|
|
7
7
|
var GATEWAY_PORT = 18789;
|
|
8
8
|
var SSH_PORT = 22;
|
|
9
9
|
var gcpProgram = async () => {
|
|
10
|
-
const [pulumi, gcp] = await Promise.all([
|
|
10
|
+
const [pulumi, gcp, { resolveIngressCidrs, detectEgressIp }] = await Promise.all([
|
|
11
11
|
import("@pulumi/pulumi"),
|
|
12
|
-
import("@pulumi/gcp")
|
|
12
|
+
import("@pulumi/gcp"),
|
|
13
|
+
import("./firewall-YYDOWDDP.js")
|
|
13
14
|
]);
|
|
14
15
|
const cfg = new pulumi.Config();
|
|
15
16
|
const instanceType = cfg.get("instanceType") ?? "e2-standard-2";
|
|
16
17
|
const region = cfg.get("region") ?? "us-central1";
|
|
17
18
|
const openclawVersion = cfg.get("openclawVersion") ?? "latest";
|
|
18
19
|
const zone = cfg.get("zone") ?? `${region}-a`;
|
|
20
|
+
const accessMode = cfg.get("accessMode") ?? "restricted";
|
|
21
|
+
const allowedCidrs = cfg.get("allowedCidrs") ?? "";
|
|
22
|
+
const sshCidrs = cfg.get("sshCidrs") ?? "";
|
|
23
|
+
const gatewayCidrs = cfg.get("gatewayCidrs") ?? "";
|
|
24
|
+
const sshPublicKey = cfg.get("sshPublicKey");
|
|
25
|
+
if (!sshPublicKey) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
'Stack config "sshPublicKey" is required for the GCP adapter. Set it with: pulumi config set --stack <name> sshPublicKey "ssh-ed25519 ..."'
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
const detectedIp = accessMode === "auto" ? await detectEgressIp("https://checkip.amazonaws.com") : "";
|
|
31
|
+
if (accessMode === "open") {
|
|
32
|
+
process.stderr.write(
|
|
33
|
+
"[clawops] WARNING: accessMode=open allows 0.0.0.0/0 on SSH and gateway ports. Only use this for development/sandbox stacks.\n"
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs, detectedIp);
|
|
37
|
+
const gatewayIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, gatewayCidrs, detectedIp);
|
|
19
38
|
const network = new gcp.compute.Network("clawops-network", {
|
|
20
39
|
autoCreateSubnetworks: false,
|
|
21
40
|
description: "clawops managed network"
|
|
@@ -25,17 +44,22 @@ var gcpProgram = async () => {
|
|
|
25
44
|
region,
|
|
26
45
|
network: network.id
|
|
27
46
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
if (sshIngressCidrs.length > 0) {
|
|
48
|
+
new gcp.compute.Firewall("clawops-firewall-ssh", {
|
|
49
|
+
network: network.selfLink,
|
|
50
|
+
allows: [{ protocol: "tcp", ports: [String(SSH_PORT)] }],
|
|
51
|
+
sourceRanges: sshIngressCidrs,
|
|
52
|
+
targetTags: ["clawops"]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (gatewayIngressCidrs.length > 0) {
|
|
56
|
+
new gcp.compute.Firewall("clawops-firewall-gateway", {
|
|
57
|
+
network: network.selfLink,
|
|
58
|
+
allows: [{ protocol: "tcp", ports: [String(GATEWAY_PORT)] }],
|
|
59
|
+
sourceRanges: gatewayIngressCidrs,
|
|
60
|
+
targetTags: ["clawops"]
|
|
61
|
+
});
|
|
62
|
+
}
|
|
39
63
|
const address = new gcp.compute.Address("clawops-address", { region });
|
|
40
64
|
const instance = new gcp.compute.Instance("clawops-instance", {
|
|
41
65
|
machineType: instanceType,
|
|
@@ -60,6 +84,8 @@ var gcpProgram = async () => {
|
|
|
60
84
|
}
|
|
61
85
|
],
|
|
62
86
|
metadata: {
|
|
87
|
+
// GCP guest agent reads 'ssh-keys' and populates /home/<user>/.ssh/authorized_keys
|
|
88
|
+
"ssh-keys": `clawops:${sshPublicKey}`,
|
|
63
89
|
"startup-script": makeStartupScript(openclawVersion)
|
|
64
90
|
},
|
|
65
91
|
serviceAccount: {
|
|
@@ -154,6 +180,11 @@ var gcpAdapter = {
|
|
|
154
180
|
};
|
|
155
181
|
},
|
|
156
182
|
normalizeInstanceType(alias) {
|
|
183
|
+
if (alias === "gpu") {
|
|
184
|
+
throw new Error(
|
|
185
|
+
"GPU instances are not yet supported on GCP. Use --provider aws (g4dn.xlarge) or --provider azure (Standard_NC6s_v3) for GPU workloads."
|
|
186
|
+
);
|
|
187
|
+
}
|
|
157
188
|
const mapped = INSTANCE_TYPE_MAP[alias];
|
|
158
189
|
if (!mapped) throw new Error(`Unknown instance alias: ${alias}`);
|
|
159
190
|
return mapped;
|
|
@@ -166,9 +197,10 @@ var gcpAdapter = {
|
|
|
166
197
|
},
|
|
167
198
|
async validateConfig() {
|
|
168
199
|
const errors = [];
|
|
169
|
-
const hasKeyFile = Boolean(
|
|
170
|
-
const
|
|
171
|
-
|
|
200
|
+
const hasKeyFile = Boolean(process2.env["GOOGLE_APPLICATION_CREDENTIALS"]);
|
|
201
|
+
const hasToken = Boolean(process2.env["GOOGLE_OAUTH_ACCESS_TOKEN"]);
|
|
202
|
+
const hasAdcFile = await checkAdcFile();
|
|
203
|
+
if (!hasKeyFile && !hasToken && !hasAdcFile) {
|
|
172
204
|
const onGcp = await checkInstanceMetadata();
|
|
173
205
|
if (!onGcp) {
|
|
174
206
|
errors.push(
|
|
@@ -179,6 +211,17 @@ var gcpAdapter = {
|
|
|
179
211
|
return { ok: errors.length === 0, errors };
|
|
180
212
|
}
|
|
181
213
|
};
|
|
214
|
+
async function checkAdcFile() {
|
|
215
|
+
try {
|
|
216
|
+
const { accessSync } = await import("fs");
|
|
217
|
+
const { join } = await import("path");
|
|
218
|
+
const home = process2.env["HOME"] ?? process2.env["USERPROFILE"] ?? "";
|
|
219
|
+
accessSync(join(home, ".config", "gcloud", "application_default_credentials.json"));
|
|
220
|
+
return true;
|
|
221
|
+
} catch {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
182
225
|
async function checkInstanceMetadata() {
|
|
183
226
|
try {
|
|
184
227
|
const res = await fetch(
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
generatePlan,
|
|
4
4
|
planId
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UAA6YOOP.js";
|
|
6
6
|
import "./chunk-YTH4L2GN.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-T5EX55GP.js";
|
|
8
8
|
import "./chunk-A2I76FTA.js";
|
|
9
9
|
import "./chunk-CX5SL5HP.js";
|
|
10
10
|
import "./chunk-KGXPLI7W.js";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// package.json
|
|
4
4
|
var name = "@clawops/cli";
|
|
5
|
-
var version = "1.
|
|
5
|
+
var version = "1.4.0";
|
|
6
6
|
var description = "Deploy and manage self-hosted OpenClaw instances across clouds";
|
|
7
7
|
var type = "module";
|
|
8
8
|
var bin = {
|
|
@@ -48,6 +48,7 @@ var dependencies = {
|
|
|
48
48
|
"@pulumi/docker": "^4.0.0",
|
|
49
49
|
"@pulumi/gcp": "^7.0.0",
|
|
50
50
|
"@pulumi/pulumi": "^3.0.0",
|
|
51
|
+
"@pulumi/random": "^4.20.0",
|
|
51
52
|
ajv: "^8.0.0",
|
|
52
53
|
"ajv-formats": "^3.0.0",
|
|
53
54
|
chalk: "^5.0.0",
|