feat: tooluse result display style optimization (#5758)

This commit is contained in:
karl 2025-05-09 09:52:15 +08:00 committed by GitHub
parent 671bc64529
commit 416a5ebcc6
2 changed files with 40 additions and 18 deletions

View File

@ -1,6 +1,7 @@
import { CheckOutlined, ExpandOutlined, LoadingOutlined, WarningOutlined } from '@ant-design/icons'
import { useSettings } from '@renderer/hooks/useSettings'
import type { ToolMessageBlock } from '@renderer/types/newMessage'
import { useShikiWithMarkdownIt } from '@renderer/utils/shiki'
import { Collapse, message as antdMessage, Modal, Tabs, Tooltip } from 'antd'
import { FC, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -25,6 +26,22 @@ const MessageTools: FC<Props> = ({ blocks }) => {
const toolResponse = blocks.metadata?.rawMcpToolResponse
const resultString = useMemo(() => {
try {
return JSON.stringify(
{
params: toolResponse?.tool?.inputSchema,
response: toolResponse?.response
},
null,
2
)
} catch (e) {
return 'Invalid Result'
}
}, [toolResponse])
const { renderedMarkdown: styledResult } = useShikiWithMarkdownIt(`\`\`\`json\n${resultString}\n\`\`\``)
if (!toolResponse) {
return null
}
@ -107,7 +124,7 @@ const MessageTools: FC<Props> = ({ blocks }) => {
),
children: isDone && result && (
<ToolResponseContainer style={{ fontFamily, fontSize: '12px' }}>
<CodeBlock>{JSON.stringify(result, null, 2)}</CodeBlock>
<div className="markdown" dangerouslySetInnerHTML={{ __html: styledResult }} />
</ToolResponseContainer>
)
})
@ -183,13 +200,7 @@ const MessageTools: FC<Props> = ({ blocks }) => {
{
key: 'raw',
label: t('message.tools.raw'),
children: (
<CodeBlock>
{typeof expandedResponse.content === 'string'
? expandedResponse.content
: JSON.stringify(expandedResponse.content, null, 2)}
</CodeBlock>
)
children: <div className="markdown" dangerouslySetInnerHTML={{ __html: styledResult }} />
}
]}
/>
@ -300,9 +311,7 @@ const CollapsibleIcon = styled.i`
`
const ToolResponseContainer = styled.div`
background: var(--color-bg-1);
border-radius: 0 0 4px 4px;
padding: 12px 16px;
overflow: auto;
max-height: 300px;
border-top: none;
@ -317,14 +326,6 @@ const PreviewBlock = styled.div`
user-select: text;
`
const CodeBlock = styled.pre`
margin: 0;
white-space: pre-wrap;
word-break: break-word;
color: var(--color-text);
font-family: ubuntu;
`
const ExpandedResponseContainer = styled.div`
background: var(--color-bg-1);
border-radius: 8px;

View File

@ -1,6 +1,8 @@
import { useTheme } from '@renderer/context/ThemeProvider'
import { ThemeMode } from '@renderer/types'
import { MarkdownItShikiOptions, setupMarkdownIt } from '@shikijs/markdown-it'
import MarkdownIt from 'markdown-it'
import { useEffect, useRef, useState } from 'react'
import { BuiltinLanguage, BuiltinTheme, bundledLanguages, createHighlighter } from 'shiki'
const defaultOptions = {
@ -33,3 +35,22 @@ export function getShikiInstance(theme: ThemeMode) {
setupMarkdownIt(markdownit, highlighter, options)
}
}
export function useShikiWithMarkdownIt(content: string) {
const [renderedMarkdown, setRenderedMarkdown] = useState('')
const md = useRef<MarkdownIt>(
new MarkdownIt({
linkify: true, // 自动转换 URL 为链接
typographer: true // 启用印刷格式优化
})
)
const { theme } = useTheme()
useEffect(() => {
const sk = getShikiInstance(theme)
md.current.use(sk)
setRenderedMarkdown(md.current.render(content))
}, [content, theme])
return {
renderedMarkdown
}
}