@clawops/cli 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -1
- package/dist/{apply-KBF7OPWL.js → apply-5RREMN3L.js} +5 -4
- package/dist/{aws-KQBWY43W.js → aws-FRE2JVAZ.js} +9 -4
- package/dist/{azure-4EJFVJZL.js → azure-PVC3AQVC.js} +11 -4
- package/dist/{bootstrap-UYCOEJQX.js → bootstrap-G4UZ2FKH.js} +3 -3
- package/dist/chunk-6ZFIFDBJ.js +41 -0
- package/dist/{chunk-BRPU7AQC.js → chunk-A2I76FTA.js} +13 -1
- package/dist/chunk-JYQZJMD3.js +764 -0
- package/dist/{chunk-ACYJBSLJ.js → chunk-T5EX55GP.js} +4 -4
- package/dist/{chunk-SSB6SGPQ.js → chunk-UAA6YOOP.js} +2 -2
- package/dist/{chunk-UDNZUSKA.js → chunk-ZFNPM2WG.js} +1 -1
- package/dist/{chunk-LU63NZD3.js → chunk-ZONXY3C6.js} +6 -2
- package/dist/cli.js +369 -79
- package/dist/{context-VUAYRAJY.js → context-PSGEX2D7.js} +2 -2
- package/dist/{gcp-SKURG3L6.js → gcp-BXDTC6EK.js} +60 -17
- package/dist/{generate-PZPLG3ZM.js → generate-Z7DBMANX.js} +3 -3
- package/dist/overlay-store-ADZPD7EU.js +11 -0
- package/dist/{package-SE3M4NJA.js → package-WAJRGBBM.js} +2 -1
- package/dist/{remote-config-JQ77SRC2.js → remote-config-QF5TT7GU.js} +1 -1
- package/dist/{server-4DNHLGEG.js → server-IWLZJ4EU.js} +98 -24
- package/dist/state-PRBIIN7I.js +17 -0
- package/package.json +2 -1
- package/dist/chunk-QJ6ERXHN.js +0 -266
package/dist/chunk-QJ6ERXHN.js
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
buildContext
|
|
4
|
-
} from "./chunk-ACYJBSLJ.js";
|
|
5
|
-
import {
|
|
6
|
-
acquireSession,
|
|
7
|
-
drainPool
|
|
8
|
-
} from "./chunk-ZVOEQCNW.js";
|
|
9
|
-
import {
|
|
10
|
-
OPENCLAW_CONFIG,
|
|
11
|
-
atomicWriteConfig,
|
|
12
|
-
restartGateway
|
|
13
|
-
} from "./chunk-UDNZUSKA.js";
|
|
14
|
-
import {
|
|
15
|
-
StateError
|
|
16
|
-
} from "./chunk-KGXPLI7W.js";
|
|
17
|
-
|
|
18
|
-
// src/mcp/tools/_conn.ts
|
|
19
|
-
async function resolveConn(ctx) {
|
|
20
|
-
if (ctx.adapter.name === "local") {
|
|
21
|
-
const state = ctx.localState;
|
|
22
|
-
if (!state) throw new StateError("Stack has no local state \u2014 run `clawops up` first.");
|
|
23
|
-
return {
|
|
24
|
-
host: state.sshHost,
|
|
25
|
-
port: state.sshPort,
|
|
26
|
-
user: state.sshUser,
|
|
27
|
-
privateKeyPath: state.privateKeyPath,
|
|
28
|
-
knownHostsPath: state.knownHostsPath
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
const { extractBaseOutputs } = await import("./outputs-DJHBY7EE.js");
|
|
32
|
-
const stack = await ctx.getStack();
|
|
33
|
-
const outputMap = await stack.outputs();
|
|
34
|
-
const outputs = Object.fromEntries(
|
|
35
|
-
Object.entries(outputMap).map(([k, v]) => [k, v.value])
|
|
36
|
-
);
|
|
37
|
-
if (!outputs["publicIp"]) {
|
|
38
|
-
throw new StateError("Stack has no outputs \u2014 run `clawops up` first.");
|
|
39
|
-
}
|
|
40
|
-
const base = extractBaseOutputs(outputs);
|
|
41
|
-
return ctx.adapter.getConnectionInfo({
|
|
42
|
-
...base,
|
|
43
|
-
privateKeyPath: ctx.config.ssh.keyPath,
|
|
44
|
-
knownHostsPath: ctx.config.ssh.knownHostsPath
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
function errText(message) {
|
|
48
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
49
|
-
}
|
|
50
|
-
function okText(t) {
|
|
51
|
-
return { content: [{ type: "text", text: t }] };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// src/mcp/tools/cli/config.ts
|
|
55
|
-
var VALID_AUTH_MODES = /* @__PURE__ */ new Set(["none", "token", "password", "trusted-proxy"]);
|
|
56
|
-
async function handleConfigGet(input, _server) {
|
|
57
|
-
const ac = new AbortController();
|
|
58
|
-
const ctx = buildContext({ stack: input.stackName });
|
|
59
|
-
const conn = await resolveConn(ctx);
|
|
60
|
-
const { session, release } = await acquireSession(conn);
|
|
61
|
-
try {
|
|
62
|
-
const result = await session.exec(`cat ${OPENCLAW_CONFIG}`, ac.signal);
|
|
63
|
-
let cfg;
|
|
64
|
-
try {
|
|
65
|
-
cfg = JSON.parse(result.stdout);
|
|
66
|
-
} catch {
|
|
67
|
-
return errText(`Cannot parse ${OPENCLAW_CONFIG}: ${result.stderr || result.stdout}`);
|
|
68
|
-
}
|
|
69
|
-
const value = input.key ? getPath(cfg, input.key) : cfg;
|
|
70
|
-
return okText(JSON.stringify(value, null, 2));
|
|
71
|
-
} finally {
|
|
72
|
-
release();
|
|
73
|
-
drainPool();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
async function handleConfigSet(input, server) {
|
|
77
|
-
const elicit = await server.server.elicitInput({
|
|
78
|
-
message: `Set ${input.key} = ${input.value} on stack "${input.stackName ?? "default"}"?`,
|
|
79
|
-
requestedSchema: {
|
|
80
|
-
type: "object",
|
|
81
|
-
properties: { confirmed: { type: "boolean", title: "Confirm config change" } },
|
|
82
|
-
required: ["confirmed"]
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
if (elicit.action !== "accept" || !elicit.content?.["confirmed"]) {
|
|
86
|
-
return okText("Config change cancelled.");
|
|
87
|
-
}
|
|
88
|
-
const ac = new AbortController();
|
|
89
|
-
const ctx = buildContext({ stack: input.stackName });
|
|
90
|
-
const conn = await resolveConn(ctx);
|
|
91
|
-
const { session, release } = await acquireSession(conn);
|
|
92
|
-
try {
|
|
93
|
-
const readResult = await session.exec(`cat ${OPENCLAW_CONFIG}`, ac.signal);
|
|
94
|
-
let cfg;
|
|
95
|
-
try {
|
|
96
|
-
cfg = JSON.parse(readResult.stdout);
|
|
97
|
-
} catch {
|
|
98
|
-
return errText(`Cannot parse ${OPENCLAW_CONFIG}: ${readResult.stderr}`);
|
|
99
|
-
}
|
|
100
|
-
let parsedValue = input.value;
|
|
101
|
-
try {
|
|
102
|
-
parsedValue = JSON.parse(input.value);
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
setPath(cfg, input.key, parsedValue);
|
|
106
|
-
try {
|
|
107
|
-
await atomicWriteConfig(session, cfg, ac.signal);
|
|
108
|
-
} catch (err) {
|
|
109
|
-
return errText(`Failed to write config: ${err.message}`);
|
|
110
|
-
}
|
|
111
|
-
let note = "";
|
|
112
|
-
if (input.restart) {
|
|
113
|
-
try {
|
|
114
|
-
await restartGateway(session, ac.signal);
|
|
115
|
-
note = " (gateway restarted)";
|
|
116
|
-
} catch (err) {
|
|
117
|
-
return errText(`Gateway restart failed: ${err.message}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return okText(`Config set: ${input.key}${note}`);
|
|
121
|
-
} finally {
|
|
122
|
-
release();
|
|
123
|
-
drainPool();
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
async function handleConfigUnset(input, server) {
|
|
127
|
-
const elicit = await server.server.elicitInput({
|
|
128
|
-
message: `Remove config key "${input.key}" on stack "${input.stackName ?? "default"}"?`,
|
|
129
|
-
requestedSchema: {
|
|
130
|
-
type: "object",
|
|
131
|
-
properties: { confirmed: { type: "boolean", title: "Confirm key removal" } },
|
|
132
|
-
required: ["confirmed"]
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
if (elicit.action !== "accept" || !elicit.content?.["confirmed"]) {
|
|
136
|
-
return okText("Config unset cancelled.");
|
|
137
|
-
}
|
|
138
|
-
const ac = new AbortController();
|
|
139
|
-
const ctx = buildContext({ stack: input.stackName });
|
|
140
|
-
const conn = await resolveConn(ctx);
|
|
141
|
-
const { session, release } = await acquireSession(conn);
|
|
142
|
-
try {
|
|
143
|
-
const readResult = await session.exec(`cat ${OPENCLAW_CONFIG}`, ac.signal);
|
|
144
|
-
let cfg;
|
|
145
|
-
try {
|
|
146
|
-
cfg = JSON.parse(readResult.stdout);
|
|
147
|
-
} catch {
|
|
148
|
-
return errText(`Cannot parse ${OPENCLAW_CONFIG}: ${readResult.stderr}`);
|
|
149
|
-
}
|
|
150
|
-
deletePath(cfg, input.key);
|
|
151
|
-
try {
|
|
152
|
-
await atomicWriteConfig(session, cfg, ac.signal);
|
|
153
|
-
} catch (err) {
|
|
154
|
-
return errText(`Failed to write config: ${err.message}`);
|
|
155
|
-
}
|
|
156
|
-
let note = "";
|
|
157
|
-
if (input.restart) {
|
|
158
|
-
try {
|
|
159
|
-
await restartGateway(session, ac.signal);
|
|
160
|
-
note = " (gateway restarted)";
|
|
161
|
-
} catch (err) {
|
|
162
|
-
return errText(`Gateway restart failed: ${err.message}`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return okText(`Config key removed: ${input.key}${note}`);
|
|
166
|
-
} finally {
|
|
167
|
-
release();
|
|
168
|
-
drainPool();
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
async function handleConfigValidate(input, _server) {
|
|
172
|
-
const ac = new AbortController();
|
|
173
|
-
const ctx = buildContext({ stack: input.stackName });
|
|
174
|
-
const conn = await resolveConn(ctx);
|
|
175
|
-
const { session, release } = await acquireSession(conn);
|
|
176
|
-
try {
|
|
177
|
-
const result = await session.exec(`cat ${OPENCLAW_CONFIG}`, ac.signal);
|
|
178
|
-
let cfg;
|
|
179
|
-
try {
|
|
180
|
-
cfg = JSON.parse(result.stdout);
|
|
181
|
-
} catch {
|
|
182
|
-
return okText(JSON.stringify({ valid: false, issues: [`Invalid JSON: ${result.stderr || result.stdout}`] }));
|
|
183
|
-
}
|
|
184
|
-
const issues = validateOpenclawConfig(cfg);
|
|
185
|
-
return okText(JSON.stringify({ valid: issues.length === 0, issues }));
|
|
186
|
-
} finally {
|
|
187
|
-
release();
|
|
188
|
-
drainPool();
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
function getPath(obj, dotKey) {
|
|
192
|
-
return dotKey.split(".").reduce((cur, k) => {
|
|
193
|
-
if (cur !== null && typeof cur === "object") return cur[k];
|
|
194
|
-
return void 0;
|
|
195
|
-
}, obj);
|
|
196
|
-
}
|
|
197
|
-
function setPath(obj, dotKey, value) {
|
|
198
|
-
const keys = dotKey.split(".");
|
|
199
|
-
let cur = obj;
|
|
200
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
201
|
-
const k = keys[i];
|
|
202
|
-
if (typeof cur[k] !== "object" || cur[k] === null) cur[k] = {};
|
|
203
|
-
cur = cur[k];
|
|
204
|
-
}
|
|
205
|
-
cur[keys[keys.length - 1]] = value;
|
|
206
|
-
}
|
|
207
|
-
function deletePath(obj, dotKey) {
|
|
208
|
-
const keys = dotKey.split(".");
|
|
209
|
-
let cur = obj;
|
|
210
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
211
|
-
const k = keys[i];
|
|
212
|
-
if (typeof cur[k] !== "object" || cur[k] === null) return;
|
|
213
|
-
cur = cur[k];
|
|
214
|
-
}
|
|
215
|
-
delete cur[keys[keys.length - 1]];
|
|
216
|
-
}
|
|
217
|
-
function validateOpenclawConfig(cfg) {
|
|
218
|
-
const issues = [];
|
|
219
|
-
if ("version" in cfg) {
|
|
220
|
-
issues.push(
|
|
221
|
-
"Top-level 'version' is not a valid OpenClaw config key. Use 'meta.lastTouchedVersion' (string) instead."
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
if ("channels" in cfg && Array.isArray(cfg["channels"])) {
|
|
225
|
-
issues.push(
|
|
226
|
-
`'channels' must be an object keyed by provider name (e.g. {"discord":{...}}), not an array.`
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
const meta = cfg["meta"];
|
|
230
|
-
if (meta !== void 0 && (typeof meta !== "object" || Array.isArray(meta) || meta === null)) {
|
|
231
|
-
issues.push("'meta' must be an object.");
|
|
232
|
-
} else if (meta && typeof meta === "object") {
|
|
233
|
-
const ltv = meta["lastTouchedVersion"];
|
|
234
|
-
if (ltv !== void 0 && typeof ltv !== "string") {
|
|
235
|
-
issues.push("'meta.lastTouchedVersion' must be a string.");
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
const gateway = cfg["gateway"];
|
|
239
|
-
if (gateway !== void 0 && typeof gateway === "object" && !Array.isArray(gateway) && gateway !== null) {
|
|
240
|
-
const gw = gateway;
|
|
241
|
-
if ("port" in gw && typeof gw["port"] !== "number") {
|
|
242
|
-
issues.push("'gateway.port' must be a number.");
|
|
243
|
-
}
|
|
244
|
-
const auth = gw["auth"];
|
|
245
|
-
if (auth !== void 0 && typeof auth === "object" && !Array.isArray(auth) && auth !== null) {
|
|
246
|
-
const mode = auth["mode"];
|
|
247
|
-
if (mode !== void 0 && !VALID_AUTH_MODES.has(mode)) {
|
|
248
|
-
issues.push(
|
|
249
|
-
`'gateway.auth.mode' must be one of: ${[...VALID_AUTH_MODES].join(", ")}. Got: "${mode}".`
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return issues;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export {
|
|
258
|
-
resolveConn,
|
|
259
|
-
errText,
|
|
260
|
-
okText,
|
|
261
|
-
handleConfigGet,
|
|
262
|
-
handleConfigSet,
|
|
263
|
-
handleConfigUnset,
|
|
264
|
-
handleConfigValidate,
|
|
265
|
-
validateOpenclawConfig
|
|
266
|
-
};
|