mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-28 05:11:24 +08:00
feat: enhance web search plugin and tool handling
- Refactored `helper.ts` to export new types `AnthropicSearchInput` and `AnthropicSearchOutput` for better integration with the web search plugin. - Updated `index.ts` to include the new types in the exports for improved type safety. - Modified `AiSdkToChunkAdapter.ts` to handle tool calls more flexibly by introducing a `GenericProviderTool` type, allowing for better differentiation between MCP tools and provider-executed tools. - Adjusted `handleTooCallChunk.ts` to accommodate the new tool type structure, enhancing the handling of tool call responses. - Updated type definitions in `index.ts` to reflect changes in tool handling logic.
This commit is contained in:
parent
42c7ebd193
commit
3ab904e789
@ -1,5 +1,5 @@
|
||||
import type { anthropic } from '@ai-sdk/anthropic'
|
||||
import type { openai } from '@ai-sdk/openai'
|
||||
import { anthropic } from '@ai-sdk/anthropic'
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
|
||||
import { ProviderOptionsMap } from '../../../options/types'
|
||||
|
||||
@ -8,7 +8,6 @@ import { ProviderOptionsMap } from '../../../options/types'
|
||||
*/
|
||||
type OpenAISearchConfig = Parameters<typeof openai.tools.webSearchPreview>[0]
|
||||
type AnthropicSearchConfig = Parameters<typeof anthropic.tools.webSearch_20250305>[0]
|
||||
|
||||
/**
|
||||
* XAI 特有的搜索参数
|
||||
* @internal
|
||||
@ -77,3 +76,14 @@ export const getXaiProviderOptions = (providerOptions: any, config?: XaiProvider
|
||||
}
|
||||
return providerOptions
|
||||
}
|
||||
|
||||
export type AnthropicSearchInput = {
|
||||
query: string
|
||||
}
|
||||
export type AnthropicSearchOutput = {
|
||||
url: string
|
||||
title: string
|
||||
pageAge: string | null
|
||||
encryptedContent: string
|
||||
type: string
|
||||
}[]
|
||||
|
||||
@ -78,7 +78,7 @@ export const webSearchPlugin = (config: WebSearchPluginConfig = DEFAULT_WEB_SEAR
|
||||
})
|
||||
|
||||
// 导出类型定义供开发者使用
|
||||
export type { WebSearchPluginConfig } from './helper'
|
||||
export type { AnthropicSearchInput, AnthropicSearchOutput, WebSearchPluginConfig } from './helper'
|
||||
|
||||
// 默认导出
|
||||
export default webSearchPlugin
|
||||
|
||||
@ -81,6 +81,12 @@ export class AiSdkToChunkAdapter {
|
||||
console.log('AI SDK chunk type:', chunk.type, chunk)
|
||||
switch (chunk.type) {
|
||||
// === 文本相关事件 ===
|
||||
// case 'text-start':
|
||||
// this.onChunk({
|
||||
// type: ChunkType.blo,
|
||||
// text: chunk.text || ''
|
||||
// })
|
||||
// break
|
||||
case 'text':
|
||||
final.text += chunk.text || ''
|
||||
this.onChunk({
|
||||
@ -93,6 +99,7 @@ export class AiSdkToChunkAdapter {
|
||||
type: ChunkType.TEXT_COMPLETE,
|
||||
text: final.text || ''
|
||||
})
|
||||
final.text = ''
|
||||
break
|
||||
case 'reasoning':
|
||||
this.onChunk({
|
||||
@ -206,9 +213,7 @@ export class AiSdkToChunkAdapter {
|
||||
case 'error':
|
||||
this.onChunk({
|
||||
type: ChunkType.ERROR,
|
||||
error: {
|
||||
message: chunk.error || 'Unknown error'
|
||||
}
|
||||
error: chunk.error as Record<string, any>
|
||||
})
|
||||
break
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 工具调用 Chunk 处理模块
|
||||
*
|
||||
* TODO: Tool包含了providerTool和普通的Tool还有MCPTool,后面需要重构
|
||||
* 提供工具调用相关的处理API,每个交互使用一个新的实例
|
||||
*/
|
||||
|
||||
@ -8,7 +8,18 @@ import { ToolCallUnion, ToolResultUnion, ToolSet } from '@cherrystudio/ai-core/i
|
||||
import Logger from '@renderer/config/logger'
|
||||
import { MCPTool, MCPToolResponse } from '@renderer/types'
|
||||
import { Chunk, ChunkType } from '@renderer/types/chunk'
|
||||
// import type {
|
||||
// AnthropicSearchOutput,
|
||||
// WebSearchPluginConfig
|
||||
// } from '@cherrystudio/ai-core/core/plugins/built-in/webSearchPlugin'
|
||||
|
||||
// 为 Provider 执行的工具创建一个通用类型
|
||||
// 这避免了污染 MCPTool 的定义,同时提供了 UI 显示所需的基本信息
|
||||
type GenericProviderTool = {
|
||||
name: string
|
||||
description: string
|
||||
type: 'provider'
|
||||
}
|
||||
/**
|
||||
* 工具调用处理器类
|
||||
*/
|
||||
@ -20,7 +31,8 @@ export class ToolCallChunkHandler {
|
||||
toolCallId: string
|
||||
toolName: string
|
||||
args: any
|
||||
mcpTool: MCPTool
|
||||
// mcpTool 现在可以是 MCPTool 或我们为 Provider 工具创建的通用类型
|
||||
mcpTool: MCPTool | GenericProviderTool
|
||||
}
|
||||
>()
|
||||
constructor(
|
||||
@ -43,30 +55,47 @@ export class ToolCallChunkHandler {
|
||||
type: 'tool-call'
|
||||
} & ToolCallUnion<ToolSet>
|
||||
): void {
|
||||
const toolCallId = chunk.toolCallId
|
||||
const toolName = chunk.toolName
|
||||
const args = chunk.input || {}
|
||||
const { toolCallId, toolName, input: args, providerExecuted } = chunk
|
||||
|
||||
if (!toolCallId || !toolName) {
|
||||
Logger.warn(`🔧 [ToolCallChunkHandler] Invalid tool call chunk: missing toolCallId or toolName`)
|
||||
return
|
||||
}
|
||||
|
||||
// 从 chunk 信息构造 MCPTool
|
||||
// const mcpTool = this.createMcpToolFromChunk(chunk)
|
||||
let tool: MCPTool | GenericProviderTool
|
||||
|
||||
// 根据 providerExecuted 标志区分处理逻辑
|
||||
if (providerExecuted) {
|
||||
// 如果是 Provider 执行的工具(如 web_search)
|
||||
Logger.info(`[ToolCallChunkHandler] Handling provider-executed tool: ${toolName}`)
|
||||
tool = {
|
||||
name: toolName,
|
||||
description: toolName,
|
||||
type: 'provider'
|
||||
}
|
||||
} else {
|
||||
// 如果是客户端执行的 MCP 工具,沿用现有逻辑
|
||||
Logger.info(`[ToolCallChunkHandler] Handling client-side MCP tool: ${toolName}`)
|
||||
const mcpTool = this.mcpTools.find((t) => t.name === toolName)
|
||||
if (!mcpTool) {
|
||||
Logger.warn(`[ToolCallChunkHandler] MCP tool not found: ${toolName}`)
|
||||
return
|
||||
}
|
||||
tool = mcpTool
|
||||
}
|
||||
|
||||
// 记录活跃的工具调用
|
||||
this.activeToolCalls.set(toolCallId, {
|
||||
toolCallId,
|
||||
toolName,
|
||||
args,
|
||||
mcpTool: this.mcpTools.find((tool) => tool.name === toolName)!
|
||||
mcpTool: tool
|
||||
})
|
||||
|
||||
// 创建 MCPToolResponse 格式
|
||||
const toolResponse: MCPToolResponse = {
|
||||
id: toolCallId,
|
||||
tool: this.activeToolCalls.get(toolCallId)!.mcpTool,
|
||||
tool: tool,
|
||||
arguments: args,
|
||||
status: 'invoking',
|
||||
toolCallId: toolCallId
|
||||
@ -121,7 +150,6 @@ export class ToolCallChunkHandler {
|
||||
},
|
||||
toolCallId: toolCallId
|
||||
}
|
||||
|
||||
// 从活跃调用中移除(交互结束后整个实例会被丢弃)
|
||||
this.activeToolCalls.delete(toolCallId)
|
||||
|
||||
|
||||
@ -5,6 +5,12 @@ import type { CSSProperties } from 'react'
|
||||
|
||||
import type { Message } from './newMessage'
|
||||
|
||||
export type GenericProviderTool = {
|
||||
name: string
|
||||
description: string
|
||||
type: 'provider'
|
||||
}
|
||||
|
||||
export type Assistant = {
|
||||
id: string
|
||||
name: string
|
||||
@ -655,7 +661,7 @@ export interface MCPConfig {
|
||||
|
||||
interface BaseToolResponse {
|
||||
id: string // unique id
|
||||
tool: MCPTool
|
||||
tool: MCPTool | GenericProviderTool
|
||||
arguments: Record<string, unknown> | undefined
|
||||
status: string // 'invoking' | 'done'
|
||||
response?: any
|
||||
|
||||
Loading…
Reference in New Issue
Block a user