foliko 1.0.73 → 1.0.75

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 (237) 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 +29 -0
  39. package/.agent/data/plugins-state.json +255 -0
  40. package/.agent/mcp_config.json +4 -0
  41. package/.agent/mcp_config_updated.json +12 -0
  42. package/.agent/plugins.json +5 -0
  43. package/.agent/rules/GEMINI.md +273 -0
  44. package/.agent/rules/allow-rule.md +77 -0
  45. package/.agent/rules/log-rule.md +83 -0
  46. package/.agent/rules/security-rule.md +93 -0
  47. package/.agent/scripts/auto_preview.py +148 -0
  48. package/.agent/scripts/checklist.py +217 -0
  49. package/.agent/scripts/session_manager.py +120 -0
  50. package/.agent/scripts/verify_all.py +327 -0
  51. package/.agent/skills/api-patterns/SKILL.md +81 -0
  52. package/.agent/skills/api-patterns/api-style.md +42 -0
  53. package/.agent/skills/api-patterns/auth.md +24 -0
  54. package/.agent/skills/api-patterns/documentation.md +26 -0
  55. package/.agent/skills/api-patterns/graphql.md +41 -0
  56. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  57. package/.agent/skills/api-patterns/response.md +37 -0
  58. package/.agent/skills/api-patterns/rest.md +40 -0
  59. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  60. package/.agent/skills/api-patterns/security-testing.md +122 -0
  61. package/.agent/skills/api-patterns/trpc.md +41 -0
  62. package/.agent/skills/api-patterns/versioning.md +22 -0
  63. package/.agent/skills/app-builder/SKILL.md +75 -0
  64. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  65. package/.agent/skills/app-builder/feature-building.md +53 -0
  66. package/.agent/skills/app-builder/project-detection.md +34 -0
  67. package/.agent/skills/app-builder/scaffolding.md +118 -0
  68. package/.agent/skills/app-builder/tech-stack.md +40 -0
  69. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  70. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  71. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  72. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  73. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  74. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  75. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  76. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  77. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  78. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  79. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  80. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  81. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  82. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  83. package/.agent/skills/architecture/SKILL.md +55 -0
  84. package/.agent/skills/architecture/context-discovery.md +43 -0
  85. package/.agent/skills/architecture/examples.md +94 -0
  86. package/.agent/skills/architecture/pattern-selection.md +68 -0
  87. package/.agent/skills/architecture/patterns-reference.md +50 -0
  88. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  89. package/.agent/skills/clean-code/SKILL.md +201 -0
  90. package/.agent/skills/doc.md +177 -0
  91. package/.agent/skills/frontend-design/SKILL.md +418 -0
  92. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  93. package/.agent/skills/frontend-design/color-system.md +311 -0
  94. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  95. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  96. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  97. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  98. package/.agent/skills/frontend-design/typography-system.md +345 -0
  99. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  100. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  101. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  102. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  103. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  104. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  105. package/.agent/workflows/brainstorm.md +113 -0
  106. package/.agent/workflows/create.md +59 -0
  107. package/.agent/workflows/debug.md +103 -0
  108. package/.agent/workflows/deploy.md +176 -0
  109. package/.agent/workflows/enhance.md +63 -0
  110. package/.agent/workflows/orchestrate.md +237 -0
  111. package/.agent/workflows/plan.md +89 -0
  112. package/.agent/workflows/preview.md +81 -0
  113. package/.agent/workflows/simple-test.md +42 -0
  114. package/.agent/workflows/status.md +86 -0
  115. package/.agent/workflows/structured-orchestrate.md +180 -0
  116. package/.agent/workflows/test.md +144 -0
  117. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  118. package/.claude/settings.local.json +157 -149
  119. package/.editorconfig +56 -0
  120. package/.husky/pre-commit +4 -0
  121. package/.lintstagedrc +7 -0
  122. package/.prettierignore +29 -0
  123. package/.prettierrc +11 -0
  124. package/CLAUDE.md +2 -0
  125. package/README.md +64 -55
  126. package/SPEC.md +102 -61
  127. package/cli/bin/foliko.js +4 -4
  128. package/cli/src/commands/chat.js +53 -51
  129. package/cli/src/commands/list.js +40 -37
  130. package/cli/src/index.js +18 -18
  131. package/cli/src/ui/chat-ui.js +78 -76
  132. package/cli/src/utils/ansi.js +15 -15
  133. package/cli/src/utils/markdown.js +112 -116
  134. package/docker-compose.yml +1 -1
  135. package/docs/ai-sdk-optimization.md +655 -636
  136. package/docs/features.md +80 -80
  137. package/docs/quick-reference.md +49 -46
  138. package/docs/user-manual.md +411 -380
  139. package/examples/ambient-example.js +95 -97
  140. package/examples/basic.js +115 -110
  141. package/examples/bootstrap.js +52 -43
  142. package/examples/mcp-example.js +56 -53
  143. package/examples/skill-example.js +49 -49
  144. package/examples/test-chat.js +60 -58
  145. package/examples/test-mcp.js +49 -43
  146. package/examples/test-reload.js +38 -40
  147. package/examples/test-telegram.js +3 -3
  148. package/examples/test-tg-bot.js +7 -4
  149. package/examples/test-tg-simple.js +4 -3
  150. package/examples/test-tg.js +3 -3
  151. package/examples/test-think.js +13 -7
  152. package/examples/test-web-plugin.js +61 -56
  153. package/examples/test-weixin-feishu.js +40 -37
  154. package/examples/workflow.js +49 -49
  155. package/foliko-1.0.75.tgz +0 -0
  156. package/package.json +37 -3
  157. package/plugins/ai-plugin.js +7 -5
  158. package/plugins/ambient-agent/EventWatcher.js +113 -0
  159. package/plugins/ambient-agent/ExplorerLoop.js +640 -0
  160. package/plugins/ambient-agent/GoalManager.js +197 -0
  161. package/plugins/ambient-agent/Reflector.js +95 -0
  162. package/plugins/ambient-agent/StateStore.js +90 -0
  163. package/plugins/ambient-agent/constants.js +101 -0
  164. package/plugins/ambient-agent/index.js +579 -0
  165. package/plugins/default-plugins.js +62 -49
  166. package/plugins/email/constants.js +64 -0
  167. package/plugins/email/handlers.js +461 -0
  168. package/plugins/email/index.js +278 -0
  169. package/plugins/email/monitor.js +269 -0
  170. package/plugins/email/parser.js +138 -0
  171. package/plugins/email/reply.js +151 -0
  172. package/plugins/email/utils.js +124 -0
  173. package/plugins/feishu-plugin.js +23 -19
  174. package/plugins/file-system-plugin.js +469 -120
  175. package/plugins/install-plugin.js +6 -4
  176. package/plugins/python-executor-plugin.js +3 -1
  177. package/plugins/python-plugin-loader.js +10 -8
  178. package/plugins/rules-plugin.js +5 -3
  179. package/plugins/scheduler-plugin.js +18 -16
  180. package/plugins/session-plugin.js +3 -1
  181. package/plugins/storage-plugin.js +5 -3
  182. package/plugins/subagent-plugin.js +152 -92
  183. package/plugins/telegram-plugin.js +26 -19
  184. package/plugins/think-plugin.js +4 -2
  185. package/plugins/tools-plugin.js +3 -1
  186. package/plugins/web-plugin.js +15 -13
  187. package/plugins/weixin-plugin.js +43 -36
  188. package/reports/system-health-report-20260401.md +79 -0
  189. package/skills/ambient-agent/SKILL.md +49 -39
  190. package/skills/foliko-dev/AGENTS.md +64 -61
  191. package/skills/foliko-dev/SKILL.md +125 -119
  192. package/skills/mcp-usage/SKILL.md +19 -17
  193. package/skills/python-plugin-dev/SKILL.md +16 -15
  194. package/skills/skill-guide/SKILL.md +12 -12
  195. package/skills/subagent-guide/SKILL.md +237 -0
  196. package/skills/workflow-guide/SKILL.md +90 -45
  197. package/skills/workflow-troubleshooting/DEBUGGING.md +36 -21
  198. package/skills/workflow-troubleshooting/SKILL.md +156 -79
  199. package/src/capabilities/index.js +4 -4
  200. package/src/capabilities/skill-manager.js +211 -197
  201. package/src/capabilities/workflow-engine.js +461 -547
  202. package/src/core/agent-chat.js +426 -279
  203. package/src/core/agent.js +453 -248
  204. package/src/core/framework.js +183 -149
  205. package/src/core/index.js +8 -8
  206. package/src/core/plugin-base.js +52 -52
  207. package/src/core/plugin-manager.js +377 -281
  208. package/src/core/provider.js +35 -32
  209. package/src/core/sub-agent-config.js +264 -0
  210. package/src/core/system-prompt-builder.js +120 -0
  211. package/src/core/tool-registry.js +416 -33
  212. package/src/core/tool-router.js +149 -68
  213. package/src/executors/executor-base.js +58 -58
  214. package/src/executors/mcp-executor.js +269 -257
  215. package/src/index.js +5 -17
  216. package/src/utils/circuit-breaker.js +301 -0
  217. package/src/utils/error-boundary.js +363 -0
  218. package/src/utils/error.js +374 -0
  219. package/src/utils/event-emitter.js +20 -20
  220. package/src/utils/id.js +133 -0
  221. package/src/utils/index.js +217 -3
  222. package/src/utils/logger.js +181 -0
  223. package/src/utils/plugin-helpers.js +90 -0
  224. package/src/utils/retry.js +122 -0
  225. package/src/utils/sandbox.js +292 -0
  226. package/test/tool-registry-validation.test.js +218 -0
  227. package/test_report.md +70 -0
  228. package/website/docs/api.html +169 -107
  229. package/website/docs/configuration.html +296 -144
  230. package/website/docs/plugin-development.html +154 -85
  231. package/website/docs/project-structure.html +110 -109
  232. package/website/docs/skill-development.html +117 -61
  233. package/website/index.html +209 -205
  234. package/website/script.js +20 -17
  235. package/website/styles.css +1 -1
  236. package/plugins/ambient-agent-plugin.js +0 -1565
  237. package/plugins/email.js +0 -1142
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Email 插件 - 自动回复
3
+ */
4
+
5
+ const { EMAIL_DEFAULTS } = require('./constants')
6
+
7
+ /**
8
+ * 处理自动回复
9
+ * @param {Object} emailPlugin - EmailPlugin 实例
10
+ * @param {Object} args - 回复参数
11
+ * @returns {Promise<Object>} 回复结果
12
+ */
13
+ async function handleAutoReply(emailPlugin, args) {
14
+ let { to, subject, body, from, _event, prompt, messageId, inReplyTo } = args
15
+
16
+ // 如果没有直接参数,尝试从 _event 提取
17
+ // 支持多种事件结构:{ email, timestamp } 或 { data: { email } } 或 { data: { ... } }
18
+ if (!to && !subject && !body && _event) {
19
+ // 兼容多种事件结构
20
+ const email = _event.email || _event.data?.email || _event.data || {}
21
+ from = email.from?.text || email.from || ''
22
+ to = email.to?.text || email.to || ''
23
+ subject = email.subject || ''
24
+ body = email.text || email.body || ''
25
+ // 优先使用 _event 中的 uid/messageId
26
+ if (!messageId) {
27
+ messageId = email.messageId || email.uid || _event.data?.messageId || _event.data?.uid
28
+ }
29
+ }
30
+
31
+ // 如果 _event 没有有效数据,不允许自动读取所有邮件
32
+ if (!_event || (!_event.email && !_event.data)) {
33
+ return {
34
+ success: false,
35
+ error: '缺少邮件数据:_event 中没有有效的邮件信息,无法自动回复。请确认是否在收到新邮件事件时调用此工具。'
36
+ }
37
+ }
38
+
39
+ // 优先使用传入的 inReplyTo,否则用 messageId
40
+ const replyTo = inReplyTo || messageId
41
+
42
+ // 检查必要参数
43
+ if (!from && !to) {
44
+ return { success: false, error: '缺少收件人地址' }
45
+ }
46
+ if (!body) {
47
+ return { success: false, error: '缺少邮件内容' }
48
+ }
49
+
50
+ try {
51
+ // 使用子 Agent 生成回复
52
+ const replyAgent = emailPlugin._framework.createSubAgent({
53
+ name: 'email_replier',
54
+ role: '邮件自动回复助手,专注于生成专业、礼貌、简洁的邮件回复',
55
+ parentTools: []
56
+ })
57
+
58
+ // 构建提示让 LLM 生成回复
59
+ const finalPrompt = prompt || `你是一封邮件自动回复助手。请根据以下邮件内容,生成一封专业的回复邮件。
60
+
61
+ 【原始邮件】
62
+ 发件人: ${from || to}
63
+ 主题: ${subject}
64
+ 内容:
65
+ ${body}
66
+
67
+ 【要求】
68
+ 1. 回复内容要针对邮件中的问题或内容进行回复
69
+ 2. 语言要专业、礼貌、简洁
70
+ 3. 只输出邮件正文内容,不要额外解释
71
+ 4. 回复语言应与原邮件一致(如果原邮件是中文,则用中文回复)`
72
+
73
+ // 等待 Agent 生成回复(带超时保护)
74
+ const timeoutMs = args.timeout || EMAIL_DEFAULTS.timeout
75
+ const timeoutPromise = new Promise((_, reject) => {
76
+ setTimeout(() => reject(new Error(`AI回复生成超时(${timeoutMs / 1000}秒)`)), timeoutMs)
77
+ })
78
+
79
+ const replyPromise = replyAgent.chat(finalPrompt, { maxSteps: 3 })
80
+ const replyResult = await Promise.race([replyPromise, timeoutPromise])
81
+
82
+ // 提取回复内容
83
+ let replyContent = ''
84
+ if (typeof replyResult === 'string') {
85
+ replyContent = replyResult.trim()
86
+ } else if (replyResult && replyResult.content) {
87
+ replyContent = replyResult.content.trim()
88
+ } else if (replyResult && replyResult.message) {
89
+ replyContent = replyResult.message.trim()
90
+ } else {
91
+ replyContent = JSON.stringify(replyResult).trim()
92
+ }
93
+
94
+ // 去掉思考过程标签
95
+ replyContent = replyContent.replace(/<think>[\s\S]*?<\/think>/g, '').trim()
96
+
97
+ if (!replyContent || replyContent.length < 5) {
98
+ return { success: false, error: 'AI未能生成有效的回复内容' }
99
+ }
100
+
101
+ // 发送回复邮件
102
+ const { sendEmail } = require('./handlers')
103
+ const sendResult = await sendEmail(emailPlugin, {
104
+ to: from || to,
105
+ subject: `Re: ${subject}`,
106
+ body: replyContent,
107
+ inReplyTo: replyTo,
108
+ references: replyTo ? [replyTo] : undefined
109
+ })
110
+
111
+ if (sendResult.success) {
112
+ // 发送成功后,标记为已处理
113
+ const emailData = _event?.email || _event?.data?.email || _event?.data || {}
114
+ const msgId = messageId || emailData.messageId || emailData.uid
115
+ if (msgId) {
116
+ emailPlugin._processedEmails.add(msgId)
117
+ emailPlugin._log.info(`邮件已处理: ${msgId}`)
118
+
119
+ // 24小时后从已处理列表中移除
120
+ setTimeout(() => {
121
+ emailPlugin._processedEmails.delete(msgId)
122
+ }, EMAIL_DEFAULTS.processedEmailTTL)
123
+ }
124
+
125
+ // 自动标记原邮件为已读
126
+ const uid = emailData.uid || msgId
127
+ if (uid) {
128
+ try {
129
+ const { markAsRead } = require('./handlers')
130
+ await markAsRead(emailPlugin, { uid: uid }) // 使用 uid 而非 messageId
131
+ } catch (err) {
132
+ emailPlugin._log.warn(`自动标记已读失败: ${err.message}`)
133
+ }
134
+ }
135
+
136
+ return {
137
+ success: true,
138
+ message: `自动回复已发送至 ${from || to}`,
139
+ replyContent
140
+ }
141
+ } else {
142
+ return { success: false, error: sendResult.error || '发送失败' }
143
+ }
144
+ } catch (err) {
145
+ return { success: false, error: err.message }
146
+ }
147
+ }
148
+
149
+ module.exports = {
150
+ handleAutoReply
151
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Email 插件 - 工具函数
3
+ */
4
+
5
+ const https = require('https')
6
+ const http = require('http')
7
+ const fs = require('fs')
8
+
9
+ /**
10
+ * 验证邮箱地址格式
11
+ * @param {string} email - 邮箱地址
12
+ * @returns {boolean}
13
+ */
14
+ function isValidEmail(email) {
15
+ if (!email) return false
16
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
17
+ return emailRegex.test(email)
18
+ }
19
+
20
+ /**
21
+ * 从邮件地址提取显示名称和邮箱
22
+ * @param {string} from - 邮件地址文本
23
+ * @returns {{name: string, email: string}}
24
+ */
25
+ function parseEmailAddress(from) {
26
+ if (!from) return { name: '', email: '' }
27
+
28
+ // 格式: "Display Name <email@example.com>"
29
+ const match = from.match(/^(.+?)\s*<(.+)>$/)
30
+ if (match) {
31
+ return { name: match[1].trim(), email: match[2].trim() }
32
+ }
33
+
34
+ // 格式: email@example.com
35
+ return { name: '', email: from.trim() }
36
+ }
37
+
38
+ /**
39
+ * 获取环境变量配置
40
+ * @param {Object} args - 参数对象
41
+ * @returns {Object} 合并后的配置
42
+ */
43
+ function getConfig(args) {
44
+ return {
45
+ host: args.host || process.env.IMAP_HOST,
46
+ port: args.port || parseInt(process.env.IMAP_PORT) || 993,
47
+ user: args.user || process.env.IMAP_USER,
48
+ password: args.password || process.env.IMAP_PASS
49
+ }
50
+ }
51
+
52
+ /**
53
+ * 从 URL 获取内容
54
+ * @param {string} url - 文件 URL
55
+ * @returns {Promise<Buffer>}
56
+ */
57
+ function fetchUrl(url) {
58
+ return new Promise((resolve, reject) => {
59
+ const lib = url.startsWith('https') ? https : http
60
+
61
+ const request = lib.get(url, (response) => {
62
+ // 处理重定向
63
+ if (response.statusCode === 301 || response.statusCode === 302) {
64
+ fetchUrl(response.headers.location).then(resolve).catch(reject)
65
+ return
66
+ }
67
+
68
+ const chunks = []
69
+ response.on('data', (chunk) => chunks.push(chunk))
70
+ response.on('end', () => resolve(Buffer.concat(chunks)))
71
+ response.on('error', reject)
72
+ })
73
+
74
+ request.on('error', reject)
75
+ request.setTimeout(10000, () => {
76
+ request.destroy()
77
+ reject(new Error('下载超时'))
78
+ })
79
+ })
80
+ }
81
+
82
+ /**
83
+ * 处理附件
84
+ * @param {Object} att - 附件定义
85
+ * @returns {Promise<Object>} 处理后的附件
86
+ */
87
+ async function processAttachment(att) {
88
+ const attachment = { filename: att.filename }
89
+
90
+ if (att.path) {
91
+ // 本地文件
92
+ attachment.content = fs.createReadStream(att.path)
93
+ } else if (att.url) {
94
+ // 远程 URL
95
+ attachment.content = await fetchUrl(att.url)
96
+ } else if (att.content) {
97
+ // Base64 内容
98
+ const base64Data = att.content.replace(/^data:[^;]+;base64,/, '')
99
+ attachment.content = Buffer.from(base64Data, 'base64')
100
+ }
101
+
102
+ if (att.cid) {
103
+ attachment.cid = att.cid
104
+ }
105
+
106
+ return attachment
107
+ }
108
+
109
+ /**
110
+ * 生成唯一调用 ID
111
+ * @returns {string}
112
+ */
113
+ function generateCallId() {
114
+ return `${Date.now()}_${Math.random().toString(36).substr(2, 5)}`
115
+ }
116
+
117
+ module.exports = {
118
+ isValidEmail,
119
+ parseEmailAddress,
120
+ getConfig,
121
+ fetchUrl,
122
+ processAttachment,
123
+ generateCallId
124
+ }
@@ -9,6 +9,8 @@
9
9
  */
10
10
 
11
11
  const { Plugin } = require('../src/core/plugin-base')
12
+ const { logger } = require('../src/utils/logger')
13
+ const log = logger.child('Feishu')
12
14
  const {cleanResponse} =require('../src/utils')
13
15
  const removeMarkdown = require('remove-markdown');
14
16
  class FeishuPlugin extends Plugin {
@@ -19,10 +21,12 @@ class FeishuPlugin extends Plugin {
19
21
  this.description = '飞书对话插件,使用 WebSocket 长连接接收消息'
20
22
  this.priority = 80
21
23
  this.enabled = false
22
- this.systemPrompt = `你是一个飞书助手。
24
+ this.systemPrompt = `你是一个飞书助手。回复内容不要使用markdown格式文本。
23
25
 
24
- **重要:**
25
- -回复内容使用纯文本,不要使用markdown
26
+ **重要:** 子Agent 匹配规则必须遵守:
27
+ - 根据【子 Agent 匹配表】,将任务委托给最匹配的子Agent处理
28
+ - 使用 subagent_call 工具并指定 agentName 来委托任务
29
+ - 只有当没有匹配的子Agent时,才直接调用工具
26
30
 
27
31
  **命令执行规范:**
28
32
  - 执行 npx skills add / npx skills remove / npx skills list 命令时,必须自动添加参数:-a openclaw -y
@@ -57,7 +61,7 @@ class FeishuPlugin extends Plugin {
57
61
  this._initialized = true
58
62
 
59
63
  if (!this.config.appId || !this.config.appSecret) {
60
- console.warn('[Feishu] No appId or appSecret.')
64
+ log.warn(' No appId or appSecret.')
61
65
  return this
62
66
  }
63
67
 
@@ -67,7 +71,7 @@ class FeishuPlugin extends Plugin {
67
71
  if (this._sessionPlugin) {
68
72
  this._sessionDeleteHandler = (sessionId) => {
69
73
  if (sessionId.startsWith('feishu_')) {
70
- console.log(`[Feishu] Session deleted: ${sessionId}`)
74
+ log.info(` Session deleted: ${sessionId}`)
71
75
  }
72
76
  }
73
77
  this._sessionPlugin.on('session:deleted', this._sessionDeleteHandler)
@@ -121,9 +125,9 @@ class FeishuPlugin extends Plugin {
121
125
  })
122
126
  }
123
127
 
124
- console.log('[Feishu] WebSocket client started')
128
+ log.info(' WebSocket client started')
125
129
  } catch (err) {
126
- console.error('[Feishu] Failed to initialize client:', err.message, err.stack)
130
+ log.error(' Failed to initialize client:', err.message, err.stack)
127
131
  }
128
132
  }
129
133
 
@@ -172,7 +176,7 @@ class FeishuPlugin extends Plugin {
172
176
  this._processingLock.set(openId, false)
173
177
  }
174
178
  } catch (err) {
175
- console.error('[Feishu] Error handling message:', err.message)
179
+ log.error(' Error handling message:', err.message)
176
180
  }
177
181
  }
