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,370 +1,370 @@
1
- /**
2
- * Session 会话管理插件
3
- * 管理多个用户会话,支持会话隔离和历史记录
4
- */
5
-
6
- const { Plugin } = require('../src/core/plugin-base')
7
- const { logger } = require('../src/utils/logger')
8
- const log = logger.child('Session')
9
- const { z } = require('zod')
10
- const { EventEmitter } = require('events')
11
-
12
- /**
13
- * 生成 UUID
14
- */
15
- function generateId() {
16
- if (require('crypto').randomUUID) {
17
- return require('crypto').randomUUID()
18
- }
19
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
20
- const r = Math.random() * 16 | 0
21
- const v = c === 'x' ? r : (r & 0x3 | 0x8)
22
- return v.toString(16)
23
- })
24
- }
25
-
26
- class SessionPlugin extends Plugin {
27
- constructor(config = {}) {
28
- super()
29
- this.name = 'session'
30
- this.version = '1.0.0'
31
- this.description = '会话管理插件,支持多会话隔离、历史记录、会话超时清理'
32
- this.priority = 5
33
-
34
- this.system = true
35
-
36
- this.config = {
37
- sessionTTL: config.sessionTTL || 30 * 60 * 1000, // 30分钟
38
- maxSessions: config.maxSessions || 100,
39
- maxHistoryLength: config.maxHistoryLength || 150, // 放宽到 150,Agent 已有智能压缩
40
- autoCleanup: config.autoCleanup !== false,
41
- cleanupInterval: config.cleanupInterval || 5 * 60 * 1000 // 5分钟
42
- }
43
-
44
- this._framework = null
45
- this._sessions = new Map()
46
- this._cleanupTimer = null
47
- this._events = new EventEmitter()
48
- }
49
-
50
- install(framework) {
51
- this._framework = framework
52
- return this
53
- }
54
-
55
- start(framework) {
56
- // 注册会话管理工具
57
- framework.registerTool({
58
- name: 'session_create',
59
- description: '创建新会话',
60
- inputSchema: z.object({
61
- sessionId: z.string().optional().describe('可选:指定会话 ID'),
62
- metadata: z.object({}).optional().describe('会话元数据')
63
- }),
64
- execute: async (args) => {
65
- const sessionId = args.sessionId || `session_${generateId()}`
66
- const session = this.createSession(sessionId, { metadata: args.metadata })
67
- return {
68
- success: true,
69
- sessionId: session.id,
70
- createdAt: session.createdAt
71
- }
72
- }
73
- })
74
-
75
- framework.registerTool({
76
- name: 'session_get',
77
- description: '获取会话信息',
78
- inputSchema: z.object({
79
- sessionId: z.string().describe('会话 ID')
80
- }),
81
- execute: async (args) => {
82
- const session = this.getSession(args.sessionId)
83
- if (!session) {
84
- return { success: false, error: 'Session not found' }
85
- }
86
- return {
87
- success: true,
88
- sessionId: session.id,
89
- messageCount: session.messages.length,
90
- variables: Object.keys(session.variables),
91
- createdAt: session.createdAt,
92
- lastActive: session.lastActive
93
- }
94
- }
95
- })
96
-
97
- framework.registerTool({
98
- name: 'session_list',
99
- description: '列出所有会话',
100
- inputSchema: z.object({}),
101
- execute: async () => {
102
- const sessions = this.listSessions()
103
- return {
104
- success: true,
105
- sessions,
106
- total: sessions.length
107
- }
108
- }
109
- })
110
-
111
- framework.registerTool({
112
- name: 'session_delete',
113
- description: '删除会话',
114
- inputSchema: z.object({
115
- sessionId: z.string().describe('会话 ID')
116
- }),
117
- execute: async (args) => {
118
- const deleted = this.deleteSession(args.sessionId)
119
- return { success: deleted, deleted: args.sessionId }
120
- }
121
- })
122
-
123
- framework.registerTool({
124
- name: 'session_history',
125
- description: '获取会话历史消息',
126
- inputSchema: z.object({
127
- sessionId: z.string().describe('会话 ID'),
128
- limit: z.number().optional().describe('返回消息数量限制')
129
- }),
130
- execute: async (args) => {
131
- const history = this.getHistory(args.sessionId, args.limit)
132
- return {
133
- success: true,
134
- sessionId: args.sessionId,
135
- messages: history,
136
- count: history.length
137
- }
138
- }
139
- })
140
-
141
- framework.registerTool({
142
- name: 'session_stats',
143
- description: '获取会话统计信息',
144
- inputSchema: z.object({}),
145
- execute: async () => {
146
- return {
147
- success: true,
148
- stats: this.getMemoryStats()
149
- }
150
- }
151
- })
152
-
153
- // 启动自动清理
154
- if (this.config.autoCleanup) {
155
- this._startAutoCleanup()
156
- }
157
-
158
- return this
159
- }
160
-
161
- /**
162
- * 创建新会话
163
- */
164
- createSession(sessionId, options = {}) {
165
- const id = sessionId || `session_${generateId()}`
166
-
167
- if (this._sessions.has(id)) {
168
- return this._sessions.get(id)
169
- }
170
-
171
- // 如果会话数超过限制,清理最老的
172
- if (this._sessions.size >= this.config.maxSessions) {
173
- this._cleanupLRU()
174
- }
175
-
176
- const session = {
177
- id,
178
- messages: options.initialMessages || [],
179
- variables: options.variables || {},
180
- metadata: options.metadata || {},
181
- createdAt: new Date(),
182
- lastActive: new Date()
183
- }
184
-
185
- this._sessions.set(id, session)
186
- return session
187
- }
188
-
189
- /**
190
- * 获取会话
191
- */
192
- getSession(sessionId) {
193
- const session = this._sessions.get(sessionId)
194
- if (session) {
195
- session.lastActive = new Date()
196
- }
197
- return session
198
- }
199
-
200
- /**
201
- * 获取或创建会话
202
- */
203
- getOrCreateSession(sessionId, options = {}) {
204
- let session = this.getSession(sessionId)
205
- if (!session) {
206
- session = this.createSession(sessionId, options)
207
- }
208
- return session
209
- }
210
-
211
- /**
212
- * 添加消息到会话
213
- */
214
- addMessage(sessionId, message) {
215
- const session = this.getSession(sessionId)
216
- if (session) {
217
- session.messages.push(message)
218
- session.lastActive = new Date()
219
-
220
- // 限制历史长度
221
- if (session.messages.length > this.config.maxHistoryLength) {
222
- session.messages = session.messages.slice(-this.config.maxHistoryLength)
223
- }
224
- }
225
- return session
226
- }
227
-
228
- /**
229
- * 获取会话历史
230
- */
231
- getHistory(sessionId, limit = null) {
232
- const session = this.getSession(sessionId)
233
- if (!session) return []
234
-
235
- const messages = session.messages
236
- if (limit) {
237
- return messages.slice(-limit)
238
- }
239
- return messages
240
- }
241
-
242
- /**
243
- * 删除会话
244
- */
245
- deleteSession(sessionId) {
246
- const deleted = this._sessions.delete(sessionId)
247
- if (deleted) {
248
- this._events.emit('session:deleted', sessionId)
249
- }
250
- return deleted
251
- }
252
-
253
- /**
254
- * 列出所有会话
255
- */
256
- listSessions() {
257
- return Array.from(this._sessions.values()).map(s => ({
258
- id: s.id,
259
- messageCount: s.messages.length,
260
- createdAt: s.createdAt,
261
- lastActive: s.lastActive,
262
- metadata: s.metadata
263
- }))
264
- }
265
-
266
- /**
267
- * 清理过期会话
268
- */
269
- cleanup() {
270
- const now = Date.now()
271
- let cleanedCount = 0
272
-
273
- for (const [sessionId, session] of this._sessions) {
274
- if (now - session.lastActive.getTime() > this.config.sessionTTL) {
275
- this._sessions.delete(sessionId)
276
- cleanedCount++
277
- }
278
- }
279
-
280
- return cleanedCount
281
- }
282
-
283
- /**
284
- * LRU 清理 - 删除最老的 20% 会话
285
- */
286
- _cleanupLRU() {
287
- const sessions = Array.from(this._sessions.values())
288
- if (sessions.length === 0) return
289
-
290
- // 按最后活跃时间排序
291
- sessions.sort((a, b) => a.lastActive.getTime() - b.lastActive.getTime())
292
-
293
- // 删除最老的会话
294
- const toDelete = sessions.slice(0, Math.ceil(sessions.length * 0.2))
295
- for (const session of toDelete) {
296
- this._sessions.delete(session.id)
297
- }
298
- }
299
-
300
- /**
301
- * 获取内存统计
302
- */
303
- getMemoryStats() {
304
- const sessionCount = this._sessions.size
305
- const totalMessages = Array.from(this._sessions.values()).reduce(
306
- (sum, s) => sum + s.messages.length, 0
307
- )
308
-
309
- return {
310
- sessionCount,
311
- maxSessions: this.config.maxSessions,
312
- totalMessages,
313
- ttl: this.config.sessionTTL
314
- }
315
- }
316
-
317
- /**
318
- * 清理所有会话
319
- */
320
- clear() {
321
- const sessionIds = Array.from(this._sessions.keys())
322
- this._sessions.clear()
323
- sessionIds.forEach(id => this._events.emit('session:deleted', id))
324
- }
325
-
326
- /**
327
- * 监听会话事件
328
- */
329
- on(event, listener) {
330
- this._events.on(event, listener)
331
- }
332
-
333
- /**
334
- * 移除会话事件监听
335
- */
336
- off(event, listener) {
337
- this._events.off(event, listener)
338
- }
339
-
340
- /**
341
- * 启动自动清理定时器
342
- */
343
- _startAutoCleanup() {
344
- if (this._cleanupTimer) {
345
- clearInterval(this._cleanupTimer)
346
- }
347
- this._cleanupTimer = setInterval(() => {
348
- const cleaned = this.cleanup()
349
- if (cleaned > 0) {
350
- log.info(` Cleaned up ${cleaned} expired sessions`)
351
- }
352
- }, this.config.cleanupInterval)
353
- }
354
-
355
- reload(framework) {
356
- this._framework = framework
357
- }
358
-
359
- uninstall(framework) {
360
- if (this._cleanupTimer) {
361
- clearInterval(this._cleanupTimer)
362
- this._cleanupTimer = null
363
- }
364
- this._events.removeAllListeners()
365
- this._sessions.clear()
366
- this._framework = null
367
- }
368
- }
369
-
1
+ /**
2
+ * Session 会话管理插件
3
+ * 管理多个用户会话,支持会话隔离和历史记录
4
+ */
5
+
6
+ const { Plugin } = require('../src/core/plugin-base')
7
+ const { logger } = require('../src/utils/logger')
8
+ const log = logger.child('Session')
9
+ const { z } = require('zod')
10
+ const { EventEmitter } = require('events')
11
+
12
+ /**
13
+ * 生成 UUID
14
+ */
15
+ function generateId() {
16
+ if (require('crypto').randomUUID) {
17
+ return require('crypto').randomUUID()
18
+ }
19
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
20
+ const r = Math.random() * 16 | 0
21
+ const v = c === 'x' ? r : (r & 0x3 | 0x8)
22
+ return v.toString(16)
23
+ })
24
+ }
25
+
26
+ class SessionPlugin extends Plugin {
27
+ constructor(config = {}) {
28
+ super()
29
+ this.name = 'session'
30
+ this.version = '1.0.0'
31
+ this.description = '会话管理插件,支持多会话隔离、历史记录、会话超时清理'
32
+ this.priority = 5
33
+
34
+ this.system = true
35
+
36
+ this.config = {
37
+ sessionTTL: config.sessionTTL || 30 * 60 * 1000, // 30分钟
38
+ maxSessions: config.maxSessions || 100,
39
+ maxHistoryLength: config.maxHistoryLength || 150, // 放宽到 150,Agent 已有智能压缩
40
+ autoCleanup: config.autoCleanup !== false,
41
+ cleanupInterval: config.cleanupInterval || 5 * 60 * 1000 // 5分钟
42
+ }
43
+
44
+ this._framework = null
45
+ this._sessions = new Map()
46
+ this._cleanupTimer = null
47
+ this._events = new EventEmitter()
48
+ }
49
+
50
+ install(framework) {
51
+ this._framework = framework
52
+ return this
53
+ }
54
+
55
+ start(framework) {
56
+ // 注册会话管理工具
57
+ framework.registerTool({
58
+ name: 'session_create',
59
+ description: '创建新会话',
60
+ inputSchema: z.object({
61
+ sessionId: z.string().optional().describe('可选:指定会话 ID'),
62
+ metadata: z.object({}).optional().describe('会话元数据')
63
+ }),
64
+ execute: async (args) => {
65
+ const sessionId = args.sessionId || `session_${generateId()}`
66
+ const session = this.createSession(sessionId, { metadata: args.metadata })
67
+ return {
68
+ success: true,
69
+ sessionId: session.id,
70
+ createdAt: session.createdAt
71
+ }
72
+ }
73
+ })
74
+
75
+ framework.registerTool({
76
+ name: 'session_get',
77
+ description: '获取会话信息',
78
+ inputSchema: z.object({
79
+ sessionId: z.string().describe('会话 ID')
80
+ }),
81
+ execute: async (args) => {
82
+ const session = this.getSession(args.sessionId)
83
+ if (!session) {
84
+ return { success: false, error: 'Session not found' }
85
+ }
86
+ return {
87
+ success: true,
88
+ sessionId: session.id,
89
+ messageCount: session.messages.length,
90
+ variables: Object.keys(session.variables),
91
+ createdAt: session.createdAt,
92
+ lastActive: session.lastActive
93
+ }
94
+ }
95
+ })
96
+
97
+ framework.registerTool({
98
+ name: 'session_list',
99
+ description: '列出所有会话',
100
+ inputSchema: z.object({}),
101
+ execute: async () => {
102
+ const sessions = this.listSessions()
103
+ return {
104
+ success: true,
105
+ sessions,
106
+ total: sessions.length
107
+ }
108
+ }
109
+ })
110
+
111
+ framework.registerTool({
112
+ name: 'session_delete',
113
+ description: '删除会话',
114
+ inputSchema: z.object({
115
+ sessionId: z.string().describe('会话 ID')
116
+ }),
117
+ execute: async (args) => {
118
+ const deleted = this.deleteSession(args.sessionId)
119
+ return { success: deleted, deleted: args.sessionId }
120
+ }
121
+ })
122
+
123
+ framework.registerTool({
124
+ name: 'session_history',
125
+ description: '获取会话历史消息',
126
+ inputSchema: z.object({
127
+ sessionId: z.string().describe('会话 ID'),
128
+ limit: z.number().optional().describe('返回消息数量限制')
129
+ }),
130
+ execute: async (args) => {
131
+ const history = this.getHistory(args.sessionId, args.limit)
132
+ return {
133
+ success: true,
134
+ sessionId: args.sessionId,
135
+ messages: history,
136
+ count: history.length
137
+ }
138
+ }
139
+ })
140
+
141
+ framework.registerTool({
142
+ name: 'session_stats',
143
+ description: '获取会话统计信息',
144
+ inputSchema: z.object({}),
145
+ execute: async () => {
146
+ return {
147
+ success: true,
148
+ stats: this.getMemoryStats()
149
+ }
150
+ }
151
+ })
152
+
153
+ // 启动自动清理
154
+ if (this.config.autoCleanup) {
155
+ this._startAutoCleanup()
156
+ }
157
+
158
+ return this
159
+ }
160
+
161
+ /**
162
+ * 创建新会话
163
+ */
164
+ createSession(sessionId, options = {}) {
165
+ const id = sessionId || `session_${generateId()}`
166
+
167
+ if (this._sessions.has(id)) {
168
+ return this._sessions.get(id)
169
+ }
170
+
171
+ // 如果会话数超过限制,清理最老的
172
+ if (this._sessions.size >= this.config.maxSessions) {
173
+ this._cleanupLRU()
174
+ }
175
+
176
+ const session = {
177
+ id,
178
+ messages: options.initialMessages || [],
179
+ variables: options.variables || {},
180
+ metadata: options.metadata || {},
181
+ createdAt: new Date(),
182
+ lastActive: new Date()
183
+ }
184
+
185
+ this._sessions.set(id, session)
186
+ return session
187
+ }
188
+
189
+ /**
190
+ * 获取会话
191
+ */
192
+ getSession(sessionId) {
193
+ const session = this._sessions.get(sessionId)
194
+ if (session) {
195
+ session.lastActive = new Date()
196
+ }
197
+ return session
198
+ }
199
+
200
+ /**
201
+ * 获取或创建会话
202
+ */
203
+ getOrCreateSession(sessionId, options = {}) {
204
+ let session = this.getSession(sessionId)
205
+ if (!session) {
206
+ session = this.createSession(sessionId, options)
207
+ }
208
+ return session
209
+ }
210
+
211
+ /**
212
+ * 添加消息到会话
213
+ */
214
+ addMessage(sessionId, message) {
215
+ const session = this.getSession(sessionId)
216
+ if (session) {
217
+ session.messages.push(message)
218
+ session.lastActive = new Date()
219
+
220
+ // 限制历史长度
221
+ if (session.messages.length > this.config.maxHistoryLength) {
222
+ session.messages = session.messages.slice(-this.config.maxHistoryLength)
223
+ }
224
+ }
225
+ return session
226
+ }
227
+
228
+ /**
229
+ * 获取会话历史
230
+ */
231
+ getHistory(sessionId, limit = null) {
232
+ const session = this.getSession(sessionId)
233
+ if (!session) return []
234
+
235
+ const messages = session.messages
236
+ if (limit) {
237
+ return messages.slice(-limit)
238
+ }
239
+ return messages
240
+ }
241
+
242
+ /**
243
+ * 删除会话
244
+ */
245
+ deleteSession(sessionId) {
246
+ const deleted = this._sessions.delete(sessionId)
247
+ if (deleted) {
248
+ this._events.emit('session:deleted', sessionId)
249
+ }
250
+ return deleted
251
+ }
252
+
253
+ /**
254
+ * 列出所有会话
255
+ */
256
+ listSessions() {
257
+ return Array.from(this._sessions.values()).map(s => ({
258
+ id: s.id,
259
+ messageCount: s.messages.length,
260
+ createdAt: s.createdAt,
261
+ lastActive: s.lastActive,
262
+ metadata: s.metadata
263
+ }))
264
+ }
265
+
266
+ /**
267
+ * 清理过期会话
268
+ */
269
+ cleanup() {
270
+ const now = Date.now()
271
+ let cleanedCount = 0
272
+
273
+ for (const [sessionId, session] of this._sessions) {
274
+ if (now - session.lastActive.getTime() > this.config.sessionTTL) {
275
+ this._sessions.delete(sessionId)
276
+ cleanedCount++
277
+ }
278
+ }
279
+
280
+ return cleanedCount
281
+ }
282
+
283
+ /**
284
+ * LRU 清理 - 删除最老的 20% 会话
285
+ */
286
+ _cleanupLRU() {
287
+ const sessions = Array.from(this._sessions.values())
288
+ if (sessions.length === 0) return
289
+
290
+ // 按最后活跃时间排序
291
+ sessions.sort((a, b) => a.lastActive.getTime() - b.lastActive.getTime())
292
+
293
+ // 删除最老的会话
294
+ const toDelete = sessions.slice(0, Math.ceil(sessions.length * 0.2))
295
+ for (const session of toDelete) {
296
+ this._sessions.delete(session.id)
297
+ }
298
+ }
299
+
300
+ /**
301
+ * 获取内存统计
302
+ */
303
+ getMemoryStats() {
304
+ const sessionCount = this._sessions.size
305
+ const totalMessages = Array.from(this._sessions.values()).reduce(
306
+ (sum, s) => sum + s.messages.length, 0
307
+ )
308
+
309
+ return {
310
+ sessionCount,
311
+ maxSessions: this.config.maxSessions,
312
+ totalMessages,
313
+ ttl: this.config.sessionTTL
314
+ }
315
+ }
316
+
317
+ /**
318
+ * 清理所有会话
319
+ */
320
+ clear() {
321
+ const sessionIds = Array.from(this._sessions.keys())
322
+ this._sessions.clear()
323
+ sessionIds.forEach(id => this._events.emit('session:deleted', id))
324
+ }
325
+
326
+ /**
327
+ * 监听会话事件
328
+ */
329
+ on(event, listener) {
330
+ this._events.on(event, listener)
331
+ }
332
+
333
+ /**
334
+ * 移除会话事件监听
335
+ */
336
+ off(event, listener) {
337
+ this._events.off(event, listener)
338
+ }
339
+
340
+ /**
341
+ * 启动自动清理定时器
342
+ */
343
+ _startAutoCleanup() {
344
+ if (this._cleanupTimer) {
345
+ clearInterval(this._cleanupTimer)
346
+ }
347
+ this._cleanupTimer = setInterval(() => {
348
+ const cleaned = this.cleanup()
349
+ if (cleaned > 0) {
350
+ log.info(` Cleaned up ${cleaned} expired sessions`)
351
+ }
352
+ }, this.config.cleanupInterval)
353
+ }
354
+
355
+ reload(framework) {
356
+ this._framework = framework
357
+ }
358
+
359
+ uninstall(framework) {
360
+ if (this._cleanupTimer) {
361
+ clearInterval(this._cleanupTimer)
362
+ this._cleanupTimer = null
363
+ }
364
+ this._events.removeAllListeners()
365
+ this._sessions.clear()
366
+ this._framework = null
367
+ }
368
+ }
369
+
370
370
  module.exports = { SessionPlugin }