foliko 1.0.75 → 1.0.77

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 (89) hide show
  1. package/.claude/settings.local.json +159 -157
  2. package/.env.example +3 -1
  3. package/cli/bin/foliko.js +12 -12
  4. package/cli/src/commands/chat.js +143 -143
  5. package/cli/src/commands/list.js +93 -93
  6. package/cli/src/index.js +75 -75
  7. package/cli/src/ui/chat-ui.js +201 -201
  8. package/cli/src/utils/ansi.js +40 -40
  9. package/cli/src/utils/markdown.js +292 -292
  10. package/examples/ambient-example.js +194 -194
  11. package/examples/basic.js +115 -115
  12. package/examples/bootstrap.js +121 -121
  13. package/examples/mcp-example.js +56 -56
  14. package/examples/skill-example.js +49 -49
  15. package/examples/test-chat.js +137 -137
  16. package/examples/test-mcp.js +85 -85
  17. package/examples/test-reload.js +59 -59
  18. package/examples/test-telegram.js +50 -50
  19. package/examples/test-tg-bot.js +45 -45
  20. package/examples/test-tg-simple.js +47 -47
  21. package/examples/test-tg.js +62 -62
  22. package/examples/test-think.js +43 -43
  23. package/examples/test-web-plugin.js +103 -103
  24. package/examples/test-weixin-feishu.js +103 -103
  25. package/examples/workflow.js +158 -158
  26. package/package.json +81 -81
  27. package/plugins/ai-plugin.js +102 -102
  28. package/plugins/ambient-agent/EventWatcher.js +113 -113
  29. package/plugins/ambient-agent/ExplorerLoop.js +640 -640
  30. package/plugins/ambient-agent/GoalManager.js +197 -197
  31. package/plugins/ambient-agent/Reflector.js +95 -95
  32. package/plugins/ambient-agent/StateStore.js +90 -90
  33. package/plugins/ambient-agent/constants.js +101 -101
  34. package/plugins/ambient-agent/index.js +579 -579
  35. package/plugins/audit-plugin.js +187 -187
  36. package/plugins/default-plugins.js +662 -662
  37. package/plugins/email/constants.js +64 -64
  38. package/plugins/email/handlers.js +461 -461
  39. package/plugins/email/index.js +278 -278
  40. package/plugins/email/monitor.js +269 -269
  41. package/plugins/email/parser.js +138 -138
  42. package/plugins/email/reply.js +151 -151
  43. package/plugins/email/utils.js +124 -124
  44. package/plugins/feishu-plugin.js +481 -481
  45. package/plugins/file-system-plugin.js +826 -826
  46. package/plugins/install-plugin.js +199 -199
  47. package/plugins/python-executor-plugin.js +367 -367
  48. package/plugins/python-plugin-loader.js +481 -481
  49. package/plugins/rules-plugin.js +294 -294
  50. package/plugins/scheduler-plugin.js +691 -691
  51. package/plugins/session-plugin.js +369 -369
  52. package/plugins/shell-executor-plugin.js +197 -197
  53. package/plugins/storage-plugin.js +240 -240
  54. package/plugins/subagent-plugin.js +845 -845
  55. package/plugins/telegram-plugin.js +482 -482
  56. package/plugins/think-plugin.js +345 -345
  57. package/plugins/tools-plugin.js +196 -196
  58. package/plugins/web-plugin.js +606 -606
  59. package/plugins/weixin-plugin.js +545 -545
  60. package/src/capabilities/index.js +11 -11
  61. package/src/capabilities/skill-manager.js +609 -609
  62. package/src/capabilities/workflow-engine.js +1109 -1109
  63. package/src/core/agent-chat.js +882 -882
  64. package/src/core/agent.js +892 -892
  65. package/src/core/framework.js +465 -465
  66. package/src/core/index.js +19 -19
  67. package/src/core/plugin-base.js +219 -219
  68. package/src/core/plugin-manager.js +863 -863
  69. package/src/core/provider.js +114 -114
  70. package/src/core/sub-agent-config.js +264 -264
  71. package/src/core/system-prompt-builder.js +120 -120
  72. package/src/core/tool-registry.js +517 -517
  73. package/src/core/tool-router.js +297 -297
  74. package/src/executors/executor-base.js +58 -58
  75. package/src/executors/mcp-executor.js +741 -741
  76. package/src/index.js +25 -25
  77. package/src/utils/circuit-breaker.js +301 -301
  78. package/src/utils/error-boundary.js +363 -363
  79. package/src/utils/error.js +374 -374
  80. package/src/utils/event-emitter.js +97 -97
  81. package/src/utils/id.js +133 -133
  82. package/src/utils/index.js +217 -217
  83. package/src/utils/logger.js +181 -181
  84. package/src/utils/plugin-helpers.js +90 -90
  85. package/src/utils/retry.js +122 -122
  86. package/src/utils/sandbox.js +292 -292
  87. package/test/tool-registry-validation.test.js +218 -218
  88. package/website/script.js +136 -136
  89. 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 }