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.
- package/.agent/data/default.json +3 -108
- package/.agent/data/plugins-state.json +34 -1
- package/.agent/mcp_config.json +0 -1
- package/.agent/memory/core.md +1 -0
- package/.agent/memory/project/mnn93ogy-ypjn27.md +9 -0
- package/.agent/memory/project/mnn98fqy-5nhc1u.md +25 -0
- package/.agent/memory/user/mnm67t9m-x8rekk.md +9 -0
- package/.agent/memory/user/mnn5mmqh-w6aktx.md +11 -0
- package/.agent/memory/user/mnnbfhhn-dk1bd1.md +22 -0
- package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
- package/.agent/plugins/poster-plugin/README.md +304 -0
- package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
- package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
- 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
- package/.agent/plugins/poster-plugin/index.js +13 -0
- package/.agent/plugins/poster-plugin/package.json +28 -0
- package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
- package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
- package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
- package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
- package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
- package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
- package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
- package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
- package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
- package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
- package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
- package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
- package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
- package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
- package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
- package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
- package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
- package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
- package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
- package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
- package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
- package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
- package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
- package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
- package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
- package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
- package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
- package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
- package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
- package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
- package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
- package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
- package/.agent/plugins/poster-plugin/src/elements/polygon.js +32 -0
- package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
- package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
- package/.agent/plugins/poster-plugin/src/elements/text.js +38 -0
- package/.agent/plugins/poster-plugin/src/fonts.js +118 -0
- package/.agent/plugins/poster-plugin/src/index.js +1659 -0
- package/.agent/plugins/poster-plugin/src/presets.js +36 -0
- package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
- package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
- package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
- package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
- package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
- package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
- package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
- package/.agent/sessions/cli_default.json +24265 -0
- package/.agent/weixin.json +6 -0
- package/.claude/settings.local.json +5 -8
- package/CLAUDE.md +144 -108
- package/docs/CONTEXT_DESIGN.md +1596 -0
- package/examples/test-concurrent-chat.js +60 -60
- package/output/beef-love-poster.png +0 -0
- package/package.json +2 -2
- package/plugins/default-plugins.js +2 -1
- package/plugins/extension-executor-plugin.js +11 -0
- package/plugins/memory-plugin.js +984 -0
- package/plugins/session-plugin.js +57 -1
- package/plugins/weixin-plugin.js +24 -22
- package/skills/poster-guide/SKILL.md +743 -0
- package/skills/python-plugin-dev/SKILL.md +238 -238
- package/skills/skill-guide/SKILL.md +130 -108
- package/src/capabilities/skill-manager.js +99 -0
- package/src/core/agent-chat.js +538 -138
- package/src/core/agent-context.js +188 -0
- package/src/core/agent.js +6 -2
- package/src/core/context-manager.js +283 -0
- package/src/core/framework.js +264 -3
- package/src/core/plugin-manager.js +79 -2
- package/src/core/request-context.js +98 -0
- package/src/core/session-context.js +341 -0
- package/src/core/session-storage.js +274 -0
- package/src/executors/mcp-executor.js +2 -2
- package/src/utils/index.js +239 -67
- package/src/utils/plugin-helpers.js +17 -0
- package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
- package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
- package/.agent/plugins/temp-repo/LICENSE +0 -201
- package/.agent/plugins/temp-repo/puppeteer-plugin/README.md +0 -147
- package/.agent/plugins/temp-repo/puppeteer-plugin/index.js +0 -1418
- package/.agent/plugins/temp-repo/puppeteer-plugin/package.json +0 -9
- package/.agent/plugins/test_plugin.py +0 -304
- package/examples/test-chat-debug.js +0 -102
- package/examples/test-chat-result.js +0 -76
- package/examples/test-chat-stream-diff.js +0 -63
|
@@ -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
|
@@ -97,7 +97,7 @@ class Agent extends EventEmitter {
|
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
// 4. 工具列表 (优先级 400)
|
|
100
|
-
this._systemPromptBuilder.register('tools', 400, () => this._buildToolsDescription());
|
|
100
|
+
//this._systemPromptBuilder.register('tools', 400, () => this._buildToolsDescription());
|
|
101
101
|
|
|
102
102
|
// 5. 技能列表 (优先级 500)
|
|
103
103
|
this._systemPromptBuilder.register('skills', 500, () => this._buildSkillsDescription());
|
|
@@ -522,17 +522,21 @@ class Agent extends EventEmitter {
|
|
|
522
522
|
4. **工具优先**:可用工具列表会提供,格式为 toolName(toolArgs)。不确定用哪个工具时,优先调用可能相关的工具。
|
|
523
523
|
5. **结果导向**:调用工具后,基于返回结果回答,不要重复工具的内部实现细节。
|
|
524
524
|
6. **多步骤任务**:复杂任务拆解为多个工具调用,逐步完成,每步基于结果决定下一步。
|
|
525
|
+
7. **步骤未完成必须提示继续**:如果任务需要多步骤操作,在返回前必须明确告知用户当前进度和下一步操作。如果回复内容为空或不完整,必须说明"步骤进行中,请继续"。
|
|
525
526
|
|
|
526
527
|
|
|
527
528
|
【响应规范】
|
|
528
529
|
- 直接给出结论或结果,不说"我需要..."、"我建议..."等铺垫话术
|
|
529
530
|
- 如果工具返回错误,说明错误原因并给出解决建议
|
|
530
531
|
- 如果信息不足,先调用工具获取必要信息,不要假设或猜测
|
|
532
|
+
- **重要:如果任务需要多步骤操作,在回复末尾必须提示用户"请继续"或"是否继续下一步"**
|
|
533
|
+
|
|
531
534
|
|
|
532
535
|
【禁止事项】
|
|
533
536
|
- 不调用工具就直接回答
|
|
534
537
|
- 编造不存在的数据、文件、订单、用户等信息
|
|
535
|
-
-
|
|
538
|
+
- 回复含糊不清,让用户无法确定答案是否正确
|
|
539
|
+
- **多步骤任务未完成就结束,不提示用户继续**`;
|
|
536
540
|
}
|
|
537
541
|
|
|
538
542
|
/**
|
|
@@ -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 };
|