foliko 1.0.86 → 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 -4310
  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/marknative/index.js +2 -7
  12. package/.agent/plugins/poster-plugin/README.md +304 -0
  13. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  14. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  15. 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
  16. package/.agent/plugins/poster-plugin/index.js +13 -0
  17. package/.agent/plugins/poster-plugin/package.json +28 -0
  18. package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
  19. package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
  20. package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
  21. package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
  22. package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
  23. package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
  24. package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
  25. package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
  26. package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
  27. package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
  28. package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
  29. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
  30. package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
  31. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
  32. package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
  33. package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
  34. package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
  35. package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
  36. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
  37. package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
  38. package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
  39. package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
  40. package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
  41. package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
  42. package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
  43. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
  44. package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
  45. package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
  46. package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
  47. package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
  48. package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
  49. package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
  50. package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
  51. package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
  52. package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
  53. package/.agent/plugins/poster-plugin/src/elements/polygon.js +32 -0
  54. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
  55. package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
  56. package/.agent/plugins/poster-plugin/src/elements/text.js +38 -0
  57. package/.agent/plugins/poster-plugin/src/fonts.js +118 -0
  58. package/.agent/plugins/poster-plugin/src/index.js +1659 -0
  59. package/.agent/plugins/poster-plugin/src/presets.js +36 -0
  60. package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
  61. package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
  62. package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
  63. package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
  64. package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
  65. package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
  66. package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
  67. package/.agent/sessions/cli_default.json +24265 -0
  68. package/.agent/weixin.json +6 -0
  69. package/.claude/settings.local.json +176 -171
  70. package/CLAUDE.md +144 -108
  71. package/docs/CONTEXT_DESIGN.md +1596 -0
  72. package/examples/test-concurrent-chat.js +60 -0
  73. package/examples/test-long-chat.js +77 -0
  74. package/examples/test-session-chat.js +93 -0
  75. package/output/beef-love-poster.png +0 -0
  76. package/package.json +2 -2
  77. package/plugins/default-plugins.js +2 -1
  78. package/plugins/extension-executor-plugin.js +11 -0
  79. package/plugins/memory-plugin.js +984 -0
  80. package/plugins/session-plugin.js +78 -1
  81. package/plugins/weixin-plugin.js +24 -22
  82. package/skills/poster-guide/SKILL.md +743 -0
  83. package/skills/python-plugin-dev/SKILL.md +238 -238
  84. package/skills/skill-guide/SKILL.md +130 -108
  85. package/src/capabilities/skill-manager.js +99 -0
  86. package/src/core/agent-chat.js +627 -180
  87. package/src/core/agent-context.js +188 -0
  88. package/src/core/agent.js +9 -63
  89. package/src/core/context-manager.js +283 -0
  90. package/src/core/framework.js +264 -3
  91. package/src/core/plugin-manager.js +79 -2
  92. package/src/core/request-context.js +98 -0
  93. package/src/core/session-context.js +341 -0
  94. package/src/core/session-storage.js +274 -0
  95. package/src/executors/mcp-executor.js +2 -2
  96. package/src/utils/index.js +239 -67
  97. package/src/utils/plugin-helpers.js +17 -0
  98. package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
  99. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  100. package/.agent/plugins/temp-repo/LICENSE +0 -201
  101. package/.agent/plugins/temp-repo/puppeteer-plugin/README.md +0 -147
  102. package/.agent/plugins/temp-repo/puppeteer-plugin/index.js +0 -1418
  103. package/.agent/plugins/temp-repo/puppeteer-plugin/package.json +0 -9
  104. package/.agent/plugins/test_plugin.py +0 -304
