foliko 1.1.93 → 2.0.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/.claude/settings.local.json +2 -1
- package/CLAUDE.md +56 -30
- package/REFACTORING_PLAN.md +645 -0
- package/docs/architecture.md +131 -0
- package/docs/migration.md +57 -0
- package/docs/public-api.md +138 -0
- package/docs/usage.md +385 -0
- package/examples/ambient-example.js +20 -137
- package/examples/basic.js +21 -48
- package/examples/bootstrap.js +16 -74
- package/examples/mcp-example.js +6 -29
- package/examples/skill-example.js +6 -19
- package/examples/workflow.js +8 -56
- package/package.json +8 -4
- package/plugins/README.md +49 -0
- package/plugins/{ambient-agent → ambient}/EventWatcher.js +1 -1
- package/plugins/{ambient-agent → ambient}/ExplorerLoop.js +3 -3
- package/plugins/{ambient-agent → ambient}/GoalManager.js +2 -2
- package/plugins/ambient/README.md +14 -0
- package/plugins/{ambient-agent → ambient}/Reflector.js +1 -1
- package/plugins/{ambient-agent → ambient}/StateStore.js +1 -1
- package/plugins/{ambient-agent → ambient}/index.js +2 -2
- package/plugins/{ai-plugin.js → core/ai/index.js} +14 -30
- package/plugins/{audit-plugin.js → core/audit/index.js} +3 -30
- package/plugins/{coordinator-plugin.js → core/coordinator/index.js} +3 -35
- package/plugins/core/default/bootstrap.js +202 -0
- package/plugins/core/default/config.js +220 -0
- package/plugins/core/default/index.js +58 -0
- package/plugins/core/mcp/index.js +1 -0
- package/plugins/{python-plugin-loader.js → core/python-loader/index.js} +7 -187
- package/plugins/{rules-plugin.js → core/rules/index.js} +121 -64
- package/plugins/{scheduler-plugin.js → core/scheduler/index.js} +12 -114
- package/plugins/{session-plugin.js → core/session/index.js} +9 -73
- package/{src/capabilities/skill-manager.js → plugins/core/skill-manager/index.js} +64 -18
- package/plugins/{storage-plugin.js → core/storage/index.js} +5 -29
- package/plugins/{subagent-plugin.js → core/sub-agent/index.js} +10 -171
- package/plugins/{think-plugin.js → core/think/index.js} +24 -91
- package/{src/capabilities/workflow-engine.js → plugins/core/workflow/index.js} +87 -85
- package/plugins/default-plugins.js +6 -720
- package/plugins/{data-splitter-plugin.js → executors/data-splitter/index.js} +9 -83
- package/plugins/{extension-executor-plugin.js → executors/extension/index.js} +13 -97
- package/plugins/{python-executor-plugin.js → executors/python/index.js} +6 -31
- package/plugins/{shell-executor-plugin.js → executors/shell/index.js} +2 -5
- package/plugins/install/README.md +9 -0
- package/plugins/{install-plugin.js → install/index.js} +3 -3
- package/plugins/{file-system-plugin.js → io/file-system/index.js} +34 -236
- package/plugins/{web-plugin.js → io/web/index.js} +11 -113
- package/plugins/memory/README.md +13 -0
- package/plugins/{memory-plugin.js → memory/index.js} +4 -18
- package/plugins/messaging/email/README.md +19 -0
- package/plugins/{email → messaging/email}/index.js +2 -2
- package/plugins/{feishu-plugin.js → messaging/feishu/index.js} +3 -3
- package/plugins/{qq-plugin.js → messaging/qq/index.js} +5 -16
- package/plugins/{telegram-plugin.js → messaging/telegram/index.js} +3 -3
- package/plugins/{weixin-plugin.js → messaging/weixin/index.js} +15 -15
- package/plugins/{plugin-manager-plugin.js → plugin-manager/index.js} +36 -180
- package/plugins/{tools-plugin.js → tools/index.js} +68 -116
- package/plugins/trading/README.md +15 -0
- package/plugins/{gate-trading.js → trading/index.js} +8 -8
- package/{examples → sandbox}/test-concurrent-chat.js +2 -2
- package/{examples → sandbox}/test-long-chat.js +2 -2
- package/{examples → sandbox}/test-session-chat.js +2 -2
- package/{examples → sandbox}/test-web-plugin.js +1 -1
- package/{examples → sandbox}/test-weixin-feishu.js +2 -2
- package/src/agent/base.js +56 -0
- package/src/{core/agent-chat.js → agent/chat.js} +11 -11
- package/src/{core/coordinator-manager.js → agent/coordinator.js} +3 -3
- package/src/agent/index.js +111 -0
- package/src/agent/main.js +337 -0
- package/src/agent/prompt.js +78 -0
- package/src/agent/sub.js +198 -0
- package/src/agent/worker.js +104 -0
- package/{cli/bin/foliko.js → src/cli/bin.js} +1 -1
- package/{cli/src → src/cli}/commands/chat.js +25 -21
- package/{cli/src → src/cli}/index.js +1 -0
- package/{cli/src → src/cli}/ui/chat-ui-old.js +40 -178
- package/{cli/src → src/cli}/ui/chat-ui.js +3 -3
- package/{cli/src → src/cli}/ui/components/footer-bar.js +1 -1
- package/src/common/errors.js +402 -0
- package/src/{utils → common}/logger.js +33 -0
- package/src/{utils/chat-queue.js → common/queue.js} +2 -2
- package/src/config/plugin-config.js +50 -0
- package/src/context/agent.js +32 -0
- package/src/context/compaction-prompts.js +170 -0
- package/src/context/compaction-utils.js +191 -0
- package/src/context/compressor.js +413 -0
- package/src/context/index.js +9 -0
- package/src/{core/context-manager.js → context/manager.js} +1 -1
- package/src/context/request.js +50 -0
- package/src/context/session.js +33 -0
- package/src/context/storage.js +30 -0
- package/src/executors/mcp-client.js +153 -0
- package/src/executors/mcp-desc.js +236 -0
- package/src/executors/mcp-executor.js +91 -956
- package/src/{core → framework}/command-registry.js +1 -1
- package/src/framework/framework.js +300 -0
- package/src/framework/index.js +18 -0
- package/src/framework/lifecycle.js +203 -0
- package/src/framework/loader.js +78 -0
- package/src/framework/registry.js +86 -0
- package/src/{core/ui-extension-context.js → framework/ui-extension.js} +1 -1
- package/src/index.js +130 -15
- package/src/llm/index.js +26 -0
- package/src/llm/provider.js +212 -0
- package/src/llm/registry.js +11 -0
- package/src/{core/token-counter.js → llm/tokens.js} +4 -37
- package/src/{core/plugin-base.js → plugin/base.js} +10 -136
- package/src/plugin/index.js +14 -0
- package/src/plugin/loader.js +101 -0
- package/src/plugin/manager.js +261 -0
- package/src/{core → session}/branch-summary-auto.js +2 -2
- package/src/{core/chat-session.js → session/chat.js} +2 -2
- package/src/session/index.js +7 -0
- package/src/{core/session-manager.js → session/session.js} +2 -2
- package/src/session/ttl.js +92 -0
- package/src/{core/jsonl-storage.js → storage/jsonl.js} +1 -1
- package/src/tool/executor.js +85 -0
- package/src/tool/index.js +15 -0
- package/src/tool/registry.js +143 -0
- package/src/{core/tool-router.js → tool/router.js} +17 -124
- package/src/tool/schema.js +108 -0
- package/src/utils/data-splitter.js +1 -1
- package/src/utils/download.js +1 -1
- package/src/utils/index.js +6 -6
- package/src/utils/message-validator.js +1 -1
- package/tests/core/context-storage.test.js +46 -0
- package/tests/core/llm.test.js +54 -0
- package/tests/core/plugin.test.js +42 -0
- package/tests/core/tool.test.js +60 -0
- package/tests/setup.js +10 -0
- package/tests/smoke.test.js +58 -0
- package/vitest.config.js +9 -0
- package/cli/src/daemon.js +0 -149
- package/docs/CONTEXT_DESIGN.md +0 -1596
- package/docs/ai-sdk-optimization.md +0 -655
- package/docs/features.md +0 -120
- package/docs/qq-bot.md +0 -976
- package/docs/quick-reference.md +0 -160
- package/docs/user-manual.md +0 -1391
- package/images/geometric_shapes.jpg +0 -0
- package/images/sunset_mountain_lake.jpg +0 -0
- package/skills/poster-guide/SKILL.md +0 -792
- package/src/capabilities/index.js +0 -11
- package/src/core/agent.js +0 -808
- package/src/core/context-compressor.js +0 -959
- package/src/core/enhanced-context-compressor.js +0 -210
- package/src/core/framework.js +0 -1422
- package/src/core/index.js +0 -30
- package/src/core/plugin-manager.js +0 -961
- package/src/core/provider-registry.js +0 -159
- package/src/core/provider.js +0 -156
- package/src/core/request-context.js +0 -98
- package/src/core/subagent.js +0 -442
- package/src/core/system-prompt-builder.js +0 -120
- package/src/core/tool-executor.js +0 -202
- package/src/core/tool-registry.js +0 -517
- package/src/core/worker-agent.js +0 -192
- package/src/executors/executor-base.js +0 -58
- package/src/utils/error-boundary.js +0 -363
- package/src/utils/error.js +0 -374
- package/system.md +0 -1645
- package/website_v2/README.md +0 -57
- package/website_v2/SPEC.md +0 -1
- package/website_v2/docs/api.html +0 -128
- package/website_v2/docs/configuration.html +0 -147
- package/website_v2/docs/plugin-development.html +0 -129
- package/website_v2/docs/project-structure.html +0 -89
- package/website_v2/docs/skill-development.html +0 -85
- package/website_v2/index.html +0 -489
- package/website_v2/scripts/main.js +0 -93
- package/website_v2/styles/animations.css +0 -8
- package/website_v2/styles/docs.css +0 -83
- package/website_v2/styles/main.css +0 -417
- package/xhs_auth.json +0 -268
- package//346/265/267/346/212/245/346/217/222/344/273/266.md +0 -621
- /package/plugins/{ambient-agent → ambient}/constants.js +0 -0
- /package/plugins/{email → messaging/email}/constants.js +0 -0
- /package/plugins/{email → messaging/email}/handlers.js +0 -0
- /package/plugins/{email → messaging/email}/monitor.js +0 -0
- /package/plugins/{email → messaging/email}/parser.js +0 -0
- /package/plugins/{email → messaging/email}/reply.js +0 -0
- /package/plugins/{email → messaging/email}/utils.js +0 -0
- /package/{examples → sandbox}/test-chat.js +0 -0
- /package/{examples → sandbox}/test-mcp.js +0 -0
- /package/{examples → sandbox}/test-reload.js +0 -0
- /package/{examples → sandbox}/test-telegram.js +0 -0
- /package/{examples → sandbox}/test-tg-bot.js +0 -0
- /package/{examples → sandbox}/test-tg-simple.js +0 -0
- /package/{examples → sandbox}/test-tg.js +0 -0
- /package/{examples → sandbox}/test-think.js +0 -0
- /package/src/{core/sub-agent-config.js → agent/sub-config.js} +0 -0
- /package/{cli/src → src/cli}/commands/daemon.js +0 -0
- /package/{cli/src → src/cli}/commands/list.js +0 -0
- /package/{cli/src → src/cli}/commands/plugin.js +0 -0
- /package/{cli/src → src/cli}/ui/components/agent-mention-provider.js +0 -0
- /package/{cli/src → src/cli}/ui/components/chained-autocomplete-provider.js +0 -0
- /package/{cli/src → src/cli}/ui/components/message-bubble.js +0 -0
- /package/{cli/src → src/cli}/ui/components/status-bar.js +0 -0
- /package/{cli/src → src/cli}/utils/ansi.js +0 -0
- /package/{cli/src → src/cli}/utils/config.js +0 -0
- /package/{cli/src → src/cli}/utils/markdown.js +0 -0
- /package/{cli/src → src/cli}/utils/plugin-config.js +0 -0
- /package/{cli/src → src/cli}/utils/render-diff.js +0 -0
- /package/src/{utils/circuit-breaker.js → common/circuit.js} +0 -0
- /package/src/{core → common}/constants.js +0 -0
- /package/src/{utils/edit-diff.js → common/diff.js} +0 -0
- /package/src/{utils/event-emitter.js → common/events.js} +0 -0
- /package/src/{utils → common}/id.js +0 -0
- /package/src/{utils → common}/retry.js +0 -0
- /package/src/{core/notification-manager.js → notification/manager.js} +0 -0
- /package/src/{core/session-entry.js → session/entry.js} +0 -0
- /package/src/{core/storage-manager.js → storage/manager.js} +0 -0
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DataSplitterPlugin — 大数据自动分拆插件
|
|
3
|
-
*
|
|
4
|
-
* 功能:
|
|
5
|
-
* 1. 注册 `split_and_process` 工具:AI 可主动调用,将大文本分拆给子 Agent 处理
|
|
6
|
-
* 2. 注册 `get_content_preview` 工具:获取大内容的前 N 行,判断是否需要分拆
|
|
7
|
-
* 3. 自动检测工具返回的大数据,触发透明分拆
|
|
8
|
-
* 4. 系统提示词中告知 AI 大数据处理能力
|
|
9
3
|
*/
|
|
10
4
|
|
|
11
|
-
const { Plugin } = require('
|
|
5
|
+
const { Plugin } = require('../../../src/plugin/base');
|
|
12
6
|
const { z } = require('zod');
|
|
13
|
-
const { logger } = require('
|
|
14
|
-
const { DataSplitter } = require('
|
|
7
|
+
const { logger } = require('../../../src/common/logger');
|
|
8
|
+
const { DataSplitter } = require('../../../src/utils/data-splitter');
|
|
15
9
|
|
|
16
|
-
// 超过此大小的工具结果自动触发分拆(字符数,默认 100K tokens ≈ 200K chars)
|
|
17
10
|
const AUTO_SPLIT_THRESHOLD = 50000;
|
|
18
11
|
|
|
19
12
|
class DataSplitterPlugin extends Plugin {
|
|
@@ -27,7 +20,6 @@ class DataSplitterPlugin extends Plugin {
|
|
|
27
20
|
this._framework = null;
|
|
28
21
|
this._splitter = null;
|
|
29
22
|
|
|
30
|
-
// 配置
|
|
31
23
|
this.config = {
|
|
32
24
|
autoSplitThreshold: config.autoSplitThreshold || AUTO_SPLIT_THRESHOLD,
|
|
33
25
|
chunkSize: config.chunkSize || 60000,
|
|
@@ -48,34 +40,20 @@ class DataSplitterPlugin extends Plugin {
|
|
|
48
40
|
}
|
|
49
41
|
|
|
50
42
|
start(framework) {
|
|
51
|
-
// 注册大数据处理工具
|
|
52
43
|
this._registerSplitTools();
|
|
53
|
-
|
|
54
|
-
// 注册系统提示词
|
|
55
44
|
this.registerPromptPart('data-splitter-rules', 85, () => this._getPromptRules());
|
|
56
|
-
|
|
57
|
-
// 注册工具结果监听器(自动检测大结果)
|
|
58
45
|
this._registerAutoSplitHook();
|
|
59
|
-
|
|
60
|
-
// log.info('[DataSplitterPlugin] 已启动,阈值:', this.config.autoSplitThreshold);
|
|
61
46
|
}
|
|
62
47
|
|
|
63
|
-
/**
|
|
64
|
-
* 注册分拆工具
|
|
65
|
-
* @private
|
|
66
|
-
*/
|
|
67
48
|
_registerSplitTools() {
|
|
68
49
|
const framework = this._framework;
|
|
69
50
|
|
|
70
|
-
// ─── 工具1: split_and_process — AI 主动调用分拆 ───
|
|
71
51
|
framework.registerTool({
|
|
72
52
|
name: 'split_and_process',
|
|
73
|
-
description: `将大文本内容按大小分块,创建多个子 Agent
|
|
74
|
-
当你读取文件或抓取网页返回的内容超过 10 万字符时,应该使用此工具来分拆处理。
|
|
75
|
-
它会将内容拆成多块,每块由一个子 Agent 独立处理,最后给你一个汇总。`,
|
|
53
|
+
description: `将大文本内容按大小分块,创建多个子 Agent 并行处理每块内容,最后自动汇总结果。`,
|
|
76
54
|
inputSchema: z.object({
|
|
77
|
-
content: z.string().describe('
|
|
78
|
-
taskDescription: z.string().describe('每个子 Agent
|
|
55
|
+
content: z.string().describe('要分拆处理的大文本内容'),
|
|
56
|
+
taskDescription: z.string().describe('每个子 Agent 要执行的任务描述'),
|
|
79
57
|
chunkSize: z.number().optional().default(60000).describe('每块最大字符数,默认 60000'),
|
|
80
58
|
maxConcurrent: z.number().optional().default(3).describe('最大并行子 Agent 数,默认 3'),
|
|
81
59
|
}),
|
|
@@ -89,7 +67,6 @@ class DataSplitterPlugin extends Plugin {
|
|
|
89
67
|
|
|
90
68
|
const stats = splitter.getContentStats(content);
|
|
91
69
|
if (!splitter.needsSplit(content)) {
|
|
92
|
-
// 内容较小,直接返回
|
|
93
70
|
return {
|
|
94
71
|
success: true,
|
|
95
72
|
data: content,
|
|
@@ -101,15 +78,9 @@ class DataSplitterPlugin extends Plugin {
|
|
|
101
78
|
};
|
|
102
79
|
}
|
|
103
80
|
|
|
104
|
-
// 生成上下文中的 sessionId 用于取消信号
|
|
105
81
|
const sessionCtx = ctx?.getCurrentSessionContext?.();
|
|
106
82
|
const signal = sessionCtx?.abortSignal;
|
|
107
83
|
|
|
108
|
-
log.debug(
|
|
109
|
-
`[split_and_process] 开始分拆: ${stats.chars} 字符, ` +
|
|
110
|
-
`${stats.chunks} 块, 任务="${taskDescription?.slice(0, 40)}..."`
|
|
111
|
-
);
|
|
112
|
-
|
|
113
84
|
const startTime = Date.now();
|
|
114
85
|
const chunks = splitter.splitContent(content, chunkSize);
|
|
115
86
|
const result = await splitter.dispatchToSubAgents({
|
|
@@ -135,11 +106,9 @@ class DataSplitterPlugin extends Plugin {
|
|
|
135
106
|
},
|
|
136
107
|
});
|
|
137
108
|
|
|
138
|
-
// ─── 工具2: get_content_preview — 获取大内容预览信息 ───
|
|
139
109
|
framework.registerTool({
|
|
140
110
|
name: 'get_content_preview',
|
|
141
|
-
description: `获取大文本内容的预览信息(前 20 行 +
|
|
142
|
-
适合在读取大文件或抓取网页后用于检查内容大小。`,
|
|
111
|
+
description: `获取大文本内容的预览信息(前 20 行 + 统计),判断是否需要分拆处理。`,
|
|
143
112
|
inputSchema: z.object({
|
|
144
113
|
content: z.string().describe('要预览的大文本内容'),
|
|
145
114
|
previewLines: z.number().optional().default(20).describe('预览前 N 行,默认 20'),
|
|
@@ -168,10 +137,6 @@ class DataSplitterPlugin extends Plugin {
|
|
|
168
137
|
});
|
|
169
138
|
}
|
|
170
139
|
|
|
171
|
-
/**
|
|
172
|
-
* 获取系统提示词
|
|
173
|
-
* @private
|
|
174
|
-
*/
|
|
175
140
|
_getPromptRules() {
|
|
176
141
|
return `## 大数据处理能力
|
|
177
142
|
|
|
@@ -188,22 +153,14 @@ class DataSplitterPlugin extends Plugin {
|
|
|
188
153
|
- 分拆时指定清晰的任务描述,例如"提取所有关键代码函数"、"总结每段内容要点"`;
|
|
189
154
|
}
|
|
190
155
|
|
|
191
|
-
/**
|
|
192
|
-
* 注册自动分拆钩子
|
|
193
|
-
* 监听 tool:result 事件,如果结果太大自动触发分拆
|
|
194
|
-
* @private
|
|
195
|
-
*/
|
|
196
156
|
_registerAutoSplitHook() {
|
|
197
157
|
const framework = this._framework;
|
|
198
158
|
|
|
199
|
-
// 监听工具结果,检测大数据
|
|
200
159
|
this._toolResultHandler = (data) => {
|
|
201
160
|
const { name, result } = data;
|
|
202
161
|
|
|
203
|
-
// 跳过已经标记为分拆结果的工具
|
|
204
162
|
if (name === 'split_and_process') return;
|
|
205
163
|
|
|
206
|
-
// 检查工具返回的内容是否过大(优先使用 data 字段)
|
|
207
164
|
let checkContent = '';
|
|
208
165
|
if (result && typeof result === 'object' && result.data) {
|
|
209
166
|
checkContent = typeof result.data === 'string' ? result.data : JSON.stringify(result.data);
|
|
@@ -211,27 +168,16 @@ class DataSplitterPlugin extends Plugin {
|
|
|
211
168
|
checkContent = typeof result === 'string' ? result : JSON.stringify(result);
|
|
212
169
|
}
|
|
213
170
|
if (!checkContent || checkContent.length < this.config.autoSplitThreshold) return;
|
|
214
|
-
|
|
215
|
-
// 不阻塞执行,只在日志中记录建议
|
|
216
|
-
// log.info(
|
|
217
|
-
// `[DataSplitter] 检测到大数据工具结果: ${name}, ` +
|
|
218
|
-
// `${checkContent.length} 字符, 建议使用 split_and_process 分拆处理`
|
|
219
|
-
// );
|
|
220
171
|
};
|
|
221
172
|
|
|
222
173
|
framework.on('tool:result', this._toolResultHandler);
|
|
223
174
|
}
|
|
224
175
|
|
|
225
|
-
/**
|
|
226
|
-
* 获取 DataSplitter 实例
|
|
227
|
-
* @private
|
|
228
|
-
*/
|
|
229
176
|
_getSplitter(ctx) {
|
|
230
177
|
return this._splitter || new DataSplitter(this._framework, this.config);
|
|
231
178
|
}
|
|
232
179
|
|
|
233
180
|
reload(framework) {
|
|
234
|
-
// 清理旧监听器
|
|
235
181
|
if (this._toolResultHandler) {
|
|
236
182
|
framework.off('tool:result', this._toolResultHandler);
|
|
237
183
|
}
|
|
@@ -239,12 +185,10 @@ class DataSplitterPlugin extends Plugin {
|
|
|
239
185
|
this._framework = framework;
|
|
240
186
|
this._splitter = new DataSplitter(framework, this.config);
|
|
241
187
|
|
|
242
|
-
// 重新注册
|
|
243
188
|
if (framework._mainAgent) {
|
|
244
189
|
this.start(framework);
|
|
245
190
|
}
|
|
246
191
|
|
|
247
|
-
// 请求刷新 mainAgent 的 system prompt
|
|
248
192
|
if (framework._mainAgent) {
|
|
249
193
|
framework._mainAgent._refreshContext();
|
|
250
194
|
}
|
|
@@ -257,27 +201,14 @@ class DataSplitterPlugin extends Plugin {
|
|
|
257
201
|
}
|
|
258
202
|
}
|
|
259
203
|
|
|
260
|
-
/**
|
|
261
|
-
* 自动检测工具结果是否过大,并透明处理
|
|
262
|
-
* 在 agent-chat 中调用
|
|
263
|
-
*
|
|
264
|
-
* @param {string} toolName - 工具名称
|
|
265
|
-
* @param {*} result - 工具返回结果
|
|
266
|
-
* @param {Object} framework - Framework 实例
|
|
267
|
-
* @returns {Promise<{ wasSplit: boolean, result: *, splitterResult?: Object }>}
|
|
268
|
-
*/
|
|
269
204
|
async function autoSplitToolResult(toolName, result, framework) {
|
|
270
|
-
// 跳过某些工具
|
|
271
205
|
const skipTools = ['split_and_process', 'get_content_preview'];
|
|
272
206
|
if (skipTools.includes(toolName)) return { wasSplit: false, result };
|
|
273
207
|
|
|
274
|
-
// 无 framework 时无法创建子 Agent,跳过
|
|
275
208
|
if (!framework || typeof framework.createSubAgent !== 'function') {
|
|
276
209
|
return { wasSplit: false, result };
|
|
277
210
|
}
|
|
278
211
|
|
|
279
|
-
// 提取用于判断大小的内容
|
|
280
|
-
// 优先使用 result.data(统一格式),再回退到整个结果字符串
|
|
281
212
|
let checkContent = '';
|
|
282
213
|
if (typeof result === 'object' && result !== null && result.data) {
|
|
283
214
|
checkContent = typeof result.data === 'string' ? result.data : JSON.stringify(result.data);
|
|
@@ -291,10 +222,6 @@ async function autoSplitToolResult(toolName, result, framework) {
|
|
|
291
222
|
const splitter = new DataSplitter(framework);
|
|
292
223
|
const taskDescription = `从以下内容中提取关键信息(代码、配置、数据等),以结构化方式输出。`;
|
|
293
224
|
|
|
294
|
-
// log.info(
|
|
295
|
-
// `[DataSplitter] 自动分拆工具 "${toolName}": ${checkContent.length} 字符`
|
|
296
|
-
// );
|
|
297
|
-
|
|
298
225
|
try {
|
|
299
226
|
const chunks = splitter.splitContent(checkContent);
|
|
300
227
|
const splitResult = await splitter.dispatchToSubAgents({
|
|
@@ -305,12 +232,11 @@ async function autoSplitToolResult(toolName, result, framework) {
|
|
|
305
232
|
|
|
306
233
|
return {
|
|
307
234
|
wasSplit: true,
|
|
308
|
-
// 返回原始结果 + 分拆汇总,AI 可以同时看到两者
|
|
309
235
|
result: {
|
|
310
236
|
_autoSplit: true,
|
|
311
237
|
_originalSize: checkContent.length,
|
|
312
238
|
_summary: splitResult.summary,
|
|
313
|
-
_originalResult: result,
|
|
239
|
+
_originalResult: result,
|
|
314
240
|
},
|
|
315
241
|
splitterResult: splitResult,
|
|
316
242
|
};
|
|
@@ -320,4 +246,4 @@ async function autoSplitToolResult(toolName, result, framework) {
|
|
|
320
246
|
}
|
|
321
247
|
}
|
|
322
248
|
|
|
323
|
-
module.exports = { DataSplitterPlugin, autoSplitToolResult };
|
|
249
|
+
module.exports = { DataSplitterPlugin, autoSplitToolResult };
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* 统一管理扩展插件(如 gate-trading)的工具,通过 ext_call 调用
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { Plugin } = require('
|
|
7
|
-
const { logger } = require('
|
|
6
|
+
const { Plugin } = require('../../../src/plugin/base');
|
|
7
|
+
const { logger } = require('../../../src/common/logger');
|
|
8
8
|
const { z } = require('zod');
|
|
9
|
-
const { PROMPT_PRIORITY } = require('
|
|
10
|
-
const { zodSchemaToMarkdown,zodSchemaToTable } = require('@chnak/zod-to-markdown');
|
|
9
|
+
const { PROMPT_PRIORITY } = require('../../../src/common/constants');
|
|
10
|
+
const { zodSchemaToMarkdown, zodSchemaToTable } = require('@chnak/zod-to-markdown');
|
|
11
11
|
|
|
12
12
|
const log = logger.child('ExtensionExecutor');
|
|
13
13
|
|
|
@@ -27,40 +27,29 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
27
27
|
install(framework) {
|
|
28
28
|
this._framework = framework;
|
|
29
29
|
|
|
30
|
-
// 监听插件加载事件,自动扫描插件的 this.tools
|
|
31
30
|
framework.on('plugin:loaded', (plugin) => {
|
|
32
31
|
this._scanPluginTools(plugin);
|
|
33
32
|
});
|
|
34
33
|
|
|
35
|
-
// 监听插件重载事件,重新扫描工具
|
|
36
34
|
framework.on('plugin:reloaded', (plugin) => {
|
|
37
35
|
this._rescanPluginTools(plugin);
|
|
38
36
|
});
|
|
39
37
|
|
|
40
|
-
// 监听框架就绪事件,刷新所有动态注册的工具(确保在 install() 中通过 registerTool() 注册的工具能被扫描到)
|
|
41
38
|
framework.on('framework:ready', () => {
|
|
42
39
|
log.debug('Framework ready, rescanning all plugin tools...');
|
|
43
40
|
const plugins = framework.pluginManager.getAll();
|
|
44
41
|
for (const { instance: plugin } of plugins) {
|
|
45
|
-
// skill-manager 插件的工具已通过 Skill.registerCommands 直接注册,
|
|
46
|
-
// 不需要再通过 _scanPluginTools 扫描,避免重复注册
|
|
47
42
|
if (plugin.name === 'skill-manager') {
|
|
48
43
|
continue;
|
|
49
44
|
}
|
|
50
45
|
this._scanPluginTools(plugin);
|
|
51
46
|
}
|
|
52
|
-
// 刷新所有 Agent 的扩展提示词
|
|
53
47
|
this._refreshAllAgentsExtPrompt(framework);
|
|
54
48
|
});
|
|
55
49
|
|
|
56
50
|
return this;
|
|
57
51
|
}
|
|
58
52
|
|
|
59
|
-
/**
|
|
60
|
-
* 扫描插件的 this.tools 并注册到扩展系统
|
|
61
|
-
* @param {Object} plugin - 插件实例
|
|
62
|
-
* @param {string} [extName] - 可选的扩展名(用于统一命名)
|
|
63
|
-
*/
|
|
64
53
|
_scanPluginTools(plugin, extName) {
|
|
65
54
|
if (!plugin || !plugin.tools || typeof plugin.tools !== 'object') {
|
|
66
55
|
return;
|
|
@@ -69,17 +58,14 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
69
58
|
const pluginName = plugin.name;
|
|
70
59
|
if (!pluginName) return;
|
|
71
60
|
|
|
72
|
-
// 确定扩展名:优先使用 extName,否则使用 pluginName
|
|
73
61
|
const useExtName = extName || pluginName;
|
|
74
62
|
|
|
75
|
-
// 获取插件信息
|
|
76
63
|
const pluginInfo = {
|
|
77
64
|
name: useExtName,
|
|
78
65
|
description: plugin.description || '',
|
|
79
66
|
version: plugin.version || '1.0.0',
|
|
80
67
|
};
|
|
81
68
|
|
|
82
|
-
// 遍历插件的所有工具
|
|
83
69
|
for (const [toolName, toolDef] of Object.entries(plugin.tools)) {
|
|
84
70
|
if (!toolDef || typeof toolDef !== 'object') continue;
|
|
85
71
|
|
|
@@ -93,15 +79,11 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
93
79
|
|
|
94
80
|
log.debug(` Scanned ${Object.keys(plugin.tools).length} tools from plugin '${pluginName}' (as '${useExtName}')`);
|
|
95
81
|
|
|
96
|
-
// 刷新所有 Agent 的扩展提示词
|
|
97
82
|
if (this._framework && this._framework._ready) {
|
|
98
83
|
this._refreshAllAgentsExtPrompt(this._framework);
|
|
99
84
|
}
|
|
100
85
|
}
|
|
101
86
|
|
|
102
|
-
/**
|
|
103
|
-
* 重新扫描插件的工具(用于热重载)
|
|
104
|
-
*/
|
|
105
87
|
_rescanPluginTools(plugin) {
|
|
106
88
|
if (!plugin || !plugin.tools || typeof plugin.tools !== 'object') {
|
|
107
89
|
return;
|
|
@@ -110,16 +92,13 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
110
92
|
const pluginName = plugin.name;
|
|
111
93
|
if (!pluginName) return;
|
|
112
94
|
|
|
113
|
-
// skill-manager 插件使用 'skill' 作为扩展名(保持与 Skill.registerCommands 一致)
|
|
114
95
|
const extName = pluginName === 'skill-manager' ? 'skill' : pluginName;
|
|
115
96
|
|
|
116
|
-
// 先移除旧工具(同时检查 'skill' 和 'skill-manager' 两个扩展名)
|
|
117
97
|
const keysToRemove = [extName, pluginName];
|
|
118
98
|
for (const key of keysToRemove) {
|
|
119
99
|
if (this._extensions.has(key)) {
|
|
120
100
|
const ext = this._extensions.get(key);
|
|
121
101
|
for (const tool of ext.tools || []) {
|
|
122
|
-
// 从 toolRouter 移除
|
|
123
102
|
if (this._framework?.toolRouter) {
|
|
124
103
|
this._framework.toolRouter.unregister(`ext_${tool.name}`);
|
|
125
104
|
}
|
|
@@ -128,19 +107,18 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
128
107
|
}
|
|
129
108
|
}
|
|
130
109
|
|
|
131
|
-
// 重新扫描工具,使用正确的扩展名
|
|
132
110
|
this._scanPluginTools(plugin, extName);
|
|
133
|
-
//log.info(` Rescanned tools from plugin '${pluginName}' (as '${extName}')`);
|
|
134
111
|
}
|
|
135
112
|
|
|
136
113
|
async start(framework) {
|
|
137
|
-
// 扫描所有已加载插件的 tools
|
|
138
114
|
const plugins = framework.pluginManager.getAll();
|
|
139
115
|
for (const { instance: plugin } of plugins) {
|
|
116
|
+
if (plugin.name === 'skill-manager') {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
140
119
|
this._scanPluginTools(plugin);
|
|
141
120
|
}
|
|
142
121
|
|
|
143
|
-
// 获取 MCP executor 引用(用于 ext_call 统一路由)
|
|
144
122
|
this._mcpExecutor = framework.pluginManager?.get('mcp') || null;
|
|
145
123
|
|
|
146
124
|
framework.registerTool({
|
|
@@ -153,13 +131,10 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
153
131
|
}),
|
|
154
132
|
execute: async (args) => {
|
|
155
133
|
const { plugin, tool, args: toolArgs = {} } = args;
|
|
156
|
-
//log.info(`[Extension] ext_call: plugin=${plugin}, tool=${tool}`);
|
|
157
134
|
|
|
158
|
-
// MCP 服务器工具(已注册为 server_toolname 格式,如 github_search)
|
|
159
135
|
if (plugin === 'mcp' && this._mcpExecutor) {
|
|
160
136
|
const mcpToolDef = this._mcpExecutor.tools?.[tool];
|
|
161
137
|
if (mcpToolDef && mcpToolDef.execute) {
|
|
162
|
-
//log.info(` ext_call [MCP]: tool=${tool}`);
|
|
163
138
|
return await mcpToolDef.execute(toolArgs || {});
|
|
164
139
|
}
|
|
165
140
|
return { success: false, error: `MCP tool '${tool}' not found` };
|
|
@@ -167,7 +142,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
167
142
|
|
|
168
143
|
const ext = this._extensions.get(plugin);
|
|
169
144
|
if (!ext) {
|
|
170
|
-
// 触发错误事件
|
|
171
145
|
framework.emit('tool:error', {
|
|
172
146
|
name: `${plugin}:${tool}`,
|
|
173
147
|
args: toolArgs,
|
|
@@ -179,7 +153,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
179
153
|
|
|
180
154
|
const toolDef = ext.tools.find((t) => t.name === tool);
|
|
181
155
|
if (!toolDef) {
|
|
182
|
-
// 触发错误事件
|
|
183
156
|
framework.emit('tool:error', {
|
|
184
157
|
name: `${plugin}:${tool}`,
|
|
185
158
|
args: toolArgs,
|
|
@@ -190,7 +163,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
190
163
|
}
|
|
191
164
|
|
|
192
165
|
try {
|
|
193
|
-
// 触发扩展工具开始事件
|
|
194
166
|
framework.emit('tool:call', {
|
|
195
167
|
name: `${plugin}:${tool}`,
|
|
196
168
|
args: toolArgs,
|
|
@@ -202,12 +174,9 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
202
174
|
source: 'extension'
|
|
203
175
|
});
|
|
204
176
|
|
|
205
|
-
// 统一 execute 签名为 (args, framework)
|
|
206
177
|
const result = await toolDef.execute(toolArgs, framework);
|
|
207
178
|
|
|
208
|
-
// 检查结果是否为错误
|
|
209
179
|
if (result && result.success === false && result.error) {
|
|
210
|
-
// 触发扩展工具错误事件
|
|
211
180
|
framework.emit('tool:error', {
|
|
212
181
|
name: `${plugin}:${tool}`,
|
|
213
182
|
args: toolArgs,
|
|
@@ -217,7 +186,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
217
186
|
return result;
|
|
218
187
|
}
|
|
219
188
|
|
|
220
|
-
// 触发扩展工具完成事件
|
|
221
189
|
framework.emit('tool:result', {
|
|
222
190
|
name: `${plugin}:${tool}`,
|
|
223
191
|
args: toolArgs,
|
|
@@ -229,7 +197,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
229
197
|
} catch (err) {
|
|
230
198
|
log.error(` Tool '${tool}' failed:`, err.message);
|
|
231
199
|
|
|
232
|
-
// 触发扩展工具错误事件
|
|
233
200
|
framework.emit('tool:error', {
|
|
234
201
|
name: `${plugin}:${tool}`,
|
|
235
202
|
args: toolArgs,
|
|
@@ -267,8 +234,8 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
267
234
|
plugin: z.string().describe('扩展插件名称')
|
|
268
235
|
}),
|
|
269
236
|
execute: async (args) => {
|
|
270
|
-
const { plugin} = args;
|
|
271
|
-
if(plugin === 'skill'){
|
|
237
|
+
const { plugin } = args;
|
|
238
|
+
if (plugin === 'skill') {
|
|
272
239
|
return "请使用 `loadSkill` 获取skill的使用详情"
|
|
273
240
|
}
|
|
274
241
|
return this.bindAllToolSkill(plugin)
|
|
@@ -287,7 +254,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
287
254
|
});
|
|
288
255
|
}
|
|
289
256
|
|
|
290
|
-
// 注册扩展插件的提示词部分(使用基类方法)
|
|
291
257
|
this.registerPromptPart('extension-tools', PROMPT_PRIORITY.EXTENSION_TOOLS, () => this._buildExtensionsDescription());
|
|
292
258
|
|
|
293
259
|
return this;
|
|
@@ -316,27 +282,23 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
316
282
|
inputSchema: toolDef.inputSchema,
|
|
317
283
|
execute: toolDef.execute,
|
|
318
284
|
};
|
|
319
|
-
// 保留额外属性(如 _options)
|
|
320
285
|
if (toolDef._options) {
|
|
321
286
|
toolEntry._options = toolDef._options;
|
|
322
287
|
}
|
|
323
288
|
if (existingIdx >= 0) {
|
|
324
|
-
// 更新已存在的工具
|
|
325
289
|
ext.tools[existingIdx] = toolEntry;
|
|
326
290
|
} else {
|
|
327
|
-
// 添加新工具
|
|
328
291
|
ext.tools.push(toolEntry);
|
|
329
292
|
}
|
|
330
293
|
|
|
331
294
|
log.debug(` Registered tool '${toolDef.name}' for extension '${pluginName}'`);
|
|
332
295
|
|
|
333
|
-
// 刷新所有 Agent 的扩展提示词
|
|
334
296
|
if (this._framework && this._framework._ready) {
|
|
335
297
|
this._refreshAllAgentsExtPrompt(this._framework);
|
|
336
298
|
}
|
|
337
299
|
}
|
|
338
300
|
|
|
339
|
-
bindAllToolSkill(pluginName){
|
|
301
|
+
bindAllToolSkill(pluginName) {
|
|
340
302
|
const mcp = this._framework.pluginManager.get('mcp');
|
|
341
303
|
const sections = [
|
|
342
304
|
'你可以通过 `ext_call` 工具调用以下扩展插件的功能。',
|
|
@@ -353,11 +315,10 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
353
315
|
];
|
|
354
316
|
|
|
355
317
|
const ext = this._extensions.get(pluginName);
|
|
356
|
-
if(!ext)return '找不到扩展!'
|
|
318
|
+
if (!ext) return '找不到扩展!'
|
|
357
319
|
for (const tool of ext.tools) {
|
|
358
320
|
sections.push(`#### \`${tool.name}\``, '');
|
|
359
321
|
sections.push(tool.description || '无描述', '');
|
|
360
|
-
// 使用 zodSchemaToMarkdown 解析参数
|
|
361
322
|
if (ext.name === 'mcp' && mcp) {
|
|
362
323
|
const mcp_desc = mcp._bindMcpParamsDesc(tool.inputSchema);
|
|
363
324
|
sections.push(mcp_desc, '');
|
|
@@ -376,7 +337,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
376
337
|
|
|
377
338
|
sections.push('');
|
|
378
339
|
return sections.join('\n')
|
|
379
|
-
|
|
380
340
|
}
|
|
381
341
|
|
|
382
342
|
_refreshAllAgentsExtPrompt(framework) {
|
|
@@ -401,18 +361,13 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
401
361
|
|
|
402
362
|
let existingPrompt = agent._originalPrompt || '';
|
|
403
363
|
|
|
404
|
-
// 移除所有已存在的 ## 【Extensions】 部分(防止重复累积)
|
|
405
364
|
const extRegex = /## 【Extensions】[\s\S]*?(?=\n## 【|$)/;
|
|
406
365
|
existingPrompt = existingPrompt.replace(extRegex, '').trim();
|
|
407
|
-
|
|
408
|
-
// 添加新的 Extensions 部分
|
|
409
|
-
//agent.setSystemPrompt(existingPrompt + '\n\n' + extDesc);
|
|
410
366
|
}
|
|
411
367
|
|
|
412
368
|
_buildExtensionsDescription() {
|
|
413
369
|
let desc = '';
|
|
414
370
|
|
|
415
|
-
// 扩展插件工具(仅列出名称和简介,详细信息通过 ext_schema 按需获取)
|
|
416
371
|
if (this._extensions.size > 0 || (this._mcpExecutor && Object.keys(this._mcpExecutor.tools || {}).length > 0)) {
|
|
417
372
|
desc += '## 【Extensions】扩展插件\n\n';
|
|
418
373
|
desc += '**使用流程(必须按顺序执行):**\n';
|
|
@@ -421,15 +376,13 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
421
376
|
desc += '> **警告**:禁止在未执行第1步获取参数的情况下直接调用 `ext_call`!\n\n';
|
|
422
377
|
|
|
423
378
|
for (const [name, ext] of this._extensions) {
|
|
424
|
-
if (name === 'mcp'|| name === 'skill') continue;
|
|
379
|
+
if (name === 'mcp' || name === 'skill') continue;
|
|
425
380
|
desc += `### ${ext.name || name}\n`;
|
|
426
381
|
desc += `${ext.description || '无描述'}\n`;
|
|
427
382
|
const validTools = ext.tools.filter(t => t && t.name);
|
|
428
383
|
desc += `**工具:** ${validTools.map(t => `\`${t.name}\``).join(', ')}\n\n`;
|
|
429
|
-
|
|
430
384
|
}
|
|
431
385
|
|
|
432
|
-
// MCP 服务器工具
|
|
433
386
|
if (this._mcpExecutor && Object.keys(this._mcpExecutor.tools || {}).length > 0) {
|
|
434
387
|
desc += '### mcp (MCP 服务器工具)\n';
|
|
435
388
|
desc += '已注册为 `服务器_工具名` 格式\n';
|
|
@@ -447,26 +400,18 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
447
400
|
return desc.trim();
|
|
448
401
|
}
|
|
449
402
|
|
|
450
|
-
/**
|
|
451
|
-
* 将 Schema 转换为 Markdown 格式的参数描述
|
|
452
|
-
* 支持 Zod schema 和 JSON Schema
|
|
453
|
-
*/
|
|
454
403
|
_convertSchemaToMarkdown(inputSchema) {
|
|
455
404
|
if (!inputSchema) return null;
|
|
456
405
|
|
|
457
|
-
// 提取实际 schema(处理 { jsonSchema: {...} } 或 { inputSchema: {...} } 格式)
|
|
458
406
|
let schema = inputSchema;
|
|
459
407
|
if (inputSchema.jsonSchema) schema = inputSchema.jsonSchema;
|
|
460
408
|
if (inputSchema.inputSchema) schema = inputSchema.inputSchema;
|
|
461
409
|
|
|
462
|
-
// 检查是否是 Zod schema
|
|
463
410
|
const isZodSchema = typeof schema.shape === 'function' || (schema._def && schema._def.typeName);
|
|
464
411
|
if (isZodSchema) {
|
|
465
|
-
// Zod schema 直接转换
|
|
466
412
|
return zodSchemaToMarkdown(schema);
|
|
467
413
|
}
|
|
468
414
|
|
|
469
|
-
// JSON Schema 转换为 Zod 再转换
|
|
470
415
|
if (schema.properties) {
|
|
471
416
|
const zodSchema = this._jsonSchemaToZod(schema);
|
|
472
417
|
if (zodSchema) {
|
|
@@ -474,13 +419,9 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
474
419
|
}
|
|
475
420
|
}
|
|
476
421
|
|
|
477
|
-
// 如果都没有,回退到简单格式
|
|
478
422
|
return this._schemaToMarkdown(schema);
|
|
479
423
|
}
|
|
480
424
|
|
|
481
|
-
/**
|
|
482
|
-
* 将 JSON Schema 转换为 Zod schema
|
|
483
|
-
*/
|
|
484
425
|
_jsonSchemaToZod(jsonSchema) {
|
|
485
426
|
if (!jsonSchema || !jsonSchema.properties) return null;
|
|
486
427
|
|
|
@@ -499,9 +440,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
499
440
|
}
|
|
500
441
|
}
|
|
501
442
|
|
|
502
|
-
/**
|
|
503
|
-
* 将 JSON Schema 属性转换为 Zod 类型
|
|
504
|
-
*/
|
|
505
443
|
_jsonSchemaPropToZod(prop, isRequired) {
|
|
506
444
|
if (prop.enum) {
|
|
507
445
|
let zodType = z.string().enum(prop.enum);
|
|
@@ -534,9 +472,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
534
472
|
}
|
|
535
473
|
}
|
|
536
474
|
|
|
537
|
-
/**
|
|
538
|
-
* 将 JSON Schema 转换为 Markdown(简单格式)
|
|
539
|
-
*/
|
|
540
475
|
_schemaToMarkdown(schema) {
|
|
541
476
|
if (!schema || !schema.properties) return null;
|
|
542
477
|
|
|
@@ -562,9 +497,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
562
497
|
}));
|
|
563
498
|
}
|
|
564
499
|
|
|
565
|
-
/**
|
|
566
|
-
* 获取 skill 命令列表(用于 autocomplete)
|
|
567
|
-
*/
|
|
568
500
|
getSkillCommands() {
|
|
569
501
|
const ext = this._extensions.get('skill');
|
|
570
502
|
if (!ext) return [];
|
|
@@ -577,9 +509,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
577
509
|
}));
|
|
578
510
|
}
|
|
579
511
|
|
|
580
|
-
/**
|
|
581
|
-
* 获取 skill 命令帮助文本
|
|
582
|
-
*/
|
|
583
512
|
getSkillCommandsHelp() {
|
|
584
513
|
const ext = this._extensions.get('skill');
|
|
585
514
|
if (!ext || ext.tools.length === 0) return '';
|
|
@@ -595,12 +524,6 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
595
524
|
return lines.join('\n');
|
|
596
525
|
}
|
|
597
526
|
|
|
598
|
-
/**
|
|
599
|
-
* 检查并执行 skill 命令
|
|
600
|
-
* @param {string} command - 命令名(如 "skillname:cmdname")
|
|
601
|
-
* @param {string} args - 命令参数
|
|
602
|
-
* @returns {Promise<object|null>} 执行结果,失败返回 null
|
|
603
|
-
*/
|
|
604
527
|
async executeSkillCommand(command, args) {
|
|
605
528
|
if (!command.includes(':')) return null;
|
|
606
529
|
try {
|
|
@@ -618,24 +541,17 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
618
541
|
|
|
619
542
|
async reload(framework) {
|
|
620
543
|
this._framework = framework;
|
|
621
|
-
// 重新扫描所有已加载插件的 tools
|
|
622
544
|
this._extensions.clear();
|
|
623
545
|
const plugins = framework.pluginManager.getAll();
|
|
624
546
|
for (const { instance: plugin } of plugins) {
|
|
625
|
-
// 使用 _rescanPluginTools 以正确处理 skill-manager 的 'skill' extName 映射
|
|
626
|
-
// (_scanPluginTools 不传 extName 时会用 pluginName,对 skill-manager 不正确)
|
|
627
547
|
this._rescanPluginTools(plugin);
|
|
628
548
|
}
|
|
629
|
-
// 重新获取 MCP executor 引用
|
|
630
549
|
this._mcpExecutor = framework.pluginManager?.get('mcp') || null;
|
|
631
|
-
// 刷新所有 Agent 的扩展提示词
|
|
632
550
|
this._refreshAllAgentsExtPrompt(framework);
|
|
633
551
|
|
|
634
|
-
// 同时重载 MCP 配置
|
|
635
552
|
await this._reloadMCPConfig(framework);
|
|
636
553
|
}
|
|
637
554
|
|
|
638
|
-
// 重载 MCP 配置
|
|
639
555
|
async _reloadMCPConfig(framework) {
|
|
640
556
|
const fs = require('fs');
|
|
641
557
|
const path = require('path');
|
|
@@ -661,4 +577,4 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
661
577
|
}
|
|
662
578
|
}
|
|
663
579
|
|
|
664
|
-
module.exports = ExtensionExecutorPlugin
|
|
580
|
+
module.exports = ExtensionExecutorPlugin
|