@clawops/cli 2.1.2 → 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 +2 -0
- 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-IQQTB7ER.js → chunk-PTCVFLZ3.js} +4 -4
- package/dist/{chunk-ELU3XQEA.js → chunk-RDUKRIRC.js} +1 -1
- package/dist/{chunk-T5XCMYAV.js → chunk-TYHTISI5.js} +187 -137
- 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-Q2BGVMH7.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-FQOMM7MK.js → mcp-wire-FIO5DFBY.js} +11 -11
- package/dist/{package-JFVGCNKU.js → package-MF5LPITL.js} +1 -1
- package/dist/{server-B7I6HBQH.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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
applyPlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7T4CIT7C.js";
|
|
5
|
+
import {
|
|
6
|
+
generatePlan
|
|
7
|
+
} from "./chunk-PTCVFLZ3.js";
|
|
5
8
|
import {
|
|
6
9
|
extractBaseOutputs
|
|
7
10
|
} from "./chunk-3QJBNAHW.js";
|
|
@@ -10,24 +13,21 @@ import {
|
|
|
10
13
|
readRemoteConfig,
|
|
11
14
|
restartGateway
|
|
12
15
|
} from "./chunk-2I7KCMXZ.js";
|
|
13
|
-
import {
|
|
14
|
-
generatePlan
|
|
15
|
-
} from "./chunk-IQQTB7ER.js";
|
|
16
16
|
import {
|
|
17
17
|
validatePlan
|
|
18
18
|
} from "./chunk-XFN3YDZE.js";
|
|
19
|
+
import {
|
|
20
|
+
buildContext
|
|
21
|
+
} from "./chunk-AVERNLUY.js";
|
|
19
22
|
import {
|
|
20
23
|
acquireSession,
|
|
21
24
|
drainPool
|
|
22
25
|
} from "./chunk-2Z7J3ERQ.js";
|
|
23
|
-
import {
|
|
24
|
-
buildContext
|
|
25
|
-
} from "./chunk-QDNFADJI.js";
|
|
26
26
|
import {
|
|
27
27
|
formatUptime,
|
|
28
28
|
gatherSnapshot,
|
|
29
29
|
runDiagnostics
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-CPCO6UJK.js";
|
|
31
31
|
import {
|
|
32
32
|
GATEWAY_LOGS_PROBE,
|
|
33
33
|
chooseLogSource,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
import {
|
|
49
49
|
getConfig,
|
|
50
50
|
getConfigDir
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-GFIR2IIJ.js";
|
|
52
52
|
import {
|
|
53
53
|
StateError,
|
|
54
54
|
UsageError
|
|
@@ -141,7 +141,7 @@ function withAudit(toolName, handler) {
|
|
|
141
141
|
// src/mcp/tools/_generated.ts
|
|
142
142
|
import { z } from "zod";
|
|
143
143
|
var clawops_statusSchema = z.object({
|
|
144
|
-
stackName: z.string().optional()
|
|
144
|
+
stackName: z.string().optional().describe("Stack name. Defaults to active stack from config.")
|
|
145
145
|
});
|
|
146
146
|
var clawops_statusDescription = "Get what is deployed for a clawops-managed stack: public IP, gateway URL,\nSSH user, or that nothing is deployed yet. Reads stack outputs; does not\ncontact the host.\n\nUse when: the user asks what exists for a stack, or where to reach it.\n\nDo NOT use when: the user asks whether the gateway is actually WORKING \u2014\nthat needs the host, so use clawops_doctor. Also not for live logs (use\nclawops_logs_tail) or config values (use clawops_config_get).";
|
|
147
147
|
var clawops_statusAnnotations = {
|
|
@@ -153,8 +153,8 @@ var clawops_statusAnnotations = {
|
|
|
153
153
|
toolsets: ["cli", "read"]
|
|
154
154
|
};
|
|
155
155
|
var clawops_doctorSchema = z.object({
|
|
156
|
-
stackName: z.string().optional(),
|
|
157
|
-
failuresOnly: z.boolean().optional().default(false)
|
|
156
|
+
stackName: z.string().optional().describe("Stack to include remote checks for. Without it, only the local machine is\nchecked \u2014 no SSH connection is made.\n"),
|
|
157
|
+
failuresOnly: z.boolean().optional().default(false).describe("Return only failing and warning checks. Passing checks are counted, not listed.")
|
|
158
158
|
});
|
|
159
159
|
var clawops_doctorDescription = "Run clawops's diagnostics and return the report: Node and Pulumi runtime, config,\nSSH key and known_hosts, cloud credentials per configured provider, and the\nsupported OpenClaw range. With stackName, also contacts the host for container\nstate, the deployed OpenClaw version, a real gateway health probe, whether the\nport is published to the internet, disk usage on the state directory, log\nrotation, and hardening drift.\n\nUse when: something is not working and you do not yet know what; before any\ndeploy, upgrade or migration; or to find out which OpenClaw version a gateway is\nactually running.\n\nDo NOT use when: you already know the problem and want to fix it. This tool only\nreports \u2014 it changes nothing, and never runs `openclaw doctor --fix`. No tool\nrepairs a gateway: `clawops gateway update` is CLI-only, so tell the user to run\nit themselves, after `clawops backup create`.\n\nEvery check carries a status: fail (something is wrong that clawops can name),\nwarn (worth knowing, not broken), info (did not apply). `ok` is false only when\nsomething failed \u2014 a fresh machine with no stacks is full of warnings and healthy.";
|
|
160
160
|
var clawops_doctorAnnotations = {
|
|
@@ -166,9 +166,9 @@ var clawops_doctorAnnotations = {
|
|
|
166
166
|
toolsets: ["cli", "read"]
|
|
167
167
|
};
|
|
168
168
|
var clawops_logs_tailSchema = z.object({
|
|
169
|
-
stackName: z.string().optional(),
|
|
170
|
-
tailLines: z.number().int().optional().default(100),
|
|
171
|
-
sinceMin: z.number().int().optional()
|
|
169
|
+
stackName: z.string().optional().describe("Which stack's gateway to read. Omitted = the default stack in ~/.clawops/config.json"),
|
|
170
|
+
tailLines: z.number().int().optional().default(100).describe("How many of the most recent lines to return. Keep it small; output is trimmed to 8KB regardless"),
|
|
171
|
+
sinceMin: z.number().int().optional().describe("Lines since N minutes ago")
|
|
172
172
|
});
|
|
173
173
|
var clawops_logs_tailDescription = "Tail recent gateway logs from a clawops-managed instance.\n\nUse when: the user wants to investigate recent activity or errors, or\nasks \"what's been happening\" on the gateway.\n\nDo NOT use when: the user wants real-time streaming logs (those are not\nwell-suited to tool calls; suggest the user run `clawops logs -f` directly\nin their terminal). Do NOT use for instance-level system logs: no tool runs\narbitrary remote commands, so tell the user to run `clawops ssh --command\n'journalctl ...'` themselves.";
|
|
174
174
|
var clawops_logs_tailAnnotations = {
|
|
@@ -180,8 +180,8 @@ var clawops_logs_tailAnnotations = {
|
|
|
180
180
|
toolsets: ["cli", "read"]
|
|
181
181
|
};
|
|
182
182
|
var clawops_monitorSchema = z.object({
|
|
183
|
-
stackName: z.string().optional(),
|
|
184
|
-
tailLines: z.number().int().optional().default(5)
|
|
183
|
+
stackName: z.string().optional().describe("Stack name. Defaults to active stack."),
|
|
184
|
+
tailLines: z.number().int().optional().default(5).describe("Log lines to include in snapshot.")
|
|
185
185
|
});
|
|
186
186
|
var clawops_monitorDescription = "Take a live snapshot of a running clawops stack: gateway health, container\nstatus, resource usage (CPU, memory, disk), and recent log lines.\n\nUse when: the user wants to know if the gateway is running, how much\nmemory or CPU it is using, what recent log activity looks like, or\nwants a quick health overview richer than clawops_status.\n\nDo NOT use when: the user wants real-time streaming logs (use\nclawops_logs_tail or suggest `clawops logs -f`). Do NOT use for\nconfiguration queries (use clawops_config_get).";
|
|
187
187
|
var clawops_monitorAnnotations = {
|
|
@@ -203,8 +203,8 @@ var clawops_stacks_listAnnotations = {
|
|
|
203
203
|
toolsets: ["admin", "read"]
|
|
204
204
|
};
|
|
205
205
|
var clawops_config_getSchema = z.object({
|
|
206
|
-
stackName: z.string().optional(),
|
|
207
|
-
key: z.string().optional()
|
|
206
|
+
stackName: z.string().optional().describe("Which stack's gateway config to read. Omitted = the default stack in ~/.clawops/config.json"),
|
|
207
|
+
key: z.string().optional().describe("Dot-path config key, e.g., gateway.auth.mode. Omit to dump the full config.")
|
|
208
208
|
});
|
|
209
209
|
var clawops_config_getDescription = "Read a configuration value from the remote OpenClaw gateway.\n\nUse when: the user wants to inspect current OpenClaw config (e.g., which\nmodel provider is active, which channels are enabled).\n\nDo NOT use when: the user wants to change the config \u2014 use\nclawops_config_set instead.";
|
|
210
210
|
var clawops_config_getAnnotations = {
|
|
@@ -216,7 +216,7 @@ var clawops_config_getAnnotations = {
|
|
|
216
216
|
toolsets: ["cli", "read"]
|
|
217
217
|
};
|
|
218
218
|
var clawops_agents_listSchema = z.object({
|
|
219
|
-
stackName: z.string().optional()
|
|
219
|
+
stackName: z.string().optional().describe("Which stack's agents to list. Omitted = the default stack in ~/.clawops/config.json")
|
|
220
220
|
});
|
|
221
221
|
var clawops_agents_listDescription = "List agents currently registered on the remote OpenClaw gateway.\n\nUse when: the user wants to see which agents are running, debug agent\nrouting, or count active workspaces.\n\nDo NOT use when: the user wants one agent's logs \u2014 no tool exposes those; tell\nthe user to run `clawops agents logs <name>`.";
|
|
222
222
|
var clawops_agents_listAnnotations = {
|
|
@@ -228,15 +228,15 @@ var clawops_agents_listAnnotations = {
|
|
|
228
228
|
toolsets: ["cli", "read"]
|
|
229
229
|
};
|
|
230
230
|
var clawops_upSchema = z.object({
|
|
231
|
-
stackName: z.string().optional(),
|
|
232
|
-
provider: z.enum(["aws", "gcp", "azure", "local"]).optional(),
|
|
233
|
-
region: z.string().optional(),
|
|
234
|
-
instanceType: z.string().optional().default("small"),
|
|
235
|
-
sshCidr: z.string().optional(),
|
|
236
|
-
gatewayCidr: z.string().optional(),
|
|
237
|
-
publishGateway: z.enum(["loopback", "all"]).optional(),
|
|
238
|
-
openclawVersion: z.string().optional(),
|
|
239
|
-
dryRun: z.boolean().optional().default(false)
|
|
231
|
+
stackName: z.string().optional().describe("Name for the stack to provision, and the name every later command refers to it by. Omitted = the default stack in ~/.clawops/config.json"),
|
|
232
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).optional().describe("Defaults to provider configured for this stack"),
|
|
233
|
+
region: z.string().optional().describe("Cloud region to deploy into, in the provider's own spelling (us-east-1, us-central1, eastus). Omitted = the region recorded for the stack"),
|
|
234
|
+
instanceType: z.string().optional().default("small").describe("A clawops size (micro|small|medium|large|gpu) or a provider-native machine type.\nNot an enum: Azure offers SKU families per subscription, and an account offered\nnone of the five sizes clawops names would otherwise have no way to deploy.\n"),
|
|
235
|
+
sshCidr: z.string().optional().describe("CIDR(s) allowed to reach SSH, comma-separated, or 'auto' for the caller's own\naddress. Omitted means none, and nothing will be able to connect \u2014 including\nevery clawops day-two command.\n"),
|
|
236
|
+
gatewayCidr: z.string().optional().describe("CIDR(s) allowed to reach the gateway port. Requires publishGateway=all."),
|
|
237
|
+
publishGateway: z.enum(["loopback", "all"]).optional().describe("Which interface the gateway binds. 'all' serves plaintext HTTP."),
|
|
238
|
+
openclawVersion: z.string().optional().describe("semver or 'stable'/'dev'"),
|
|
239
|
+
dryRun: z.boolean().optional().default(false).describe("Show what would be created and change nothing. Use this first when the user has not yet approved a spend")
|
|
240
240
|
});
|
|
241
241
|
var clawops_upDescription = 'Provision and deploy a clawops stack. Idempotent \u2014 re-running with no spec\nchange produces no diff. Long-running (median 3min, p99 8min) so emits\nprogress notifications per R12.\n\nUse when: the user explicitly asks to deploy, provision, create, or "spin\nup" a stack. Always after the user has reviewed a plan\n(clawops_plan first when in doubt).\n\nDo NOT use when: the user has not yet generated a plan and is in\nexploratory/discovery mode \u2014 use clawops_plan first. Do NOT use for an\nexisting stack you only need to update; refresh first.';
|
|
242
242
|
var clawops_upAnnotations = {
|
|
@@ -248,8 +248,8 @@ var clawops_upAnnotations = {
|
|
|
248
248
|
toolsets: ["cli"]
|
|
249
249
|
};
|
|
250
250
|
var clawops_destroySchema = z.object({
|
|
251
|
-
stackName: z.string(),
|
|
252
|
-
yes: z.boolean().optional().default(false)
|
|
251
|
+
stackName: z.string().describe("The stack to destroy. Required, and worth repeating back to the user before calling: this deletes every resource it provisioned"),
|
|
252
|
+
yes: z.boolean().optional().default(false).describe("Skip elicitation; CI/scripted use only")
|
|
253
253
|
});
|
|
254
254
|
var clawops_destroyDescription = "Destroy a clawops stack. Removes ALL provisioned resources. Triggers\nelicitation confirmation showing the resource diff before execution\n(R19). Cannot be undone.\n\nUse when: the user explicitly asks to destroy, tear down, delete, or\nremove a stack. Always confirm the stack name.\n\nDo NOT use when: the user wants to stop the gateway temporarily \u2014 that is not\na destroy, and no tool stops a gateway; clawops_gateway_restart is the only\ngateway tool. Do NOT use when in doubt about which stack; list first with\nclawops_stacks_list.";
|
|
255
255
|
var clawops_destroyAnnotations = {
|
|
@@ -261,8 +261,8 @@ var clawops_destroyAnnotations = {
|
|
|
261
261
|
toolsets: ["cli"]
|
|
262
262
|
};
|
|
263
263
|
var clawops_applySchema = z.object({
|
|
264
|
-
planPath: z.string(),
|
|
265
|
-
yes: z.boolean().optional().default(false)
|
|
264
|
+
planPath: z.string().describe("Absolute path to plan JSON (R7)"),
|
|
265
|
+
yes: z.boolean().optional().default(false).describe("Skip the confirmation and apply immediately. Only when the user has already approved this specific plan")
|
|
266
266
|
});
|
|
267
267
|
var clawops_applyDescription = "Apply a previously-generated Maker plan (deploy-plan.schema.json).\nDeterministic \u2014 the plan describes exactly what will be created.\n\nUse when: the user has a plan file path and wants to apply it. This is\nthe agent-friendly path for any deploy/destroy operation.\n\nDo NOT use when: there's no plan file \u2014 generate one first with\nclawops_plan.";
|
|
268
268
|
var clawops_applyAnnotations = {
|
|
@@ -274,16 +274,16 @@ var clawops_applyAnnotations = {
|
|
|
274
274
|
toolsets: ["cli"]
|
|
275
275
|
};
|
|
276
276
|
var clawops_planSchema = z.object({
|
|
277
|
-
stackName: z.string().optional(),
|
|
278
|
-
provider: z.enum(["aws", "gcp", "azure", "local"]).optional(),
|
|
279
|
-
region: z.string().optional(),
|
|
280
|
-
instanceType: z.string().optional(),
|
|
281
|
-
openclawVersion: z.string().optional(),
|
|
282
|
-
sshCidr: z.string().optional(),
|
|
283
|
-
gatewayCidr: z.string().optional(),
|
|
284
|
-
publishGateway: z.enum(["loopback", "all"]).optional(),
|
|
285
|
-
privateOnly: z.boolean().optional(),
|
|
286
|
-
outPath: z.string().optional()
|
|
277
|
+
stackName: z.string().optional().describe("Which stack the plan is for. Omitted = the default stack in ~/.clawops/config.json"),
|
|
278
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).optional().describe("Cloud to plan against. Omitted = the provider recorded for the stack. 'local' has no plan/apply path and is refused"),
|
|
279
|
+
region: z.string().optional().describe("Cloud region, in the provider's own spelling (us-east-1, us-central1, eastus). Omitted = the region recorded for the stack"),
|
|
280
|
+
instanceType: z.string().optional().describe("A clawops alias (micro|small|medium|large|gpu) or a machine type the cloud names itself, e.g. t3.small"),
|
|
281
|
+
openclawVersion: z.string().optional().describe("semver, or 'stable'/'dev'"),
|
|
282
|
+
sshCidr: z.string().optional().describe("CIDR(s) allowed to reach SSH, comma-separated, or 'auto' for this machine. Omitted = none, and nothing will be able to connect"),
|
|
283
|
+
gatewayCidr: z.string().optional().describe("CIDR(s) allowed to reach the gateway port, or 'auto'. Requires publishGateway=all"),
|
|
284
|
+
publishGateway: z.enum(["loopback", "all"]).optional().describe("Which interface the gateway binds. loopback (default) keeps it off the network"),
|
|
285
|
+
privateOnly: z.boolean().optional().describe("Close public SSH and gateway access; reach the stack over its tailnet. Requires a verified tailnet address (clawops_harden with tailscale), and refuses unless that address answers SSH now"),
|
|
286
|
+
outPath: z.string().optional().describe("Absolute path to write plan; if omitted, plan returned inline")
|
|
287
287
|
});
|
|
288
288
|
var clawops_planDescription = "Generate a Maker deploy plan (does NOT apply). Plan is JSON conforming to\ndeploy-plan.schema.json \u2014 review before applying.\n\nUse when: the user wants to see what would be created before committing,\nor you (the agent) need a reviewable artifact for the user to approve.\n\nDo NOT use when: the user has explicitly asked to deploy and you already\nhave their approval \u2014 go directly to clawops_up.";
|
|
289
289
|
var clawops_planAnnotations = {
|
|
@@ -295,10 +295,10 @@ var clawops_planAnnotations = {
|
|
|
295
295
|
toolsets: ["cli", "read"]
|
|
296
296
|
};
|
|
297
297
|
var clawops_config_setSchema = z.object({
|
|
298
|
-
stackName: z.string().optional(),
|
|
299
|
-
key: z.string(),
|
|
300
|
-
value: z.string(),
|
|
301
|
-
restart: z.boolean().optional().default(false)
|
|
298
|
+
stackName: z.string().optional().describe("Which stack's gateway config to write. Omitted = the default stack in ~/.clawops/config.json"),
|
|
299
|
+
key: z.string().describe("Dotted path into the gateway config, e.g. models.provider or channels.slack.enabled"),
|
|
300
|
+
value: z.string().describe("Stringified; JSON for complex values"),
|
|
301
|
+
restart: z.boolean().optional().default(false).describe("Restart the gateway so the change takes effect. Without it the value is written and the running gateway keeps the old one")
|
|
302
302
|
});
|
|
303
303
|
var clawops_config_setDescription = "Set a configuration value on the remote OpenClaw gateway. Optionally\nrestarts the gateway after.\n\nUse when: the user wants to change OpenClaw configuration (model\nprovider, channel auth, gateway port).\n\nDo NOT use when: the user is reading config \u2014 use clawops_config_get.\nDo NOT bulk-edit; one key at a time so changes are auditable (R21).";
|
|
304
304
|
var clawops_config_setAnnotations = {
|
|
@@ -310,9 +310,9 @@ var clawops_config_setAnnotations = {
|
|
|
310
310
|
toolsets: ["cli"]
|
|
311
311
|
};
|
|
312
312
|
var clawops_config_unsetSchema = z.object({
|
|
313
|
-
stackName: z.string().optional(),
|
|
314
|
-
key: z.string(),
|
|
315
|
-
restart: z.boolean().optional().default(false)
|
|
313
|
+
stackName: z.string().optional().describe("Which stack's gateway config to write. Omitted = the default stack in ~/.clawops/config.json"),
|
|
314
|
+
key: z.string().describe("Dot-path config key to remove"),
|
|
315
|
+
restart: z.boolean().optional().default(false).describe("Restart the gateway so the removal takes effect. Without it the key is removed and the running gateway keeps the old value")
|
|
316
316
|
});
|
|
317
317
|
var clawops_config_unsetDescription = "Remove a configuration key from the remote OpenClaw gateway config, reverting\nit to the OpenClaw default.\n\nUse when: the user wants to delete a config key entirely (e.g., remove a\nchannel, clear an override).\n\nDo NOT use when: the user wants to set the key to a new value \u2014 use\nclawops_config_set instead.";
|
|
318
318
|
var clawops_config_unsetAnnotations = {
|
|
@@ -324,7 +324,7 @@ var clawops_config_unsetAnnotations = {
|
|
|
324
324
|
toolsets: ["cli"]
|
|
325
325
|
};
|
|
326
326
|
var clawops_config_validateSchema = z.object({
|
|
327
|
-
stackName: z.string().optional()
|
|
327
|
+
stackName: z.string().optional().describe("Which stack's deployed config to validate. Omitted = the default stack in ~/.clawops/config.json")
|
|
328
328
|
});
|
|
329
329
|
var clawops_config_validateDescription = "Validate the remote OpenClaw gateway config against the known schema. Checks\nfor structural errors (wrong types, unknown top-level keys) that would cause\nOpenClaw to fail on startup.\n\nUse when: the user wants to verify config before restarting the gateway, or\nafter editing openclaw.json manually.\n\nDo NOT use when: the user wants to change config \u2014 use clawops_config_set.";
|
|
330
330
|
var clawops_config_validateAnnotations = {
|
|
@@ -336,7 +336,7 @@ var clawops_config_validateAnnotations = {
|
|
|
336
336
|
toolsets: ["cli", "read"]
|
|
337
337
|
};
|
|
338
338
|
var clawops_gateway_restartSchema = z.object({
|
|
339
|
-
stackName: z.string().optional()
|
|
339
|
+
stackName: z.string().optional().describe("Which stack's gateway to restart. Omitted = the default stack in ~/.clawops/config.json")
|
|
340
340
|
});
|
|
341
341
|
var clawops_gateway_restartDescription = "Restart the OpenClaw gateway daemon on the remote instance.\n\nUse when: a gateway-wide config change requires reload, or the gateway is\nreported as unresponsive.\n\nNote: OpenClaw 2.0 removed per-agent restart; `gateway restart` is the only\nrestart it offers, and it affects every agent on the host. Brief downtime (~10s).";
|
|
342
342
|
var clawops_gateway_restartAnnotations = {
|
|
@@ -347,13 +347,32 @@ var clawops_gateway_restartAnnotations = {
|
|
|
347
347
|
openWorldHint: true,
|
|
348
348
|
toolsets: ["cli"]
|
|
349
349
|
};
|
|
350
|
+
var clawops_initSchema = z.object({
|
|
351
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).describe("Which cloud this stack deploys to, or 'local' for a machine you already have"),
|
|
352
|
+
stackName: z.string().optional().describe('Name for the stack, used by every later call. Omitted = "default"'),
|
|
353
|
+
stateUrl: z.string().optional().describe("Where Pulumi state lives, e.g. s3://bucket/clawops, gs://bucket/clawops, azblob://container. Omitted = clawops names one from the cloud account it can see, which needs credentials"),
|
|
354
|
+
region: z.string().optional().describe("Cloud region in the provider's own spelling. Omitted = us-east-1 (aws), us-central1 (gcp), eastus (azure)"),
|
|
355
|
+
host: z.string().optional().describe("[local only] Hostname or IP of the machine to manage. Required when provider is local"),
|
|
356
|
+
sshUser: z.string().optional().describe("[local only] SSH login user. Omitted = root"),
|
|
357
|
+
sshPort: z.number().int().optional().describe("[local only] SSH port. Omitted = 22"),
|
|
358
|
+
force: z.boolean().optional().describe("Overwrite a stack that already exists. Refused without it, because replacing a state backend orphans the state it points at")
|
|
359
|
+
});
|
|
360
|
+
var clawops_initDescription = "Register a stack and write ~/.clawops/config.json: the provider, the state backend, the\nregion, and an SSH key pair generated if one is not already there. Nothing is provisioned\nand nothing is charged; this only creates local configuration.\n\nUse when: any other clawops tool reports that there is no config, or the user wants to add\na second stack alongside the ones they have. This is the first call on a machine that has\nnever run clawops \u2014 a fresh container, a new laptop, a sandbox.\n\nAdding a stack is additive and safe: existing stacks are kept. Overwriting one needs\nforce: true, because changing a state backend orphans the Pulumi state it points at \u2014 the\ninfrastructure stays up and clawops can no longer see or destroy it.\n\nFor aws, gcp and azure, stateUrl can be omitted and clawops names a bucket from the\naccount it can see; that needs cloud credentials in the environment, so in a sandbox pass\nstateUrl explicitly. The local provider needs host instead, and no cloud account at all.\n\nDo NOT use when: the user wants to deploy \u2014 that is clawops_up, after this. Credentials\nare never passed here: clawops reads them from the environment (R6).";
|
|
361
|
+
var clawops_initAnnotations = {
|
|
362
|
+
title: "Initialise clawops Config",
|
|
363
|
+
readOnlyHint: false,
|
|
364
|
+
destructiveHint: false,
|
|
365
|
+
idempotentHint: false,
|
|
366
|
+
openWorldHint: false,
|
|
367
|
+
toolsets: ["cli"]
|
|
368
|
+
};
|
|
350
369
|
var clawops_hardenSchema = z.object({
|
|
351
|
-
stackName: z.string().optional(),
|
|
352
|
-
options: z.string().optional(),
|
|
353
|
-
dryRun: z.boolean().optional().default(false),
|
|
354
|
-
tailscale: z.boolean().optional().default(false),
|
|
355
|
-
tailscaleRevert: z.boolean().optional().default(false),
|
|
356
|
-
yes: z.boolean().optional().default(false)
|
|
370
|
+
stackName: z.string().optional().describe("Which stack to harden. Omitted = the default stack in ~/.clawops/config.json"),
|
|
371
|
+
options: z.string().optional().describe("Comma-separated module IDs; default is every defaultOn module for the provider"),
|
|
372
|
+
dryRun: z.boolean().optional().default(false).describe("Report the current state, change nothing"),
|
|
373
|
+
tailscale: z.boolean().optional().default(false).describe("Join the tailnet, verify this machine reaches the host there, then use that address"),
|
|
374
|
+
tailscaleRevert: z.boolean().optional().default(false).describe("Leave the tailnet and go back to the public address"),
|
|
375
|
+
yes: z.boolean().optional().default(false).describe("Skip elicitation; CI/scripted use only")
|
|
357
376
|
});
|
|
358
377
|
var clawops_hardenDescription = "Apply security hardening to a deployed stack: SSH, UFW, fail2ban,\nunattended-upgrades, the Docker socket, and per-cloud checks. Optionally join\nthe stack to a Tailscale network and reach it there instead of over the public\ninternet.\n\nUse when: the user asks to harden, secure, or lock down a stack; asks what the\nhardening report says (with dryRun: true, which changes nothing); or asks to put\na stack on their tailnet.\n\ntailscale: true installs Tailscale, joins the tailnet as clawops-<stack>, and\nthen moves clawops onto that address \u2014 but only after opening an SSH session to\nit, against host keys pinned over the connection already trusted. If that fails,\nnothing is recorded and the public address stays in use. The auth key comes from\n`clawops secret set TAILSCALE_AUTH_KEY` and is never passed through this tool\n(R6).\n\ntailscaleRevert: true takes the host back off the tailnet, over its public\naddress. On a private-only stack it refuses and names the plan/apply commands\nthat reopen SSH first \u2014 relay them rather than trying to work around it.\n\nTo close the public ports afterwards, plan with privateOnly: true and apply that\nplan; this tool does not change firewall rules.\n\nDo NOT use when: the user wants to know whether a stack is healthy \u2014 that is\nclawops_doctor. Do NOT pass tailscale and tailscaleRevert together.";
|
|
359
378
|
var clawops_hardenAnnotations = {
|
|
@@ -365,10 +384,10 @@ var clawops_hardenAnnotations = {
|
|
|
365
384
|
toolsets: ["cli"]
|
|
366
385
|
};
|
|
367
386
|
var clawops_workflow_deploy_appSchema = z.object({
|
|
368
|
-
provider: z.enum(["aws", "gcp", "azure", "local"]),
|
|
369
|
-
region: z.string().optional(),
|
|
370
|
-
stackName: z.string().optional().default("default"),
|
|
371
|
-
instanceType: z.enum(["micro", "small", "medium", "large", "gpu"]).optional().default("small")
|
|
387
|
+
provider: z.enum(["aws", "gcp", "azure", "local"]).describe("Cloud to deploy to. Omitted = the default provider in ~/.clawops/config.json"),
|
|
388
|
+
region: z.string().optional().describe("Cloud region, in the provider's own spelling (us-east-1, us-central1, eastus). Omitted = the provider's default"),
|
|
389
|
+
stackName: z.string().optional().default("default").describe("Name for the new stack. Omitted = the default stack name in ~/.clawops/config.json"),
|
|
390
|
+
instanceType: z.enum(["micro", "small", "medium", "large", "gpu"]).optional().default("small").describe("Machine size: a clawops alias (micro|small|medium|large|gpu) or a type the cloud names itself, e.g. t3.small")
|
|
372
391
|
});
|
|
373
392
|
var clawops_workflow_deploy_appDescription = 'Single-tool workflow that takes a user from "I want to deploy OpenClaw\nto <provider>" to a verified, healthy gateway. Internally: plan \u2192 user\nconfirms (elicitation) \u2192 up \u2192 wait for healthy \u2192 return URL.\n\nUse when: the user expresses end-to-end deployment intent ("deploy to\nAWS", "spin up an OpenClaw on GCP for me").\n\nDo NOT use when: the user is mid-deployment and only needs one step\n(e.g., they already have a plan; use clawops_apply). Do NOT use for\ndestroying or updating \u2014 separate workflows.';
|
|
374
393
|
var clawops_workflow_deploy_appAnnotations = {
|
|
@@ -380,7 +399,7 @@ var clawops_workflow_deploy_appAnnotations = {
|
|
|
380
399
|
toolsets: ["workflow"]
|
|
381
400
|
};
|
|
382
401
|
var clawops_workflow_recoverSchema = z.object({
|
|
383
|
-
stackName: z.string().optional()
|
|
402
|
+
stackName: z.string().optional().describe("Which stack to diagnose. Omitted = the default stack in ~/.clawops/config.json")
|
|
384
403
|
});
|
|
385
404
|
var clawops_workflow_recoverDescription = `Diagnostic workflow for an unhealthy stack. Internally: status check \u2192
|
|
386
405
|
gateway logs \u2192 agent logs \u2192 systemd service status \u2192 produces a structured
|
|
@@ -400,7 +419,7 @@ var clawops_workflow_recoverAnnotations = {
|
|
|
400
419
|
toolsets: ["workflow", "read"]
|
|
401
420
|
};
|
|
402
421
|
var clawops_task_statusSchema = z.object({
|
|
403
|
-
taskId: z.string()
|
|
422
|
+
taskId: z.string().describe("The taskId returned by a long-running tool such as clawops_up, clawops_apply or clawops_destroy")
|
|
404
423
|
});
|
|
405
424
|
var clawops_task_statusDescription = "Poll the status of a long-running clawops task (returned by clawops_up,\nclawops_destroy, clawops_apply, etc.). Per R12 streaming model.\n\nUse when: the user is waiting on a long-running deploy/destroy and wants\nprogress, OR you need to check whether a previously-started operation\nfinished.\n\nDo NOT use when: there is no active taskId \u2014 start the operation first.";
|
|
406
425
|
var clawops_task_statusAnnotations = {
|
|
@@ -427,6 +446,7 @@ var TOOLSETS = {
|
|
|
427
446
|
"clawops_config_unset",
|
|
428
447
|
"clawops_config_validate",
|
|
429
448
|
"clawops_gateway_restart",
|
|
449
|
+
"clawops_init",
|
|
430
450
|
"clawops_harden",
|
|
431
451
|
"clawops_task_status"
|
|
432
452
|
],
|
|
@@ -602,6 +622,29 @@ async function handleStacksList(_input, _server) {
|
|
|
602
622
|
return { content: [{ type: "text", text: JSON.stringify({ stacks }, null, 2) }] };
|
|
603
623
|
}
|
|
604
624
|
|
|
625
|
+
// src/mcp/tools/_confirm.ts
|
|
626
|
+
async function confirmDestructive(server, opts) {
|
|
627
|
+
const capabilities = server.server.getClientCapabilities();
|
|
628
|
+
if (!capabilities?.elicitation) {
|
|
629
|
+
return {
|
|
630
|
+
confirmed: false,
|
|
631
|
+
reason: `This client cannot show a confirmation prompt, and ${opts.what} is not something clawops will do unconfirmed. Ask the user to confirm, then call this tool again with \`yes: true\`. (The client did not declare the MCP elicitation capability.)`
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
const elicit = await server.server.elicitInput({
|
|
635
|
+
message: opts.message,
|
|
636
|
+
requestedSchema: {
|
|
637
|
+
type: "object",
|
|
638
|
+
properties: { confirmed: { type: "boolean", title: opts.title } },
|
|
639
|
+
required: ["confirmed"]
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
if (elicit.action !== "accept" || !elicit.content?.["confirmed"]) {
|
|
643
|
+
return { confirmed: false, reason: `Cancelled \u2014 ${opts.what} did not run. Nothing was changed.` };
|
|
644
|
+
}
|
|
645
|
+
return { confirmed: true };
|
|
646
|
+
}
|
|
647
|
+
|
|
605
648
|
// src/mcp/tools/cli/config.ts
|
|
606
649
|
async function handleConfigGet(input, _server) {
|
|
607
650
|
const ac = new AbortController();
|
|
@@ -623,16 +666,13 @@ async function handleConfigGet(input, _server) {
|
|
|
623
666
|
}
|
|
624
667
|
}
|
|
625
668
|
async function handleConfigSet(input, server) {
|
|
626
|
-
const
|
|
669
|
+
const confirmation = await confirmDestructive(server, {
|
|
627
670
|
message: `Set ${input.key} = ${input.value} on stack "${input.stackName ?? "default"}"?`,
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
properties: { confirmed: { type: "boolean", title: "Confirm config change" } },
|
|
631
|
-
required: ["confirmed"]
|
|
632
|
-
}
|
|
671
|
+
title: "Confirm config change",
|
|
672
|
+
what: "changing gateway configuration"
|
|
633
673
|
});
|
|
634
|
-
if (
|
|
635
|
-
return okText(
|
|
674
|
+
if (!confirmation.confirmed) {
|
|
675
|
+
return okText(confirmation.reason);
|
|
636
676
|
}
|
|
637
677
|
const ac = new AbortController();
|
|
638
678
|
const ctx = buildContext({ stack: input.stackName });
|
|
@@ -672,16 +712,13 @@ async function handleConfigSet(input, server) {
|
|
|
672
712
|
}
|
|
673
713
|
}
|
|
674
714
|
async function handleConfigUnset(input, server) {
|
|
675
|
-
const
|
|
715
|
+
const confirmation = await confirmDestructive(server, {
|
|
676
716
|
message: `Remove config key "${input.key}" on stack "${input.stackName ?? "default"}"?`,
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
properties: { confirmed: { type: "boolean", title: "Confirm key removal" } },
|
|
680
|
-
required: ["confirmed"]
|
|
681
|
-
}
|
|
717
|
+
title: "Confirm key removal",
|
|
718
|
+
what: "changing gateway configuration"
|
|
682
719
|
});
|
|
683
|
-
if (
|
|
684
|
-
return okText(
|
|
720
|
+
if (!confirmation.confirmed) {
|
|
721
|
+
return okText(confirmation.reason);
|
|
685
722
|
}
|
|
686
723
|
const ac = new AbortController();
|
|
687
724
|
const ctx = buildContext({ stack: input.stackName });
|
|
@@ -786,16 +823,13 @@ async function handleAgentsList(input, _server) {
|
|
|
786
823
|
|
|
787
824
|
// src/mcp/tools/cli/gateway.ts
|
|
788
825
|
async function handleGatewayRestart(input, server) {
|
|
789
|
-
const
|
|
826
|
+
const confirmation = await confirmDestructive(server, {
|
|
790
827
|
message: `Restart the OpenClaw gateway on stack "${input.stackName ?? "default"}"? This will briefly interrupt connections.`,
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
properties: { confirmed: { type: "boolean", title: "Confirm restart" } },
|
|
794
|
-
required: ["confirmed"]
|
|
795
|
-
}
|
|
828
|
+
title: "Confirm restart",
|
|
829
|
+
what: "restarting the gateway"
|
|
796
830
|
});
|
|
797
|
-
if (
|
|
798
|
-
return okText(
|
|
831
|
+
if (!confirmation.confirmed) {
|
|
832
|
+
return okText(confirmation.reason);
|
|
799
833
|
}
|
|
800
834
|
const ctx = buildContext({ stack: input.stackName });
|
|
801
835
|
const conn = await resolveConn(ctx);
|
|
@@ -855,16 +889,13 @@ function makeProgressEmitter(server, progressToken) {
|
|
|
855
889
|
// src/mcp/tools/cli/up.ts
|
|
856
890
|
async function handleUp(input, server) {
|
|
857
891
|
if (!input.dryRun) {
|
|
858
|
-
const
|
|
892
|
+
const confirmation = await confirmDestructive(server, {
|
|
859
893
|
message: `Deploy stack "${input.stackName ?? "default"}" (provider: ${input.provider ?? "from config"}, instance: ${input.instanceType})? This will provision cloud resources.`,
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
properties: { confirmed: { type: "boolean", title: "Confirm deployment" } },
|
|
863
|
-
required: ["confirmed"]
|
|
864
|
-
}
|
|
894
|
+
title: "Confirm deployment",
|
|
895
|
+
what: "provisioning cloud resources"
|
|
865
896
|
});
|
|
866
|
-
if (
|
|
867
|
-
return okText(
|
|
897
|
+
if (!confirmation.confirmed) {
|
|
898
|
+
return okText(confirmation.reason);
|
|
868
899
|
}
|
|
869
900
|
}
|
|
870
901
|
const ctx = buildContext({ stack: input.stackName, provider: input.provider });
|
|
@@ -877,7 +908,7 @@ async function handleUp(input, server) {
|
|
|
877
908
|
);
|
|
878
909
|
}
|
|
879
910
|
const { localOpts } = stackConfig;
|
|
880
|
-
const { localBootstrap } = await import("./bootstrap-
|
|
911
|
+
const { localBootstrap } = await import("./bootstrap-3PBVY7MA.js");
|
|
881
912
|
const ac = new AbortController();
|
|
882
913
|
const state = await localBootstrap({
|
|
883
914
|
host: localOpts.host,
|
|
@@ -900,8 +931,8 @@ async function handleUp(input, server) {
|
|
|
900
931
|
const progressToken = void 0;
|
|
901
932
|
const emit = makeProgressEmitter(server, progressToken);
|
|
902
933
|
startTask(taskId, `clawops_up stack=${ctx.stackName}`);
|
|
903
|
-
const { generatePlan: generatePlan2 } = await import("./generate-
|
|
904
|
-
const { applyPlan: applyPlan2 } = await import("./apply-
|
|
934
|
+
const { generatePlan: generatePlan2 } = await import("./generate-NE54BATS.js");
|
|
935
|
+
const { applyPlan: applyPlan2 } = await import("./apply-JARPVA5Y.js");
|
|
905
936
|
const { resolveNetworkFlags } = await import("./network-args-PYJRJBYO.js");
|
|
906
937
|
const { detectEgressIp } = await import("./firewall-5VKZ4WBH.js");
|
|
907
938
|
const network = await resolveNetworkFlags(
|
|
@@ -953,16 +984,13 @@ async function handleUp(input, server) {
|
|
|
953
984
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
954
985
|
async function handleDestroy(input, server) {
|
|
955
986
|
if (!input.yes) {
|
|
956
|
-
const
|
|
987
|
+
const confirmation = await confirmDestructive(server, {
|
|
957
988
|
message: `DESTROY stack "${input.stackName}"? This permanently deletes all provisioned resources and cannot be undone.`,
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
properties: { confirmed: { type: "boolean", title: "Confirm destruction (irreversible)" } },
|
|
961
|
-
required: ["confirmed"]
|
|
962
|
-
}
|
|
989
|
+
title: "Confirm destruction (irreversible)",
|
|
990
|
+
what: "destroying a stack"
|
|
963
991
|
});
|
|
964
|
-
if (
|
|
965
|
-
return okText(
|
|
992
|
+
if (!confirmation.confirmed) {
|
|
993
|
+
return okText(confirmation.reason);
|
|
966
994
|
}
|
|
967
995
|
}
|
|
968
996
|
const ctx = buildContext({ stack: input.stackName });
|
|
@@ -1019,7 +1047,7 @@ async function handlePlan(input, _server) {
|
|
|
1019
1047
|
let network = resolved;
|
|
1020
1048
|
if (input.privateOnly) {
|
|
1021
1049
|
const { privateOnlyNetwork, assertTailnetReachable } = await import("./private-only-DIA26I2E.js");
|
|
1022
|
-
const { probeSsh } = await import("./tailscale-cutover-
|
|
1050
|
+
const { probeSsh } = await import("./tailscale-cutover-EKAQSDXP.js");
|
|
1023
1051
|
network = privateOnlyNetwork(flags, resolved, ctx.config.stacks[stackName]?.tailscale, stackName);
|
|
1024
1052
|
await assertTailnetReachable(ctx, (conn) => probeSsh(conn));
|
|
1025
1053
|
}
|
|
@@ -1056,30 +1084,31 @@ async function handleHarden(input, server) {
|
|
|
1056
1084
|
"tailscale and tailscaleRevert do the opposite of each other; pass one, not both."
|
|
1057
1085
|
);
|
|
1058
1086
|
}
|
|
1059
|
-
const { getConfig: getConfig2 } = await import("./store-
|
|
1087
|
+
const { getConfig: getConfig2 } = await import("./store-YOLQYXMB.js");
|
|
1060
1088
|
const config = getConfig2();
|
|
1061
|
-
if (!config)
|
|
1089
|
+
if (!config) {
|
|
1090
|
+
return errText(
|
|
1091
|
+
"No clawops config on this machine. Call clawops_init first to register a stack; until then every clawops tool will say this."
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1062
1094
|
const ctx = buildContext({ stack: input.stackName });
|
|
1063
1095
|
if (!input.dryRun && !input.yes) {
|
|
1064
1096
|
const what = input.tailscaleRevert ? `Take "${ctx.stackName}" off its tailnet and go back to its public address?` : input.tailscale ? `Harden "${ctx.stackName}" and join it to your tailnet? clawops will use the tailnet address afterwards.` : `Apply hardening modules to "${ctx.stackName}"? This changes the running host.`;
|
|
1065
|
-
const
|
|
1097
|
+
const confirmation = await confirmDestructive(server, {
|
|
1066
1098
|
message: what,
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
properties: { confirmed: { type: "boolean", title: "Confirm" } },
|
|
1070
|
-
required: ["confirmed"]
|
|
1071
|
-
}
|
|
1099
|
+
title: "Confirm",
|
|
1100
|
+
what: "changing a running host"
|
|
1072
1101
|
});
|
|
1073
|
-
if (
|
|
1074
|
-
return okText(
|
|
1102
|
+
if (!confirmation.confirmed) {
|
|
1103
|
+
return okText(confirmation.reason);
|
|
1075
1104
|
}
|
|
1076
1105
|
}
|
|
1077
|
-
const { revertTailnet, cutOverToTailnet, connectionFor } = await import("./flows-
|
|
1106
|
+
const { revertTailnet, cutOverToTailnet, connectionFor } = await import("./flows-HGJIA6EL.js");
|
|
1078
1107
|
if (input.tailscaleRevert) {
|
|
1079
1108
|
const outcome = await revertTailnet(ctx, config);
|
|
1080
1109
|
return outcome.ok ? okText(outcome.message) : errText(outcome.reason);
|
|
1081
1110
|
}
|
|
1082
|
-
const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary, makeTailscaleModule } = await import("./harden-
|
|
1111
|
+
const { MODULE_CATALOG, resolveModules, runHardening, formatHardenSummary, makeTailscaleModule } = await import("./harden-RUOUA5BV.js");
|
|
1083
1112
|
const forStack = makeTailscaleModule(ctx.stackName);
|
|
1084
1113
|
const resolved = resolveModules(MODULE_CATALOG, input.options, ctx.adapter.name).map(
|
|
1085
1114
|
(m) => m.id === "tailscale" ? forStack : m
|
|
@@ -1121,6 +1150,32 @@ async function handleHarden(input, server) {
|
|
|
1121
1150
|
return failed.length > 0 ? errText(content) : okText(content);
|
|
1122
1151
|
}
|
|
1123
1152
|
|
|
1153
|
+
// src/mcp/tools/cli/init.ts
|
|
1154
|
+
async function handleInit(input, _server) {
|
|
1155
|
+
const { initStack } = await import("./init-HOPXDNWY.js");
|
|
1156
|
+
const result = await initStack({
|
|
1157
|
+
provider: input.provider,
|
|
1158
|
+
stackName: input.stackName,
|
|
1159
|
+
stateUrl: input.stateUrl,
|
|
1160
|
+
region: input.region,
|
|
1161
|
+
force: input.force,
|
|
1162
|
+
host: input.host,
|
|
1163
|
+
sshUser: input.sshUser,
|
|
1164
|
+
sshPort: input.sshPort
|
|
1165
|
+
});
|
|
1166
|
+
if (!result.ok) return errText(result.reason);
|
|
1167
|
+
const lines = [
|
|
1168
|
+
`Stack "${result.stackName}" registered for ${result.provider}.`,
|
|
1169
|
+
`Config: ${result.configPath}`,
|
|
1170
|
+
`State backend: ${result.stateUrl}`,
|
|
1171
|
+
...result.region ? [`Region: ${result.region}`] : [],
|
|
1172
|
+
`SSH key: ${result.keyPath}${result.keyGenerated ? " (generated now)" : " (already existed)"}`,
|
|
1173
|
+
"",
|
|
1174
|
+
"Nothing has been provisioned and nothing is being charged. Deploying from here needs cloud credentials in the environment clawops runs in; clawops_doctor reports which are missing."
|
|
1175
|
+
];
|
|
1176
|
+
return okText(lines.join("\n"));
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1124
1179
|
// src/mcp/tools/cli/apply.ts
|
|
1125
1180
|
import { readFileSync } from "fs";
|
|
1126
1181
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
@@ -1142,18 +1197,15 @@ ${validation.errors.join("\n")}`);
|
|
|
1142
1197
|
}
|
|
1143
1198
|
if (!input.yes) {
|
|
1144
1199
|
const diffLine = plan.diff ? `${plan.diff.create.length} to create, ${plan.diff.update.length} to update, ${plan.diff.delete.length} to delete` : "diff unavailable";
|
|
1145
|
-
const
|
|
1200
|
+
const confirmation = await confirmDestructive(server, {
|
|
1146
1201
|
message: `Apply plan for stack "${plan.spec.stackName}" (${plan.spec.provider})?
|
|
1147
1202
|
Changes: ${diffLine}.
|
|
1148
1203
|
This will provision cloud resources and may incur costs.`,
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
properties: { confirmed: { type: "boolean", title: "Confirm plan apply" } },
|
|
1152
|
-
required: ["confirmed"]
|
|
1153
|
-
}
|
|
1204
|
+
title: "Confirm plan apply",
|
|
1205
|
+
what: "applying a plan"
|
|
1154
1206
|
});
|
|
1155
|
-
if (
|
|
1156
|
-
return okText(
|
|
1207
|
+
if (!confirmation.confirmed) {
|
|
1208
|
+
return okText(confirmation.reason);
|
|
1157
1209
|
}
|
|
1158
1210
|
}
|
|
1159
1211
|
const taskId = randomUUID4();
|
|
@@ -1282,17 +1334,14 @@ Falling back to direct deployment.`);
|
|
|
1282
1334
|
);
|
|
1283
1335
|
}
|
|
1284
1336
|
const diffLine = plan.diff ? `${plan.diff.create.length} to create, ${plan.diff.update.length} to update, ${plan.diff.delete.length} to delete` : "? changes";
|
|
1285
|
-
const
|
|
1337
|
+
const confirmation = await confirmDestructive(server, {
|
|
1286
1338
|
message: `Deploy OpenClaw on ${provider} (stack: "${input.stackName}", instance: ${input.instanceType}${input.region ? `, region: ${input.region}` : ""})?
|
|
1287
1339
|
Changes: ${diffLine}. This will provision cloud resources and may incur costs.`,
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
properties: { confirmed: { type: "boolean", title: "Confirm end-to-end deployment" } },
|
|
1291
|
-
required: ["confirmed"]
|
|
1292
|
-
}
|
|
1340
|
+
title: "Confirm end-to-end deployment",
|
|
1341
|
+
what: "provisioning cloud resources"
|
|
1293
1342
|
});
|
|
1294
|
-
if (
|
|
1295
|
-
return okText(
|
|
1343
|
+
if (!confirmation.confirmed) {
|
|
1344
|
+
return okText(confirmation.reason);
|
|
1296
1345
|
}
|
|
1297
1346
|
parts.push("### Step 2: Apply");
|
|
1298
1347
|
const emit = makeProgressEmitter(server, void 0);
|
|
@@ -1371,6 +1420,7 @@ var TOOL_REGISTRY = {
|
|
|
1371
1420
|
clawops_destroy: makeEntry(clawops_destroySchema, clawops_destroyAnnotations, handleDestroy, clawops_destroyDescription),
|
|
1372
1421
|
clawops_apply: makeEntry(clawops_applySchema, clawops_applyAnnotations, handleApply, clawops_applyDescription),
|
|
1373
1422
|
clawops_plan: makeEntry(clawops_planSchema, clawops_planAnnotations, handlePlan, clawops_planDescription),
|
|
1423
|
+
clawops_init: makeEntry(clawops_initSchema, clawops_initAnnotations, handleInit, clawops_initDescription),
|
|
1374
1424
|
clawops_harden: makeEntry(clawops_hardenSchema, clawops_hardenAnnotations, handleHarden, clawops_hardenDescription),
|
|
1375
1425
|
clawops_config_set: makeEntry(clawops_config_setSchema, clawops_config_setAnnotations, handleConfigSet, clawops_config_setDescription),
|
|
1376
1426
|
clawops_config_unset: makeEntry(clawops_config_unsetSchema, clawops_config_unsetAnnotations, handleConfigUnset, clawops_config_unsetDescription),
|
|
@@ -1676,7 +1726,7 @@ function bearerFrom(header) {
|
|
|
1676
1726
|
return match?.[1]?.trim();
|
|
1677
1727
|
}
|
|
1678
1728
|
async function serveMcp(opts) {
|
|
1679
|
-
const { version } = await import("./package-
|
|
1729
|
+
const { version } = await import("./package-MF5LPITL.js");
|
|
1680
1730
|
const makeServer = () => {
|
|
1681
1731
|
const server = new McpServer({ name: "clawops", version });
|
|
1682
1732
|
registerTools(server, opts);
|