@lacneu/wix-openclaw 0.1.0 → 0.2.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +161 -74
  3. package/dist/tools/_query.d.ts +117 -0
  4. package/dist/tools/_query.js +240 -0
  5. package/dist/tools/_query.js.map +1 -0
  6. package/dist/tools/blog.d.ts +92 -0
  7. package/dist/tools/blog.js +122 -20
  8. package/dist/tools/blog.js.map +1 -1
  9. package/dist/tools/bookings.d.ts +18 -22
  10. package/dist/tools/bookings.js +28 -19
  11. package/dist/tools/bookings.js.map +1 -1
  12. package/dist/tools/contacts.d.ts +20 -2
  13. package/dist/tools/contacts.js +27 -16
  14. package/dist/tools/contacts.js.map +1 -1
  15. package/dist/tools/data.d.ts +14 -2
  16. package/dist/tools/data.js +22 -35
  17. package/dist/tools/data.js.map +1 -1
  18. package/dist/tools/events.d.ts +44 -4
  19. package/dist/tools/events.js +29 -28
  20. package/dist/tools/events.js.map +1 -1
  21. package/dist/tools/faq.d.ts +12 -0
  22. package/dist/tools/faq.js +15 -9
  23. package/dist/tools/faq.js.map +1 -1
  24. package/dist/tools/forms.d.ts +24 -4
  25. package/dist/tools/forms.js +38 -25
  26. package/dist/tools/forms.js.map +1 -1
  27. package/dist/tools/media.d.ts +4 -0
  28. package/dist/tools/media.js +32 -23
  29. package/dist/tools/media.js.map +1 -1
  30. package/dist/tools/multilingual.d.ts +21 -1
  31. package/dist/tools/multilingual.js +16 -18
  32. package/dist/tools/multilingual.js.map +1 -1
  33. package/dist/tools/reviews.d.ts +22 -2
  34. package/dist/tools/reviews.js +18 -16
  35. package/dist/tools/reviews.js.map +1 -1
  36. package/dist/tools/site.d.ts +20 -0
  37. package/dist/tools/site.js +17 -25
  38. package/dist/tools/site.js.map +1 -1
  39. package/openclaw.plugin.json +1 -1
  40. package/package.json +4 -2