@@ -0,0 +1,188 @@
1
+ /**
2
+ * AgentContext - Agent 级别的上下文封装
3
+ *
4
+ * 职责:
5
+ * 1. 隔离不同 Agent 实例的状态
6
+ * 2. 管理 Agent 级工具注册
7
+ * 3. 管理 Agent 级技能
8
+ * 4. 管理 Agent 级系统提示词
9
+ */
10
+
11
+ class AgentContext {
12
+ /**
13
+ * @param {string} agentId - Agent ID
14
+ * @param {Agent} agent - Agent 实例引用
15
+ * @param {Object} options - 配置选项
16
+ */
17
+ constructor(agentId, agent, options = {}) {
18
+ this.agentId = agentId;
19
+ this.agent = agent; // Agent 实例引用
20
+
21
+ this.name = options.name || agent?.name || agentId;
22
+
23
+ // Agent 级工具注册(覆盖全局)
24
+ this.tools = new Map();
25
+
26
+ // Agent 级技能
27
+ this.skills = [];
28
+
29
+ // Agent 级系统提示词
30
+ this.systemPrompt = null;
31
+
32
+ // 自定义数据
33
+ this.customData = new Map();
34
+
35
+ // 元数据
36
+ this.metadata = {
37
+ createdAt: Date.now(),
38
+ lastActive: Date.now(),
39
+ };
40
+ }
41
+
42
+ // ==================== 工具管理 ====================
43
+
44
+ /**
45
+ * 注册工具
46
+ * @param {Object} toolDef - 工具定义
47
+ */
48
+ registerTool(toolDef) {
49
+ this.tools.set(toolDef.name, toolDef);
50
+ }
51
+
52
+ /**
53
+ * 批量注册工具
54
+ * @param {Array<Object>} toolDefs - 工具定义数组
55
+ */
56
+ registerTools(toolDefs) {
57
+ for (const toolDef of toolDefs) {
58
+ this.registerTool(toolDef);
59
+ }
60
+ }
61
+
62
+ /**
63
+ * 注销工具
64
+ * @param {string} name - 工具名
65
+ */
66
+ unregisterTool(name) {
67
+ this.tools.delete(name);
68
+ }
69
+
70
+ /**
71
+ * 获取工具
72
+ * @param {string} name - 工具名
73
+ * @returns {Object|null}
74
+ */
75
+ getTool(name) {
76
+ return this.tools.get(name) || null;
77
+ }
78
+
79
+ /**
80
+ * 获取所有工具
81
+ * @returns {Array}
82
+ */
83
+ getAllTools() {
84
+ return Array.from(this.tools.values());
85
+ }
86
+
87
+ /**
88
+ * 检查是否有工具
89
+ * @param {string} name - 工具名
90
+ * @returns {boolean}
91
+ */
92
+ hasTool(name) {
93
+ return this.tools.has(name);
94
+ }
95
+
96
+ // ==================== 技能管理 ====================
97
+
98
+ /**
99
+ * 添加技能
100
+ * @param {Object} skill - 技能对象
101
+ */
102
+ addSkill(skill) {
103
+ this.skills.push(skill);
104
+ }
105
+
106
+ /**
107
+ * 移除技能
108
+ * @param {string} skillName - 技能名
109
+ */
110
+ removeSkill(skillName) {
111
+ this.skills = this.skills.filter((s) => s.name !== skillName);
112
+ }
113
+
114
+ /**
115
+ * 获取所有技能
116
+ * @returns {Array}
117
+ */
118
+ getAllSkills() {
119
+ return [...this.skills];
120
+ }
121
+
122
+ // ==================== 系统提示词 ====================
123
+
124
+ /**
125
+ * 设置系统提示词
126
+ * @param {string} prompt - 提示词
127
+ */
128
+ setSystemPrompt(prompt) {
129
+ this.systemPrompt = prompt;
130
+ }
131
+
132
+ /**
133
+ * 获取系统提示词
134
+ * @returns {string|null}
135
+ */
136
+ getSystemPrompt() {
137
+ return this.systemPrompt;
138
+ }
139
+
140
+ // ==================== 自定义数据 ====================
141
+
142
+ /**
143
+ * 设置自定义数据
144
+ * @param {string} key - 键
145
+ * @param {*} value - 值
146
+ */
147
+ setCustomData(key, value) {
148
+ this.customData.set(key, value);
149
+ }
150
+
151
+ /**
152
+ * 获取自定义数据
153
+ * @param {string} key - 键
154
+ * @param {*} defaultValue - 默认值
155
+ * @returns {*}
156
+ */
157
+ getCustomData(key, defaultValue = undefined) {
158
+ return this.customData.get(key) ?? defaultValue;
159
+ }
160
+
161
+ /**
162
+ * 删除自定义数据
163
+ * @param {string} key - 键
164
+ */
165
+ deleteCustomData(key) {
166
+ this.customData.delete(key);
167
+ }
168
+
169
+ // ==================== 生命周期 ====================
170
+
171
+ /**
172
+ * 更新最后活跃时间
173
+ */
174
+ touch() {
175
+ this.metadata.lastActive = Date.now();
176
+ }
177
+
178
+ /**
179
+ * 销毁
180
+ */
181
+ destroy() {
182
+ this.tools.clear();
183
+ this.skills = [];
184
+ this.customData.clear();
185
+ }
186
+ }
187
+
188
+ module.exports = { AgentContext };
package/src/core/agent.js CHANGED
@@ -53,10 +53,6 @@ class Agent extends EventEmitter {
53
53
  // 子Agent管理
54
54
  this._subAgents = new Map();
55
55
 
56
- // 消息队列(用于 pushMessage)
57
- this._messageQueue = [];
58
- this._isProcessingQueue = false;
59
-
60
56
  // System prompt 构建器
61
57
  this._systemPromptBuilder = new SystemPromptBuilder();
62
58
  this._registerDefaultPromptParts();
@@ -101,7 +97,7 @@ class Agent extends EventEmitter {
101
97
  });
