@lacneu/wix-openclaw 0.0.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 +68 -0
- package/LICENSE +21 -0
- package/README.md +483 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.js +60 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks/approval.d.ts +29 -0
- package/dist/hooks/approval.js +65 -0
- package/dist/hooks/approval.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +97 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/_factory.d.ts +40 -0
- package/dist/tools/_factory.js +69 -0
- package/dist/tools/_factory.js.map +1 -0
- package/dist/tools/blog.d.ts +140 -0
- package/dist/tools/blog.js +191 -0
- package/dist/tools/blog.js.map +1 -0
- package/dist/tools/bookings.d.ts +116 -0
- package/dist/tools/bookings.js +97 -0
- package/dist/tools/bookings.js.map +1 -0
- package/dist/tools/contacts.d.ts +216 -0
- package/dist/tools/contacts.js +128 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/data.d.ts +114 -0
- package/dist/tools/data.js +129 -0
- package/dist/tools/data.js.map +1 -0
- package/dist/tools/design.d.ts +32 -0
- package/dist/tools/design.js +165 -0
- package/dist/tools/design.js.map +1 -0
- package/dist/tools/events.d.ts +66 -0
- package/dist/tools/events.js +70 -0
- package/dist/tools/events.js.map +1 -0
- package/dist/tools/faq.d.ts +98 -0
- package/dist/tools/faq.js +90 -0
- package/dist/tools/faq.js.map +1 -0
- package/dist/tools/forms.d.ts +46 -0
- package/dist/tools/forms.js +63 -0
- package/dist/tools/forms.js.map +1 -0
- package/dist/tools/media.d.ts +50 -0
- package/dist/tools/media.js +75 -0
- package/dist/tools/media.js.map +1 -0
- package/dist/tools/multilingual.d.ts +38 -0
- package/dist/tools/multilingual.js +48 -0
- package/dist/tools/multilingual.js.map +1 -0
- package/dist/tools/reviews.d.ts +62 -0
- package/dist/tools/reviews.js +72 -0
- package/dist/tools/reviews.js.map +1 -0
- package/dist/tools/site.d.ts +36 -0
- package/dist/tools/site.js +94 -0
- package/dist/tools/site.js.map +1 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/wix-client.d.ts +66 -0
- package/dist/wix-client.js +194 -0
- package/dist/wix-client.js.map +1 -0
- package/openclaw.plugin.json +95 -0
- package/package.json +72 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// `before_tool_call` hook for destructive Wix operations.
|
|
2
|
+
//
|
|
3
|
+
// Reads the `approvalRequired` set from resolved config and, when a tool
|
|
4
|
+
// matches, returns a `requireApproval` directive. The OpenClaw runtime
|
|
5
|
+
// surfaces this to the operator (Telegram inline button, Control UI, ...)
|
|
6
|
+
// before the tool call proceeds.
|
|
7
|
+
//
|
|
8
|
+
// Notes on the SDK contract (see `node_modules/openclaw/dist/plugin-sdk/
|
|
9
|
+
// src/plugins/types.d.ts`):
|
|
10
|
+
// - `severity` accepts "info" | "warning" | "critical" (NOT "high").
|
|
11
|
+
// - `timeoutBehavior` accepts "allow" | "deny".
|
|
12
|
+
// - `pluginId` is set automatically by the hook runner — do not set it
|
|
13
|
+
// yourself.
|
|
14
|
+
const DEFAULT_TIMEOUT_MS = 600_000; // 10 minutes
|
|
15
|
+
const PARAM_PREVIEW_CHARS = 600;
|
|
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.
|
|
20
|
+
*/
|
|
21
|
+
function previewParams(params) {
|
|
22
|
+
const { siteId: _siteId, ...rest } = params; // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
23
|
+
let json;
|
|
24
|
+
try {
|
|
25
|
+
json = JSON.stringify(rest, null, 2);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
json = "<unserializable params>";
|
|
29
|
+
}
|
|
30
|
+
if (json.length <= PARAM_PREVIEW_CHARS)
|
|
31
|
+
return json;
|
|
32
|
+
return `${json.slice(0, PARAM_PREVIEW_CHARS)}…`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build a `before_tool_call` handler bound to a resolved Wix config.
|
|
36
|
+
* Extracted as a factory so tests can exercise it without a full plugin
|
|
37
|
+
* registration.
|
|
38
|
+
*/
|
|
39
|
+
export function createApprovalHook(config, logger) {
|
|
40
|
+
return function beforeToolCall(event) {
|
|
41
|
+
if (!config.enabled)
|
|
42
|
+
return undefined;
|
|
43
|
+
if (!config.approvalRequired.has(event.toolName))
|
|
44
|
+
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.";
|
|
51
|
+
if (config.logLevel === "debug") {
|
|
52
|
+
logger.debug?.(`wix: requesting approval for ${event.toolName} (runId=${event.runId ?? "?"})`);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
requireApproval: {
|
|
56
|
+
title: `Wix: confirm ${event.toolName}`,
|
|
57
|
+
description,
|
|
58
|
+
severity: "critical",
|
|
59
|
+
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
60
|
+
timeoutBehavior: "deny",
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=approval.js.map
|
|
@@ -0,0 +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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
|
+
export { resolveConfig, resolveEnv } from "./config.js";
|
|
3
|
+
export { createApprovalHook } from "./hooks/approval.js";
|
|
4
|
+
export { WixClient, WixApiError, WixSiteNotAllowedError, } from "./wix-client.js";
|
|
5
|
+
export type { ResolvedWixConfig, WixPluginConfig, WixRequestOptions, } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Register every Wix tool against the provided plugin API. Exposed so
|
|
8
|
+
* tests can drive the registration with a fake API surface.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerWixPlugin(api: OpenClawPluginApi): void;
|
|
11
|
+
declare const _default: {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
configSchema: import("openclaw/plugin-sdk/plugin-entry").OpenClawPluginConfigSchema;
|
|
16
|
+
register: NonNullable<import("openclaw/plugin-sdk/plugin-entry").OpenClawPluginDefinition["register"]>;
|
|
17
|
+
} & Pick<import("openclaw/plugin-sdk/plugin-entry").OpenClawPluginDefinition, "kind" | "reload" | "nodeHostCommands" | "securityAuditCollectors">;
|
|
18
|
+
export default _default;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// wix-openclaw — Wix REST API plugin for OpenClaw.
|
|
2
|
+
//
|
|
3
|
+
// Exposes ~50 tools spanning Blog, CMS Data, Forms, Contacts, Bookings,
|
|
4
|
+
// Events, Reviews, FAQ, Multilingual, plus a `wix_design_brief` helper.
|
|
5
|
+
//
|
|
6
|
+
// Security model:
|
|
7
|
+
// 1. Site whitelist — every site-scoped call is checked against
|
|
8
|
+
// `allowedSiteIds` before any HTTP request goes out. Calls to
|
|
9
|
+
// sites outside the list throw {@link WixSiteNotAllowedError} and
|
|
10
|
+
// surface as a tool failure to the model.
|
|
11
|
+
// 2. Approval gating — destructive operations (publish, delete,
|
|
12
|
+
// cancel, moderate) trigger a `before_tool_call` approval prompt
|
|
13
|
+
// handled by OpenClaw's approval runtime.
|
|
14
|
+
// 3. No secret in code — `apiKey` and `accountId` come from the
|
|
15
|
+
// plugin config (with `${ENV_VAR}` substitution), never from the
|
|
16
|
+
// LLM's parameter space.
|
|
17
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
18
|
+
import { resolveConfig } from "./config.js";
|
|
19
|
+
import { createApprovalHook } from "./hooks/approval.js";
|
|
20
|
+
import { buildBlogTools } from "./tools/blog.js";
|
|
21
|
+
import { buildBookingsTools } from "./tools/bookings.js";
|
|
22
|
+
import { buildContactsTools } from "./tools/contacts.js";
|
|
23
|
+
import { buildDataTools } from "./tools/data.js";
|
|
24
|
+
import { buildDesignTools } from "./tools/design.js";
|
|
25
|
+
import { buildEventsTools } from "./tools/events.js";
|
|
26
|
+
import { buildFaqTools } from "./tools/faq.js";
|
|
27
|
+
import { buildFormsTools } from "./tools/forms.js";
|
|
28
|
+
import { buildMediaTools } from "./tools/media.js";
|
|
29
|
+
import { buildMultilingualTools } from "./tools/multilingual.js";
|
|
30
|
+
import { buildReviewsTools } from "./tools/reviews.js";
|
|
31
|
+
import { buildSiteTools } from "./tools/site.js";
|
|
32
|
+
import { WixClient } from "./wix-client.js";
|
|
33
|
+
// Re-export helpers so tests can pull them without re-importing every
|
|
34
|
+
// submodule, and so downstream packagers can depend on internals if they
|
|
35
|
+
// need to (e.g. for an inspector tool).
|
|
36
|
+
export { resolveConfig, resolveEnv } from "./config.js";
|
|
37
|
+
export { createApprovalHook } from "./hooks/approval.js";
|
|
38
|
+
export { WixClient, WixApiError, WixSiteNotAllowedError, } from "./wix-client.js";
|
|
39
|
+
/**
|
|
40
|
+
* Register every Wix tool against the provided plugin API. Exposed so
|
|
41
|
+
* tests can drive the registration with a fake API surface.
|
|
42
|
+
*/
|
|
43
|
+
export function registerWixPlugin(api) {
|
|
44
|
+
const rawConfig = (api.pluginConfig ?? {});
|
|
45
|
+
const config = resolveConfig(rawConfig);
|
|
46
|
+
if (!config.enabled) {
|
|
47
|
+
api.logger.warn("wix-openclaw: disabled via config — no tools registered");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!config.apiKey) {
|
|
51
|
+
api.logger.warn("wix-openclaw: apiKey is empty — plugin disabled (set plugins.entries.wix-openclaw.config.apiKey)");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (config.allowedSiteIds.length === 0) {
|
|
55
|
+
api.logger.warn("wix-openclaw: allowedSiteIds is empty — every site-scoped call will be rejected. Add at least one site UUID to enable.");
|
|
56
|
+
}
|
|
57
|
+
const client = new WixClient(config, api.logger);
|
|
58
|
+
// Order doesn't matter for tools — we group by domain for log clarity.
|
|
59
|
+
const allTools = [
|
|
60
|
+
...buildBlogTools(client),
|
|
61
|
+
...buildMediaTools(client),
|
|
62
|
+
...buildSiteTools(client),
|
|
63
|
+
...buildDataTools(client),
|
|
64
|
+
...buildFormsTools(client),
|
|
65
|
+
...buildContactsTools(client),
|
|
66
|
+
...buildBookingsTools(client),
|
|
67
|
+
...buildEventsTools(client),
|
|
68
|
+
...buildReviewsTools(client),
|
|
69
|
+
...buildFaqTools(client),
|
|
70
|
+
...buildMultilingualTools(client),
|
|
71
|
+
...buildDesignTools(client),
|
|
72
|
+
];
|
|
73
|
+
for (const tool of allTools) {
|
|
74
|
+
// The SDK exposes `registerTool(tool: AnyAgentTool, opts?)`. Our
|
|
75
|
+
// factory output is shape-compatible (name, description, parameters,
|
|
76
|
+
// execute, label) but the precise `AnyAgentTool` type is inferred
|
|
77
|
+
// through several generics; we hand the runtime a structurally
|
|
78
|
+
// compatible object via an `unknown` widen.
|
|
79
|
+
api.registerTool(tool);
|
|
80
|
+
}
|
|
81
|
+
// Approval gating for destructive operations.
|
|
82
|
+
const approvalHandler = createApprovalHook(config, api.logger);
|
|
83
|
+
// The SDK's `api.on<K>` is strongly typed per hook name; cast at the
|
|
84
|
+
// boundary so we can keep our handler signature explicit.
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
86
|
+
api.on("before_tool_call", approvalHandler);
|
|
87
|
+
api.logger.info(`wix-openclaw: ready — ${allTools.length} tools registered, ${config.approvalRequired.size} approval-gated, ${config.allowedSiteIds.length} allowed site(s)`);
|
|
88
|
+
}
|
|
89
|
+
export default definePluginEntry({
|
|
90
|
+
id: "wix-openclaw",
|
|
91
|
+
name: "Wix",
|
|
92
|
+
description: "Wix REST API plugin for OpenClaw — manage blog, CMS data, forms, bookings, contacts, events, FAQ on a single Wix site with site_id whitelist and approval gating on destructive ops",
|
|
93
|
+
register(api) {
|
|
94
|
+
registerWixPlugin(api);
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Static, TSchema } from "@sinclair/typebox";
|
|
2
|
+
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
|
|
3
|
+
import { type WixClient } from "../wix-client.js";
|
|
4
|
+
/**
|
|
5
|
+
* Definition for a single Wix tool. Generic over the TypeBox schema so the
|
|
6
|
+
* `execute` body sees fully typed params.
|
|
7
|
+
*
|
|
8
|
+
* - `name` is the tool identifier exposed to the LLM. Convention:
|
|
9
|
+
* `wix_<domain>_<verb>` (e.g. `wix_blog_create_draft`).
|
|
10
|
+
* - `description` is what the model sees. Keep it short and unambiguous;
|
|
11
|
+
* mention any parameters the model is likely to forget (e.g. `richContent`
|
|
12
|
+
* format for blog posts, `MEDIA_IMAGE` ref chaining, ...).
|
|
13
|
+
* - `parameters` is a TypeBox `Type.Object(...)` schema.
|
|
14
|
+
* - `run(params, client)` does the actual API call. Returning a value (any
|
|
15
|
+
* JSON-serialisable shape) is enough — the factory wraps it as a text
|
|
16
|
+
* tool result for the model.
|
|
17
|
+
*/
|
|
18
|
+
export interface WixToolDefinition<TSchema_ extends TSchema> {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
parameters: TSchema_;
|
|
22
|
+
label?: string;
|
|
23
|
+
run: (params: Static<TSchema_>, client: WixClient, signal?: AbortSignal) => Promise<unknown>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Wrap a {@link WixToolDefinition} into the `AgentTool` shape consumed by
|
|
27
|
+
* `api.registerTool`. Captured in a closure so `client` is bound once at
|
|
28
|
+
* plugin registration time.
|
|
29
|
+
*/
|
|
30
|
+
export declare function defineWixTool<TSchema_ extends TSchema>(def: WixToolDefinition<TSchema_>, client: WixClient): {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
label: string;
|
|
34
|
+
parameters: TSchema_;
|
|
35
|
+
execute: (toolCallId: string, params: Static<TSchema_>, signal?: AbortSignal) => Promise<AgentToolResult<{
|
|
36
|
+
status: "ok" | "failed";
|
|
37
|
+
data?: unknown;
|
|
38
|
+
error?: string;
|
|
39
|
+
}>>;
|
|
40
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Tool factory shared across every Wix tool.
|
|
2
|
+
//
|
|
3
|
+
// The factory standardises:
|
|
4
|
+
// - JSON serialisation of the tool result via `payloadTextResult`
|
|
5
|
+
// - Error mapping (WixApiError, WixSiteNotAllowedError → tool failure)
|
|
6
|
+
// - The `execute(toolCallId, params, signal)` signature expected by the
|
|
7
|
+
// OpenClaw runtime
|
|
8
|
+
//
|
|
9
|
+
// Each domain file (blog, data, contacts, ...) declares its tools by
|
|
10
|
+
// calling {@link defineWixTool} and exporting an array, which the entry
|
|
11
|
+
// point collects and registers in bulk.
|
|
12
|
+
import { WixApiError, WixSiteNotAllowedError } from "../wix-client.js";
|
|
13
|
+
/**
|
|
14
|
+
* Wrap a {@link WixToolDefinition} into the `AgentTool` shape consumed by
|
|
15
|
+
* `api.registerTool`. Captured in a closure so `client` is bound once at
|
|
16
|
+
* plugin registration time.
|
|
17
|
+
*/
|
|
18
|
+
export function defineWixTool(def, client) {
|
|
19
|
+
const label = def.label ?? def.name;
|
|
20
|
+
return {
|
|
21
|
+
name: def.name,
|
|
22
|
+
description: def.description,
|
|
23
|
+
label,
|
|
24
|
+
parameters: def.parameters,
|
|
25
|
+
async execute(_toolCallId, params, signal) {
|
|
26
|
+
try {
|
|
27
|
+
const data = await def.run(params, client, signal);
|
|
28
|
+
const text = data === null || data === undefined
|
|
29
|
+
? "OK"
|
|
30
|
+
: typeof data === "string"
|
|
31
|
+
? data
|
|
32
|
+
: JSON.stringify(data, null, 2);
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: "text", text }],
|
|
35
|
+
details: { status: "ok", data },
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
// Distinguish whitelist violations from generic Wix errors so the
|
|
40
|
+
// model can react accordingly (and so tests can assert).
|
|
41
|
+
if (err instanceof WixSiteNotAllowedError) {
|
|
42
|
+
return {
|
|
43
|
+
content: [
|
|
44
|
+
{ type: "text", text: `Refused: ${err.message}` },
|
|
45
|
+
],
|
|
46
|
+
details: { status: "failed", error: err.message },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (err instanceof WixApiError) {
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
text: `Wix API error (${err.status}): ${err.bodyPreview.slice(0, 300)}`,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
details: { status: "failed", error: err.message },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: "text", text: `Error: ${msg}` }],
|
|
63
|
+
details: { status: "failed", error: msg },
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=_factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_factory.js","sourceRoot":"","sources":["../../src/tools/_factory.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,4BAA4B;AAC5B,oEAAoE;AACpE,yEAAyE;AACzE,0EAA0E;AAC1E,uBAAuB;AACvB,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,wCAAwC;AAKxC,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAkB,MAAM,kBAAkB,CAAC;AA4BvF;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAgC,EAChC,MAAiB;IAYjB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC;IAEpC,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,KAAK;QACL,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM;YACvC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBACnD,MAAM,IAAI,GACR,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;oBACjC,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ;wBACxB,CAAC,CAAC,IAAI;wBACN,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBACtC,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;oBACjC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE;iBAChC,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,kEAAkE;gBAClE,yDAAyD;gBACzD,IAAI,GAAG,YAAY,sBAAsB,EAAE,CAAC;oBAC1C,OAAO;wBACL,OAAO,EAAE;4BACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,CAAC,OAAO,EAAE,EAAE;yBAClD;wBACD,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE;qBAClD,CAAC;gBACJ,CAAC;gBACD,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;oBAC/B,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,kBAAkB,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;6BACxE;yBACF;wBACD,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE;qBAClD,CAAC;gBACJ,CAAC;gBACD,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,EAAE,EAAE,CAAC;oBAClD,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;iBAC1C,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { WixClient } from "../wix-client.js";
|
|
2
|
+
export declare function buildBlogTools(client: WixClient): ({
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
label: string;
|
|
6
|
+
parameters: import("@sinclair/typebox").TObject<{
|
|
7
|
+
siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
8
|
+
paging: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
9
|
+
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
10
|
+
offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
11
|
+
}>>;
|
|
12
|
+
}>;
|
|
13
|
+
execute: (toolCallId: string, params: {
|
|
14
|
+
siteId?: string | undefined;
|
|
15
|
+
paging?: {
|
|
16
|
+
limit?: number | undefined;
|
|
17
|
+
offset?: number | undefined;
|
|
18
|
+
} | undefined;
|
|
19
|
+
}, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
|
|
20
|
+
status: "ok" | "failed";
|
|
21
|
+
data?: unknown;
|
|
22
|
+
error?: string;
|
|
23
|
+
}>>;
|
|
24
|
+
} | {
|
|
25
|
+
name: string;
|
|
26
|
+
description: string;
|
|
27
|
+
label: string;
|
|
28
|
+
parameters: import("@sinclair/typebox").TObject<{
|
|
29
|
+
siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
30
|
+
draftPostId: import("@sinclair/typebox").TString;
|
|
31
|
+
}>;
|
|
32
|
+
execute: (toolCallId: string, params: {
|
|
33
|
+
siteId?: string | undefined;
|
|
34
|
+
draftPostId: string;
|
|
35
|
+
}, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
|
|
36
|
+
status: "ok" | "failed";
|
|
37
|
+
data?: unknown;
|
|
38
|
+
error?: string;
|
|
39
|
+
}>>;
|
|
40
|
+
} | {
|
|
41
|
+
name: string;
|
|
42
|
+
description: string;
|
|
43
|
+
label: string;
|
|
44
|
+
parameters: import("@sinclair/typebox").TObject<{
|
|
45
|
+
siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
46
|
+
title: import("@sinclair/typebox").TString;
|
|
47
|
+
richContent: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
|
|
48
|
+
excerpt: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
49
|
+
coverMedia: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
50
|
+
imageId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
51
|
+
displayed: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
52
|
+
custom: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
53
|
+
}>>;
|
|
54
|
+
tagIds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
55
|
+
categoryIds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
56
|
+
slug: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
57
|
+
seoData: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
|
|
58
|
+
}>;
|
|
59
|
+
execute: (toolCallId: string, params: {
|
|
60
|
+
siteId?: string | undefined;
|
|
61
|
+
richContent?: unknown;
|
|
62
|
+
excerpt?: string | undefined;
|
|
63
|
+
coverMedia?: {
|
|
64
|
+
imageId?: string | undefined;
|
|
65
|
+
displayed?: boolean | undefined;
|
|
66
|
+
custom?: boolean | undefined;
|
|
67
|
+
} | undefined;
|
|
68
|
+
tagIds?: string[] | undefined;
|
|
69
|
+
categoryIds?: string[] | undefined;
|
|
70
|
+
slug?: string | undefined;
|
|
71
|
+
seoData?: unknown;
|
|
72
|
+
title: string;
|
|
73
|
+
}, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
|
|
74
|
+
status: "ok" | "failed";
|
|
75
|
+
data?: unknown;
|
|
76
|
+
error?: string;
|
|
77
|
+
}>>;
|
|
78
|
+
} | {
|
|
79
|
+
name: string;
|
|
80
|
+
description: string;
|
|
81
|
+
label: string;
|
|
82
|
+
parameters: import("@sinclair/typebox").TObject<{
|
|
83
|
+
siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
84
|
+
draftPostId: import("@sinclair/typebox").TString;
|
|
85
|
+
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
86
|
+
richContent: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
|
|
87
|
+
excerpt: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
88
|
+
tagIds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
89
|
+
categoryIds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
90
|
+
slug: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
91
|
+
seoData: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
|
|
92
|
+
fieldMask: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
93
|
+
}>;
|
|
94
|
+
execute: (toolCallId: string, params: {
|
|
95
|
+
siteId?: string | undefined;
|
|
96
|
+
title?: string | undefined;
|
|
97
|
+
richContent?: unknown;
|
|
98
|
+
excerpt?: string | undefined;
|
|
99
|
+
tagIds?: string[] | undefined;
|
|
100
|
+
categoryIds?: string[] | undefined;
|
|
101
|
+
slug?: string | undefined;
|
|
102
|
+
seoData?: unknown;
|
|
103
|
+
fieldMask?: string[] | undefined;
|
|
104
|
+
draftPostId: string;
|
|
105
|
+
}, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
|
|
106
|
+
status: "ok" | "failed";
|
|
107
|
+
data?: unknown;
|
|
108
|
+
error?: string;
|
|
109
|
+
}>>;
|
|
110
|
+
} | {
|
|
111
|
+
name: string;
|
|
112
|
+
description: string;
|
|
113
|
+
label: string;
|
|
114
|
+
parameters: import("@sinclair/typebox").TObject<{
|
|
115
|
+
siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
116
|
+
postId: import("@sinclair/typebox").TString;
|
|
117
|
+
}>;
|
|
118
|
+
execute: (toolCallId: string, params: {
|
|
119
|
+
siteId?: string | undefined;
|
|
120
|
+
postId: string;
|
|
121
|
+
}, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
|
|
122
|
+
status: "ok" | "failed";
|
|
123
|
+
data?: unknown;
|
|
124
|
+
error?: string;
|
|
125
|
+
}>>;
|
|
126
|
+
} | {
|
|
127
|
+
name: string;
|
|
128
|
+
description: string;
|
|
129
|
+
label: string;
|
|
130
|
+
parameters: import("@sinclair/typebox").TObject<{
|
|
131
|
+
siteId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
132
|
+
}>;
|
|
133
|
+
execute: (toolCallId: string, params: {
|
|
134
|
+
siteId?: string | undefined;
|
|
135
|
+
}, signal?: AbortSignal) => Promise<import("@mariozechner/pi-agent-core").AgentToolResult<{
|
|
136
|
+
status: "ok" | "failed";
|
|
137
|
+
data?: unknown;
|
|
138
|
+
error?: string;
|
|
139
|
+
}>>;
|
|
140
|
+
})[];
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// Wix Blog (`/blog/v3/...`) tools.
|
|
2
|
+
//
|
|
3
|
+
// Read endpoints (list drafts, list posts, list categories, list tags)
|
|
4
|
+
// validated live against a real Ataraxis site. Write endpoints
|
|
5
|
+
// (create/update/publish/unpublish/delete) are pattern-validated against
|
|
6
|
+
// the published Wix Blog REST docs but were not exercised live to avoid
|
|
7
|
+
// polluting the production blog.
|
|
8
|
+
import { Type } from "@sinclair/typebox";
|
|
9
|
+
import { defineWixTool } from "./_factory.js";
|
|
10
|
+
const SiteIdParam = Type.Optional(Type.String({
|
|
11
|
+
description: "Wix site UUID. Optional — falls back to defaultSiteId when omitted. Must be in allowedSiteIds.",
|
|
12
|
+
}));
|
|
13
|
+
export function buildBlogTools(client) {
|
|
14
|
+
return [
|
|
15
|
+
// -------------------------------------------------------------------
|
|
16
|
+
// Drafts
|
|
17
|
+
// -------------------------------------------------------------------
|
|
18
|
+
defineWixTool({
|
|
19
|
+
name: "wix_blog_list_drafts",
|
|
20
|
+
description: "List blog draft posts (not yet published). Supports paging and basic filtering.",
|
|
21
|
+
parameters: Type.Object({
|
|
22
|
+
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 })),
|
|
26
|
+
})),
|
|
27
|
+
}),
|
|
28
|
+
run: (params) => client.request("GET", "/blog/v3/draft-posts", {
|
|
29
|
+
siteId: params.siteId,
|
|
30
|
+
query: {
|
|
31
|
+
"paging.limit": params.paging?.limit,
|
|
32
|
+
"paging.offset": params.paging?.offset,
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
}, client),
|
|
36
|
+
defineWixTool({
|
|
37
|
+
name: "wix_blog_get_draft",
|
|
38
|
+
description: "Fetch a single blog draft post by id.",
|
|
39
|
+
parameters: Type.Object({
|
|
40
|
+
siteId: SiteIdParam,
|
|
41
|
+
draftPostId: Type.String({ description: "Draft post id" }),
|
|
42
|
+
}),
|
|
43
|
+
run: (params) => client.request("GET", `/blog/v3/draft-posts/${encodeURIComponent(params.draftPostId)}`, { siteId: params.siteId }),
|
|
44
|
+
}, client),
|
|
45
|
+
defineWixTool({
|
|
46
|
+
name: "wix_blog_create_draft",
|
|
47
|
+
description: "Create a new blog draft post. `richContent` follows the Wix Ricos format. To embed an image, upload it first via wix_media_upload, then reference its `id` in a Ricos `image` node.",
|
|
48
|
+
parameters: Type.Object({
|
|
49
|
+
siteId: SiteIdParam,
|
|
50
|
+
title: Type.String(),
|
|
51
|
+
richContent: Type.Optional(Type.Unknown({
|
|
52
|
+
description: "Ricos rich-content document. See https://dev.wix.com/docs/sdk/articles/working-with-the-sdk/working-with-ricos",
|
|
53
|
+
})),
|
|
54
|
+
excerpt: Type.Optional(Type.String()),
|
|
55
|
+
coverMedia: Type.Optional(Type.Object({
|
|
56
|
+
imageId: Type.Optional(Type.String({
|
|
57
|
+
description: "Wix Site Media image id returned by wix_media_upload",
|
|
58
|
+
})),
|
|
59
|
+
displayed: Type.Optional(Type.Boolean()),
|
|
60
|
+
custom: Type.Optional(Type.Boolean()),
|
|
61
|
+
})),
|
|
62
|
+
tagIds: Type.Optional(Type.Array(Type.String())),
|
|
63
|
+
categoryIds: Type.Optional(Type.Array(Type.String())),
|
|
64
|
+
slug: Type.Optional(Type.String()),
|
|
65
|
+
seoData: Type.Optional(Type.Unknown()),
|
|
66
|
+
}),
|
|
67
|
+
run: (params) => client.request("POST", "/blog/v3/draft-posts", {
|
|
68
|
+
siteId: params.siteId,
|
|
69
|
+
body: {
|
|
70
|
+
draftPost: {
|
|
71
|
+
title: params.title,
|
|
72
|
+
richContent: params.richContent,
|
|
73
|
+
excerpt: params.excerpt,
|
|
74
|
+
media: params.coverMedia,
|
|
75
|
+
tagIds: params.tagIds,
|
|
76
|
+
categoryIds: params.categoryIds,
|
|
77
|
+
slug: params.slug,
|
|
78
|
+
seoData: params.seoData,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
}, client),
|
|
83
|
+
defineWixTool({
|
|
84
|
+
name: "wix_blog_update_draft",
|
|
85
|
+
description: "Update fields on an existing blog draft post (PATCH). Only the fields you pass are modified.",
|
|
86
|
+
parameters: Type.Object({
|
|
87
|
+
siteId: SiteIdParam,
|
|
88
|
+
draftPostId: Type.String(),
|
|
89
|
+
title: Type.Optional(Type.String()),
|
|
90
|
+
richContent: Type.Optional(Type.Unknown()),
|
|
91
|
+
excerpt: Type.Optional(Type.String()),
|
|
92
|
+
tagIds: Type.Optional(Type.Array(Type.String())),
|
|
93
|
+
categoryIds: Type.Optional(Type.Array(Type.String())),
|
|
94
|
+
slug: Type.Optional(Type.String()),
|
|
95
|
+
seoData: Type.Optional(Type.Unknown()),
|
|
96
|
+
fieldMask: Type.Optional(Type.Array(Type.String(), {
|
|
97
|
+
description: "Optional list of paths to update (e.g. ['title', 'richContent']). Falls back to changed fields when omitted.",
|
|
98
|
+
})),
|
|
99
|
+
}),
|
|
100
|
+
run: (params) => {
|
|
101
|
+
const { siteId, draftPostId, fieldMask, ...rest } = params;
|
|
102
|
+
return client.request("PATCH", `/blog/v3/draft-posts/${encodeURIComponent(draftPostId)}`, {
|
|
103
|
+
siteId,
|
|
104
|
+
body: {
|
|
105
|
+
draftPost: rest,
|
|
106
|
+
...(fieldMask ? { fieldMask: { paths: fieldMask } } : {}),
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
}, client),
|
|
111
|
+
defineWixTool({
|
|
112
|
+
name: "wix_blog_publish_draft",
|
|
113
|
+
description: "Publish a draft blog post — makes it visible to site visitors. APPROVAL GATED.",
|
|
114
|
+
parameters: Type.Object({
|
|
115
|
+
siteId: SiteIdParam,
|
|
116
|
+
draftPostId: Type.String(),
|
|
117
|
+
}),
|
|
118
|
+
run: (params) => client.request("POST", `/blog/v3/draft-posts/${encodeURIComponent(params.draftPostId)}/publish`, { siteId: params.siteId, body: {} }),
|
|
119
|
+
}, client),
|
|
120
|
+
defineWixTool({
|
|
121
|
+
name: "wix_blog_delete_draft",
|
|
122
|
+
description: "Permanently delete a blog draft. APPROVAL GATED. Prefer wix_blog_unpublish for published posts (reversible).",
|
|
123
|
+
parameters: Type.Object({
|
|
124
|
+
siteId: SiteIdParam,
|
|
125
|
+
draftPostId: Type.String(),
|
|
126
|
+
}),
|
|
127
|
+
run: (params) => client.request("DELETE", `/blog/v3/draft-posts/${encodeURIComponent(params.draftPostId)}`, { siteId: params.siteId }),
|
|
128
|
+
}, client),
|
|
129
|
+
// -------------------------------------------------------------------
|
|
130
|
+
// Published posts
|
|
131
|
+
// -------------------------------------------------------------------
|
|
132
|
+
defineWixTool({
|
|
133
|
+
name: "wix_blog_list_published",
|
|
134
|
+
description: "List published blog posts. Supports paging.",
|
|
135
|
+
parameters: Type.Object({
|
|
136
|
+
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 })),
|
|
140
|
+
})),
|
|
141
|
+
}),
|
|
142
|
+
run: (params) => client.request("GET", "/blog/v3/posts", {
|
|
143
|
+
siteId: params.siteId,
|
|
144
|
+
query: {
|
|
145
|
+
"paging.limit": params.paging?.limit,
|
|
146
|
+
"paging.offset": params.paging?.offset,
|
|
147
|
+
},
|
|
148
|
+
}),
|
|
149
|
+
}, client),
|
|
150
|
+
defineWixTool({
|
|
151
|
+
name: "wix_blog_get_post",
|
|
152
|
+
description: "Fetch a single published blog post by id.",
|
|
153
|
+
parameters: Type.Object({
|
|
154
|
+
siteId: SiteIdParam,
|
|
155
|
+
postId: Type.String(),
|
|
156
|
+
}),
|
|
157
|
+
run: (params) => client.request("GET", `/blog/v3/posts/${encodeURIComponent(params.postId)}`, { siteId: params.siteId }),
|
|
158
|
+
}, client),
|
|
159
|
+
defineWixTool({
|
|
160
|
+
name: "wix_blog_unpublish",
|
|
161
|
+
description: "Move a published blog post back to drafts (reversible). APPROVAL GATED. Use this rather than delete to keep the post recoverable.",
|
|
162
|
+
// Endpoint shape pattern-validated against the public docs.
|
|
163
|
+
// Confirm live before promoting to production destructive use.
|
|
164
|
+
parameters: Type.Object({
|
|
165
|
+
siteId: SiteIdParam,
|
|
166
|
+
postId: Type.String(),
|
|
167
|
+
}),
|
|
168
|
+
run: (params) => client.request("POST", `/blog/v3/posts/${encodeURIComponent(params.postId)}/move-to-trash`, { siteId: params.siteId, body: {} }),
|
|
169
|
+
}, client),
|
|
170
|
+
// -------------------------------------------------------------------
|
|
171
|
+
// Taxonomy
|
|
172
|
+
// -------------------------------------------------------------------
|
|
173
|
+
defineWixTool({
|
|
174
|
+
name: "wix_blog_list_categories",
|
|
175
|
+
description: "List blog categories (used to classify posts).",
|
|
176
|
+
parameters: Type.Object({ siteId: SiteIdParam }),
|
|
177
|
+
run: (params) => client.request("GET", "/blog/v3/categories", {
|
|
178
|
+
siteId: params.siteId,
|
|
179
|
+
}),
|
|
180
|
+
}, client),
|
|
181
|
+
defineWixTool({
|
|
182
|
+
name: "wix_blog_list_tags",
|
|
183
|
+
description: "List blog tags.",
|
|
184
|
+
parameters: Type.Object({ siteId: SiteIdParam }),
|
|
185
|
+
run: (params) => client.request("GET", "/blog/v3/tags", {
|
|
186
|
+
siteId: params.siteId,
|
|
187
|
+
}),
|
|
188
|
+
}, client),
|
|
189
|
+
];
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=blog.js.map
|