@@ -0,0 +1,240 @@
1
+ // Shared query helpers for Wix tools.
2
+ //
3
+ // Wix exposes two distinct query styles:
4
+ //
5
+ // 1. POST `/.../query` endpoints — accept a JSON body shaped as
6
+ // `{ query: { filter, sort, paging | cursorPaging, fields } }`. The
7
+ // filter supports MongoDB-style operators
8
+ // (`$eq/$ne/$gt/$gte/$lt/$lte/$in/$nin/$exists/$startsWith/$hasSome
9
+ // /$hasAll/$contains/$matches/$and/$or/$not`) — see the Wix Query
10
+ // Language docs:
11
+ // https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/data-retrieval/about-the-wix-api-query-language
12
+ //
13
+ // 2. Flat GET endpoints — accept named query string parameters plus
14
+ // `paging.limit` / `paging.offset` (or `paging.cursor` when the
15
+ // endpoint paginates by cursor). They do NOT accept the operator
16
+ // syntax above; trying to send `?filter={"$eq":...}` is silently
17
+ // ignored.
18
+ //
19
+ // To keep tools honest about what their backing endpoint actually
20
+ // accepts, we expose two distinct envelopes:
21
+ //
22
+ // - `WixQueryBodyEnvelope` for POST /query tools — full passthrough
23
+ // `filter`, `sort`, `paging`/`cursorPaging`, `fields` (projection)
24
+ // - `WixGetPagingEnvelope` for flat GET tools — `paging` only; named
25
+ // filters live as plain top-level params on each tool.
26
+ //
27
+ // The mappers (`buildQueryBody`, `buildGetPagingQuery`) are the single
28
+ // source of truth for shape. Per-tool tests assert that
29
+ // `tool.execute(...)` lands the right keys in the right place; the
30
+ // mapper itself gets exhaustive coverage in a single test file.
31
+ import { Type } from "@sinclair/typebox";
32
+ // ---------------------------------------------------------------------------
33
+ // POST /query envelope
34
+ // ---------------------------------------------------------------------------
35
+ /**
36
+ * Sort entry — `fieldName` is the dotted path (e.g.
37
+ * `info.emails.email`), `order` is `ASC` (default) or `DESC`. Maps 1:1
38
+ * to the Wix sort entry shape.
39
+ */
40
+ export const WixSortEntrySchema = Type.Object({
41
+ fieldName: Type.String({
42
+ description: "Dotted path of the field to sort by, e.g. `createdDate`",
43
+ }),
44
+ order: Type.Optional(Type.Union([Type.Literal("ASC"), Type.Literal("DESC")], {
45
+ description: "Sort order — defaults to ASC when omitted",
46
+ })),
47
+ });
48
+ /**
49
+ * Offset paging — preferred form for POST /query endpoints that don't
50
+ * stream very large result sets. `limit` defaults to 50 server-side.
51
+ */
52
+ export const WixOffsetPagingSchema = Type.Object({
53
+ limit: Type.Optional(Type.Number({
54
+ minimum: 1,
55
+ maximum: 1000,
56
+ description: "Items per page (default 50, capped per endpoint)",
57
+ })),
58
+ offset: Type.Optional(Type.Number({ minimum: 0, description: "Number of items to skip" })),
59
+ });
60
+ /**
61
+ * Cursor paging — used by endpoints that need stable iteration over
62
+ * large or fast-changing collections (e.g. Site Media, some Bookings
63
+ * queries). Pass back the `cursor` returned in `pagingMetadata.cursors.next`.
64
+ */
65
+ export const WixCursorPagingSchema = Type.Object({
66
+ limit: Type.Optional(Type.Number({ minimum: 1, maximum: 1000 })),
67
+ cursor: Type.Optional(Type.String({
68
+ description: "Opaque cursor returned by the previous page (`pagingMetadata.cursors.next`)",
69
+ })),
70
+ });
71
+ /**
72
+ * Generic query body envelope shared by every POST /query tool.
73
+ *
74
+ * The `filter` is intentionally typed as `Type.Unknown()` — Wix accepts
75
+ * arbitrarily nested MongoDB-style operator trees that we don't try to
76
+ * model in TypeBox. The agent gets full operator richness; tools layer
77
+ * ergonomic shortcuts on top by merging into this filter.
78
+ *
79
+ * Per-tool ergonomic shortcuts (e.g. `wix_blog_list_drafts.status`)
80
+ * compose with `filter` via {@link mergeFilter}.
81
+ */
82
+ export const WixQueryBodyEnvelopeSchema = Type.Object({
83
+ filter: Type.Optional(Type.Unknown({
84
+ description: 'MongoDB-style filter, e.g. `{"status": {"$eq": "ACTIVE"}}` or ' +
85
+ '`{"$or": [{"a": {"$gt": 1}}, {"b": "x"}]}`. Operators: ' +
86
+ "$eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $exists, " +
87
+ "$startsWith, $contains, $hasSome, $hasAll, $matches, $and, $or, $not.",
88
+ })),
89
+ sort: Type.Optional(Type.Array(WixSortEntrySchema, {
90
+ description: "List of sort entries, applied in order",
91
+ })),
92
+ paging: Type.Optional(WixOffsetPagingSchema),
93
+ cursorPaging: Type.Optional(WixCursorPagingSchema),
94
+ fields: Type.Optional(Type.Array(Type.String(), {
95
+ description: "Projection — list of field paths to include in the response (endpoint-specific support)",
96
+ })),
97
+ });
98
+ /**
99
+ * Build the JSON body for a POST /query call.
100
+ *
101
+ * Returns `{ query: { ... } }` with only the populated keys — Wix
102
+ * rejects empty `paging: {}` and friends on some endpoints.
103
+ *
104
+ * `extraFilter` is merged into `envelope.filter` via {@link mergeFilter}.
105
+ * Use it when a tool layers ergonomic shortcuts on top of the raw
106
+ * passthrough (e.g. `wix_forms_list_submissions` always pins
107
+ * `namespace`).
108
+ */
109
+ export function buildQueryBody(envelope, extraFilter) {
110
+ const env = envelope ?? {};
111
+ const filter = mergeFilter(env.filter, extraFilter);
112
+ const query = {};
113
+ if (filter !== undefined)
114
+ query.filter = filter;
115
+ if (env.sort && env.sort.length > 0)
116
+ query.sort = env.sort;
117
+ if (env.paging && Object.keys(env.paging).length > 0) {
118
+ query.paging = env.paging;
119
+ }
120
+ if (env.cursorPaging && Object.keys(env.cursorPaging).length > 0) {
121
+ query.cursorPaging = env.cursorPaging;
122
+ }
123
+ if (env.fields && env.fields.length > 0)
124
+ query.fields = env.fields;
125
+ return { query };
126
+ }
127
+ /**
128
+ * Merge a tool-level shortcut filter (`extra`) with a user-provided
129
+ * passthrough filter (`base`).
130
+ *
131
+ * Precedence rule: the SHORTCUT WINS on field-level collision.
132
+ *
133
+ * Why: shortcuts encode constraints Wix REQUIRES (e.g.
134
+ * `wix_forms_list_submissions.namespace` — Wix rejects the call without
135
+ * a namespace filter). If the agent's passthrough were to override a
136
+ * pinned namespace, the call would fail with "namespace required".
137
+ *
138
+ * Implementation:
139
+ * - If only one side defines a key, that key is kept verbatim.
140
+ * - If both sides define the SAME top-level key, the shortcut wins
141
+ * and the passthrough's value for that key is dropped (logged
142
+ * conceptually, but we don't have a logger here).
143
+ * - Non-conflicting keys from both sides are combined with `$and`
144
+ * when needed, otherwise spread into a flat object.
145
+ *
146
+ * - Both undefined → undefined (caller decides whether to omit the key)
147
+ * - Only one defined → returned as-is
148
+ */
149
+ export function mergeFilter(base, extra) {
150
+ const hasExtra = extra && Object.keys(extra).length > 0;
151
+ if (base === undefined && !hasExtra)
152
+ return undefined;
153
+ if (base === undefined)
154
+ return extra;
155
+ if (!hasExtra)
156
+ return base;
157
+ // Both defined. If `base` is a plain object whose top-level keys are
158
+ // disjoint from `extra`, we can flatten the merge — Wix is happy with
159
+ // either flat or `$and`. If there's a key collision, drop the
160
+ // conflicting key from `base` so the shortcut wins, then `$and` the
161
+ // remainder.
162
+ if (base !== null &&
163
+ typeof base === "object" &&
164
+ !Array.isArray(base)) {
165
+ const baseObj = base;
166
+ const extraKeys = new Set(Object.keys(extra));
167
+ const reservedTopLevel = new Set(["$and", "$or", "$not"]);
168
+ const baseKeys = Object.keys(baseObj);
169
+ const baseHasTopLevelOperator = baseKeys.some((k) => reservedTopLevel.has(k));
170
+ if (!baseHasTopLevelOperator) {
171
+ // Field-level diff: keep the non-conflicting fields from base.
172
+ const filteredBase = {};
173
+ for (const [k, v] of Object.entries(baseObj)) {
174
+ if (!extraKeys.has(k))
175
+ filteredBase[k] = v;
176
+ }
177
+ const filteredKeys = Object.keys(filteredBase);
178
+ if (filteredKeys.length === 0) {
179
+ // The agent's passthrough only contained collisions — every
180
+ // entry was overridden by the shortcut.
181
+ return extra;
182
+ }
183
+ // Non-collision fields remain. Combine extra (canonical) + the
184
+ // surviving subset of base. We use `$and` for clarity; Wix
185
+ // accepts either.
186
+ return { $and: [extra, filteredBase] };
187
+ }
188
+ }
189
+ // Base uses operator-level composition ($and/$or/$not) or is not a
190
+ // plain object — fall back to `$and` to keep the shortcut authoritative
191
+ // even when the passthrough is operator-rooted.
192
+ return { $and: [extra, base] };
193
+ }
194
+ // ---------------------------------------------------------------------------
195
+ // Flat GET envelope
196
+ // ---------------------------------------------------------------------------
197
+ /**
198
+ * Paging shape for flat GET endpoints. Some Wix endpoints support
199
+ * offset paging (`paging.limit`/`paging.offset`), others use cursor
200
+ * paging (`paging.limit`/`paging.cursor`). We expose both — tools pick
201
+ * the right pair when calling {@link buildGetPagingQuery}.
202
+ */
203
+ export const WixGetPagingEnvelopeSchema = Type.Object({
204
+ limit: Type.Optional(Type.Number({ minimum: 1, maximum: 1000 })),
205
+ offset: Type.Optional(Type.Number({ minimum: 0 })),
206
+ cursor: Type.Optional(Type.String()),
207
+ });
208
+ /**
209
+ * Map a `paging` envelope to flat `paging.limit` / `paging.offset` /
210
+ * `paging.cursor` query string keys (Wix's documented convention).
211
+ *
212
+ * Returns a partial query object the caller can spread into
213
+ * `client.request({ query: { ...buildGetPagingQuery(p), other: x } })`.
214
+ */
215
+ export function buildGetPagingQuery(paging) {
216
+ if (!paging)
217
+ return {};
218
+ const out = {};
219
+ if (paging.limit !== undefined)
220
+ out["paging.limit"] = paging.limit;
221
+ if (paging.offset !== undefined)
222
+ out["paging.offset"] = paging.offset;
223
+ if (paging.cursor !== undefined)
224
+ out["paging.cursor"] = paging.cursor;
225
+ return out;
226
+ }
227
+ /**
228
+ * Drop `undefined`, `null`, and empty-string entries from a query
229
+ * record so they don't end up as `?key=undefined` after serialisation.
230
+ */
231
+ export function compactQuery(q) {
232
+ const out = {};
233
+ for (const [k, v] of Object.entries(q)) {
234
+ if (v === undefined || v === null || v === "")
235
+ continue;
236
+ out[k] = v;
237
+ }
238
+ return out;
239
+ }
240
+ //# sourceMappingURL=_query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_query.js","sourceRoot":"","sources":["../../src/tools/_query.ts"],"names":[],"mappings":"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"}
@@ -5,17 +5,25 @@ export declare function buildBlogTools(client: WixClient): ({
5
5
  label: string;
6
6
  parameters: import("@sinclair/typebox").TObject<{
7
7
  siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
8
+ status: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"UNPUBLISHED">, import("@sinclair/typebox").TLiteral<"PUBLISHED">, import("@sinclair/typebox").TLiteral<"SCHEDULED">, import("@sinclair/typebox").TLiteral<"IN_REVIEW">, import("@sinclair/typebox").TLiteral<"ALL">]>>;
9
+ sort: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"EDITING_DATE_ASC">, import("@sinclair/typebox").TLiteral<"EDITING_DATE_DESC">]>>;
10
+ fieldsets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"URL">, import("@sinclair/typebox").TLiteral<"INTERNAL_ID">, import("@sinclair/typebox").TLiteral<"CONTENT">, import("@sinclair/typebox").TLiteral<"RICH_CONTENT">, import("@sinclair/typebox").TLiteral<"TRANSLATIONS">, import("@sinclair/typebox").TLiteral<"GENERATED_EXCERPT">, import("@sinclair/typebox").TLiteral<"COUNTERS">, import("@sinclair/typebox").TLiteral<"CONTENT_TEXT">]>>>;
8
11
  paging: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