102
98
 
103
99
  // 4. 工具列表 (优先级 400)
104
- this._systemPromptBuilder.register('tools', 400, () => this._buildToolsDescription());
100
+ //this._systemPromptBuilder.register('tools', 400, () => this._buildToolsDescription());
105
101
 
106
102
  // 5. 技能列表 (优先级 500)
107
103
  this._systemPromptBuilder.register('skills', 500, () => this._buildSkillsDescription());
@@ -526,17 +522,21 @@ class Agent extends EventEmitter {
526
522
  4. **工具优先**:可用工具列表会提供,格式为 toolName(toolArgs)。不确定用哪个工具时,优先调用可能相关的工具。
527
523
  5. **结果导向**:调用工具后,基于返回结果回答,不要重复工具的内部实现细节。
528
524
  6. **多步骤任务**:复杂任务拆解为多个工具调用,逐步完成,每步基于结果决定下一步。
525
+ 7. **步骤未完成必须提示继续**:如果任务需要多步骤操作,在返回前必须明确告知用户当前进度和下一步操作。如果回复内容为空或不完整,必须说明"步骤进行中,请继续"。
529
526
 
530
527
 
531
528
  【响应规范】
532
529
  - 直接给出结论或结果,不说"我需要..."、"我建议..."等铺垫话术
533
530
  - 如果工具返回错误,说明错误原因并给出解决建议
534
531
  - 如果信息不足,先调用工具获取必要信息,不要假设或猜测
532
+ - **重要:如果任务需要多步骤操作,在回复末尾必须提示用户"请继续"或"是否继续下一步"**
533
+
535
534
 
536
535
  【禁止事项】
537
536
  - 不调用工具就直接回答
538
537
  - 编造不存在的数据、文件、订单、用户等信息
539
- - 回复含糊不清,让用户无法确定答案是否正确`;
538
+ - 回复含糊不清,让用户无法确定答案是否正确
539
+ - **多步骤任务未完成就结束,不提示用户继续**`;
540
540
  }
541
541
 
542
542
  /**
@@ -734,10 +734,6 @@ class Agent extends EventEmitter {
734
734
  * 发送消息
735
735
  */
736
736
  async chat(message, options = {}) {
737
- if (this._status === 'busy') {
738
- throw new Error('Agent is busy');
739
- }
740
-
741
737
  if (this._status === 'error') {
742
738
  this._status = 'idle';
743
739
  }
@@ -755,21 +751,16 @@ class Agent extends EventEmitter {
755
751
 
756
752
  this._syncTools();
757
753
 
754
+ // 通过 handler 的 enqueue 处理(自动排队)
758
755
  const result = await this._chatHandler.chat(enhancedMessage, options);
756
+
759
757
  this._status = 'idle';
760
758
  this.emit('status', { status: 'idle' });
761
759
 
762
- // 处理队列中的下一条消息
763
- setImmediate(() => this._processQueue());
764
-
765
760
  return result;
766
761
  } catch (err) {
767
762
  this._status = 'error';
768
763
  this.emit('status', { status: 'error', error: err.message });
769
-
770
- // 发生错误时也要处理队列
771
- setImmediate(() => this._processQueue());
772
-
773
764
  throw err;
774
765
  }
775
766
  }
