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.
- package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
- package/.agent/ARCHITECTURE.md +288 -0
- package/.agent/agents/ambient-agent.md +57 -0
- package/.agent/agents/debugger.md +55 -0
- package/.agent/agents/email-assistant.md +49 -0
- package/.agent/agents/file-manager.md +42 -0
- package/.agent/agents/python-developer.md +60 -0
- package/.agent/agents/scheduler.md +59 -0
- package/.agent/agents/web-developer.md +45 -0
- package/.agent/data/default.json +325 -21
- package/.agent/data/plugins-state.json +194 -162
- package/.agent/data/puppeteer-sessions/undefined.json +6 -0
- package/.agent/mcp_config.json +0 -1
- package/.agent/mcp_config_updated.json +12 -0
- package/.agent/plugins/poster-plugin/README.md +304 -0
- package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
- package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
- package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
- 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
- package/.agent/plugins/poster-plugin/index.js +13 -0
- package/.agent/plugins/poster-plugin/package.json +28 -0
- package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
- package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
- package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
- package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
- package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
- package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
- package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
- package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
- package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
- package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
- package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
- package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
- package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
- package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
- package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
- package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
- package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
- package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
- package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
- package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
- package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
- package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
- package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
- package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
- package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
- package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
- package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
- package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
- package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
- package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
- package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
- package/.agent/plugins/poster-plugin/src/elements/polygon.js +63 -0
- package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
- package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
- package/.agent/plugins/poster-plugin/src/elements/text.js +107 -0
- package/.agent/plugins/poster-plugin/src/fonts.js +233 -0
- package/.agent/plugins/poster-plugin/src/index.js +1658 -0
- package/.agent/plugins/poster-plugin/src/presets.js +36 -0
- package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
- package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
- package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
- package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
- package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
- package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
- package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
- package/.agent/plugins/{temp-repo/puppeteer-plugin → puppeteer-plugin}/index.js +1 -1
- package/.agent/plugins.json +5 -11
- package/.agent/rules/GEMINI.md +273 -0
- package/.agent/rules/allow-rule.md +77 -0
- package/.agent/rules/log-rule.md +83 -0
- package/.agent/rules/security-rule.md +93 -0
- package/.agent/scripts/auto_preview.py +148 -0
- package/.agent/scripts/checklist.py +217 -0
- package/.agent/scripts/session_manager.py +120 -0
- package/.agent/scripts/verify_all.py +327 -0
- package/.agent/sessions/cli_default.json +419 -0
- package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +2195 -0
- package/.agent/skills/api-patterns/SKILL.md +81 -0
- package/.agent/skills/api-patterns/api-style.md +42 -0
- package/.agent/skills/api-patterns/auth.md +24 -0
- package/.agent/skills/api-patterns/documentation.md +26 -0
- package/.agent/skills/api-patterns/graphql.md +41 -0
- package/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/.agent/skills/api-patterns/response.md +37 -0
- package/.agent/skills/api-patterns/rest.md +40 -0
- package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/.agent/skills/api-patterns/security-testing.md +122 -0
- package/.agent/skills/api-patterns/trpc.md +41 -0
- package/.agent/skills/api-patterns/versioning.md +22 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +40 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
- package/.agent/skills/architecture/SKILL.md +55 -0
- package/.agent/skills/architecture/context-discovery.md +43 -0
- package/.agent/skills/architecture/examples.md +94 -0
- package/.agent/skills/architecture/pattern-selection.md +68 -0
- package/.agent/skills/architecture/patterns-reference.md +50 -0
- package/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/.agent/skills/clean-code/SKILL.md +201 -0
- package/.agent/skills/doc.md +177 -0
- package/.agent/skills/frontend-design/SKILL.md +418 -0
- package/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/.agent/skills/frontend-design/color-system.md +311 -0
- package/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/.agent/skills/frontend-design/typography-system.md +345 -0
- package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
- package/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/.agent/skills/mcp-builder/SKILL.md +176 -0
- package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
- package/.agent/workflows/brainstorm.md +113 -0
- package/.agent/workflows/create.md +59 -0
- package/.agent/workflows/debug.md +103 -0
- package/.agent/workflows/deploy.md +176 -0
- package/.agent/workflows/enhance.md +63 -0
- package/.agent/workflows/orchestrate.md +237 -0
- package/.agent/workflows/plan.md +89 -0
- package/.agent/workflows/preview.md +81 -0
- package/.agent/workflows/simple-test.md +42 -0
- package/.agent/workflows/status.md +86 -0
- package/.agent/workflows/structured-orchestrate.md +180 -0
- package/.agent/workflows/test.md +144 -0
- package/.agent/workflows/ui-ux-pro-max.md +296 -0
- package/.claude/settings.local.json +20 -8
- package/.env.example +56 -56
- package/CLAUDE.md +144 -108
- package/README.md +441 -441
- package/calc_tokens_weixin.js +81 -0
- package/cli/src/commands/chat.js +2 -1
- package/docs/CONTEXT_DESIGN.md +1596 -0
- package/examples/test-concurrent-chat.js +60 -60
- package/foliko-creative-3.png +0 -0
- package/foliko-creative-4.png +0 -0
- package/foliko-creative-5.png +0 -0
- package/package.json +2 -2
- package/plugins/default-plugins.js +2 -1
- package/plugins/extension-executor-plugin.js +91 -2
- package/plugins/file-system-plugin.js +2 -2
- package/plugins/memory-plugin.js +984 -0
- package/plugins/session-plugin.js +57 -1
- package/plugins/weixin-plugin.js +33 -23
- package/skills/find-skills/AGENTS.md +162 -162
- package/skills/find-skills/SKILL.md +133 -133
- package/skills/poster-guide/SKILL.md +1059 -0
- package/skills/python-plugin-dev/SKILL.md +238 -238
- package/skills/skill-guide/SKILL.md +130 -108
- package/src/capabilities/skill-manager.js +99 -0
- package/src/core/agent-chat.js +620 -141
- package/src/core/agent-context.js +188 -0
- package/src/core/agent.js +6 -2
- package/src/core/context-manager.js +283 -0
- package/src/core/framework.js +264 -3
- package/src/core/plugin-manager.js +79 -2
- package/src/core/request-context.js +98 -0
- package/src/core/session-context.js +341 -0
- package/src/core/session-storage.js +274 -0
- package/src/executors/mcp-executor.js +2 -2
- package/src/utils/index.js +239 -67
- package/src/utils/plugin-helpers.js +17 -0
- package/story-cover-book-v2.png +0 -0
- package/story-cover-japanese-1.png +0 -0
- package/story-cover-japanese-2.png +0 -0
- package/story-cover-japanese-3.png +0 -0
- package/story-cover-moran.png +0 -0
- package/undefined.png +0 -0
- package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
- package/.agent/agents/code-assistant.json +0 -14
- package/.agent/agents/email-assistant.json +0 -14
- package/.agent/agents/file-assistant.json +0 -15
- package/.agent/agents/system-assistant.json +0 -15
- package/.agent/agents/web-assistant.json +0 -12
- package/.agent/data/ambient/goals.json +0 -50
- package/.agent/data/ambient/memories.json +0 -7
- package/.agent/data/scheduler/tasks.json +0 -1
- package/.agent/package.json +0 -8
- package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
- package/.agent/plugins/daytona/README.md +0 -89
- package/.agent/plugins/daytona/index.js +0 -377
- package/.agent/plugins/daytona/package.json +0 -12
- package/.agent/plugins/marknative/README.md +0 -134
- package/.agent/plugins/marknative/index.js +0 -228
- package/.agent/plugins/marknative/package.json +0 -12
- package/.agent/plugins/marknative/update-readme.js +0 -134
- package/.agent/plugins/system-info/index.js +0 -387
- package/.agent/plugins/system-info/package.json +0 -4
- package/.agent/plugins/system-info/test.js +0 -40
- package/.agent/plugins/temp-repo/LICENSE +0 -201
- package/.agent/plugins/test_plugin.py +0 -304
- package/.agent/python-scripts/test_sample.py +0 -24
- package/.agent/skills/agent-browser/SKILL.md +0 -311
- package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
- package/.agent/skills/sysinfo/SKILL.md +0 -38
- package/.agent/skills/sysinfo/system-info.sh +0 -130
- package/.agent/skills/workflow/SKILL.md +0 -324
- package/.agent/workflows/email-digest.json +0 -50
- package/.agent/workflows/file-backup.json +0 -21
- package/.agent/workflows/get-ip-notify.json +0 -32
- package/.agent/workflows/news-aggregator.json +0 -93
- package/.agent/workflows/news-dashboard-v2.json +0 -94
- package/.agent/workflows/notification-batch.json +0 -32
- package/examples/test-chat-debug.js +0 -102
- package/examples/test-chat-result.js +0 -76
- package/examples/test-chat-stream-diff.js +0 -63
- /package/.agent/plugins/{temp-repo/puppeteer-plugin → puppeteer-plugin}/README.md +0 -0
- /package/.agent/plugins/{temp-repo/puppeteer-plugin → puppeteer-plugin}/package.json +0 -0
package/src/utils/index.js
CHANGED
|
@@ -161,86 +161,104 @@ async function retry(fn, options = {}) {
|
|
|
161
161
|
throw lastError;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
/**
|
|
165
|
+
* 安全序列化工具结果,移除循环引用
|
|
166
|
+
* 处理 Error 对象、函数等无法 JSON 序列化的内容
|
|
167
|
+
*/
|
|
168
|
+
function sanitizeForJSON(obj) {
|
|
169
|
+
if (obj === null || obj === undefined) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
168
172
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const msg = messages[i];
|
|
172
|
-
if (msg.role === 'assistant' && msg.content) {
|
|
173
|
-
const content = Array.isArray(msg.content) ? msg.content : [msg.content];
|
|
174
|
-
for (const item of content) {
|
|
175
|
-
if (item.type === 'tool-call' && item.toolCallId) {
|
|
176
|
-
toolCallToAssistant.set(item.toolCallId, i);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
173
|
+
if (typeof obj === 'string') {
|
|
174
|
+
return obj;
|
|
180
175
|
}
|
|
181
176
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (msg.role === 'tool' && msg.toolCallId) {
|
|
185
|
-
if (toolCallToAssistant.has(msg.toolCallId)) {
|
|
186
|
-
pairedIds.add(msg.toolCallId);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
177
|
+
if (typeof obj === 'number' || typeof obj === 'boolean') {
|
|
178
|
+
return obj;
|
|
189
179
|
}
|
|
190
180
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
let shouldKeep = true;
|
|
195
|
-
let cleanedMsg = { ...msg };
|
|
181
|
+
if (obj instanceof Error) {
|
|
182
|
+
return `Error: ${obj.message}`;
|
|
183
|
+
}
|
|
196
184
|
|
|
197
|
-
|
|
198
|
-
|
|
185
|
+
if (typeof obj === 'function' || typeof obj === 'symbol') {
|
|
186
|
+
return '[Unserializable]';
|
|
187
|
+
}
|
|
199
188
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
return pairedIds.has(item.toolCallId);
|
|
204
|
-
}
|
|
205
|
-
return true; // 保留 text 类型
|
|
206
|
-
});
|
|
189
|
+
if (Array.isArray(obj)) {
|
|
190
|
+
return obj.map((item) => sanitizeForJSON(item));
|
|
191
|
+
}
|
|
207
192
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
193
|
+
if (typeof obj === 'object') {
|
|
194
|
+
// 检测并处理循环引用
|
|
195
|
+
const seen = new WeakSet();
|
|
196
|
+
const result = {};
|
|
197
|
+
|
|
198
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
199
|
+
if (value === obj) continue; // 跳过自身引用
|
|
200
|
+
if (seen.has(value)) {
|
|
201
|
+
result[key] = '[Circular]';
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (typeof value === 'object' && value !== null) {
|
|
205
|
+
seen.add(value);
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
result[key] = sanitizeForJSON(value);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
result[key] = '[Unserializable]';
|
|
213
211
|
}
|
|
214
212
|
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
216
|
+
return String(obj);
|
|
217
|
+
}
|
|
219
218
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
219
|
+
/**
|
|
220
|
+
* 清理工具结果内容,确保可安全序列化
|
|
221
|
+
*/
|
|
222
|
+
function sanitizeToolResult(result) {
|
|
223
|
+
if (result === null || result === undefined) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 如果已经是字符串,直接返回
|
|
228
|
+
if (typeof result === 'string') {
|
|
229
|
+
return result.substring(0, 50000); // 限制长度
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 如果是纯数据对象,直接序列化
|
|
233
|
+
if (typeof result === 'number' || typeof result === 'boolean') {
|
|
234
|
+
return result;
|
|
236
235
|
}
|
|
237
236
|
|
|
238
|
-
|
|
237
|
+
// 尝试安全序列化
|
|
238
|
+
try {
|
|
239
|
+
const sanitized = sanitizeForJSON(result);
|
|
240
|
+
const str = JSON.stringify(sanitized);
|
|
241
|
+
// 验证可以再次解析
|
|
242
|
+
JSON.parse(str);
|
|
243
|
+
return sanitized;
|
|
244
|
+
} catch (e) {
|
|
245
|
+
// 序列化失败,转换为字符串
|
|
246
|
+
return String(result).substring(0, 50000);
|
|
247
|
+
}
|
|
239
248
|
}
|
|
240
249
|
|
|
241
250
|
// 更激进的方法:确保所有消息都有有效的 content
|
|
242
|
-
|
|
251
|
+
// 接收 pairedIds 参数用于过滤未配对的 tool 消息
|
|
252
|
+
function validateAndFixMessages(messages, pairedIds = null) {
|
|
243
253
|
return messages.filter((msg) => {
|
|
254
|
+
// 如果提供了 pairedIds,检查 tool 消息是否配对
|
|
255
|
+
if (pairedIds && msg.role === 'tool' && msg.toolCallId) {
|
|
256
|
+
if (!pairedIds.has(msg.toolCallId)) {
|
|
257
|
+
console.log(`丢弃消息: role=tool, toolCallId=${msg.toolCallId} 未配对`);
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
244
262
|
// 检查 content 是否存在且非空
|
|
245
263
|
if (!msg.content) {
|
|
246
264
|
console.log(`丢弃消息: role=${msg.role}, 无 content`);
|
|
@@ -286,11 +304,166 @@ function validateAndFixMessages(messages) {
|
|
|
286
304
|
|
|
287
305
|
// 完整处理流程
|
|
288
306
|
function prepareMessagesForAPI(rawMessages) {
|
|
289
|
-
//
|
|
290
|
-
|
|
307
|
+
// 辅助函数:从消息中提取 toolCallId(兼容两种格式)
|
|
308
|
+
// 格式1: msg.toolCallId (旧格式)
|
|
309
|
+
// 格式2: msg.content[0].toolCallId (AI SDK CoreMessage 格式)
|
|
310
|
+
function extractToolCallId(msg) {
|
|
311
|
+
if (msg.toolCallId) return msg.toolCallId;
|
|
312
|
+
if (Array.isArray(msg.content) && msg.content.length > 0) {
|
|
313
|
+
const firstContent = msg.content[0];
|
|
314
|
+
if (firstContent && firstContent.toolCallId) return firstContent.toolCallId;
|
|
315
|
+
}
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// 1. 先配对,收集配对的 toolCallId
|
|
320
|
+
const pairedIds = new Set();
|
|
321
|
+
const toolCallToAssistant = new Map();
|
|
322
|
+
const orphanedToolResults = []; // 用于调试:记录孤立的 tool results
|
|
323
|
+
|
|
324
|
+
// 收集所有 assistant 的 tool-call
|
|
325
|
+
for (let i = 0; i < rawMessages.length; i++) {
|
|
326
|
+
const msg = rawMessages[i];
|
|
327
|
+
if (msg.role === 'assistant' && msg.content) {
|
|
328
|
+
const content = Array.isArray(msg.content) ? msg.content : [msg.content];
|
|
329
|
+
for (const item of content) {
|
|
330
|
+
if (item.type === 'tool-call' && item.toolCallId) {
|
|
331
|
+
toolCallToAssistant.set(item.toolCallId, i);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// 找出配对的 tool result(兼容两种格式)
|
|
338
|
+
for (const msg of rawMessages) {
|
|
339
|
+
if (msg.role === 'tool') {
|
|
340
|
+
const toolCallId = extractToolCallId(msg);
|
|
341
|
+
if (toolCallId && toolCallToAssistant.has(toolCallId)) {
|
|
342
|
+
pairedIds.add(toolCallId);
|
|
343
|
+
} else if (toolCallId) {
|
|
344
|
+
// 记录孤立的 tool result(调试用)
|
|
345
|
+
orphanedToolResults.push({
|
|
346
|
+
toolCallId,
|
|
347
|
+
hasAssistantMessage: toolCallToAssistant.has(toolCallId),
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// 调试:输出孤立 tool result 的信息(仅在有孤立结果时)
|
|
354
|
+
if (orphanedToolResults.length > 0 && pairedIds.size > 0) {
|
|
355
|
+
console.log(
|
|
356
|
+
`[prepareMessagesForAPI] Warning: ${orphanedToolResults.length} orphaned tool results detected:`
|
|
357
|
+
);
|
|
358
|
+
for (const orphan of orphanedToolResults) {
|
|
359
|
+
console.log(
|
|
360
|
+
` - toolCallId=${orphan.toolCallId}, hasAssistantMessage=${orphan.hasAssistantMessage}`
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
console.log(` Paired IDs: ${Array.from(pairedIds).join(', ')}`);
|
|
364
|
+
console.log(` Assistant tool-call IDs: ${Array.from(toolCallToAssistant.keys()).join(', ')}`);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// 2. 过滤并清理空消息,同时过滤未配对的 tool 消息
|
|
368
|
+
const cleaned = [];
|
|
369
|
+
for (const msg of rawMessages) {
|
|
370
|
+
let shouldKeep = true;
|
|
371
|
+
|
|
372
|
+
if (msg.role === 'assistant' && msg.content) {
|
|
373
|
+
// 如果 content 是字符串(普通文本消息),保持不变
|
|
374
|
+
if (typeof msg.content === 'string') {
|
|
375
|
+
// 字符串内容不需要处理
|
|
376
|
+
} else if (Array.isArray(msg.content)) {
|
|
377
|
+
// content 是数组(包含 tool-call 等),进行过滤和清理
|
|
378
|
+
// 过滤:保留有 tool result 的 tool-call,保留 text 类型
|
|
379
|
+
const filteredContent = msg.content.filter((item) => {
|
|
380
|
+
if (item.type === 'tool-call') {
|
|
381
|
+
// 只保留有对应 tool result 的 tool call
|
|
382
|
+
return pairedIds.has(item.toolCallId);
|
|
383
|
+
}
|
|
384
|
+
return true; // 保留 text 类型
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// 检查过滤后是否还有有效内容
|
|
388
|
+
if (filteredContent.length === 0) {
|
|
389
|
+
shouldKeep = false;
|
|
390
|
+
} else {
|
|
391
|
+
// 清理 tool-result 内容项(assistant 消息中不应该有 tool-result,但以防万一)
|
|
392
|
+
msg.content = filteredContent.map((item) => {
|
|
393
|
+
if (item && item.type === 'tool-result' && item.result !== undefined) {
|
|
394
|
+
return {
|
|
395
|
+
...item,
|
|
396
|
+
result: sanitizeToolResult(item.result),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
return item;
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (msg.role === 'tool') {
|
|
406
|
+
// 检查 tool message 是否有配对的 tool call
|
|
407
|
+
// 注意:一个 tool message 可能包含多个 tool-results,需要逐个检查
|
|
408
|
+
if (Array.isArray(msg.content)) {
|
|
409
|
+
// 过滤出有配对的 tool-results
|
|
410
|
+
const pairedResults = msg.content.filter((item) => {
|
|
411
|
+
if (item && item.type === 'tool-result' && item.toolCallId) {
|
|
412
|
+
return pairedIds.has(item.toolCallId);
|
|
413
|
+
}
|
|
414
|
+
// 保留非 tool-result 类型的内容(如 text)
|
|
415
|
+
return item && item.type !== 'tool-result';
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// 检查是否有有效的 tool-results
|
|
419
|
+
const hasPairedResults = pairedResults.some(
|
|
420
|
+
(item) =>
|
|
421
|
+
item && item.type === 'tool-result' && item.toolCallId && pairedIds.has(item.toolCallId)
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
if (!hasPairedResults) {
|
|
425
|
+
// 所有 tool-results 都是orphaned,跳过整个消息
|
|
426
|
+
console.log(
|
|
427
|
+
`[prepareMessagesForAPI] Dropping tool message: all ${msg.content.length} tool-results are orphaned`
|
|
428
|
+
);
|
|
429
|
+
shouldKeep = false;
|
|
430
|
+
} else {
|
|
431
|
+
// 保留有配对的 tool-results,清理内容
|
|
432
|
+
msg.content = pairedResults.map((item) => {
|
|
433
|
+
if (item && item.type === 'tool-result' && item.result !== undefined) {
|
|
434
|
+
return {
|
|
435
|
+
...item,
|
|
436
|
+
result: sanitizeToolResult(item.result),
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
return item;
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
// 非数组格式的 tool message(如旧格式)
|
|
444
|
+
const toolCallId = extractToolCallId(msg);
|
|
445
|
+
shouldKeep = toolCallId && pairedIds.has(toolCallId);
|
|
446
|
+
if (shouldKeep && msg.content) {
|
|
447
|
+
msg.content = sanitizeToolResult(msg.content);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
291
451
|
|
|
292
|
-
|
|
293
|
-
|
|
452
|
+
// 验证 content 有效性
|
|
453
|
+
if (shouldKeep) {
|
|
454
|
+
if (!msg.content) {
|
|
455
|
+
shouldKeep = false;
|
|
456
|
+
} else if (Array.isArray(msg.content) && msg.content.length === 0) {
|
|
457
|
+
shouldKeep = false;
|
|
458
|
+
} else if (typeof msg.content === 'string' && !msg.content.trim()) {
|
|
459
|
+
shouldKeep = false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (shouldKeep) {
|
|
464
|
+
cleaned.push(msg);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
294
467
|
|
|
295
468
|
// 3. 确保消息交替顺序正确(user/assistant/tool)
|
|
296
469
|
const finalMessages = [];
|
|
@@ -299,7 +472,6 @@ function prepareMessagesForAPI(rawMessages) {
|
|
|
299
472
|
for (const msg of cleaned) {
|
|
300
473
|
// 跳过连续的相同角色消息(除了 tool)
|
|
301
474
|
if (msg.role === lastRole && msg.role !== 'tool') {
|
|
302
|
-
// 静默跳过,不打印日志
|
|
303
475
|
continue;
|
|
304
476
|
}
|
|
305
477
|
|
|
@@ -65,10 +65,27 @@ function scanPluginNames(pluginsDir) {
|
|
|
65
65
|
return [];
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// 忽略的目录/文件(无意义或系统文件)
|
|
69
|
+
const IGNORE_PATTERNS = new Set([
|
|
70
|
+
'__pycache__',
|
|
71
|
+
'node_modules',
|
|
72
|
+
'.git',
|
|
73
|
+
'.svn',
|
|
74
|
+
'.hg',
|
|
75
|
+
'__MACOSX',
|
|
76
|
+
'.DS_Store',
|
|
77
|
+
'Thumbs.db',
|
|
78
|
+
]);
|
|
79
|
+
|
|
68
80
|
const names = new Set();
|
|
69
81
|
const entries = fs.readdirSync(pluginsDir, { withFileTypes: true });
|
|
70
82
|
|
|
71
83
|
for (const entry of entries) {
|
|
84
|
+
// 跳过忽略列表中的条目
|
|
85
|
+
if (IGNORE_PATTERNS.has(entry.name)) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
72
89
|
if (entry.isDirectory()) {
|
|
73
90
|
// 文件夹插件
|
|
74
91
|
names.add(entry.name);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/undefined.png
ADDED
|
Binary file
|