foliko 1.0.75 → 1.0.76

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 (88) hide show
  1. package/.claude/settings.local.json +159 -157
  2. package/cli/bin/foliko.js +12 -12
  3. package/cli/src/commands/chat.js +143 -143
  4. package/cli/src/commands/list.js +93 -93
  5. package/cli/src/index.js +75 -75
  6. package/cli/src/ui/chat-ui.js +201 -201
  7. package/cli/src/utils/ansi.js +40 -40
  8. package/cli/src/utils/markdown.js +292 -292
  9. package/examples/ambient-example.js +194 -194
  10. package/examples/basic.js +115 -115
  11. package/examples/bootstrap.js +121 -121
  12. package/examples/mcp-example.js +56 -56
  13. package/examples/skill-example.js +49 -49
  14. package/examples/test-chat.js +137 -137
  15. package/examples/test-mcp.js +85 -85
  16. package/examples/test-reload.js +59 -59
  17. package/examples/test-telegram.js +50 -50
  18. package/examples/test-tg-bot.js +45 -45
  19. package/examples/test-tg-simple.js +47 -47
  20. package/examples/test-tg.js +62 -62
  21. package/examples/test-think.js +43 -43
  22. package/examples/test-web-plugin.js +103 -103
  23. package/examples/test-weixin-feishu.js +103 -103
  24. package/examples/workflow.js +158 -158
  25. package/package.json +1 -1
  26. package/plugins/ai-plugin.js +102 -102
  27. package/plugins/ambient-agent/EventWatcher.js +113 -113
  28. package/plugins/ambient-agent/ExplorerLoop.js +640 -640
  29. package/plugins/ambient-agent/GoalManager.js +197 -197
  30. package/plugins/ambient-agent/Reflector.js +95 -95
  31. package/plugins/ambient-agent/StateStore.js +90 -90
  32. package/plugins/ambient-agent/constants.js +101 -101
  33. package/plugins/ambient-agent/index.js +579 -579
  34. package/plugins/audit-plugin.js +187 -187
  35. package/plugins/default-plugins.js +662 -662
  36. package/plugins/email/constants.js +64 -64
  37. package/plugins/email/handlers.js +461 -461
  38. package/plugins/email/index.js +278 -278
  39. package/plugins/email/monitor.js +269 -269
  40. package/plugins/email/parser.js +138 -138
  41. package/plugins/email/reply.js +151 -151
  42. package/plugins/email/utils.js +124 -124
  43. package/plugins/feishu-plugin.js +481 -481
  44. package/plugins/file-system-plugin.js +826 -826
  45. package/plugins/install-plugin.js +199 -199
  46. package/plugins/python-executor-plugin.js +367 -367
  47. package/plugins/python-plugin-loader.js +481 -481
  48. package/plugins/rules-plugin.js +294 -294
  49. package/plugins/scheduler-plugin.js +691 -691
  50. package/plugins/session-plugin.js +369 -369
  51. package/plugins/shell-executor-plugin.js +197 -197
  52. package/plugins/storage-plugin.js +240 -240
  53. package/plugins/subagent-plugin.js +845 -845
  54. package/plugins/telegram-plugin.js +482 -482
  55. package/plugins/think-plugin.js +345 -345
  56. package/plugins/tools-plugin.js +196 -196
  57. package/plugins/web-plugin.js +606 -606
  58. package/plugins/weixin-plugin.js +545 -545
  59. package/src/capabilities/index.js +11 -11
  60. package/src/capabilities/skill-manager.js +609 -609
  61. package/src/capabilities/workflow-engine.js +1109 -1109
  62. package/src/core/agent-chat.js +882 -882
  63. package/src/core/agent.js +892 -892
  64. package/src/core/framework.js +465 -465
  65. package/src/core/index.js +19 -19
  66. package/src/core/plugin-base.js +219 -219
  67. package/src/core/plugin-manager.js +863 -863
  68. package/src/core/provider.js +114 -114
  69. package/src/core/sub-agent-config.js +264 -264
  70. package/src/core/system-prompt-builder.js +120 -120
  71. package/src/core/tool-registry.js +517 -517
  72. package/src/core/tool-router.js +297 -297
  73. package/src/executors/executor-base.js +58 -58
  74. package/src/executors/mcp-executor.js +741 -741
  75. package/src/index.js +25 -25
  76. package/src/utils/circuit-breaker.js +301 -301
  77. package/src/utils/error-boundary.js +363 -363
  78. package/src/utils/error.js +374 -374
  79. package/src/utils/event-emitter.js +97 -97
  80. package/src/utils/id.js +133 -133
  81. package/src/utils/index.js +217 -217
  82. package/src/utils/logger.js +181 -181
  83. package/src/utils/plugin-helpers.js +90 -90
  84. package/src/utils/retry.js +122 -122
  85. package/src/utils/sandbox.js +292 -292
  86. package/test/tool-registry-validation.test.js +218 -218
  87. package/website/script.js +136 -136
  88. package/foliko-1.0.75.tgz +0 -0
