mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 21:01:32 +08:00
chore: bump @cherrystudio/ai-core version to 1.0.0-alpha.6 and refactor web search tool
- Updated version in package.json to 1.0.0-alpha.6. - Simplified response structure in ToolCallChunkHandler by removing unnecessary nesting. - Refactored input schema for web search tool to enhance type safety and clarity. - Cleaned up commented-out code in MessageTool for improved readability.
This commit is contained in:
parent
eca9442907
commit
e690da840c
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@cherrystudio/ai-core",
|
||||
"version": "1.0.0-alpha.5",
|
||||
"version": "1.0.0-alpha.6",
|
||||
"description": "Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs",
|
||||
|
||||
@ -229,10 +229,7 @@ export class ToolCallChunkHandler {
|
||||
tool: toolCallInfo.tool,
|
||||
arguments: input,
|
||||
status: 'done',
|
||||
response: {
|
||||
data: output,
|
||||
success: true
|
||||
},
|
||||
response: output,
|
||||
toolCallId: toolCallId
|
||||
}
|
||||
// 从活跃调用中移除(交互结束后整个实例会被丢弃)
|
||||
|
||||
@ -3,7 +3,7 @@ import WebSearchService from '@renderer/services/WebSearchService'
|
||||
import { Assistant, Message, WebSearchProvider } from '@renderer/types'
|
||||
import { UserMessageStatus } from '@renderer/types/newMessage'
|
||||
import { ExtractResults } from '@renderer/utils/extract'
|
||||
import { type InferToolOutput, tool } from 'ai'
|
||||
import { type InferToolInput, type InferToolOutput, tool } from 'ai'
|
||||
import { z } from 'zod'
|
||||
|
||||
// import { AiSdkTool, ToolCallResult } from './types'
|
||||
@ -18,15 +18,16 @@ const WebSearchProviderResult = z.object({
|
||||
})
|
||||
)
|
||||
})
|
||||
const webSearchToolInputSchema = z.object({
|
||||
query: z.string().describe('The query to search for')
|
||||
})
|
||||
|
||||
export const webSearchTool = (webSearchProviderId: WebSearchProvider['id']) => {
|
||||
const webSearchService = WebSearchService.getInstance(webSearchProviderId)
|
||||
return tool({
|
||||
name: 'builtin_web_search',
|
||||
description: 'Search the web for information',
|
||||
inputSchema: z.object({
|
||||
query: z.string().describe('The query to search for')
|
||||
}),
|
||||
inputSchema: webSearchToolInputSchema,
|
||||
outputSchema: WebSearchProviderResult,
|
||||
execute: async ({ query }) => {
|
||||
console.log('webSearchTool', query)
|
||||
@ -36,6 +37,7 @@ export const webSearchTool = (webSearchProviderId: WebSearchProvider['id']) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
export type WebSearchToolInput = InferToolInput<ReturnType<typeof webSearchTool>>
|
||||
export type WebSearchToolOutput = InferToolOutput<ReturnType<typeof webSearchTool>>
|
||||
|
||||
export const webSearchToolWithExtraction = (
|
||||
|
||||
@ -33,28 +33,6 @@ export default function Spinner({ text }: Props) {
|
||||
</Searching>
|
||||
)
|
||||
}
|
||||
|
||||
// const baseContainer = css`
|
||||
// display: flex;
|
||||
// flex-direction: row;
|
||||
// align-items: center;
|
||||
// `
|
||||
|
||||
// const Container = styled.div`
|
||||
// ${baseContainer}
|
||||
// background-color: var(--color-background-mute);
|
||||
// padding: 10px;
|
||||
// border-radius: 10px;
|
||||
// margin-bottom: 10px;
|
||||
// gap: 10px;
|
||||
// `
|
||||
|
||||
// const StatusText = styled.div`
|
||||
// font-size: 14px;
|
||||
// line-height: 1.6;
|
||||
// text-decoration: none;
|
||||
// color: var(--color-text-1);
|
||||
// `
|
||||
const SearchWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -1,48 +1,45 @@
|
||||
import Spinner from '@renderer/components/Spinner'
|
||||
import i18n from '@renderer/i18n'
|
||||
import type { MCPToolResponse } from '@renderer/types'
|
||||
import type { ToolMessageBlock } from '@renderer/types/newMessage'
|
||||
import { Collapse } from 'antd'
|
||||
import { useMemo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { MessageWebSearchToolBody, MessageWebSearchToolTitle } from './MessageWebSearchTool'
|
||||
|
||||
interface Props {
|
||||
block: ToolMessageBlock
|
||||
}
|
||||
|
||||
const toolNameMapText = {
|
||||
web_search: i18n.t('message.searching')
|
||||
}
|
||||
const toolDoneNameMapText = (args: Record<string, any>) => {
|
||||
const count = args.count ?? 0
|
||||
return i18n.t('message.websearch.fetch_complete', { count })
|
||||
}
|
||||
// const toolNameMapText = {
|
||||
// web_search: i18n.t('message.searching')
|
||||
// }
|
||||
// const toolDoneNameMapText = (args: Record<string, any>) => {
|
||||
// const count = args.count ?? 0
|
||||
// return i18n.t('message.websearch.fetch_complete', { count })
|
||||
// }
|
||||
|
||||
const PrepareTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||
const toolNameText = useMemo(
|
||||
() => toolNameMapText[toolResponse.tool.name] || toolResponse.tool.name,
|
||||
[toolResponse.tool]
|
||||
)
|
||||
// const PrepareTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||
// const toolNameText = useMemo(
|
||||
// () => toolNameMapText[toolResponse.tool.name] || toolResponse.tool.name,
|
||||
// [toolResponse.tool]
|
||||
// )
|
||||
|
||||
return (
|
||||
<Spinner
|
||||
text={
|
||||
<PrepareToolWrapper>
|
||||
{toolNameText}
|
||||
<span>{JSON.stringify(toolResponse.arguments)}</span>
|
||||
</PrepareToolWrapper>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
// return (
|
||||
// <Spinner
|
||||
// text={
|
||||
// <PrepareToolWrapper>
|
||||
// {toolNameText}
|
||||
// <span>{JSON.stringify(toolResponse.arguments)}</span>
|
||||
// </PrepareToolWrapper>
|
||||
// }
|
||||
// />
|
||||
// )
|
||||
// }
|
||||
|
||||
const DoneTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||
const toolDoneNameText = useMemo(
|
||||
() => toolDoneNameMapText({ count: toolResponse.response?.data?.length ?? 0 }),
|
||||
[toolResponse.response]
|
||||
)
|
||||
return <p>{toolDoneNameText}</p>
|
||||
}
|
||||
// const DoneTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||
// const toolDoneNameText = useMemo(
|
||||
// () => toolDoneNameMapText({ count: toolResponse.response?.data?.length ?? 0 }),
|
||||
// [toolResponse.response]
|
||||
// )
|
||||
// return <p>{toolDoneNameText}</p>
|
||||
// }
|
||||
|
||||
export default function MessageTool({ block }: Props) {
|
||||
const toolResponse = block.metadata?.rawMcpToolResponse
|
||||
@ -54,27 +51,25 @@ export default function MessageTool({ block }: Props) {
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label:
|
||||
toolResponse.status !== 'done' ? (
|
||||
<PrepareTool toolResponse={toolResponse} />
|
||||
) : (
|
||||
<DoneTool toolResponse={toolResponse} />
|
||||
),
|
||||
children: (
|
||||
<p>{JSON.stringify(toolResponse.status !== 'done' ? toolResponse.arguments : toolResponse.response)}</p>
|
||||
),
|
||||
showArrow: false
|
||||
label: <MessageWebSearchToolTitle toolResponse={toolResponse} />,
|
||||
children: <MessageWebSearchToolBody toolResponse={toolResponse} />,
|
||||
showArrow: false,
|
||||
styles: {
|
||||
header: {
|
||||
paddingLeft: '0'
|
||||
}
|
||||
}
|
||||
}
|
||||
]}
|
||||
size="small"
|
||||
ghost
|
||||
/>
|
||||
)
|
||||
}
|
||||
const PrepareToolWrapper = styled.span`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 14px;
|
||||
padding: 10px;
|
||||
padding-left: 0;
|
||||
`
|
||||
// const PrepareToolWrapper = styled.span`
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// gap: 4px;
|
||||
// font-size: 14px;
|
||||
// padding-left: 0;
|
||||
// `
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
import { WebSearchToolInput, WebSearchToolOutput } from '@renderer/aiCore/tools/WebSearchTool'
|
||||
import Spinner from '@renderer/components/Spinner'
|
||||
import i18n from '@renderer/i18n'
|
||||
import { MCPToolResponse } from '@renderer/types'
|
||||
import { Typography } from 'antd'
|
||||
import { Search } from 'lucide-react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const { Text, Link } = Typography
|
||||
|
||||
export const MessageWebSearchToolTitle = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||
const toolInput = toolResponse.arguments as WebSearchToolInput
|
||||
const toolOutput = toolResponse.response as WebSearchToolOutput
|
||||
|
||||
return toolResponse.status !== 'done' ? (
|
||||
<Spinner
|
||||
text={
|
||||
<PrepareToolWrapper>
|
||||
{i18n.t('message.searching')}
|
||||
<span>{toolInput?.query ?? ''}</span>
|
||||
</PrepareToolWrapper>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<MessageWebSearchToolTitleTextWrapper type="secondary">
|
||||
<Search size={16} style={{ color: 'unset' }} />
|
||||
{i18n.t('message.websearch.fetch_complete', { count: toolOutput.results.length ?? 0 })}
|
||||
</MessageWebSearchToolTitleTextWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export const MessageWebSearchToolBody = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||
const toolOutput = toolResponse.response as WebSearchToolOutput
|
||||
|
||||
return toolResponse.status === 'done' ? (
|
||||
<MessageWebSearchToolBodyUlWrapper>
|
||||
{toolOutput.results.map((result) => (
|
||||
<li key={result.url}>
|
||||
<Link href={result.url}>{result.title}</Link>
|
||||
</li>
|
||||
))}
|
||||
</MessageWebSearchToolBodyUlWrapper>
|
||||
) : null
|
||||
}
|
||||
|
||||
const PrepareToolWrapper = styled.span`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 14px;
|
||||
padding-left: 0;
|
||||
`
|
||||
|
||||
const MessageWebSearchToolTitleTextWrapper = styled(Text)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
`
|
||||
|
||||
const MessageWebSearchToolBodyUlWrapper = styled.ul`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 0;
|
||||
`
|
||||
Loading…
Reference in New Issue
Block a user