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

View File

@ -1,10 +1,12 @@
import { aiSdk, Tool } from '@cherrystudio/ai-core'
import { loggerService } from '@logger'
// import { AiSdkTool, ToolCallResult } from '@renderer/aiCore/tools/types'
import { MCPTool, MCPToolResponse } from '@renderer/types'
import { callMCPTool } from '@renderer/utils/mcp-tools'
import { JSONSchema7 } from 'json-schema'
const { tool } = aiSdk
const logger = loggerService.withContext('MCP-utils')
// Setup tools configuration based on provided parameters
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> = {}
for (const mcpTool of mcpTools) {
console.log('mcpTool', mcpTool.inputSchema)
tools[mcpTool.name] = tool({
description: mcpTool.description || `Tool from ${mcpTool.serverName}`,
inputSchema: aiSdk.jsonSchema(mcpTool.inputSchema as JSONSchema7),
execute: async (params) => {
console.log('execute_params', params)
// 创建适配的 MCPToolResponse 对象
const toolResponse: MCPToolResponse = {
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) {
throw new Error(result.content?.[0]?.text || 'Tool execution failed')
}
console.log('result', result)
// 返回工具执行结果
return result
} catch (error) {
console.error(`MCP Tool execution failed: ${mcpTool.name}`, error)
logger.error(`MCP Tool execution failed: ${mcpTool.name}`, { 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 { SdkToolCall } from './sdk'
@ -292,7 +299,7 @@ export interface MCPToolCreatedChunk {
export interface MCPToolPendingChunk {
type: ChunkType.MCP_TOOL_PENDING
responses: MCPToolResponse[]
responses: MCPToolResponse[] | NormalToolResponse[]
}
export interface MCPToolInProgressChunk {
@ -303,14 +310,14 @@ export interface MCPToolInProgressChunk {
/**
* The tool responses of the chunk
*/
responses: MCPToolResponse[]
responses: MCPToolResponse[] | NormalToolResponse[]
}
export interface MCPToolCompleteChunk {
/**
* The tool response of the chunk
*/
responses: MCPToolResponse[]
responses: MCPToolResponse[] | NormalToolResponse[]
/**
* The type of the chunk

View File

@ -874,7 +874,16 @@ export interface ToolCallResponse extends BaseToolResponse {
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 {
type: 'text' | 'image' | 'audio' | 'resource'