@capyclaw/tool-host 0.1.0 → 0.1.1
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/dsh-suite.json +6 -4
- package/package.json +15 -2
- package/src/index.mjs +341 -341
- package/src/optimizers/E2E/346/265/213/350/257/225/346/212/245/345/221/212.md +0 -396
- package/src/optimizers/PPT/345/234/272/346/231/257/344/274/230/345/214/226/346/226/271/346/241/210.md +0 -607
- package/src/optimizers/PPT/345/256/236/346/227/266/346/270/262/346/237/223/346/226/271/346/241/210.md +0 -456
- package/src/optimizers/PPT/346/265/201/345/274/217/346/270/262/346/237/223-/347/224/237/344/272/247/347/272/247/344/274/230/345/214/226.md +0 -874
- package/src/optimizers/README.md +0 -374
- package/src/optimizers/batch-optimizer.mjs +0 -94
- package/src/optimizers/cache-optimizer.mjs +0 -217
- package/src/optimizers/concurrency-optimizer.mjs +0 -129
- package/src/optimizers/e2e-test.mjs +0 -674
- package/src/optimizers/examples.mjs +0 -243
- package/src/optimizers/index.mjs +0 -188
- package/src/optimizers/ppt-optimizer.mjs +0 -263
- package/src/optimizers/ppt-streaming-demo.mjs +0 -192
- package/src/optimizers/ppt-streaming-renderer.mjs +0 -332
- package/src/optimizers/production-streaming-demo.mjs +0 -267
- package/src/optimizers/production-streaming-renderer.mjs +0 -611
- package/src/optimizers/real-ppt-test.mjs +0 -397
- package/src/optimizers/real-world-benchmark.mjs +0 -470
- package/src/optimizers/retry-optimizer.mjs +0 -118
- package/src/optimizers//347/224/237/344/272/247/347/272/247/344/274/230/345/214/226/346/200/273/347/273/223.md +0 -110
- package/src/optimizers//347/234/237/345/256/236/346/200/247/350/203/275/346/217/220/345/215/207/351/252/214/350/257/201/346/212/245/345/221/212.md +0 -331
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP 2.0 优化示例
|
|
3
|
-
*
|
|
4
|
-
* 展示如何在实际项目中使用优化器
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { createOptimizedExecutor } from './optimizers/index.mjs';
|
|
8
|
-
import { Client } from '@modelcontextprotocol/client';
|
|
9
|
-
|
|
10
|
-
// ============================================
|
|
11
|
-
// 示例 1: 基础使用
|
|
12
|
-
// ============================================
|
|
13
|
-
|
|
14
|
-
async function basicExample() {
|
|
15
|
-
// 创建 MCP 客户端
|
|
16
|
-
const client = new Client({
|
|
17
|
-
name: 'dsh-example',
|
|
18
|
-
version: '1.0.0'
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// 创建优化执行器
|
|
22
|
-
const executor = createOptimizedExecutor(client, {
|
|
23
|
-
batchSize: 10, // 批量大小
|
|
24
|
-
maxConcurrent: 20, // 最大并发
|
|
25
|
-
maxRetries: 3, // 最大重试次数
|
|
26
|
-
cacheTTL: 300000 // 缓存5分钟
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// 普通调用(自动重试+并发控制)
|
|
30
|
-
const result = await executor.callTool('analyze_text', {
|
|
31
|
-
text: 'Hello world'
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
console.log('Result:', result);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ============================================
|
|
38
|
-
// 示例 2: 批量操作
|
|
39
|
-
// ============================================
|
|
40
|
-
|
|
41
|
-
async function batchExample(executor) {
|
|
42
|
-
console.log('=== 批量操作示例 ===\n');
|
|
43
|
-
|
|
44
|
-
// 批量调用(自动合并为一个请求)
|
|
45
|
-
const start = Date.now();
|
|
46
|
-
|
|
47
|
-
const results = await Promise.all([
|
|
48
|
-
executor.callTool('process_item', { id: 1 }, { batch: true }),
|
|
49
|
-
executor.callTool('process_item', { id: 2 }, { batch: true }),
|
|
50
|
-
executor.callTool('process_item', { id: 3 }, { batch: true }),
|
|
51
|
-
executor.callTool('process_item', { id: 4 }, { batch: true }),
|
|
52
|
-
executor.callTool('process_item', { id: 5 }, { batch: true }),
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
const duration = Date.now() - start;
|
|
56
|
-
console.log(`✅ 批量处理完成: ${results.length} items in ${duration}ms`);
|
|
57
|
-
console.log(` 平均: ${(duration / results.length).toFixed(2)}ms/item\n`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ============================================
|
|
61
|
-
// 示例 3: 智能缓存
|
|
62
|
-
// ============================================
|
|
63
|
-
|
|
64
|
-
async function cacheExample(executor) {
|
|
65
|
-
console.log('=== 智能缓存示例 ===\n');
|
|
66
|
-
|
|
67
|
-
// 第一次调用(无缓存)
|
|
68
|
-
console.log('第一次调用...');
|
|
69
|
-
const start1 = Date.now();
|
|
70
|
-
const schema1 = await executor.callTool('get_tool_schema',
|
|
71
|
-
{ name: 'my_tool' },
|
|
72
|
-
{ cacheable: true }
|
|
73
|
-
);
|
|
74
|
-
console.log(` 耗时: ${Date.now() - start1}ms\n`);
|
|
75
|
-
|
|
76
|
-
// 第二次调用(命中缓存)
|
|
77
|
-
console.log('第二次调用(应该命中缓存)...');
|
|
78
|
-
const start2 = Date.now();
|
|
79
|
-
const schema2 = await executor.callTool('get_tool_schema',
|
|
80
|
-
{ name: 'my_tool' },
|
|
81
|
-
{ cacheable: true }
|
|
82
|
-
);
|
|
83
|
-
console.log(` 耗时: ${Date.now() - start2}ms`);
|
|
84
|
-
console.log(` 性能提升: ${Math.floor((Date.now() - start1) / (Date.now() - start2))}x\n`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// ============================================
|
|
88
|
-
// 示例 4: 并发控制
|
|
89
|
-
// ============================================
|
|
90
|
-
|
|
91
|
-
async function concurrencyExample(executor) {
|
|
92
|
-
console.log('=== 并发控制示例 ===\n');
|
|
93
|
-
|
|
94
|
-
const items = Array.from({ length: 50 }, (_, i) => i + 1);
|
|
95
|
-
|
|
96
|
-
console.log(`处理 ${items.length} 个任务...`);
|
|
97
|
-
const start = Date.now();
|
|
98
|
-
|
|
99
|
-
// 自动限流(不会压垮服务器)
|
|
100
|
-
const results = await Promise.all(
|
|
101
|
-
items.map(id =>
|
|
102
|
-
executor.callTool('heavy_task', { id })
|
|
103
|
-
)
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
const duration = Date.now() - start;
|
|
107
|
-
console.log(`✅ 完成: ${results.length} tasks in ${duration}ms`);
|
|
108
|
-
console.log(` 吞吐量: ${(results.length / (duration / 1000)).toFixed(2)} ops/s\n`);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ============================================
|
|
112
|
-
// 示例 5: 智能重试
|
|
113
|
-
// ============================================
|
|
114
|
-
|
|
115
|
-
async function retryExample(executor) {
|
|
116
|
-
console.log('=== 智能重试示例 ===\n');
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
// 模拟不稳定的网络调用
|
|
120
|
-
const result = await executor.callTool('unstable_api', {
|
|
121
|
-
url: 'https://example.com/api',
|
|
122
|
-
failRate: 0.5 // 50% 失败率
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
console.log('✅ 调用成功(可能经过重试):', result);
|
|
126
|
-
} catch (error) {
|
|
127
|
-
console.log('❌ 所有重试失败:', error.message);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// ============================================
|
|
132
|
-
// 示例 6: 统计监控
|
|
133
|
-
// ============================================
|
|
134
|
-
|
|
135
|
-
async function monitoringExample(executor) {
|
|
136
|
-
console.log('=== 统计监控示例 ===\n');
|
|
137
|
-
|
|
138
|
-
// 执行一些操作
|
|
139
|
-
await executor.callTool('task1', {});
|
|
140
|
-
await executor.callTool('task2', {}, { batch: true });
|
|
141
|
-
await executor.callTool('task3', {}, { cacheable: true });
|
|
142
|
-
|
|
143
|
-
// 获取统计信息
|
|
144
|
-
const stats = executor.getStats();
|
|
145
|
-
|
|
146
|
-
console.log('📊 执行统计:');
|
|
147
|
-
console.log(' 总调用:', stats.calls);
|
|
148
|
-
console.log(' 批量调用:', stats.batched);
|
|
149
|
-
console.log(' 缓存命中:', stats.cached);
|
|
150
|
-
console.log(' 错误数:', stats.errors);
|
|
151
|
-
console.log(' 缓存命中率:', stats.cacheHitRate);
|
|
152
|
-
console.log(' 错误率:', stats.errorRate);
|
|
153
|
-
console.log(' RPS:', stats.rps);
|
|
154
|
-
console.log(' 运行时间:', (stats.runtime / 1000).toFixed(2) + 's\n');
|
|
155
|
-
|
|
156
|
-
console.log('📈 并发状态:');
|
|
157
|
-
console.log(' 当前并发:', stats.concurrency.currentConcurrent);
|
|
158
|
-
console.log(' 运行中:', stats.concurrency.running);
|
|
159
|
-
console.log(' 队列中:', stats.concurrency.queued);
|
|
160
|
-
console.log(' 成功:', stats.concurrency.successCount);
|
|
161
|
-
console.log(' 失败:', stats.concurrency.errorCount);
|
|
162
|
-
console.log('\n');
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// ============================================
|
|
166
|
-
// 示例 7: 与现有 tool-host 集成
|
|
167
|
-
// ============================================
|
|
168
|
-
|
|
169
|
-
export function createOptimizedToolHost(capabilities, options = {}) {
|
|
170
|
-
const registry = createRegistry(capabilities, options);
|
|
171
|
-
|
|
172
|
-
// 创建优化执行器
|
|
173
|
-
const executor = createOptimizedExecutor(registry.client, {
|
|
174
|
-
batchSize: options.batchSize || 10,
|
|
175
|
-
maxConcurrent: options.maxConcurrent || 20,
|
|
176
|
-
maxRetries: options.maxRetries || 3
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
tools: registry.TOOLS,
|
|
181
|
-
|
|
182
|
-
// 优化的 callTool
|
|
183
|
-
async callTool(name, args, context = {}) {
|
|
184
|
-
// 根据工具类型自动选择策略
|
|
185
|
-
const tool = registry.TOOL_META[name];
|
|
186
|
-
|
|
187
|
-
if (!tool) {
|
|
188
|
-
throw new Error(`Tool not found: ${name}`);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const options = {
|
|
192
|
-
// 读取操作可以缓存
|
|
193
|
-
cacheable: tool.kind === 'read',
|
|
194
|
-
// 多个同类操作可以批量
|
|
195
|
-
batch: context.enableBatch || false
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
return executor.callTool(name, args, options);
|
|
199
|
-
},
|
|
200
|
-
|
|
201
|
-
// 批量调用
|
|
202
|
-
async callTools(calls) {
|
|
203
|
-
return executor.callTools(calls);
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
// 获取统计
|
|
207
|
-
getStats() {
|
|
208
|
-
return executor.getStats();
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// ============================================
|
|
214
|
-
// 完整运行示例
|
|
215
|
-
// ============================================
|
|
216
|
-
|
|
217
|
-
async function main() {
|
|
218
|
-
console.log('🚀 MCP 2.0 优化器演示\n');
|
|
219
|
-
console.log('='.repeat(50) + '\n');
|
|
220
|
-
|
|
221
|
-
const client = new Client({ name: 'demo', version: '1.0.0' });
|
|
222
|
-
const executor = createOptimizedExecutor(client);
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
await basicExample();
|
|
226
|
-
await batchExample(executor);
|
|
227
|
-
await cacheExample(executor);
|
|
228
|
-
await concurrencyExample(executor);
|
|
229
|
-
await retryExample(executor);
|
|
230
|
-
await monitoringExample(executor);
|
|
231
|
-
|
|
232
|
-
console.log('✅ 所有示例运行完成!');
|
|
233
|
-
} catch (error) {
|
|
234
|
-
console.error('❌ 错误:', error);
|
|
235
|
-
} finally {
|
|
236
|
-
executor.destroy();
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// 如果直接运行此文件
|
|
241
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
242
|
-
main().catch(console.error);
|
|
243
|
-
}
|
package/src/optimizers/index.mjs
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP 2.0 统一优化执行器
|
|
3
|
-
*
|
|
4
|
-
* 整合所有优化特性:
|
|
5
|
-
* - 批量操作
|
|
6
|
-
* - 智能重试
|
|
7
|
-
* - 并发控制
|
|
8
|
-
* - 资源缓存
|
|
9
|
-
* - 流式响应(预留)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { BatchToolExecutor } from './batch-optimizer.mjs';
|
|
13
|
-
import { RetryManager } from './retry-optimizer.mjs';
|
|
14
|
-
import { AdaptiveConcurrencyManager } from './concurrency-optimizer.mjs';
|
|
15
|
-
import { CachedToolExecutor } from './cache-optimizer.mjs';
|
|
16
|
-
|
|
17
|
-
export class OptimizedMCPExecutor {
|
|
18
|
-
constructor(client, options = {}) {
|
|
19
|
-
this.client = client;
|
|
20
|
-
this.options = options;
|
|
21
|
-
|
|
22
|
-
// 批量执行器
|
|
23
|
-
this.batchExecutor = new BatchToolExecutor(client, {
|
|
24
|
-
batchSize: options.batchSize || 10,
|
|
25
|
-
batchTimeout: options.batchTimeout || 100
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// 并发管理器
|
|
29
|
-
this.concurrencyManager = new AdaptiveConcurrencyManager({
|
|
30
|
-
min: options.minConcurrent || 1,
|
|
31
|
-
max: options.maxConcurrent || 20,
|
|
32
|
-
initial: options.initialConcurrent || 5
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// 重试管理器
|
|
36
|
-
this.retryManager = new RetryManager({
|
|
37
|
-
maxRetries: options.maxRetries || 3,
|
|
38
|
-
initialDelay: options.retryDelay || 1000
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// 缓存执行器
|
|
42
|
-
this.cachedExecutor = new CachedToolExecutor(client, {
|
|
43
|
-
schemaTTL: options.schemaTTL || 3600000,
|
|
44
|
-
resultTTL: options.resultTTL || 60000,
|
|
45
|
-
maxSize: options.cacheSize || 1000
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// 统计信息
|
|
49
|
-
this.stats = {
|
|
50
|
-
calls: 0,
|
|
51
|
-
batched: 0,
|
|
52
|
-
cached: 0,
|
|
53
|
-
retried: 0,
|
|
54
|
-
errors: 0,
|
|
55
|
-
startTime: Date.now()
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 智能工具调用
|
|
61
|
-
* 自动选择最优执行策略
|
|
62
|
-
*/
|
|
63
|
-
async callTool(name, args, options = {}) {
|
|
64
|
-
this.stats.calls++;
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
// 1. 检查缓存(对于schema查询等幂等操作)
|
|
68
|
-
if (options.cacheable) {
|
|
69
|
-
this.stats.cached++;
|
|
70
|
-
return await this.cachedExecutor.callTool(name, args, options);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// 2. 批量调用(对于可以合并的操作)
|
|
74
|
-
if (options.batch) {
|
|
75
|
-
this.stats.batched++;
|
|
76
|
-
return await this.batchExecutor.callTool(name, args);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// 3. 普通调用(带重试和并发控制)
|
|
80
|
-
return await this.concurrencyManager.execute(async () => {
|
|
81
|
-
return await this.retryManager.execute(async () => {
|
|
82
|
-
return await this.client.request('tools/call', {
|
|
83
|
-
name,
|
|
84
|
-
arguments: args
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
} catch (error) {
|
|
90
|
-
this.stats.errors++;
|
|
91
|
-
throw error;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* 批量调用多个工具
|
|
97
|
-
*/
|
|
98
|
-
async callTools(calls, options = {}) {
|
|
99
|
-
return Promise.all(
|
|
100
|
-
calls.map(call =>
|
|
101
|
-
this.callTool(call.name, call.args, {
|
|
102
|
-
...options,
|
|
103
|
-
...call.options
|
|
104
|
-
})
|
|
105
|
-
)
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* 获取工具列表(带缓存)
|
|
111
|
-
*/
|
|
112
|
-
async listTools() {
|
|
113
|
-
return this.callTool('tools/list', {}, {
|
|
114
|
-
cacheable: true,
|
|
115
|
-
cacheKey: 'tools_list',
|
|
116
|
-
cacheTTL: 600000 // 10分钟
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* 获取统计信息
|
|
122
|
-
*/
|
|
123
|
-
getStats() {
|
|
124
|
-
const runtime = Date.now() - this.stats.startTime;
|
|
125
|
-
const rps = this.stats.calls / (runtime / 1000);
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
...this.stats,
|
|
129
|
-
runtime,
|
|
130
|
-
rps: rps.toFixed(2),
|
|
131
|
-
cacheHitRate: (this.stats.cached / this.stats.calls * 100).toFixed(1) + '%',
|
|
132
|
-
errorRate: (this.stats.errors / this.stats.calls * 100).toFixed(1) + '%',
|
|
133
|
-
concurrency: this.concurrencyManager.getStats(),
|
|
134
|
-
cache: this.cachedExecutor.getStats()
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* 重置统计
|
|
140
|
-
*/
|
|
141
|
-
resetStats() {
|
|
142
|
-
this.stats = {
|
|
143
|
-
calls: 0,
|
|
144
|
-
batched: 0,
|
|
145
|
-
cached: 0,
|
|
146
|
-
retried: 0,
|
|
147
|
-
errors: 0,
|
|
148
|
-
startTime: Date.now()
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* 销毁
|
|
154
|
-
*/
|
|
155
|
-
destroy() {
|
|
156
|
-
this.cachedExecutor.destroy();
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* 创建优化的MCP执行器
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* const executor = createOptimizedExecutor(client, {
|
|
165
|
-
* batchSize: 10,
|
|
166
|
-
* maxConcurrent: 20,
|
|
167
|
-
* maxRetries: 3
|
|
168
|
-
* });
|
|
169
|
-
*
|
|
170
|
-
* // 普通调用
|
|
171
|
-
* const result = await executor.callTool('my_tool', { arg: 'value' });
|
|
172
|
-
*
|
|
173
|
-
* // 批量调用
|
|
174
|
-
* await executor.callTool('tool1', {}, { batch: true });
|
|
175
|
-
* await executor.callTool('tool2', {}, { batch: true });
|
|
176
|
-
*
|
|
177
|
-
* // 缓存调用
|
|
178
|
-
* const schema = await executor.callTool('get_schema', {}, { cacheable: true });
|
|
179
|
-
*/
|
|
180
|
-
export function createOptimizedExecutor(client, options = {}) {
|
|
181
|
-
return new OptimizedMCPExecutor(client, options);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// 导出所有优化器
|
|
185
|
-
export { BatchToolExecutor } from './batch-optimizer.mjs';
|
|
186
|
-
export { RetryManager, withRetry } from './retry-optimizer.mjs';
|
|
187
|
-
export { ConcurrencyLimiter, AdaptiveConcurrencyManager } from './concurrency-optimizer.mjs';
|
|
188
|
-
export { ResourceCache, CachedToolExecutor } from './cache-optimizer.mjs';
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PPT 场景专用 MCP 2.0 优化器
|
|
3
|
-
*
|
|
4
|
-
* 针对 PPT 工作台的特定使用模式优化:
|
|
5
|
-
* - 频繁状态查询 → 多级缓存
|
|
6
|
-
* - 批量元素操作 → 智能批量
|
|
7
|
-
* - 长时间设计操作 → 流式进度
|
|
8
|
-
* - 编辑后刷新 → 智能失效
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
export class PPTOptimizedExecutor {
|
|
12
|
-
constructor(client, options = {}) {
|
|
13
|
-
this.client = client;
|
|
14
|
-
|
|
15
|
-
// PPT 多级缓存
|
|
16
|
-
this.caches = {
|
|
17
|
-
schema: { map: new Map(), ttl: 3600000 }, // 1小时 - 能力/模板
|
|
18
|
-
document: { map: new Map(), ttl: 300000 }, // 5分钟 - 文档信息
|
|
19
|
-
elements: { map: new Map(), ttl: 30000 } // 30秒 - 元素信息
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// 批量队列
|
|
23
|
-
this.batchQueue = [];
|
|
24
|
-
this.batchTimer = null;
|
|
25
|
-
|
|
26
|
-
// 统计
|
|
27
|
-
this.stats = {
|
|
28
|
-
queries: 0,
|
|
29
|
-
edits: 0,
|
|
30
|
-
designs: 0,
|
|
31
|
-
cacheHits: 0,
|
|
32
|
-
batched: 0
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* 智能工具调用
|
|
38
|
-
*/
|
|
39
|
-
async callTool(name, args, options = {}) {
|
|
40
|
-
const toolType = this._identifyToolType(name);
|
|
41
|
-
|
|
42
|
-
switch (toolType) {
|
|
43
|
-
case 'query':
|
|
44
|
-
return this._handleQuery(name, args, options);
|
|
45
|
-
case 'edit':
|
|
46
|
-
return this._handleEdit(name, args, options);
|
|
47
|
-
case 'design':
|
|
48
|
-
return this._handleDesign(name, args, options);
|
|
49
|
-
default:
|
|
50
|
-
return this._handleGeneric(name, args, options);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 查询操作 - 多级缓存
|
|
56
|
-
*/
|
|
57
|
-
async _handleQuery(name, args, options) {
|
|
58
|
-
this.stats.queries++;
|
|
59
|
-
|
|
60
|
-
// 选择缓存级别
|
|
61
|
-
const cacheLevel = this._getCacheLevel(name);
|
|
62
|
-
const cache = this.caches[cacheLevel];
|
|
63
|
-
const cacheKey = `${name}:${JSON.stringify(args)}`;
|
|
64
|
-
|
|
65
|
-
// 检查缓存
|
|
66
|
-
if (cache.map.has(cacheKey)) {
|
|
67
|
-
const cached = cache.map.get(cacheKey);
|
|
68
|
-
if (Date.now() - cached.timestamp < cache.ttl) {
|
|
69
|
-
this.stats.cacheHits++;
|
|
70
|
-
return cached.data;
|
|
71
|
-
}
|
|
72
|
-
cache.map.delete(cacheKey);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// 请求数据
|
|
76
|
-
const result = await this.client.request('tools/call', {
|
|
77
|
-
name,
|
|
78
|
-
arguments: args
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// 存入缓存
|
|
82
|
-
cache.map.set(cacheKey, {
|
|
83
|
-
data: result,
|
|
84
|
-
timestamp: Date.now()
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return result;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* 编辑操作 - 批量优化
|
|
92
|
-
*/
|
|
93
|
-
async _handleEdit(name, args, options) {
|
|
94
|
-
this.stats.edits++;
|
|
95
|
-
|
|
96
|
-
// 批量模式
|
|
97
|
-
if (options.batch !== false) {
|
|
98
|
-
this.stats.batched++;
|
|
99
|
-
return this._batchEdit(name, args);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// 单个编辑
|
|
103
|
-
const result = await this.client.request('tools/call', {
|
|
104
|
-
name,
|
|
105
|
-
arguments: args
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// 失效缓存
|
|
109
|
-
this._invalidateCache(name);
|
|
110
|
-
|
|
111
|
-
return result;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* 设计操作 - 进度反馈
|
|
116
|
-
*/
|
|
117
|
-
async _handleDesign(name, args, options) {
|
|
118
|
-
this.stats.designs++;
|
|
119
|
-
|
|
120
|
-
// 带进度
|
|
121
|
-
if (options.onProgress) {
|
|
122
|
-
const interval = setInterval(() => {
|
|
123
|
-
options.onProgress({ status: 'processing' });
|
|
124
|
-
}, 1000);
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
const result = await this.client.request('tools/call', {
|
|
128
|
-
name,
|
|
129
|
-
arguments: args
|
|
130
|
-
});
|
|
131
|
-
clearInterval(interval);
|
|
132
|
-
options.onProgress({ status: 'complete', progress: 100 });
|
|
133
|
-
return result;
|
|
134
|
-
} catch (error) {
|
|
135
|
-
clearInterval(interval);
|
|
136
|
-
options.onProgress({ status: 'error' });
|
|
137
|
-
throw error;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return this.client.request('tools/call', { name, arguments: args });
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* 通用操作
|
|
146
|
-
*/
|
|
147
|
-
async _handleGeneric(name, args, options) {
|
|
148
|
-
return this.client.request('tools/call', {
|
|
149
|
-
name,
|
|
150
|
-
arguments: args
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* 批量编辑
|
|
156
|
-
*/
|
|
157
|
-
async _batchEdit(name, args) {
|
|
158
|
-
return new Promise((resolve, reject) => {
|
|
159
|
-
this.batchQueue.push({ name, args, resolve, reject });
|
|
160
|
-
|
|
161
|
-
if (!this.batchTimer) {
|
|
162
|
-
this.batchTimer = setTimeout(() => this._flushBatch(), 50);
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async _flushBatch() {
|
|
168
|
-
this.batchTimer = null;
|
|
169
|
-
if (this.batchQueue.length === 0) return;
|
|
170
|
-
|
|
171
|
-
const batch = this.batchQueue.splice(0);
|
|
172
|
-
|
|
173
|
-
// 并行执行
|
|
174
|
-
const results = await Promise.allSettled(
|
|
175
|
-
batch.map(item =>
|
|
176
|
-
this.client.request('tools/call', {
|
|
177
|
-
name: item.name,
|
|
178
|
-
arguments: item.args
|
|
179
|
-
})
|
|
180
|
-
)
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
// 失效缓存
|
|
184
|
-
this._invalidateCache('batch');
|
|
185
|
-
|
|
186
|
-
// 分发结果
|
|
187
|
-
batch.forEach((item, i) => {
|
|
188
|
-
if (results[i].status === 'fulfilled') {
|
|
189
|
-
item.resolve(results[i].value);
|
|
190
|
-
} else {
|
|
191
|
-
item.reject(results[i].reason);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* 识别工具类型
|
|
198
|
-
*/
|
|
199
|
-
_identifyToolType(name) {
|
|
200
|
-
if (name.startsWith('ppt_get_') || name.startsWith('ppt_list_')) {
|
|
201
|
-
return 'query';
|
|
202
|
-
}
|
|
203
|
-
if (name.startsWith('ppt_add_') || name.startsWith('ppt_update_') ||
|
|
204
|
-
name.startsWith('ppt_delete_') || name.startsWith('ppt_set_')) {
|
|
205
|
-
return 'edit';
|
|
206
|
-
}
|
|
207
|
-
if (name.includes('design') || name.includes('layout') || name.includes('format')) {
|
|
208
|
-
return 'design';
|
|
209
|
-
}
|
|
210
|
-
return 'generic';
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* 确定缓存级别
|
|
215
|
-
*/
|
|
216
|
-
_getCacheLevel(name) {
|
|
217
|
-
if (name.includes('capabilities') || name.includes('template')) {
|
|
218
|
-
return 'schema';
|
|
219
|
-
}
|
|
220
|
-
if (name.includes('element') || name.includes('selection')) {
|
|
221
|
-
return 'elements';
|
|
222
|
-
}
|
|
223
|
-
return 'document';
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* 失效缓存
|
|
228
|
-
*/
|
|
229
|
-
_invalidateCache(name) {
|
|
230
|
-
// 编辑操作清除元素缓存
|
|
231
|
-
if (name.includes('add') || name.includes('update') || name.includes('delete')) {
|
|
232
|
-
this.caches.elements.map.clear();
|
|
233
|
-
}
|
|
234
|
-
// 幻灯片操作清除文档缓存
|
|
235
|
-
if (name.includes('slide') && !name.includes('element')) {
|
|
236
|
-
this.caches.document.map.clear();
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* 统计信息
|
|
242
|
-
*/
|
|
243
|
-
getStats() {
|
|
244
|
-
const total = this.stats.queries + this.stats.edits + this.stats.designs;
|
|
245
|
-
return {
|
|
246
|
-
total,
|
|
247
|
-
queries: this.stats.queries,
|
|
248
|
-
edits: this.stats.edits,
|
|
249
|
-
designs: this.stats.designs,
|
|
250
|
-
cacheHits: this.stats.cacheHits,
|
|
251
|
-
batched: this.stats.batched,
|
|
252
|
-
cacheHitRate: total > 0 ? (this.stats.cacheHits / total * 100).toFixed(1) + '%' : '0%',
|
|
253
|
-
batchRate: this.stats.edits > 0 ? (this.stats.batched / this.stats.edits * 100).toFixed(1) + '%' : '0%'
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* 创建 PPT 优化执行器
|
|
260
|
-
*/
|
|
261
|
-
export function createPPTOptimizer(client, options = {}) {
|
|
262
|
-
return new PPTOptimizedExecutor(client, options);
|
|
263
|
-
}
|