178
182
 
@@ -238,7 +242,7 @@ class FeishuPlugin extends Plugin {
238
242
  try {
239
243
  await this._sendTextMessage(openId, reminderText)
240
244
  } catch (err) {
241
- console.error(`[Feishu] Failed to send reminder:`, err.message)
245
+ log.error(` Failed to send reminder:`, err.message)
242
246
  }
243
247
  return
244
248
  }
@@ -253,7 +257,7 @@ class FeishuPlugin extends Plugin {
253
257
  try {
254
258
  await this._sendTextMessage(openId, reminderText)
255
259
  } catch (err) {
256
- console.error(`[Feishu] Failed to send reminder:`, err.message)
260
+ log.error(` Failed to send reminder:`, err.message)
257
261
  }
258
262
  }
259
263
  }
@@ -274,9 +278,9 @@ class FeishuPlugin extends Plugin {
274
278
 
275
279
  try {
276
280
  await this._sendTextMessage(openId, notificationText)
277
- console.log(`[Feishu] Webhook notification sent to ${openId}`)
281
+ log.info(` Webhook notification sent to ${openId}`)
278
282
  } catch (err) {
279
- console.error(`[Feishu] Failed to send webhook notification:`, err.message)
283
+ log.error(` Failed to send webhook notification:`, err.message)
280
284
  }
281
285
  }