9
12
  limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
10
13
  offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
14
+ cursor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
11
15
  }>>;
12
16
  }>;
13
17
  execute: (toolCallId: string, params: {
18
+ sort?: "EDITING_DATE_ASC" | "EDITING_DATE_DESC" | undefined;
14
19
  siteId?: string | undefined;
15
20
  paging?: {
16
21
  limit?: number | undefined;
17
22
  offset?: number | undefined;
23
+ cursor?: string | undefined;
18
24
  } | undefined;
25
+ status?: "UNPUBLISHED" | "PUBLISHED" | "SCHEDULED" | "IN_REVIEW" | "ALL" | undefined;
26
+ fieldsets?: ("URL" | "INTERNAL_ID" | "CONTENT" | "RICH_CONTENT" | "TRANSLATIONS" | "GENERATED_EXCERPT" | "COUNTERS" | "CONTENT_TEXT")[] | undefined;
19
27
  }, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
20
28
  status: "ok" | "failed";
21
29
  data?: unknown;
@@ -28,9 +36,11 @@ export declare function buildBlogTools(client: WixClient): ({
28
36
  parameters: import("@sinclair/typebox").TObject<{
29
37
  siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
30
38
  draftPostId: import("@sinclair/typebox").TString;
39
+ fieldsets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"URL">, import("@sinclair/typebox").TLiteral<"INTERNAL_ID">, import("@sinclair/typebox").TLiteral<"CONTENT">, import("@sinclair/typebox").TLiteral<"RICH_CONTENT">, import("@sinclair/typebox").TLiteral<"TRANSLATIONS">, import("@sinclair/typebox").TLiteral<"GENERATED_EXCERPT">, import("@sinclair/typebox").TLiteral<"COUNTERS">, import("@sinclair/typebox").TLiteral<"CONTENT_TEXT">]>>>;
31
40
  }>;
32
41
  execute: (toolCallId: string, params: {
33
42
  siteId?: string | undefined;
43
+ fieldsets?: ("URL" | "INTERNAL_ID" | "CONTENT" | "RICH_CONTENT" | "TRANSLATIONS" | "GENERATED_EXCERPT" | "COUNTERS" | "CONTENT_TEXT")[] | undefined;
34
44
  draftPostId: string;
35
45
  }, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
36
46
  status: "ok" | "failed";
@@ -107,6 +117,58 @@ export declare function buildBlogTools(client: WixClient): ({
107
117
  data?: unknown;
108
118
  error?: string;
109
119
  }>>;
120
+ } | {
121
+ name: string;
122
+ description: string;
123
+ label: string;
124
+ parameters: import("@sinclair/typebox").TObject<{
125
+ siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
126
+ draftPostId: import("@sinclair/typebox").TString;
127
+ }>;
128
+ execute: (toolCallId: string, params: {
129
+ siteId?: string | undefined;
130
+ draftPostId: string;
131
+ }, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
132
+ status: "ok" | "failed";
133
+ data?: unknown;
134
+ error?: string;
135
+ }>>;
136
+ } | {
137
+ name: string;
138
+ description: string;
139
+ label: string;
140
+ parameters: import("@sinclair/typebox").TObject<{
141
+ siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
142
+ sort: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"PUBLISHED_DATE_ASC">, import("@sinclair/typebox").TLiteral<"PUBLISHED_DATE_DESC">, import("@sinclair/typebox").TLiteral<"VIEW_COUNT_ASC">, import("@sinclair/typebox").TLiteral<"VIEW_COUNT_DESC">, import("@sinclair/typebox").TLiteral<"LIKE_COUNT_ASC">, import("@sinclair/typebox").TLiteral<"LIKE_COUNT_DESC">]>>;
143
+ featured: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
144
+ language: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
145
+ tagIds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
146
+ categoryIds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
147
+ fieldsets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"URL">, import("@sinclair/typebox").TLiteral<"INTERNAL_ID">, import("@sinclair/typebox").TLiteral<"CONTENT">, import("@sinclair/typebox").TLiteral<"RICH_CONTENT">, import("@sinclair/typebox").TLiteral<"TRANSLATIONS">, import("@sinclair/typebox").TLiteral<"GENERATED_EXCERPT">, import("@sinclair/typebox").TLiteral<"COUNTERS">, import("@sinclair/typebox").TLiteral<"CONTENT_TEXT">]>>>;
148
+ paging: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
149
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
150
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
151
+ cursor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
152
+ }>>;
153
+ }>;
154
+ execute: (toolCallId: string, params: {
155
+ sort?: "PUBLISHED_DATE_ASC" | "PUBLISHED_DATE_DESC" | "VIEW_COUNT_ASC" | "VIEW_COUNT_DESC" | "LIKE_COUNT_ASC" | "LIKE_COUNT_DESC" | undefined;
156
+ siteId?: string | undefined;
157
+ paging?: {
158
+ limit?: number | undefined;
159
+ offset?: number | undefined;
160
+ cursor?: string | undefined;
161
+ } | undefined;
162
+ fieldsets?: ("URL" | "INTERNAL_ID" | "CONTENT" | "RICH_CONTENT" | "TRANSLATIONS" | "GENERATED_EXCERPT" | "COUNTERS" | "CONTENT_TEXT")[] | undefined;
163
+ tagIds?: string[] | undefined;
164
+ categoryIds?: string[] | undefined;
165
+ featured?: boolean | undefined;
166
+ language?: string | undefined;
167
+ }, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
168
+ status: "ok" | "failed";
169
+ data?: unknown;
170
+ error?: string;
171
+ }>>;
110
172
  } | {
111
173
  name: string;
112
174
  description: string;
@@ -114,9 +176,11 @@ export declare function buildBlogTools(client: WixClient): ({
114
176
  parameters: import("@sinclair/typebox").TObject<{
115
177
  siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
116
178
  postId: import("@sinclair/typebox").TString;
179
+ fieldsets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"URL">, import("@sinclair/typebox").TLiteral<"INTERNAL_ID">, import("@sinclair/typebox").TLiteral<"CONTENT">, import("@sinclair/typebox").TLiteral<"RICH_CONTENT">, import("@sinclair/typebox").TLiteral<"TRANSLATIONS">, import("@sinclair/typebox").TLiteral<"GENERATED_EXCERPT">, import("@sinclair/typebox").TLiteral<"COUNTERS">, import("@sinclair/typebox").TLiteral<"CONTENT_TEXT">]>>>;
117
180
  }>;
118
181
  execute: (toolCallId: string, params: {
119
182
  siteId?: string | undefined;
183
+ fieldsets?: ("URL" | "INTERNAL_ID" | "CONTENT" | "RICH_CONTENT" | "TRANSLATIONS" | "GENERATED_EXCERPT" | "COUNTERS" | "CONTENT_TEXT")[] | undefined;
120
184
  postId: string;
121
185
  }, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
122
186
  status: "ok" | "failed";
@@ -129,9 +193,37 @@ export declare function buildBlogTools(client: WixClient): ({
129
193
  label: string;
130
194
  parameters: import("@sinclair/typebox").TObject<{
131
195
  siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
196
+ postId: import("@sinclair/typebox").TString;
132
197
  }>;
133
198
  execute: (toolCallId: string, params: {
134
199
  siteId?: string | undefined;
200
+ postId: string;
201
+ }, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
202
+ status: "ok" | "failed";
203
+ data?: unknown;
204
+ error?: string;
205
+ }>>;
206
+ } | {
207
+ name: string;
208
+ description: string;
209
+ label: string;
210
+ parameters: import("@sinclair/typebox").TObject<{
211
+ siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
212
+ language: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
213
+ paging: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
214
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
215
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
216
+ cursor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
217
+ }>>;
218
+ }>;
219
+ execute: (toolCallId: string, params: {
220
+ siteId?: string | undefined;
221
+ paging?: {
222
+ limit?: number | undefined;
223
+ offset?: number | undefined;
224
+ cursor?: string | undefined;
225
+ } | undefined;
226
+ language?: string | undefined;
135
227
  }, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
136
228
  status: "ok" | "failed";
137
229
  data?: unknown;
@@ -5,11 +5,43 @@
5
5
  // (create/update/publish/unpublish/delete) are pattern-validated against
6
6
  // the published Wix Blog REST docs but were not exercised live to avoid
7
7
  // polluting the production blog.
8
+ //
9
+ // `wix_blog_list_drafts` and `wix_blog_list_published` are FLAT GET
10
+ // endpoints — they accept named query params (`status`, `featured`,
11
+ // `tagIds`, `categoryIds`, `language`, `sort`, `fieldsets`,
12
+ // `paging.limit`, `paging.offset`) but NOT the MongoDB-style operator
13
+ // passthrough used by POST `/query` endpoints. Hence no `filter`
14
+ // passthrough here — exposing one would silently get dropped by Wix.
8
15
  import { Type } from "@sinclair/typebox";
9
16
  import { defineWixTool } from "./_factory.js";
17
+ import { WixGetPagingEnvelopeSchema, buildGetPagingQuery, compactQuery, } from "./_query.js";
10
18
  const SiteIdParam = Type.Optional(Type.String({
11
19
  description: "Wix site UUID. Optional — falls back to defaultSiteId when omitted. Must be in allowedSiteIds.",
12
20
  }));
21
+ // `fieldsets` enum — verified live on /blog/v3/draft-posts and
22
+ // /blog/v3/posts. UNKNOWN exists in the schema but is a no-op.
23
+ const FieldsetsParam = Type.Optional(Type.Array(Type.Union([
24
+ Type.Literal("URL"),
25
+ Type.Literal("INTERNAL_ID"),
26
+ Type.Literal("CONTENT"),
27
+ Type.Literal("RICH_CONTENT"),
28
+ Type.Literal("TRANSLATIONS"),
29
+ Type.Literal("GENERATED_EXCERPT"),
30
+ // Posts-only — Wix accepts COUNTERS / CONTENT_TEXT on /posts but
31
+ // rejects them on /draft-posts. We keep the union loose; bad
32
+ // values surface as a clean Wix 400 the model can react to.
33
+ Type.Literal("COUNTERS"),
34
+ Type.Literal("CONTENT_TEXT"),
35
+ ]), {
36
+ description: "Optional response projection. URL adds `url`, RICH_CONTENT adds Ricos body, COUNTERS/CONTENT_TEXT are posts-only. See https://dev.wix.com/docs/rest/business-management/blog",
37
+ }));
38
+ // Encode array params as comma-separated values — what Wix's GET
39
+ // endpoints expect for `tagIds`, `categoryIds`, `fieldsets`.
40
+ function csv(values) {
41
+ if (!values || values.length === 0)
42
+ return undefined;
43
+ return values.join(",");
44
+ }
13
45
  export function buildBlogTools(client) {
14
46
  return [
15
47
  // -------------------------------------------------------------------
@@ -17,20 +49,44 @@ export function buildBlogTools(client) {
17
49
  // -------------------------------------------------------------------
18
50
  defineWixTool({
19
51
  name: "wix_blog_list_drafts",
20
- description: "List blog draft posts (not yet published). Supports paging and basic filtering.",
52
+ description: "List blog draft posts. Supports filtering by status, sorting, " +
53
+ "field projection, and offset paging. Default behaviour returns " +
54
+ "drafts with all statuses (UNPUBLISHED, PUBLISHED-snapshots, " +
55
+ "SCHEDULED, IN_REVIEW) — pass `status` to narrow.",
21
56
  parameters: Type.Object({
22
57
  siteId: SiteIdParam,
23
- paging: Type.Optional(Type.Object({
24
- limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100 })),
25
- offset: Type.Optional(Type.Number({ minimum: 0 })),
58
+ // Status enum verified live against Wix:
59
+ // UNPUBLISHED, PUBLISHED, SCHEDULED, IN_REVIEW are accepted.
60
+ // ALL is a CLIENT-SIDE convention — we map it to "no status
61
+ // param" because Wix returns 400 for any unknown status value.
62
+ status: Type.Optional(Type.Union([
63
+ Type.Literal("UNPUBLISHED"),
64
+ Type.Literal("PUBLISHED"),
65
+ Type.Literal("SCHEDULED"),
66
+ Type.Literal("IN_REVIEW"),
67
+ Type.Literal("ALL"),
68
+ ], {
69
+ description: "Draft status filter. ALL (default) returns drafts with every status — same as omitting the parameter. PUBLISHED returns drafts that are also currently published (the live snapshot).",
26
70
  })),
71
+ sort: Type.Optional(Type.Union([
72
+ Type.Literal("EDITING_DATE_ASC"),
73
+ Type.Literal("EDITING_DATE_DESC"),
74
+ ], {
75
+ description: "Sort order. Defaults to EDITING_DATE_DESC (most recently edited first).",
76
+ })),
77
+ fieldsets: FieldsetsParam,
78
+ paging: Type.Optional(WixGetPagingEnvelopeSchema),
27
79
  }),
28
80
  run: (params) => client.request("GET", "/blog/v3/draft-posts", {
29
81
  siteId: params.siteId,
30
- query: {
31
- "paging.limit": params.paging?.limit,
32
- "paging.offset": params.paging?.offset,
33
- },
82
+ query: compactQuery({
83
+ // Map our `ALL` shortcut → omit the param so we get the
84
+ // documented "all statuses" default.
85
+ status: params.status === "ALL" ? undefined : params.status,
86
+ sort: params.sort,
87
+ fieldsets: csv(params.fieldsets),
88
+ ...buildGetPagingQuery(params.paging),
89
+ }),
34
90
  }),
35
91
  }, client),
36
92
  defineWixTool({
@@ -39,8 +95,12 @@ export function buildBlogTools(client) {
39
95
  parameters: Type.Object({
40
96
  siteId: SiteIdParam,
41
97
  draftPostId: Type.String({ description: "Draft post id" }),
98
+ fieldsets: FieldsetsParam,
99
+ }),
100
+ run: (params) => client.request("GET", `/blog/v3/draft-posts/${encodeURIComponent(params.draftPostId)}`, {
101
+ siteId: params.siteId,
102
+ query: compactQuery({ fieldsets: csv(params.fieldsets) }),
42
103
  }),
43
- run: (params) => client.request("GET", `/blog/v3/draft-posts/${encodeURIComponent(params.draftPostId)}`, { siteId: params.siteId }),
44
104
  }, client),
45
105
  defineWixTool({
46
106
  name: "wix_blog_create_draft",
@@ -131,20 +191,42 @@ export function buildBlogTools(client) {
131
191
  // -------------------------------------------------------------------
132
192
  defineWixTool({
133
193
  name: "wix_blog_list_published",
134
- description: "List published blog posts. Supports paging.",
194
+ description: "List published blog posts. Supports sorting, language filter, " +
195
+ "tag/category filtering, field projection, and offset paging.",
135
196
  parameters: Type.Object({
136
197
  siteId: SiteIdParam,
137
- paging: Type.Optional(Type.Object({
138
- limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100 })),
139
- offset: Type.Optional(Type.Number({ minimum: 0 })),
198
+ // Sort enum verified live: PUBLISHED_DATE_DESC works.
199
+ // Wix docs also list PUBLISHED_DATE_ASC and VIEW_COUNT_*.
200
+ sort: Type.Optional(Type.Union([
201
+ Type.Literal("PUBLISHED_DATE_ASC"),
202
+ Type.Literal("PUBLISHED_DATE_DESC"),
203
+ Type.Literal("VIEW_COUNT_ASC"),
204
+ Type.Literal("VIEW_COUNT_DESC"),
205
+ Type.Literal("LIKE_COUNT_ASC"),
206
+ Type.Literal("LIKE_COUNT_DESC"),
207
+ ])),
208
+ featured: Type.Optional(Type.Boolean({
209
+ description: "If true, only featured posts. Default false (no filter).",
210
+ })),
211
+ language: Type.Optional(Type.String({
212
+ description: "ISO 639-1 language code (e.g. `fr`, `en`). Wix returns 200 + empty list when language is not configured on the site.",
140
213
  })),
214
+ tagIds: Type.Optional(Type.Array(Type.String())),
215
+ categoryIds: Type.Optional(Type.Array(Type.String())),
216
+ fieldsets: FieldsetsParam,
217
+ paging: Type.Optional(WixGetPagingEnvelopeSchema),
141
218
  }),
142
219
  run: (params) => client.request("GET", "/blog/v3/posts", {
143
220
  siteId: params.siteId,
144
- query: {
145
- "paging.limit": params.paging?.limit,
146
- "paging.offset": params.paging?.offset,
147
- },
221
+ query: compactQuery({
222
+ sort: params.sort,
223
+ featured: params.featured,
224
+ language: params.language,
225
+ tagIds: csv(params.tagIds),
226
+ categoryIds: csv(params.categoryIds),
227
+ fieldsets: csv(params.fieldsets),
228
+ ...buildGetPagingQuery(params.paging),
229
+ }),
148
230
  }),
149
231
  }, client),
150
232
  defineWixTool({
@@ -153,8 +235,12 @@ export function buildBlogTools(client) {
153
235
  parameters: Type.Object({
154
236
  siteId: SiteIdParam,
155
237
  postId: Type.String(),
238
+ fieldsets: FieldsetsParam,
239
+ }),
240
+ run: (params) => client.request("GET", `/blog/v3/posts/${encodeURIComponent(params.postId)}`, {
241
+ siteId: params.siteId,
242
+ query: compactQuery({ fieldsets: csv(params.fieldsets) }),
156
243
  }),
157
- run: (params) => client.request("GET", `/blog/v3/posts/${encodeURIComponent(params.postId)}`, { siteId: params.siteId }),
158
244
  }, client),
159
245
  defineWixTool({
160
246
  name: "wix_blog_unpublish",
@@ -173,17 +259,33 @@ export function buildBlogTools(client) {
173
259
  defineWixTool({
174
260
  name: "wix_blog_list_categories",
175
261
  description: "List blog categories (used to classify posts).",
176
- parameters: Type.Object({ siteId: SiteIdParam }),
262
+ parameters: Type.Object({
263
+ siteId: SiteIdParam,
264
+ language: Type.Optional(Type.String()),
265
+ paging: Type.Optional(WixGetPagingEnvelopeSchema),
266
+ }),
177
267
  run: (params) => client.request("GET", "/blog/v3/categories", {
178
268
  siteId: params.siteId,
269
+ query: compactQuery({
270
+ language: params.language,
271
+ ...buildGetPagingQuery(params.paging),
272
+ }),
179
273
  }),
180
274
  }, client),
181
275
  defineWixTool({
182
276
  name: "wix_blog_list_tags",
183
277
  description: "List blog tags.",
184
- parameters: Type.Object({ siteId: SiteIdParam }),
278
+ parameters: Type.Object({
279
+ siteId: SiteIdParam,
280
+ language: Type.Optional(Type.String()),
281
+ paging: Type.Optional(WixGetPagingEnvelopeSchema),
282
+ }),
185
283
  run: (params) => client.request("GET", "/blog/v3/tags", {
186
284
  siteId: params.siteId,
285
+ query: compactQuery({
286
+ language: params.language,
287
+ ...buildGetPagingQuery(params.paging),
288
+ }),
187
289
  }),
188
290
  }, client),
189
291
  ];