@kvasar/openclaw-storyblok-plugin 0.1.8 → 0.1.10

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/index.ts CHANGED
@@ -11,7 +11,7 @@ import { Type } from "@sinclair/typebox";
11
11
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
12
12
 
13
13
  import { StoryblokClient, type StoryblokConfig } from "./src/client.js";
14
- import { validateConfig, redactTokens } from "./src/config.js";
14
+ import { redactTokens } from "./src/config.js";
15
15
 
16
16
  interface StoryblokPluginConfig {
17
17
  baseUrl?: string;
@@ -31,28 +31,6 @@ interface OpenClawPluginApi {
31
31
  }): void;
32
32
  }
33
33
 
34
- interface CreateStoryParams {
35
- title: string;
36
- slug?: string;
37
- folder_id?: number;
38
- parent_id?: number;
39
- content?: Record<string, any>;
40
- tags?: string[];
41
- is_folder?: boolean;
42
- language?: string;
43
- }
44
-
45
- interface UpdateStoryParams {
46
- story_id: string;
47
- title?: string;
48
- slug?: string;
49
- content?: Record<string, any>;
50
- parent_id?: number;
51
- tags?: string[];
52
- language?: string;
53
- version?: string;
54
- }
55
-
56
34
  function ok(data: unknown) {
57
35
  return {
58
36
  content: [
@@ -77,12 +55,6 @@ function fail(error: unknown) {
77
55
  };
78
56
  }
79
57
 
80
- function safeError(error: unknown, cfg: StoryblokPluginConfig) {
81
- return fail(
82
- redactTokens(String((error as any)?.message ?? error), cfg)
83
- );
84
- }
85
-
86
58
  export default definePluginEntry({
87
59
  id: "openclaw-storyblok",
88
60
  name: "Storyblok Integration",
@@ -90,54 +62,56 @@ export default definePluginEntry({
90
62
  "Interact with Storyblok CMS: manage stories, components, and space information.",
91
63
 
92
64
  register(api: OpenClawPluginApi) {
93
- const rawCfg = (
94
- api.pluginConfig ??
95
- api.config ??
96
- {}
97
- ) as StoryblokPluginConfig;
98
-
99
- const cfg: StoryblokPluginConfig = {
100
- baseUrl: rawCfg.baseUrl ?? "https://api.storyblok.com",
101
- spaceId: rawCfg.spaceId,
102
- managementToken: rawCfg.managementToken,
103
- previewToken: rawCfg.previewToken,
104
- };
105
-
106
- try {
107
- validateConfig(cfg);
108
- } catch (error) {
109
- console.warn(
110
- "[openclaw-storyblok] Config validation warning:",
111
- error
112
- );
65
+ function resolveClient() {
66
+ const rawCfg = (api.pluginConfig ?? api.config ?? {}) as StoryblokPluginConfig;
67
+
68
+ const cfg: StoryblokPluginConfig = {
69
+ baseUrl: rawCfg.baseUrl ?? "https://api.storyblok.com",
70
+ spaceId: rawCfg.spaceId,
71
+ managementToken: rawCfg.managementToken,
72
+ previewToken: rawCfg.previewToken,
73
+ };
74
+
75
+ const clientCfg: StoryblokConfig = {
76
+ baseUrl: cfg.baseUrl!,
77
+ spaceId: cfg.spaceId ?? "",
78
+ managementToken: cfg.managementToken ?? "",
79
+ previewToken: cfg.previewToken,
80
+ };
81
+
82
+ return {
83
+ client: new StoryblokClient(clientCfg),
84
+ cfg,
85
+ };
113
86
  }
114
87
 
115
- const clientCfg: StoryblokConfig = {
116
- baseUrl: cfg.baseUrl ?? "https://api.storyblok.com",
117
- spaceId: cfg.spaceId ?? "",
118
- managementToken: cfg.managementToken ?? "",
119
- previewToken: cfg.previewToken,
120
- };
121
-
122
- const client = new StoryblokClient(clientCfg);
88
+ async function executeSafely<T>(
89
+ handler: (client: StoryblokClient, params?: T) => Promise<unknown>,
90
+ params?: T
91
+ ) {
92
+ const { client, cfg } = resolveClient();
93
+
94
+ try {
95
+ return ok(await handler(client, params));
96
+ } catch (error) {
97
+ return fail(
98
+ redactTokens(String((error as any)?.message ?? error), cfg)
99
+ );
100
+ }
101
+ }
123
102
 
124
103
  api.registerTool({
125
104
  name: "storyblok_get_space",
126
105
  description: "Retrieve Storyblok space details.",
127
106
  parameters: Type.Object({}),
128
- async execute() {
129
- try {
130
- return ok(await client.getSpace());
131
- } catch (error) {
132
- return safeError(error, cfg);
133
- }
107
+ execute() {
108
+ return executeSafely((client) => client.getSpace());
134
109
  },
135
110
  });
136
111
 
137
112
  api.registerTool({
138
113
  name: "storyblok_get_story",
139
- description:
140
- "Retrieve a story by ID, UUID, or slug.",
114
+ description: "Retrieve a story by ID, UUID, or slug.",
141
115
  parameters: Type.Object({
142
116
  identifier: Type.String({
143
117
  description: "Story ID, UUID, or slug",
@@ -150,26 +124,15 @@ export default definePluginEntry({
150
124
  language: Type.Optional(Type.String()),
151
125
  svg_render: Type.Optional(Type.Boolean()),
152
126
  }),
153
- async execute(
154
- _id: string | undefined,
155
- params: {
156
- identifier: string;
157
- version?: string;
158
- language?: string;
159
- svg_render?: boolean;
160
- }
161
- ) {
162
- try {
163
- return ok(
164
- await client.getStory(params.identifier, {
165
- version: params.version,
166
- language: params.language,
167
- svg_render: params.svg_render,
168
- })
169
- );
170
- } catch (error) {
171
- return safeError(error, cfg);
172
- }
127
+ execute(_id, params) {
128
+ return executeSafely((client, p: any) =>
129
+ client.getStory(p.identifier, {
130
+ version: p.version,
131
+ language: p.language,
132
+ svg_render: p.svg_render,
133
+ }),
134
+ params
135
+ );
173
136
  },
174
137
  });
175
138
 
@@ -186,12 +149,8 @@ export default definePluginEntry({
186
149
  sort_by: Type.Optional(Type.String()),
187
150
  direction: Type.Optional(Type.String()),
188
151
  }),
189
- async execute(_id: string | undefined, params: Record<string, any>) {
190
- try {
191
- return ok(await client.listStories(params));
192
- } catch (error) {
193
- return safeError(error, cfg);
194
- }
152
+ execute(_id, params) {
153
+ return executeSafely((client, p) => client.listStories(p), params);
195
154
  },
196
155
  });
197
156
 
@@ -203,19 +162,13 @@ export default definePluginEntry({
203
162
  slug: Type.Optional(Type.String()),
204
163
  folder_id: Type.Optional(Type.Number()),
205
164
  parent_id: Type.Optional(Type.Number()),
206
- content: Type.Optional(
207
- Type.Record(Type.String(), Type.Any())
208
- ),
165
+ content: Type.Optional(Type.Record(Type.String(), Type.Any())),
209
166
  tags: Type.Optional(Type.Array(Type.String())),
210
167
  is_folder: Type.Optional(Type.Boolean()),
211
168
  language: Type.Optional(Type.String()),
212
169
  }),
213
- async execute(_id: string | undefined, params: CreateStoryParams) {
214
- try {
215
- return ok(await client.createStory(params));
216
- } catch (error) {
217
- return safeError(error, cfg);
218
- }
170
+ execute(_id, params) {
171
+ return executeSafely((client, p) => client.createStory(p), params);
219
172
  },
220
173
  });
221
174
 
@@ -226,26 +179,17 @@ export default definePluginEntry({
226
179
  story_id: Type.String(),
227
180
  title: Type.Optional(Type.String()),
228
181
  slug: Type.Optional(Type.String()),
229
- content: Type.Optional(
230
- Type.Record(Type.String(), Type.Any())
231
- ),
182
+ content: Type.Optional(Type.Record(Type.String(), Type.Any())),
232
183
  parent_id: Type.Optional(Type.Number()),
233
184
  tags: Type.Optional(Type.Array(Type.String())),
234
185
  language: Type.Optional(Type.String()),
235
186
  version: Type.Optional(Type.String()),
236
187
  }),
237
- async execute(_id: string | undefined, params: UpdateStoryParams) {
238
- try {
239
- const { story_id, ...update } = params;
240
- return ok(
241
- await client.updateStory(
242
- story_id,
243
- update
244
- )
245
- );
246
- } catch (error) {
247
- return safeError(error, cfg);
248
- }
188
+ execute(_id, params) {
189
+ return executeSafely((client, p: any) => {
190
+ const { story_id, ...update } = p;
191
+ return client.updateStory(story_id, update);
192
+ }, params);
249
193
  },
250
194
  });
251
195
 
@@ -258,18 +202,15 @@ export default definePluginEntry({
258
202
  language: Type.Optional(Type.String()),
259
203
  publish_notes: Type.Optional(Type.String()),
260
204
  }),
261
- async execute(_id: string | undefined, params: Record<string, any>) {
262
- try {
263
- return ok(
264
- await client.publishStory(params.story_id, {
265
- version: params.version,
266
- language: params.language,
267
- publish_notes: params.publish_notes,
268
- })
269
- );
270
- } catch (error) {
271
- return safeError(error, cfg);
272
- }
205
+ execute(_id, params) {
206
+ return executeSafely((client, p: any) =>
207
+ client.publishStory(p.story_id, {
208
+ version: p.version,
209
+ language: p.language,
210
+ publish_notes: p.publish_notes,
211
+ }),
212
+ params
213
+ );
273
214
  },
274
215
  });
275
216
 
@@ -280,17 +221,11 @@ export default definePluginEntry({
280
221
  story_id: Type.String(),
281
222
  language: Type.Optional(Type.String()),
282
223
  }),
283
- async execute(_id: string | undefined, params: Record<string, any>) {
284
- try {
285
- return ok(
286
- await client.unpublishStory(
287
- params.story_id,
288
- params.language
289
- )
290
- );
291
- } catch (error) {
292
- return safeError(error, cfg);
293
- }
224
+ execute(_id, params) {
225
+ return executeSafely((client, p: any) =>
226
+ client.unpublishStory(p.story_id, p.language),
227
+ params
228
+ );
294
229
  },
295
230
  });
296
231
 
@@ -301,17 +236,11 @@ export default definePluginEntry({
301
236
  version: Type.Optional(Type.String()),
302
237
  language: Type.Optional(Type.String()),
303
238
  }),
304
- async execute(_id: string | undefined, params: Record<string, any>) {
305
- try {
306
- return ok(
307
- await client.getComponents(
308
- params.version,
309
- params.language
310
- )
311
- );
312
- } catch (error) {
313
- return safeError(error, cfg);
314
- }
239
+ execute(_id, params) {
240
+ return executeSafely((client, p: any) =>
241
+ client.getComponents(p.version, p.language),
242
+ params
243
+ );
315
244
  },
316
245
  });
317
246
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-storyblok",
3
3
  "name": "Storyblok Integration",
4
- "version": "0.1.8",
4
+ "version": "0.1.10",
5
5
  "description": "Provides tools to interact with Storyblok CMS via Management API and Delivery API. Supports stories, components, and space management.",
6
6
  "skills": ["skills"],
7
7
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kvasar/openclaw-storyblok-plugin",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "OpenClaw plugin — interact with Storyblok CMS via Management API and Delivery API",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
package/skills/SKILL.md CHANGED
@@ -31,6 +31,68 @@ This skill package provides agents with the ability to work with **Storyblok CMS
31
31
 
32
32
  ## Core Concepts
33
33
 
34
+
35
+
36
+ ### Storyblok Block Types
37
+
38
+ Storyblok components can be organized into three structural categories:
39
+
40
+ #### Nestable Block
41
+
42
+ Reusable blocks that are inserted **inside other blocks or pages**.
43
+
44
+ Examples:
45
+
46
+ - Hero
47
+ - Grid
48
+ - Section
49
+ - Newsletter Section
50
+ - Chapter
51
+ - Full Width Image
52
+ - Slider
53
+ - CTA Banner
54
+ - Feature Grid
55
+
56
+ Use these when building modular page layouts.
57
+
58
+ ---
59
+
60
+ #### Content Type Block
61
+
62
+ Top-level content models representing an entry/page/document.
63
+
64
+ Examples:
65
+
66
+ - Landing Page
67
+ - Post
68
+ - Authors
69
+ - Product
70
+ - Page
71
+ - Team Members
72
+ - FAQ Article
73
+ - Case Study
74
+
75
+ Use these as standalone entries in Storyblok.
76
+
77
+ ---
78
+
79
+ #### Universal Block
80
+
81
+ A block that can be used **both as a content type and nested block**.
82
+
83
+ Examples:
84
+
85
+ - FAQ Section
86
+ - Testimonials
87
+ - Rich Text Section
88
+ - Gallery
89
+ - Reusable Promo Page
90
+ - Contact Section
91
+
92
+ Use when flexibility is needed across multiple content structures.
93
+
94
+ ---
95
+
34
96
  ### Tools
35
97
 
36
98
  All tools are provided by the `openclaw-storyblok` plugin: