foliko 1.0.87 → 1.1.0

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 (104) hide show
  1. package/.agent/data/default.json +3 -108
  2. package/.agent/data/plugins-state.json +34 -1
  3. package/.agent/mcp_config.json +0 -1
  4. package/.agent/memory/core.md +1 -0
  5. package/.agent/memory/project/mnn93ogy-ypjn27.md +9 -0
  6. package/.agent/memory/project/mnn98fqy-5nhc1u.md +25 -0
  7. package/.agent/memory/user/mnm67t9m-x8rekk.md +9 -0
  8. package/.agent/memory/user/mnn5mmqh-w6aktx.md +11 -0
  9. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +22 -0
  10. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  11. package/.agent/plugins/poster-plugin/README.md +304 -0
  12. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  13. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  14. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221/347/262/227/344/275/223.ttf +0 -0
  15. package/.agent/plugins/poster-plugin/index.js +13 -0
  16. package/.agent/plugins/poster-plugin/package.json +28 -0
  17. package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
  18. package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
  19. package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
  20. package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
  21. package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
  22. package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
  23. package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
  24. package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
  25. package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
  26. package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
  27. package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
  28. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
  29. package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
  30. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
  31. package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
  32. package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
  33. package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
  34. package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
  35. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
  36. package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
  37. package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
  38. package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
  39. package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
  40. package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
  41. package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
  42. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
  43. package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
  44. package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
  45. package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
  46. package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
  47. package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
  48. package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
  49. package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
  50. package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
  51. package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
  52. package/.agent/plugins/poster-plugin/src/elements/polygon.js +32 -0
  53. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
  54. package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
  55. package/.agent/plugins/poster-plugin/src/elements/text.js +38 -0
  56. package/.agent/plugins/poster-plugin/src/fonts.js +118 -0
  57. package/.agent/plugins/poster-plugin/src/index.js +1659 -0
  58. package/.agent/plugins/poster-plugin/src/presets.js +36 -0
  59. package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
  60. package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
  61. package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
  62. package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
  63. package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
  64. package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
  65. package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
  66. package/.agent/sessions/cli_default.json +24265 -0
  67. package/.agent/weixin.json +6 -0
  68. package/.claude/settings.local.json +5 -8
  69. package/CLAUDE.md +144 -108
  70. package/docs/CONTEXT_DESIGN.md +1596 -0
  71. package/examples/test-concurrent-chat.js +60 -60
  72. package/output/beef-love-poster.png +0 -0
  73. package/package.json +2 -2
  74. package/plugins/default-plugins.js +2 -1
  75. package/plugins/extension-executor-plugin.js +11 -0
  76. package/plugins/memory-plugin.js +984 -0
  77. package/plugins/session-plugin.js +57 -1
  78. package/plugins/weixin-plugin.js +24 -22
  79. package/skills/poster-guide/SKILL.md +743 -0
  80. package/skills/python-plugin-dev/SKILL.md +238 -238
  81. package/skills/skill-guide/SKILL.md +130 -108
  82. package/src/capabilities/skill-manager.js +99 -0
  83. package/src/core/agent-chat.js +538 -138
  84. package/src/core/agent-context.js +188 -0
  85. package/src/core/agent.js +6 -2
  86. package/src/core/context-manager.js +283 -0
  87. package/src/core/framework.js +264 -3
  88. package/src/core/plugin-manager.js +79 -2
  89. package/src/core/request-context.js +98 -0
  90. package/src/core/session-context.js +341 -0
  91. package/src/core/session-storage.js +274 -0
  92. package/src/executors/mcp-executor.js +2 -2
  93. package/src/utils/index.js +239 -67
  94. package/src/utils/plugin-helpers.js +17 -0
  95. package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
  96. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  97. package/.agent/plugins/temp-repo/LICENSE +0 -201
  98. package/.agent/plugins/temp-repo/puppeteer-plugin/README.md +0 -147
  99. package/.agent/plugins/temp-repo/puppeteer-plugin/index.js +0 -1418
  100. package/.agent/plugins/temp-repo/puppeteer-plugin/package.json +0 -9
  101. package/.agent/plugins/test_plugin.py +0 -304
  102. package/examples/test-chat-debug.js +0 -102
  103. package/examples/test-chat-result.js +0 -76
  104. package/examples/test-chat-stream-diff.js +0 -63
