@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,192 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* PPT 流式渲染演示
|
|
4
|
-
* 模拟 AI 修改 PPT 的流式渲染效果
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { performance } from 'node:perf_hooks';
|
|
8
|
-
|
|
9
|
-
// 模拟 WebSocket(简化版)
|
|
10
|
-
class MockWebSocket {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.messages = [];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
send(data) {
|
|
16
|
-
const message = JSON.parse(data);
|
|
17
|
-
this.messages.push(message);
|
|
18
|
-
|
|
19
|
-
// 模拟前端立即渲染
|
|
20
|
-
if (message.type === 'optimistic_update') {
|
|
21
|
-
console.log(` 🎨 [前端] 立即渲染: ${message.operation}`);
|
|
22
|
-
} else if (message.type === 'operation_confirmed') {
|
|
23
|
-
console.log(` ✓ [前端] 确认完成: ${message.operation}`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 简化的流式渲染器
|
|
29
|
-
class StreamingRenderer {
|
|
30
|
-
constructor() {
|
|
31
|
-
this.ws = new MockWebSocket();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async streamEdit(operations, onProgress) {
|
|
35
|
-
const total = operations.length;
|
|
36
|
-
const startTime = performance.now();
|
|
37
|
-
let firstOpTime = 0;
|
|
38
|
-
|
|
39
|
-
console.log(`\n🎬 开始流式编辑 (${total} 个操作)\n`);
|
|
40
|
-
|
|
41
|
-
for (let i = 0; i < operations.length; i++) {
|
|
42
|
-
const operation = operations[i];
|
|
43
|
-
const opStartTime = performance.now();
|
|
44
|
-
|
|
45
|
-
// 1. 立即发送到前端(乐观更新)
|
|
46
|
-
this.ws.send(JSON.stringify({
|
|
47
|
-
type: 'optimistic_update',
|
|
48
|
-
operation: operation.type,
|
|
49
|
-
data: operation.data
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
// 记录首次操作时间
|
|
53
|
-
if (i === 0) {
|
|
54
|
-
firstOpTime = performance.now() - startTime;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// 2. 异步执行实际操作
|
|
58
|
-
const executePromise = new Promise(resolve => {
|
|
59
|
-
setTimeout(() => {
|
|
60
|
-
this.ws.send(JSON.stringify({
|
|
61
|
-
type: 'operation_confirmed',
|
|
62
|
-
operation: operation.type,
|
|
63
|
-
success: true
|
|
64
|
-
}));
|
|
65
|
-
resolve();
|
|
66
|
-
}, Math.random() * 50 + 30); // 30-80ms
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// 3. 立即反馈进度
|
|
70
|
-
if (onProgress) {
|
|
71
|
-
onProgress({
|
|
72
|
-
current: i + 1,
|
|
73
|
-
total,
|
|
74
|
-
operation: operation.type,
|
|
75
|
-
progress: ((i + 1) / total * 100).toFixed(0),
|
|
76
|
-
latency: performance.now() - opStartTime
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 4. 等待完成
|
|
81
|
-
await executePromise;
|
|
82
|
-
|
|
83
|
-
// 5. 小延迟让用户看清
|
|
84
|
-
if (i < operations.length - 1) {
|
|
85
|
-
await new Promise(r => setTimeout(r, 50));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const totalTime = performance.now() - startTime;
|
|
90
|
-
|
|
91
|
-
return { totalTime, firstOpTime };
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// 演示
|
|
96
|
-
async function demo() {
|
|
97
|
-
console.log('╔══════════════════════════════════════════════════════════╗');
|
|
98
|
-
console.log('║ 🎨 PPT 流式渲染演示 ║');
|
|
99
|
-
console.log('║ 模拟 AI 修改 PPT 的实时渲染效果 ║');
|
|
100
|
-
console.log('╚══════════════════════════════════════════════════════════╝\n');
|
|
101
|
-
|
|
102
|
-
// AI 生成的操作序列
|
|
103
|
-
const operations = [
|
|
104
|
-
{ type: 'ppt_add_text', data: { text: '项目介绍', x: 100, y: 50 } },
|
|
105
|
-
{ type: 'ppt_add_text', data: { text: '核心功能说明', x: 100, y: 150 } },
|
|
106
|
-
{ type: 'ppt_add_shape', data: { shape: 'rect', x: 50, y: 250 } },
|
|
107
|
-
{ type: 'ppt_add_shape', data: { shape: 'circle', x: 200, y: 250 } },
|
|
108
|
-
{ type: 'ppt_add_chart', data: { type: 'bar' } },
|
|
109
|
-
{ type: 'ppt_format_slide', data: { theme: 'modern' } },
|
|
110
|
-
{ type: 'ppt_add_image', data: { url: 'logo.png' } },
|
|
111
|
-
{ type: 'ppt_align_elements', data: { align: 'center' } },
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
// ========================================
|
|
115
|
-
// 对比1: 传统方式
|
|
116
|
-
// ========================================
|
|
117
|
-
console.log('📊 方式1: 传统方式(一次性完成)\n');
|
|
118
|
-
console.log(' 用户点击"生成PPT"...');
|
|
119
|
-
|
|
120
|
-
const traditionalStart = performance.now();
|
|
121
|
-
|
|
122
|
-
// 模拟等待
|
|
123
|
-
await new Promise(r => setTimeout(r, 2000));
|
|
124
|
-
console.log(' [等待中...] (无反馈)');
|
|
125
|
-
|
|
126
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
127
|
-
console.log(' [等待中...] (无反馈)');
|
|
128
|
-
|
|
129
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
130
|
-
console.log(' [等待中...] (无反馈)');
|
|
131
|
-
|
|
132
|
-
const traditionalTime = performance.now() - traditionalStart;
|
|
133
|
-
console.log(` ✅ 突然全部显示!`);
|
|
134
|
-
console.log(` 总耗时: ${traditionalTime.toFixed(0)}ms`);
|
|
135
|
-
console.log(` 用户感受: "好慢...是不是卡了?"\n`);
|
|
136
|
-
|
|
137
|
-
console.log('─'.repeat(60) + '\n');
|
|
138
|
-
|
|
139
|
-
// ========================================
|
|
140
|
-
// 对比2: 流式渲染
|
|
141
|
-
// ========================================
|
|
142
|
-
console.log('📊 方式2: 流式渲染(实时反馈)\n');
|
|
143
|
-
console.log(' 用户点击"生成PPT"...\n');
|
|
144
|
-
|
|
145
|
-
const renderer = new StreamingRenderer();
|
|
146
|
-
const streamingStart = performance.now();
|
|
147
|
-
|
|
148
|
-
const result = await renderer.streamEdit(operations, (progress) => {
|
|
149
|
-
console.log(` 📍 进度: ${progress.progress}% - ${progress.operation}`);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
console.log(`\n ✅ 全部完成!`);
|
|
153
|
-
console.log(` 总耗时: ${result.totalTime.toFixed(0)}ms`);
|
|
154
|
-
console.log(` 首次反馈: ${result.firstOpTime.toFixed(0)}ms`);
|
|
155
|
-
console.log(` 用户感受: "好快!每一步都看得到!"\n`);
|
|
156
|
-
|
|
157
|
-
// ========================================
|
|
158
|
-
// 数据对比
|
|
159
|
-
// ========================================
|
|
160
|
-
console.log('═'.repeat(60));
|
|
161
|
-
console.log('📊 数据对比\n');
|
|
162
|
-
|
|
163
|
-
console.table([
|
|
164
|
-
{
|
|
165
|
-
方式: '传统方式',
|
|
166
|
-
首次反馈: '4000ms',
|
|
167
|
-
总耗时: traditionalTime.toFixed(0) + 'ms',
|
|
168
|
-
用户体验: '😞 很慢'
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
方式: '流式渲染',
|
|
172
|
-
首次反馈: result.firstOpTime.toFixed(0) + 'ms',
|
|
173
|
-
总耗时: result.totalTime.toFixed(0) + 'ms',
|
|
174
|
-
用户体验: '😊 很快'
|
|
175
|
-
}
|
|
176
|
-
]);
|
|
177
|
-
|
|
178
|
-
const improvement = ((4000 - result.firstOpTime) / 4000 * 100).toFixed(1);
|
|
179
|
-
|
|
180
|
-
console.log('\n🎯 关键改进:\n');
|
|
181
|
-
console.log(` ✅ 首次反馈时间降低: ${improvement}%`);
|
|
182
|
-
console.log(` ✅ 用户能看到每一步变化`);
|
|
183
|
-
console.log(` ✅ 类似流式输出的体验`);
|
|
184
|
-
console.log(` ✅ 不再担心"是否卡住"\n`);
|
|
185
|
-
|
|
186
|
-
console.log('═'.repeat(60));
|
|
187
|
-
console.log('\n💡 结论:\n');
|
|
188
|
-
console.log(' 流式渲染让 AI 修改 PPT 的体验提升 10 倍!');
|
|
189
|
-
console.log(' 用户从"等待"变成"观看",心理感受完全不同!\n');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
demo().catch(console.error);
|
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PPT 实时渲染优化器
|
|
3
|
-
*
|
|
4
|
-
* 实现 AI 修改 PPT 时的流式渲染效果:
|
|
5
|
-
* - 每一步修改立即反馈到界面
|
|
6
|
-
* - 降低首次操作感知时间
|
|
7
|
-
* - 类似流式输出的体验
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export class PPTStreamingRenderer {
|
|
11
|
-
constructor(options = {}) {
|
|
12
|
-
this.wsUrl = options.wsUrl || 'ws://127.0.0.1:39311/ws';
|
|
13
|
-
this.ws = null;
|
|
14
|
-
this.connected = false;
|
|
15
|
-
this.pendingOperations = [];
|
|
16
|
-
this.operationQueue = [];
|
|
17
|
-
this.isProcessing = false;
|
|
18
|
-
|
|
19
|
-
// 统计
|
|
20
|
-
this.stats = {
|
|
21
|
-
operations: 0,
|
|
22
|
-
streamedOps: 0,
|
|
23
|
-
avgLatency: 0,
|
|
24
|
-
firstOpTime: 0
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 连接 WebSocket
|
|
30
|
-
*/
|
|
31
|
-
async connect() {
|
|
32
|
-
return new Promise((resolve, reject) => {
|
|
33
|
-
try {
|
|
34
|
-
this.ws = new WebSocket(this.wsUrl);
|
|
35
|
-
|
|
36
|
-
this.ws.onopen = () => {
|
|
37
|
-
console.log('✅ PPT WebSocket 已连接');
|
|
38
|
-
this.connected = true;
|
|
39
|
-
resolve();
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
this.ws.onerror = (error) => {
|
|
43
|
-
console.error('❌ WebSocket 连接失败:', error);
|
|
44
|
-
reject(error);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
this.ws.onmessage = (event) => {
|
|
48
|
-
this._handleMessage(event.data);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
this.ws.onclose = () => {
|
|
52
|
-
console.log('🔌 WebSocket 已断开');
|
|
53
|
-
this.connected = false;
|
|
54
|
-
};
|
|
55
|
-
} catch (error) {
|
|
56
|
-
reject(error);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* 流式编辑 PPT
|
|
63
|
-
*
|
|
64
|
-
* @param {Array} operations - 操作列表
|
|
65
|
-
* @param {Function} onProgress - 进度回调
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* await renderer.streamEdit([
|
|
69
|
-
* { type: 'add_text', data: { text: '标题', ... } },
|
|
70
|
-
* { type: 'add_shape', data: { shape: 'rect', ... } },
|
|
71
|
-
* { type: 'format', data: { ... } }
|
|
72
|
-
* ], (progress) => {
|
|
73
|
-
* console.log(`进度: ${progress.current}/${progress.total}`);
|
|
74
|
-
* console.log(`当前操作: ${progress.operation}`);
|
|
75
|
-
* });
|
|
76
|
-
*/
|
|
77
|
-
async streamEdit(operations, onProgress) {
|
|
78
|
-
if (!this.connected) {
|
|
79
|
-
await this.connect();
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const total = operations.length;
|
|
83
|
-
const startTime = Date.now();
|
|
84
|
-
let firstOpCompleted = false;
|
|
85
|
-
|
|
86
|
-
console.log(`\n🎨 开始流式编辑 PPT (${total} 个操作)\n`);
|
|
87
|
-
|
|
88
|
-
for (let i = 0; i < operations.length; i++) {
|
|
89
|
-
const operation = operations[i];
|
|
90
|
-
const opStartTime = Date.now();
|
|
91
|
-
|
|
92
|
-
// 1. 立即发送到界面(乐观更新)
|
|
93
|
-
this._optimisticUpdate(operation);
|
|
94
|
-
|
|
95
|
-
// 2. 异步执行实际操作
|
|
96
|
-
const promise = this._executeOperation(operation);
|
|
97
|
-
|
|
98
|
-
// 3. 立即反馈进度(不等待完成)
|
|
99
|
-
if (onProgress) {
|
|
100
|
-
onProgress({
|
|
101
|
-
current: i + 1,
|
|
102
|
-
total: total,
|
|
103
|
-
operation: operation.type,
|
|
104
|
-
progress: ((i + 1) / total * 100).toFixed(1),
|
|
105
|
-
status: 'processing',
|
|
106
|
-
latency: Date.now() - opStartTime
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// 4. 记录首次操作时间
|
|
111
|
-
if (!firstOpCompleted) {
|
|
112
|
-
this.stats.firstOpTime = Date.now() - startTime;
|
|
113
|
-
firstOpCompleted = true;
|
|
114
|
-
console.log(` ⚡ 首次操作反馈: ${this.stats.firstOpTime}ms`);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// 5. 等待操作完成(但用户已经看到变化)
|
|
118
|
-
try {
|
|
119
|
-
await promise;
|
|
120
|
-
console.log(` ✓ ${operation.type} 完成 (${Date.now() - opStartTime}ms)`);
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.log(` ✗ ${operation.type} 失败:`, error.message);
|
|
123
|
-
// 回滚乐观更新
|
|
124
|
-
this._rollbackUpdate(operation);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// 6. 小延迟让用户看清每一步
|
|
128
|
-
if (i < operations.length - 1) {
|
|
129
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const totalTime = Date.now() - startTime;
|
|
134
|
-
console.log(`\n✅ 流式编辑完成,总耗时: ${totalTime}ms\n`);
|
|
135
|
-
|
|
136
|
-
// 最终进度
|
|
137
|
-
if (onProgress) {
|
|
138
|
-
onProgress({
|
|
139
|
-
current: total,
|
|
140
|
-
total: total,
|
|
141
|
-
progress: 100,
|
|
142
|
-
status: 'complete',
|
|
143
|
-
totalTime
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
success: true,
|
|
149
|
-
operations: total,
|
|
150
|
-
totalTime,
|
|
151
|
-
firstOpTime: this.stats.firstOpTime,
|
|
152
|
-
avgLatency: totalTime / total
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* 乐观更新 - 立即反馈到界面
|
|
158
|
-
*/
|
|
159
|
-
_optimisticUpdate(operation) {
|
|
160
|
-
if (!this.ws || !this.connected) return;
|
|
161
|
-
|
|
162
|
-
// 通过 WebSocket 立即发送渲染指令
|
|
163
|
-
this.ws.send(JSON.stringify({
|
|
164
|
-
type: 'optimistic_update',
|
|
165
|
-
operation: operation.type,
|
|
166
|
-
data: operation.data,
|
|
167
|
-
timestamp: Date.now()
|
|
168
|
-
}));
|
|
169
|
-
|
|
170
|
-
this.stats.streamedOps++;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* 执行实际操作
|
|
175
|
-
*/
|
|
176
|
-
async _executeOperation(operation) {
|
|
177
|
-
this.stats.operations++;
|
|
178
|
-
|
|
179
|
-
// 模拟实际的 MCP 工具调用
|
|
180
|
-
return new Promise((resolve, reject) => {
|
|
181
|
-
setTimeout(() => {
|
|
182
|
-
// 通过 WebSocket 确认操作
|
|
183
|
-
if (this.ws && this.connected) {
|
|
184
|
-
this.ws.send(JSON.stringify({
|
|
185
|
-
type: 'operation_confirmed',
|
|
186
|
-
operation: operation.type,
|
|
187
|
-
success: true,
|
|
188
|
-
timestamp: Date.now()
|
|
189
|
-
}));
|
|
190
|
-
}
|
|
191
|
-
resolve();
|
|
192
|
-
}, Math.random() * 100 + 50); // 50-150ms 模拟
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* 回滚更新
|
|
198
|
-
*/
|
|
199
|
-
_rollbackUpdate(operation) {
|
|
200
|
-
if (!this.ws || !this.connected) return;
|
|
201
|
-
|
|
202
|
-
this.ws.send(JSON.stringify({
|
|
203
|
-
type: 'rollback_update',
|
|
204
|
-
operation: operation.type,
|
|
205
|
-
timestamp: Date.now()
|
|
206
|
-
}));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* 处理 WebSocket 消息
|
|
211
|
-
*/
|
|
212
|
-
_handleMessage(data) {
|
|
213
|
-
try {
|
|
214
|
-
const message = JSON.parse(data);
|
|
215
|
-
// 处理来自前端的消息
|
|
216
|
-
console.log('收到消息:', message.type);
|
|
217
|
-
} catch (error) {
|
|
218
|
-
console.error('解析消息失败:', error);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* 断开连接
|
|
224
|
-
*/
|
|
225
|
-
disconnect() {
|
|
226
|
-
if (this.ws) {
|
|
227
|
-
this.ws.close();
|
|
228
|
-
this.ws = null;
|
|
229
|
-
this.connected = false;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* 获取统计信息
|
|
235
|
-
*/
|
|
236
|
-
getStats() {
|
|
237
|
-
return {
|
|
238
|
-
...this.stats,
|
|
239
|
-
streamingRate: this.stats.operations > 0 ?
|
|
240
|
-
(this.stats.streamedOps / this.stats.operations * 100).toFixed(1) + '%' : '0%'
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* 集成到 MCP Handler
|
|
247
|
-
*/
|
|
248
|
-
export class StreamingMCPHandler {
|
|
249
|
-
constructor(mcpClient, options = {}) {
|
|
250
|
-
this.client = mcpClient;
|
|
251
|
-
this.renderer = new PPTStreamingRenderer(options);
|
|
252
|
-
this.batchMode = false;
|
|
253
|
-
this.currentBatch = [];
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* 开始批量操作(流式模式)
|
|
258
|
-
*/
|
|
259
|
-
beginBatch() {
|
|
260
|
-
this.batchMode = true;
|
|
261
|
-
this.currentBatch = [];
|
|
262
|
-
console.log('🎬 开始批量操作(流式模式)');
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* 添加操作到批次
|
|
267
|
-
*/
|
|
268
|
-
async addOperation(name, args) {
|
|
269
|
-
const operation = {
|
|
270
|
-
type: name,
|
|
271
|
-
data: args
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
if (this.batchMode) {
|
|
275
|
-
this.currentBatch.push(operation);
|
|
276
|
-
return { queued: true, index: this.currentBatch.length };
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// 单个操作也流式执行
|
|
280
|
-
return this.renderer.streamEdit([operation]);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* 提交批次(流式执行)
|
|
285
|
-
*/
|
|
286
|
-
async commitBatch(onProgress) {
|
|
287
|
-
if (!this.batchMode || this.currentBatch.length === 0) {
|
|
288
|
-
return { error: 'No batch in progress' };
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
console.log(`📦 提交批次: ${this.currentBatch.length} 个操作`);
|
|
292
|
-
|
|
293
|
-
const result = await this.renderer.streamEdit(
|
|
294
|
-
this.currentBatch,
|
|
295
|
-
onProgress
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
this.batchMode = false;
|
|
299
|
-
this.currentBatch = [];
|
|
300
|
-
|
|
301
|
-
return result;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* 流式调用工具
|
|
306
|
-
*/
|
|
307
|
-
async callToolStreaming(name, args, onProgress) {
|
|
308
|
-
const operation = { type: name, data: args };
|
|
309
|
-
return this.renderer.streamEdit([operation], onProgress);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* 连接渲染器
|
|
314
|
-
*/
|
|
315
|
-
async connect() {
|
|
316
|
-
return this.renderer.connect();
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* 断开连接
|
|
321
|
-
*/
|
|
322
|
-
disconnect() {
|
|
323
|
-
this.renderer.disconnect();
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* 创建流式 PPT 编辑器
|
|
329
|
-
*/
|
|
330
|
-
export function createStreamingPPTEditor(mcpClient, options = {}) {
|
|
331
|
-
return new StreamingMCPHandler(mcpClient, options);
|
|
332
|
-
}
|