@lacneu/wix-openclaw 0.2.2 → 0.3.1

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.
@@ -11,25 +11,313 @@
11
11
  // - `timeoutBehavior` accepts "allow" | "deny".
12
12
  // - `pluginId` is set automatically by the hook runner — do not set it
13
13
  // yourself.
14
+ import { createHash } from "node:crypto";
14
15
  const DEFAULT_TIMEOUT_MS = 600_000; // 10 minutes
15
- const PARAM_PREVIEW_CHARS = 600;
16
16
  /**
17
- * Truncate the parameter snapshot so we never surface a wall of JSON to
18
- * the operator. We strip `siteId` since it's covered by the config and
19
- * adds noise to the prompt.
17
+ * THE PROTOCOL'S OWN LIMITS, not ours.
18
+ *
19
+ * `PluginApprovalRequestParamsSchema` (openclaw gateway, plugin-approvals)
20
+ * declares `title` as 1–80 characters and `description` as 1–256. A longer one
21
+ * is not truncated by the gateway — the request fails validation, so the
22
+ * operator is never asked and the tool is blocked. The previous prompt embedded
23
+ * a 600-character JSON preview under a paragraph of boilerplate and could not
24
+ * fit: every gated tool was affected, not only the SEO ones.
25
+ *
26
+ * So the description is BUILT to the budget rather than written and hoped for.
20
27
  */
