foliko 1.1.13 → 1.1.14
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/.shared/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
- package/.agent/ARCHITECTURE.md +288 -0
- package/.agent/agents/ambient-agent.md +57 -0
- package/.agent/agents/debugger.md +55 -0
- package/.agent/agents/email-assistant.md +49 -0
- package/.agent/agents/file-manager.md +42 -0
- package/.agent/agents/poster-expert.md +135 -196
- package/.agent/agents/python-developer.md +60 -0
- package/.agent/agents/scheduler.md +59 -0
- package/.agent/agents/web-developer.md +45 -0
- package/.agent/data/default.json +404 -9
- package/.agent/data/plugins-state.json +172 -173
- package/.agent/data/puppeteer-sessions/undefined.json +6 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
- package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
- package/.agent/mcp_config.json +21 -0
- package/.agent/memory/feedback/mnygjgox-ualjip.md +11 -0
- package/.agent/memory/project/mnqx54u5-loqtoe.md +9 -0
- package/.agent/memory/project/mnqx84cv-mx6dmd.md +9 -0
- package/.agent/memory/project/mnsacuyr-hgtk5n.md +20 -0
- package/.agent/memory/project/mnu5hy2x-bjsg7u.md +9 -0
- package/.agent/memory/project/mny28ot4-8qe9au.md +9 -0
- package/.agent/memory/reference/mnre3cww-penbo1.md +9 -0
- package/.agent/memory/reference/mns9wn48-luerua.md +14 -0
- package/.agent/memory/reference/mns9yz5c-thc2s0.md +16 -0
- package/.agent/memory/reference/mnsfy4um-910f1o.md +23 -0
- package/.agent/memory/reference/mnsg37dp-lmfj18.md +32 -0
- package/.agent/memory/reference/mnsll60q-0j911u.md +36 -0
- package/.agent/memory/reference/mnsmlb5y-nej31u.md +16 -0
- package/.agent/memory/reference/mnssle72-yrot96.md +9 -0
- package/.agent/memory/reference/mnygj8nb-bjthmc.md +20 -0
- package/.agent/memory/user/mnsfuon6-l416q1.md +21 -0
- package/.agent/memory/user/mnsg9kut-95m7rf.md +20 -0
- package/.agent/memory/user/mnu2eo1v-yy6fhe.md +9 -0
- package/.agent/memory/user/mnu2etuo-8u8jk8.md +9 -0
- package/.agent/memory/user/mnx0rk6g-gsznjj.md +9 -0
- package/.agent/memory/user/mnyf1riz-4yo5yz.md +9 -0
- package/.agent/plugins/puppeteer-plugin/README.md +147 -0
- package/.agent/plugins/puppeteer-plugin/index.js +1422 -0
- package/.agent/plugins/puppeteer-plugin/package.json +9 -0
- package/.agent/plugins.json +5 -11
- package/.agent/rules/GEMINI.md +273 -0
- package/.agent/rules/allow-rule.md +77 -0
- package/.agent/rules/log-rule.md +83 -0
- package/.agent/rules/security-rule.md +93 -0
- package/.agent/scripts/auto_preview.py +148 -0
- package/.agent/scripts/checklist.py +217 -0
- package/.agent/scripts/session_manager.py +120 -0
- package/.agent/scripts/verify_all.py +327 -0
- package/.agent/sessions/cli_default.json +11 -641
- package/.agent/skills/api-patterns/SKILL.md +81 -0
- package/.agent/skills/api-patterns/api-style.md +42 -0
- package/.agent/skills/api-patterns/auth.md +24 -0
- package/.agent/skills/api-patterns/documentation.md +26 -0
- package/.agent/skills/api-patterns/graphql.md +41 -0
- package/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/.agent/skills/api-patterns/response.md +37 -0
- package/.agent/skills/api-patterns/rest.md +40 -0
- package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/.agent/skills/api-patterns/security-testing.md +122 -0
- package/.agent/skills/api-patterns/trpc.md +41 -0
- package/.agent/skills/api-patterns/versioning.md +22 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +40 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
- package/.agent/skills/architecture/SKILL.md +55 -0
- package/.agent/skills/architecture/context-discovery.md +43 -0
- package/.agent/skills/architecture/examples.md +94 -0
- package/.agent/skills/architecture/pattern-selection.md +68 -0
- package/.agent/skills/architecture/patterns-reference.md +50 -0
- package/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/.agent/skills/clean-code/SKILL.md +201 -0
- package/.agent/skills/doc.md +177 -0
- package/.agent/skills/frontend-design/SKILL.md +418 -0
- package/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/.agent/skills/frontend-design/color-system.md +311 -0
- package/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/.agent/skills/frontend-design/typography-system.md +345 -0
- package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
- package/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/.agent/skills/mcp-builder/SKILL.md +176 -0
- package/.agent/skills/poster-design/SKILL.md +385 -0
- package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
- package/.agent/workflows/brainstorm.md +113 -0
- package/.agent/workflows/create.md +59 -0
- package/.agent/workflows/debug.md +103 -0
- package/.agent/workflows/deploy.md +176 -0
- package/.agent/workflows/enhance.md +63 -0
- package/.agent/workflows/orchestrate.md +237 -0
- package/.agent/workflows/plan.md +89 -0
- package/.agent/workflows/preview.md +81 -0
- package/.agent/workflows/simple-test.md +42 -0
- package/.agent/workflows/status.md +86 -0
- package/.agent/workflows/structured-orchestrate.md +180 -0
- package/.agent/workflows/test.md +144 -0
- package/.agent/workflows/ui-ux-pro-max.md +296 -0
- package/.claude/settings.local.json +23 -1
- package/.env.example +56 -56
- package/README.md +441 -441
- package/cli/src/commands/chat.js +9 -15
- package/cli/src/ui/chat-ui.js +41 -71
- package/package.json +1 -1
- package/plugins/default-plugins.js +5 -5
- package/plugins/file-system-plugin.js +1 -1
- package/plugins/memory-plugin.js +12 -12
- package/plugins/plugin-manager-plugin.js +1 -0
- package/plugins/subagent-plugin.js +55 -1
- package/plugins/telegram-plugin.js +9 -6
- package/plugins/weixin-plugin.js +50 -34
- package/skills/find-skills/AGENTS.md +162 -162
- package/skills/find-skills/SKILL.md +133 -133
- package/src/core/agent-chat.js +460 -1612
- package/src/core/agent.js +53 -134
- package/src/core/chat-session.js +423 -0
- package/src/core/context-compressor.js +473 -0
- package/src/core/context-manager.js +0 -48
- package/src/core/framework.js +95 -68
- package/src/core/index.js +11 -0
- package/src/core/notification-manager.js +125 -0
- package/src/core/subagent.js +295 -0
- package/src/core/token-counter.js +190 -0
- package/src/core/tool-executor.js +270 -0
- package/src/executors/mcp-executor.js +14 -1
- package/system.md +312 -2373
- package/.agent/agents/code-assistant.json +0 -17
- package/.agent/agents/email-assistant.json +0 -14
- package/.agent/agents/file-assistant.json +0 -18
- package/.agent/agents/orchestrator-demo.md +0 -53
- package/.agent/agents/orchestrator.json +0 -7
- package/.agent/agents/system-assistant.json +0 -15
- package/.agent/agents/web-assistant.json +0 -12
- package/.agent/data/email/processed-emails.json +0 -1
- package/.agent/data/scheduler/tasks.json +0 -1
- package/.agent/data/web/web-config.json +0 -5
- package/.agent/memory/feedback/mnv3nu27-3o15pf.md +0 -9
- package/.agent/memory/feedback/mnv3o078-b959yj.md +0 -9
- package/.agent/memory/feedback/mnv3o6ej-u0fif5.md +0 -9
- package/.agent/memory/feedback/mnv3obgl-bkkjoj.md +0 -9
- package/.agent/memory/feedback/mnv4a3js-dv6onx.md +0 -9
- package/.agent/memory/feedback/mnv4aacm-sxxowp.md +0 -9
- package/.agent/memory/feedback/mnv4ahto-w40ffm.md +0 -9
- package/.agent/memory/feedback/mnv4anvp-3cs06y.md +0 -9
- package/.agent/memory/feedback/mnvzgvtd-0o2900.md +0 -9
- package/.agent/memory/feedback/mnvzhajn-swbx61.md +0 -15
- package/.agent/memory/feedback/mnvzhgsp-p5vog3.md +0 -9
- package/.agent/memory/feedback/mnvzho0c-fgql7q.md +0 -14
- package/.agent/memory/feedback/mnvzhtzq-ufr5at.md +0 -9
- package/.agent/memory/feedback/mnvzhyb3-9byq2z.md +0 -9
- package/.agent/memory/feedback/mnvzi7hp-hyeafp.md +0 -9
- package/.agent/memory/feedback/mnvzibph-z7rwp5.md +0 -9
- package/.agent/memory/feedback/mnvzilys-7h176w.md +0 -14
- package/.agent/memory/feedback/mnvziuh5-zjshci.md +0 -9
- package/.agent/memory/feedback/mnw07wde-6zqsc8.md +0 -9
- package/.agent/memory/feedback/mnw084bp-j0ba2a.md +0 -9
- package/.agent/memory/user/mnv3n62r-y0h79j.md +0 -21
- package/.agent/memory/user/mnv3n9yf-ead4g8.md +0 -13
- package/.agent/memory/user/mnv3ne3j-82tq1k.md +0 -19
- package/.agent/memory/user/mnv3nhgm-g2s2us.md +0 -11
- package/.agent/memory/user/mnv3nl9u-ejd998.md +0 -16
- package/.agent/memory/user/mnv3nofp-ya5szl.md +0 -10
- package/.agent/memory/user/mnv49qne-bhk0ki.md +0 -9
- package/.agent/memory/user/mnv49w3y-rzr8ju.md +0 -13
- package/.agent/package.json +0 -8
- package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
- package/.agent/plugins/daytona/README.md +0 -89
- package/.agent/plugins/daytona/index.js +0 -377
- package/.agent/plugins/daytona/package.json +0 -12
- package/.agent/plugins/marknative/README.md +0 -134
- package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
- package/.agent/plugins/marknative/fonts.zip +0 -0
- package/.agent/plugins/marknative/index.js +0 -256
- package/.agent/plugins/marknative/package.json +0 -12
- package/.agent/plugins/system-info/index.js +0 -387
- package/.agent/plugins/system-info/package.json +0 -4
- package/.agent/plugins/system-info/test.js +0 -40
- package/.agent/plugins/test-plugin.py +0 -123
- package/.agent/plugins/test_nested_plugin.py +0 -85
- package/.agent/python-scripts/test_sample.py +0 -24
- package/.agent/sessions/test.json +0 -16
- package/.agent/skills/agent-browser/SKILL.md +0 -311
- package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
- package/.agent/skills/sysinfo/SKILL.md +0 -38
- package/.agent/skills/sysinfo/system-info.sh +0 -130
- package/.agent/skills/workflow/SKILL.md +0 -324
- package/.agent/test-agent.js +0 -35
- package/.agent/weixin.json +0 -6
- package/.agent/workflows/email-digest.json +0 -50
- package/.agent/workflows/file-backup.json +0 -21
- package/.agent/workflows/get-ip-notify.json +0 -32
- package/.agent/workflows/news-aggregator.json +0 -93
- package/.agent/workflows/news-dashboard-v2.json +0 -94
- package/.agent/workflows/notification-batch.json +0 -32
- package/plugins/python-plugin-loader.js.bak +0 -856
- package/src/core/agent-context.js +0 -188
package/src/core/agent.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const { EventEmitter } = require('../utils/event-emitter');
|
|
7
7
|
const { AgentChatHandler } = require('./agent-chat');
|
|
8
8
|
const { SystemPromptBuilder } = require('./system-prompt-builder');
|
|
9
|
+
const { NotificationManager } = require('./notification-manager');
|
|
9
10
|
const { zodSchemaToMarkdown, zodSchemaToTable } = require('@chnak/zod-to-markdown');
|
|
10
11
|
const { zodSchema } = require('ai');
|
|
11
12
|
const os = require('os');
|
|
@@ -120,6 +121,9 @@ class Agent extends EventEmitter {
|
|
|
120
121
|
// 处理后的 system prompt (带上下文)
|
|
121
122
|
this.systemPrompt = this._buildSystemPrompt();
|
|
122
123
|
|
|
124
|
+
// 通知管理器
|
|
125
|
+
this._notificationManager = new NotificationManager(framework);
|
|
126
|
+
|
|
123
127
|
// 初始化聊天处理器
|
|
124
128
|
this._initChatHandler();
|
|
125
129
|
|
|
@@ -246,21 +250,26 @@ class Agent extends EventEmitter {
|
|
|
246
250
|
* 构建工具描述(直接调用的工具)
|
|
247
251
|
*/
|
|
248
252
|
_buildToolsDescription() {
|
|
249
|
-
|
|
253
|
+
const tools = this.framework.getTools();
|
|
254
|
+
if (!tools || tools.length === 0) {
|
|
250
255
|
return '';
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
const directTools = [];
|
|
254
259
|
|
|
255
|
-
for (const
|
|
260
|
+
for (const tool of tools) {
|
|
256
261
|
if (!tool.description) continue;
|
|
257
262
|
|
|
258
263
|
// MCP 和 ext 工具不在这里显示,它们通过专门的描述部分提供
|
|
259
|
-
if (
|
|
264
|
+
if (
|
|
265
|
+
tool.name.startsWith('mcp_') ||
|
|
266
|
+
tool.name.startsWith('ext_') ||
|
|
267
|
+
tool.name.startsWith('workflow_')
|
|
268
|
+
) {
|
|
260
269
|
continue;
|
|
261
270
|
}
|
|
262
271
|
|
|
263
|
-
directTools.push({ name, tool });
|
|
272
|
+
directTools.push({ name: tool.name, tool });
|
|
264
273
|
}
|
|
265
274
|
|
|
266
275
|
if (directTools.length === 0) {
|
|
@@ -610,45 +619,7 @@ class Agent extends EventEmitter {
|
|
|
610
619
|
return '';
|
|
611
620
|
}
|
|
612
621
|
|
|
613
|
-
|
|
614
|
-
const lines = ['## 子 Agent 匹配表', ''];
|
|
615
|
-
lines.push('');
|
|
616
|
-
lines.push('> **提示**:根据任务类型选择最匹配的子 Agent 处理');
|
|
617
|
-
lines.push('');
|
|
618
|
-
|
|
619
|
-
// 动态从配置文件读取每个子Agent的核心能力
|
|
620
|
-
for (const plugin of allSubAgents) {
|
|
621
|
-
const name = plugin.name;
|
|
622
|
-
const role = plugin.role;
|
|
623
|
-
const goal = plugin.description || '';
|
|
624
|
-
|
|
625
|
-
// 优先使用 SubAgentConfigManager 获取详细信息
|
|
626
|
-
const config = this.framework._subAgentConfigManager?.get(name);
|
|
627
|
-
if (config) {
|
|
628
|
-
const agentDesc = config.getDescription();
|
|
629
|
-
const skills = config.getSkills();
|
|
630
|
-
let info = agentDesc || role || goal || '子代理';
|
|
631
|
-
if (skills && skills.length > 0) {
|
|
632
|
-
info += ` (技能: ${skills.join(', ')})`;
|
|
633
|
-
}
|
|
634
|
-
lines.push(`- **${name}**:${info}`);
|
|
635
|
-
} else {
|
|
636
|
-
// 回退到旧逻辑
|
|
637
|
-
lines.push(`- **${name}**:${role || goal || '子代理'}`);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// 通用规则
|
|
642
|
-
lines.push('');
|
|
643
|
-
lines.push('### 子 Agent 调用规则');
|
|
644
|
-
lines.push('');
|
|
645
|
-
lines.push('> **重要**:必须严格遵守以下规则');
|
|
646
|
-
lines.push('');
|
|
647
|
-
lines.push('1. 根据上述「子 Agent 匹配表」,将任务委托给最匹配的子 Agent 处理');
|
|
648
|
-
lines.push('2. 使用 `subagent_call` 工具并指定 `agentName` 来委托任务');
|
|
649
|
-
lines.push('3. 只有当没有匹配的子 Agent 时,才直接调用工具');
|
|
650
|
-
|
|
651
|
-
return lines.join('\n');
|
|
622
|
+
return subAgentManager._buildDescription();
|
|
652
623
|
}
|
|
653
624
|
|
|
654
625
|
/**
|
|
@@ -924,35 +895,38 @@ class Agent extends EventEmitter {
|
|
|
924
895
|
}
|
|
925
896
|
|
|
926
897
|
/**
|
|
927
|
-
* 注册工具到
|
|
898
|
+
* 注册工具到 Framework(统一入口)
|
|
928
899
|
*/
|
|
929
900
|
registerTool(tool) {
|
|
930
|
-
|
|
931
|
-
this.
|
|
901
|
+
// 注册到 framework(统一管理)
|
|
902
|
+
this.framework.registerTool(tool);
|
|
903
|
+
// 注册到 chatHandler
|
|
932
904
|
if (this._chatHandler) {
|
|
933
905
|
this._chatHandler.registerTool(tool);
|
|
934
906
|
}
|
|
907
|
+
this._invalidateSystemPromptCache();
|
|
935
908
|
this._refreshContext();
|
|
936
909
|
return this;
|
|
937
910
|
}
|
|
938
911
|
|
|
939
912
|
/**
|
|
940
|
-
*
|
|
913
|
+
* 获取已注册工具(从 framework 获取)
|
|
941
914
|
*/
|
|
942
915
|
getTools() {
|
|
943
|
-
return
|
|
916
|
+
return this.framework.getTools();
|
|
944
917
|
}
|
|
945
918
|
|
|
946
919
|
/**
|
|
947
|
-
* 同步框架中的工具到
|
|
920
|
+
* 同步框架中的工具到 ChatHandler
|
|
948
921
|
* @private
|
|
949
922
|
*/
|
|
950
923
|
_syncTools() {
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
924
|
+
// 从 framework 获取工具并注册到 chatHandler
|
|
925
|
+
const tools = this.framework.getTools();
|
|
926
|
+
for (const tool of tools) {
|
|
927
|
+
// 直接注册到 chatHandler(registerTool 是幂等的)
|
|
928
|
+
if (this._chatHandler) {
|
|
929
|
+
this._chatHandler.registerTool(tool);
|
|
956
930
|
}
|
|
957
931
|
}
|
|
958
932
|
}
|
|
@@ -988,74 +962,6 @@ class Agent extends EventEmitter {
|
|
|
988
962
|
return this._subAgents;
|
|
989
963
|
}
|
|
990
964
|
|
|
991
|
-
/**
|
|
992
|
-
* 获取待处理的调度通知并清除(下次不再重复显示)
|
|
993
|
-
*/
|
|
994
|
-
_getAndClearSchedulerNotifications() {
|
|
995
|
-
try {
|
|
996
|
-
const scheduler = this.framework.pluginManager.get('scheduler');
|
|
997
|
-
if (scheduler && scheduler.instance && scheduler.instance.getPendingNotifications) {
|
|
998
|
-
const results = scheduler.instance.getPendingNotifications();
|
|
999
|
-
if (results.length > 0) {
|
|
1000
|
-
// 使用常量替代硬编码数字
|
|
1001
|
-
const notifications = results.slice(-AGENT_CONFIG.MAX_NOTIFICATIONS).reverse();
|
|
1002
|
-
// 清除已发送的通知
|
|
1003
|
-
if (scheduler.instance.clearDeliveredNotifications) {
|
|
1004
|
-
scheduler.instance.clearDeliveredNotifications(notifications.length);
|
|
1005
|
-
}
|
|
1006
|
-
return notifications;
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
} catch (err) {
|
|
1010
|
-
logger.warn('Agent', '获取调度通知失败', err.message);
|
|
1011
|
-
}
|
|
1012
|
-
return [];
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
/**
|
|
1016
|
-
* 获取待处理的思考结果并清除
|
|
1017
|
-
*/
|
|
1018
|
-
_getAndClearThinkNotifications() {
|
|
1019
|
-
try {
|
|
1020
|
-
const think = this.framework.pluginManager.get('think');
|
|
1021
|
-
if (think && think.instance && think.instance.getPendingThoughts) {
|
|
1022
|
-
const thoughts = think.instance.getPendingThoughts();
|
|
1023
|
-
if (thoughts.length > 0) {
|
|
1024
|
-
// 使用常量替代硬编码数字
|
|
1025
|
-
return thoughts.slice(-AGENT_CONFIG.MAX_NOTIFICATIONS).reverse();
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
} catch (err) {
|
|
1029
|
-
logger.warn('Agent', '获取思考通知失败', err.message);
|
|
1030
|
-
}
|
|
1031
|
-
return [];
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
/**
|
|
1035
|
-
* 获取所有待处理的系统通知(调度 + 思考)
|
|
1036
|
-
*/
|
|
1037
|
-
_getAllPendingNotifications() {
|
|
1038
|
-
const notifications = [];
|
|
1039
|
-
|
|
1040
|
-
// 调度通知
|
|
1041
|
-
const schedulerNotifs = this._getAndClearSchedulerNotifications();
|
|
1042
|
-
for (const n of schedulerNotifs) {
|
|
1043
|
-
notifications.push(
|
|
1044
|
-
`【定时任务通知】\n任务: ${n.taskName || n.taskId}\n执行时间: ${n.executedAt}\n结果: ${n.result || n.action || '执行完成'}`
|
|
1045
|
-
);
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
// 思考通知
|
|
1049
|
-
const thinkNotifs = this._getAndClearThinkNotifications();
|
|
1050
|
-
for (const t of thinkNotifs) {
|
|
1051
|
-
notifications.push(
|
|
1052
|
-
`【主动思考】\n模式: ${t.mode}\n主题: ${t.topic}\n结果: ${t.result || '思考完成'}`
|
|
1053
|
-
);
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
return notifications;
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
965
|
/**
|
|
1060
966
|
* 发送消息
|
|
1061
967
|
*/
|
|
@@ -1068,12 +974,8 @@ class Agent extends EventEmitter {
|
|
|
1068
974
|
this.emit('status', { status: 'busy' });
|
|
1069
975
|
|
|
1070
976
|
try {
|
|
1071
|
-
//
|
|
1072
|
-
const
|
|
1073
|
-
let enhancedMessage = message;
|
|
1074
|
-
if (notifications.length > 0) {
|
|
1075
|
-
enhancedMessage = `【系统通知】\n${notifications.join('\n\n')}\n\n---\n用户消息: ${message}`;
|
|
1076
|
-
}
|
|
977
|
+
// 使用 NotificationManager 增强消息
|
|
978
|
+
const enhancedMessage = this._notificationManager.enhanceMessage(message);
|
|
1077
979
|
|
|
1078
980
|
// 子agent跳过工具同步,使用createSubAgent时已配置的工具
|
|
1079
981
|
if (!this._skipSyncTools) {
|
|
@@ -1131,12 +1033,8 @@ class Agent extends EventEmitter {
|
|
|
1131
1033
|
this.emit('status', { status: 'busy' });
|
|
1132
1034
|
|
|
1133
1035
|
try {
|
|
1134
|
-
//
|
|
1135
|
-
const
|
|
1136
|
-
let enhancedMessage = message;
|
|
1137
|
-
if (notifications.length > 0) {
|
|
1138
|
-
enhancedMessage = `【系统通知】\n${notifications.join('\n\n')}\n\n---\n用户消息: ${message}`;
|
|
1139
|
-
}
|
|
1036
|
+
// 使用 NotificationManager 增强消息
|
|
1037
|
+
const enhancedMessage = this._notificationManager.enhanceMessage(message);
|
|
1140
1038
|
|
|
1141
1039
|
// 子agent跳过工具同步,使用createSubAgent时已配置的工具
|
|
1142
1040
|
if (!this._skipSyncTools) {
|
|
@@ -1166,6 +1064,27 @@ class Agent extends EventEmitter {
|
|
|
1166
1064
|
return this._chatHandler.sendMessage(message, options);
|
|
1167
1065
|
}
|
|
1168
1066
|
|
|
1067
|
+
/**
|
|
1068
|
+
* 流式发送消息(带队列,支持实时yield)
|
|
1069
|
+
*/
|
|
1070
|
+
async *sendMessageStream(message, options = {}) {
|
|
1071
|
+
yield* this._chatHandler.sendMessageStream(message, options);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* 批量发送消息
|
|
1076
|
+
*/
|
|
1077
|
+
async sendBatch(messages, options = {}) {
|
|
1078
|
+
return this._chatHandler.sendBatch(messages, options);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* 取消会话的所有请求
|
|
1083
|
+
*/
|
|
1084
|
+
cancelSession(sessionId) {
|
|
1085
|
+
return this._chatHandler.cancelSession(sessionId);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1169
1088
|
/**
|
|
1170
1089
|
* 设置元数据
|
|
1171
1090
|
*/
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatSession - 会话管理器
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* 1. 管理 Per-Session 的消息存储
|
|
6
|
+
* 2. 会话消息历史加载/保存
|
|
7
|
+
* 3. 会话消息队列管理
|
|
8
|
+
* 4. SessionScope 事件作用域
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { EventEmitter } = require('../utils/event-emitter');
|
|
12
|
+
const { ChatQueueManager } = require('../utils/chat-queue');
|
|
13
|
+
const { logger } = require('../utils/logger');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Session 作用域的事件监听器
|
|
17
|
+
* 自动过滤只属于特定 sessionId 的事件
|
|
18
|
+
*/
|
|
19
|
+
class SessionScope extends EventEmitter {
|
|
20
|
+
/**
|
|
21
|
+
* @param {ChatSession} session - ChatSession 实例
|
|
22
|
+
* @param {string} sessionId - Session ID
|
|
23
|
+
*/
|
|
24
|
+
constructor(session, sessionId) {
|
|
25
|
+
super();
|
|
26
|
+
this.session = session;
|
|
27
|
+
this.sessionId = sessionId;
|
|
28
|
+
this._handlers = new Set();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 注册事件监听器(自动过滤 sessionId)
|
|
33
|
+
* @param {string} event - 事件名
|
|
34
|
+
* @param {Function} handler - 处理函数
|
|
35
|
+
* @returns {this}
|
|
36
|
+
*/
|
|
37
|
+
on(event, handler) {
|
|
38
|
+
const wrapped = (data) => {
|
|
39
|
+
if (data && data.sessionId !== this.sessionId) return;
|
|
40
|
+
handler(data);
|
|
41
|
+
};
|
|
42
|
+
this._handlers.add({ event, wrapped });
|
|
43
|
+
this.session.on(event, wrapped);
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 注册一次性事件监听器
|
|
49
|
+
*/
|
|
50
|
+
once(event, handler) {
|
|
51
|
+
const wrapped = (data) => {
|
|
52
|
+
if (data && data.sessionId !== this.sessionId) return;
|
|
53
|
+
handler(data);
|
|
54
|
+
};
|
|
55
|
+
this._handlers.add({ event, wrapped });
|
|
56
|
+
this.session.once(event, wrapped);
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 移除事件监听器
|
|
62
|
+
*/
|
|
63
|
+
off(event, handler) {
|
|
64
|
+
const toRemove = [];
|
|
65
|
+
for (const item of this._handlers) {
|
|
66
|
+
if (item.event === event && item.handler === handler) {
|
|
67
|
+
this.session.off(event, item.wrapped);
|
|
68
|
+
toRemove.push(item);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const item of toRemove) {
|
|
72
|
+
this._handlers.delete(item);
|
|
73
|
+
}
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 移除所有这个 scope 注册的监听器
|
|
79
|
+
*/
|
|
80
|
+
removeAllListeners() {
|
|
81
|
+
for (const { event, wrapped } of this._handlers) {
|
|
82
|
+
this.session.off(event, wrapped);
|
|
83
|
+
}
|
|
84
|
+
this._handlers.clear();
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 获取当前 sessionId
|
|
90
|
+
*/
|
|
91
|
+
getSessionId() {
|
|
92
|
+
return this.sessionId;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
class ChatSession extends EventEmitter {
|
|
97
|
+
/**
|
|
98
|
+
* @param {Object} config - 配置
|
|
99
|
+
* @param {Function} [config.messageProcessor] - 消息处理器函数 (sessionId, message, options) => Promise
|
|
100
|
+
*/
|
|
101
|
+
constructor(config = {}) {
|
|
102
|
+
super();
|
|
103
|
+
|
|
104
|
+
this.config = config;
|
|
105
|
+
this.agent = config.agent;
|
|
106
|
+
|
|
107
|
+
// 消息处理器
|
|
108
|
+
this._messageProcessor = config.messageProcessor;
|
|
109
|
+
|
|
110
|
+
// Session 消息存储 Map: sessionId -> { messages: [], historyLoaded: false, compressionState: {} }
|
|
111
|
+
this._sessionMessageStores = new Map();
|
|
112
|
+
|
|
113
|
+
// Session 队列: sessionId -> Queue of {message, options, resolve, reject}
|
|
114
|
+
this._sessionQueues = new Map();
|
|
115
|
+
this._processingSessions = new Set();
|
|
116
|
+
|
|
117
|
+
// Session 事件作用域 Map: sessionId -> Set<{event, handler}>
|
|
118
|
+
this._sessionScopes = new Map();
|
|
119
|
+
|
|
120
|
+
// 队列管理器
|
|
121
|
+
this.queueManager = new ChatQueueManager({
|
|
122
|
+
maxConcurrent: config.maxConcurrent || 1,
|
|
123
|
+
retryAttempts: config.retryAttempts || 3,
|
|
124
|
+
retryDelay: config.retryDelay || 1000,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
this._setupQueueEvents();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 设置消息处理器
|
|
132
|
+
* @param {Function} processor - (sessionId, message, options) => Promise
|
|
133
|
+
*/
|
|
134
|
+
setMessageProcessor(processor) {
|
|
135
|
+
this._messageProcessor = processor;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 设置队列事件转发
|
|
140
|
+
* @private
|
|
141
|
+
*/
|
|
142
|
+
_setupQueueEvents() {
|
|
143
|
+
const events = [
|
|
144
|
+
'queue:added',
|
|
145
|
+
'queue:processing',
|
|
146
|
+
'queue:completed',
|
|
147
|
+
'queue:failed',
|
|
148
|
+
'queue:retry',
|
|
149
|
+
'queue:empty',
|
|
150
|
+
'queue:cleared',
|
|
151
|
+
'queue:session-removed',
|
|
152
|
+
'stream:chunk',
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
events.forEach((eventName) => {
|
|
156
|
+
this.queueManager.on(eventName, (data) => {
|
|
157
|
+
this.emit(eventName, data);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 获取或创建 SessionScope
|
|
164
|
+
* @param {string} sessionId - Session ID
|
|
165
|
+
* @returns {SessionScope}
|
|
166
|
+
*/
|
|
167
|
+
createSessionScope(sessionId) {
|
|
168
|
+
return new SessionScope(this, sessionId);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 获取会话消息存储
|
|
173
|
+
* @param {string} sessionId - Session ID
|
|
174
|
+
* @returns {Object} messageStore
|
|
175
|
+
*/
|
|
176
|
+
getSessionMessageStore(sessionId) {
|
|
177
|
+
if (!sessionId) {
|
|
178
|
+
sessionId = 'default';
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (!this._sessionMessageStores.has(sessionId)) {
|
|
182
|
+
const store = {
|
|
183
|
+
messages: [],
|
|
184
|
+
historyLoaded: false,
|
|
185
|
+
usage: null,
|
|
186
|
+
compressionState: {
|
|
187
|
+
count: 0,
|
|
188
|
+
lastCompressedAt: null,
|
|
189
|
+
lastTokenCount: 0,
|
|
190
|
+
pendingCompression: false,
|
|
191
|
+
},
|
|
192
|
+
save: () => {
|
|
193
|
+
this.saveHistory(sessionId, store.messages);
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
this._sessionMessageStores.set(sessionId, store);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return this._sessionMessageStores.get(sessionId);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 加载会话历史
|
|
204
|
+
* @param {string} sessionId - Session ID
|
|
205
|
+
* @returns {Array} 消息数组
|
|
206
|
+
*/
|
|
207
|
+
loadHistory(sessionId) {
|
|
208
|
+
if (!sessionId) return [];
|
|
209
|
+
|
|
210
|
+
const messageStore = this.getSessionMessageStore(sessionId);
|
|
211
|
+
if (messageStore.historyLoaded) {
|
|
212
|
+
return messageStore.messages;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 从 SessionContext 加载
|
|
216
|
+
if (this.agent?.framework) {
|
|
217
|
+
const sessionCtx = this.agent.framework._sessionContexts?.get(sessionId);
|
|
218
|
+
if (sessionCtx) {
|
|
219
|
+
const messages = sessionCtx.getMessages();
|
|
220
|
+
if (messages && messages.length > 0) {
|
|
221
|
+
messageStore.messages = messages;
|
|
222
|
+
messageStore.historyLoaded = true;
|
|
223
|
+
logger.debug(`Loaded ${messages.length} messages for session ${sessionId}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return messageStore.messages;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 保存会话历史
|
|
233
|
+
* @param {string} sessionId - Session ID
|
|
234
|
+
* @param {Array} messages - 消息数组
|
|
235
|
+
*/
|
|
236
|
+
saveHistory(sessionId, messages) {
|
|
237
|
+
if (!sessionId || !messages) return;
|
|
238
|
+
|
|
239
|
+
const messageStore = this.getSessionMessageStore(sessionId);
|
|
240
|
+
|
|
241
|
+
// 保存到 SessionContext
|
|
242
|
+
if (this.agent?.framework) {
|
|
243
|
+
const sessionCtx = this.agent.framework._sessionContexts?.get(sessionId);
|
|
244
|
+
if (sessionCtx) {
|
|
245
|
+
sessionCtx.replaceMessages(messages);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
messageStore.historyLoaded = true;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* 添加消息到会话
|
|
254
|
+
* @param {string} sessionId - Session ID
|
|
255
|
+
* @param {Object} message - 消息
|
|
256
|
+
*/
|
|
257
|
+
addMessage(sessionId, message) {
|
|
258
|
+
const store = this.getSessionMessageStore(sessionId);
|
|
259
|
+
store.messages.push(message);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* 入队消息
|
|
264
|
+
* @param {string} sessionId - Session ID
|
|
265
|
+
* @param {Object} message - 消息
|
|
266
|
+
* @param {Object} options - 选项
|
|
267
|
+
* @returns {Promise}
|
|
268
|
+
*/
|
|
269
|
+
enqueue(sessionId, message, options = {}) {
|
|
270
|
+
if (!this._sessionQueues.has(sessionId)) {
|
|
271
|
+
this._sessionQueues.set(sessionId, []);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return new Promise((resolve, reject) => {
|
|
275
|
+
const item = {
|
|
276
|
+
message,
|
|
277
|
+
options,
|
|
278
|
+
resolve,
|
|
279
|
+
reject,
|
|
280
|
+
timestamp: Date.now(),
|
|
281
|
+
executeFunction: options.executeFunction,
|
|
282
|
+
};
|
|
283
|
+
this._sessionQueues.get(sessionId).push(item);
|
|
284
|
+
this.emit('queue:added', {
|
|
285
|
+
sessionId,
|
|
286
|
+
message,
|
|
287
|
+
queueSize: this._sessionQueues.get(sessionId).length,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// 触发队列处理
|
|
291
|
+
this._processNext(sessionId);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* 处理队列中的下一条消息
|
|
297
|
+
* @param {string} sessionId - Session ID
|
|
298
|
+
* @private
|
|
299
|
+
*/
|
|
300
|
+
async _processNext(sessionId) {
|
|
301
|
+
if (this._processingSessions.has(sessionId)) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const queue = this._sessionQueues.get(sessionId);
|
|
306
|
+
if (!queue || queue.length === 0) {
|
|
307
|
+
this.emit('queue:empty', { sessionId });
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
this._processingSessions.add(sessionId);
|
|
312
|
+
this.emit('queue:processing', { sessionId });
|
|
313
|
+
|
|
314
|
+
const item = queue.shift();
|
|
315
|
+
try {
|
|
316
|
+
// 如果有 executeFunction,使用流式处理
|
|
317
|
+
if (item.executeFunction) {
|
|
318
|
+
const chunks = [];
|
|
319
|
+
const stream = item.executeFunction(item.message, { ...item.options, sessionId });
|
|
320
|
+
|
|
321
|
+
for await (const chunk of stream) {
|
|
322
|
+
chunks.push(chunk);
|
|
323
|
+
this.emit('stream:chunk', {
|
|
324
|
+
sessionId,
|
|
325
|
+
chunk,
|
|
326
|
+
accumulated: chunks.length,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const fullText = chunks
|
|
331
|
+
.filter((a) => a.type === 'text')
|
|
332
|
+
.map((item) => item.text)
|
|
333
|
+
.join('');
|
|
334
|
+
|
|
335
|
+
item.resolve({ text: fullText, chunks });
|
|
336
|
+
} else {
|
|
337
|
+
const result = await this._processMessage(sessionId, item.message, item.options);
|
|
338
|
+
item.resolve(result);
|
|
339
|
+
}
|
|
340
|
+
} catch (err) {
|
|
341
|
+
item.reject(err);
|
|
342
|
+
} finally {
|
|
343
|
+
this._processingSessions.delete(sessionId);
|
|
344
|
+
// 处理下一条
|
|
345
|
+
setImmediate(() => this._processNext(sessionId));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* 处理单条消息(子类实现)
|
|
351
|
+
* @param {string} sessionId - Session ID
|
|
352
|
+
* @param {Object} message - 消息
|
|
353
|
+
* @param {Object} options - 选项
|
|
354
|
+
* @returns {Promise}
|
|
355
|
+
* @protected
|
|
356
|
+
*/
|
|
357
|
+
async _processMessage(sessionId, message, options) {
|
|
358
|
+
// 如果设置了处理器,使用处理器
|
|
359
|
+
if (this._messageProcessor) {
|
|
360
|
+
return this._messageProcessor(sessionId, message, options);
|
|
361
|
+
}
|
|
362
|
+
// 否则使用 agent 的处理逻辑
|
|
363
|
+
if (this.agent?._chatHandler) {
|
|
364
|
+
return this.agent._chatHandler._processMessage(sessionId, message, options);
|
|
365
|
+
}
|
|
366
|
+
throw new Error('No message processor set');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* 取消会话队列
|
|
371
|
+
* @param {string} sessionId - Session ID
|
|
372
|
+
*/
|
|
373
|
+
cancelSession(sessionId) {
|
|
374
|
+
const queue = this._sessionQueues.get(sessionId);
|
|
375
|
+
if (queue) {
|
|
376
|
+
queue.forEach((item) => {
|
|
377
|
+
item.reject(new Error('Session cancelled'));
|
|
378
|
+
});
|
|
379
|
+
queue.length = 0;
|
|
380
|
+
}
|
|
381
|
+
this._processingSessions.delete(sessionId);
|
|
382
|
+
this.emit('queue:session-removed', { sessionId });
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* 获取队列状态
|
|
387
|
+
* @param {string} sessionId - Session ID
|
|
388
|
+
* @returns {Object}
|
|
389
|
+
*/
|
|
390
|
+
getQueueStatus(sessionId) {
|
|
391
|
+
const queue = this._sessionQueues.get(sessionId) || [];
|
|
392
|
+
return {
|
|
393
|
+
sessionId,
|
|
394
|
+
size: queue.length,
|
|
395
|
+
processing: this._processingSessions.has(sessionId),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* 清空队列
|
|
401
|
+
* @param {string} sessionId - Session ID
|
|
402
|
+
*/
|
|
403
|
+
clearQueue(sessionId) {
|
|
404
|
+
const queue = this._sessionQueues.get(sessionId);
|
|
405
|
+
if (queue) {
|
|
406
|
+
queue.forEach((item) => {
|
|
407
|
+
item.reject(new Error('Queue cleared'));
|
|
408
|
+
});
|
|
409
|
+
queue.length = 0;
|
|
410
|
+
}
|
|
411
|
+
this.emit('queue:cleared', { sessionId });
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* 生成请求 ID
|
|
416
|
+
* @returns {string}
|
|
417
|
+
*/
|
|
418
|
+
generateRequestId() {
|
|
419
|
+
return `req_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
module.exports = { ChatSession, SessionScope };
|