@@ -789,49 +780,10 @@ class Agent extends EventEmitter {
789
780
  options.sessionId = ctx.sessionId;
790
781
  }
791
782
 
792
- // 如果忙碌,进入队列等待
793
- if (this._status === 'busy') {
794
- const queuedItem = { message, options, resolve: null, reject: null };
795
- const promise = new Promise((resolve, reject) => {
796
- queuedItem.resolve = resolve;
797
- queuedItem.reject = reject;
798
- });
799
- this._messageQueue.push(queuedItem);
800
- // Agent busy, message queued
801
- return promise;
802
- }
803
-
804
- // 空闲则直接处理
783
+ // 直接调用 chat,由 handler 的 enqueue 处理排队
805
784
  return this.chat(message, options);
806
785
  }
807
786
 
808
- /**
809
- * 处理消息队列
810
- * @private
811
- */
812
- async _processQueue() {
813
- if (this._isProcessingQueue || this._messageQueue.length === 0) {
814
- return;
815
- }
816
-
817
- this._isProcessingQueue = true;
818
-
819
- // 强制设置为 idle,确保 this.chat() 能执行
820
- this._status = 'idle';
821
-
822
- while (this._messageQueue.length > 0) {
823
- const item = this._messageQueue.shift();
824
- try {
825
- const result = await this.chat(item.message, item.options);
826
- item.resolve(result);
827
- } catch (err) {
828
- item.reject(err);
829
- }
830
- }
831
-
832
- this._isProcessingQueue = false;
833
- }
834
-
835
787
  /**
836
788
  * 发送消息(流式)
837
789
  */
@@ -861,16 +813,10 @@ class Agent extends EventEmitter {
861
813
  yield* this._chatHandler.chatStream(enhancedMessage, options);
862
814
  this._status = 'idle';
863
815
  this.emit('status', { status: 'idle' });
864
-
865
- // 处理队列中的下一条消息
866
- setImmediate(() => this._processQueue());
867
816
  } catch (err) {
868
817
  this._status = 'error';
869
818
  this.emit('status', { status: 'error', error: err.message });
870
819
 
871
- // 发生错误时也要处理队列
872
- setImmediate(() => this._processQueue());
873
-
874
820
  throw err;
875
821
  }
876
822
  }
@@ -0,0 +1,283 @@
1
+ /**
2
+ * ContextManager - 上下文管理器
3
+ *
4
+ * 职责:
5
+ * 1. 统一管理所有 Context 的生命周期
6
+ * 2. 提供上下文查询接口
7
+ * 3. 处理上下文清理和资源释放
8
+ */
9
+
10
+ const { RequestContext } = require('./request-context');
11
+ const { SessionContext } = require('./session-context');
12
+ const { AgentContext } = require('./agent-context');
13
+
14
+ class ContextManager {
15
+ /**
16
+ * @param {Framework} framework - 框架实例
17
+ */
18
+ constructor(framework) {
19
+ this.framework = framework;
20
+
21
+ // Context 存储
22
+ this._requestContexts = new Map(); // requestId → RequestContext
23
+ this._sessionContexts = new Map(); // sessionId → SessionContext
24
+ this._agentContexts = new Map(); // agentId → AgentContext
25
+
26
+ // 引用计数(用于自动清理)
27
+ this._refCounts = new Map();
28
+
29
+ // 事件转发
30
+ this._setupEventForwarding();
31
+ }
32
+
33
+ /**
34
+ * 设置事件转发
35
+ * @private
36
+ */
37
+ _setupEventForwarding() {
38
+ if (this.framework) {
39
+ this.framework.on('session:context-created', (ctx) => {
40
+ // 可以在这里添加日志、监控等
41
+ });
42
+ this.framework.on('session:context-destroyed', (ctx) => {
43
+ // 可以在这里添加清理逻辑
44
+ });
45
+ }
46
+ }
47
+
48
+ // ==================== Request Context ====================
49
+
50
+ /**
51
+ * 创建 Request Context
52
+ * @param {Object} options - 请求选项
53
+ * @returns {RequestContext}
54
+ */
55
+ createRequestContext(options = {}) {
56
+ const ctx = new RequestContext(options);
57
+ this._requestContexts.set(ctx.requestId, ctx);
58
+ this._refCounts.set(`request:${ctx.requestId}`, 1);
59
+ return ctx;
60
+ }
61
+
62
+ /**
63
+ * 获取 Request Context
64
+ * @param {string} requestId - 请求 ID
65
+ * @returns {RequestContext|null}
66
+ */
67
+ getRequestContext(requestId) {
68
+ return this._requestContexts.get(requestId) || null;
69
+ }
70
+
71
+ /**
72
+ * 释放 Request Context
73
+ * @param {string} requestId - 请求 ID
74
+ */
75
+ releaseRequestContext(requestId) {
76
+ const ctx = this._requestContexts.get(requestId);
77
+ if (ctx) {
78
+ ctx.cancel();
79
+ this._requestContexts.delete(requestId);
80
+ this._refCounts.delete(`request:${requestId}`);
81
+ }
82
+ }
83
+
84
+ /**
85
+ * 增加 Request Context 引用计数
86
+ * @param {string} requestId - 请求 ID
87
+ */
88
+ retainRequestContext(requestId) {
89
+ const key = `request:${requestId}`;
90
+ this._refCounts.set(key, (this._refCounts.get(key) || 0) + 1);
91
+ }
92
+
93
+ // ==================== Session Context ====================
94
+
95
+ /**
96
+ * 获取或创建 Session Context
97
+ * @param {string} sessionId - 会话 ID
98
+ * @param {Object} options - 配置选项
99
+ * @returns {SessionContext}
100
+ */
101
+ getOrCreateSessionContext(sessionId, options = {}) {
102
+ let ctx = this._sessionContexts.get(sessionId);
103
+ if (!ctx) {
104
+ ctx = new SessionContext(sessionId, this.framework, options);
105
+ this._sessionContexts.set(sessionId, ctx);
106
+ this._refCounts.set(`session:${sessionId}`, 1);
107
+ } else {
108
+ // 增加引用计数
109
+ const key = `session:${sessionId}`;
110
+ this._refCounts.set(key, (this._refCounts.get(key) || 0) + 1);
111
+ }
112
+ return ctx;
113
+ }
114
+
115
+ /**
116
+ * 获取 Session Context
117
+ * @param {string} sessionId - 会话 ID
118
+ * @returns {SessionContext|null}
119
+ */
120
+ getSessionContext(sessionId) {
121
+ return this._sessionContexts.get(sessionId) || null;
122
+ }
123
+
124
+ /**
125
+ * 释放 Session Context(减少引用计数)
126
+ * @param {string} sessionId - 会话 ID
127
+ * @param {boolean} [force=false] - 强制销毁
128
+ */
129
+ releaseSessionContext(sessionId, force = false) {
130
+ const key = `session:${sessionId}`;
131
+ const count = this._refCounts.get(key) || 0;
132
+
133
+ if (force || count <= 1) {
134
+ const ctx = this._sessionContexts.get(sessionId);
135
+ if (ctx) {
136
+ ctx.destroy();
137
+ this.framework.emit('session:context-destroyed', ctx);
138
+ }
139
+ this._sessionContexts.delete(sessionId);
140
+ this._refCounts.delete(key);
141
+ } else {
142
+ this._refCounts.set(key, count - 1);
143
+ }
144
+ }
145
+
146
+ /**
147
+ * 增加 Session Context 引用计数
148
+ * @param {string} sessionId - 会话 ID
149
+ */
150
+ retainSessionContext(sessionId) {
151
+ const key = `session:${sessionId}`;
152
+ this._refCounts.set(key, (this._refCounts.get(key) || 0) + 1);
153
+ }
154
+
155
+ /**
156
+ * 检查 Session Context 是否存在
157
+ * @param {string} sessionId - 会话 ID
158
+ * @returns {boolean}
159
+ */
160
+ hasSessionContext(sessionId) {
161
+ return this._sessionContexts.has(sessionId);
162
+ }
163
+
164
+ // ==================== Agent Context ====================
165
+
166
+ /**
167
+ * 获取或创建 Agent Context
168
+ * @param {string} agentId - Agent ID
169
+ * @param {Agent} agent - Agent 实例
170
+ * @param {Object} options - 配置选项
171
+ * @returns {AgentContext}
172
+ */
173
+ getOrCreateAgentContext(agentId, agent, options = {}) {
174
+ let ctx = this._agentContexts.get(agentId);
175
+ if (!ctx) {
176
+ ctx = new AgentContext(agentId, agent, options);
177
+ this._agentContexts.set(agentId, ctx);
178
+ }
179
+ return ctx;
180
+ }
181
+
182
+ /**
183
+ * 获取 Agent Context
184
+ * @param {string} agentId - Agent ID
185
+ * @returns {AgentContext|null}
186
+ */
187
+ getAgentContext(agentId) {
188
+ return this._agentContexts.get(agentId) || null;
189
+ }
190
+
191
+ /**
192
+ * 删除 Agent Context
193
+ * @param {string} agentId - Agent ID
194
+ */
195
+ removeAgentContext(agentId) {
196
+ const ctx = this._agentContexts.get(agentId);
197
+ if (ctx) {
198
+ ctx.destroy();
199
+ this._agentContexts.delete(agentId);
200
+ }
201
+ }
202
+
203
+ // ==================== 批量操作 ====================
204
+
205
+ /**
206
+ * 销毁所有 Session Context
207
+ */
208
+ destroyAllSessionContexts() {
209
+ for (const [sessionId] of this._sessionContexts) {
210
+ this.releaseSessionContext(sessionId, true);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * 清理过期的 Request Context
216
+ * @param {number} [maxAge=300000] - 最大存活时间(毫秒),默认 5 分钟
217
+ */
218
+ cleanupExpiredRequests(maxAge = 300000) {
219
+ const now = Date.now();
220
+ for (const [requestId, ctx] of this._requestContexts) {
221
+ if (now - ctx.startTime > maxAge) {
222
+ this.releaseRequestContext(requestId);
223
+ }
224
+ }
225
+ }
226
+
227
+ /**
228
+ * 清理所有 Context
229
+ */
230
+ destroyAll() {
231
+ // 清理 Request Contexts
232
+ for (const [requestId] of this._requestContexts) {
233
+ this.releaseRequestContext(requestId);
234
+ }
235
+
236
+ // 清理 Session Contexts
237
+ this.destroyAllSessionContexts();
238
+
239
+ // 清理 Agent Contexts
240
+ for (const [agentId] of this._agentContexts) {
241
+ this.removeAgentContext(agentId);
242
+ }
243
+ }
244
+
245
+ // ==================== 统计 ====================
246
+
247
+ /**
248
+ * 获取统计信息
249
+ * @returns {Object}
250
+ */
251
+ getStats() {
252
+ return {
253
+ activeRequests: this._requestContexts.size,
254
+ activeSessions: this._sessionContexts.size,
255
+ activeAgents: this._agentContexts.size,
256
+ refCounts: Object.fromEntries(this._refCounts),
257
+ };
258
+ }
259
+
260
+ /**
261
+ * 获取内存使用估计
262
+ * @returns {Object}
263
+ */
264
+ getMemoryUsage() {
265
+ let sessionMessagesSize = 0;
266
+ let sessionVariablesSize = 0;
267
+
268
+ for (const ctx of this._sessionContexts.values()) {
269
+ sessionMessagesSize += ctx.messageStore.messages.length;
270
+ sessionVariablesSize += ctx.variables.size;
271
+ }
272
+
273
+ return {
274
+ requestContexts: this._requestContexts.size,
275
+ sessionContexts: this._sessionContexts.size,
276
+ agentContexts: this._agentContexts.size,
277
+ totalSessionMessages: sessionMessagesSize,
278
+ totalSessionVariables: sessionVariablesSize,
279
+ };
280
+ }
281
+ }
282
+
283
+ module.exports = { ContextManager };