feat(aiCore): enhance tool response handling and type definitions

- Updated the ToolCallChunkHandler to support both MCPTool and NormalToolResponse types, improving flexibility in tool response management.
- Refactored type definitions for MCPToolResponse and introduced NormalToolResponse to better differentiate between tool response types.
- Enhanced logging in MCP utility functions for improved error tracking and debugging.
- Cleaned up type imports and ensured consistent handling of tool responses across various chunks.
This commit is contained in:
MyPrototypeWhat 2025-08-21 16:30:30 +08:00
parent aa9ed3b9c8
commit d34b640807
4 changed files with 33 additions and 18 deletions

View File

@ -6,7 +6,7 @@
import { ProviderMetadata, ToolSet, TypedToolCall, TypedToolResult } from '@cherrystudio/ai-core' import { ProviderMetadata, ToolSet, TypedToolCall, TypedToolResult } from '@cherrystudio/ai-core'
import { loggerService } from '@logger' import { loggerService } from '@logger'
import { BaseTool, MCPToolResponse, ToolCallResponse } from '@renderer/types' import { BaseTool, MCPTool, MCPToolResponse, NormalToolResponse } from '@renderer/types'
import { Chunk, ChunkType } from '@renderer/types/chunk' import { Chunk, ChunkType } from '@renderer/types/chunk'
// import type { // import type {
// AnthropicSearchOutput, // AnthropicSearchOutput,
@ -68,7 +68,7 @@ export class ToolCallChunkHandler {
// 能拿到说明是mcpTool // 能拿到说明是mcpTool
// if (this.activeToolCalls.get(chunk.id)) return // if (this.activeToolCalls.get(chunk.id)) return
const tool: BaseTool = { const tool: BaseTool | MCPTool = {
id: chunk.id, id: chunk.id,
name: chunk.toolName, name: chunk.toolName,
description: chunk.toolName, description: chunk.toolName,
@ -80,7 +80,7 @@ export class ToolCallChunkHandler {
args: '', args: '',
tool tool
}) })
const toolResponse: ToolCallResponse = { const toolResponse: MCPToolResponse | NormalToolResponse = {
id: chunk.id, id: chunk.id,
tool: tool, tool: tool,
arguments: {}, arguments: {},
@ -155,7 +155,7 @@ export class ToolCallChunkHandler {
return return
} }
let tool: BaseTool let tool: BaseTool | MCPTool
// 根据 providerExecuted 标志区分处理逻辑 // 根据 providerExecuted 标志区分处理逻辑
if (providerExecuted) { if (providerExecuted) {
@ -166,7 +166,7 @@ export class ToolCallChunkHandler {
name: toolName, name: toolName,
description: toolName, description: toolName,
type: 'provider' type: 'provider'
} } as BaseTool
} else if (toolName.startsWith('builtin_')) { } else if (toolName.startsWith('builtin_')) {
// 如果是内置工具,沿用现有逻辑 // 如果是内置工具,沿用现有逻辑
logger.info(`[ToolCallChunkHandler] Handling builtin tool: ${toolName}`) logger.info(`[ToolCallChunkHandler] Handling builtin tool: ${toolName}`)
@ -175,7 +175,7 @@ export class ToolCallChunkHandler {
name: toolName, name: toolName,
description: toolName, description: toolName,
type: 'builtin' type: 'builtin'
} } as BaseTool
} else { } else {
// 如果是客户端执行的 MCP 工具,沿用现有逻辑 // 如果是客户端执行的 MCP 工具,沿用现有逻辑
logger.info(`[ToolCallChunkHandler] Handling client-side MCP tool: ${toolName}`) logger.info(`[ToolCallChunkHandler] Handling client-side MCP tool: ${toolName}`)
@ -184,7 +184,7 @@ export class ToolCallChunkHandler {
logger.warn(`[ToolCallChunkHandler] MCP tool not found: ${toolName}`) logger.warn(`[ToolCallChunkHandler] MCP tool not found: ${toolName}`)
return return
} }
tool = mcpTool tool = mcpTool as MCPTool
} }
// 记录活跃的工具调用 // 记录活跃的工具调用
@ -196,7 +196,7 @@ export class ToolCallChunkHandler {
}) })
// 创建 MCPToolResponse 格式 // 创建 MCPToolResponse 格式
const toolResponse: MCPToolResponse = { const toolResponse: MCPToolResponse | NormalToolResponse = {
id: toolCallId, id: toolCallId,
tool: tool, tool: tool,
arguments: args, arguments: args,
@ -236,7 +236,7 @@ export class ToolCallChunkHandler {
} }
// 创建工具调用结果的 MCPToolResponse 格式 // 创建工具调用结果的 MCPToolResponse 格式
const toolResponse: MCPToolResponse = { const toolResponse: MCPToolResponse | NormalToolResponse = {
id: toolCallInfo.toolCallId, id: toolCallInfo.toolCallId,
tool: toolCallInfo.tool, tool: toolCallInfo.tool,
arguments: input, arguments: input,

View File

@ -1,10 +1,12 @@
import { aiSdk, Tool } from '@cherrystudio/ai-core' import { aiSdk, Tool } from '@cherrystudio/ai-core'
import { loggerService } from '@logger'
// import { AiSdkTool, ToolCallResult } from '@renderer/aiCore/tools/types' // import { AiSdkTool, ToolCallResult } from '@renderer/aiCore/tools/types'
import { MCPTool, MCPToolResponse } from '@renderer/types' import { MCPTool, MCPToolResponse } from '@renderer/types'
import { callMCPTool } from '@renderer/utils/mcp-tools' import { callMCPTool } from '@renderer/utils/mcp-tools'
import { JSONSchema7 } from 'json-schema' import { JSONSchema7 } from 'json-schema'
const { tool } = aiSdk const { tool } = aiSdk
const logger = loggerService.withContext('MCP-utils')
// Setup tools configuration based on provided parameters // Setup tools configuration based on provided parameters
export function setupToolsConfig(mcpTools?: MCPTool[]): Record<string, Tool> | undefined { export function setupToolsConfig(mcpTools?: MCPTool[]): Record<string, Tool> | undefined {
@ -26,12 +28,10 @@ export function convertMcpToolsToAiSdkTools(mcpTools: MCPTool[]): Record<string,
const tools: Record<string, Tool> = {} const tools: Record<string, Tool> = {}
for (const mcpTool of mcpTools) { for (const mcpTool of mcpTools) {
console.log('mcpTool', mcpTool.inputSchema)
tools[mcpTool.name] = tool({ tools[mcpTool.name] = tool({
description: mcpTool.description || `Tool from ${mcpTool.serverName}`, description: mcpTool.description || `Tool from ${mcpTool.serverName}`,
inputSchema: aiSdk.jsonSchema(mcpTool.inputSchema as JSONSchema7), inputSchema: aiSdk.jsonSchema(mcpTool.inputSchema as JSONSchema7),
execute: async (params) => { execute: async (params) => {
console.log('execute_params', params)
// 创建适配的 MCPToolResponse 对象 // 创建适配的 MCPToolResponse 对象
const toolResponse: MCPToolResponse = { const toolResponse: MCPToolResponse = {
id: `tool_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, id: `tool_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
@ -49,11 +49,10 @@ export function convertMcpToolsToAiSdkTools(mcpTools: MCPTool[]): Record<string,
if (result.isError) { if (result.isError) {
throw new Error(result.content?.[0]?.text || 'Tool execution failed') throw new Error(result.content?.[0]?.text || 'Tool execution failed')
} }
console.log('result', result)
// 返回工具执行结果 // 返回工具执行结果
return result return result
} catch (error) { } catch (error) {
console.error(`MCP Tool execution failed: ${mcpTool.name}`, error) logger.error(`MCP Tool execution failed: ${mcpTool.name}`, { error })
throw error throw error
} }
} }

View File

@ -1,4 +1,11 @@
import { ExternalToolResult, KnowledgeReference, MCPToolResponse, ToolUseResponse, WebSearchResponse } from '.' import {
ExternalToolResult,
KnowledgeReference,
MCPToolResponse,
NormalToolResponse,
ToolUseResponse,
WebSearchResponse
} from '.'
import { Response, ResponseError } from './newMessage' import { Response, ResponseError } from './newMessage'
import { SdkToolCall } from './sdk' import { SdkToolCall } from './sdk'
@ -292,7 +299,7 @@ export interface MCPToolCreatedChunk {
export interface MCPToolPendingChunk { export interface MCPToolPendingChunk {
type: ChunkType.MCP_TOOL_PENDING type: ChunkType.MCP_TOOL_PENDING
responses: MCPToolResponse[] responses: MCPToolResponse[] | NormalToolResponse[]
} }
export interface MCPToolInProgressChunk { export interface MCPToolInProgressChunk {
@ -303,14 +310,14 @@ export interface MCPToolInProgressChunk {
/** /**
* The tool responses of the chunk * The tool responses of the chunk
*/ */
responses: MCPToolResponse[] responses: MCPToolResponse[] | NormalToolResponse[]
} }
export interface MCPToolCompleteChunk { export interface MCPToolCompleteChunk {
/** /**
* The tool response of the chunk * The tool response of the chunk
*/ */
responses: MCPToolResponse[] responses: MCPToolResponse[] | NormalToolResponse[]
/** /**
* The type of the chunk * The type of the chunk

View File

@ -874,7 +874,16 @@ export interface ToolCallResponse extends BaseToolResponse {
toolCallId?: string toolCallId?: string
} }
export type MCPToolResponse = ToolUseResponse | ToolCallResponse // export type MCPToolResponse = ToolUseResponse | ToolCallResponse
export interface MCPToolResponse extends Omit<ToolUseResponse | ToolCallResponse, 'tool'> {
tool: MCPTool
toolCallId?: string
toolUseId?: string
}
export interface NormalToolResponse extends Omit<ToolCallResponse, 'tool'> {
tool: BaseTool
}
export interface MCPToolResultContent { export interface MCPToolResultContent {
type: 'text' | 'image' | 'audio' | 'resource' type: 'text' | 'image' | 'audio' | 'resource'