21
- function previewParams(params) {
22
- const { siteId: _siteId, ...rest } = params; // eslint-disable-line @typescript-eslint/no-unused-vars
28
+ const APPROVAL_TITLE_MAX = 80;
29
+ const APPROVAL_DESCRIPTION_MAX = 256;
30
+ /**
31
+ * Parameters that must reach the operator, in priority order.
32
+ *
33
+ * With 256 characters there is no room for the full parameters, so what is
34
+ * shown has to be what DECIDES: a redirect carries two free-form paths, and
35
+ * `forceReplace` — the flag that deletes an existing redirect for good — must
36
+ * never be the part that falls off the end.
37
+ *
38
+ * TABLE-DRIVEN so a destructive parameter cannot be added to a tool without
39
+ * saying where it ranks in the prompt.
40
+ */
41
+ const APPROVAL_HIGHLIGHTS = {
42
+ wix_seo_create_redirect: ["forceReplace", "redirect"],
43
+ wix_seo_delete_redirect: ["redirectId"],
44
+ wix_seo_bulk_create_redirects: ["redirects"],
45
+ wix_seo_bulk_delete_redirects: ["redirectIds"],
46
+ };
47
+ /** One-line effect warnings, shown FIRST because they are the reason to refuse. */
48
+ const APPROVAL_EFFECTS = {
49
+ // A create destroys in TWO ways, and the second needs no existing redirect:
50
+ // a redirect takes precedence over a real page at the same path, so creating
51
+ // one from a path that still serves a page makes that page unreachable. The
52
+ // pre-flight cannot see it — it reads redirects, not pages — so the prompt is
53
+ // the only place the operator can be told.
54
+ wix_seo_create_redirect: "may DELETE a redirect; HIDES any real page at `from` (permanent)",
55
+ wix_seo_delete_redirect: "permanent",
56
+ wix_seo_bulk_create_redirects: "not atomic; may DELETE redirects; HIDES real pages at a `from`",
57
+ wix_seo_bulk_delete_redirects: "permanent",
58
+ };
59
+ /** Longest a single value may occupy in the prompt, so one long path cannot
60
+ * crowd out everything after it. */
61
+ const VALUE_MAX = 60;
62
+ /** Make control characters VISIBLE instead of letting them act.
63
+ *
64
+ * The description is rendered as a line-structured message, so a `from` path,
65
+ * a language or a parameter name carrying a newline can paint fields that were
66
+ * never sent — on the one surface whose whole purpose is an operator deciding
67
+ * whether to allow an irreversible write. The generic branch was safe by
68
+ * accident, `JSON.stringify` escaping these; the redirect rendering, which
69
+ * exists precisely to be more readable than JSON, was not. */
70
+ function sanitize(value) {
71
+ return value.replace(
72
+ // eslint-disable-next-line no-control-regex
73
+ /[\u0000-\u001f\u007f\u0085\u2028\u2029]/g, (c) => {
74
+ if (c === "\n")
75
+ return "\\n";
76
+ if (c === "\r")
77
+ return "\\r";
78
+ if (c === "\t")
79
+ return "\\t";
80
+ return `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`;
81
+ });
82
+ }
83
+ /** Shorten in the MIDDLE: a path's beginning and its end are what identify it,
84
+ * and two long paths sharing a prefix are told apart only by their tails.
85
+ * Neutralises controls FIRST, so truncation can never be what lets one
86
+ * through. */
87
+ function shorten(raw, max = VALUE_MAX) {
88
+ const value = sanitize(raw);
89
+ if (value.length <= max)
90
+ return value;
91
+ const head = Math.ceil((max - 1) / 2);
92
+ const tail = Math.floor((max - 1) / 2);
93
+ return `${value.slice(0, head)}…${value.slice(value.length - tail)}`;
94
+ }
95
+ /** A short, stable fingerprint of a whole set, so two approvals for DIFFERENT
96
+ * sets never read identically even when only a few members are shown.
97
+ *
98
+ * SHA-256, truncated to 128 bits. A 32-bit FNV was small enough to collide on
99
+ * purpose: two batches whose first three members matched could be given the
100
+ * same digest, and with only three members sampled the two prompts became
101
+ * indistinguishable — for two different permanent deletions. */
102
+ function digest(input) {
103
+ return createHash("sha256").update(input).digest("hex").slice(0, 32);
104
+ }
105
+ /** A stable serialisation of the WHOLE value, before anything is shortened for
106
+ * display. What the fingerprint must identify is the batch, not its preview. */
107
+ function canonical(value) {
108
+ const walk = (v) => {
109
+ if (Array.isArray(v))
110
+ return v.map(walk);
111
+ if (v !== null && typeof v === "object") {
112
+ // KEYS SORTED. `JSON.stringify` preserves insertion order, so the same
113
+ // batch written with its fields in a different order fingerprinted
114
+ // differently — an identity that changes for no reason is no identity.
115
+ const obj = v;
116
+ const out = {};
117
+ for (const k of Object.keys(obj).sort())
118
+ out[k] = walk(obj[k]);
119
+ return out;
120
+ }
121
+ return v;
122
+ };
123
+ try {
124
+ return JSON.stringify(walk(value)) ?? String(value);
125
+ }
126
+ catch {
127
+ return String(value);
128
+ }
129
+ }
130
+ /** How many members of a list to name before the fingerprint stands in for the
131
+ * rest. */
132
+ const LIST_SAMPLE = 3;
133
+ /** Compact rendering of a highlighted value.
134
+ *
135
+ * A list reports its LENGTH, then a few members, then a fingerprint of the
136
+ * whole set. Length alone made two bulk deletes of completely different GUIDs
137
+ * produce the same prompt — the operator was approving a permanent deletion
138
+ * with nothing on screen that distinguished it from another one.
139
+ */
140
+ /** `from → to [exact|group, language]`, or null when the value is not a
141
+ * redirect. Shared by the single and the bulk rendering: a bulk create's
142
+ * members went through the generic JSON path, so up to 500 GROUP rules over
143
+ * whole branches could read the same as 500 exact ones. */
144
+ function renderRedirect(value, max) {
145
+ if (value === null || typeof value !== "object")
146
+ return null;
147
+ const obj = value;
148
+ if (typeof obj.from !== "string" || typeof obj.to !== "string")
149
+ return null;
150
+ const options = obj.options;
151
+ const scope = options?.groupRedirect === true ? "group" : "exact";
152
+ // Bounded and neutralised like the paths: `language` went in raw, so it was
153
+ // both an injection point and a way to crowd out the rest of the line.
154
+ const language = typeof obj.language === "string" && obj.language.length > 0
155
+ ? shorten(obj.language, 16)
156
+ : "all";
157
+ return `${shorten(obj.from, max)} → ${shorten(obj.to, max)} [${scope}, ${language}]`;
158
+ }
159
+ /** Widest blast radius first: a group rule carries every path under its own,
160
+ * and a rule with no language applies to every language. Sampling in order
161
+ * showed three exact rules while the global group ones sat behind a `+N`. */
162
+ function blastRadius(value) {
163
+ if (value === null || typeof value !== "object")
164
+ return 0;
165
+ const obj = value;
166
+ const options = obj.options;
167
+ const group = options?.groupRedirect === true ? 2 : 0;
168
+ const global = typeof obj.language === "string" && obj.language.length > 0 ? 0 : 1;
169
+ return group + global;
170
+ }
171
+ /** `2 group/all, 1 exact/fr` — what the batch DOES, over every member, in the
172
+ * space a sample cannot cover. */
173
+ function scopeTally(value) {
174
+ const counts = new Map();
175
+ for (const v of value) {
176
+ const rendered = renderRedirect(v, 1);
177
+ if (rendered === null)
178
+ return null;
179
+ const scope = rendered.slice(rendered.lastIndexOf("[") + 1, -1);
180
+ counts.set(scope, (counts.get(scope) ?? 0) + 1);
181
+ }
182
+ return [...counts.entries()].map(([k, n]) => `${n} ${k}`).join(", ");
183
+ }
184
+ function renderHighlight(rawKey, value) {
185
+ // A PARAMETER NAME IS CALLER-SUPPLIED TOO. The tail loop renders every key the
186
+ // call carries, declared or not.
187
+ const key = shorten(rawKey, 40);
188
+ if (Array.isArray(value)) {
189
+ const members = value.map((v) => {
190
+ const asRedirect = renderRedirect(v, 12);
191
+ if (asRedirect !== null)
192
+ return asRedirect;
193
+ return typeof v === "string" ? v : (JSON.stringify(v) ?? "");
194
+ });
195
+ const sample = value
196
+ .map((v, i) => ({ i, radius: blastRadius(v) }))
197
+ .sort((a, b) => b.radius - a.radius || a.i - b.i)
198
+ .slice(0, LIST_SAMPLE)
199
+ .map(({ i }) => shorten(members[i], 40))
200
+ .join(", ");
201
+ const rest = members.length - Math.min(LIST_SAMPLE, members.length);
202
+ const tally = scopeTally(value);
203
+ // THREE PARTS, NOT ONE. Joined into a single string, a long tally — eight
204
+ // distinct languages is enough — pushed the whole thing over the budget and
205
+ // `fitParts` skipped it entire: no count, no member, no fingerprint, and an
206
+ // operator approving an irreversible batch with nothing identifying it.
207
+ // Split, the core survives and only the detail is dropped.
208
+ return [
209
+ // Fingerprint over the ORIGINAL values, not the shortened renderings:
210
+ // `/sameX-A-different-Ytail` and `/sameX-B-different-Ytail` both render as
211
+ // `/sameX…Ytail`, so a digest taken after truncation gave two different
212
+ // destructive batches the same identity.
213
+ `${key}: ${members.length}× #${digest(canonical(value))}`,
214
+ ...(tally !== null ? [`(${tally})`] : []),
215
+ `[${sample}${rest > 0 ? `, +${rest}` : ""}]`,
216
+ ];
217
+ }
218
+ // A redirect reads as `from → to` WITH ITS SCOPE. Showing only the paths made
219
+ // an exact French-only rule and a global group rule over a whole branch
220
+ // produce the same prompt — and the second can make far more pages
221
+ // unreachable than the first.
222
+ const asRedirect = renderRedirect(value, 40);
223
+ if (asRedirect !== null)
224
+ return asRedirect;
23
225
  let json;
24
226
  try {
25
- json = JSON.stringify(rest, null, 2);
227
+ json = JSON.stringify(value);
26
228
  }
27
229
  catch {
28
- json = "<unserializable params>";
230
+ json = "<unserializable>";
231
+ }
232
+ return `${key}: ${shorten(json)}`;
233
+ }
234
+ /** Join what fits, in order, marking that something was left out.
235
+ *
236
+ * SKIPS an oversized part rather than stopping at it: stopping meant one long
237
+ * value hid every fact after it, which is how `from` and `to` could vanish
238
+ * from a prompt entirely. Every part is already length-bounded, so skipping is
239
+ * the rare case, not the normal one. */
240
+ const OMISSION_MARKER = " \u00b7 \u2026";
241
+ function fitParts(parts, budget) {
242
+ const out = [];
243
+ let used = 0;
244
+ let dropped = false;
245
+ for (const part of parts) {
246
+ const cost = out.length === 0 ? part.length : part.length + 3;
247
+ // Room for the marker is reserved once something HAS been dropped — that is
248
+ // when it will certainly be appended. The reservation used to be the other
249
+ // way round, so after the first drop the remaining parts filled the budget
250
+ // to the brim and the final `slice` ate the marker: an approval that had
251
+ // silently omitted parameters read as complete, on destructive calls.
252
+ if (used + cost > budget - (dropped ? OMISSION_MARKER.length : 0)) {
253
+ dropped = true;
254
+ continue;
255
+ }
256
+ out.push(part);
257
+ used += cost;
258
+ }
259
+ if (!dropped)
260
+ return out.join(" · ").slice(0, budget);
261
+ // Reserving as we go is not enough on its own: the drop can be the LAST
262
+ // part, after earlier ones already filled the budget. Give the marker its
263
+ // room by surrendering trailing parts — parts are ordered by what decides a
264
+ // refusal, so the least decisive go first, and a truthful "something is
265
+ // missing" outranks one more shown value.
266
+ let joined = out.join(" · ");
267
+ while (out.length > 0 && joined.length + OMISSION_MARKER.length > budget) {
268
+ out.pop();
269
+ joined = out.join(" · ");
29
270
  }
30
- if (json.length <= PARAM_PREVIEW_CHARS)
31
- return json;
32
- return `${json.slice(0, PARAM_PREVIEW_CHARS)}…`;
271
+ if (out.length === 0)
272
+ return "";
273
+ return `${joined}${OMISSION_MARKER}`.slice(0, budget);
274
+ }
275
+ /**
276
+ * The approval description, guaranteed to satisfy the protocol.
277
+ *
278
+ * Ordered by what decides a refusal: the irreversible effect, the site the call
279
+ * actually lands on (the preview used to strip `siteId`, so on a multi-site key
280
+ * the operator never saw which tenant), then each highlighted parameter.
281
+ */
282
+ export function buildApprovalDescription(toolName, params, defaultSiteId) {
283
+ const site = typeof params.siteId === "string" && params.siteId.length > 0
284
+ ? params.siteId
285
+ : defaultSiteId || "<no site configured>";
286
+ const parts = [];
287
+ const effect = APPROVAL_EFFECTS[toolName];
288
+ if (effect !== undefined)
289
+ parts.push(effect.toUpperCase());
290
+ parts.push(`site ${site}`);
291
+ // Highlighted parameters first, in the table's order, then EVERYTHING ELSE
292
+ // the call carries. Without the tail, a gated tool with no table entry —
293
+ // every pre-existing one — would show the operator nothing but a site.
294
+ const highlighted = APPROVAL_HIGHLIGHTS[toolName] ?? [];
295
+ const seen = new Set(["siteId"]);
296
+ const push = (rendered) => {
297
+ if (Array.isArray(rendered))
298
+ parts.push(...rendered);
299
+ else
300
+ parts.push(rendered);
301
+ };
302
+ for (const key of highlighted) {
303
+ if (!(key in params))
304
+ continue;
305
+ seen.add(key);
306
+ push(renderHighlight(key, params[key]));
307
+ }
308
+ for (const [key, value] of Object.entries(params)) {
309
+ if (seen.has(key))
310
+ continue;
311
+ push(renderHighlight(key, value));
312
+ }
313
+ const body = fitParts(parts, APPROVAL_DESCRIPTION_MAX);
314
+ // fitParts already respects the budget; the guard is belt-and-braces so a
315
+ // future edit cannot reintroduce the failure this function exists to prevent.
316
+ return body.slice(0, APPROVAL_DESCRIPTION_MAX) || toolName;
317
+ }
318
+ /** The approval title, likewise bounded (protocol: 1–80). */
319
+ export function buildApprovalTitle(toolName) {
320
+ return `Wix: confirm ${toolName}`.slice(0, APPROVAL_TITLE_MAX);
33
321
  }
34
322
  /**
35
323
  * Build a `before_tool_call` handler bound to a resolved Wix config.
@@ -42,18 +330,13 @@ export function createApprovalHook(config, logger) {
42
330
  return undefined;
43
331
  if (!config.approvalRequired.has(event.toolName))
44
332
  return undefined;
45
- const description = `Tool \`${event.toolName}\` is about to run with the following parameters:\n\n` +
46
- "```json\n" +
47
- previewParams(event.params) +
48
- "\n```\n\n" +
49
- "Approve to execute, deny to cancel. The call will deny automatically " +
50
- "if no decision is made within 10 minutes.";
333
+ const description = buildApprovalDescription(event.toolName, event.params, config.defaultSiteId);
51
334
  if (config.logLevel === "debug") {
52
335
  logger.debug?.(`wix: requesting approval for ${event.toolName} (runId=${event.runId ?? "?"})`);
53
336
  }
54
337
  return {
55
338
  requireApproval: {
56
- title: `Wix: confirm ${event.toolName}`,
339
+ title: buildApprovalTitle(event.toolName),
57
340
  description,
58
341
  severity: "critical",
59
342
  timeoutMs: DEFAULT_TIMEOUT_MS,
@@ -1 +1 @@
1
- {"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/hooks/approval.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,0EAA0E;AAC1E,iCAAiC;AACjC,EAAE;AACF,yEAAyE;AACzE,4BAA4B;AAC5B,uEAAuE;AACvE,kDAAkD;AAClD,yEAAyE;AACzE,gBAAgB;AA4BhB,MAAM,kBAAkB,GAAG,OAAO,CAAC,CAAC,aAAa;AACjD,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC;;;;GAIG;AACH,SAAS,aAAa,CAAC,MAA+B;IACpD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,wDAAwD;IACrG,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,yBAAyB,CAAC;IACnC,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,IAAI,mBAAmB;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,GAAG,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAyB,EACzB,MAAiB;IAEjB,OAAO,SAAS,cAAc,CAC5B,KAA0B;QAE1B,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAC;QAEnE,MAAM,WAAW,GACf,UAAU,KAAK,CAAC,QAAQ,uDAAuD;YAC/E,WAAW;YACX,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC;YAC3B,WAAW;YACX,uEAAuE;YACvE,2CAA2C,CAAC;QAE9C,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAChC,MAAM,CAAC,KAAK,EAAE,CACZ,gCAAgC,KAAK,CAAC,QAAQ,WAAW,KAAK,CAAC,KAAK,IAAI,GAAG,GAAG,CAC/E,CAAC;QACJ,CAAC;QAED,OAAO;YACL,eAAe,EAAE;gBACf,KAAK,EAAE,gBAAgB,KAAK,CAAC,QAAQ,EAAE;gBACvC,WAAW;gBACX,QAAQ,EAAE,UAAU;gBACpB,SAAS,EAAE,kBAAkB;gBAC7B,eAAe,EAAE,MAAM;aACxB;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/hooks/approval.ts"],"names":[],"mappings":"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"}