282
286
 
@@ -311,7 +315,7 @@ class FeishuPlugin extends Plugin {
311
315
  }
312
316
 
313
317
  if (!openId) {
314
- console.warn('[Feishu] No feishu session found for notification')
318
+ log.warn(' No feishu session found for notification')
315
319
  return
316
320
  }
317
321
 
@@ -327,9 +331,9 @@ class FeishuPlugin extends Plugin {
327
331
 
328
332
  try {
329
333
  await this._sendTextMessage(openId, notificationText)
330
- console.log(`[Feishu] Notification sent to ${openId}`)
334
+ log.info(` Notification sent to ${openId}`)
331
335
  } catch (err) {
332
- console.error(`[Feishu] Failed to send notification:`, err.message)
336
+ log.error(` Failed to send notification:`, err.message)
333
337
  }
334
338
  }
335
339
 
@@ -358,7 +362,7 @@ class FeishuPlugin extends Plugin {
358
362
  await this._sendMessage(openId, '抱歉,我没有收到有效的回复。', originalMsg)
359
363
  }
360
364
  } catch (err) {
361
- console.error('[Feishu] Chat error:', err)
365
+ log.error(' Chat error:', err)
362
366
  await this._sendMessage(openId, `发生错误:${err.message}`, originalMsg)
363
367
  }
364
368
  }
@@ -375,7 +379,7 @@ class FeishuPlugin extends Plugin {
375
379
  }
376
380
  })
377
381
  } catch (err) {
378
- console.error('[Feishu] Failed to send text message:', err.message)
382
+ log.error(' Failed to send text message:', err.message)
379
383
  throw err
380
384
  }
381
385
  }
@@ -396,7 +400,7 @@ class FeishuPlugin extends Plugin {
396
400
  }
397
401
  })
398
402
  } catch (err) {
399
- console.error('[Feishu] Failed to send message:', err.message)
403
+ log.error(' Failed to send message:', err.message)
400
404
  }
401
405
  }
402
406
 
@@ -437,7 +441,7 @@ class FeishuPlugin extends Plugin {
437
441
  try { this._wsClient.close() } catch (e) { /* ignore */ }
438
442
  this._wsClient = null
439
443
  this._client = null
440
- console.log('[Feishu] Client stopped')
444
+ log.info(' Client stopped')
441
445
  }
442
446
  }
443
447