ibi-ai-talk 1.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/README.md +24 -0
- package/dist/demo.html +5 -0
- package/dist/index.common.js +2653 -0
- package/dist/index.common.js.map +1 -0
- package/dist/index.umd.js +2665 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/index.umd.min.js +2 -0
- package/dist/index.umd.min.js.map +1 -0
- package/index.js +8 -0
- package/package.json +18 -0
- package/src/index.vue +57 -0
- package/src/utils/blocking-queue.js +98 -0
- package/src/utils/controller.js +34 -0
- package/src/utils/manager.js +39 -0
- package/src/utils/opus-codec.js +169 -0
- package/src/utils/ota-connector.js +115 -0
- package/src/utils/player.js +262 -0
- package/src/utils/recorder.js +420 -0
- package/src/utils/stream-context.js +184 -0
- package/src/utils/tools.js +517 -0
- package/src/utils/websocket.js +565 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
// 全局变量
|
|
2
|
+
let mcpTools = [];
|
|
3
|
+
let mcpEditingIndex = null;
|
|
4
|
+
let mcpProperties = [];
|
|
5
|
+
let websocket = null; // 将从外部设置
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 设置 WebSocket 实例
|
|
9
|
+
* @param {WebSocket} ws - WebSocket 连接实例
|
|
10
|
+
*/
|
|
11
|
+
export function setWebSocket(ws) {
|
|
12
|
+
websocket = ws;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 初始化 MCP 工具
|
|
17
|
+
*/
|
|
18
|
+
export async function initMcpTools() {
|
|
19
|
+
// 加载默认工具数据
|
|
20
|
+
const defaultMcpTools = await fetch("/default-mcp-tools.json").then((res) =>
|
|
21
|
+
res.json()
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const savedTools = localStorage.getItem("mcpTools");
|
|
25
|
+
if (savedTools) {
|
|
26
|
+
try {
|
|
27
|
+
mcpTools = JSON.parse(savedTools);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.log("加载MCP工具失败,使用默认工具", "warning");
|
|
30
|
+
mcpTools = [...defaultMcpTools];
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
mcpTools = [...defaultMcpTools];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// renderMcpTools();
|
|
37
|
+
// setupMcpEventListeners();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 渲染工具列表
|
|
42
|
+
*/
|
|
43
|
+
function renderMcpTools() {
|
|
44
|
+
const container = document.getElementById("mcpToolsContainer");
|
|
45
|
+
const countSpan = document.getElementById("mcpToolsCount");
|
|
46
|
+
|
|
47
|
+
countSpan.textContent = `${mcpTools.length} 个工具`;
|
|
48
|
+
|
|
49
|
+
if (mcpTools.length === 0) {
|
|
50
|
+
container.innerHTML =
|
|
51
|
+
'<div style="text-align: center; padding: 30px; color: #999;">暂无工具,点击下方按钮添加新工具</div>';
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
container.innerHTML = mcpTools
|
|
56
|
+
.map((tool, index) => {
|
|
57
|
+
const paramCount = tool.inputSchema.properties
|
|
58
|
+
? Object.keys(tool.inputSchema.properties).length
|
|
59
|
+
: 0;
|
|
60
|
+
const requiredCount = tool.inputSchema.required
|
|
61
|
+
? tool.inputSchema.required.length
|
|
62
|
+
: 0;
|
|
63
|
+
const hasMockResponse =
|
|
64
|
+
tool.mockResponse && Object.keys(tool.mockResponse).length > 0;
|
|
65
|
+
|
|
66
|
+
return `
|
|
67
|
+
<div class="mcp-tool-card">
|
|
68
|
+
<div class="mcp-tool-header">
|
|
69
|
+
<div class="mcp-tool-name">${tool.name}</div>
|
|
70
|
+
<div class="mcp-tool-actions">
|
|
71
|
+
<button onclick="window.mcpModule.editMcpTool(${index})"
|
|
72
|
+
style="padding: 4px 10px; border: none; border-radius: 4px; background-color: #2196f3; color: white; cursor: pointer; font-size: 12px;">
|
|
73
|
+
✏️ 编辑
|
|
74
|
+
</button>
|
|
75
|
+
<button onclick="window.mcpModule.deleteMcpTool(${index})"
|
|
76
|
+
style="padding: 4px 10px; border: none; border-radius: 4px; background-color: #f44336; color: white; cursor: pointer; font-size: 12px;">
|
|
77
|
+
🗑️ 删除
|
|
78
|
+
</button>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="mcp-tool-description">${tool.description}</div>
|
|
82
|
+
<div class="mcp-tool-info">
|
|
83
|
+
<div class="mcp-tool-info-row">
|
|
84
|
+
<span class="mcp-tool-info-label">参数数量:</span>
|
|
85
|
+
<span class="mcp-tool-info-value">${paramCount} 个 ${
|
|
86
|
+
requiredCount > 0 ? `(${requiredCount} 个必填)` : ""
|
|
87
|
+
}</span>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="mcp-tool-info-row">
|
|
90
|
+
<span class="mcp-tool-info-label">模拟返回:</span>
|
|
91
|
+
<span class="mcp-tool-info-value">${
|
|
92
|
+
hasMockResponse
|
|
93
|
+
? "✅ 已配置: " + JSON.stringify(tool.mockResponse)
|
|
94
|
+
: "⚪ 使用默认"
|
|
95
|
+
}</span>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
`;
|
|
100
|
+
})
|
|
101
|
+
.join("");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 渲染参数列表
|
|
106
|
+
*/
|
|
107
|
+
function renderMcpProperties() {
|
|
108
|
+
const container = document.getElementById("mcpPropertiesContainer");
|
|
109
|
+
|
|
110
|
+
if (mcpProperties.length === 0) {
|
|
111
|
+
container.innerHTML =
|
|
112
|
+
'<div style="text-align: center; padding: 20px; color: #999; font-size: 14px;">暂无参数,点击下方按钮添加参数</div>';
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
container.innerHTML = mcpProperties
|
|
117
|
+
.map(
|
|
118
|
+
(prop, index) => `
|
|
119
|
+
<div class="mcp-property-item">
|
|
120
|
+
<div class="mcp-property-header">
|
|
121
|
+
<span class="mcp-property-name">${prop.name}</span>
|
|
122
|
+
<button type="button" onclick="window.mcpModule.deleteMcpProperty(${index})"
|
|
123
|
+
style="padding: 3px 8px; border: none; border-radius: 3px; background-color: #f44336; color: white; cursor: pointer; font-size: 11px;">
|
|
124
|
+
删除
|
|
125
|
+
</button>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="mcp-property-row">
|
|
128
|
+
<div>
|
|
129
|
+
<label class="mcp-small-label">参数名称 *</label>
|
|
130
|
+
<input type="text" class="mcp-small-input" value="${
|
|
131
|
+
prop.name
|
|
132
|
+
}"
|
|
133
|
+
onchange="window.mcpModule.updateMcpProperty(${index}, 'name', this.value)" required>
|
|
134
|
+
</div>
|
|
135
|
+
<div>
|
|
136
|
+
<label class="mcp-small-label">数据类型 *</label>
|
|
137
|
+
<select class="mcp-small-input" onchange="window.mcpModule.updateMcpProperty(${index}, 'type', this.value)">
|
|
138
|
+
<option value="string" ${
|
|
139
|
+
prop.type === "string" ? "selected" : ""
|
|
140
|
+
}>字符串</option>
|
|
141
|
+
<option value="integer" ${
|
|
142
|
+
prop.type === "integer" ? "selected" : ""
|
|
143
|
+
}>整数</option>
|
|
144
|
+
<option value="number" ${
|
|
145
|
+
prop.type === "number" ? "selected" : ""
|
|
146
|
+
}>数字</option>
|
|
147
|
+
<option value="boolean" ${
|
|
148
|
+
prop.type === "boolean" ? "selected" : ""
|
|
149
|
+
}>布尔值</option>
|
|
150
|
+
<option value="array" ${
|
|
151
|
+
prop.type === "array" ? "selected" : ""
|
|
152
|
+
}>数组</option>
|
|
153
|
+
<option value="object" ${
|
|
154
|
+
prop.type === "object" ? "selected" : ""
|
|
155
|
+
}>对象</option>
|
|
156
|
+
</select>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
${
|
|
160
|
+
prop.type === "integer" || prop.type === "number"
|
|
161
|
+
? `
|
|
162
|
+
<div class="mcp-property-row">
|
|
163
|
+
<div>
|
|
164
|
+
<label class="mcp-small-label">最小值</label>
|
|
165
|
+
<input type="number" class="mcp-small-input" value="${
|
|
166
|
+
prop.minimum !== undefined ? prop.minimum : ""
|
|
167
|
+
}"
|
|
168
|
+
placeholder="可选" onchange="window.mcpModule.updateMcpProperty(${index}, 'minimum', this.value ? parseFloat(this.value) : undefined)">
|
|
169
|
+
</div>
|
|
170
|
+
<div>
|
|
171
|
+
<label class="mcp-small-label">最大值</label>
|
|
172
|
+
<input type="number" class="mcp-small-input" value="${
|
|
173
|
+
prop.maximum !== undefined ? prop.maximum : ""
|
|
174
|
+
}"
|
|
175
|
+
placeholder="可选" onchange="window.mcpModule.updateMcpProperty(${index}, 'maximum', this.value ? parseFloat(this.value) : undefined)">
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
`
|
|
179
|
+
: ""
|
|
180
|
+
}
|
|
181
|
+
<div class="mcp-property-row-full">
|
|
182
|
+
<label class="mcp-small-label">参数描述</label>
|
|
183
|
+
<input type="text" class="mcp-small-input" value="${
|
|
184
|
+
prop.description || ""
|
|
185
|
+
}"
|
|
186
|
+
placeholder="可选" onchange="window.mcpModule.updateMcpProperty(${index}, 'description', this.value)">
|
|
187
|
+
</div>
|
|
188
|
+
<label class="mcp-checkbox-label">
|
|
189
|
+
<input type="checkbox" ${prop.required ? "checked" : ""}
|
|
190
|
+
onchange="window.mcpModule.updateMcpProperty(${index}, 'required', this.checked)">
|
|
191
|
+
必填参数
|
|
192
|
+
</label>
|
|
193
|
+
</div>
|
|
194
|
+
`
|
|
195
|
+
)
|
|
196
|
+
.join("");
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 添加参数
|
|
201
|
+
*/
|
|
202
|
+
function addMcpProperty() {
|
|
203
|
+
mcpProperties.push({
|
|
204
|
+
name: `param_${mcpProperties.length + 1}`,
|
|
205
|
+
type: "string",
|
|
206
|
+
required: false,
|
|
207
|
+
description: "",
|
|
208
|
+
});
|
|
209
|
+
renderMcpProperties();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 更新参数
|
|
214
|
+
*/
|
|
215
|
+
function updateMcpProperty(index, field, value) {
|
|
216
|
+
if (field === "name") {
|
|
217
|
+
const isDuplicate = mcpProperties.some(
|
|
218
|
+
(p, i) => i !== index && p.name === value
|
|
219
|
+
);
|
|
220
|
+
if (isDuplicate) {
|
|
221
|
+
alert("参数名称已存在,请使用不同的名称");
|
|
222
|
+
renderMcpProperties();
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
mcpProperties[index][field] = value;
|
|
228
|
+
|
|
229
|
+
if (field === "type" && value !== "integer" && value !== "number") {
|
|
230
|
+
delete mcpProperties[index].minimum;
|
|
231
|
+
delete mcpProperties[index].maximum;
|
|
232
|
+
renderMcpProperties();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* 删除参数
|
|
238
|
+
*/
|
|
239
|
+
function deleteMcpProperty(index) {
|
|
240
|
+
mcpProperties.splice(index, 1);
|
|
241
|
+
renderMcpProperties();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 设置事件监听
|
|
246
|
+
*/
|
|
247
|
+
function setupMcpEventListeners() {
|
|
248
|
+
const toggleBtn = document.getElementById("toggleMcpTools");
|
|
249
|
+
const panel = document.getElementById("mcpToolsPanel");
|
|
250
|
+
const addBtn = document.getElementById("addMcpToolBtn");
|
|
251
|
+
const modal = document.getElementById("mcpToolModal");
|
|
252
|
+
const closeBtn = document.getElementById("closeMcpModalBtn");
|
|
253
|
+
const cancelBtn = document.getElementById("cancelMcpBtn");
|
|
254
|
+
const form = document.getElementById("mcpToolForm");
|
|
255
|
+
const addPropertyBtn = document.getElementById("addMcpPropertyBtn");
|
|
256
|
+
|
|
257
|
+
toggleBtn.addEventListener("click", () => {
|
|
258
|
+
const isExpanded = panel.classList.contains("expanded");
|
|
259
|
+
panel.classList.toggle("expanded");
|
|
260
|
+
toggleBtn.textContent = isExpanded ? "展开" : "收起";
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
addBtn.addEventListener("click", () => openMcpModal());
|
|
264
|
+
closeBtn.addEventListener("click", closeMcpModal);
|
|
265
|
+
cancelBtn.addEventListener("click", closeMcpModal);
|
|
266
|
+
addPropertyBtn.addEventListener("click", addMcpProperty);
|
|
267
|
+
|
|
268
|
+
modal.addEventListener("click", (e) => {
|
|
269
|
+
if (e.target === modal) closeMcpModal();
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
form.addEventListener("submit", handleMcpSubmit);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* 打开模态框
|
|
277
|
+
*/
|
|
278
|
+
function openMcpModal(index = null) {
|
|
279
|
+
const isConnected = websocket && websocket.readyState === WebSocket.OPEN;
|
|
280
|
+
if (isConnected) {
|
|
281
|
+
alert("WebSocket 已连接,无法编辑工具");
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
mcpEditingIndex = index;
|
|
286
|
+
const errorContainer = document.getElementById("mcpErrorContainer");
|
|
287
|
+
errorContainer.innerHTML = "";
|
|
288
|
+
|
|
289
|
+
if (index !== null) {
|
|
290
|
+
document.getElementById("mcpModalTitle").textContent = "编辑工具";
|
|
291
|
+
const tool = mcpTools[index];
|
|
292
|
+
document.getElementById("mcpToolName").value = tool.name;
|
|
293
|
+
document.getElementById("mcpToolDescription").value = tool.description;
|
|
294
|
+
document.getElementById("mcpMockResponse").value = tool.mockResponse
|
|
295
|
+
? JSON.stringify(tool.mockResponse, null, 2)
|
|
296
|
+
: "";
|
|
297
|
+
|
|
298
|
+
mcpProperties = [];
|
|
299
|
+
const schema = tool.inputSchema;
|
|
300
|
+
if (schema.properties) {
|
|
301
|
+
Object.keys(schema.properties).forEach((key) => {
|
|
302
|
+
const prop = schema.properties[key];
|
|
303
|
+
mcpProperties.push({
|
|
304
|
+
name: key,
|
|
305
|
+
type: prop.type || "string",
|
|
306
|
+
minimum: prop.minimum,
|
|
307
|
+
maximum: prop.maximum,
|
|
308
|
+
description: prop.description || "",
|
|
309
|
+
required: schema.required && schema.required.includes(key),
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
document.getElementById("mcpModalTitle").textContent = "添加工具";
|
|
315
|
+
document.getElementById("mcpToolForm").reset();
|
|
316
|
+
mcpProperties = [];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
renderMcpProperties();
|
|
320
|
+
document.getElementById("mcpToolModal").style.display = "block";
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* 关闭模态框
|
|
325
|
+
*/
|
|
326
|
+
function closeMcpModal() {
|
|
327
|
+
document.getElementById("mcpToolModal").style.display = "none";
|
|
328
|
+
mcpEditingIndex = null;
|
|
329
|
+
document.getElementById("mcpToolForm").reset();
|
|
330
|
+
mcpProperties = [];
|
|
331
|
+
document.getElementById("mcpErrorContainer").innerHTML = "";
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* 处理表单提交
|
|
336
|
+
*/
|
|
337
|
+
function handleMcpSubmit(e) {
|
|
338
|
+
e.preventDefault();
|
|
339
|
+
const errorContainer = document.getElementById("mcpErrorContainer");
|
|
340
|
+
errorContainer.innerHTML = "";
|
|
341
|
+
|
|
342
|
+
const name = document.getElementById("mcpToolName").value.trim();
|
|
343
|
+
const description = document
|
|
344
|
+
.getElementById("mcpToolDescription")
|
|
345
|
+
.value.trim();
|
|
346
|
+
const mockResponseText = document
|
|
347
|
+
.getElementById("mcpMockResponse")
|
|
348
|
+
.value.trim();
|
|
349
|
+
|
|
350
|
+
// 检查名称重复
|
|
351
|
+
const isDuplicate = mcpTools.some(
|
|
352
|
+
(tool, index) => tool.name === name && index !== mcpEditingIndex
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
if (isDuplicate) {
|
|
356
|
+
showMcpError("工具名称已存在,请使用不同的名称");
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// 解析模拟返回结果
|
|
361
|
+
let mockResponse = null;
|
|
362
|
+
if (mockResponseText) {
|
|
363
|
+
try {
|
|
364
|
+
mockResponse = JSON.parse(mockResponseText);
|
|
365
|
+
} catch (e) {
|
|
366
|
+
showMcpError("模拟返回结果不是有效的 JSON 格式: " + e.message);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// 构建 inputSchema
|
|
372
|
+
const inputSchema = {
|
|
373
|
+
type: "object",
|
|
374
|
+
properties: {},
|
|
375
|
+
required: [],
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
mcpProperties.forEach((prop) => {
|
|
379
|
+
const propSchema = { type: prop.type };
|
|
380
|
+
|
|
381
|
+
if (prop.description) {
|
|
382
|
+
propSchema.description = prop.description;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (prop.type === "integer" || prop.type === "number") {
|
|
386
|
+
if (prop.minimum !== undefined && prop.minimum !== "") {
|
|
387
|
+
propSchema.minimum = prop.minimum;
|
|
388
|
+
}
|
|
389
|
+
if (prop.maximum !== undefined && prop.maximum !== "") {
|
|
390
|
+
propSchema.maximum = prop.maximum;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
inputSchema.properties[prop.name] = propSchema;
|
|
395
|
+
|
|
396
|
+
if (prop.required) {
|
|
397
|
+
inputSchema.required.push(prop.name);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
if (inputSchema.required.length === 0) {
|
|
402
|
+
delete inputSchema.required;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const tool = { name, description, inputSchema, mockResponse };
|
|
406
|
+
|
|
407
|
+
if (mcpEditingIndex !== null) {
|
|
408
|
+
mcpTools[mcpEditingIndex] = tool;
|
|
409
|
+
console.log(`已更新工具: ${name}`, "success");
|
|
410
|
+
} else {
|
|
411
|
+
mcpTools.push(tool);
|
|
412
|
+
console.log(`已添加工具: ${name}`, "success");
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
saveMcpTools();
|
|
416
|
+
renderMcpTools();
|
|
417
|
+
closeMcpModal();
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* 显示错误
|
|
422
|
+
*/
|
|
423
|
+
function showMcpError(message) {
|
|
424
|
+
const errorContainer = document.getElementById("mcpErrorContainer");
|
|
425
|
+
errorContainer.innerHTML = `<div class="mcp-error">${message}</div>`;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* 编辑工具
|
|
430
|
+
*/
|
|
431
|
+
function editMcpTool(index) {
|
|
432
|
+
openMcpModal(index);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* 删除工具
|
|
437
|
+
*/
|
|
438
|
+
function deleteMcpTool(index) {
|
|
439
|
+
const isConnected = websocket && websocket.readyState === WebSocket.OPEN;
|
|
440
|
+
if (isConnected) {
|
|
441
|
+
alert("WebSocket 已连接,无法编辑工具");
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
if (confirm(`确定要删除工具 "${mcpTools[index].name}" 吗?`)) {
|
|
445
|
+
const toolName = mcpTools[index].name;
|
|
446
|
+
mcpTools.splice(index, 1);
|
|
447
|
+
saveMcpTools();
|
|
448
|
+
renderMcpTools();
|
|
449
|
+
console.log(`已删除工具: ${toolName}`, "info");
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* 保存工具
|
|
455
|
+
*/
|
|
456
|
+
function saveMcpTools() {
|
|
457
|
+
localStorage.setItem("mcpTools", JSON.stringify(mcpTools));
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* 获取工具列表
|
|
462
|
+
*/
|
|
463
|
+
export function getMcpTools() {
|
|
464
|
+
return mcpTools.map((tool) => ({
|
|
465
|
+
name: tool.name,
|
|
466
|
+
description: tool.description,
|
|
467
|
+
inputSchema: tool.inputSchema,
|
|
468
|
+
}));
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* 执行工具调用
|
|
473
|
+
*/
|
|
474
|
+
export function executeMcpTool(toolName, toolArgs) {
|
|
475
|
+
const tool = mcpTools.find((t) => t.name === toolName);
|
|
476
|
+
if (!tool) {
|
|
477
|
+
console.log(`未找到工具: ${toolName}`, "error");
|
|
478
|
+
return {
|
|
479
|
+
success: false,
|
|
480
|
+
error: `未知工具: ${toolName}`,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (tool.name == "self.drink_car_list") {
|
|
485
|
+
console.log("准备触发 gotoOrderEvent 事件"); // 增加此日志
|
|
486
|
+
const event = new CustomEvent("gotoOrderEvent");
|
|
487
|
+
window.dispatchEvent(event);
|
|
488
|
+
return {
|
|
489
|
+
success: true,
|
|
490
|
+
message: `工具 ${toolName} 执行成功`,
|
|
491
|
+
data: sessionStorage.getItem('cartList') || [],
|
|
492
|
+
};
|
|
493
|
+
} else if (tool.name == "self.drink_car_reset") {
|
|
494
|
+
console.log("准备触发 resetOrderEvent 事件"); // 增加此日志
|
|
495
|
+
const event = new CustomEvent("resetOrderEvent", {
|
|
496
|
+
detail: toolArgs,
|
|
497
|
+
});
|
|
498
|
+
window.dispatchEvent(event);
|
|
499
|
+
return {
|
|
500
|
+
success: true,
|
|
501
|
+
message: `工具 ${toolName} 执行成功`,
|
|
502
|
+
data: sessionStorage.getItem('cartList') || [],
|
|
503
|
+
}
|
|
504
|
+
} else if (tool.name == "self.drink_order") {
|
|
505
|
+
console.log("准备触发 orderEvent 事件"); // 增加此日志
|
|
506
|
+
const event = new CustomEvent("orderEvent");
|
|
507
|
+
window.dispatchEvent(event);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// 暴露全局方法供 HTML 内联事件调用
|
|
512
|
+
window.mcpModule = {
|
|
513
|
+
updateMcpProperty,
|
|
514
|
+
deleteMcpProperty,
|
|
515
|
+
editMcpTool,
|
|
516
|
+
deleteMcpTool,
|
|
517
|
+
};
|