@clawops/cli 2.1.1 → 2.1.3
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 +23 -1
- package/dist/{apply-HJ5GAKHW.js → apply-JARPVA5Y.js} +8 -8
- package/dist/{automation-MKCJ46I6.js → automation-NBYQ6MFZ.js} +1 -1
- package/dist/{bootstrap-NN647RCY.js → bootstrap-3PBVY7MA.js} +2 -2
- package/dist/{chunk-X56CQ6GB.js → chunk-4MHDW2NB.js} +1 -1
- package/dist/{chunk-3Z5TDXCJ.js → chunk-55UMO37O.js} +1 -1
- package/dist/chunk-755X5OGS.js +213 -0
- package/dist/{chunk-R3DTA35B.js → chunk-7T4CIT7C.js} +6 -6
- package/dist/{chunk-QDNFADJI.js → chunk-AVERNLUY.js} +6 -6
- package/dist/{chunk-GFUK6KDR.js → chunk-CPCO6UJK.js} +9 -9
- package/dist/{chunk-64PONSA5.js → chunk-GFIR2IIJ.js} +3 -1
- package/dist/{chunk-YEBFVLOE.js → chunk-PTCVFLZ3.js} +4 -4
- package/dist/{chunk-ELU3XQEA.js → chunk-RDUKRIRC.js} +1 -1
- package/dist/{chunk-OFTAXLOY.js → chunk-TYHTISI5.js} +239 -159
- package/dist/cli.js +127 -274
- package/dist/{context-7VI3R6EK.js → context-WOKSKAIA.js} +5 -5
- package/dist/{flows-RI7FGHAM.js → flows-HGJIA6EL.js} +7 -7
- package/dist/{generate-JNJ63ZYZ.js → generate-NE54BATS.js} +6 -6
- package/dist/{harden-3KKCR7BL.js → harden-RUOUA5BV.js} +2 -2
- package/dist/init-HOPXDNWY.js +13 -0
- package/dist/{mcp-wire-B57DUNOD.js → mcp-wire-FIO5DFBY.js} +11 -11
- package/dist/{package-SAUDFQLG.js → package-MF5LPITL.js} +1 -1
- package/dist/{server-RHON6QMN.js → server-OXWHBTXK.js} +11 -11
- package/dist/{stack-config-LUTS2XAD.js → stack-config-ICQ5YHUL.js} +2 -2
- package/dist/{state-AOAYLYY5.js → state-AKZP2S4T.js} +2 -2
- package/dist/{store-OVB3DAJR.js → store-YOLQYXMB.js} +1 -1
- package/dist/{tailscale-cutover-6YP2QKFM.js → tailscale-cutover-EKAQSDXP.js} +2 -2
- package/package.json +1 -1
- package/spec/mcp-tools.yaml +69 -28
- package/dist/{chunk-BELTQGHT.js → chunk-CHNSL3TC.js} +3 -3
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@clawops/cli)
|
|
4
4
|
[](https://www.npmjs.com/package/@clawops/cli)
|
|
5
|
+
[](https://glama.ai/mcp/servers/dfridkin/clawops)
|
|
5
6
|
|
|
6
7
|
MCP-native infrastructure ops for OpenClaw, with read-only mode, destructive-action confirmation, and audit logs built in.
|
|
7
8
|
|
|
@@ -362,6 +363,7 @@ Do not bind to a non-loopback address without additional authentication controls
|
|
|
362
363
|
| `clawops_config_validate` | cli | Validate the deployed config against the OpenClaw schema |
|
|
363
364
|
| `clawops_gateway_restart` | cli | Restart the gateway (elicits confirmation) |
|
|
364
365
|
| `clawops_harden` | cli | Apply hardening modules; join or leave a tailnet (elicits confirmation) |
|
|
366
|
+
| `clawops_init` | cli | Register a stack and write `~/.clawops/config.json` (no cloud resources) |
|
|
365
367
|
| `clawops_workflow_deploy_app` | workflow | End-to-end deploy: plan → confirm → apply → status |
|
|
366
368
|
| `clawops_workflow_recover` | workflow | Diagnostic workflow for an unhealthy stack |
|
|
367
369
|
| `clawops_task_status` | cli | Poll a long-running task |
|
|
@@ -542,7 +544,7 @@ pnpm dev doctor # verify toolchain
|
|
|
542
544
|
```bash
|
|
543
545
|
pnpm dev # run CLI from src/ via tsx
|
|
544
546
|
pnpm build # tsup → dist/
|
|
545
|
-
pnpm test # vitest (
|
|
547
|
+
pnpm test # vitest (1897 tests, ~13s)
|
|
546
548
|
pnpm test:changed # vitest --changed (fast edit loop)
|
|
547
549
|
pnpm test:integration # Docker-based SSH integration tests
|
|
548
550
|
pnpm typecheck # tsc --noEmit
|
|
@@ -603,6 +605,7 @@ Use `pnpm changeset` to record a release note before merging a `feat` or `fix`.
|
|
|
603
605
|
## What's new in 2.1
|
|
604
606
|
|
|
605
607
|
Private networking, hardening on every cloud, and two fixes to commands that could not start.
|
|
608
|
+
2.1.1 follows with the fixes below it.
|
|
606
609
|
|
|
607
610
|
### Reach a stack over your tailnet
|
|
608
611
|
|
|
@@ -645,6 +648,25 @@ Private networking, hardening on every cloud, and two fixes to commands that cou
|
|
|
645
648
|
- The published package carries its license, keywords and issue tracker, so it is findable on npm
|
|
646
649
|
and its listing is complete.
|
|
647
650
|
|
|
651
|
+
### 2.1.1
|
|
652
|
+
|
|
653
|
+
- **`clawops` started with no command and a pipe on stdin serves MCP** instead of printing help.
|
|
654
|
+
That is how every MCP client starts a server, and how directories that infer a run command
|
|
655
|
+
start one; several were getting the help text and reporting the server as broken. Typed at a
|
|
656
|
+
terminal, `clawops` still prints help, and so does `clawops | less`.
|
|
657
|
+
- The MCP config example is `npx -y @clawops/cli mcp serve`, which runs as written. It used to
|
|
658
|
+
say `/path/to/clawops`, which nothing could run and no directory could copy.
|
|
659
|
+
- The description is inside the MCP registry's 100-character limit. The one 2.1.0 shipped was
|
|
660
|
+
110, and the registry refused it with a 422 after npm had already published — so 2.1.0 reached
|
|
661
|
+
npm and not the registry.
|
|
662
|
+
- `clawops harden` says a stack is not deployed, or that its state could not be read, instead of
|
|
663
|
+
passing along `code: -2` and a subprocess dump.
|
|
664
|
+
- The MCP registry backfill registers the version that was released rather than the one the
|
|
665
|
+
release tooling is preparing, so an entry that falls behind can actually be repaired.
|
|
666
|
+
- The Docker image builds. It had never been built, and did not: `npm pack --pack-destination`
|
|
667
|
+
does not create its destination. `pnpm verify:docker` builds it and speaks MCP to the running
|
|
668
|
+
container, both through its entrypoint and as a bare binary, in CI.
|
|
669
|
+
|
|
648
670
|
---
|
|
649
671
|
|
|
650
672
|
## What's new in 2.0.1
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
applyPlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7T4CIT7C.js";
|
|
5
5
|
import "./chunk-BOPSG2LI.js";
|
|
6
6
|
import "./chunk-6ZFIFDBJ.js";
|
|
7
7
|
import "./chunk-2I7KCMXZ.js";
|
|
8
|
-
import "./chunk-3Z5TDXCJ.js";
|
|
9
|
-
import "./chunk-AEEMRFZV.js";
|
|
10
8
|
import "./chunk-XFN3YDZE.js";
|
|
11
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-55UMO37O.js";
|
|
10
|
+
import "./chunk-AEEMRFZV.js";
|
|
11
|
+
import "./chunk-AVERNLUY.js";
|
|
12
12
|
import "./chunk-NUDIHZEH.js";
|
|
13
|
+
import "./chunk-CHNSL3TC.js";
|
|
13
14
|
import "./chunk-JW5A7E3X.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-VUFMZEIM.js";
|
|
15
16
|
import "./chunk-GIEVAGEK.js";
|
|
16
17
|
import "./chunk-VOEJYRIK.js";
|
|
17
18
|
import "./chunk-EI7CQQ7D.js";
|
|
18
19
|
import "./chunk-FEK7VJAY.js";
|
|
19
20
|
import "./chunk-RHOWYIWT.js";
|
|
20
21
|
import "./chunk-N4WZLWJ4.js";
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-RDUKRIRC.js";
|
|
23
|
+
import "./chunk-GFIR2IIJ.js";
|
|
23
24
|
import "./chunk-KGXPLI7W.js";
|
|
24
|
-
import "./chunk-VUFMZEIM.js";
|
|
25
25
|
export {
|
|
26
26
|
applyPlan
|
|
27
27
|
};
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
import "./chunk-EI7CQQ7D.js";
|
|
15
15
|
import {
|
|
16
16
|
writeLocalState
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-RDUKRIRC.js";
|
|
18
|
+
import "./chunk-GFIR2IIJ.js";
|
|
19
19
|
import {
|
|
20
20
|
ProviderError
|
|
21
21
|
} from "./chunk-KGXPLI7W.js";
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getConfig,
|
|
4
|
+
getConfigDir,
|
|
5
|
+
setConfig
|
|
6
|
+
} from "./chunk-GFIR2IIJ.js";
|
|
7
|
+
|
|
8
|
+
// src/config/init.ts
|
|
9
|
+
import { spawnSync } from "child_process";
|
|
10
|
+
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
11
|
+
import path from "path";
|
|
12
|
+
|
|
13
|
+
// src/providers/state-bucket.ts
|
|
14
|
+
function deriveStateBucket(provider, scope) {
|
|
15
|
+
if (provider === "azure") {
|
|
16
|
+
return { ok: true, name: "clawops-state" };
|
|
17
|
+
}
|
|
18
|
+
if (!scope.account) {
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
needs: provider === "aws" ? "an AWS account id \u2014 set AWS_PROFILE, or run `aws sso login --profile <name>`" : "a GCP project \u2014 run `gcloud config set project <id>`, or set GOOGLE_CLOUD_PROJECT"
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (provider === "gcp") return { ok: true, name: `clawops-state-${scope.account}` };
|
|
25
|
+
if (!scope.region) return { ok: false, needs: "a region" };
|
|
26
|
+
return { ok: true, name: `clawops-state-${scope.account}-${scope.region}` };
|
|
27
|
+
}
|
|
28
|
+
function stateUrlFor(provider, bucket) {
|
|
29
|
+
const verdict = validateStateBucket(provider, bucket);
|
|
30
|
+
if (verdict !== true) throw new Error(`Not a usable ${provider} state backend name: ${verdict}`);
|
|
31
|
+
const scheme = provider === "aws" ? "s3://" : provider === "gcp" ? "gs://" : "azblob://";
|
|
32
|
+
return provider === "azure" ? `${scheme}${bucket}` : `${scheme}${bucket}/clawops`;
|
|
33
|
+
}
|
|
34
|
+
var IPV4 = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
35
|
+
function validateStateBucket(provider, name) {
|
|
36
|
+
const n = name.trim();
|
|
37
|
+
if (n === "") return "Required";
|
|
38
|
+
if (n !== name) return "No leading or trailing spaces";
|
|
39
|
+
if (n.length < 3) return `Too short \u2014 ${labelFor(provider)} names are at least 3 characters`;
|
|
40
|
+
const dotted = provider === "gcp" && n.includes(".");
|
|
41
|
+
const max = dotted ? 222 : 63;
|
|
42
|
+
if (n.length > max) return `Too long \u2014 ${labelFor(provider)} names are at most ${max} characters`;
|
|
43
|
+
if (dotted && n.split(".").some((part) => part.length > 63)) {
|
|
44
|
+
return "Each dot-separated part of a Cloud Storage name is at most 63 characters";
|
|
45
|
+
}
|
|
46
|
+
if (n !== n.toLowerCase()) return "Lowercase only";
|
|
47
|
+
if (provider === "azure") {
|
|
48
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(n)) {
|
|
49
|
+
return "Letters, digits and single hyphens only, starting and ending with a letter or digit";
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
if (!/^[a-z0-9][a-z0-9._-]*[a-z0-9]$/.test(n)) {
|
|
54
|
+
return "Letters, digits, dots, hyphens and underscores only, starting and ending with a letter or digit";
|
|
55
|
+
}
|
|
56
|
+
if (n.includes("..")) return "No consecutive dots";
|
|
57
|
+
if (IPV4.test(n)) return "Cannot be formatted as an IP address";
|
|
58
|
+
if (provider === "aws") {
|
|
59
|
+
if (n.startsWith("xn--")) return 'Cannot start with "xn--"';
|
|
60
|
+
if (n.startsWith("sthree-")) return 'Cannot start with "sthree-"';
|
|
61
|
+
if (n.endsWith("-s3alias")) return 'Cannot end with "-s3alias"';
|
|
62
|
+
if (n.endsWith("--ol-s3")) return 'Cannot end with "--ol-s3"';
|
|
63
|
+
if (n.includes("_")) return "Underscores are not allowed in S3 bucket names";
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (n.startsWith("goog")) return 'Cannot start with "goog"';
|
|
67
|
+
if (n.includes("google")) return 'Cannot contain "google"';
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
function labelFor(provider) {
|
|
71
|
+
if (provider === "aws") return "S3 bucket";
|
|
72
|
+
if (provider === "gcp") return "Cloud Storage bucket";
|
|
73
|
+
return "blob container";
|
|
74
|
+
}
|
|
75
|
+
async function resolveScopeAccount(provider, signal) {
|
|
76
|
+
if (provider === "azure") return void 0;
|
|
77
|
+
try {
|
|
78
|
+
if (provider === "aws") {
|
|
79
|
+
const { callerAccount } = await import("./preflight-TFD4N5ZU.js");
|
|
80
|
+
return await callerAccount(signal);
|
|
81
|
+
}
|
|
82
|
+
const { resolveProjectId } = await import("./preflight-IE2YWBAC.js");
|
|
83
|
+
return resolveProjectId();
|
|
84
|
+
} catch {
|
|
85
|
+
return void 0;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/config/init.ts
|
|
90
|
+
var SUPPORTED_PROVIDERS = ["gcp", "aws", "azure", "local"];
|
|
91
|
+
var PROVIDER_DEFAULTS = {
|
|
92
|
+
gcp: { region: "us-central1", credEnv: "GOOGLE_APPLICATION_CREDENTIALS", stateScheme: "gs://" },
|
|
93
|
+
aws: { region: "us-east-1", credEnv: "AWS_PROFILE", stateScheme: "s3://" },
|
|
94
|
+
azure: { region: "eastus", credEnv: "AZURE_CLIENT_ID", stateScheme: "azblob://" }
|
|
95
|
+
};
|
|
96
|
+
async function initStack(opts) {
|
|
97
|
+
const provider = opts.provider;
|
|
98
|
+
if (!SUPPORTED_PROVIDERS.includes(provider)) {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
reason: `Unsupported provider: ${provider}. Supported: ${SUPPORTED_PROVIDERS.join(", ")}`
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const stackName = opts.stackName ?? "default";
|
|
105
|
+
const existing = getConfig();
|
|
106
|
+
if (existing?.stacks[stackName] && !opts.force) {
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
reason: `Stack "${stackName}" already exists in ${path.join(getConfigDir(), "config.json")} (${existing.stacks[stackName].stateUrl}). Pass force to overwrite its settings, or use a different stack name to add another one.`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const configDir = getConfigDir();
|
|
113
|
+
mkdirSync(configDir, { recursive: true });
|
|
114
|
+
const keyPath = opts.keyPath ?? path.join(configDir, "id_ed25519");
|
|
115
|
+
const knownHostsPath = path.join(configDir, "known_hosts");
|
|
116
|
+
let keyGenerated = false;
|
|
117
|
+
if (!existsSync(keyPath)) {
|
|
118
|
+
if (opts.keyPath) return { ok: false, reason: `SSH key not found at ${keyPath}` };
|
|
119
|
+
const gen = spawnSync(
|
|
120
|
+
"ssh-keygen",
|
|
121
|
+
["-t", "ed25519", "-f", keyPath, "-N", "", "-C", "clawops", "-q"],
|
|
122
|
+
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
123
|
+
);
|
|
124
|
+
if (gen.error || gen.status !== 0) {
|
|
125
|
+
const reason = gen.error?.message ?? gen.stderr?.toString().trim() ?? `exit ${gen.status}`;
|
|
126
|
+
return {
|
|
127
|
+
ok: false,
|
|
128
|
+
reason: `Could not generate an SSH key: ${reason}
|
|
129
|
+
Generate one yourself and point clawops at it:
|
|
130
|
+
ssh-keygen -t ed25519 -f ${keyPath} -N '' -C clawops
|
|
131
|
+
clawops init --key-path ${keyPath}`
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
keyGenerated = true;
|
|
135
|
+
}
|
|
136
|
+
if (!existsSync(knownHostsPath)) writeFileSync(knownHostsPath, "", "utf-8");
|
|
137
|
+
if (provider === "local") {
|
|
138
|
+
if (!opts.host) return { ok: false, reason: "host is required for the local provider" };
|
|
139
|
+
const config = merge(existing, stackName, provider, keyPath, knownHostsPath, {
|
|
140
|
+
provider,
|
|
141
|
+
stateUrl: "file://~/.clawops/state",
|
|
142
|
+
credentialsRef: { source: "file", envVars: [] },
|
|
143
|
+
localOpts: {
|
|
144
|
+
host: opts.host,
|
|
145
|
+
sshUser: opts.sshUser ?? "root",
|
|
146
|
+
sshPort: opts.sshPort ?? 22,
|
|
147
|
+
sshKeyPath: keyPath
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
setConfig(config);
|
|
151
|
+
return {
|
|
152
|
+
ok: true,
|
|
153
|
+
configPath: path.join(configDir, "config.json"),
|
|
154
|
+
stackName,
|
|
155
|
+
provider,
|
|
156
|
+
stateUrl: "file://~/.clawops/state",
|
|
157
|
+
keyPath,
|
|
158
|
+
keyGenerated
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const defaults = PROVIDER_DEFAULTS[provider];
|
|
162
|
+
const region = opts.region ?? defaults.region;
|
|
163
|
+
let stateUrl;
|
|
164
|
+
if (opts.stateUrl) {
|
|
165
|
+
stateUrl = opts.stateUrl;
|
|
166
|
+
} else {
|
|
167
|
+
const account = await resolveScopeAccount(provider);
|
|
168
|
+
const derived = deriveStateBucket(provider, { account, region });
|
|
169
|
+
if (!derived.ok) {
|
|
170
|
+
return {
|
|
171
|
+
ok: false,
|
|
172
|
+
reason: `Could not name a state backend for ${provider}: clawops needs ${derived.needs}. Authenticate first, or name the backend yourself, e.g. ${defaults.stateScheme}your-bucket/clawops`
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
stateUrl = stateUrlFor(provider, derived.name);
|
|
176
|
+
}
|
|
177
|
+
setConfig(
|
|
178
|
+
merge(existing, stackName, provider, keyPath, knownHostsPath, {
|
|
179
|
+
provider,
|
|
180
|
+
stateUrl,
|
|
181
|
+
region,
|
|
182
|
+
credentialsRef: { source: "env", envVars: [defaults.credEnv] }
|
|
183
|
+
})
|
|
184
|
+
);
|
|
185
|
+
return {
|
|
186
|
+
ok: true,
|
|
187
|
+
configPath: path.join(configDir, "config.json"),
|
|
188
|
+
stackName,
|
|
189
|
+
provider,
|
|
190
|
+
stateUrl,
|
|
191
|
+
region,
|
|
192
|
+
keyPath,
|
|
193
|
+
keyGenerated
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function merge(existing, stackName, provider, keyPath, knownHostsPath, stack) {
|
|
197
|
+
return {
|
|
198
|
+
...existing ?? {},
|
|
199
|
+
version: 1,
|
|
200
|
+
defaults: { stack: stackName, provider },
|
|
201
|
+
stacks: { ...existing?.stacks ?? {}, [stackName]: stack },
|
|
202
|
+
ssh: { keyPath, knownHostsPath }
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export {
|
|
207
|
+
deriveStateBucket,
|
|
208
|
+
validateStateBucket,
|
|
209
|
+
resolveScopeAccount,
|
|
210
|
+
SUPPORTED_PROVIDERS,
|
|
211
|
+
PROVIDER_DEFAULTS,
|
|
212
|
+
initStack
|
|
213
|
+
};
|
|
@@ -11,22 +11,22 @@ import {
|
|
|
11
11
|
readRemoteConfig,
|
|
12
12
|
restartGateway
|
|
13
13
|
} from "./chunk-2I7KCMXZ.js";
|
|
14
|
-
import {
|
|
15
|
-
writeStackConfig
|
|
16
|
-
} from "./chunk-3Z5TDXCJ.js";
|
|
17
14
|
import {
|
|
18
15
|
validatePlan
|
|
19
16
|
} from "./chunk-XFN3YDZE.js";
|
|
17
|
+
import {
|
|
18
|
+
writeStackConfig
|
|
19
|
+
} from "./chunk-55UMO37O.js";
|
|
20
20
|
import {
|
|
21
21
|
buildContext
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-AVERNLUY.js";
|
|
23
23
|
import {
|
|
24
24
|
GATEWAY_PORT
|
|
25
25
|
} from "./chunk-VOEJYRIK.js";
|
|
26
26
|
import {
|
|
27
27
|
getConfig,
|
|
28
28
|
setConfig
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-GFIR2IIJ.js";
|
|
30
30
|
import {
|
|
31
31
|
UsageError
|
|
32
32
|
} from "./chunk-KGXPLI7W.js";
|
|
@@ -54,7 +54,7 @@ ${validation.errors.join("\n")}`
|
|
|
54
54
|
});
|
|
55
55
|
const stack = await ctx.getStack();
|
|
56
56
|
const { guardPrivateOnlyApply } = await import("./private-only-DIA26I2E.js");
|
|
57
|
-
const { probeSsh } = await import("./tailscale-cutover-
|
|
57
|
+
const { probeSsh } = await import("./tailscale-cutover-EKAQSDXP.js");
|
|
58
58
|
await guardPrivateOnlyApply(plan, ctx, opts?.probeTailnet ?? ((conn2) => probeSsh(conn2, opts?.signal)));
|
|
59
59
|
await writeStackConfig(stack, plan);
|
|
60
60
|
if (plan.metadata.stackVersion !== void 0) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getProvider
|
|
4
|
+
} from "./chunk-VUFMZEIM.js";
|
|
2
5
|
import {
|
|
3
6
|
readLocalState
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RDUKRIRC.js";
|
|
5
8
|
import {
|
|
6
9
|
getConfigDir,
|
|
7
10
|
requireConfig
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GFIR2IIJ.js";
|
|
9
12
|
import {
|
|
10
13
|
UsageError
|
|
11
14
|
} from "./chunk-KGXPLI7W.js";
|
|
12
|
-
import {
|
|
13
|
-
getProvider
|
|
14
|
-
} from "./chunk-VUFMZEIM.js";
|
|
15
15
|
|
|
16
16
|
// src/cli/context.ts
|
|
17
17
|
function buildContext(args) {
|
|
@@ -41,7 +41,7 @@ function buildContext(args) {
|
|
|
41
41
|
`Stack "${stackName}" not found in config. Run \`clawops init\` or use \`--stack\` to specify a different stack.`
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
|
-
const { getOrCreateStack } = await import("./automation-
|
|
44
|
+
const { getOrCreateStack } = await import("./automation-NBYQ6MFZ.js");
|
|
45
45
|
stackCache = await getOrCreateStack({
|
|
46
46
|
stack: stackName,
|
|
47
47
|
stateUrl: stackConfig.stateUrl,
|
|
@@ -146,8 +146,8 @@ function renderSnapshot(snap, opts) {
|
|
|
146
146
|
return lines.join("\n");
|
|
147
147
|
}
|
|
148
148
|
async function probeEntries() {
|
|
149
|
-
const { buildContext } = await import("./context-
|
|
150
|
-
const { getConfig } = await import("./store-
|
|
149
|
+
const { buildContext } = await import("./context-WOKSKAIA.js");
|
|
150
|
+
const { getConfig } = await import("./store-YOLQYXMB.js");
|
|
151
151
|
const config = getConfig();
|
|
152
152
|
if (!config) return [];
|
|
153
153
|
return Promise.all(
|
|
@@ -215,7 +215,7 @@ function renderMenu(entries, selectedIdx, showAll, noColor, confirmDelete) {
|
|
|
215
215
|
return lines.join("\n");
|
|
216
216
|
}
|
|
217
217
|
async function deleteFromRegistry(name) {
|
|
218
|
-
const { requireConfig, setConfig } = await import("./store-
|
|
218
|
+
const { requireConfig, setConfig } = await import("./store-YOLQYXMB.js");
|
|
219
219
|
const config = requireConfig();
|
|
220
220
|
const newStacks = { ...config.stacks };
|
|
221
221
|
delete newStacks[name];
|
|
@@ -373,7 +373,7 @@ var monitor_default = defineCommand({
|
|
|
373
373
|
const tailLines = Math.max(1, parseInt(String(args.tail ?? "10"), 10) || 10);
|
|
374
374
|
const isTTY = Boolean(process.stdout.isTTY);
|
|
375
375
|
const noColor = Boolean(args["no-color"]) || !isTTY;
|
|
376
|
-
const { buildContext } = await import("./context-
|
|
376
|
+
const { buildContext } = await import("./context-WOKSKAIA.js");
|
|
377
377
|
const { acquireSession, drainPool } = await import("./pool-PIIKJ4L2.js");
|
|
378
378
|
const ac = new AbortController();
|
|
379
379
|
process.on("SIGINT", () => ac.abort());
|
|
@@ -508,7 +508,7 @@ import { accessSync, mkdirSync, readFileSync, constants } from "fs";
|
|
|
508
508
|
import ssh2 from "ssh2";
|
|
509
509
|
import path from "path";
|
|
510
510
|
async function runDiagnostics(opts = {}, deps = {}) {
|
|
511
|
-
const { getConfig, getConfigDir } = await import("./store-
|
|
511
|
+
const { getConfig, getConfigDir } = await import("./store-YOLQYXMB.js");
|
|
512
512
|
const config = getConfig();
|
|
513
513
|
const sections = [];
|
|
514
514
|
sections.push({ title: "Runtime", checks: await runtimeChecks(getConfigDir()) });
|
|
@@ -808,8 +808,8 @@ async function deployedVersionCheck(image, deployedVersion) {
|
|
|
808
808
|
}
|
|
809
809
|
async function hardeningChecks(conn, stack, signal) {
|
|
810
810
|
try {
|
|
811
|
-
const { MODULE_CATALOG, resolveModules, withRemoteExec } = await import("./harden-
|
|
812
|
-
const { buildContext } = await import("./context-
|
|
811
|
+
const { MODULE_CATALOG, resolveModules, withRemoteExec } = await import("./harden-RUOUA5BV.js");
|
|
812
|
+
const { buildContext } = await import("./context-WOKSKAIA.js");
|
|
813
813
|
const provider = buildContext({ stack }).adapter.name;
|
|
814
814
|
const modules = resolveModules(MODULE_CATALOG, void 0, provider);
|
|
815
815
|
const checks = [];
|
|
@@ -831,8 +831,8 @@ async function hardeningChecks(conn, stack, signal) {
|
|
|
831
831
|
}
|
|
832
832
|
}
|
|
833
833
|
async function defaultOpenSession(stack, signal) {
|
|
834
|
-
const { getConfig } = await import("./store-
|
|
835
|
-
const { buildContext } = await import("./context-
|
|
834
|
+
const { getConfig } = await import("./store-YOLQYXMB.js");
|
|
835
|
+
const { buildContext } = await import("./context-WOKSKAIA.js");
|
|
836
836
|
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
837
837
|
const { acquireSession } = await import("./pool-PIIKJ4L2.js");
|
|
838
838
|
const config = getConfig();
|
|
@@ -76,7 +76,9 @@ function getConfig() {
|
|
|
76
76
|
function requireConfig() {
|
|
77
77
|
const cfg = getConfig();
|
|
78
78
|
if (!cfg) {
|
|
79
|
-
throw new UsageError(
|
|
79
|
+
throw new UsageError(
|
|
80
|
+
`No clawops config at ${getConfigPath()}. Create one with \`clawops init\` in a terminal, or by calling the clawops_init tool. Either way it registers a stack \u2014 a provider and a state backend \u2014 and generates an SSH key; nothing is provisioned and nothing is charged.`
|
|
81
|
+
);
|
|
80
82
|
}
|
|
81
83
|
return cfg;
|
|
82
84
|
}
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
buildContext,
|
|
7
7
|
loadAdapterModule
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-AVERNLUY.js";
|
|
9
9
|
import {
|
|
10
10
|
getConfig
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GFIR2IIJ.js";
|
|
12
12
|
import {
|
|
13
13
|
StateError,
|
|
14
14
|
UsageError
|
|
@@ -71,7 +71,7 @@ async function generatePlan(intent, _opts) {
|
|
|
71
71
|
"plan/apply is not supported for the local provider. Use `clawops up` directly."
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
|
-
const { version } = await import("./package-
|
|
74
|
+
const { version } = await import("./package-MF5LPITL.js");
|
|
75
75
|
const config = getConfig();
|
|
76
76
|
const instanceType = await resolveInstanceType(intent);
|
|
77
77
|
const { guardOpenclawVersion, defaultOpenclawVersion } = await import("./version-guard-XVYW5WFJ.js");
|
|
@@ -123,7 +123,7 @@ A plan is only as good as the state it was computed against, so this is not a pl
|
|
|
123
123
|
);
|
|
124
124
|
}
|
|
125
125
|
try {
|
|
126
|
-
const { writeStackConfig } = await import("./stack-config-
|
|
126
|
+
const { writeStackConfig } = await import("./stack-config-ICQ5YHUL.js");
|
|
127
127
|
await writeStackConfig(stack, plan);
|
|
128
128
|
const outputLines = [];
|
|
129
129
|
const preview = await stack.preview({
|