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