@lacneu/wix-openclaw 0.2.1 → 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.
- package/CHANGELOG.md +497 -2
- package/README.md +94 -8
- package/dist/config.d.ts +1 -0
- package/dist/config.js +16 -1
- package/dist/config.js.map +1 -1
- package/dist/hooks/approval.d.ts +10 -0
- package/dist/hooks/approval.js +301 -18
- package/dist/hooks/approval.js.map +1 -1
- package/dist/index.d.ts +1348 -8
- package/dist/index.js +47 -18
- package/dist/index.js.map +1 -1
- package/dist/tools/_factory.d.ts +26 -2
- package/dist/tools/_factory.js.map +1 -1
- package/dist/tools/blog.d.ts +11 -11
- package/dist/tools/bookings.d.ts +5 -5
- package/dist/tools/contacts.d.ts +5 -5
- package/dist/tools/data.d.ts +5 -5
- package/dist/tools/design.d.ts +1 -1
- package/dist/tools/events.d.ts +3 -3
- package/dist/tools/faq.d.ts +5 -5
- package/dist/tools/forms.d.ts +2 -2
- package/dist/tools/media.d.ts +2 -2
- package/dist/tools/multilingual.d.ts +2 -2
- package/dist/tools/reviews.d.ts +3 -3
- package/dist/tools/seo.d.ts +199 -0
- package/dist/tools/seo.js +836 -0
- package/dist/tools/seo.js.map +1 -0
- package/dist/tools/site.d.ts +2 -2
- package/dist/types.d.ts +11 -0
- package/dist/wix-client.js +30 -4
- package/dist/wix-client.js.map +1 -1
- package/openclaw.plugin.json +106 -5
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,501 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [
|
|
8
|
+
## [0.3.0] - 2026-08-28
|
|
9
|
+
|
|
10
|
+
Nine `wix_seo_*` tools, **off by default**, close the gap that made this plugin
|
|
11
|
+
able to manage a site's *content* but not to look at its SEO. Turn them on with
|
|
12
|
+
`enableSeoTools: true`.
|
|
13
|
+
|
|
14
|
+
**One fix here affects every existing install, whether or not you want the SEO
|
|
15
|
+
tools:** approval prompts were too long for the gateway to accept, so every
|
|
16
|
+
approval-gated tool was blocked without the operator ever being asked. See
|
|
17
|
+
*approval prompts were too long for the gateway to show at all* below.
|
|
18
|
+
|
|
19
|
+
The three SEO read paths were verified against a live Wix site; the four writing
|
|
20
|
+
paths were deliberately left unexercised. Everything else recorded under this
|
|
21
|
+
version is work on code that had not shipped before — it is written down because
|
|
22
|
+
the reasoning is the point, not because anyone was affected by it.
|
|
23
|
+
|
|
24
|
+
### Added — SEO: auditing a site, and managing its URL redirects
|
|
25
|
+
|
|
26
|
+
> **These tools are OFF by default and must be opted into with
|
|
27
|
+
> `enableSeoTools: true`.** Every Wix endpoint behind them is in Developer
|
|
28
|
+
> Preview: Wix may change them at any time and states they shouldn't be used on
|
|
29
|
+
> live sites. Four of them also write irreversibly the moment they succeed.
|
|
30
|
+
|
|
31
|
+
**Permission.** All nine sit behind a single Wix scope,
|
|
32
|
+
`SCOPE.PROMOTE.MANAGE-SEO` — shown untranslated in the Wix UI, under *All site
|
|
33
|
+
permissions*, between *Social Posts* and *Import orders*. Wix publishes no
|
|
34
|
+
read-only SEO scope, so a key that can audit a site can also delete its
|
|
35
|
+
redirects: the read/write boundary is `enableSeoTools` plus the approvals, not
|
|
36
|
+
the key. The three read paths were verified live against a real site; the four
|
|
37
|
+
writing paths were deliberately left unexercised.
|
|
38
|
+
|
|
39
|
+
Nine tools under `wix_seo_*`, closing the gap that made the plugin able to
|
|
40
|
+
manage a site's *content* but not to look at its SEO.
|
|
41
|
+
|
|
42
|
+
**Audit.** `wix_seo_list_item_tags` is the entry point: pass `STATIC_PAGE` and
|
|
43
|
+
it enumerates the site's pages, each with the tags it sets itself, whether it
|
|
44
|
+
sets any (`hasOverride`), and the tags it is expected to render with — every one
|
|
45
|
+
marked with where it came from (the item, its host page, a customised pattern,
|
|
46
|
+
Wix's own pattern, or the site). Other item types are `BLOG_POST`,
|
|
47
|
+
`STORES_PRODUCT` and `WIX_DATA_PAGE_ITEM-{pageId}`. `wix_seo_get_item_tags` and
|
|
48
|
+
`wix_seo_get_site_tags` read one item and the site-wide tags.
|
|
49
|
+
|
|
50
|
+
**Redirects.** List, get, create, delete, and both bulk forms.
|
|
51
|
+
|
|
52
|
+
### Two limits stated in the tool descriptions, not just the docs
|
|
53
|
+
|
|
54
|
+
*A static page reads as its SAVED revision, never the published one*, and
|
|
55
|
+
`publishStatus` is always `PUBLISH_STATUS_UNSPECIFIED` for one — Wix exposes no
|
|
56
|
+
path to read the published revision back. The description says so, because an
|
|
57
|
+
agent that doesn't know it will report on a draft as though it were the live
|
|
58
|
+
page. `resolvedTags` likewise omits whatever site code and apps add at render
|
|
59
|
+
time, so it is not the page's rendered `<head>`.
|
|
60
|
+
|
|
61
|
+
### Changed — `wix_seo_create_redirect` is approval-gated, like the deletes
|
|
62
|
+
|
|
63
|
+
Creating a redirect is destructive by construction. Redirects do not chain: when
|
|
64
|
+
an existing redirect **starts at** the path a new one points to, that existing
|
|
65
|
+
redirect is deleted so the create can proceed — no flag asked for, and no way
|
|
66
|
+
back. `options.forceReplace` deletes a second one. Gating by verb would have
|
|
67
|
+
left the most damaging call in the set ungated.
|
|
68
|
+
|
|
69
|
+
### Fixed — approval prompts were too long for the gateway to show at all
|
|
70
|
+
|
|
71
|
+
The gateway declares an approval's `title` as 1–80 characters and its
|
|
72
|
+
`description` as 1–256 (`PluginApprovalRequestParamsSchema`). The prompt this
|
|
73
|
+
plugin built embedded a 600-character parameter preview under a paragraph of
|
|
74
|
+
boilerplate, so it could not fit — and an over-long request is not truncated,
|
|
75
|
+
it fails validation. **Every approval-gated tool was affected, not only the new
|
|
76
|
+
ones**: the operator was never asked, and the call was blocked.
|
|
77
|
+
|
|
78
|
+
The description is now BUILT to that budget rather than written and hoped for,
|
|
79
|
+
ordered by what decides a refusal: the irreversible effect first, then the site
|
|
80
|
+
the call actually lands on (the old preview stripped `siteId`, so on a
|
|
81
|
+
multi-site key the operator never saw which tenant), then the parameters that
|
|
82
|
+
matter, then everything else until the budget runs out.
|
|
83
|
+
|
|
84
|
+
A redirect is shown with its SCOPE — exact or group, and its language or `all`
|
|
85
|
+
— because the paths alone made an exact French-only rule and a global group rule
|
|
86
|
+
over a whole branch read identically, while the second can make far more pages
|
|
87
|
+
unreachable. That applies to a bulk create's members too, which had been going
|
|
88
|
+
through the generic JSON path: up to 500 group rules over whole branches read
|
|
89
|
+
the same as 500 exact ones. A batch also reports a count PER SCOPE over every
|
|
90
|
+
member, and its sample leads with the widest rules. Its size and fingerprint are
|
|
91
|
+
their own part of the prompt, so a long scope breakdown can be dropped without
|
|
92
|
+
taking the batch's identity with it — sampling in request order
|
|
93
|
+
put three exact rules on screen while the global group ones sat inside an
|
|
94
|
+
opaque fingerprint. A list reports its size, a few of its members and a stable
|
|
95
|
+
fingerprint of the whole set — reporting only a count made two bulk deletes of completely
|
|
96
|
+
different GUIDs read identically. Long values are shortened in the middle, so
|
|
97
|
+
two paths sharing a prefix stay distinguishable, and a value that still cannot
|
|
98
|
+
fit is skipped rather than ending the rendering, which is how `from` and `to`
|
|
99
|
+
could disappear from a prompt entirely. A test asserts both limits for every
|
|
100
|
+
gated tool, at the largest values Wix itself accepts.
|
|
101
|
+
|
|
102
|
+
### Changed — a redirect create REFUSES rather than silently destroying
|
|
103
|
+
|
|
104
|
+
Creating a redirect deletes an existing one that starts at the path the new one
|
|
105
|
+
points to — redirects do not chain — and `forceReplace` deletes the one holding
|
|
106
|
+
the same `from` path. Neither is reported by the API, and telling the agent to
|
|
107
|
+
check first only made it advice: a direct call, or a model that skipped the
|
|
108
|
+
instruction, still lost a redirect nobody had named.
|
|
109
|
+
|
|
110
|
+
`wix_seo_create_redirect` and `wix_seo_bulk_create_redirects` now list the
|
|
111
|
+
site's redirects themselves and refuse, naming each redirect they would delete
|
|
112
|
+
and why, until the caller repeats those GUIDs back in `acknowledgeDeletions`.
|
|
113
|
+
Trailing-slash and case differences count as the same path, as Wix treats them.
|
|
114
|
+
A create that destroys nothing goes straight through.
|
|
115
|
+
|
|
116
|
+
### Changed — the destructive preflight compares what Wix STORES, and fails closed
|
|
117
|
+
|
|
118
|
+
Three ways the check could be walked around, all closed:
|
|
119
|
+
|
|
120
|
+
- **Language prefixes.** Wix stores a language-scoped redirect without its
|
|
121
|
+
prefix — a `fr` redirect from `/fr/about` comes back as `/about`. Comparing
|
|
122
|
+
the caller's path against the stored one found nothing, so a language-scoped
|
|
123
|
+
deletion went through unannounced. Paths are now normalised the way Wix
|
|
124
|
+
stores them, against the language of BOTH sides: a global create pointing at
|
|
125
|
+
`/fr/blog` is aiming at the public path of a `fr` redirect stored as `/blog`,
|
|
126
|
+
and normalising only by the candidate's own language (none, there) left the
|
|
127
|
+
two looking unrelated. Scopes that cannot collide are skipped rather than
|
|
128
|
+
flagged.
|
|
129
|
+
- **An unreadable list.** Anything that wasn't a `redirects` array — a 2xx the
|
|
130
|
+
client couldn't parse, a schema change, a proxy's own page — read as "this
|
|
131
|
+
site has no redirects", and the destructive write went out on the strength of
|
|
132
|
+
it. The call now refuses. The one answer a safety check must never invent is
|
|
133
|
+
the reassuring one.
|
|
134
|
+
- **Concurrency.** The check and the write are two requests, so two concurrent
|
|
135
|
+
creates could each read a state without the other's redirect and the second to
|
|
136
|
+
land would delete the first's. Destructive writes are now serialised per
|
|
137
|
+
EFFECTIVE site — keying on the raw argument put an omitted `siteId` and the
|
|
138
|
+
same site named explicitly into two different queues, so the calls the lock
|
|
139
|
+
exists to order ran side by side. A change made in the Wix dashboard between
|
|
140
|
+
the read and the write is still possible — Wix offers no precondition to close
|
|
141
|
+
that — and the tool descriptions say so rather than promising otherwise.
|
|
142
|
+
- **An entry the plugin cannot read.** Validating only that `redirects` was an
|
|
143
|
+
array closed the check at the top and left it open underneath: a preview
|
|
144
|
+
rename to `source` passes an array test, every `from` reads as undefined, no
|
|
145
|
+
conflict is found, and the write goes out on a list nobody understood. Each
|
|
146
|
+
entry is now checked before anything is computed from it.
|
|
147
|
+
|
|
148
|
+
### Changed — an acknowledgement is tied to the redirect's CURRENT state
|
|
149
|
+
|
|
150
|
+
`acknowledgeDeletions` took bare GUIDs, which were guessable: a caller could
|
|
151
|
+
name one on the first call and never be shown what it destroys. Worse, an id
|
|
152
|
+
outlives the redirect behind it — Wix lets a create supply its own GUID, so
|
|
153
|
+
between a refusal and the retry the same id can point somewhere else, and the
|
|
154
|
+
acknowledgement would authorise deleting something the user never saw.
|
|
155
|
+
|
|
156
|
+
The refusal now hands back a `token` derived from the redirect's id, paths,
|
|
157
|
+
language and group flag, **and the effective site**, HMAC'd with a secret minted
|
|
158
|
+
once per process. It cannot be produced without having listed, it stops matching
|
|
159
|
+
the moment the redirect changes — in which case the call refuses again with the
|
|
160
|
+
new one — and a token earned on one site does not unlock its twin on another.
|
|
161
|
+
Two allowed sites can hold an identical redirect, since Wix accepts
|
|
162
|
+
caller-supplied GUIDs, and a cross-site replay would have authorised a deletion
|
|
163
|
+
on a tenant whose state nobody was shown.
|
|
164
|
+
|
|
165
|
+
### Changed — the two kinds of bulk loop are told apart, and only one is guarded
|
|
166
|
+
|
|
167
|
+
An intermediate version of this work refused any batch whose members looped on
|
|
168
|
+
each other, on the assumption that one would delete the other. The reference says
|
|
169
|
+
otherwise: an item closing a loop with an EARLIER item of the same request fails
|
|
170
|
+
on its own with `REDIRECT_LOOP` and the rest of the batch goes ahead — nothing
|
|
171
|
+
is deleted. That guard blocked migrations Wix would have applied in part, and
|
|
172
|
+
told the operator redirects would be lost when none would. It is gone.
|
|
173
|
+
|
|
174
|
+
What remains guarded is the deletion the reference does document: an item that
|
|
175
|
+
closes a loop with a redirect ALREADY ON THE SITE is created and that redirect is
|
|
176
|
+
deleted. The tool description now states both cases separately.
|
|
177
|
+
|
|
178
|
+
The declared bound also drops from 500 to **100** for bulk create, which is what
|
|
179
|
+
the method page and the Developer Preview index both say. Bulk delete stays 500.
|
|
180
|
+
|
|
181
|
+
### Fixed — irreversible SEO writes were being replayed
|
|
182
|
+
|
|
183
|
+
The HTTP client retries 429/502/503/504 twice. A create that Wix applied before
|
|
184
|
+
answering 503 — deleting a loop-closing redirect on the way — was then applied
|
|
185
|
+
again, and neither answer says which happened. `WixRequestOptions` gained
|
|
186
|
+
`retry`, and all four writes set it to `false` — a delete Wix applied before
|
|
187
|
+
answering 503 comes back 404 on the replay, and the plugin would then report a
|
|
188
|
+
failure for a permanent deletion that did happen: the error surfaces and the caller
|
|
189
|
+
re-reads, instead of a second irreversible write nobody asked for.
|
|
190
|
+
|
|
191
|
+
### Fixed — an unsupported field rode through to Wix
|
|
192
|
+
|
|
193
|
+
TypeBox objects accept properties a schema does not mention, so a per-item
|
|
194
|
+
`options.forceReplace` on a bulk create survived validation and reached Wix —
|
|
195
|
+
while the preflight had been run with `forceReplace: false` and the approval
|
|
196
|
+
prompt never showed the nested flag. Wix deletes the redirect holding that
|
|
197
|
+
`from` path. Both creates now send a redirect rebuilt from the fields the plugin
|
|
198
|
+
actually supports; `forceReplace` is honoured only as the single create's own
|
|
199
|
+
top-level parameter, where the preflight accounts for it. The stripping is in
|
|
200
|
+
the code rather than left to the schema, because `execute` can be called
|
|
201
|
+
directly.
|
|
202
|
+
|
|
203
|
+
### Changed — a delete names a redirect, not just an id
|
|
204
|
+
|
|
205
|
+
`wix_seo_delete_redirect` sent the DELETE straight from a GUID. Wix accepts
|
|
206
|
+
caller-supplied GUIDs, so between a listing, the operator's approval and the
|
|
207
|
+
call, the same id can name a different redirect — and the prompt showed nothing
|
|
208
|
+
but the id. The redirect is now re-read and the call refuses, showing its paths,
|
|
209
|
+
language and scope, until the `token` from that refusal comes back. Same protocol
|
|
210
|
+
as the creates, and the same staleness: if the redirect changed, the token no
|
|
211
|
+
longer matches. The bulk delete follows it too — it had been sending up to 500
|
|
212
|
+
GUIDs straight through, with an approval prompt carrying ids and no paths.
|
|
213
|
+
|
|
214
|
+
### Fixed — the SEO opt-in is reachable from the configurator
|
|
215
|
+
|
|
216
|
+
`enableSeoTools` defaults to false and had no `uiHints` entry, and OpenClaw's
|
|
217
|
+
configuration flow prompts only for the properties declared there. The switch
|
|
218
|
+
that registers the nine SEO tools was therefore unreachable without hand-editing
|
|
219
|
+
the config file — the feature shipped off, with no supported way to turn it on.
|
|
220
|
+
A manifest test now requires a `uiHints` entry for every configurable property.
|
|
221
|
+
|
|
222
|
+
### Fixed — a value cannot paint its own lines in the approval prompt
|
|
223
|
+
|
|
224
|
+
The description is rendered as a line-structured message, and the redirect
|
|
225
|
+
rendering — which exists to be more readable than JSON — put paths, languages
|
|
226
|
+
and parameter names into it verbatim. A `from` of `/a\nsite: attacker-site` drew
|
|
227
|
+
a second field naming a site the call never touched, on the one surface whose
|
|
228
|
+
purpose is a human deciding about an irreversible write. The generic branch had
|
|
229
|
+
been safe only because `JSON.stringify` escapes controls. Controls are now made
|
|
230
|
+
visible before any truncation, at every insertion point, and `language` is
|
|
231
|
+
bounded like the paths.
|
|
232
|
+
|
|
233
|
+
### Fixed — an `options` shape this version cannot read is refused
|
|
234
|
+
|
|
235
|
+
`options: []` is `typeof "object"` and passed the pre-flight, as did a drift
|
|
236
|
+
renaming the flag to `isGroupRedirect`. Either left a group redirect described
|
|
237
|
+
to the operator as exact and its acknowledgement token blind to the scope it
|
|
238
|
+
really has — the two things the token exists to bind. `options` must now be a
|
|
239
|
+
plain object carrying no key but `groupRedirect`.
|
|
240
|
+
|
|
241
|
+
### Fixed — the prompt names both ways a create destroys
|
|
242
|
+
|
|
243
|
+
A redirect takes precedence over a real page at the same path, so creating one
|
|
244
|
+
from a path that still serves a page makes that page unreachable — no existing
|
|
245
|
+
redirect involved, and nothing the pre-flight can see, since it reads redirects
|
|
246
|
+
rather than pages. Both create prompts warned only about deleting a redirect.
|
|
247
|
+
They now name the hidden page too, which is the operator's only warning about it.
|
|
248
|
+
|
|
249
|
+
The `Manage SEO` scope also moved out of the README's "minimum required" list.
|
|
250
|
+
In the default configuration `enableSeoTools` is false and the SEO tools are not
|
|
251
|
+
registered, so granting a scope that permits deleting redirects buys nothing —
|
|
252
|
+
it is listed as conditional on turning them on.
|
|
253
|
+
|
|
254
|
+
### Fixed — a create that points under another language's prefix
|
|
255
|
+
|
|
256
|
+
The language filter ran before any path comparison, for both checks. Two
|
|
257
|
+
languages are separate URL namespaces, so that is right for a create pointing
|
|
258
|
+
inside its own — refusing there would block a create that destroys nothing. But
|
|
259
|
+
a caller can write the other language's prefix explicitly: an `en` redirect
|
|
260
|
+
pointing at `/fr/blog` names the public entry of the `fr` redirect Wix stores as
|
|
261
|
+
`/blog`, and the filter dropped that pair before the comparison that would have
|
|
262
|
+
recognised it, so the deletion went unannounced. That case is now detected; none
|
|
263
|
+
is taken away. Two related questions upstream does not answer — whether a group
|
|
264
|
+
redirect resolves a loop for destinations merely UNDER its `from`, and how the
|
|
265
|
+
two languages compare in general — are recorded in the code as known bounds
|
|
266
|
+
rather than guessed at, because settling them needs a create and a delete
|
|
267
|
+
against a live site.
|
|
268
|
+
|
|
269
|
+
A global redirect — one with no `language` — applies to every language, so it is
|
|
270
|
+
also entered at `/de/blog` and not only at `/blog`. Against such a rule the scope
|
|
271
|
+
comparison always "overlaps", which is precisely what kept the foreign-prefix
|
|
272
|
+
check from running, and a create pointing at `/de/blog` closed a loop with it
|
|
273
|
+
unannounced. The site's configured languages cannot be read here (that endpoint
|
|
274
|
+
needs a different scope and can answer 403), so a leading segment SHAPED like a
|
|
275
|
+
language tag is now recognised. It errs towards announcing: a `/fr/...` that is
|
|
276
|
+
really a content folder costs one acknowledgement, and the operator sees exactly
|
|
277
|
+
which redirect is named.
|
|
278
|
+
|
|
279
|
+
### Fixed — the create describes the protocol it implements
|
|
280
|
+
|
|
281
|
+
Two sentences of `wix_seo_create_redirect`'s description sent a model down paths
|
|
282
|
+
the code refuses: it named Wix's own `options.forceReplace` — the nested flag
|
|
283
|
+
this plugin strips, so the create would have failed as if the flag were never
|
|
284
|
+
set — and it asked for the doomed redirects' GUIDs, where the acknowledgement
|
|
285
|
+
protocol takes the `token` from the refusal and rejects a bare id. The behaviour
|
|
286
|
+
was right throughout; only the contract a model reads before acting was wrong,
|
|
287
|
+
which no behavioural test could catch. Both are corrected, the bulk create says
|
|
288
|
+
`token` explicitly too, and a test now holds the descriptions to it.
|
|
289
|
+
|
|
290
|
+
### Fixed — the pre-flight trusts a listing only when it understands all of it
|
|
291
|
+
|
|
292
|
+
The destructive pre-flight refused a redirect listing whose entries had no
|
|
293
|
+
string `from`, but the acknowledgement token also binds `id`, `to`, `language`
|
|
294
|
+
and `groupRedirect`, substituting a default for whatever is absent. A drift that
|
|
295
|
+
renamed or dropped `to` — a stated possibility on a Developer Preview API —
|
|
296
|
+
therefore degraded the token into one that no longer changed when the redirect's
|
|
297
|
+
destination did, and a stale acknowledgement would have authorised a permanent
|
|
298
|
+
deletion. Every field the token binds is now checked, scope fields for shape.
|
|
299
|
+
|
|
300
|
+
### Fixed — the write lock forgets, and the audit pages as the endpoint defines
|
|
301
|
+
|
|
302
|
+
`serializedBySite` kept one settled promise per site id it had ever been given.
|
|
303
|
+
The key is caller-supplied and queued BEFORE the whitelist rejects it, so a
|
|
304
|
+
long-lived gateway retained an entry for every string ever passed — the comment
|
|
305
|
+
already claimed the chain was dropped "once it is the last one"; now the code
|
|
306
|
+
does it, and only while it is still the tail.
|
|
307
|
+
|
|
308
|
+
`wix_seo_list_item_tags` advertised the shared GET paging envelope, `offset`
|
|
309
|
+
included, on an endpoint that pages by cursor alone. The schema is now
|
|
310
|
+
cursor-only AND the query is built from those two keys: narrowing a TypeBox
|
|
311
|
+
object does not strip what it omits, and `execute` can be called directly, so
|
|
312
|
+
an `offset` arriving at runtime would still have been forwarded.
|
|
313
|
+
|
|
314
|
+
The smoke test no longer probes the SEO endpoints unless `WIX_SMOKE_SEO=1`.
|
|
315
|
+
They would otherwise have demanded `SCOPE.PROMOTE.MANAGE-SEO` — a scope that
|
|
316
|
+
also permits deleting redirects — of every key, including the default
|
|
317
|
+
configuration where the SEO tools are not even registered.
|
|
318
|
+
|
|
319
|
+
### Fixed — a refusal names the whole loss, and the protocol converges
|
|
320
|
+
|
|
321
|
+
Every refusal listed only the redirects still lacking an acknowledgement, while
|
|
322
|
+
`howToProceed` asked for "every token above". The phrase therefore named a
|
|
323
|
+
different set on each round: a caller that REPLACED its token list rather than
|
|
324
|
+
extending it alternated between halves and never got through, so a legitimate
|
|
325
|
+
multi-redirect deletion was impossible. The shrinking list also understated the
|
|
326
|
+
loss — the second prompt showed fewer deletions than the first. All three
|
|
327
|
+
multi-target refusals (single create, bulk create, bulk delete) now list the
|
|
328
|
+
complete set, each entry carrying `acknowledged: true | false`.
|
|
329
|
+
|
|
330
|
+
### Fixed — an omitted parameter is always marked as omitted
|
|
331
|
+
|
|
332
|
+
The approval description reserved room for the ` · …` marker only until the
|
|
333
|
+
first part was dropped, and stopped reserving exactly when the marker had become
|
|
334
|
+
certain. Parts after that drop filled the 256-character budget to the brim and
|
|
335
|
+
the final truncation cut the marker off, so a prompt that had silently dropped a
|
|
336
|
+
parameter read as complete — on the destructive calls where it matters. Room is
|
|
337
|
+
now reserved from the first drop onwards, and trailing parts are surrendered if
|
|
338
|
+
that is what it takes for the marker to survive.
|
|
339
|
+
|
|
340
|
+
The approval fingerprint moved from a 32-bit FNV to SHA-256 truncated to 128
|
|
341
|
+
bits, over a key-sorted serialisation. The old one was small enough to collide
|
|
342
|
+
deliberately — two batches whose sampled members matched then produced identical
|
|
343
|
+
prompts for two different permanent deletions — and insertion-order
|
|
344
|
+
serialisation gave the same batch different identities depending on how its
|
|
345
|
+
fields happened to be written.
|
|
346
|
+
|
|
347
|
+
### Fixed — SEO writes ignored cancellation
|
|
348
|
+
|
|
349
|
+
The tool factory hands each run an `AbortSignal` and the HTTP client honours it,
|
|
350
|
+
but the SEO tools never took it. A destructive write can sit behind another
|
|
351
|
+
site-write for as long as that one takes, so an irreversible POST could go out
|
|
352
|
+
after the runtime had already reported the operation cancelled. The signal is
|
|
353
|
+
now checked after the queue and again immediately before the write, and passed
|
|
354
|
+
to every request — the five READ tools had never declared it either, so a
|
|
355
|
+
cancelled audit went on waiting, retrying and spending quota. The retry backoff
|
|
356
|
+
is interruptible too: a plain timer meant an abandoned call still sat out the
|
|
357
|
+
whole wait, which `Retry-After` can make long, before noticing.
|
|
358
|
+
|
|
359
|
+
### Fixed — the manifest tests were checking a list they maintained themselves
|
|
360
|
+
|
|
361
|
+
`test/manifest.test.ts` re-listed the tool domains instead of reading what the
|
|
362
|
+
plugin registers, so adding a whole domain left its guards passing over the new
|
|
363
|
+
tools without seeing them. Registration now goes through a single exported
|
|
364
|
+
`buildAllTools()` that the tests read, and two guards were added: `contracts.tools`
|
|
365
|
+
must name exactly the registered tools, and the manifest's `approvalRequired`
|
|
366
|
+
default must match the code's.
|
|
367
|
+
|
|
368
|
+
### Fixed — the build no longer depends on a package nobody declared
|
|
369
|
+
|
|
370
|
+
`src/tools/_factory.ts` imported the `AgentToolResult` type from
|
|
371
|
+
`@mariozechner/pi-agent-core`, which was never a dependency of this plugin: it
|
|
372
|
+
arrived only because `openclaw` happened to pull it in. Upstream dropped it
|
|
373
|
+
(absent from 2026.6.x onwards), so the import resolved on a machine holding an
|
|
374
|
+
older tree and nowhere else — a fresh install compiled no more.
|
|
375
|
+
|
|
376
|
+
The shape is now declared in the plugin itself. `openclaw/plugin-sdk/agent-core`
|
|
377
|
+
re-exports the same type, but that subpath only exists from 2026.5.28 while this
|
|
378
|
+
plugin supports `>=2026.5.0`: importing it would have quietly dropped the bottom
|
|
379
|
+
of the declared range. The local declaration holds across the whole of it, and
|
|
380
|
+
the structural check still happens where it matters — at `registerTool`, against
|
|
381
|
+
whichever SDK is installed. Verified compiling at both ends of the range, 2026.5.2
|
|
382
|
+
and 2026.6.34.
|
|
383
|
+
|
|
384
|
+
Two related repairs came with it. The default export is now annotated
|
|
385
|
+
(`ReturnType<typeof definePluginEntry>`): its inferred type reached into an
|
|
386
|
+
openclaw build-internal chunk that TypeScript cannot name from a declaration
|
|
387
|
+
file (`TS2742`). And `package-lock.json`, stale at `0.1.1` since that release,
|
|
388
|
+
is regenerated — `npm ci` had been failing on every run since, silently falling
|
|
389
|
+
back to `npm install`, which is why a dependency that had quietly vanished
|
|
390
|
+
upstream went unnoticed until now.
|
|
391
|
+
|
|
392
|
+
### Migration
|
|
393
|
+
|
|
394
|
+
For instance owners on `@lacneu/wix-openclaw@0.2.2`:
|
|
395
|
+
|
|
396
|
+
1. `openclaw plugins update @lacneu/wix-openclaw` — **`update`, not
|
|
397
|
+
`install`**: `install` rewrites `plugins.entries.wix-openclaw` with the
|
|
398
|
+
manifest's defaults, discarding the API key, the site whitelist and any
|
|
399
|
+
`approvalRequired` you have tuned. `update` preserves them.
|
|
400
|
+
2. Restart the gateway container. This release adds no environment variable, so
|
|
401
|
+
a `restart` is enough — no `--force-recreate` needed.
|
|
402
|
+
3. Verify in the boot log:
|
|
403
|
+
`wix-openclaw: ready — 50 tool(s) registered`.
|
|
404
|
+
|
|
405
|
+
Fifty, not fifty-nine: the SEO tools are not registered until you opt in. Nothing
|
|
406
|
+
else changes, and the approval fix applies as soon as the plugin loads — a gated
|
|
407
|
+
tool that used to fail without asking will now put its prompt to the operator.
|
|
408
|
+
|
|
409
|
+
To add the SEO tools:
|
|
410
|
+
|
|
411
|
+
1. Tick **Manage SEO** (`SCOPE.PROMOTE.MANAGE-SEO`) on the Wix API key used by
|
|
412
|
+
that instance. Its label
|
|
413
|
+
is untranslated in the Wix UI — it sits under *All site permissions*, between
|
|
414
|
+
*Social Posts* and *Import orders*. There is no read-only variant: the same
|
|
415
|
+
permission that allows the audit also allows deleting redirects.
|
|
416
|
+
2. Set `enableSeoTools: true` — via the configurator, which prompts for it as
|
|
417
|
+
*Enable SEO tools (audit + URL redirects)*, or with
|
|
418
|
+
`openclaw config set plugins.entries.wix-openclaw.config.enableSeoTools true`.
|
|
419
|
+
`update` carries your existing config forward and the new field simply
|
|
420
|
+
defaults to `false`, so nothing turns on by surprise.
|
|
421
|
+
3. Restart, and expect `59 tool(s) registered`.
|
|
422
|
+
4. Read the Developer Preview warning at the top of this section before pointing
|
|
423
|
+
any of the four writing tools at a live site.
|
|
424
|
+
|
|
425
|
+
## [0.2.2] - 2026-05-03
|
|
426
|
+
|
|
427
|
+
### Fixed — OpenClaw 2026.5.x compatibility
|
|
428
|
+
|
|
429
|
+
OpenClaw 2026.5.2 introduced a manifest contract for plugin tool
|
|
430
|
+
ownership: tools registered via `api.registerTool(...)` are
|
|
431
|
+
**rejected at runtime** with the error
|
|
432
|
+
`plugin must declare contracts.tools before registering agent tools`
|
|
433
|
+
when the plugin manifest does not declare them.
|
|
434
|
+
|
|
435
|
+
Without this release, `@lacneu/wix-openclaw` loads on 2026.5.x but
|
|
436
|
+
all 50 of its `wix_*` tools are silently rejected at registration —
|
|
437
|
+
the plugin runs hooks but exposes 0 tools to the agent.
|
|
438
|
+
|
|
439
|
+
### Added — `contracts.tools` (50 entries)
|
|
440
|
+
|
|
441
|
+
`openclaw.plugin.json` now declares every tool the plugin owns
|
|
442
|
+
under `contracts.tools` as a flat array of strings. Mirrors the 50
|
|
443
|
+
tools registered by `registerWixPlugin(api)`:
|
|
444
|
+
|
|
445
|
+
- 11 blog tools (drafts CRUD, publish/unpublish, posts, categories, tags)
|
|
446
|
+
- 6 bookings (services list, query, create, get, cancel, reschedule)
|
|
447
|
+
- 1 business info
|
|
448
|
+
- 6 contacts CRUD + label + query
|
|
449
|
+
- 6 wix data CRUD (collections, items)
|
|
450
|
+
- 1 design brief
|
|
451
|
+
- 3 events (list, get, list_guests)
|
|
452
|
+
- 5 FAQ (list categories/questions, create/update/delete question)
|
|
453
|
+
- 2 forms (list submissions, get submission)
|
|
454
|
+
- 2 media (list, upload)
|
|
455
|
+
- 2 multilingual (list languages, list schemas)
|
|
456
|
+
- 3 reviews (list, get, moderate)
|
|
457
|
+
- 2 sites (list, url get)
|
|
458
|
+
|
|
459
|
+
### Added — `activation.onStartup: true`
|
|
460
|
+
|
|
461
|
+
Per the OpenClaw 2026.5.x manifest spec, external plugins should
|
|
462
|
+
declare an explicit activation policy. `onStartup: true` ensures
|
|
463
|
+
the plugin is loaded at gateway startup so its tools are
|
|
464
|
+
discoverable when the agent resolves its tool inventory.
|
|
465
|
+
|
|
466
|
+
### Added — `toolMetadata._default.configSignals`
|
|
467
|
+
|
|
468
|
+
Tells OpenClaw's tool descriptor planner that every tool in this
|
|
469
|
+
plugin requires both `apiKey` and `accountId` to be configured at
|
|
470
|
+
`plugins.entries.wix-openclaw.config`. The platform skips loading
|
|
471
|
+
the plugin runtime when these are missing — cheap availability
|
|
472
|
+
check at reply startup.
|
|
473
|
+
|
|
474
|
+
### Changed — compat aligned to 2026.5.0
|
|
475
|
+
|
|
476
|
+
- `package.json#openclaw.compat`:
|
|
477
|
+
`pluginApi: ">=2026.4.0"` → `">=2026.5.0"`,
|
|
478
|
+
`minGatewayVersion: "2026.4.0"` → `"2026.5.0"`.
|
|
479
|
+
- `peerDependencies.openclaw` and `devDependencies.openclaw`:
|
|
480
|
+
`">=2026.4.0"` → `">=2026.5.0"`.
|
|
481
|
+
|
|
482
|
+
### Migration
|
|
483
|
+
|
|
484
|
+
For instance owners on `@lacneu/wix-openclaw@0.2.1` running
|
|
485
|
+
OpenClaw 2026.5.x:
|
|
486
|
+
|
|
487
|
+
1. `openclaw plugins install @lacneu/wix-openclaw@0.2.2 --force`
|
|
488
|
+
2. Restart the gateway container.
|
|
489
|
+
3. Verify in the boot log:
|
|
490
|
+
`wix-openclaw: ready — 50 tool(s) registered`.
|
|
491
|
+
4. Verify with `openclaw plugins inspect wix-openclaw --runtime --json`:
|
|
492
|
+
`"toolNames"` should list the 50 `wix_*` tools.
|
|
493
|
+
|
|
494
|
+
### Note on agent tool inventory bug
|
|
495
|
+
|
|
496
|
+
OpenClaw 2026.5.2 has a separate regression (issue #76598) that
|
|
497
|
+
prevents plugin tools from appearing in the per-agent tool
|
|
498
|
+
inventory even when the plugin is correctly installed and registered.
|
|
499
|
+
Fixed in commit `a3b94f39109d` on 2026-05-03 — pending in 2026.5.3.
|
|
500
|
+
Symptom: `tools.alsoAllow` listing the wix tools logs as
|
|
501
|
+
`unknown entries` despite the plugin being loaded. No client-side
|
|
502
|
+
workaround; await the upstream release.
|
|
9
503
|
|
|
10
504
|
## [0.2.1] - 2026-04-29
|
|
11
505
|
|
|
@@ -157,5 +651,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
157
651
|
- Release workflow using **npm Trusted Publishing (OIDC)** — no `NPM_TOKEN`
|
|
158
652
|
secret required, provenance attached automatically.
|
|
159
653
|
|
|
160
|
-
[Unreleased]: https://github.com/OlivierNeu/wix-openclaw-plugin/compare/v0.
|
|
654
|
+
[Unreleased]: https://github.com/OlivierNeu/wix-openclaw-plugin/compare/v0.3.0...HEAD
|
|
655
|
+
[0.3.0]: https://github.com/OlivierNeu/wix-openclaw-plugin/compare/v0.2.2...v0.3.0
|
|
161
656
|
[0.1.0]: https://github.com/OlivierNeu/wix-openclaw-plugin/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
## Overview
|
|
16
16
|
|
|
17
17
|
`wix-openclaw` is an OpenClaw plugin that lets your agent operate a Wix site
|
|
18
|
-
through the official Wix REST API. It registers ~
|
|
18
|
+
through the official Wix REST API. It registers ~60 tools split across a dozen
|
|
19
19
|
Wix products (Blog, CMS Data, Forms, Bookings, Contacts, Events, Reviews, FAQ,
|
|
20
|
-
Multilingual, Sites, Site Media), plus a `wix_design_brief` helper that
|
|
21
|
-
loose textual briefs into structured markdown artefacts.
|
|
20
|
+
Multilingual, Sites, Site Media, SEO), plus a `wix_design_brief` helper that
|
|
21
|
+
turns loose textual briefs into structured markdown artefacts.
|
|
22
22
|
|
|
23
23
|
Every tool funnels through a single authenticated HTTP client that:
|
|
24
24
|
|
|
@@ -175,6 +175,19 @@ should stay unticked.
|
|
|
175
175
|
Tick these only if the corresponding Wix product is actually in use on
|
|
176
176
|
the target site:
|
|
177
177
|
|
|
178
|
+
- [ ] **Manage SEO** (`SCOPE.PROMOTE.MANAGE-SEO`) — **only if you set
|
|
179
|
+
`enableSeoTools: true`.** In the default configuration the SEO tools are not
|
|
180
|
+
registered at all, so granting this scope would hand the key the power to
|
|
181
|
+
delete redirects for tools that cannot run. Wix exposes a **single** SEO
|
|
182
|
+
scope, not a read/write pair: ticking it grants redirect creation and deletion
|
|
183
|
+
along with the read-only audit, so there is no such thing as an audit-only SEO
|
|
184
|
+
key. In the Wix UI the checkbox sits under **All site permissions**, between
|
|
185
|
+
*Social Posts* and *Import orders*; its label is currently untranslated and
|
|
186
|
+
renders literally as `site.scope.SCOPE.PROMOTE.MANAGE-SEO.name`. Since Wix
|
|
187
|
+
cannot narrow it, the read/write boundary is enforced by this plugin instead —
|
|
188
|
+
the four writing tools require an approval naming every redirect they would
|
|
189
|
+
destroy.
|
|
190
|
+
|
|
178
191
|
- [ ] **Pricing Plans** — if you sell subscription packages
|
|
179
192
|
- [ ] **Wix Stores** + **Wix eCommerce** — if you sell physical/digital
|
|
180
193
|
products. Without these, the `wix_*` tools that touch e-commerce
|
|
@@ -225,6 +238,7 @@ columns and remove the matching tools from your agent's allow-list.
|
|
|
225
238
|
| `wix_reviews_*` | Wix Reviews | Reviews moderation |
|
|
226
239
|
| `wix_faq_*` | Manage FAQ | FAQ tooling |
|
|
227
240
|
| `wix_multilingual_*` | Multilingual Translation Schema Read | Translation reads |
|
|
241
|
+
| `wix_seo_*` (all nine) | Manage SEO (`SCOPE.PROMOTE.MANAGE-SEO`) | SEO audit **and** redirect changes — Wix has no read-only SEO scope, so this one permission covers both |
|
|
228
242
|
| `wix_design_brief` | _(none — no API call)_ | Always |
|
|
229
243
|
|
|
230
244
|
### Wix app installation requirements
|
|
@@ -237,7 +251,7 @@ working as soon as the app is installed (no plugin upgrade needed).
|
|
|
237
251
|
| Tool group | Wix app required | Error returned when missing |
|
|
238
252
|
|---|---|---|
|
|
239
253
|
| `wix_blog_*` | Wix Blog | `404` |
|
|
240
|
-
| `wix_data_*` | Velo / Wix Code
|
|
254
|
+
| `wix_data_*` | Wix CMS (Velo / Wix Code — enable in Editor) | `400 WDE0110: Wix CMS app is not installed for site` |
|
|
241
255
|
| `wix_forms_*` | Wix Forms | `404` |
|
|
242
256
|
| `wix_bookings_*` | Wix Bookings | `404` |
|
|
243
257
|
| `wix_events_*` | Wix Events | `428 WIX_EVENTS_APP_NOT_INSTALLED` |
|
|
@@ -338,7 +352,9 @@ site; `app-not-installed` and `velo-not-enabled` mean the tool's
|
|
|
338
352
|
endpoint exists but its backing Wix product is not active on the
|
|
339
353
|
smoke-test site (the request still reaches Wix and the path/headers
|
|
340
354
|
are correct); `docs` means write/destructive endpoints that we do not
|
|
341
|
-
exercise live.
|
|
355
|
+
exercise live. The SEO reads are skipped by the smoke test unless
|
|
356
|
+
`WIX_SMOKE_SEO=1` is set, so a key without `SCOPE.PROMOTE.MANAGE-SEO` is not
|
|
357
|
+
failed for lacking a scope the default configuration never uses.
|
|
342
358
|
|
|
343
359
|
### Blog
|
|
344
360
|
|
|
@@ -455,15 +471,85 @@ Requires the Wix FAQ app (returns `400 App is not installed` otherwise).
|
|
|
455
471
|
|
|
456
472
|
### Multilingual (read-only in V1)
|
|
457
473
|
|
|
458
|
-
Returns `403` on the Ataraxis smoke-test site
|
|
459
|
-
`Multilingual Translation Schema Read` permission
|
|
460
|
-
|
|
474
|
+
Returns `403` on the Ataraxis smoke-test site, with an EMPTY body. The earlier
|
|
475
|
+
guess — a missing `Multilingual Translation Schema Read` permission — has since
|
|
476
|
+
been ruled out: that permission is granted on the key and the `403` persists.
|
|
477
|
+
What remains undetermined is whether the Wix Multilingual app is simply not
|
|
478
|
+
installed, or whether these two endpoints also require the separate
|
|
479
|
+
`SCOPE.MULTILINGUAL.MANAGE_TRANSLATIONS` scope. The empty body does not say, and
|
|
480
|
+
neither answer has been tested.
|
|
461
481
|
|
|
462
482
|
| Tool | What it does | Approval | Validated |
|
|
463
483
|
|---|---|---|---|
|
|
464
484
|
| `wix_multilingual_list_languages` | List configured languages; standard query envelope | — | 403-permission |
|
|
465
485
|
| `wix_multilingual_list_schemas` | List translation schemas | — | 403-permission |
|
|
466
486
|
|
|
487
|
+
### SEO
|
|
488
|
+
|
|
489
|
+
> **Developer Preview, and OFF by default.** Every Wix endpoint behind these
|
|
490
|
+
> nine tools is listed in Wix's
|
|
491
|
+
> [Developer Preview](https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-developer-preview)
|
|
492
|
+
> — Item SEO Tags, Site SEO Tags and all six Redirects methods. Wix may change
|
|
493
|
+
> them at any time, and states plainly that you **shouldn't use them on live
|
|
494
|
+
> sites**: they are for testing and feedback. An API stays in preview for at
|
|
495
|
+
> most six months.
|
|
496
|
+
>
|
|
497
|
+
> Nothing here registers unless you set `enableSeoTools: true` in the plugin
|
|
498
|
+
> config. Four of the tools write irreversibly to the live site the moment they
|
|
499
|
+
> succeed, so opting in is the operator saying they accept both risks.
|
|
500
|
+
> _Preview status verified against the Wix reference on 2026-08-28._
|
|
501
|
+
|
|
502
|
+
Auditing a site's SEO, and managing its URL redirects.
|
|
503
|
+
|
|
504
|
+
| Tool | What it does | Approval | Validated |
|
|
505
|
+
|---|---|---|---|
|
|
506
|
+
| `wix_seo_list_item_tags` | List the items of one type with their SEO tags. `STATIC_PAGE` enumerates the site's pages. Reports `hasOverride`, the item's own `tags`, and `resolvedTags` marked with each tag's source. Cursor paging. | — | live |
|
|
507
|
+
| `wix_seo_get_item_tags` | One item's tags, own and resolved | — | schema |
|
|
508
|
+
| `wix_seo_get_site_tags` | Site-wide tags, plus dashboard verification embeds (read-only) | — | live |
|
|
509
|
+
| `wix_seo_list_redirects` | Every redirect on the site. No filter, sort or paging — the endpoint takes none | — | live |
|
|
510
|
+
| `wix_seo_get_redirect` | One redirect by GUID | — | schema |
|
|
511
|
+
| `wix_seo_create_redirect` | Create a 301 redirect | **required** | schema |
|
|
512
|
+
| `wix_seo_delete_redirect` | Delete one redirect (re-reads it and refuses until its token is acknowledged) | **required** | schema |
|
|
513
|
+
| `wix_seo_bulk_create_redirects` | Create 1–100 redirects | **required** | schema |
|
|
514
|
+
| `wix_seo_bulk_delete_redirects` | Delete 1–500 redirects | **required** | schema |
|
|
515
|
+
|
|
516
|
+
**Three things to know before using these.**
|
|
517
|
+
|
|
518
|
+
*A read of a static page is the SAVED revision, not the live one.* For
|
|
519
|
+
`STATIC_PAGE`, `tags`, `focusKeywords` and `resolvedTags` always reflect the
|
|
520
|
+
saved revision, and `publishStatus` is always `PUBLISH_STATUS_UNSPECIFIED` — the
|
|
521
|
+
API has no path to read the published revision back. An audit report should say
|
|
522
|
+
it is about the saved page. `resolvedTags` also omits anything site code or apps
|
|
523
|
+
add while the page renders, so it is not a copy of the rendered `<head>`.
|
|
524
|
+
|
|
525
|
+
*Creating a redirect can delete another one.* Redirects do not chain: if an
|
|
526
|
+
existing redirect **starts at** the path a new one points to, that existing
|
|
527
|
+
redirect is deleted and the create proceeds — no flag involved, no way back.
|
|
528
|
+
The tool's own top-level `forceReplace` parameter additionally deletes a
|
|
529
|
+
redirect holding the same `from` path. Wix documents that flag nested as
|
|
530
|
+
`options.forceReplace`; do **not** send it there — the tool rebuilds the
|
|
531
|
+
redirect from the fields it supports, so a nested flag is dropped and the create
|
|
532
|
+
fails with `FROM_URL_EXISTS` as if it had never been set. This is why
|
|
533
|
+
`wix_seo_create_redirect` is approval-gated by default
|
|
534
|
+
alongside the deletes. A redirect also takes precedence over a real page at the
|
|
535
|
+
same path, which makes that page unreachable.
|
|
536
|
+
|
|
537
|
+
*The create refuses before it destroys.* `wix_seo_create_redirect` and
|
|
538
|
+
`wix_seo_bulk_create_redirects` list the site's redirects themselves and refuse,
|
|
539
|
+
naming each redirect they would delete — with its paths, language and whether it
|
|
540
|
+
is a group rule — until the caller repeats the `token` from that refusal back in
|
|
541
|
+
`acknowledgeDeletions`. The token is derived from the redirect's current state,
|
|
542
|
+
so it cannot be guessed without listing and goes stale if the redirect changes.
|
|
543
|
+
The check is in the execution path, not in the tool description, so a direct call
|
|
544
|
+
gets it too, and it refuses outright rather than assuming an empty list when the
|
|
545
|
+
redirects cannot be read. Destructive writes are serialised per site; a change
|
|
546
|
+
made in the Wix dashboard between the read and the write remains possible.
|
|
547
|
+
|
|
548
|
+
*There is no update method and no query method.* To change a redirect: get it,
|
|
549
|
+
delete it, then create it carrying **every** field over — an omitted field is
|
|
550
|
+
filled with its default, not its previous value. To find one, list them all and
|
|
551
|
+
filter client-side.
|
|
552
|
+
|
|
467
553
|
### Design
|
|
468
554
|
|
|
469
555
|
| Tool | What it does | Approval | Validated |
|
package/dist/config.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { ResolvedWixConfig, WixPluginConfig } from "./types.js";
|
|
|
6
6
|
* become empty strings to avoid leaking `undefined` into downstream code.
|
|
7
7
|
*/
|
|
8
8
|
export declare function resolveEnv<T>(value: T): T;
|
|
9
|
+
export declare const DEFAULT_APPROVAL_REQUIRED: string[];
|
|
9
10
|
/**
|
|
10
11
|
* Apply defaults and env substitution to the raw plugin config.
|
|
11
12
|
*
|