foliko 1.0.40 → 1.0.43

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.
@@ -9,343 +9,396 @@
9
9
 
10
10
  const { Plugin } = require('../src/core/plugin-base')
11
11
  const { z } = require('zod')
12
-
13
- module.exports = function(Plugin) {
14
- return class WeixinPlugin extends Plugin {
15
- constructor(config = {}) {
16
- super()
17
- this.name = 'weixin'
18
- this.version = '1.0.0'
19
- this.description = '微信对话插件,使用微信网页账号进行对话'
20
- this.priority = 80
21
- // 默认不启用,需要在 plugins.json 中设置 enabled: true
22
- this.enabled = false
23
- this.path=`.agent/data`
24
- this.systemPrompt='你是一个微信助手。回复内容不要使用markdown格式文本'
25
-
26
- this.config = {
27
- forceLogin: config.forceLogin || process.env.WEIXIN_FORCE_LOGIN === 'true',
28
- qrcodeTerminal: config.qrcodeTerminal !== false && process.env.WEIXIN_QRCODE_TERMINAL !== 'false',
29
- allowedUsers: config.allowedUsers || []
30
- }
31
-
32
- this._framework = null
33
- this._bot = null
34
- this._sessionPlugin = null
35
- this._sessionDeleteHandler = null
36
- this._sessionAgents = new Map() // userId -> Agent
37
- this._qrcodeTerminal = null
38
- this._origStderrWrite = null
39
- this._initialized = false
12
+ const { WeixinBot } = require('@chnak/weixin-bot')
13
+
14
+ class WeixinPlugin extends Plugin {
15
+ constructor(config = {}) {
16
+ super()
17
+ this.name = 'weixin'
18
+ this.version = '1.0.0'
19
+ this.description = '微信对话插件,使用微信网页账号进行对话'
20
+ this.priority = 80
21
+ // 默认不启用,需要在 plugins.json 中设置 enabled: true
22
+ this.enabled = false
23
+ this.path=`.agent/data`
24
+ this.systemPrompt=`你是一个微信助手。回复内容不要使用markdown格式文本
25
+
26
+ **命令执行规范:**
27
+ - 执行 npx skills add / npx skills remove / npx skills list 命令时,必须自动添加参数:-a openclaw -y
28
+ - 禁止添加 -g 参数
29
+ - 例如:npx skills add xxx 应该执行为 npx skills add xxx -a openclaw -y`
30
+
31
+ this.config = {
32
+ forceLogin: config.forceLogin || process.env.WEIXIN_FORCE_LOGIN === 'true',
33
+ qrcodeTerminal: config.qrcodeTerminal !== false && process.env.WEIXIN_QRCODE_TERMINAL !== 'false',
34
+ allowedUsers: config.allowedUsers || []
40
35
  }
41
36
 
42
- install(framework) {
43
- this._framework = framework
44
- return this
45
- }
37
+ this._framework = null
38
+ this._bot = null
39
+ this._sessionPlugin = null
40
+ this._sessionDeleteHandler = null
41
+ this._sessionAgents = new Map() // userId -> Agent
42
+ this._qrcodeTerminal = null
43
+ this._origStderrWrite = null
44
+ this._initialized = false
45
+ }
46
46
 
47
- async start(framework) {
48
- // 防止重复初始化
49
- if (this._initialized) return this
50
- this._initialized = true
47
+ install(framework) {
48
+ this._framework = framework
49
+ return this
50
+ }
51
51
 
52
- // 获取 SessionPlugin 引用
53
- this._sessionPlugin = framework.pluginManager.get('session')
52
+ async start(framework) {
53
+ // 防止重复初始化
54
+ if (this._initialized) return this
55
+ this._initialized = true
54
56
 
55
- // 监听 SessionPlugin 的会话删除事件
56
- if (this._sessionPlugin) {
57
- this._sessionDeleteHandler = (sessionId) => {
58
- // 只处理 weixin 会话的删除
59
- if (sessionId.startsWith('weixin_')) {
60
- console.log(`[WeChat] Session deleted: ${sessionId}`)
61
- }
57
+ // 获取 SessionPlugin 引用
58
+ this._sessionPlugin = framework.pluginManager.get('session')
59
+
60
+ // 监听 SessionPlugin 的会话删除事件
61
+ if (this._sessionPlugin) {
62
+ this._sessionDeleteHandler = (sessionId) => {
63
+ // 只处理 weixin 会话的删除
64
+ if (sessionId.startsWith('weixin_')) {
65
+ console.log(`[WeChat] Session deleted: ${sessionId}`)
62
66
  }
63
- this._sessionPlugin.on('session:deleted', this._sessionDeleteHandler)
64
67
  }
68
+ this._sessionPlugin.on('session:deleted', this._sessionDeleteHandler)
69
+ }
65
70
 
66
- // 异步初始化 Bot
67
- this._initBotAsync().catch(err => {
68
- console.error('[WeChat] Failed to initialize bot:', err.message)
71
+ // 监听定时提醒事件
72
+ if (this._framework) {
73
+ this._framework.on('scheduler:reminder', async (data) => {
74
+ console.log('[WeChat] Received scheduler reminder:', data)
75
+ await this._handleScheduledReminder(data)
69
76
  })
70
- return this
71
77
  }
72
78
 
73
- async _initBotAsync() {
79
+ // 异步初始化 Bot
80
+ this._initBotAsync().catch(err => {
81
+ console.error('[WeChat] Failed to initialize bot:', err.message)
82
+ })
83
+ return this
84
+ }
85
+
86
+ async _initBotAsync() {
74
87
 
75
- let WeixinBot
88
+ // 如果启用终端二维码渲染
89
+ if (this.config.qrcodeTerminal) {
76
90
  try {
77
- const module = await import('@chnak/weixin-bot')
78
- WeixinBot = module.WeixinBot
91
+ this._qrcodeTerminal = require('qrcode-terminal')
92
+ this._interceptQRCode()
79
93
  } catch (err) {
80
- console.warn('[WeChat] Failed to load @chnak/weixin-bot:', err.message)
81
- console.warn('[WeChat] Make sure @chnak/weixin-bot is installed: npm install @chnak/weixin-bot qrcode-terminal')
82
- return
94
+ console.warn('[WeChat] qrcode-terminal not installed:', err.message)
83
95
  }
96
+ }
84
97
 
85
- // 如果启用终端二维码渲染
86
- if (this.config.qrcodeTerminal) {
87
- try {
88
- this._qrcodeTerminal = require('qrcode-terminal')
89
- this._interceptQRCode()
90
- } catch (err) {
91
- console.warn('[WeChat] qrcode-terminal not installed:', err.message)
92
- }
93
- }
94
-
95
- this._bot = new WeixinBot({
96
- tokenPath:`${this.path}/${this.name}.json`,
97
- onError: (err) => {
98
- console.error('[WeChat] Error:', err instanceof Error ? err.stack ?? err.message : String(err))
99
- },
100
- })
101
-
102
- const loginOptions = { force: this.config.forceLogin }
103
- console.log('[WeChat]', this.config.forceLogin ? '强制重新扫码登录...' : '正在登录(已有凭证则自动跳过扫码)...')
98
+ this._bot = new WeixinBot({
99
+ tokenPath:`${this.path}/${this.name}.json`,
100
+ onError: (err) => {
101
+ console.error('[WeChat] Error:', err instanceof Error ? err.stack ?? err.message : String(err))
102
+ },
103
+ })
104
+
105
+ const loginOptions = { force: this.config.forceLogin }
106
+ console.log('[WeChat]', this.config.forceLogin ? '强制重新扫码登录...' : '正在登录(已有凭证则自动跳过扫码)...')
107
+
108
+ const creds = await this._bot.login(loginOptions)
109
+ console.log('[WeChat] 登录成功 — Bot ID:', creds.accountId)
110
+ console.log('[WeChat] 关联用户:', creds.userId)
111
+ console.log('[WeChat] API 地址:', creds.baseUrl)
112
+
113
+ // 注册消息处理
114
+ this._bot.onMessage(async (msg) => {
115
+ await this._handleMessage(msg)
116
+ })
117
+
118
+ // 启动Bot
119
+ await this._bot.run()
120
+ console.log('[WeChat] 开始接收微信消息')
121
+ }
104
122
 
105
- const creds = await this._bot.login(loginOptions)
106
- console.log('[WeChat] 登录成功 Bot ID:', creds.accountId)
107
- console.log('[WeChat] 关联用户:', creds.userId)
108
- console.log('[WeChat] API 地址:', creds.baseUrl)
123
+ /**
124
+ * 拦截 SDK stderr 输出,渲染二维码到终端
125
+ */
126
+ _interceptQRCode() {
127
+ if (!this._qrcodeTerminal) return
128
+
129
+ this._origStderrWrite = process.stderr.write.bind(process.stderr)
130
+ process.stderr.write = ((chunk, ...args) => {
131
+ const str = typeof chunk === 'string' ? chunk : chunk.toString()
132
+ // 检测到登录 URL,渲染二维码
133
+ if (str.startsWith('https://') && str.includes('qrcode=')) {
134
+ const url = str.trim()
135
+ this._qrcodeTerminal.generate(url, { small: true }, (qr) => {
136
+ this._origStderrWrite(qr + '\n')
137
+ })
138
+ }
139
+ return this._origStderrWrite(chunk, ...args)
140
+ })
141
+ }
109
142
 
110
- // 注册消息处理
111
- this._bot.onMessage(async (msg) => {
112
- await this._handleMessage(msg)
113
- })
143
+ /**
144
+ * 获取主Agent
145
+ */
146
+ _getMainAgent() {
147
+ if (this._framework._mainAgent) {
148
+ return this._framework._mainAgent
149
+ }
150
+ const agents = this._framework._agents || []
151
+ return agents.length > 0 ? agents[agents.length - 1] : null
152
+ }
114
153
 
115
- // 启动Bot
116
- await this._bot.run()
117
- console.log('[WeChat] 开始接收微信消息')
154
+ /**
155
+ * 获取或创建会话Agent
156
+ * 使用 SessionPlugin 统一管理会话历史
157
+ */
158
+ _getSessionAgent(userId) {
159
+ // 检查缓存
160
+ if (this._sessionAgents.has(userId)) {
161
+ const agent = this._sessionAgents.get(userId)
162
+ console.log('[WeChat] Reusing cached session agent for userId:', userId)
163
+ return { agent, sessionId: `weixin_${userId}` }
118
164
  }
119
165
 
120
- /**
121
- * 拦截 SDK stderr 输出,渲染二维码到终端
122
- */
123
- _interceptQRCode() {
124
- if (!this._qrcodeTerminal) return
125
-
126
- this._origStderrWrite = process.stderr.write.bind(process.stderr)
127
- process.stderr.write = ((chunk, ...args) => {
128
- const str = typeof chunk === 'string' ? chunk : chunk.toString()
129
- // 检测到登录 URL,渲染二维码
130
- if (str.startsWith('https://') && str.includes('qrcode=')) {
131
- const url = str.trim()
132
- this._qrcodeTerminal.generate(url, { small: true }, (qr) => {
133
- this._origStderrWrite(qr + '\n')
134
- })
135
- }
136
- return this._origStderrWrite(chunk, ...args)
166
+ // 创建新 agent
167
+ const agent = this._framework.createSessionAgent(`weixin_${userId}`, {
168
+ systemPrompt: this.systemPrompt,
169
+ sharedPrompt: `工作目录: {{WORK_DIR}}`,
170
+ metadata: { WORK_DIR: process.cwd() }
171
+ })
172
+ this._sessionAgents.set(userId, agent)
173
+ console.log('[WeChat] Created new session agent for userId:', userId)
174
+
175
+ // 使用 SessionPlugin 管理会话历史
176
+ if (this._sessionPlugin) {
177
+ const sessionId = `weixin_${userId}`
178
+ this._sessionPlugin.getOrCreateSession(sessionId, {
179
+ metadata: { platform: 'weixin', userId }
137
180
  })
138
181
  }
139
182
 
140
- /**
141
- * 获取主Agent
142
- */
143
- _getMainAgent() {
144
- if (this._framework._mainAgent) {
145
- return this._framework._mainAgent
146
- }
147
- const agents = this._framework._agents || []
148
- return agents.length > 0 ? agents[agents.length - 1] : null
183
+ console.log(`[WeChat] Session ready for user: ${userId}`)
184
+ return { agent, sessionId: `weixin_${userId}` }
185
+ }
186
+
187
+ /**
188
+ * 处理消息
189
+ */
190
+ async _handleMessage(msg) {
191
+ if (!msg || !msg.userId) return
192
+
193
+ const userId = msg.userId
194
+ // 从 SessionPlugin 获取历史消息数量
195
+ let messageCount = 0
196
+ if (this._sessionPlugin) {
197
+ const session = this._sessionPlugin.getSession(`weixin_${userId}`)
198
+ messageCount = session?.messages?.length || 0
149
199
  }
150
200
 
151
- /**
152
- * 获取或创建会话Agent
153
- * 使用 SessionPlugin 统一管理会话历史
154
- */
155
- _getSessionAgent(userId) {
156
- // 检查缓存
157
- if (this._sessionAgents.has(userId)) {
158
- const agent = this._sessionAgents.get(userId)
159
- console.log('[WeChat] Reusing cached session agent for userId:', userId)
160
- return { agent, sessionId: `weixin_${userId}` }
161
- }
201
+ console.log(`[WeChat] #${messageCount + 1} | 类型: ${msg.type} | 用户: ${userId}`)
202
+ console.log(`[WeChat] 内容: ${msg.text}`)
162
203
 
163
- // 创建新 agent
164
- const agent = this._framework.createSessionAgent(`weixin_${userId}`, {
165
- systemPrompt: this.systemPrompt
166
- })
167
- this._sessionAgents.set(userId, agent)
168
- console.log('[WeChat] Created new session agent for userId:', userId)
204
+ // 非文本消息暂不处理
205
+ if (msg.type !== 'text' || !msg.text) {
206
+ console.log('[WeChat] Unsupported message type or no text')
207
+ return
208
+ }
169
209
 
170
- // 使用 SessionPlugin 管理会话历史
171
- if (this._sessionPlugin) {
172
- const sessionId = `weixin_${userId}`
173
- this._sessionPlugin.getOrCreateSession(sessionId, {
174
- metadata: { platform: 'weixin', userId }
175
- })
176
- }
210
+ const text = msg.text.trim()
211
+ await this._processChat(userId, text, msg)
212
+ }
177
213
 
178
- console.log(`[WeChat] Session ready for user: ${userId}`)
179
- return { agent, sessionId: `weixin_${userId}` }
214
+ /**
215
+ * 处理对话
216
+ */
217
+ async _processChat(userId, text, originalMsg) {
218
+ const sessionInfo = this._getSessionAgent(userId)
219
+ if (!sessionInfo) {
220
+ console.error('[WeChat] No session agent available')
221
+ return
180
222
  }
181
223
 
182
- /**
183
- * 处理消息
184
- */
185
- async _handleMessage(msg) {
186
- if (!msg || !msg.userId) return
224
+ const { agent, sessionId } = sessionInfo
187
225
 
188
- const userId = msg.userId
189
- // SessionPlugin 获取历史消息数量
190
- let messageCount = 0
191
- if (this._sessionPlugin) {
192
- const session = this._sessionPlugin.getSession(`weixin_${userId}`)
193
- messageCount = session?.messages?.length || 0
194
- }
226
+ // 使用 SessionPlugin 添加用户消息到历史
227
+ if (this._sessionPlugin) {
228
+ this._sessionPlugin.addMessage(sessionId, { role: 'user', content: text })
229
+ }
195
230
 
196
- console.log(`[WeChat] #${messageCount + 1} | 类型: ${msg.type} | 用户: ${userId}`)
197
- console.log(`[WeChat] 内容: ${msg.text}`)
231
+ // 发送正在输入状态
232
+ try {
233
+ await this._bot.sendTyping(userId)
234
+ } catch { /* typing 失败不影响回复 */ }
198
235
 
199
- // 非文本消息暂不处理
200
- if (msg.type !== 'text' || !msg.text) {
201
- console.log('[WeChat] Unsupported message type or no text')
202
- return
203
- }
236
+ await new Promise((resolve) => setTimeout(resolve, 1000))
204
237
 
205
- const text = msg.text.trim()
206
- await this._processChat(userId, text, msg)
207
- }
238
+ try {
239
+ let fullResponse = ''
208
240
 
209
- /**
210
- * 处理对话
211
- */
212
- async _processChat(userId, text, originalMsg) {
213
- const sessionInfo = this._getSessionAgent(userId)
214
- if (!sessionInfo) {
215
- console.error('[WeChat] No session agent available')
216
- return
241
+ // 使用流式响应
242
+ for await (const chunk of agent.chatStream(text, {
243
+ sessionId: sessionId
244
+ })) {
245
+ if (chunk.type === 'text' && chunk.text) {
246
+ fullResponse += chunk.text
247
+ }
217
248
  }
218
249
 
219
- const { agent, sessionId } = sessionInfo
220
-
221
- // 使用 SessionPlugin 添加用户消息到历史
250
+ // 保存助手回复到历史(使用 SessionPlugin)
222
251
  if (this._sessionPlugin) {
223
- this._sessionPlugin.addMessage(sessionId, { role: 'user', content: text })
252
+ this._sessionPlugin.addMessage(sessionId, { role: 'assistant', content: fullResponse })
224
253
  }
225
254
 
226
- // 发送正在输入状态
227
- try {
228
- await this._bot.sendTyping(userId)
229
- } catch { /* typing 失败不影响回复 */ }
255
+ // 发送回复
256
+ if (fullResponse) {
257
+ await this._bot.reply(originalMsg, fullResponse)
258
+ console.log(`[WeChat] 回复成功 (${fullResponse.length} 字符)`)
259
+ } else {
260
+ await this._bot.reply(originalMsg, '抱歉,我没有收到有效的回复。')
261
+ }
230
262
 
231
- await new Promise((resolve) => setTimeout(resolve, 1000))
263
+ } catch (err) {
264
+ console.error('[WeChat] Chat error:', err)
265
+ await this._bot.reply(originalMsg, `发生错误:${err.message}`)
266
+ }
267
+ }
232
268
 
233
- try {
234
- let fullResponse = ''
235
-
236
- // 使用流式响应
237
- for await (const chunk of agent.chatStream(text, {
238
- sessionId: sessionId
239
- })) {
240
- if (chunk.type === 'text' && chunk.text) {
241
- fullResponse += chunk.text
242
- }
243
- }
269
+ /**
270
+ * 权限检查
271
+ */
272
+ _checkPermission(userId) {
273
+ if (!this.config.allowedUsers || this.config.allowedUsers.length === 0) {
274
+ return true
275
+ }
276
+ return this.config.allowedUsers.includes(userId)
277
+ }
244
278
 
245
- // 保存助手回复到历史(使用 SessionPlugin)
246
- if (this._sessionPlugin) {
247
- this._sessionPlugin.addMessage(sessionId, { role: 'assistant', content: fullResponse })
248
- }
279
+ /**
280
+ * 清除会话
281
+ */
282
+ _clearSession(userId) {
283
+ // 清除 SessionPlugin 中的会话(会触发 session:deleted 事件)
284
+ if (this._sessionPlugin) {
285
+ const sessionId = `weixin_${userId}`
286
+ this._sessionPlugin.deleteSession(sessionId)
287
+ }
288
+ }
249
289
 
250
- // 发送回复
251
- if (fullResponse) {
252
- await this._bot.reply(originalMsg, fullResponse)
253
- console.log(`[WeChat] 回复成功 (${fullResponse.length} 字符)`)
254
- } else {
255
- await this._bot.reply(originalMsg, '抱歉,我没有收到有效的回复。')
256
- }
290
+ /**
291
+ * 处理定时提醒
292
+ */
293
+ async _handleScheduledReminder(data) {
294
+ const { taskName, message, sessionId } = data
257
295
 
258
- } catch (err) {
259
- console.error('[WeChat] Chat error:', err)
260
- await this._bot.reply(originalMsg, `发生错误:${err.message}`)
261
- }
296
+ if (!this._bot) {
297
+ console.warn('[WeChat] Bot not ready, cannot send reminder')
298
+ return
262
299
  }
263
300
 
264
- /**
265
- * 权限检查
266
- */
267
- _checkPermission(userId) {
268
- if (!this.config.allowedUsers || this.config.allowedUsers.length === 0) {
269
- return true
270
- }
271
- return this.config.allowedUsers.includes(userId)
272
- }
301
+ // 构建提醒消息
302
+ const reminderText = `🔔 [${taskName}]\n\n${message}`
273
303
 
274
- /**
275
- * 清除会话
276
- */
277
- _clearSession(userId) {
278
- // 清除 SessionPlugin 中的会话(会触发 session:deleted 事件)
279
- if (this._sessionPlugin) {
280
- const sessionId = `weixin_${userId}`
281
- this._sessionPlugin.deleteSession(sessionId)
304
+ // 如果有 sessionId 是 weixin 类型的,发送到对应用户
305
+ if (sessionId && sessionId.startsWith('weixin_')) {
306
+ const userId = sessionId.replace('weixin_', '')
307
+ try {
308
+ await this._bot.sendText(userId, reminderText)
309
+ console.log(`[WeChat] Reminder sent to user ${userId}`)
310
+ } catch (err) {
311
+ console.error(`[WeChat] Failed to send reminder:`, err.message)
282
312
  }
313
+ return
283
314
  }
284
315
 
285
- /**
286
- * 获取插件状态
287
- */
288
- getStatus() {
289
- // SessionPlugin 获取 WeChat 相关会话
290
- let sessions = []
291
- if (this._sessionPlugin) {
292
- const allSessions = this._sessionPlugin.listSessions()
293
- sessions = allSessions
294
- .filter(s => s.id.startsWith('weixin_'))
295
- .map(s => ({
296
- userId: s.id.replace('weixin_', ''),
297
- historyLength: s.messageCount,
298
- lastActive: s.lastActive
299
- }))
300
- }
316
+ // 其他情况(包括 null 或其他 sessionId),发送到最近的 WeChat 会话
317
+ if (this._sessionPlugin) {
318
+ const allSessions = this._sessionPlugin.listSessions()
319
+ const weixinSessions = allSessions
320
+ .filter(s => s.id.startsWith('weixin_'))
321
+ .sort((a, b) => new Date(b.lastActive).getTime() - new Date(a.lastActive).getTime())
301
322
 
302
- return {
303
- connected: !!this._bot,
304
- sessionCount: sessions.length,
305
- sessions,
306
- config: {
307
- forceLogin: this.config.forceLogin,
308
- qrcodeTerminal: this.config.qrcodeTerminal
323
+ if (weixinSessions.length > 0) {
324
+ const userId = weixinSessions[0].id.replace('weixin_', '')
325
+ try {
326
+ await this._bot.sendText(userId, reminderText)
327
+ console.log(`[WeChat] Reminder sent to recent user ${userId}`)
328
+ } catch (err) {
329
+ console.error(`[WeChat] Failed to send reminder:`, err.message)
309
330
  }
331
+ } else {
332
+ console.warn('[WeChat] No WeChat session found to send reminder')
310
333
  }
311
334
  }
335
+ }
336
+
337
+ /**
338
+ * 获取插件状态
339
+ */
340
+ getStatus() {
341
+ // 从 SessionPlugin 获取 WeChat 相关会话
342
+ let sessions = []
343
+ if (this._sessionPlugin) {
344
+ const allSessions = this._sessionPlugin.listSessions()
345
+ sessions = allSessions
346
+ .filter(s => s.id.startsWith('weixin_'))
347
+ .map(s => ({
348
+ userId: s.id.replace('weixin_', ''),
349
+ historyLength: s.messageCount,
350
+ lastActive: s.lastActive
351
+ }))
352
+ }
312
353
 
313
- /**
314
- * 停止 Bot
315
- */
316
- stopBot() {
317
- if (this._bot) {
318
- this._bot.stop()
319
- this._bot = null
320
- console.log('[WeChat] Bot stopped')
354
+ return {
355
+ connected: !!this._bot,
356
+ sessionCount: sessions.length,
357
+ sessions,
358
+ config: {
359
+ forceLogin: this.config.forceLogin,
360
+ qrcodeTerminal: this.config.qrcodeTerminal
321
361
  }
322
362
  }
363
+ }
323
364
 
324
- reload(framework) {
325
- this._framework = framework
326
- this._initialized = false
327
- this.stopBot()
328
- this.start(framework)
365
+ /**
366
+ * 停止 Bot
367
+ */
368
+ stopBot() {
369
+ if (this._bot) {
370
+ this._bot.stop()
371
+ this._bot = null
372
+ console.log('[WeChat] Bot stopped')
329
373
  }
374
+ }
330
375
 
331
- uninstall(framework) {
332
- // 销毁所有 session agents
333
- for (const agent of this._sessionAgents.values()) {
334
- agent.destroy()
335
- }
336
- this._sessionAgents.clear()
376
+ reload(framework) {
377
+ this._framework = framework
378
+ this._initialized = false
379
+ this.stopBot()
380
+ this.start(framework)
381
+ }
337
382
 
338
- this.stopBot()
339
- if (this._sessionPlugin && this._sessionDeleteHandler) {
340
- this._sessionPlugin.off('session:deleted', this._sessionDeleteHandler)
341
- this._sessionDeleteHandler = null
342
- }
343
- this._sessionPlugin = null
344
- this._framework = null
345
- // 恢复 stderr
346
- if (this._origStderrWrite) {
347
- process.stderr.write = this._origStderrWrite
348
- }
383
+ uninstall(framework) {
384
+ // 销毁所有 session agents
385
+ for (const agent of this._sessionAgents.values()) {
386
+ agent.destroy()
387
+ }
388
+ this._sessionAgents.clear()
389
+
390
+ this.stopBot()
391
+ if (this._sessionPlugin && this._sessionDeleteHandler) {
392
+ this._sessionPlugin.off('session:deleted', this._sessionDeleteHandler)
393
+ this._sessionDeleteHandler = null
394
+ }
395
+ this._sessionPlugin = null
396
+ this._framework = null
397
+ // 恢复 stderr
398
+ if (this._origStderrWrite) {
399
+ process.stderr.write = this._origStderrWrite
349
400
  }
350
401
  }
351
402
  }
403
+
404
+ module.exports = { WeixinPlugin }