foliko 1.0.86 → 1.1.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 (104) hide show
  1. package/.agent/data/default.json +3 -4310
  2. package/.agent/data/plugins-state.json +34 -1
  3. package/.agent/mcp_config.json +0 -1
  4. package/.agent/memory/core.md +1 -0
  5. package/.agent/memory/project/mnn93ogy-ypjn27.md +9 -0
  6. package/.agent/memory/project/mnn98fqy-5nhc1u.md +25 -0
  7. package/.agent/memory/user/mnm67t9m-x8rekk.md +9 -0
  8. package/.agent/memory/user/mnn5mmqh-w6aktx.md +11 -0
  9. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +22 -0
  10. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  11. package/.agent/plugins/marknative/index.js +2 -7
  12. package/.agent/plugins/poster-plugin/README.md +304 -0
  13. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  14. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  15. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221/347/262/227/344/275/223.ttf +0 -0
  16. package/.agent/plugins/poster-plugin/index.js +13 -0
  17. package/.agent/plugins/poster-plugin/package.json +28 -0
  18. package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
  19. package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
  20. package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
  21. package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
  22. package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
  23. package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
  24. package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
  25. package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
  26. package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
  27. package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
  28. package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
  29. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
  30. package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
  31. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
  32. package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
  33. package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
  34. package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
  35. package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
  36. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
  37. package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
  38. package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
  39. package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
  40. package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
  41. package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
  42. package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
  43. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
  44. package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
  45. package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
  46. package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
  47. package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
  48. package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
  49. package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
  50. package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
  51. package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
  52. package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
  53. package/.agent/plugins/poster-plugin/src/elements/polygon.js +32 -0
  54. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
  55. package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
  56. package/.agent/plugins/poster-plugin/src/elements/text.js +38 -0
  57. package/.agent/plugins/poster-plugin/src/fonts.js +118 -0
  58. package/.agent/plugins/poster-plugin/src/index.js +1659 -0
  59. package/.agent/plugins/poster-plugin/src/presets.js +36 -0
  60. package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
  61. package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
  62. package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
  63. package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
  64. package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
  65. package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
  66. package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
  67. package/.agent/sessions/cli_default.json +24265 -0
  68. package/.agent/weixin.json +6 -0
  69. package/.claude/settings.local.json +176 -171
  70. package/CLAUDE.md +144 -108
  71. package/docs/CONTEXT_DESIGN.md +1596 -0
  72. package/examples/test-concurrent-chat.js +60 -0
  73. package/examples/test-long-chat.js +77 -0
  74. package/examples/test-session-chat.js +93 -0
  75. package/output/beef-love-poster.png +0 -0
  76. package/package.json +2 -2
  77. package/plugins/default-plugins.js +2 -1
  78. package/plugins/extension-executor-plugin.js +11 -0
  79. package/plugins/memory-plugin.js +984 -0
  80. package/plugins/session-plugin.js +78 -1
  81. package/plugins/weixin-plugin.js +24 -22
  82. package/skills/poster-guide/SKILL.md +743 -0
  83. package/skills/python-plugin-dev/SKILL.md +238 -238
  84. package/skills/skill-guide/SKILL.md +130 -108
  85. package/src/capabilities/skill-manager.js +99 -0
  86. package/src/core/agent-chat.js +627 -180
  87. package/src/core/agent-context.js +188 -0
  88. package/src/core/agent.js +9 -63
  89. package/src/core/context-manager.js +283 -0
  90. package/src/core/framework.js +264 -3
  91. package/src/core/plugin-manager.js +79 -2
  92. package/src/core/request-context.js +98 -0
  93. package/src/core/session-context.js +341 -0
  94. package/src/core/session-storage.js +274 -0
  95. package/src/executors/mcp-executor.js +2 -2
  96. package/src/utils/index.js +239 -67
  97. package/src/utils/plugin-helpers.js +17 -0
  98. package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
  99. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  100. package/.agent/plugins/temp-repo/LICENSE +0 -201
  101. package/.agent/plugins/temp-repo/puppeteer-plugin/README.md +0 -147
  102. package/.agent/plugins/temp-repo/puppeteer-plugin/index.js +0 -1418
  103. package/.agent/plugins/temp-repo/puppeteer-plugin/package.json +0 -9
  104. package/.agent/plugins/test_plugin.py +0 -304
