import { nextTick, type Ref } from "vue"; import { LocalMessageIdPool, type ChatMessagesManager } from "./Messages"; import { ChatMessage as ChatMessageModel } from "../model/Message"; import { ChatUtils } from "../utils/ChatUtils"; import type OpenAI from "openai" import type { ChatToolContext, ChatToolsManager } from "./Tools"; import type { ChatInterfaceManager } from "./Chat"; import type { ChatSessionManager } from "../composables/useChatSession"; export function useToolCalls( messagesManager: ChatMessagesManager, toolsManager: ChatToolsManager, interfaceManager: ChatInterfaceManager, sessionManager: ChatSessionManager ) { /** * 执行工具调用 */ async function executeToolCalls(toolCalls: OpenAI.Chat.ChatCompletionMessageToolCall[], parentMessageId: number) { const ctx: ChatToolContext = { messages: messagesManager.messages as Ref, scrollToBottom: interfaceManager.scrollToBottom, }; for (const call of toolCalls) { if (call.type !== "function") continue; const name = call.function.name; const tool = toolsManager.toolRegistry.value.get(name); const newToolMessageId = LocalMessageIdPool.getNextId(); const toolMsg = messagesManager.addMessage(ChatMessageModel.createTool(name, `调用工具 ${name}`, newToolMessageId) as ChatMessageModel);; toolMsg.parentId = parentMessageId; try { if (!tool) throw new Error(`未找到工具:${name}`); let args: any = call.function.arguments; if (typeof args === "string" && args.trim()) { try { args = JSON.parse(args); } catch (error) { throw new Error('工具参数解析失败: ' + (error as Error).message); } } const rs = await tool.handler(args, ctx); if (toolMsg) { toolMsg.content += ' 成功' toolMsg.extra = (typeof rs === "string" ? rs : JSON.stringify(rs, null, 2)); toolMsg.state = "success"; } } catch (error) { toolMsg.state = "error"; toolMsg.content += ' 失败'; toolMsg.setError("工具执行失败", ChatUtils.formatError(error)); } if (toolMsg) { try { await sessionManager.persistMessages([toolMsg]); } catch (error) { console.error(error); } } await nextTick(); await interfaceManager.scrollToBottom?.(); } } return { executeToolCalls, } }