@clawops/cli 1.5.0 → 1.7.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 +2 -0
- package/dist/{apply-5RREMN3L.js → apply-BTZFFGAD.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-T5EX55GP.js → chunk-3MFZ7E74.js} +3 -3
- package/dist/{chunk-IVX62LFO.js → chunk-7KLLWDBA.js} +2 -2
- package/dist/{chunk-R5S6IXBE.js → chunk-CG3Y7Y2R.js} +41 -71
- package/dist/{chunk-4U3LTLWZ.js → chunk-GJEF6UQA.js} +1 -0
- package/dist/{chunk-ZONXY3C6.js → chunk-ISFHLA4G.js} +4 -4
- package/dist/{chunk-ZVOEQCNW.js → chunk-LCKD7L7X.js} +1 -1
- package/dist/chunk-Q7NQY5HV.js +37 -0
- package/dist/chunk-XKT42M34.js +72 -0
- package/dist/cli.js +410 -58
- package/dist/{context-PSGEX2D7.js → context-ALSJMTHE.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-ZTD4BVVI.js} +2 -2
- package/dist/harden-BDVYW567.js +748 -0
- package/dist/human-Z44CW7TR.js +21 -0
- package/dist/{package-QLDA65A3.js → package-7WOZMHSO.js} +5 -1
- package/dist/{pool-FBFHATDG.js → pool-JZGKPP6K.js} +2 -2
- package/dist/{server-LOL2NUJ2.js → server-EXBOOIEP.js} +11 -10
- package/dist/{ssh-IQXNME3D.js → ssh-E2AMBPZY.js} +1 -1
- package/package.json +5 -1
- package/dist/firewall-YYDOWDDP.js +0 -36
package/README.md
CHANGED
|
@@ -277,6 +277,8 @@ clawops down --yes # Destroy local-provider stack
|
|
|
277
277
|
| `mcp install` | Interactively wire clawops into AI editors |
|
|
278
278
|
| `mcp wire` | Wire the gateway's AI as an MCP client of clawops |
|
|
279
279
|
| `help` | List all commands and global flags |
|
|
280
|
+
| `harden` | Apply security hardening to a deployed stack (SSH, UFW, fail2ban, unattended-upgrades, Docker socket; AWS: SG audit, SSM check, Flow Logs, GuardDuty) |
|
|
281
|
+
| `bug` | Open a pre-filled GitHub issue with system context from `doctor` |
|
|
280
282
|
|
|
281
283
|
Full flag reference: `clawops <command> --help`
|
|
282
284
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
applyPlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ISFHLA4G.js";
|
|
5
5
|
import "./chunk-YTH4L2GN.js";
|
|
6
6
|
import "./chunk-6ZFIFDBJ.js";
|
|
7
7
|
import "./chunk-BOPSG2LI.js";
|
|
8
|
-
import "./chunk-T5EX55GP.js";
|
|
9
8
|
import "./chunk-ZFNPM2WG.js";
|
|
9
|
+
import "./chunk-3MFZ7E74.js";
|
|
10
10
|
import "./chunk-A2I76FTA.js";
|
|
11
11
|
import "./chunk-CX5SL5HP.js";
|
|
12
12
|
import "./chunk-KGXPLI7W.js";
|
|
@@ -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/aws/index.ts
|
|
4
7
|
import process2 from "process";
|
|
@@ -10,7 +13,7 @@ var awsProgram = async () => {
|
|
|
10
13
|
const [pulumi, aws, { resolveIngressCidrs, detectEgressIp }] = await Promise.all([
|
|
11
14
|
import("@pulumi/pulumi"),
|
|
12
15
|
import("@pulumi/aws"),
|
|
13
|
-
import("./firewall-
|
|
16
|
+
import("./firewall-XQGO7HWK.js")
|
|
14
17
|
]);
|
|
15
18
|
const cfg = new pulumi.Config();
|
|
16
19
|
const instanceType = cfg.get("instanceType") ?? "t3.small";
|
|
@@ -21,20 +24,21 @@ var awsProgram = async () => {
|
|
|
21
24
|
const sshCidrs = cfg.get("sshCidrs") ?? "";
|
|
22
25
|
const gatewayCidrs = cfg.get("gatewayCidrs") ?? "";
|
|
23
26
|
const bedrockEnabled = cfg.get("bedrockEnabled") === "true";
|
|
27
|
+
const pinnedAmiId = cfg.get("amiId");
|
|
24
28
|
const sshPublicKey = cfg.get("sshPublicKey");
|
|
25
29
|
if (!sshPublicKey) {
|
|
26
30
|
throw new Error(
|
|
27
31
|
'Stack config "sshPublicKey" is required for the AWS adapter. Set it with: pulumi config set --stack <name> sshPublicKey "ssh-ed25519 ..."'
|
|
28
32
|
);
|
|
29
33
|
}
|
|
30
|
-
const
|
|
34
|
+
const egressResult = accessMode === "auto" ? await detectEgressIp("https://ifconfig.me") : { ok: true, ip: "" };
|
|
31
35
|
if (accessMode === "open") {
|
|
32
36
|
process.stderr.write(
|
|
33
37
|
"[clawops] WARNING: accessMode=open allows 0.0.0.0/0 on SSH and gateway ports. Only use this for development/sandbox stacks.\n"
|
|
34
38
|
);
|
|
35
39
|
}
|
|
36
|
-
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs,
|
|
37
|
-
const gatewayIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, gatewayCidrs,
|
|
40
|
+
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs, egressResult);
|
|
41
|
+
const gatewayIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, gatewayCidrs, egressResult);
|
|
38
42
|
const vpc = new aws.ec2.Vpc("clawops-vpc", {
|
|
39
43
|
cidrBlock: "10.0.0.0/16",
|
|
40
44
|
enableDnsHostnames: true,
|
|
@@ -68,33 +72,36 @@ var awsProgram = async () => {
|
|
|
68
72
|
subnetId: subnet.id,
|
|
69
73
|
routeTableId: routeTable.id
|
|
70
74
|
});
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
const sg = new aws.ec2.SecurityGroup("clawops-sg", {
|
|
76
|
+
vpcId: vpc.id,
|
|
77
|
+
description: "clawops managed security group",
|
|
78
|
+
tags: { Name: "clawops" }
|
|
79
|
+
});
|
|
80
|
+
sshIngressCidrs.forEach((cidr, i) => {
|
|
81
|
+
new aws.vpc.SecurityGroupIngressRule(`clawops-sg-ssh-${i}`, {
|
|
82
|
+
securityGroupId: sg.id,
|
|
83
|
+
ipProtocol: "tcp",
|
|
74
84
|
fromPort: SSH_PORT,
|
|
75
85
|
toPort: SSH_PORT,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
cidrIpv4: cidr,
|
|
87
|
+
tags: { Name: `clawops-ssh-${i}` }
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
gatewayIngressCidrs.forEach((cidr, i) => {
|
|
91
|
+
new aws.vpc.SecurityGroupIngressRule(`clawops-sg-gw-${i}`, {
|
|
92
|
+
securityGroupId: sg.id,
|
|
93
|
+
ipProtocol: "tcp",
|
|
81
94
|
fromPort: GATEWAY_PORT,
|
|
82
95
|
toPort: GATEWAY_PORT,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
fromPort: 0,
|
|
93
|
-
toPort: 0,
|
|
94
|
-
cidrBlocks: ["0.0.0.0/0"],
|
|
95
|
-
description: "Allow all egress"
|
|
96
|
-
}],
|
|
97
|
-
tags: { Name: "clawops" }
|
|
96
|
+
cidrIpv4: cidr,
|
|
97
|
+
tags: { Name: `clawops-gateway-${i}` }
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
new aws.vpc.SecurityGroupEgressRule("clawops-sg-egress", {
|
|
101
|
+
securityGroupId: sg.id,
|
|
102
|
+
ipProtocol: "-1",
|
|
103
|
+
cidrIpv4: "0.0.0.0/0",
|
|
104
|
+
tags: { Name: "clawops-egress" }
|
|
98
105
|
});
|
|
99
106
|
const role = new aws.iam.Role("clawops-role", {
|
|
100
107
|
assumeRolePolicy: JSON.stringify({
|
|
@@ -112,10 +119,19 @@ var awsProgram = async () => {
|
|
|
112
119
|
policyArn: "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
|
|
113
120
|
});
|
|
114
121
|
if (bedrockEnabled) {
|
|
115
|
-
new aws.iam.
|
|
122
|
+
new aws.iam.RolePolicy("clawops-bedrock-invoke", {
|
|
116
123
|
role: role.name,
|
|
117
|
-
|
|
118
|
-
|
|
124
|
+
policy: JSON.stringify({
|
|
125
|
+
Version: "2012-10-17",
|
|
126
|
+
Statement: [{
|
|
127
|
+
Effect: "Allow",
|
|
128
|
+
Action: [
|
|
129
|
+
"bedrock:InvokeModel",
|
|
130
|
+
"bedrock:InvokeModelWithResponseStream"
|
|
131
|
+
],
|
|
132
|
+
Resource: "*"
|
|
133
|
+
}]
|
|
134
|
+
})
|
|
119
135
|
});
|
|
120
136
|
}
|
|
121
137
|
const instanceProfile = new aws.iam.InstanceProfile("clawops-profile", {
|
|
@@ -125,7 +141,7 @@ var awsProgram = async () => {
|
|
|
125
141
|
publicKey: sshPublicKey,
|
|
126
142
|
tags: { Name: "clawops" }
|
|
127
143
|
});
|
|
128
|
-
const
|
|
144
|
+
const amiId = pinnedAmiId ?? (await aws.ec2.getAmi({
|
|
129
145
|
mostRecent: true,
|
|
130
146
|
owners: ["099720109477"],
|
|
131
147
|
// Canonical
|
|
@@ -133,15 +149,17 @@ var awsProgram = async () => {
|
|
|
133
149
|
{ name: "name", values: ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] },
|
|
134
150
|
{ name: "virtualization-type", values: ["hvm"] }
|
|
135
151
|
]
|
|
136
|
-
});
|
|
152
|
+
})).id;
|
|
153
|
+
process.stderr.write(`[clawops] Using AMI: ${amiId}
|
|
154
|
+
`);
|
|
137
155
|
const instance = new aws.ec2.Instance("clawops-instance", {
|
|
138
|
-
ami:
|
|
156
|
+
ami: amiId,
|
|
139
157
|
instanceType,
|
|
140
158
|
subnetId: subnet.id,
|
|
141
159
|
vpcSecurityGroupIds: [sg.id],
|
|
142
160
|
iamInstanceProfile: instanceProfile.name,
|
|
143
161
|
keyName: keyPair.keyName,
|
|
144
|
-
userData: makeStartupScript(openclawVersion, bedrockEnabled),
|
|
162
|
+
userData: makeStartupScript({ openclawVersion, os: "ubuntu", bedrockEnabled }),
|
|
145
163
|
// IMDSv2 with hopLimit=2 so Docker containers on this host can reach IMDS
|
|
146
164
|
// and obtain the instance role credentials (required for Bedrock access).
|
|
147
165
|
metadataOptions: {
|
|
@@ -169,62 +187,6 @@ var awsProgram = async () => {
|
|
|
169
187
|
provisionedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
170
188
|
};
|
|
171
189
|
};
|
|
172
|
-
function makeStartupScript(openclawVersion, bedrockEnabled) {
|
|
173
|
-
const bedrockEnvFlag = bedrockEnabled ? " -e AWS_DEFAULT_REGION=$(curl -sf http://169.254.169.254/latest/meta-data/placement/region || echo us-east-1) \\\n" : "";
|
|
174
|
-
return `#!/bin/bash
|
|
175
|
-
set -euo pipefail
|
|
176
|
-
|
|
177
|
-
# Create clawops user with SSH access
|
|
178
|
-
id -u clawops &>/dev/null || useradd -m -s /bin/bash clawops
|
|
179
|
-
mkdir -p /home/clawops/.ssh
|
|
180
|
-
chmod 700 /home/clawops/.ssh
|
|
181
|
-
chown clawops:clawops /home/clawops/.ssh
|
|
182
|
-
|
|
183
|
-
# Install Docker if not present (AWS AMI is ubuntu-22.04)
|
|
184
|
-
if ! command -v docker &>/dev/null; then
|
|
185
|
-
export DEBIAN_FRONTEND=noninteractive
|
|
186
|
-
apt-get update -q
|
|
187
|
-
apt-get install -y -q ca-certificates curl gnupg lsb-release
|
|
188
|
-
install -m 0755 -d /etc/apt/keyrings
|
|
189
|
-
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \\
|
|
190
|
-
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
191
|
-
chmod a+r /etc/apt/keyrings/docker.gpg
|
|
192
|
-
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \\
|
|
193
|
-
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \\
|
|
194
|
-
> /etc/apt/sources.list.d/docker.list
|
|
195
|
-
apt-get update -q
|
|
196
|
-
apt-get install -y -q docker-ce docker-ce-cli containerd.io
|
|
197
|
-
systemctl enable --now docker
|
|
198
|
-
fi
|
|
199
|
-
|
|
200
|
-
usermod -aG docker clawops
|
|
201
|
-
|
|
202
|
-
# Pull OpenClaw image
|
|
203
|
-
OPENCLAW_VERSION="${openclawVersion}"
|
|
204
|
-
docker pull ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION}
|
|
205
|
-
|
|
206
|
-
# Create default openclaw.json if not present
|
|
207
|
-
# apply.ts will overwrite this with the plan's config overlay post-provisioning.
|
|
208
|
-
OPENCLAW_CONFIG=/home/clawops/openclaw.json
|
|
209
|
-
if [ ! -f "\${OPENCLAW_CONFIG}" ]; then
|
|
210
|
-
cat > "\${OPENCLAW_CONFIG}" <<'OPENCLAWJSON'
|
|
211
|
-
{"meta":{"lastTouchedVersion":"2026.4"},"gateway":{"port":18789,"auth":{"mode":"token"}},"models":{},"channels":{}}
|
|
212
|
-
OPENCLAWJSON
|
|
213
|
-
chown clawops:clawops "\${OPENCLAW_CONFIG}"
|
|
214
|
-
fi
|
|
215
|
-
|
|
216
|
-
# Start OpenClaw container
|
|
217
|
-
docker stop openclaw 2>/dev/null || true
|
|
218
|
-
docker rm openclaw 2>/dev/null || true
|
|
219
|
-
docker run -d \\
|
|
220
|
-
--name openclaw \\
|
|
221
|
-
--restart unless-stopped \\
|
|
222
|
-
-p ${GATEWAY_PORT}:${GATEWAY_PORT} \\
|
|
223
|
-
-v "\${OPENCLAW_CONFIG}":/app/config.json:ro \\
|
|
224
|
-
${bedrockEnvFlag} ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION} \\
|
|
225
|
-
node openclaw.mjs gateway run --allow-unconfigured
|
|
226
|
-
`;
|
|
227
|
-
}
|
|
228
190
|
|
|
229
191
|
// src/providers/aws/index.ts
|
|
230
192
|
var INSTANCE_TYPE_MAP = {
|
|
@@ -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/azure/index.ts
|
|
4
7
|
import process2 from "process";
|
|
@@ -12,7 +15,7 @@ var azureProgram = async () => {
|
|
|
12
15
|
import("@pulumi/pulumi"),
|
|
13
16
|
import("@pulumi/azure-native"),
|
|
14
17
|
import("@pulumi/random"),
|
|
15
|
-
import("./firewall-
|
|
18
|
+
import("./firewall-XQGO7HWK.js")
|
|
16
19
|
]);
|
|
17
20
|
const cfg = new pulumi.Config();
|
|
18
21
|
const stackName = pulumi.getStack();
|
|
@@ -31,14 +34,15 @@ var azureProgram = async () => {
|
|
|
31
34
|
'Stack config "sshPublicKey" is required for the Azure adapter. Set it with: pulumi config set --stack <name> sshPublicKey "ssh-ed25519 ..."'
|
|
32
35
|
);
|
|
33
36
|
}
|
|
34
|
-
const
|
|
37
|
+
const clientConfig = await azure.authorization.getClientConfig({});
|
|
38
|
+
const egressResult = accessMode === "auto" ? await detectEgressIp("https://ifconfig.me") : { ok: true, ip: "" };
|
|
35
39
|
if (accessMode === "open") {
|
|
36
40
|
process.stderr.write(
|
|
37
41
|
"[clawops] WARNING: accessMode=open allows 0.0.0.0/0 on SSH and gateway ports. Only use this for development/sandbox stacks.\n"
|
|
38
42
|
);
|
|
39
43
|
}
|
|
40
|
-
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs,
|
|
41
|
-
const gatewayIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, gatewayCidrs,
|
|
44
|
+
const sshIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, sshCidrs, egressResult);
|
|
45
|
+
const gatewayIngressCidrs = resolveIngressCidrs(accessMode, allowedCidrs, gatewayCidrs, egressResult);
|
|
42
46
|
const rg = new azure.resources.ResourceGroup("clawops-rg", {
|
|
43
47
|
resourceGroupName,
|
|
44
48
|
location
|
|
@@ -111,7 +115,7 @@ var azureProgram = async () => {
|
|
|
111
115
|
osProfile: {
|
|
112
116
|
adminUsername: "clawops",
|
|
113
117
|
computerName: "clawops",
|
|
114
|
-
customData: Buffer.from(makeStartupScript(openclawVersion)).toString("base64"),
|
|
118
|
+
customData: Buffer.from(makeStartupScript({ openclawVersion, os: "ubuntu" })).toString("base64"),
|
|
115
119
|
linuxConfiguration: {
|
|
116
120
|
disablePasswordAuthentication: true,
|
|
117
121
|
ssh: {
|
|
@@ -125,8 +129,10 @@ var azureProgram = async () => {
|
|
|
125
129
|
storageProfile: {
|
|
126
130
|
imageReference: {
|
|
127
131
|
publisher: "Canonical",
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
// Ubuntu 22.04 LTS — Canonical migrated from the legacy 'UbuntuServer'
|
|
133
|
+
// offer to this naming scheme. 22_04-lts-gen2 is available in all regions.
|
|
134
|
+
offer: "0001-com-ubuntu-server-jammy",
|
|
135
|
+
sku: "22_04-lts-gen2",
|
|
130
136
|
version: "latest"
|
|
131
137
|
},
|
|
132
138
|
osDisk: {
|
|
@@ -153,10 +159,10 @@ var azureProgram = async () => {
|
|
|
153
159
|
enableRbacAuthorization: true
|
|
154
160
|
}
|
|
155
161
|
});
|
|
162
|
+
const kvSecretsUserRoleId = `/subscriptions/${clientConfig.subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/4633458b-17de-408a-b874-0445c86b69e6`;
|
|
156
163
|
new azure.authorization.RoleAssignment("clawops-kv-role", {
|
|
157
164
|
scope: kv.id,
|
|
158
|
-
roleDefinitionId:
|
|
159
|
-
// Key Vault Secrets User
|
|
165
|
+
roleDefinitionId: kvSecretsUserRoleId,
|
|
160
166
|
principalId: pulumi.output(vm.identity).apply((i) => i?.principalId ?? ""),
|
|
161
167
|
principalType: "ServicePrincipal"
|
|
162
168
|
});
|
|
@@ -183,53 +189,6 @@ var azureProgram = async () => {
|
|
|
183
189
|
provisionedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
184
190
|
};
|
|
185
191
|
};
|
|
186
|
-
function makeStartupScript(openclawVersion) {
|
|
187
|
-
return `#!/bin/bash
|
|
188
|
-
set -euo pipefail
|
|
189
|
-
|
|
190
|
-
# Install Docker if not present
|
|
191
|
-
if ! command -v docker &>/dev/null; then
|
|
192
|
-
apt-get update -q
|
|
193
|
-
apt-get install -y -q ca-certificates curl gnupg lsb-release
|
|
194
|
-
install -m 0755 -d /etc/apt/keyrings
|
|
195
|
-
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \\
|
|
196
|
-
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
197
|
-
chmod a+r /etc/apt/keyrings/docker.gpg
|
|
198
|
-
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \\
|
|
199
|
-
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \\
|
|
200
|
-
> /etc/apt/sources.list.d/docker.list
|
|
201
|
-
apt-get update -q
|
|
202
|
-
apt-get install -y -q docker-ce docker-ce-cli containerd.io
|
|
203
|
-
systemctl enable --now docker
|
|
204
|
-
fi
|
|
205
|
-
|
|
206
|
-
usermod -aG docker clawops
|
|
207
|
-
|
|
208
|
-
# Pull OpenClaw image
|
|
209
|
-
OPENCLAW_VERSION="${openclawVersion}"
|
|
210
|
-
docker pull ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION}
|
|
211
|
-
|
|
212
|
-
# Create default openclaw.json if not present
|
|
213
|
-
OPENCLAW_CONFIG=/home/clawops/openclaw.json
|
|
214
|
-
if [ ! -f "\${OPENCLAW_CONFIG}" ]; then
|
|
215
|
-
cat > "\${OPENCLAW_CONFIG}" <<'OPENCLAWJSON'
|
|
216
|
-
{"meta":{"lastTouchedVersion":"2026.4"},"gateway":{"port":18789,"auth":{"mode":"token"}},"models":{},"channels":{}}
|
|
217
|
-
OPENCLAWJSON
|
|
218
|
-
chown clawops:clawops "\${OPENCLAW_CONFIG}"
|
|
219
|
-
fi
|
|
220
|
-
|
|
221
|
-
# Start OpenClaw container
|
|
222
|
-
docker stop openclaw 2>/dev/null || true
|
|
223
|
-
docker rm openclaw 2>/dev/null || true
|
|
224
|
-
docker run -d \\
|
|
225
|
-
--name openclaw \\
|
|
226
|
-
--restart unless-stopped \\
|
|
227
|
-
-p 18789:18789 \\
|
|
228
|
-
-v "\${OPENCLAW_CONFIG}":/app/config.json:ro \\
|
|
229
|
-
ghcr.io/openclaw/openclaw:\${OPENCLAW_VERSION} \\
|
|
230
|
-
node openclaw.mjs gateway run --allow-unconfigured
|
|
231
|
-
`;
|
|
232
|
-
}
|
|
233
192
|
|
|
234
193
|
// src/providers/azure/index.ts
|
|
235
194
|
var INSTANCE_TYPE_MAP = {
|
|
@@ -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-6FT2A45S.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-D7Y6LCGK.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-JQAMNVHN.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-3MFZ7E74.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-7WOZMHSO.js");
|
|
49
49
|
const config = getConfig();
|
|
50
50
|
const instanceType = intent.instanceType ?? "small";
|
|
51
51
|
const openclawVersion = intent.openclawVersion ?? "latest";
|
|
@@ -1,50 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
OPENCLAW_CONFIG,
|
|
4
|
+
atomicWriteConfig,
|
|
5
|
+
restartGateway
|
|
6
|
+
} from "./chunk-ZFNPM2WG.js";
|
|
2
7
|
import {
|
|
3
8
|
buildContext
|
|
4
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3MFZ7E74.js";
|
|
5
10
|
import {
|
|
6
11
|
acquireSession,
|
|
7
12
|
drainPool
|
|
8
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-LCKD7L7X.js";
|
|
9
14
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "./chunk-ZFNPM2WG.js";
|
|
15
|
+
chalk,
|
|
16
|
+
failure
|
|
17
|
+
} from "./chunk-Q7NQY5HV.js";
|
|
14
18
|
import {
|
|
15
19
|
StateError
|
|
16
20
|
} from "./chunk-KGXPLI7W.js";
|
|
17
21
|
|
|
18
22
|
// src/cli/commands/monitor.ts
|
|
19
23
|
import { defineCommand } from "citty";
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
// src/output/human.ts
|
|
23
|
-
import chalk from "chalk";
|
|
24
|
-
import ora from "ora";
|
|
25
|
-
function success(msg) {
|
|
26
|
-
console.log(chalk.green("\u2713") + " " + msg);
|
|
27
|
-
}
|
|
28
|
-
function failure(msg) {
|
|
29
|
-
console.error(chalk.red("\u2717") + " " + msg);
|
|
30
|
-
}
|
|
31
|
-
function warn(msg) {
|
|
32
|
-
console.warn(chalk.yellow("\u26A0") + " " + msg);
|
|
33
|
-
}
|
|
34
|
-
function info(msg) {
|
|
35
|
-
console.log(chalk.blue("\u2139") + " " + msg);
|
|
36
|
-
}
|
|
37
|
-
function spinner(text) {
|
|
38
|
-
return ora(text).start();
|
|
39
|
-
}
|
|
40
|
-
var REPO_URL = "https://github.com/dfridkin/clawops";
|
|
41
|
-
function printCta() {
|
|
42
|
-
process.stdout.write(
|
|
43
|
-
"\n" + chalk.dim(" Thank you for using clawops! If it has been useful, star the project:") + "\n" + chalk.dim(" " + REPO_URL) + "\n\n" + chalk.dim(" Found a bug? Open an issue:") + "\n" + chalk.dim(" " + REPO_URL + "/issues") + "\n\n"
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// src/cli/commands/monitor.ts
|
|
24
|
+
import process from "process";
|
|
48
25
|
var GATEWAY_PORT = 18789;
|
|
49
26
|
function formatUptime(startedAt) {
|
|
50
27
|
if (!startedAt) return "\u2014";
|
|
@@ -154,7 +131,7 @@ function renderSnapshot(snap, opts) {
|
|
|
154
131
|
return lines.join("\n");
|
|
155
132
|
}
|
|
156
133
|
async function probeEntries() {
|
|
157
|
-
const { buildContext: buildContext2 } = await import("./context-
|
|
134
|
+
const { buildContext: buildContext2 } = await import("./context-ALSJMTHE.js");
|
|
158
135
|
const { getConfig } = await import("./store-SDUR52Z5.js");
|
|
159
136
|
const config = getConfig();
|
|
160
137
|
if (!config) return [];
|
|
@@ -234,7 +211,7 @@ async function deleteFromRegistry(name) {
|
|
|
234
211
|
setConfig(updated);
|
|
235
212
|
}
|
|
236
213
|
async function runStackMenu(ac, setKeyHandler, noColor) {
|
|
237
|
-
|
|
214
|
+
process.stdout.write("\x1B[2J\x1B[H\n Checking stacks...\n");
|
|
238
215
|
const entries = await probeEntries();
|
|
239
216
|
if (ac.signal.aborted) return null;
|
|
240
217
|
let selectedIdx = 0;
|
|
@@ -244,7 +221,7 @@ async function runStackMenu(ac, setKeyHandler, noColor) {
|
|
|
244
221
|
return showAll ? entries : entries.filter((e) => e.deployed);
|
|
245
222
|
}
|
|
246
223
|
function redraw() {
|
|
247
|
-
|
|
224
|
+
process.stdout.write("\x1B[2J\x1B[H" + renderMenu(entries, selectedIdx, showAll, noColor, confirmDelete));
|
|
248
225
|
}
|
|
249
226
|
redraw();
|
|
250
227
|
return new Promise((resolve) => {
|
|
@@ -323,7 +300,7 @@ async function runDashboard(session, stackName, opts, ac, setKeyHandler, menuMod
|
|
|
323
300
|
noColor: opts.noColor,
|
|
324
301
|
menuMode
|
|
325
302
|
});
|
|
326
|
-
|
|
303
|
+
process.stdout.write("\x1B[2J\x1B[H" + out + "\n");
|
|
327
304
|
}
|
|
328
305
|
async function doRefresh() {
|
|
329
306
|
cancelRefresh();
|
|
@@ -333,7 +310,7 @@ async function runDashboard(session, stackName, opts, ac, setKeyHandler, menuMod
|
|
|
333
310
|
redraw();
|
|
334
311
|
} catch (err) {
|
|
335
312
|
if (!ac.signal.aborted) {
|
|
336
|
-
|
|
313
|
+
process.stdout.write("\x1B[2J\x1B[H Error gathering snapshot: " + (err instanceof Error ? err.message : String(err)) + "\n");
|
|
337
314
|
}
|
|
338
315
|
}
|
|
339
316
|
if (!ac.signal.aborted) scheduleRefresh();
|
|
@@ -379,20 +356,20 @@ var monitor_default = defineCommand({
|
|
|
379
356
|
async run({ args }) {
|
|
380
357
|
const intervalSec = Math.max(2, parseInt(String(args.interval ?? "10"), 10) || 10);
|
|
381
358
|
const tailLines = Math.max(1, parseInt(String(args.tail ?? "10"), 10) || 10);
|
|
382
|
-
const isTTY = Boolean(
|
|
359
|
+
const isTTY = Boolean(process.stdout.isTTY);
|
|
383
360
|
const noColor = Boolean(args["no-color"]) || !isTTY;
|
|
384
|
-
const { buildContext: buildContext2 } = await import("./context-
|
|
385
|
-
const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-
|
|
361
|
+
const { buildContext: buildContext2 } = await import("./context-ALSJMTHE.js");
|
|
362
|
+
const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-JZGKPP6K.js");
|
|
386
363
|
const ac = new AbortController();
|
|
387
|
-
|
|
388
|
-
|
|
364
|
+
process.on("SIGINT", () => ac.abort());
|
|
365
|
+
process.on("SIGTERM", () => ac.abort());
|
|
389
366
|
if (args.stack) {
|
|
390
367
|
const ctx = buildContext2(args);
|
|
391
368
|
let conn;
|
|
392
369
|
if (ctx.adapter.name === "local") {
|
|
393
370
|
if (!ctx.localState) {
|
|
394
371
|
failure("Stack is not bootstrapped. Run `clawops up` first.");
|
|
395
|
-
|
|
372
|
+
process.exit(4);
|
|
396
373
|
}
|
|
397
374
|
const ls = ctx.localState;
|
|
398
375
|
conn = { host: ls.sshHost, port: ls.sshPort, user: ls.sshUser, privateKeyPath: ls.privateKeyPath, knownHostsPath: ls.knownHostsPath };
|
|
@@ -405,7 +382,7 @@ var monitor_default = defineCommand({
|
|
|
405
382
|
);
|
|
406
383
|
if (!outputs["publicIp"]) {
|
|
407
384
|
failure("Stack has no outputs. Run `clawops up` first.");
|
|
408
|
-
|
|
385
|
+
process.exit(4);
|
|
409
386
|
}
|
|
410
387
|
const base = extractBaseOutputs(outputs);
|
|
411
388
|
conn = ctx.adapter.getConnectionInfo({
|
|
@@ -418,7 +395,7 @@ var monitor_default = defineCommand({
|
|
|
418
395
|
const { session: session2, release: release2 } = await acquireSession2({ ...conn, signal: ac.signal });
|
|
419
396
|
try {
|
|
420
397
|
const snap = await gatherSnapshot(session2, ac.signal, tailLines);
|
|
421
|
-
|
|
398
|
+
process.stdout.write(
|
|
422
399
|
renderSnapshot(snap, { stackName: ctx.stackName, intervalSec, showLogs: true, noColor }) + "\n"
|
|
423
400
|
);
|
|
424
401
|
} finally {
|
|
@@ -428,21 +405,21 @@ var monitor_default = defineCommand({
|
|
|
428
405
|
return;
|
|
429
406
|
}
|
|
430
407
|
const { session, release } = await acquireSession2({ ...conn, signal: ac.signal });
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
408
|
+
process.stdin.setRawMode(true);
|
|
409
|
+
process.stdin.resume();
|
|
410
|
+
process.stdin.setEncoding("utf8");
|
|
411
|
+
process.stdout.write("\x1B[?25l");
|
|
435
412
|
let keyHandler2 = () => {
|
|
436
413
|
};
|
|
437
|
-
|
|
414
|
+
process.stdin.on("data", (key) => keyHandler2(key));
|
|
438
415
|
try {
|
|
439
416
|
await runDashboard(session, ctx.stackName, { intervalSec, tailLines, noColor }, ac, (fn) => {
|
|
440
417
|
keyHandler2 = fn;
|
|
441
418
|
}, false);
|
|
442
419
|
} finally {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
420
|
+
process.stdin.setRawMode(false);
|
|
421
|
+
process.stdin.pause();
|
|
422
|
+
process.stdout.write("\x1B[?25h\n");
|
|
446
423
|
release();
|
|
447
424
|
drainPool2();
|
|
448
425
|
}
|
|
@@ -450,15 +427,15 @@ var monitor_default = defineCommand({
|
|
|
450
427
|
}
|
|
451
428
|
if (!isTTY) {
|
|
452
429
|
failure("Pass --stack <name> or run in a TTY for interactive stack selection.");
|
|
453
|
-
|
|
430
|
+
process.exit(2);
|
|
454
431
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
432
|
+
process.stdin.setRawMode(true);
|
|
433
|
+
process.stdin.resume();
|
|
434
|
+
process.stdin.setEncoding("utf8");
|
|
435
|
+
process.stdout.write("\x1B[?25l");
|
|
459
436
|
let keyHandler = () => {
|
|
460
437
|
};
|
|
461
|
-
|
|
438
|
+
process.stdin.on("data", (key) => keyHandler(key));
|
|
462
439
|
try {
|
|
463
440
|
while (!ac.signal.aborted) {
|
|
464
441
|
const stackName = await runStackMenu(ac, (fn) => {
|
|
@@ -503,9 +480,9 @@ var monitor_default = defineCommand({
|
|
|
503
480
|
}
|
|
504
481
|
}
|
|
505
482
|
} finally {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
483
|
+
process.stdin.setRawMode(false);
|
|
484
|
+
process.stdin.pause();
|
|
485
|
+
process.stdout.write("\x1B[?25h\n");
|
|
509
486
|
}
|
|
510
487
|
}
|
|
511
488
|
});
|
|
@@ -750,13 +727,6 @@ function validateOpenclawConfig(cfg) {
|
|
|
750
727
|
}
|
|
751
728
|
|
|
752
729
|
export {
|
|
753
|
-
chalk,
|
|
754
|
-
success,
|
|
755
|
-
failure,
|
|
756
|
-
warn,
|
|
757
|
-
info,
|
|
758
|
-
spinner,
|
|
759
|
-
printCta,
|
|
760
730
|
resolveConn,
|
|
761
731
|
errText,
|
|
762
732
|
okText,
|