mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-07 13:59:28 +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",
|
"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",
|
"description": "Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/index.mjs",
|
"module": "dist/index.mjs",
|
||||||
|
|||||||
@ -229,10 +229,7 @@ export class ToolCallChunkHandler {
|
|||||||
tool: toolCallInfo.tool,
|
tool: toolCallInfo.tool,
|
||||||
arguments: input,
|
arguments: input,
|
||||||
status: 'done',
|
status: 'done',
|
||||||
response: {
|
response: output,
|
||||||
data: output,
|
|
||||||
success: true
|
|
||||||
},
|
|
||||||
toolCallId: toolCallId
|
toolCallId: toolCallId
|
||||||
}
|
}
|
||||||
// 从活跃调用中移除(交互结束后整个实例会被丢弃)
|
// 从活跃调用中移除(交互结束后整个实例会被丢弃)
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import WebSearchService from '@renderer/services/WebSearchService'
|
|||||||
import { Assistant, Message, WebSearchProvider } from '@renderer/types'
|
import { Assistant, Message, WebSearchProvider } from '@renderer/types'
|
||||||
import { UserMessageStatus } from '@renderer/types/newMessage'
|
import { UserMessageStatus } from '@renderer/types/newMessage'
|
||||||
import { ExtractResults } from '@renderer/utils/extract'
|
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 { z } from 'zod'
|
||||||
|
|
||||||
// import { AiSdkTool, ToolCallResult } from './types'
|
// 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']) => {
|
export const webSearchTool = (webSearchProviderId: WebSearchProvider['id']) => {
|
||||||
const webSearchService = WebSearchService.getInstance(webSearchProviderId)
|
const webSearchService = WebSearchService.getInstance(webSearchProviderId)
|
||||||
return tool({
|
return tool({
|
||||||
name: 'builtin_web_search',
|
name: 'builtin_web_search',
|
||||||
description: 'Search the web for information',
|
description: 'Search the web for information',
|
||||||
inputSchema: z.object({
|
inputSchema: webSearchToolInputSchema,
|
||||||
query: z.string().describe('The query to search for')
|
|
||||||
}),
|
|
||||||
outputSchema: WebSearchProviderResult,
|
outputSchema: WebSearchProviderResult,
|
||||||
execute: async ({ query }) => {
|
execute: async ({ query }) => {
|
||||||
console.log('webSearchTool', 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 type WebSearchToolOutput = InferToolOutput<ReturnType<typeof webSearchTool>>
|
||||||
|
|
||||||
export const webSearchToolWithExtraction = (
|
export const webSearchToolWithExtraction = (
|
||||||
|
|||||||
@ -33,28 +33,6 @@ export default function Spinner({ text }: Props) {
|
|||||||
</Searching>
|
</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`
|
const SearchWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
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 type { ToolMessageBlock } from '@renderer/types/newMessage'
|
||||||
import { Collapse } from 'antd'
|
import { Collapse } from 'antd'
|
||||||
import { useMemo } from 'react'
|
|
||||||
import styled from 'styled-components'
|
import { MessageWebSearchToolBody, MessageWebSearchToolTitle } from './MessageWebSearchTool'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
block: ToolMessageBlock
|
block: ToolMessageBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolNameMapText = {
|
// const toolNameMapText = {
|
||||||
web_search: i18n.t('message.searching')
|
// web_search: i18n.t('message.searching')
|
||||||
}
|
// }
|
||||||
const toolDoneNameMapText = (args: Record<string, any>) => {
|
// const toolDoneNameMapText = (args: Record<string, any>) => {
|
||||||
const count = args.count ?? 0
|
// const count = args.count ?? 0
|
||||||
return i18n.t('message.websearch.fetch_complete', { count })
|
// return i18n.t('message.websearch.fetch_complete', { count })
|
||||||
}
|
// }
|
||||||
|
|
||||||
const PrepareTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
// const PrepareTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||||
const toolNameText = useMemo(
|
// const toolNameText = useMemo(
|
||||||
() => toolNameMapText[toolResponse.tool.name] || toolResponse.tool.name,
|
// () => toolNameMapText[toolResponse.tool.name] || toolResponse.tool.name,
|
||||||
[toolResponse.tool]
|
// [toolResponse.tool]
|
||||||
)
|
// )
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<Spinner
|
// <Spinner
|
||||||
text={
|
// text={
|
||||||
<PrepareToolWrapper>
|
// <PrepareToolWrapper>
|
||||||
{toolNameText}
|
// {toolNameText}
|
||||||
<span>{JSON.stringify(toolResponse.arguments)}</span>
|
// <span>{JSON.stringify(toolResponse.arguments)}</span>
|
||||||
</PrepareToolWrapper>
|
// </PrepareToolWrapper>
|
||||||
}
|
// }
|
||||||
/>
|
// />
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
const DoneTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
// const DoneTool = ({ toolResponse }: { toolResponse: MCPToolResponse }) => {
|
||||||
const toolDoneNameText = useMemo(
|
// const toolDoneNameText = useMemo(
|
||||||
() => toolDoneNameMapText({ count: toolResponse.response?.data?.length ?? 0 }),
|
// () => toolDoneNameMapText({ count: toolResponse.response?.data?.length ?? 0 }),
|
||||||
[toolResponse.response]
|
// [toolResponse.response]
|
||||||
)
|
// )
|
||||||
return <p>{toolDoneNameText}</p>
|
// return <p>{toolDoneNameText}</p>
|
||||||
}
|
// }
|
||||||
|
|
||||||
export default function MessageTool({ block }: Props) {
|
export default function MessageTool({ block }: Props) {
|
||||||
const toolResponse = block.metadata?.rawMcpToolResponse
|
const toolResponse = block.metadata?.rawMcpToolResponse
|
||||||
@ -54,27 +51,25 @@ export default function MessageTool({ block }: Props) {
|
|||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
key: '1',
|
key: '1',
|
||||||
label:
|
label: <MessageWebSearchToolTitle toolResponse={toolResponse} />,
|
||||||
toolResponse.status !== 'done' ? (
|
children: <MessageWebSearchToolBody toolResponse={toolResponse} />,
|
||||||
<PrepareTool toolResponse={toolResponse} />
|
showArrow: false,
|
||||||
) : (
|
styles: {
|
||||||
<DoneTool toolResponse={toolResponse} />
|
header: {
|
||||||
),
|
paddingLeft: '0'
|
||||||
children: (
|
}
|
||||||
<p>{JSON.stringify(toolResponse.status !== 'done' ? toolResponse.arguments : toolResponse.response)}</p>
|
}
|
||||||
),
|
|
||||||
showArrow: false
|
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
|
size="small"
|
||||||
ghost
|
ghost
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const PrepareToolWrapper = styled.span`
|
// const PrepareToolWrapper = styled.span`
|
||||||
display: flex;
|
// display: flex;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
gap: 4px;
|
// gap: 4px;
|
||||||
font-size: 14px;
|
// font-size: 14px;
|
||||||
padding: 10px;
|
// padding-left: 0;
|
||||||
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