@@ -0,0 +1,1659 @@
1
+ /**
2
+ * Poster Plugin - 海报制作插件 (重构版)
3
+ *
4
+ * 模块化架构,支持组件化海报生成
5
+ */
6
+
7
+ const { z } = require('zod')
8
+ const path = require('path')
9
+ const fs = require('fs')
10
+
11
+ // 导入模块
12
+ const PRESETS = require('./presets')
13
+ const CanvasManager = require('./canvas')
14
+ const { createFromConfig, COMPONENT_TYPES } = require('./composer')
15
+ const { applyTemplate, getAvailableTemplates } = require('./templates')
16
+ const {
17
+ addRectangle,
18
+ addCircle,
19
+ addLine,
20
+ addPolygon,
21
+ addImage,
22
+ addText,
23
+ addArtText,
24
+ addBackground,
25
+ addSVG,
26
+ } = require('./elements')
27
+ const {
28
+ createCard,
29
+ createBadge,
30
+ createCTA,
31
+ createFeature,
32
+ createFeatureGrid,
33
+ createDivider,
34
+ createAvatar,
35
+ createProgress,
36
+ createRating,
37
+ createQuote,
38
+ createStatCard,
39
+ createTagCloud,
40
+ createStepper,
41
+ createTimeline,
42
+ createListItem,
43
+ createNotification,
44
+ createImageFrame,
45
+ createColumns,
46
+ createGrid,
47
+ createStar,
48
+ createArrow,
49
+ createProgressCircle,
50
+ createChip,
51
+ createChart,
52
+ createWatermark,
53
+ createTable,
54
+ } = require('./components')
55
+
56
+ module.exports = function (Plugin) {
57
+ return class PosterPlugin extends Plugin {
58
+ constructor(config = {}) {
59
+ super()
60
+ this.name = 'poster'
61
+ this.version = '1.1.0'
62
+ this.description = '海报制作插件 - 支持组件化海报生成'
63
+ this.priority = 15
64
+
65
+ this._framework = null
66
+ this._canvasManager = new CanvasManager()
67
+ }
68
+
69
+ async install(framework) {
70
+ this._framework = framework
71
+ console.log('[poster] Poster plugin installed (v1.1.0)')
72
+ console.log('[poster] Components:', Object.keys(COMPONENT_TYPES).join(', '))
73
+ return this
74
+ }
75
+
76
+ start(framework) {
77
+ console.log('[poster] Poster plugin started')
78
+ }
79
+
80
+ // ==================== 工具定义 ====================
81
+
82
+ all_tools = {
83
+ // ==================== 画布管理 ====================
84
+
85
+ /**
86
+ * 列出预设尺寸
87
+ */
88
+ list_poster_presets: {
89
+ description: '列出所有可用的海报/Banner预设尺寸',
90
+ inputSchema: z.object({}),
91
+ execute: async () => ({
92
+ success: true,
93
+ presets: Object.entries(PRESETS).map(([key, value]) => ({ key, ...value })),
94
+ }),
95
+ },
96
+
97
+ /**
98
+ * 创建画布
99
+ */
100
+ create_poster_canvas: {
101
+ description: '创建新画布,支持预设尺寸或自定义尺寸',
102
+ inputSchema: z.object({
103
+ preset: z.string().optional().describe('预设尺寸key'),
104
+ width: z.number().optional().describe('自定义宽度'),
105
+ height: z.number().optional().describe('自定义高度'),
106
+ background: z.string().optional().describe('背景颜色'),
107
+ }),
108
+ execute: async (args) => {
109
+ try {
110
+ const result = this._canvasManager.create(args)
111
+ return { success: true, ...result }
112
+ } catch (err) {
113
+ return { success: false, error: err.message }
114
+ }
115
+ },
116
+ },
117
+
118
+ /**
119
+ * 获取画布信息
120
+ */
121
+ get_poster_canvas_info: {
122
+ description: '获取当前画布信息',
123
+ inputSchema: z.object({}),
124
+ execute: async () => {
125
+ if (!this._canvasManager.isCreated()) {
126
+ return { success: false, error: 'No canvas created' }
127
+ }
128
+ const size = this._canvasManager.getSize()
129
+ return {
130
+ success: true,
131
+ ...size,
132
+ elementCount: this._canvasManager.getElementCount(),
133
+ }
134
+ },
135
+ },
136
+
137
+ /**
138
+ * 清除画布
139
+ */
140
+ clear_poster_canvas: {
141
+ description: '清除画布上的所有元素',
142
+ inputSchema: z.object({}),
143
+ execute: async () => {
144
+ if (!this._canvasManager.isCreated()) {
145
+ return { success: false, error: 'No canvas created' }
146
+ }
147
+ this._canvasManager.clear()
148
+ return { success: true, message: 'Canvas cleared' }
149
+ },
150
+ },
151
+
152
+ // ==================== 基础元素 ====================
153
+
154
+ /**
155
+ * 添加背景
156
+ */
157
+ add_poster_background: {
158
+ description: '为画布添加纯色或渐变背景',
159
+ inputSchema: z.object({
160
+ color: z.string().optional().describe('纯色背景'),
161
+ gradient: z.object({
162
+ type: z.enum(['linear', 'radial']).describe('渐变类型'),
163
+ colors: z.array(z.string()).describe('颜色数组'),
164
+ direction: z.number().optional().describe('方向角度,默认45'),
165
+ }).optional(),
166
+ }),
167
+ execute: async (args) => {
168
+ try {
169
+ if (!this._canvasManager.isCreated()) {
170
+ return { success: false, error: 'No canvas created' }
171
+ }
172
+ return addBackground(
173
+ this._canvasManager.getProject(),
174
+ this._canvasManager.getCanvas(),
175
+ args
176
+ )
177
+ } catch (err) {
178
+ return { success: false, error: err.message }
179
+ }
180
+ },
181
+ },
182
+
183
+ /**
184
+ * 添加矩形
185
+ */
186
+ add_poster_rectangle: {
187
+ description: '在画布上添加矩形',
188
+ inputSchema: z.object({
189
+ x: z.number().describe('X坐标'),
190
+ y: z.number().describe('Y坐标'),
191
+ width: z.number().describe('宽度'),
192
+ height: z.number().describe('高度'),
193
+ fill: z.string().optional().describe('填充颜色'),
194
+ stroke: z.string().optional().describe('边框颜色'),
195
+ strokeWidth: z.number().optional().describe('边框宽度'),
196
+ radius: z.number().optional().describe('圆角半径'),
197
+ opacity: z.number().optional().describe('透明度 0-1'),
198
+ }),
199
+ execute: async (args) => {
200
+ try {
201
+ if (!this._canvasManager.isCreated()) {
202
+ return { success: false, error: 'No canvas created' }
203
+ }
204
+ return addRectangle(this._canvasManager.getProject(), args)
205
+ } catch (err) {
206
+ return { success: false, error: err.message }
207
+ }
208
+ },
209
+ },
210
+
211
+ /**
212
+ * 添加圆形
213
+ */
214
+ add_poster_circle: {
215
+ description: '在画布上添加圆形或椭圆',
216
+ inputSchema: z.object({
217
+ cx: z.number().describe('圆心X坐标'),
218
+ cy: z.number().describe('圆心Y坐标'),
219
+ rx: z.number().describe('X轴半径'),
220
+ ry: z.number().optional().describe('Y轴半径'),
221
+ fill: z.string().optional().describe('填充颜色'),
222
+ stroke: z.string().optional().describe('边框颜色'),
223
+ strokeWidth: z.number().optional().describe('边框宽度'),
224
+ opacity: z.number().optional().describe('透明度 0-1'),
225
+ }),
226
+ execute: async (args) => {
227
+ try {
228
+ if (!this._canvasManager.isCreated()) {
229
+ return { success: false, error: 'No canvas created' }
230
+ }
231
+ return addCircle(this._canvasManager.getProject(), args)
232
+ } catch (err) {
233
+ return { success: false, error: err.message }
234
+ }
235
+ },
236
+ },
237
+
238
+ /**
239
+ * 添加线条
240
+ */
241
+ add_poster_line: {
242
+ description: '在画布上添加线条',
243
+ inputSchema: z.object({
244
+ x1: z.number().describe('起点X'),
245
+ y1: z.number().describe('起点Y'),
246
+ x2: z.number().describe('终点X'),
247
+ y2: z.number().describe('终点Y'),
248
+ stroke: z.string().optional().describe('线条颜色'),
249
+ strokeWidth: z.number().optional().describe('线条宽度'),
250
+ }),
251
+ execute: async (args) => {
252
+ try {
253
+ if (!this._canvasManager.isCreated()) {
254
+ return { success: false, error: 'No canvas created' }
255
+ }
256
+ return addLine(this._canvasManager.getProject(), args)
257
+ } catch (err) {
258
+ return { success: false, error: err.message }
259
+ }
260
+ },
261
+ },
262
+
263
+ /**
264
+ * 添加多边形
265
+ */
266
+ add_poster_polygon: {
267
+ description: '在画布上添加多边形',
268
+ inputSchema: z.object({
269
+ cx: z.number().describe('中心X坐标'),
270
+ cy: z.number().describe('中心Y坐标'),
271
+ radius: z.number().describe('外接圆半径'),
272
+ sides: z.number().describe('边数'),
273
+ fill: z.string().optional().describe('填充颜色'),
274
+ stroke: z.string().optional().describe('边框颜色'),
275
+ strokeWidth: z.number().optional().describe('边框宽度'),
276
+ opacity: z.number().optional().describe('透明度 0-1'),
277
+ }),
278
+ execute: async (args) => {
279
+ try {
280
+ if (!this._canvasManager.isCreated()) {
281
+ return { success: false, error: 'No canvas created' }
282
+ }
283
+ return addPolygon(this._canvasManager.getProject(), args)
284
+ } catch (err) {
285
+ return { success: false, error: err.message }
286
+ }
287
+ },
288
+ },
289
+
290
+ /**
291
+ * 添加文字
292
+ */
293
+ add_poster_text: {
294
+ description: '在画布上添加文字',
295
+ inputSchema: z.object({
296
+ text: z.string().describe('文字内容'),
297
+ x: z.number().describe('X坐标'),
298
+ y: z.number().describe('Y坐标'),
299
+ fontSize: z.number().optional().describe('字体大小,默认48'),
300
+ fontFamily: z.string().optional().describe('字体名称'),
301
+ color: z.string().optional().describe('文字颜色'),
302
+ align: z.enum(['left', 'center', 'right']).optional().describe('对齐方式'),
303
+ shadow: z.object({
304
+ color: z.string().describe('阴影颜色'),
305
+ blur: z.number().optional(),
306
+ offsetX: z.number().optional(),
307
+ offsetY: z.number().optional(),
308
+ }).optional(),
309
+ }),
310
+ execute: async (args) => {
311
+ try {
312
+ if (!this._canvasManager.isCreated()) {
313
+ return { success: false, error: 'No canvas created' }
314
+ }
315
+ return addText(this._canvasManager.getProject(), args)
316
+ } catch (err) {
317
+ return { success: false, error: err.message }
318
+ }
319
+ },
320
+ },
321
+
322
+ /**
323
+ * 添加艺术文字
324
+ */
325
+ add_poster_art_text: {
326
+ description: '添加艺术文字,支持渐变填充和描边',
327
+ inputSchema: z.object({
328
+ text: z.string().describe('文字内容'),
329
+ x: z.number().describe('X坐标'),
330
+ y: z.number().describe('Y坐标'),
331
+ fontSize: z.number().optional().describe('字体大小,默认120'),
332
+ fontFamily: z.string().optional().describe('字体名称'),
333
+ gradient: z.object({
334
+ colors: z.array(z.string()).describe('渐变颜色数组'),
335
+ direction: z.number().optional().describe('方向角度'),
336
+ }).optional(),
337
+ strokeColor: z.string().optional().describe('描边颜色'),
338
+ strokeWidth: z.number().optional().describe('描边宽度'),
339
+ shadow: z.object({
340
+ color: z.string().describe('阴影颜色'),
341
+ blur: z.number().optional(),
342
+ offsetX: z.number().optional(),
343
+ offsetY: z.number().optional(),
344
+ }).optional(),
345
+ }),
346
+ execute: async (args) => {
347
+ try {
348
+ if (!this._canvasManager.isCreated()) {
349
+ return { success: false, error: 'No canvas created' }
350
+ }
351
+ return addArtText(this._canvasManager.getProject(), args)
352
+ } catch (err) {
353
+ return { success: false, error: err.message }
354
+ }
355
+ },
356
+ },
357
+
358
+ /**
359
+ * 添加图片
360
+ */
361
+ add_poster_image: {
362
+ description: '在画布上添加图片',
363
+ inputSchema: z.object({
364
+ src: z.string().describe('图片路径或URL'),
365
+ x: z.number().describe('X坐标'),
366
+ y: z.number().describe('Y坐标'),
367
+ width: z.number().optional().describe('图片宽度'),
368
+ height: z.number().optional().describe('图片高度'),
369
+ opacity: z.number().optional().describe('透明度 0-1'),
370
+ }),
371
+ execute: async (args) => {
372
+ try {
373
+ if (!this._canvasManager.isCreated()) {
374
+ return { success: false, error: 'No canvas created' }
375
+ }
376
+ return addImage(this._canvasManager.getProject(), args)
377
+ } catch (err) {
378
+ return { success: false, error: err.message }
379
+ }
380
+ },
381
+ },
382
+
383
+ // ==================== SVG 支持 ====================
384
+
385
+ /**
386
+ * 导入 SVG 文件或内容
387
+ */
388
+ add_poster_svg: {
389
+ description: '在画布上添加 SVG(支持文件路径或 SVG 字符串)',
390
+ inputSchema: z.object({
391
+ src: z.string().describe('SVG 文件路径或 SVG 字符串'),
392
+ x: z.number().describe('X坐标'),
393
+ y: z.number().describe('Y坐标'),
394
+ width: z.number().optional().describe('宽度'),
395
+ height: z.number().optional().describe('高度'),
396
+ opacity: z.number().optional().describe('透明度 0-1'),
397
+ }),
398
+ execute: async (args) => {
399
+ try {
400
+ if (!this._canvasManager.isCreated()) {
401
+ return { success: false, error: 'No canvas created' }
402
+ }
403
+ return addSVG(this._canvasManager.getProject(), args)
404
+ } catch (err) {
405
+ return { success: false, error: err.message }
406
+ }
407
+ },
408
+ },
409
+
410
+ /**
411
+ * 导出为 SVG 格式
412
+ */
413
+ export_poster_svg: {
414
+ description: '导出画布为 SVG 格式',
415
+ inputSchema: z.object({
416
+ filename: z.string().describe('文件名(不含扩展名)'),
417
+ outputDir: z.string().optional().describe('输出目录'),
418
+ }),
419
+ execute: async (args) => {
420
+ try {
421
+ if (!this._canvasManager.isCreated()) {
422
+ return { success: false, error: 'No canvas created' }
423
+ }
424
+
425
+ const outputDir = args.outputDir || '.'
426
+ const filename = `${args.filename}.svg`
427
+ await fs.promises.mkdir(outputDir, { recursive: true })
428
+ const filepath = path.join(outputDir, filename)
429
+
430
+ const svg = this._canvasManager.getProject().exportSVG({
431
+ asString: true,
432
+ bounds: 'content',
433
+ })
434
+
435
+ await fs.promises.writeFile(filepath, svg)
436
+
437
+ return {
438
+ success: true,
439
+ filepath,
440
+ filename,
441
+ format: 'svg',
442
+ size: Buffer.byteLength(svg),
443
+ }
444
+ } catch (err) {
445
+ return { success: false, error: err.message }
446
+ }
447
+ },
448
+ },
449
+
450
+ /**
451
+ * 导出为 SVG Base64
452
+ */
453
+ export_poster_svg_base64: {
454
+ description: '导出画布为 SVG Base64 编码',
455
+ inputSchema: z.object({}),
456
+ execute: async () => {
457
+ try {
458
+ if (!this._canvasManager.isCreated()) {
459
+ return { success: false, error: 'No canvas created' }
460
+ }
461
+
462
+ const svg = this._canvasManager.getProject().exportSVG({
463
+ asString: true,
464
+ bounds: 'content',
465
+ })
466
+
467
+ const base64 = Buffer.from(svg).toString('base64')
468
+
469
+ return {
470
+ success: true,
471
+ base64,
472
+ svg,
473
+ mimeType: 'image/svg+xml',
474
+ }
475
+ } catch (err) {
476
+ return { success: false, error: err.message }
477
+ }
478
+ },
479
+ },
480
+
481
+ // ==================== 高级组件 ====================
482
+
483
+ /**
484
+ * 添加卡片组件
485
+ */
486
+ add_poster_card: {
487
+ description: '添加卡片组件(带背景、标题、副标题)',
488
+ inputSchema: z.object({
489
+ x: z.number().describe('X坐标'),
490
+ y: z.number().describe('Y坐标'),
491
+ width: z.number().describe('卡片宽度'),
492
+ height: z.number().describe('卡片高度'),
493
+ background: z.string().optional().describe('背景色'),
494
+ border: z.string().optional().describe('边框颜色'),
495
+ borderWidth: z.number().optional().describe('边框宽度'),
496
+ radius: z.number().optional().describe('圆角半径'),
497
+ title: z.string().optional().describe('标题文字'),
498
+ titleSize: z.number().optional().describe('标题字体大小'),
499
+ titleColor: z.string().optional().describe('标题颜色'),
500
+ subtitle: z.string().optional().describe('副标题'),
501
+ subtitleSize: z.number().optional().describe('副标题字体大小'),
502
+ subtitleColor: z.string().optional().describe('副标题颜色'),
503
+ padding: z.number().optional().describe('内边距'),
504
+ }),
505
+ execute: async (args) => {
506
+ try {
507
+ if (!this._canvasManager.isCreated()) {
508
+ return { success: false, error: 'No canvas created' }
509
+ }
510
+ return createCard(
511
+ this._canvasManager.getProject(),
512
+ this._canvasManager.getCanvas(),
513
+ args
514
+ )
515
+ } catch (err) {
516
+ return { success: false, error: err.message }
517
+ }
518
+ },
519
+ },
520
+
521
+ /**
522
+ * 添加徽章组件
523
+ */
524
+ add_poster_badge: {
525
+ description: '添加徽章/标签组件',
526
+ inputSchema: z.object({
527
+ x: z.number().describe('X坐标(居中)'),
528
+ y: z.number().describe('Y坐标'),
529
+ text: z.string().describe('徽章文字'),
530
+ background: z.string().optional().describe('背景色'),
531
+ color: z.string().optional().describe('文字颜色'),
532
+ border: z.string().optional().describe('边框颜色'),
533
+ fontSize: z.number().optional().describe('字体大小'),
534
+ padding: z.number().optional().describe('内边距'),
535
+ radius: z.number().optional().describe('圆角半径'),
536
+ }),
537
+ execute: async (args) => {
538
+ try {
539
+ if (!this._canvasManager.isCreated()) {
540
+ return { success: false, error: 'No canvas created' }
541
+ }
542
+ return createBadge(
543
+ this._canvasManager.getProject(),
544
+ this._canvasManager.getCanvas(),
545
+ args
546
+ )
547
+ } catch (err) {
548
+ return { success: false, error: err.message }
549
+ }
550
+ },
551
+ },
552
+
553
+ /**
554
+ * 添加 CTA 按钮
555
+ */
556
+ add_poster_cta: {
557
+ description: '添加行动号召按钮',
558
+ inputSchema: z.object({
559
+ x: z.number().describe('X坐标(居中)'),
560
+ y: z.number().describe('Y坐标'),
561
+ text: z.string().describe('按钮文字'),
562
+ background: z.string().optional().describe('背景色'),
563
+ color: z.string().optional().describe('文字颜色'),
564
+ border: z.string().optional().describe('边框颜色'),
565
+ fontSize: z.number().optional().describe('字体大小'),
566
+ padding: z.number().optional().describe('内边距'),
567
+ radius: z.number().optional().describe('圆角半径'),
568
+ shadow: z.object({
569
+ color: z.string().optional(),
570
+ blur: z.number().optional(),
571
+ offsetX: z.number().optional(),
572
+ offsetY: z.number().optional(),
573
+ }).optional(),
574
+ }),
575
+ execute: async (args) => {
576
+ try {
577
+ if (!this._canvasManager.isCreated()) {
578
+ return { success: false, error: 'No canvas created' }
579
+ }
580
+ return createCTA(
581
+ this._canvasManager.getProject(),
582
+ this._canvasManager.getCanvas(),
583
+ args
584
+ )
585
+ } catch (err) {
586
+ return { success: false, error: err.message }
587
+ }
588
+ },
589
+ },
590
+
591
+ /**
592
+ * 添加特性展示
593
+ */
594
+ add_poster_feature: {
595
+ description: '添加特性展示块',
596
+ inputSchema: z.object({
597
+ x: z.number().describe('X坐标'),
598
+ y: z.number().describe('Y坐标'),
599
+ width: z.number().describe('宽度'),
600
+ icon: z.string().optional().describe('图标 emoji'),
601
+ title: z.string().optional().describe('标题'),
602
+ description: z.string().optional().describe('描述'),
603
+ iconColor: z.string().optional().describe('图标颜色'),
604
+ titleColor: z.string().optional().describe('标题颜色'),
605
+ descColor: z.string().optional().describe('描述颜色'),
606
+ iconSize: z.number().optional().describe('图标大小'),
607
+ titleSize: z.number().optional().describe('标题大小'),
608
+ descSize: z.number().optional().describe('描述大小'),
609
+ }),
610
+ execute: async (args) => {
611
+ try {
612
+ if (!this._canvasManager.isCreated()) {
613
+ return { success: false, error: 'No canvas created' }
614
+ }
615
+ return createFeature(
616
+ this._canvasManager.getProject(),
617
+ this._canvasManager.getCanvas(),
618
+ args
619
+ )
620
+ } catch (err) {
621
+ return { success: false, error: err.message }
622
+ }
623
+ },
624
+ },
625
+
626
+ /**
627
+ * 添加特性网格
628
+ */
629
+ add_poster_feature_grid: {
630
+ description: '添加特性网格布局',
631
+ inputSchema: z.object({
632
+ x: z.number().describe('X坐标'),
633
+ y: z.number().describe('Y坐标'),
634
+ columns: z.number().optional().describe('列数,默认3'),
635
+ itemWidth: z.number().optional().describe('每个特性宽度,默认200'),
636
+ itemHeight: z.number().optional().describe('每个特性高度,默认120'),
637
+ gap: z.number().optional().describe('间距,默认20'),
638
+ items: z.array(z.object({
639
+ icon: z.string().optional(),
640
+ title: z.string().optional(),
641
+ description: z.string().optional(),
642
+ iconColor: z.string().optional(),
643
+ titleColor: z.string().optional(),
644
+ descColor: z.string().optional(),
645
+ })).describe('特性数组'),
646
+ background: z.string().optional().describe('背景色'),
647
+ borderColor: z.string().optional().describe('边框颜色'),
648
+ radius: z.number().optional().describe('圆角半径'),
649
+ }),
650
+ execute: async (args) => {
651
+ try {
652
+ if (!this._canvasManager.isCreated()) {
653
+ return { success: false, error: 'No canvas created' }
654
+ }
655
+ return createFeatureGrid(
656
+ this._canvasManager.getProject(),
657
+ this._canvasManager.getCanvas(),
658
+ args
659
+ )
660
+ } catch (err) {
661
+ return { success: false, error: err.message }
662
+ }
663
+ },
664
+ },
665
+
666
+ /**
667
+ * 添加分隔线
668
+ */
669
+ add_poster_divider: {
670
+ description: '添加分隔线',
671
+ inputSchema: z.object({
672
+ x: z.number().describe('X坐标'),
673
+ y: z.number().describe('Y坐标'),
674
+ width: z.number().describe('宽度'),
675
+ color: z.string().optional().describe('颜色'),
676
+ thickness: z.number().optional().describe('厚度'),
677
+ style: z.enum(['solid', 'dashed']).optional().describe('样式'),
678
+ align: z.enum(['left', 'center', 'right']).optional().describe('对齐'),
679
+ }),
680
+ execute: async (args) => {
681
+ try {
682
+ if (!this._canvasManager.isCreated()) {
683
+ return { success: false, error: 'No canvas created' }
684
+ }
685
+ return createDivider(
686
+ this._canvasManager.getProject(),
687
+ this._canvasManager.getCanvas(),
688
+ args
689
+ )
690
+ } catch (err) {
691
+ return { success: false, error: err.message }
692
+ }
693
+ },
694
+ },
695
+
696
+ /**
697
+ * 添加头像
698
+ */
699
+ add_poster_avatar: {
700
+ description: '添加头像组件',
701
+ inputSchema: z.object({
702
+ x: z.number().describe('圆心X坐标'),
703
+ y: z.number().describe('圆心Y坐标'),
704
+ size: z.number().optional().describe('头像大小'),
705
+ initials: z.string().optional().describe('首字母'),
706
+ background: z.string().optional().describe('背景色'),
707
+ border: z.string().optional().describe('边框颜色'),
708
+ borderWidth: z.number().optional().describe('边框宽度'),
709
+ color: z.string().optional().describe('文字颜色'),
710
+ }),
711
+ execute: async (args) => {
712
+ try {
713
+ if (!this._canvasManager.isCreated()) {
714
+ return { success: false, error: 'No canvas created' }
715
+ }
716
+ return createAvatar(
717
+ this._canvasManager.getProject(),
718
+ this._canvasManager.getCanvas(),
719
+ args
720
+ )
721
+ } catch (err) {
722
+ return { success: false, error: err.message }
723
+ }
724
+ },
725
+ },
726
+
727
+ /**
728
+ * 添加进度条
729
+ */
730
+ add_poster_progress: {
731
+ description: '添加进度条组件',
732
+ inputSchema: z.object({
733
+ x: z.number().describe('X坐标'),
734
+ y: z.number().describe('Y坐标'),
735
+ width: z.number().optional().describe('进度条宽度'),
736
+ height: z.number().optional().describe('进度条高度'),
737
+ value: z.number().optional().describe('进度值 0-100'),
738
+ trackColor: z.string().optional().describe('轨道颜色'),
739
+ fillColor: z.string().optional().describe('填充颜色'),
740
+ radius: z.number().optional().describe('圆角半径'),
741
+ showLabel: z.boolean().optional().describe('是否显示标签'),
742
+ label: z.string().optional().describe('标签文字'),
743
+ }),
744
+ execute: async (args) => {
745
+ try {
746
+ if (!this._canvasManager.isCreated()) {
747
+ return { success: false, error: 'No canvas created' }
748
+ }
749
+ return createProgress(
750
+ this._canvasManager.getProject(),
751
+ this._canvasManager.getCanvas(),
752
+ args
753
+ )
754
+ } catch (err) {
755
+ return { success: false, error: err.message }
756
+ }
757
+ },
758
+ },
759
+
760
+ /**
761
+ * 添加星级评分
762
+ */
763
+ add_poster_rating: {
764
+ description: '添加星级评分组件',
765
+ inputSchema: z.object({
766
+ x: z.number().describe('X坐标'),
767
+ y: z.number().describe('Y坐标'),
768
+ value: z.number().optional().describe('评分值 0-5'),
769
+ max: z.number().optional().describe('最大值'),
770
+ size: z.number().optional().describe('星星大小'),
771
+ filledColor: z.string().optional().describe('填充颜色'),
772
+ emptyColor: z.string().optional().describe('空心颜色'),
773
+ gap: z.number().optional().describe('星星间距'),
774
+ }),
775
+ execute: async (args) => {
776
+ try {
777
+ if (!this._canvasManager.isCreated()) {
778
+ return { success: false, error: 'No canvas created' }
779
+ }
780
+ return createRating(
781
+ this._canvasManager.getProject(),
782
+ this._canvasManager.getCanvas(),
783
+ args
784
+ )
785
+ } catch (err) {
786
+ return { success: false, error: err.message }
787
+ }
788
+ },
789
+ },
790
+
791
+ /**
792
+ * 添加引用块
793
+ */
794
+ add_poster_quote: {
795
+ description: '添加引用块组件',
796
+ inputSchema: z.object({
797
+ x: z.number().describe('X坐标'),
798
+ y: z.number().describe('Y坐标'),
799
+ width: z.number().optional().describe('宽度'),
800
+ text: z.string().describe('引用文字'),
801
+ author: z.string().optional().describe('作者'),
802
+ background: z.string().optional().describe('背景色'),
803
+ borderColor: z.string().optional().describe('左边框颜色'),
804
+ padding: z.number().optional().describe('内边距'),
805
+ radius: z.number().optional().describe('圆角半径'),
806
+ textColor: z.string().optional().describe('文字颜色'),
807
+ authorColor: z.string().optional().describe('作者颜色'),
808
+ fontSize: z.number().optional().describe('字体大小'),
809
+ }),
810
+ execute: async (args) => {
811
+ try {
812
+ if (!this._canvasManager.isCreated()) {
813
+ return { success: false, error: 'No canvas created' }
814
+ }
815
+ return createQuote(
816
+ this._canvasManager.getProject(),
817
+ this._canvasManager.getCanvas(),
818
+ args
819
+ )
820
+ } catch (err) {
821
+ return { success: false, error: err.message }
822
+ }
823
+ },
824
+ },
825
+
826
+ /**
827
+ * 添加统计卡片
828
+ */
829
+ add_poster_stat_card: {
830
+ description: '添加统计卡片组件',
831
+ inputSchema: z.object({
832
+ x: z.number().describe('X坐标'),
833
+ y: z.number().describe('Y坐标'),
834
+ width: z.number().optional().describe('宽度'),
835
+ height: z.number().optional().describe('高度'),
836
+ label: z.string().optional().describe('标签'),
837
+ value: z.string().optional().describe('数值'),
838
+ change: z.string().optional().describe('变化值'),
839
+ positive: z.boolean().optional().describe('变化是否为正'),
840
+ icon: z.string().optional().describe('图标'),
841
+ iconColor: z.string().optional().describe('图标颜色'),
842
+ background: z.string().optional().describe('背景色'),
843
+ border: z.string().optional().describe('边框颜色'),
844
+ radius: z.number().optional().describe('圆角半径'),
845
+ }),
846
+ execute: async (args) => {
847
+ try {
848
+ if (!this._canvasManager.isCreated()) {
849
+ return { success: false, error: 'No canvas created' }
850
+ }
851
+ return createStatCard(
852
+ this._canvasManager.getProject(),
853
+ this._canvasManager.getCanvas(),
854
+ args
855
+ )
856
+ } catch (err) {
857
+ return { success: false, error: err.message }
858
+ }
859
+ },
860
+ },
861
+
862
+ /**
863
+ * 添加标签云
864
+ */
865
+ add_poster_tag_cloud: {
866
+ description: '添加标签云组件',
867
+ inputSchema: z.object({
868
+ x: z.number().describe('X坐标'),
869
+ y: z.number().describe('Y坐标'),
870
+ tags: z.array(z.object({
871
+ text: z.string(),
872
+ color: z.string().optional(),
873
+ bgColor: z.string().optional(),
874
+ })).describe('标签数组'),
875
+ fontSize: z.number().optional().describe('字体大小'),
876
+ padding: z.number().optional().describe('标签内边距'),
877
+ gap: z.number().optional().describe('标签间距'),
878
+ maxWidth: z.number().optional().describe('最大宽度'),
879
+ }),
880
+ execute: async (args) => {
881
+ try {
882
+ if (!this._canvasManager.isCreated()) {
883
+ return { success: false, error: 'No canvas created' }
884
+ }
885
+ return createTagCloud(
886
+ this._canvasManager.getProject(),
887
+ this._canvasManager.getCanvas(),
888
+ args
889
+ )
890
+ } catch (err) {
891
+ return { success: false, error: err.message }
892
+ }
893
+ },
894
+ },
895
+
896
+ /**
897
+ * 添加步骤指示器
898
+ */
899
+ add_poster_stepper: {
900
+ description: '添加步骤指示器组件',
901
+ inputSchema: z.object({
902
+ x: z.number().describe('X坐标'),
903
+ y: z.number().describe('Y坐标'),
904
+ width: z.number().optional().describe('总宽度'),
905
+ steps: z.array(z.object({
906
+ title: z.string(),
907
+ description: z.string().optional(),
908
+ })).describe('步骤数组'),
909
+ currentStep: z.number().optional().describe('当前步骤'),
910
+ activeColor: z.string().optional().describe('激活颜色'),
911
+ inactiveColor: z.string().optional().describe('未激活颜色'),
912
+ completedColor: z.string().optional().describe('已完成颜色'),
913
+ circleSize: z.number().optional().describe('圆圈大小'),
914
+ }),
915
+ execute: async (args) => {
916
+ try {
917
+ if (!this._canvasManager.isCreated()) {
918
+ return { success: false, error: 'No canvas created' }
919
+ }
920
+ return createStepper(
921
+ this._canvasManager.getProject(),
922
+ this._canvasManager.getCanvas(),
923
+ args
924
+ )
925
+ } catch (err) {
926
+ return { success: false, error: err.message }
927
+ }
928
+ },
929
+ },
930
+
931
+ /**
932
+ * 添加时间线
933
+ */
934
+ add_poster_timeline: {
935
+ description: '添加时间线组件',
936
+ inputSchema: z.object({
937
+ x: z.number().describe('X坐标'),
938
+ y: z.number().describe('Y坐标'),
939
+ width: z.number().optional().describe('总宽度'),
940
+ items: z.array(z.object({
941
+ date: z.string().optional(),
942
+ title: z.string(),
943
+ description: z.string().optional(),
944
+ active: z.boolean().optional(),
945
+ })).describe('时间线项目数组'),
946
+ lineColor: z.string().optional().describe('线条颜色'),
947
+ dotColor: z.string().optional().describe('点颜色'),
948
+ dotSize: z.number().optional().describe('点大小'),
949
+ gap: z.number().optional().describe('项目间距'),
950
+ }),
951
+ execute: async (args) => {
952
+ try {
953
+ if (!this._canvasManager.isCreated()) {
954
+ return { success: false, error: 'No canvas created' }
955
+ }
956
+ return createTimeline(
957
+ this._canvasManager.getProject(),
958
+ this._canvasManager.getCanvas(),
959
+ args
960
+ )
961
+ } catch (err) {
962
+ return { success: false, error: err.message }
963
+ }
964
+ },
965
+ },
966
+
967
+ /**
968
+ * 添加列表项
969
+ */
970
+ add_poster_list_item: {
971
+ description: '添加列表项组件',
972
+ inputSchema: z.object({
973
+ x: z.number().describe('X坐标'),
974
+ y: z.number().describe('Y坐标'),
975
+ width: z.number().optional().describe('宽度'),
976
+ icon: z.string().optional().describe('图标'),
977
+ title: z.string().optional().describe('标题'),
978
+ description: z.string().optional().describe('描述'),
979
+ badge: z.string().optional().describe('徽章文字'),
980
+ badgeColor: z.string().optional().describe('徽章颜色'),
981
+ iconColor: z.string().optional().describe('图标颜色'),
982
+ background: z.string().optional().describe('背景色'),
983
+ borderColor: z.string().optional().describe('边框颜色'),
984
+ height: z.number().optional().describe('高度'),
985
+ radius: z.number().optional().describe('圆角半径'),
986
+ }),
987
+ execute: async (args) => {
988
+ try {
989
+ if (!this._canvasManager.isCreated()) {
990
+ return { success: false, error: 'No canvas created' }
991
+ }
992
+ return createListItem(
993
+ this._canvasManager.getProject(),
994
+ this._canvasManager.getCanvas(),
995
+ args
996
+ )
997
+ } catch (err) {
998
+ return { success: false, error: err.message }
999
+ }
1000
+ },
1001
+ },
1002
+
1003
+ /**
1004
+ * 添加通知提示
1005
+ */
1006
+ add_poster_notification: {
1007
+ description: '添加通知提示组件',
1008
+ inputSchema: z.object({
1009
+ x: z.number().describe('X坐标'),
1010
+ y: z.number().describe('Y坐标'),
1011
+ width: z.number().optional().describe('宽度'),
1012
+ type: z.enum(['success', 'warning', 'error', 'info']).optional().describe('类型'),
1013
+ title: z.string().optional().describe('标题'),
1014
+ message: z.string().optional().describe('消息内容'),
1015
+ showIcon: z.boolean().optional().describe('是否显示图标'),
1016
+ radius: z.number().optional().describe('圆角半径'),
1017
+ }),
1018
+ execute: async (args) => {
1019
+ try {
1020
+ if (!this._canvasManager.isCreated()) {
1021
+ return { success: false, error: 'No canvas created' }
1022
+ }
1023
+ return createNotification(
1024
+ this._canvasManager.getProject(),
1025
+ this._canvasManager.getCanvas(),
1026
+ args
1027
+ )
1028
+ } catch (err) {
1029
+ return { success: false, error: err.message }
1030
+ }
1031
+ },
1032
+ },
1033
+
1034
+ /**
1035
+ * 添加图片框组件
1036
+ */
1037
+ add_poster_image_frame: {
1038
+ description: '添加带装饰边框的图片框组件',
1039
+ inputSchema: z.object({
1040
+ src: z.string().describe('图片路径或URL'),
1041
+ x: z.number().describe('X坐标'),
1042
+ y: z.number().describe('Y坐标'),
1043
+ width: z.number().describe('图片宽度'),
1044
+ height: z.number().describe('图片高度'),
1045
+ borderColor: z.string().optional().describe('边框颜色'),
1046
+ borderWidth: z.number().optional().describe('边框宽度'),
1047
+ outerColor: z.string().optional().describe('外边框颜色'),
1048
+ outerWidth: z.number().optional().describe('外边框宽度'),
1049
+ shadowBlur: z.number().optional().describe('阴影模糊'),
1050
+ shadowOffsetX: z.number().optional().describe('阴影X偏移'),
1051
+ shadowOffsetY: z.number().optional().describe('阴影Y偏移'),
1052
+ shadowColor: z.string().optional().describe('阴影颜色'),
1053
+ radius: z.number().optional().describe('圆角半径'),
1054
+ overlayColor: z.string().optional().describe('叠加颜色'),
1055
+ overlayOpacity: z.number().optional().describe('叠加透明度'),
1056
+ fit: z.enum(['cover', 'contain', 'fill']).optional().describe('图片填充方式'),
1057
+ }),
1058
+ execute: async (args) => {
1059
+ try {
1060
+ if (!this._canvasManager.isCreated()) {
1061
+ return { success: false, error: 'No canvas created' }
1062
+ }
1063
+ return createImageFrame(
1064
+ this._canvasManager.getProject(),
1065
+ this._canvasManager.getCanvas(),
1066
+ args
1067
+ )
1068
+ } catch (err) {
1069
+ return { success: false, error: err.message }
1070
+ }
1071
+ },
1072
+ },
1073
+
1074
+ /**
1075
+ * 添加分栏布局组件
1076
+ */
1077
+ add_poster_columns: {
1078
+ description: '添加分栏布局组件(左右分栏、三栏等)',
1079
+ inputSchema: z.object({
1080
+ x: z.number().describe('起始X坐标'),
1081
+ y: z.number().describe('起始Y坐标'),
1082
+ width: z.number().describe('总宽度'),
1083
+ height: z.number().describe('总高度'),
1084
+ columns: z.number().optional().describe('列数,默认2'),
1085
+ gap: z.number().optional().describe('列间距,默认20'),
1086
+ background: z.string().optional().describe('背景色'),
1087
+ borderColor: z.string().optional().describe('边框颜色'),
1088
+ borderWidth: z.number().optional().describe('边框宽度'),
1089
+ radius: z.number().optional().describe('圆角半径'),
1090
+ direction: z.enum(['horizontal', 'vertical']).optional().describe('排列方向'),
1091
+ align: z.enum(['top', 'center', 'bottom']).optional().describe('垂直对齐'),
1092
+ }),
1093
+ execute: async (args) => {
1094
+ try {
1095
+ if (!this._canvasManager.isCreated()) {
1096
+ return { success: false, error: 'No canvas created' }
1097
+ }
1098
+ return createColumns(
1099
+ this._canvasManager.getProject(),
1100
+ this._canvasManager.getCanvas(),
1101
+ args
1102
+ )
1103
+ } catch (err) {
1104
+ return { success: false, error: err.message }
1105
+ }
1106
+ },
1107
+ },
1108
+
1109
+ /**
1110
+ * 添加网格布局组件
1111
+ */
1112
+ add_poster_grid: {
1113
+ description: '添加网格布局组件(任意行列)',
1114
+ inputSchema: z.object({
1115
+ x: z.number().describe('起始X坐标'),
1116
+ y: z.number().describe('起始Y坐标'),
1117
+ width: z.number().describe('总宽度'),
1118
+ height: z.number().describe('总高度'),
1119
+ columns: z.number().optional().describe('列数,默认3'),
1120
+ rows: z.number().optional().describe('行数,默认2'),
1121
+ gapX: z.number().optional().describe('水平间距,默认20'),
1122
+ gapY: z.number().optional().describe('垂直间距,默认20'),
1123
+ background: z.string().optional().describe('背景色'),
1124
+ borderColor: z.string().optional().describe('边框颜色'),
1125
+ borderWidth: z.number().optional().describe('边框宽度'),
1126
+ radius: z.number().optional().describe('圆角半径'),
1127
+ direction: z.enum(['row', 'column']).optional().describe('排列方向'),
1128
+ }),
1129
+ execute: async (args) => {
1130
+ try {
1131
+ if (!this._canvasManager.isCreated()) {
1132
+ return { success: false, error: 'No canvas created' }
1133
+ }
1134
+ return createGrid(
1135
+ this._canvasManager.getProject(),
1136
+ this._canvasManager.getCanvas(),
1137
+ args
1138
+ )
1139
+ } catch (err) {
1140
+ return { success: false, error: err.message }
1141
+ }
1142
+ },
1143
+ },
1144
+
1145
+ /**
1146
+ * 添加星形组件
1147
+ */
1148
+ add_poster_star: {
1149
+ description: '添加星形/多角形装饰',
1150
+ inputSchema: z.object({
1151
+ cx: z.number().describe('中心X坐标'),
1152
+ cy: z.number().describe('中心Y坐标'),
1153
+ points: z.number().optional().describe('星形点数,默认5'),
1154
+ innerRadius: z.number().optional().describe('内半径'),
1155
+ outerRadius: z.number().describe('外半径'),
1156
+ fill: z.string().optional().describe('填充颜色'),
1157
+ stroke: z.string().optional().describe('边框颜色'),
1158
+ strokeWidth: z.number().optional().describe('边框宽度'),
1159
+ opacity: z.number().optional().describe('透明度 0-1'),
1160
+ rotation: z.number().optional().describe('旋转角度'),
1161
+ }),
1162
+ execute: async (args) => {
1163
+ try {
1164
+ if (!this._canvasManager.isCreated()) {
1165
+ return { success: false, error: 'No canvas created' }
1166
+ }
1167
+ const project = this._canvasManager.getProject()
1168
+ const result = createStar(project, this._canvasManager.getCanvas(), args)
1169
+ // 强制将所有子元素添加到活动层
1170
+ if (result && result.elements && project) {
1171
+ // 收集所有新创建的 item
1172
+ const allItems = project.getItems({})
1173
+ const existingIds = new Set(allItems.map(i => i.id))
1174
+
1175
+ // 从项目的所有层中获取新添加的 item
1176
+ project.layers.forEach(layer => {
1177
+ layer.children.forEach(item => {
1178
+ if (item.id && !existingIds.has(item.id) || item.parent === layer) {
1179
+ if (item.parent !== project.activeLayer) {
1180
+ project.activeLayer.addChild(item)
1181
+ }
1182
+ }
1183
+ })
1184
+ })
1185
+ }
1186
+ return result
1187
+ } catch (err) {
1188
+ return { success: false, error: err.message }
1189
+ }
1190
+ },
1191
+ },
1192
+
1193
+ /**
1194
+ * 添加箭头组件
1195
+ */
1196
+ add_poster_arrow: {
1197
+ description: '添加箭头指示',
1198
+ inputSchema: z.object({
1199
+ x1: z.number().describe('起点X'),
1200
+ y1: z.number().describe('起点Y'),
1201
+ x2: z.number().describe('终点X'),
1202
+ y2: z.number().describe('终点Y'),
1203
+ color: z.string().optional().describe('箭头颜色'),
1204
+ strokeWidth: z.number().optional().describe('线宽'),
1205
+ headSize: z.number().optional().describe('箭头头部大小'),
1206
+ style: z.enum(['solid', 'dashed']).optional().describe('样式'),
1207
+ direction: z.enum(['end', 'start', 'both']).optional().describe('箭头方向'),
1208
+ }),
1209
+ execute: async (args) => {
1210
+ try {
1211
+ if (!this._canvasManager.isCreated()) {
1212
+ return { success: false, error: 'No canvas created' }
1213
+ }
1214
+ const result = createArrow(
1215
+ this._canvasManager.getProject(),
1216
+ this._canvasManager.getCanvas(),
1217
+ args
1218
+ )
1219
+ if (result && result.elements && this._canvasManager.getProject()) {
1220
+ const project = this._canvasManager.getProject()
1221
+ result.elements.forEach(el => {
1222
+ if (el.id) {
1223
+ const item = project.getItem({ id: el.id })
1224
+ if (item) project.activeLayer.addChild(item)
1225
+ }
1226
+ })
1227
+ }
1228
+ return result
1229
+ } catch (err) {
1230
+ return { success: false, error: err.message }
1231
+ }
1232
+ },
1233
+ },
1234
+
1235
+ /**
1236
+ * 添加环形进度条
1237
+ */
1238
+ add_poster_progress_circle: {
1239
+ description: '添加环形进度条组件',
1240
+ inputSchema: z.object({
1241
+ cx: z.number().describe('圆心X坐标'),
1242
+ cy: z.number().describe('圆心Y坐标'),
1243
+ radius: z.number().describe('圆环半径'),
1244
+ value: z.number().describe('进度值 0-100'),
1245
+ strokeWidth: z.number().optional().describe('环宽度'),
1246
+ trackColor: z.string().optional().describe('轨道颜色'),
1247
+ fillColor: z.string().optional().describe('进度颜色'),
1248
+ backgroundColor: z.string().optional().describe('背景填充色'),
1249
+ showLabel: z.boolean().optional().describe('是否显示百分比标签'),
1250
+ labelColor: z.string().optional().describe('标签颜色'),
1251
+ }),
1252
+ execute: async (args) => {
1253
+ try {
1254
+ if (!this._canvasManager.isCreated()) {
1255
+ return { success: false, error: 'No canvas created' }
1256
+ }
1257
+ const result = createProgressCircle(
1258
+ this._canvasManager.getProject(),
1259
+ this._canvasManager.getCanvas(),
1260
+ args
1261
+ )
1262
+ if (result && result.elements && this._canvasManager.getProject()) {
1263
+ const project = this._canvasManager.getProject()
1264
+ result.elements.forEach(el => {
1265
+ if (el.id) {
1266
+ const item = project.getItem({ id: el.id })
1267
+ if (item) project.activeLayer.addChild(item)
1268
+ }
1269
+ })
1270
+ }
1271
+ return result
1272
+ } catch (err) {
1273
+ return { success: false, error: err.message }
1274
+ }
1275
+ },
1276
+ },
1277
+
1278
+ /**
1279
+ * 添加 Chip 标签
1280
+ */
1281
+ add_poster_chip: {
1282
+ description: '添加小型信息标签组件',
1283
+ inputSchema: z.object({
1284
+ x: z.number().describe('X坐标(居中)'),
1285
+ y: z.number().describe('Y坐标'),
1286
+ text: z.string().describe('标签文字'),
1287
+ background: z.string().optional().describe('背景色'),
1288
+ color: z.string().optional().describe('文字颜色'),
1289
+ borderColor: z.string().optional().describe('边框颜色'),
1290
+ fontSize: z.number().optional().describe('字体大小'),
1291
+ padding: z.number().optional().describe('内边距'),
1292
+ radius: z.number().optional().describe('圆角'),
1293
+ icon: z.string().optional().describe('前置图标 emoji'),
1294
+ }),
1295
+ execute: async (args) => {
1296
+ try {
1297
+ if (!this._canvasManager.isCreated()) {
1298
+ return { success: false, error: 'No canvas created' }
1299
+ }
1300
+ const result = createChip(
1301
+ this._canvasManager.getProject(),
1302
+ this._canvasManager.getCanvas(),
1303
+ args
1304
+ )
1305
+ if (result && result.elements && this._canvasManager.getProject()) {
1306
+ const project = this._canvasManager.getProject()
1307
+ result.elements.forEach(el => {
1308
+ if (el.id) {
1309
+ const item = project.getItem({ id: el.id })
1310
+ if (item) project.activeLayer.addChild(item)
1311
+ }
1312
+ })
1313
+ }
1314
+ return result
1315
+ } catch (err) {
1316
+ return { success: false, error: err.message }
1317
+ }
1318
+ },
1319
+ },
1320
+
1321
+ /**
1322
+ * 添加图表组件
1323
+ */
1324
+ add_poster_chart: {
1325
+ description: '添加图表组件(柱状图/饼图)',
1326
+ inputSchema: z.object({
1327
+ type: z.enum(['bar', 'pie']).describe('图表类型'),
1328
+ x: z.number().describe('X坐标'),
1329
+ y: z.number().describe('Y坐标'),
1330
+ width: z.number().describe('宽度'),
1331
+ height: z.number().describe('高度'),
1332
+ data: z.array(z.object({
1333
+ label: z.string().describe('标签'),
1334
+ value: z.number().describe('数值'),
1335
+ color: z.string().optional().describe('颜色'),
1336
+ })).describe('数据'),
1337
+ barColor: z.string().optional().describe('默认柱状颜色'),
1338
+ showLabels: z.boolean().optional().describe('显示标签'),
1339
+ showValues: z.boolean().optional().describe('显示数值'),
1340
+ }),
1341
+ execute: async (args) => {
1342
+ try {
1343
+ if (!this._canvasManager.isCreated()) {
1344
+ return { success: false, error: 'No canvas created' }
1345
+ }
1346
+ const result = createChart(
1347
+ this._canvasManager.getProject(),
1348
+ this._canvasManager.getCanvas(),
1349
+ args
1350
+ )
1351
+ if (result && result.elements && this._canvasManager.getProject()) {
1352
+ const project = this._canvasManager.getProject()
1353
+ result.elements.forEach(el => {
1354
+ if (el.id) {
1355
+ const item = project.getItem({ id: el.id })
1356
+ if (item) project.activeLayer.addChild(item)
1357
+ }
1358
+ })
1359
+ }
1360
+ return result
1361
+ } catch (err) {
1362
+ return { success: false, error: err.message }
1363
+ }
1364
+ },
1365
+ },
1366
+
1367
+ /**
1368
+ * 添加水印
1369
+ */
1370
+ add_poster_watermark: {
1371
+ description: '添加水印文字',
1372
+ inputSchema: z.object({
1373
+ text: z.string().describe('水印文字'),
1374
+ cx: z.number().describe('中心X坐标'),
1375
+ cy: z.number().describe('中心Y坐标'),
1376
+ color: z.string().optional().describe('水印颜色'),
1377
+ fontSize: z.number().optional().describe('字体大小'),
1378
+ fontFamily: z.string().optional().describe('字体'),
1379
+ opacity: z.number().optional().describe('透明度'),
1380
+ rotation: z.number().optional().describe('旋转角度'),
1381
+ align: z.enum(['left', 'center', 'right']).optional().describe('对齐方式'),
1382
+ }),
1383
+ execute: async (args) => {
1384
+ try {
1385
+ if (!this._canvasManager.isCreated()) {
1386
+ return { success: false, error: 'No canvas created' }
1387
+ }
1388
+ const result = createWatermark(
1389
+ this._canvasManager.getProject(),
1390
+ this._canvasManager.getCanvas(),
1391
+ args
1392
+ )
1393
+ if (result && result.elements && this._canvasManager.getProject()) {
1394
+ const project = this._canvasManager.getProject()
1395
+ result.elements.forEach(el => {
1396
+ if (el.id) {
1397
+ const item = project.getItem({ id: el.id })
1398
+ if (item) project.activeLayer.addChild(item)
1399
+ }
1400
+ })
1401
+ }
1402
+ return result
1403
+ } catch (err) {
1404
+ return { success: false, error: err.message }
1405
+ }
1406
+ },
1407
+ },
1408
+
1409
+ /**
1410
+ * 添加表格组件
1411
+ */
1412
+ add_poster_table: {
1413
+ description: '添加表格组件',
1414
+ inputSchema: z.object({
1415
+ x: z.number().describe('X坐标'),
1416
+ y: z.number().describe('Y坐标'),
1417
+ width: z.number().describe('表格宽度'),
1418
+ columns: z.array(z.object({
1419
+ title: z.string().describe('列标题'),
1420
+ width: z.number().optional().describe('列宽'),
1421
+ align: z.enum(['left', 'center', 'right']).optional().describe('对齐'),
1422
+ })).describe('列配置'),
1423
+ rows: z.array(z.array(z.string())).describe('行数据'),
1424
+ rowHeight: z.number().optional().describe('行高'),
1425
+ headerBg: z.string().optional().describe('表头背景色'),
1426
+ headerColor: z.string().optional().describe('表头文字色'),
1427
+ borderColor: z.string().optional().describe('边框颜色'),
1428
+ fontSize: z.number().optional().describe('字体大小'),
1429
+ striped: z.boolean().optional().describe('斑马纹'),
1430
+ }),
1431
+ execute: async (args) => {
1432
+ try {
1433
+ if (!this._canvasManager.isCreated()) {
1434
+ return { success: false, error: 'No canvas created' }
1435
+ }
1436
+ const result = createTable(
1437
+ this._canvasManager.getProject(),
1438
+ this._canvasManager.getCanvas(),
1439
+ args
1440
+ )
1441
+ if (result && result.elements && this._canvasManager.getProject()) {
1442
+ const project = this._canvasManager.getProject()
1443
+ result.elements.forEach(el => {
1444
+ if (el.id) {
1445
+ const item = project.getItem({ id: el.id })
1446
+ if (item) project.activeLayer.addChild(item)
1447
+ }
1448
+ })
1449
+ }
1450
+ return result
1451
+ } catch (err) {
1452
+ return { success: false, error: err.message }
1453
+ }
1454
+ },
1455
+ },
1456
+
1457
+ // ==================== 组件化海报生成 ====================
1458
+
1459
+ /**
1460
+ * 组件化生成海报
1461
+ */
1462
+ compose_poster: {
1463
+ description: '使用组件配置一次性生成海报',
1464
+ inputSchema: z.object({
1465
+ components: z.array(z.object({
1466
+ type: z.enum([
1467
+ 'background', 'rectangle', 'circle', 'line', 'polygon',
1468
+ 'text', 'artText', 'image', 'svg', 'imageFrame',
1469
+ 'columns', 'grid', 'star', 'arrow', 'progressCircle', 'chip', 'chart', 'watermark', 'table',
1470
+ 'card', 'badge', 'cta', 'feature', 'featureGrid', 'divider',
1471
+ 'avatar', 'progress', 'rating', 'quote', 'statCard',
1472
+ 'tagCloud', 'stepper', 'timeline', 'listItem', 'notification',
1473
+ ]).describe('组件类型'),
1474
+ })).describe('组件配置数组'),
1475
+ }),
1476
+ execute: async (args) => {
1477
+ try {
1478
+ if (!this._canvasManager.isCreated()) {
1479
+ return { success: false, error: 'No canvas created' }
1480
+ }
1481
+ return createFromConfig(
1482
+ this._canvasManager.getProject(),
1483
+ this._canvasManager.getCanvas(),
1484
+ args
1485
+ )
1486
+ } catch (err) {
1487
+ return { success: false, error: err.message }
1488
+ }
1489
+ },
1490
+ },
1491
+
1492
+ /**
1493
+ * 获取可用组件类型
1494
+ */
1495
+ list_poster_components: {
1496
+ description: '列出所有可用的组件类型',
1497
+ inputSchema: z.object({}),
1498
+ execute: async () => ({
1499
+ success: true,
1500
+ components: Object.keys(COMPONENT_TYPES),
1501
+ }),
1502
+ },
1503
+
1504
+ // ==================== 模板 ====================
1505
+
1506
+ /**
1507
+ * 一键生成海报
1508
+ */
1509
+ generate_poster: {
1510
+ description: '使用预设模板一键生成海报',
1511
+ inputSchema: z.object({
1512
+ template: z.enum(['modern', 'business', 'social', 'simple', 'tech', 'gradient']).describe('模板类型'),
1513
+ title: z.string().describe('主标题'),
1514
+ subtitle: z.string().optional().describe('副标题'),
1515
+ background: z.string().optional().describe('背景色'),
1516
+ accentColor: z.string().optional().describe('强调色'),
1517
+ output: z.string().describe('输出文件名'),
1518
+ outputDir: z.string().optional().describe('输出目录'),
1519
+ }),
1520
+ execute: async (args) => {
1521
+ try {
1522
+ if (!this._canvasManager.isCreated()) {
1523
+ return { success: false, error: 'No canvas created' }
1524
+ }
1525
+
1526
+ // 应用模板
1527
+ applyTemplate(
1528
+ this._canvasManager.getProject(),
1529
+ this._canvasManager.getCanvas(),
1530
+ args.template,
1531
+ args
1532
+ )
1533
+
1534
+ // 导出
1535
+ const format = 'png'
1536
+ const outputDir = args.outputDir || '.'
1537
+ const filename = `${args.output}.${format}`
1538
+ await fs.promises.mkdir(outputDir, { recursive: true })
1539
+ const filepath = path.join(outputDir, filename)
1540
+ const buffer = this._canvasManager.toBuffer(format)
1541
+ await fs.promises.writeFile(filepath, buffer)
1542
+
1543
+ return {
1544
+ success: true,
1545
+ filepath,
1546
+ template: args.template,
1547
+ size: buffer.length,
1548
+ }
1549
+ } catch (err) {
1550
+ return { success: false, error: err.message }
1551
+ }
1552
+ },
1553
+ },
1554
+
1555
+ /**
1556
+ * 列出可用模板
1557
+ */
1558
+ list_poster_templates: {
1559
+ description: '列出所有可用的海报模板',
1560
+ inputSchema: z.object({}),
1561
+ execute: async () => ({
1562
+ success: true,
1563
+ templates: getAvailableTemplates(),
1564
+ }),
1565
+ },
1566
+
1567
+ // ==================== 导出 ====================
1568
+
1569
+ /**
1570
+ * 导出为文件
1571
+ */
1572
+ export_poster_canvas: {
1573
+ description: '导出画布为图片文件',
1574
+ inputSchema: z.object({
1575
+ filename: z.string().describe('文件名(不含扩展名)'),
1576
+ format: z.enum(['png', 'jpg']).optional().describe('格式,默认png'),
1577
+ quality: z.number().optional().describe('JPEG质量'),
1578
+ outputDir: z.string().optional().describe('输出目录'),
1579
+ }),
1580
+ execute: async (args) => {
1581
+ try {
1582
+ if (!this._canvasManager.isCreated()) {
1583
+ return { success: false, error: 'No canvas created' }
1584
+ }
1585
+
1586
+ const format = args.format || 'png'
1587
+ const outputDir = args.outputDir || '.'
1588
+ const filename = `${args.filename}.${format}`
1589
+ await fs.promises.mkdir(outputDir, { recursive: true })
1590
+ const filepath = path.join(outputDir, filename)
1591
+ const buffer = this._canvasManager.toBuffer(format, args.quality)
1592
+ await fs.promises.writeFile(filepath, buffer)
1593
+
1594
+ return {
1595
+ success: true,
1596
+ filepath,
1597
+ filename,
1598
+ format,
1599
+ size: buffer.length,
1600
+ }
1601
+ } catch (err) {
1602
+ return { success: false, error: err.message }
1603
+ }
1604
+ },
1605
+ },
1606
+
1607
+ /**
1608
+ * 导出为 Base64
1609
+ */
1610
+ export_poster_base64: {
1611
+ description: '导出画布为 Base64 编码',
1612
+ inputSchema: z.object({
1613
+ format: z.enum(['png', 'jpg']).optional().describe('格式'),
1614
+ quality: z.number().optional().describe('JPEG质量'),
1615
+ }),
1616
+ execute: async (args) => {
1617
+ try {
1618
+ if (!this._canvasManager.isCreated()) {
1619
+ return { success: false, error: 'No canvas created' }
1620
+ }
1621
+
1622
+ const format = args.format || 'png'
1623
+ const base64 = this._canvasManager.toBase64(format, args.quality)
1624
+ const mimeType = format === 'jpg' ? 'image/jpeg' : 'image/png'
1625
+
1626
+ return {
1627
+ success: true,
1628
+ base64,
1629
+ format,
1630
+ mimeType,
1631
+ }
1632
+ } catch (err) {
1633
+ return { success: false, error: err.message }
1634
+ }
1635
+ },
1636
+ },
1637
+ }
1638
+
1639
+ install(framework){
1640
+ this._framework=framework
1641
+ Object.keys(this.all_tools).map(key=>{
1642
+ this._framework.registerTool({...this.all_tools[key],name:key})
1643
+ })
1644
+ }
1645
+
1646
+
1647
+
1648
+ reload(framework) {
1649
+ console.log('[poster] Reloading poster plugin')
1650
+ this._framework = framework
1651
+ }
1652
+
1653
+ uninstall(framework) {
1654
+ this._canvasManager.reset()
1655
+ this._framework = null
1656
+ console.log('[poster] Poster plugin uninstalled')
1657
+ }
1658
+ }
1659
+ }