@@ -1,278 +1,278 @@
1
- /**
2
- * Email 插件
3
- * 邮件收发插件 - 支持读取和发送电子邮件、监控新邮件
4
- */
5
-
6
- const { Plugin } = require('../../src/core/plugin-base')
7
- const { logger } = require('../../src/utils/logger')
8
- const log = logger.child('Email')
9
- const { z } = require('zod')
10
-
11
- // 导入子模块
12
- const { sendEmail, readEmails, getUnreadCount, markAsRead, deleteEmail, getEmailConfig } = require('./handlers')
13
- const { handleEmailWatch } = require('./monitor')
14
- const { handleAutoReply } = require('./reply')
15
- const { EMAIL_DEFAULTS } = require('./constants')
16
-
17
- class EmailPlugin extends Plugin {
18
- constructor(config = {}) {
19
- super()
20
- this.name = 'email'
21
- this.version = '1.1.0'
22
- this.description = `邮件收发插件 - 支持读取和发送电子邮件、监控新邮件
23
- 功能:
24
- - 发送邮件支持附件(本地文件、远程URL、Base64)
25
- - 读取邮件(IMAP协议)
26
- - 监控新邮件(支持IMAP IDLE推送和定时轮询)
27
- 发送邮件支持附件:
28
- - attachments.path: 本地文件路径
29
- - attachments.url: 远程图片/文件URL(自动下载)
30
- - attachments.content: Base64内容
31
- - attachments.cid: 嵌入式图片CID(HTML中用 <img src="cid:xxx"> 引用)`
32
- this.priority = 10
33
- this.enabled = false
34
-
35
- // 邮件监控状态
36
- this._watchInterval = null
37
- this._lastSeenUid = null
38
- this._watchConfig = null
39
- this._watchEnabled = false
40
- this._checkInProgress = false
41
-
42
- // 带上限的 Set,防止内存泄漏
43
- const MAX_SET_SIZE = 1000
44
- this._recentlyEmailed = new Set()
45
- this._processedEmails = new Set()
46
- this._maxSetSize = MAX_SET_SIZE
47
-
48
- // 日志器
49
- this._log = log
50
- }
51
-
52
- install(framework) {
53
- this._framework = framework
54
- this._registerTools()
55
- return this
56
- }
57
-
58
- start(framework) {
59
- return this
60
- }
61
-
62
- /**
63
- * 向 Set 中添加元素,自动控制大小防止内存泄漏
64
- * @param {Set} set - 要操作的 Set
65
- * @param {*} item - 要添加的元素
66
- * @private
67
- */
68
- _addToBoundedSet(set, item) {
69
- if (set.size >= this._maxSetSize) {
70
- // 删除最早的元素(Set 的插入顺序)
71
- const firstKey = set.values().next().value
72
- set.delete(firstKey)
73
- }
74
- set.add(item)
75
- }
76
-
77
- /**
78
- * 发送邮件事件
79
- */
80
- _emitEmailReceived(email) {
81
- if (!this._framework) return
82
-
83
- const msgId = email.messageId || email.uid
84
-
85
- // 优先检查是否已处理过(长TTL,防止服务器标记失败导致重复处理)
86
- if (msgId && this._processedEmails.has(msgId)) {
87
- this._log.info(`跳过已处理的邮件: ${email.subject} (${msgId})`)
88
- return
89
- }
90
-
91
- // 快速去重(短TTL,防止同一批次重复触发)
92
- if (msgId && this._recentlyEmailed.has(msgId)) {
93
- return
94
- }
95
-
96
- // 标记为已处理
97
- if (msgId) {
98
- // 使用 bounded set 防止内存泄漏
99
- this._addToBoundedSet(this._recentlyEmailed, msgId)
100
- setTimeout(() => {
101
- this._recentlyEmailed.delete(msgId)
102
- }, EMAIL_DEFAULTS.recentlyEmailTTL)
103
-
104
- // _processedEmails 也需要 bounded
105
- this._addToBoundedSet(this._processedEmails, msgId)
106
- }
107
-
108
- this._framework.emit('email:received', {
109
- email,
110
- timestamp: new Date()
111
- })
112
- }
113
-
114
- _registerTools() {
115
- // 发送邮件工具
116
- this._framework.registerTool({
117
- name: 'email_send',
118
- description: '发送电子邮件,无须用户确认',
119
- inputSchema: z.object({
120
- to: z.string().describe('收件人邮箱地址'),
121
- subject: z.string().describe('邮件主题'),
122
- body: z.string().describe('邮件正文内容'),
123
- cc: z.string().optional().describe('抄送邮箱地址,多个用逗号分隔'),
124
- bcc: z.string().optional().describe('密送邮箱地址,多个用逗号分隔'),
125
- isHtml: z.boolean().optional().describe('是否为HTML格式,默认false'),
126
- attachments: z.array(z.object({
127
- filename: z.string().describe('附件文件名'),
128
- path: z.string().optional().describe('本地文件路径'),
129
- url: z.string().optional().describe('远程图片URL'),
130
- content: z.string().optional().describe('Base64编码内容(可带前缀如 data:image/png;base64,)'),
131
- cid: z.string().optional().describe('嵌入式图片的CID(用于在HTML中嵌入图片,如 <img src="cid:xxx">)')
132
- })).optional().describe('附件列表,支持本地文件、远程URL或Base64内容')
133
- }),
134
- execute: async (args) => {
135
- return sendEmail(this, args)
136
- }
137
- })
138
-
139
- // 读取邮件工具
140
- this._framework.registerTool({
141
- name: 'email_read',
142
- description: '读取电子邮件(支持IMAP协议)',
143
- inputSchema: z.object({
144
- box: z.string().optional().describe('邮箱文件夹,默认INBOX'),
145
- limit: z.number().optional().describe('读取邮件数量,默认10'),
146
- unreadOnly: z.boolean().optional().describe('仅读取未读邮件,默认false'),
147
- searchCriteria: z.string().optional().describe('搜索条件,如 "UNSEEN", "FROM sender@example.com"')
148
- }),
149
- execute: async (args) => {
150
- return readEmails(this, args)
151
- }
152
- })
153
-
154
- // 获取未读邮件数量
155
- this._framework.registerTool({
156
- name: 'email_unread_count',
157
- description: '获取邮箱未读邮件数量',
158
- inputSchema: z.object({
159
- box: z.string().optional().describe('邮箱文件夹,默认INBOX')
160
- }),
161
- execute: async (args) => {
162
- return getUnreadCount(this, args)
163
- }
164
- })
165
-
166
- // 标记邮件为已读
167
- this._framework.registerTool({
168
- name: 'email_mark_read',
169
- description: '标记邮件为已读',
170
- inputSchema: z.object({
171
- messageId: z.string().describe('邮件UID或序列号')
172
- }),
173
- execute: async (args) => {
174
- return markAsRead(this, args)
175
- }
176
- })
177
-
178
- // 删除邮件
179
- this._framework.registerTool({
180
- name: 'email_delete',
181
- description: '删除邮件(标记为已删除,然后永久删除)',
182
- inputSchema: z.object({
183
- messageId: z.string().describe('邮件UID或序列号'),
184
- box: z.string().optional().describe('邮箱文件夹,默认INBOX')
185
- }),
186
- execute: async (args) => {
187
- return deleteEmail(this, args)
188
- }
189
- })
190
-
191
- // 配置邮箱连接
192
- this._framework.registerTool({
193
- name: 'email_configure',
194
- description: '查看邮箱配置(实际配置通过环境变量设置)',
195
- inputSchema: z.object({}),
196
- execute: async () => {
197
- return getEmailConfig()
198
- }
199
- })
200
-
201
- // 监控新邮件
202
- this._framework.registerTool({
203
- name: 'email_watch',
204
- description: '启动/停止邮件监控,检测新邮件并发送事件通知',
205
- inputSchema: z.object({
206
- action: z.enum(['start', 'stop', 'status']).describe('操作:启动监控、停止监控、查看状态'),
207
- interval: z.number().optional().describe('轮询间隔(秒),默认60秒,适用于不支持IDLE的服务器'),
208
- box: z.string().optional().describe('邮箱文件夹,默认INBOX')
209
- }),
210
- execute: async (args) => {
211
- return handleEmailWatch(this, args)
212
- }
213
- })
214
-
215
- // 自动回复邮件
216
- this._framework.registerTool({
217
- name: 'email_auto_reply',
218
- description: '自动分析邮件内容并发送回复(无需用户确认)',
219
- inputSchema: z.object({
220
- to: z.string().describe('收件人邮箱地址'),
221
- subject: z.string().describe('原始邮件主题'),
222
- body: z.string().describe('原始邮件内容'),
223
- from: z.string().optional().describe('发件人邮箱地址(可选)'),
224
- prompt: z.string().optional().describe('自定义提示词,用于指导AI生成回复内容'),
225
- timeout: z.number().optional().describe('AI生成回复超时时间(毫秒),默认60000'),
226
- messageId: z.string().optional().describe('原始邮件的Message-ID,用于在邮件客户端中创建回复线程')
227
- }),
228
- execute: async (args) => {
229
- return handleAutoReply(this, args)
230
- }
231
- })
232
- }
233
-
234
- /**
235
- * 启动邮件监控(内部方法)
236
- */
237
- _startEmailWatch(config) {
238
- const { startEmailWatch } = require('./monitor')
239
- return startEmailWatch(this, config)
240
- }
241
-
242
- /**
243
- * 停止邮件监控(内部方法)
244
- */
245
- _stopEmailWatch() {
246
- const { stopEmailWatch } = require('./monitor')
247
- return stopEmailWatch(this)
248
- }
249
-
250
- /**
251
- * 获取监控状态(内部方法)
252
- */
253
- _getEmailWatchStatus() {
254
- const { getEmailWatchStatus } = require('./monitor')
255
- return getEmailWatchStatus(this)
256
- }
257
-
258
- /**
259
- * 检查新邮件(内部方法)
260
- */
261
- async _checkNewEmails() {
262
- const { checkNewEmails } = require('./monitor')
263
- return checkNewEmails(this)
264
- }
265
-
266
- uninstall(framework) {
267
- // 停止邮件监控
268
- if (this._watchInterval) {
269
- clearInterval(this._watchInterval)
270
- this._watchInterval = null
271
- }
272
- this._watchEnabled = false
273
- this._watchConfig = null
274
- this._framework = null
275
- }
276
- }
277
-
278
- module.exports = { EmailPlugin }
1
+ /**
2
+ * Email 插件
3
+ * 邮件收发插件 - 支持读取和发送电子邮件、监控新邮件
4
+ */
5
+
6
+ const { Plugin } = require('../../src/core/plugin-base')
7
+ const { logger } = require('../../src/utils/logger')
8
+ const log = logger.child('Email')
9
+ const { z } = require('zod')
10
+
11
+ // 导入子模块
12
+ const { sendEmail, readEmails, getUnreadCount, markAsRead, deleteEmail, getEmailConfig } = require('./handlers')
13
+ const { handleEmailWatch } = require('./monitor')
14
+ const { handleAutoReply } = require('./reply')
15
+ const { EMAIL_DEFAULTS } = require('./constants')
16
+
17
+ class EmailPlugin extends Plugin {
18
+ constructor(config = {}) {
19
+ super()
20
+ this.name = 'email'
21
+ this.version = '1.1.0'
22
+ this.description = `邮件收发插件 - 支持读取和发送电子邮件、监控新邮件
23
+ 功能:
24
+ - 发送邮件支持附件(本地文件、远程URL、Base64)
25
+ - 读取邮件(IMAP协议)
26
+ - 监控新邮件(支持IMAP IDLE推送和定时轮询)
27
+ 发送邮件支持附件:
28
+ - attachments.path: 本地文件路径
29
+ - attachments.url: 远程图片/文件URL(自动下载)
30
+ - attachments.content: Base64内容
31
+ - attachments.cid: 嵌入式图片CID(HTML中用 <img src="cid:xxx"> 引用)`
32
+ this.priority = 10
33
+ this.enabled = false
34
+
35
+ // 邮件监控状态
36
+ this._watchInterval = null
37
+ this._lastSeenUid = null
38
+ this._watchConfig = null
39
+ this._watchEnabled = false
40
+ this._checkInProgress = false
41
+
42
+ // 带上限的 Set,防止内存泄漏
43
+ const MAX_SET_SIZE = 1000
44
+ this._recentlyEmailed = new Set()
45
+ this._processedEmails = new Set()
46
+ this._maxSetSize = MAX_SET_SIZE
47
+
48
+ // 日志器
49
+ this._log = log
50
+ }
51
+
52
+ install(framework) {
53
+ this._framework = framework
54
+ this._registerTools()
55
+ return this
56
+ }
57
+
58
+ start(framework) {
59
+ return this
60
+ }
61
+
62
+ /**
63
+ * 向 Set 中添加元素,自动控制大小防止内存泄漏
64
+ * @param {Set} set - 要操作的 Set
65
+ * @param {*} item - 要添加的元素
66
+ * @private
67
+ */
68
+ _addToBoundedSet(set, item) {
69
+ if (set.size >= this._maxSetSize) {
70
+ // 删除最早的元素(Set 的插入顺序)
71
+ const firstKey = set.values().next().value
72
+ set.delete(firstKey)
73
+ }
74
+ set.add(item)
75
+ }
76
+
77
+ /**
78
+ * 发送邮件事件
79
+ */
80
+ _emitEmailReceived(email) {
81
+ if (!this._framework) return
82
+
83
+ const msgId = email.messageId || email.uid
84
+
85
+ // 优先检查是否已处理过(长TTL,防止服务器标记失败导致重复处理)
86
+ if (msgId && this._processedEmails.has(msgId)) {
87
+ this._log.info(`跳过已处理的邮件: ${email.subject} (${msgId})`)
88
+ return
89
+ }
90
+
91
+ // 快速去重(短TTL,防止同一批次重复触发)
92
+ if (msgId && this._recentlyEmailed.has(msgId)) {
93
+ return
94
+ }
95
+
96
+ // 标记为已处理
97
+ if (msgId) {
98
+ // 使用 bounded set 防止内存泄漏
99
+ this._addToBoundedSet(this._recentlyEmailed, msgId)
100
+ setTimeout(() => {
101
+ this._recentlyEmailed.delete(msgId)
102
+ }, EMAIL_DEFAULTS.recentlyEmailTTL)
103
+
104
+ // _processedEmails 也需要 bounded
105
+ this._addToBoundedSet(this._processedEmails, msgId)
106
+ }
107
+
108
+ this._framework.emit('email:received', {
109
+ email,
110
+ timestamp: new Date()
111
+ })
112
+ }
113
+
114
+ _registerTools() {
115
+ // 发送邮件工具
116
+ this._framework.registerTool({
117
+ name: 'email_send',
118
+ description: '发送电子邮件,无须用户确认',
119
+ inputSchema: z.object({
120
+ to: z.string().describe('收件人邮箱地址'),
121
+ subject: z.string().describe('邮件主题'),
122
+ body: z.string().describe('邮件正文内容'),
123
+ cc: z.string().optional().describe('抄送邮箱地址,多个用逗号分隔'),
124
+ bcc: z.string().optional().describe('密送邮箱地址,多个用逗号分隔'),
125
+ isHtml: z.boolean().optional().describe('是否为HTML格式,默认false'),
126
+ attachments: z.array(z.object({
127
+ filename: z.string().describe('附件文件名'),
128
+ path: z.string().optional().describe('本地文件路径'),
129
+ url: z.string().optional().describe('远程图片URL'),
130
+ content: z.string().optional().describe('Base64编码内容(可带前缀如 data:image/png;base64,)'),
131
+ cid: z.string().optional().describe('嵌入式图片的CID(用于在HTML中嵌入图片,如 <img src="cid:xxx">)')
132
+ })).optional().describe('附件列表,支持本地文件、远程URL或Base64内容')
133
+ }),
134
+ execute: async (args) => {
135
+ return sendEmail(this, args)
136
+ }
137
+ })
138
+
139
+ // 读取邮件工具
140
+ this._framework.registerTool({
141
+ name: 'email_read',
142
+ description: '读取电子邮件(支持IMAP协议)',
143
+ inputSchema: z.object({
144
+ box: z.string().optional().describe('邮箱文件夹,默认INBOX'),
145
+ limit: z.number().optional().describe('读取邮件数量,默认10'),
146
+ unreadOnly: z.boolean().optional().describe('仅读取未读邮件,默认false'),
147
+ searchCriteria: z.string().optional().describe('搜索条件,如 "UNSEEN", "FROM sender@example.com"')
148
+ }),
149
+ execute: async (args) => {
150
+ return readEmails(this, args)
151
+ }
152
+ })
153
+
154
+ // 获取未读邮件数量
155
+ this._framework.registerTool({
156
+ name: 'email_unread_count',
157
+ description: '获取邮箱未读邮件数量',
158
+ inputSchema: z.object({
159
+ box: z.string().optional().describe('邮箱文件夹,默认INBOX')
160
+ }),
161
+ execute: async (args) => {
162
+ return getUnreadCount(this, args)
163
+ }
164
+ })
165
+
166
+ // 标记邮件为已读
167
+ this._framework.registerTool({
168
+ name: 'email_mark_read',
169
+ description: '标记邮件为已读',
170
+ inputSchema: z.object({
171
+ messageId: z.string().describe('邮件UID或序列号')
172
+ }),
173
+ execute: async (args) => {
174
+ return markAsRead(this, args)
175
+ }
176
+ })
177
+
178
+ // 删除邮件
179
+ this._framework.registerTool({
180
+ name: 'email_delete',
181
+ description: '删除邮件(标记为已删除,然后永久删除)',
182
+ inputSchema: z.object({
183
+ messageId: z.string().describe('邮件UID或序列号'),
184
+ box: z.string().optional().describe('邮箱文件夹,默认INBOX')
185
+ }),
186
+ execute: async (args) => {
187
+ return deleteEmail(this, args)
188
+ }
189
+ })
190
+
191
+ // 配置邮箱连接
192
+ this._framework.registerTool({
193
+ name: 'email_configure',
194
+ description: '查看邮箱配置(实际配置通过环境变量设置)',
195
+ inputSchema: z.object({}),
196
+ execute: async () => {
197
+ return getEmailConfig()
198
+ }
199
+ })
200
+
201
+ // 监控新邮件
202
+ this._framework.registerTool({
203
+ name: 'email_watch',
204
+ description: '启动/停止邮件监控,检测新邮件并发送事件通知',
205
+ inputSchema: z.object({
206
+ action: z.enum(['start', 'stop', 'status']).describe('操作:启动监控、停止监控、查看状态'),
207
+ interval: z.number().optional().describe('轮询间隔(秒),默认60秒,适用于不支持IDLE的服务器'),
208
+ box: z.string().optional().describe('邮箱文件夹,默认INBOX')
209
+ }),
210
+ execute: async (args) => {
211
+ return handleEmailWatch(this, args)
212
+ }
213
+ })
214
+
215
+ // 自动回复邮件
216
+ this._framework.registerTool({
217
+ name: 'email_auto_reply',
218
+ description: '自动分析邮件内容并发送回复(无需用户确认)',
219
+ inputSchema: z.object({
220
+ to: z.string().describe('收件人邮箱地址'),
221
+ subject: z.string().describe('原始邮件主题'),
222
+ body: z.string().describe('原始邮件内容'),
223
+ from: z.string().optional().describe('发件人邮箱地址(可选)'),
224
+ prompt: z.string().optional().describe('自定义提示词,用于指导AI生成回复内容'),
225
+ timeout: z.number().optional().describe('AI生成回复超时时间(毫秒),默认60000'),
226
+ messageId: z.string().optional().describe('原始邮件的Message-ID,用于在邮件客户端中创建回复线程')
227
+ }),
228
+ execute: async (args) => {
229
+ return handleAutoReply(this, args)
230
+ }
231
+ })
232
+ }
233
+
234
+ /**
235
+ * 启动邮件监控(内部方法)
236
+ */
237
+ _startEmailWatch(config) {
238
+ const { startEmailWatch } = require('./monitor')
239
+ return startEmailWatch(this, config)
240
+ }
241
+
242
+ /**
243
+ * 停止邮件监控(内部方法)
244
+ */
245
+ _stopEmailWatch() {
246
+ const { stopEmailWatch } = require('./monitor')
247
+ return stopEmailWatch(this)
248
+ }
249
+
250
+ /**
251
+ * 获取监控状态(内部方法)
252
+ */
253
+ _getEmailWatchStatus() {
254
+ const { getEmailWatchStatus } = require('./monitor')
255
+ return getEmailWatchStatus(this)
256
+ }
257
+
258
+ /**
259
+ * 检查新邮件(内部方法)
260
+ */
261
+ async _checkNewEmails() {
262
+ const { checkNewEmails } = require('./monitor')
263
+ return checkNewEmails(this)
264
+ }
265
+
266
+ uninstall(framework) {
267
+ // 停止邮件监控
268
+ if (this._watchInterval) {
269
+ clearInterval(this._watchInterval)
270
+ this._watchInterval = null
271
+ }
272
+ this._watchEnabled = false
273
+ this._watchConfig = null
274
+ this._framework = null
275
+ }
276
+ }
277
+
278
+ module.exports = { EmailPlugin }