@@ -0,0 +1,341 @@
1
+ /**
2
+ * SessionContext - Session 级别的上下文封装
3
+ *
4
+ * 职责:
5
+ * 1. 管理 Per-Session 的消息存储
6
+ * 2. 管理会话变量(variables)
7
+ * 3. 跟踪会话元数据
8
+ * 4. 处理上下文压缩状态
9
+ * 5. 持久化到文件(可选)
10
+ */
11
+
12
+ const { SessionStorageAdapter, getDefaultAdapter } = require('./session-storage');
13
+
14
+ class SessionContext {
15
+ /**
16
+ * @param {string} sessionId - 会话 ID
17
+ * @param {Framework} framework - 框架实例
18
+ * @param {Object} options - 配置选项
19
+ * @param {Object} [options.metadata] - 初始元数据
20
+ * @param {Object} [options.variables] - 初始变量
21
+ * @param {Array} [options.initialMessages] - 初始消息
22
+ * @param {SessionStorageAdapter} [options.storage] - 存储适配器
23
+ * @param {boolean} [options.autoSave=true] - 是否自动保存
24
+ */
25
+ constructor(sessionId, framework, options = {}) {
26
+ this.sessionId = sessionId;
27
+ this.framework = framework;
28
+
29
+ // 存储适配器
30
+ this._storage = options.storage || getDefaultAdapter();
31
+ this._autoSave = options.autoSave !== false;
32
+
33
+ // 会话变量(可被工具读写)
34
+ this.variables = new Map();
35
+ if (options.variables) {
36
+ for (const [key, value] of Object.entries(options.variables)) {
37
+ this.variables.set(key, value);
38
+ }
39
+ }
40
+
41
+ // 元数据
42
+ this.metadata = {
43
+ createdAt: Date.now(),
44
+ lastActive: Date.now(),
45
+ messageCount: 0,
46
+ compressionCount: 0,
47
+ ...options.metadata,
48
+ };
49
+
50
+ // Per-Session 消息存储
51
+ this.messageStore = {
52
+ messages: options.initialMessages || [], // 对话历史
53
+ historyLoaded: false, // 是否已从持久化加载
54
+ systemPrompt: null, // 当前系统提示词
55
+ };
56
+
57
+ // 压缩状态
58
+ this.compressionState = {
59
+ lastCompressedAt: null,
60
+ lastTokenCount: 0,
61
+ pendingCompression: false,
62
+ };
63
+
64
+ // 自定义数据插槽
65
+ this.customData = new Map();
66
+ }
67
+
68
+ // ==================== 消息管理 ====================
69
+
70
+ /**
71
+ * 获取消息历史
72
+ * @returns {Array} 消息数组
73
+ */
74
+ getMessages() {
75
+ return this.messageStore.messages;
76
+ }
77
+
78
+ /**
79
+ * 添加消息
80
+ * @param {Object} message - 消息对象
81
+ */
82
+ addMessage(message) {
83
+ this.messageStore.messages.push(message);
84
+ this.metadata.messageCount++;
85
+ this.metadata.lastActive = Date.now();
86
+ this._autoSaveIfEnabled();
87
+ }
88
+
89
+ /**
90
+ * 添加多条消息
91
+ * @param {Array} messages - 消息数组
92
+ */
93
+ addMessages(messages) {
94
+ for (const msg of messages) {
95
+ this.messageStore.messages.push(msg);
96
+ this.metadata.messageCount++;
97
+ }
98
+ this.metadata.lastActive = Date.now();
99
+ this._autoSaveIfEnabled();
100
+ }
101
+
102
+ /**
103
+ * 替换所有消息(用于压缩后同步)
104
+ * @param {Array} messages - 新消息数组
105
+ */
106
+ replaceMessages(messages) {
107
+ this.messageStore.messages = messages || [];
108
+ this._autoSaveIfEnabled();
109
+ }
110
+
111
+ /**
112
+ * 清空消息历史
113
+ */
114
+ clearMessages() {
115
+ this.messageStore.messages = [];
116
+ this._autoSaveIfEnabled();
117
+ }
118
+
119
+ /**
120
+ * 如果启用了自动保存,则保存到存储
121
+ * @private
122
+ */
123
+ _autoSaveIfEnabled() {
124
+ if (this._autoSave) {
125
+ this.save();
126
+ }
127
+ }
128
+
129
+ /**
130
+ * 手动保存到存储(立即保存,不 debounce)
131
+ * @returns {Promise}
132
+ */
133
+ async save() {
134
+ const data = this.toJSON();
135
+ await this._storage.saveImmediate(this.sessionId, data);
136
+ }
137
+
138
+ /**
139
+ * 同步加载(用于文件存储)
140
+ * @param {string} sessionId
141
+ * @param {Framework} framework
142
+ * @param {Object} options
143
+ * @returns {SessionContext|null}
144
+ */
145
+ static loadSync(sessionId, framework, options = {}) {
146
+ const storage = options.storage || getDefaultAdapter();
147
+
148
+ // 只有 file 类型支持同步加载
149
+ if (storage.type !== 'file') {
150
+ return null;
151
+ }
152
+
153
+ const fs = require('fs');
154
+ const path = require('path');
155
+ const filePath = path.resolve(process.cwd(), storage.baseDir, `${sessionId}.json`);
156
+
157
+ if (!fs.existsSync(filePath)) {
158
+ return null;
159
+ }
160
+
161
+ try {
162
+ const content = fs.readFileSync(filePath, 'utf-8');
163
+ const data = JSON.parse(content);
164
+
165
+ // 恢复 SessionContext
166
+ const ctx = new SessionContext(sessionId, framework, {
167
+ ...options,
168
+ initialMessages: data.messages || [],
169
+ variables: data.variables || {},
170
+ metadata: data.metadata || {},
171
+ storage,
172
+ });
173
+
174
+ ctx.messageStore.historyLoaded = true;
175
+ return ctx;
176
+ } catch (err) {
177
+ console.error(`[SessionContext] Failed to load sync:`, err.message);
178
+ return null;
179
+ }
180
+ }
181
+
182
+ /**
183
+ * 从存储加载(异步)
184
+ * @param {string} sessionId
185
+ * @param {Framework} framework
186
+ * @param {Object} options
187
+ * @returns {Promise<SessionContext|null>}
188
+ */
189
+ static async load(sessionId, framework, options = {}) {
190
+ const storage = options.storage || getDefaultAdapter();
191
+ const data = await storage.load(sessionId);
192
+
193
+ if (!data) {
194
+ return null;
195
+ }
196
+
197
+ // 恢复 SessionContext
198
+ const ctx = new SessionContext(sessionId, framework, {
199
+ ...options,
200
+ initialMessages: data.messages || [],
201
+ variables: data.variables || {},
202
+ metadata: data.metadata || {},
203
+ });
204
+
205
+ ctx.messageStore.historyLoaded = true;
206
+ return ctx;
207
+ }
208
+
209
+ /**
210
+ * 获取消息数量
211
+ * @returns {number}
212
+ */
213
+ getMessageCount() {
214
+ return this.messageStore.messages.length;
215
+ }
216
+
217
+ // ==================== 变量管理 ====================
218
+
219
+ /**
220
+ * 获取变量
221
+ * @param {string} key - 变量名
222
+ * @param {*} defaultValue - 默认值
223
+ * @returns {*}
224
+ */
225
+ getVariable(key, defaultValue = undefined) {
226
+ return this.variables.get(key) ?? defaultValue;
227
+ }
228
+
229
+ /**
230
+ * 设置变量
231
+ * @param {string} key - 变量名
232
+ * @param {*} value - 变量值
233
+ */
234
+ setVariable(key, value) {
235
+ this.variables.set(key, value);
236
+ this.touch();
237
+ this._autoSaveIfEnabled();
238
+ }
239
+
240
+ /**
241
+ * 删除变量
242
+ * @param {string} key - 变量名
243
+ */
244
+ deleteVariable(key) {
245
+ this.variables.delete(key);
246
+ }
247
+
248
+ /**
249
+ * 获取所有变量
250
+ * @returns {Object}
251
+ */
252
+ getAllVariables() {
253
+ return Object.fromEntries(this.variables);
254
+ }
255
+
256
+ // ==================== 元数据 ====================
257
+
258
+ /**
259
+ * 更新最后活跃时间
260
+ */
261
+ touch() {
262
+ this.metadata.lastActive = Date.now();
263
+ }
264
+
265
+ /**
266
+ * 获取会话摘要
267
+ * @returns {Object}
268
+ */
269
+ getSummary() {
270
+ return {
271
+ sessionId: this.sessionId,
272
+ messageCount: this.metadata.messageCount,
273
+ createdAt: this.metadata.createdAt,
274
+ lastActive: this.metadata.lastActive,
275
+ variables: this.getAllVariables(),
276
+ };
277
+ }
278
+
279
+ // ==================== 压缩状态 ====================
280
+
281
+ /**
282
+ * 更新压缩状态
283
+ * @param {number} tokenCount - 压缩后的 token 数
284
+ */
285
+ recordCompression(tokenCount) {
286
+ this.compressionState.lastCompressedAt = Date.now();
287
+ this.compressionState.lastTokenCount = tokenCount;
288
+ this.metadata.compressionCount++;
289
+ }
290
+
291
+ /**
292
+ * 获取压缩状态
293
+ * @returns {Object}
294
+ */
295
+ getCompressionState() {
296
+ return { ...this.compressionState };
297
+ }
298
+
299
+ // ==================== 历史加载状态 ====================
300
+
301
+ /**
302
+ * 标记为已加载历史
303
+ */
304
+ markHistoryLoaded() {
305
+ this.messageStore.historyLoaded = true;
306
+ }
307
+
308
+ /**
309
+ * 检查是否已加载历史
310
+ * @returns {boolean}
311
+ */
312
+ isHistoryLoaded() {
313
+ return this.messageStore.historyLoaded;
314
+ }
315
+
316
+ // ==================== 生命周期 ====================
317
+
318
+ /**
319
+ * 销毁会话上下文
320
+ */
321
+ destroy() {
322
+ this.variables.clear();
323
+ this.customData.clear();
324
+ this.messageStore.messages = [];
325
+ }
326
+
327
+ /**
328
+ * 导出为 JSON(用于持久化)
329
+ * @returns {Object}
330
+ */
331
+ toJSON() {
332
+ return {
333
+ sessionId: this.sessionId,
334
+ messages: this.messageStore.messages,
335
+ variables: this.getAllVariables(),
336
+ metadata: this.metadata,
337
+ };
338
+ }
339
+ }
340
+
341
+ module.exports = { SessionContext };
@@ -0,0 +1,274 @@
1
+ /**
2
+ * SessionStorageAdapter - Session 持久化存储适配器
3
+ *
4
+ * 支持多种存储后端:
5
+ * - Memory: 内存存储(默认)
6
+ * - File: JSON 文件存储
7
+ * - Future: Database, Redis 等
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ class SessionStorageAdapter {
14
+ /**
15
+ * @param {Object} options - 配置选项
16
+ * @param {string} [options.type='memory'] - 存储类型: 'memory', 'file'
17
+ * @param {string} [options.baseDir='.agent/sessions'] - 文件存储基础目录
18
+ */
19
+ constructor(options = {}) {
20
+ this.type = options.type || 'memory';
21
+ this.baseDir = options.baseDir || '.agent/sessions';
22
+
23
+ if (this.type === 'file') {
24
+ this._ensureDirectory();
25
+ }
26
+
27
+ // 内存存储
28
+ this._memoryStore = new Map();
29
+
30
+ // 写回队列(用于 debounce)
31
+ this._writeQueue = null;
32
+ this._writeTimeout = null;
33
+ }
34
+
35
+ /**
36
+ * 确保目录存在
37
+ * @private
38
+ */
39
+ _ensureDirectory() {
40
+ const dir = path.resolve(process.cwd(), this.baseDir);
41
+ if (!fs.existsSync(dir)) {
42
+ fs.mkdirSync(dir, { recursive: true });
43
+ }
44
+ }
45
+
46
+ /**
47
+ * 获取存储文件路径
48
+ * @param {string} sessionId
49
+ * @returns {string}
50
+ * @private
51
+ */
52
+ _getFilePath(sessionId) {
53
+ return path.resolve(process.cwd(), this.baseDir, `${sessionId}.json`);
54
+ }
55
+
56
+ /**
57
+ * 保存 Session 数据
58
+ * @param {string} sessionId - 会话 ID
59
+ * @param {Object} data - 要保存的数据
60
+ * @returns {Promise}
61
+ */
62
+ async save(sessionId, data) {
63
+ if (this.type === 'memory') {
64
+ this._memoryStore.set(sessionId, data);
65
+ return;
66
+ }
67
+
68
+ if (this.type === 'file') {
69
+ // Debounce 写操作,500ms 内的多次保存合并为一次
70
+ if (this._writeTimeout) {
71
+ clearTimeout(this._writeTimeout);
72
+ }
73
+
74
+ return new Promise((resolve, reject) => {
75
+ this._writeQueue = { sessionId, data };
76
+ this._writeTimeout = setTimeout(async () => {
77
+ try {
78
+ await this._writeToFile(this._writeQueue.sessionId, this._writeQueue.data);
79
+ resolve();
80
+ } catch (err) {
81
+ reject(err);
82
+ } finally {
83
+ this._writeQueue = null;
84
+ this._writeTimeout = null;
85
+ }
86
+ }, 500);
87
+ });
88
+ }
89
+ }
90
+
91
+ /**
92
+ * 立即保存(不 debounce)
93
+ * @param {string} sessionId
94
+ * @param {Object} data
95
+ */
96
+ async saveImmediate(sessionId, data) {
97
+ if (this._writeTimeout) {
98
+ clearTimeout(this._writeTimeout);
99
+ this._writeTimeout = null;
100
+ }
101
+
102
+ if (this.type === 'memory') {
103
+ this._memoryStore.set(sessionId, data);
104
+ return;
105
+ }
106
+
107
+ if (this.type === 'file') {
108
+ await this._writeToFile(sessionId, data);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * 写入文件
114
+ * @param {string} sessionId
115
+ * @param {Object} data
116
+ * @private
117
+ */
118
+ async _writeToFile(sessionId, data) {
119
+ const filePath = this._getFilePath(sessionId);
120
+
121
+ try {
122
+ // 确保目录存在
123
+ const dir = path.dirname(filePath);
124
+ if (!fs.existsSync(dir)) {
125
+ fs.mkdirSync(dir, { recursive: true });
126
+ }
127
+
128
+ const content = JSON.stringify(data, null, 2);
129
+ fs.writeFileSync(filePath, content, 'utf-8');
130
+ } catch (err) {
131
+ console.error(`[SessionStorage] Failed to write ${sessionId}:`, err.message);
132
+ throw err;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * 加载 Session 数据
138
+ * @param {string} sessionId - 会话 ID
139
+ * @returns {Promise<Object|null>}
140
+ */
141
+ async load(sessionId) {
142
+ if (this.type === 'memory') {
143
+ return this._memoryStore.get(sessionId) || null;
144
+ }
145
+
146
+ if (this.type === 'file') {
147
+ const filePath = this._getFilePath(sessionId);
148
+
149
+ if (!fs.existsSync(filePath)) {
150
+ return null;
151
+ }
152
+
153
+ try {
154
+ const content = fs.readFileSync(filePath, 'utf-8');
155
+ return JSON.parse(content);
156
+ } catch (err) {
157
+ console.error(`[SessionStorage] Failed to read ${sessionId}:`, err.message);
158
+ return null;
159
+ }
160
+ }
161
+
162
+ return null;
163
+ }
164
+
165
+ /**
166
+ * 删除 Session 数据
167
+ * @param {string} sessionId - 会话 ID
168
+ * @returns {Promise<boolean>}
169
+ */
170
+ async delete(sessionId) {
171
+ if (this.type === 'memory') {
172
+ return this._memoryStore.delete(sessionId);
173
+ }
174
+
175
+ if (this.type === 'file') {
176
+ const filePath = this._getFilePath(sessionId);
177
+
178
+ if (fs.existsSync(filePath)) {
179
+ try {
180
+ fs.unlinkSync(filePath);
181
+ return true;
182
+ } catch (err) {
183
+ console.error(`[SessionStorage] Failed to delete ${sessionId}:`, err.message);
184
+ return false;
185
+ }
186
+ }
187
+ return false;
188
+ }
189
+
190
+ return false;
191
+ }
192
+
193
+ /**
194
+ * 列出所有 Session ID
195
+ * @returns {Promise<string[]>}
196
+ */
197
+ async list() {
198
+ if (this.type === 'memory') {
199
+ return Array.from(this._memoryStore.keys());
200
+ }
201
+
202
+ if (this.type === 'file') {
203
+ const dir = path.resolve(process.cwd(), this.baseDir);
204
+
205
+ if (!fs.existsSync(dir)) {
206
+ return [];
207
+ }
208
+
209
+ try {
210
+ const files = fs.readdirSync(dir);
211
+ return files.filter((f) => f.endsWith('.json')).map((f) => f.replace(/\.json$/, ''));
212
+ } catch (err) {
213
+ console.error(`[SessionStorage] Failed to list sessions:`, err.message);
214
+ return [];
215
+ }
216
+ }
217
+
218
+ return [];
219
+ }
220
+
221
+ /**
222
+ * 强制刷新所有待处理的写操作
223
+ */
224
+ async flush() {
225
+ if (this._writeTimeout) {
226
+ clearTimeout(this._writeTimeout);
227
+ this._writeTimeout = null;
228
+
229
+ if (this._writeQueue) {
230
+ await this._writeToFile(this._writeQueue.sessionId, this._writeQueue.data);
231
+ this._writeQueue = null;
232
+ }
233
+ }
234
+ }
235
+
236
+ /**
237
+ * 销毁存储适配器
238
+ */
239
+ async destroy() {
240
+ await this.flush();
241
+ this._memoryStore.clear();
242
+ }
243
+ }
244
+
245
+ /**
246
+ * 全局默认存储适配器实例
247
+ */
248
+ let _defaultAdapter = null;
249
+
250
+ /**
251
+ * 获取默认存储适配器
252
+ * @param {Object} options - 配置选项
253
+ * @returns {SessionStorageAdapter}
254
+ */
255
+ function getDefaultAdapter(options = {}) {
256
+ if (!_defaultAdapter) {
257
+ _defaultAdapter = new SessionStorageAdapter(options);
258
+ }
259
+ return _defaultAdapter;
260
+ }
261
+
262
+ /**
263
+ * 设置默认存储适配器
264
+ * @param {SessionStorageAdapter} adapter
265
+ */
266
+ function setDefaultAdapter(adapter) {
267
+ _defaultAdapter = adapter;
268
+ }
269
+
270
+ module.exports = {
271
+ SessionStorageAdapter,
272
+ getDefaultAdapter,
273
+ setDefaultAdapter,
274
+ };
@@ -502,7 +502,7 @@ class MCPExecutorPlugin extends Plugin {
502
502
  _refreshAgentMCPPrompt(agent) {
503
503
  // 检查是否已刷新过(通过检查系统提示词是否已包含 MCP 描述)
504
504
  const existingPrompt = agent._originalPrompt || '';
505
- if (existingPrompt.includes('[MCP Servers]')) {
505
+ if (existingPrompt.includes('MCP Servers')) {
506
506
  return;
507
507
  }
508
508
 
@@ -532,7 +532,7 @@ class MCPExecutorPlugin extends Plugin {
532
532
  return '';
533
533
  }
534
534
 
535
- let desc = '[MCP Servers]\n\n';
535
+ let desc = 'MCP Servers】 工具合集\n\n';
536
536
  desc += '你可以通过 `mcp_call` 工具调用以下 MCP 服务器的工具。\n\n';
537
537
 
538
538
  for (const [serverName, info] of this._clients) {