mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-08 14:29:15 +08:00
feat: support preview of MCP call results (#5236)
This commit is contained in:
parent
5a44f6aca8
commit
62b6584d65
@ -562,7 +562,9 @@
|
|||||||
"tools": {
|
"tools": {
|
||||||
"completed": "Completed",
|
"completed": "Completed",
|
||||||
"invoking": "Invoking",
|
"invoking": "Invoking",
|
||||||
"error": "Error occurred"
|
"error": "Error occurred",
|
||||||
|
"raw": "Raw",
|
||||||
|
"preview": "Preview"
|
||||||
},
|
},
|
||||||
"topic.added": "New topic added",
|
"topic.added": "New topic added",
|
||||||
"upgrade.success.button": "Restart",
|
"upgrade.success.button": "Restart",
|
||||||
|
|||||||
@ -561,7 +561,9 @@
|
|||||||
"tools": {
|
"tools": {
|
||||||
"completed": "完了",
|
"completed": "完了",
|
||||||
"invoking": "呼び出し中",
|
"invoking": "呼び出し中",
|
||||||
"error": "エラーが発生しました"
|
"error": "エラーが発生しました",
|
||||||
|
"raw": "生データ",
|
||||||
|
"preview": "プレビュー"
|
||||||
},
|
},
|
||||||
"topic.added": "新しいトピックが追加されました",
|
"topic.added": "新しいトピックが追加されました",
|
||||||
"upgrade.success.button": "再起動",
|
"upgrade.success.button": "再起動",
|
||||||
|
|||||||
@ -562,7 +562,9 @@
|
|||||||
"tools": {
|
"tools": {
|
||||||
"completed": "Завершено",
|
"completed": "Завершено",
|
||||||
"invoking": "Вызов",
|
"invoking": "Вызов",
|
||||||
"error": "Произошла ошибка"
|
"error": "Произошла ошибка",
|
||||||
|
"raw": "Исходный",
|
||||||
|
"preview": "Предпросмотр"
|
||||||
},
|
},
|
||||||
"topic.added": "Новый топик добавлен",
|
"topic.added": "Новый топик добавлен",
|
||||||
"upgrade.success.button": "Перезапустить",
|
"upgrade.success.button": "Перезапустить",
|
||||||
|
|||||||
@ -562,7 +562,9 @@
|
|||||||
"tools": {
|
"tools": {
|
||||||
"completed": "已完成",
|
"completed": "已完成",
|
||||||
"invoking": "调用中",
|
"invoking": "调用中",
|
||||||
"error": "发生错误"
|
"error": "发生错误",
|
||||||
|
"raw": "原始",
|
||||||
|
"preview": "预览"
|
||||||
},
|
},
|
||||||
"topic.added": "话题添加成功",
|
"topic.added": "话题添加成功",
|
||||||
"upgrade.success.button": "重启",
|
"upgrade.success.button": "重启",
|
||||||
|
|||||||
@ -562,7 +562,9 @@
|
|||||||
"tools": {
|
"tools": {
|
||||||
"completed": "已完成",
|
"completed": "已完成",
|
||||||
"invoking": "調用中",
|
"invoking": "調用中",
|
||||||
"error": "發生錯誤"
|
"error": "發生錯誤",
|
||||||
|
"raw": "原始碼",
|
||||||
|
"preview": "預覽"
|
||||||
},
|
},
|
||||||
"topic.added": "新話題已新增",
|
"topic.added": "新話題已新增",
|
||||||
"upgrade.success.button": "重新啟動",
|
"upgrade.success.button": "重新啟動",
|
||||||
|
|||||||
@ -503,7 +503,9 @@
|
|||||||
"switch.disabled": "Παρακαλείστε να περιμένετε τη λήξη της τρέχουσας απάντησης",
|
"switch.disabled": "Παρακαλείστε να περιμένετε τη λήξη της τρέχουσας απάντησης",
|
||||||
"tools": {
|
"tools": {
|
||||||
"completed": "Ολοκληρώθηκε",
|
"completed": "Ολοκληρώθηκε",
|
||||||
"invoking": "κλήση σε εξέλιξη"
|
"invoking": "κλήση σε εξέλιξη",
|
||||||
|
"raw": "Ακατέργαστο",
|
||||||
|
"preview": "Προεπισκόπηση"
|
||||||
},
|
},
|
||||||
"topic.added": "Η θεματική προστέθηκε επιτυχώς",
|
"topic.added": "Η θεματική προστέθηκε επιτυχώς",
|
||||||
"upgrade.success.button": "Επανεκκίνηση",
|
"upgrade.success.button": "Επανεκκίνηση",
|
||||||
|
|||||||
@ -503,7 +503,9 @@
|
|||||||
"switch.disabled": "Espere a que se complete la respuesta actual antes de realizar la operación",
|
"switch.disabled": "Espere a que se complete la respuesta actual antes de realizar la operación",
|
||||||
"tools": {
|
"tools": {
|
||||||
"completed": "Completado",
|
"completed": "Completado",
|
||||||
"invoking": "En llamada"
|
"invoking": "En llamada",
|
||||||
|
"raw": "Crudo",
|
||||||
|
"preview": "Vista previa"
|
||||||
},
|
},
|
||||||
"topic.added": "Tema agregado con éxito",
|
"topic.added": "Tema agregado con éxito",
|
||||||
"upgrade.success.button": "Reiniciar",
|
"upgrade.success.button": "Reiniciar",
|
||||||
|
|||||||
@ -503,7 +503,9 @@
|
|||||||
"switch.disabled": "Veuillez attendre la fin de la réponse actuelle avant de procéder",
|
"switch.disabled": "Veuillez attendre la fin de la réponse actuelle avant de procéder",
|
||||||
"tools": {
|
"tools": {
|
||||||
"completed": "Terminé",
|
"completed": "Terminé",
|
||||||
"invoking": "En cours d'exécution"
|
"invoking": "En cours d'exécution",
|
||||||
|
"raw": "Brut",
|
||||||
|
"preview": "Aperçu"
|
||||||
},
|
},
|
||||||
"topic.added": "Thème ajouté avec succès",
|
"topic.added": "Thème ajouté avec succès",
|
||||||
"upgrade.success.button": "Redémarrer",
|
"upgrade.success.button": "Redémarrer",
|
||||||
|
|||||||
@ -503,7 +503,9 @@
|
|||||||
"switch.disabled": "Aguarde a conclusão da resposta atual antes de operar",
|
"switch.disabled": "Aguarde a conclusão da resposta atual antes de operar",
|
||||||
"tools": {
|
"tools": {
|
||||||
"completed": "Completo",
|
"completed": "Completo",
|
||||||
"invoking": "Em execução"
|
"invoking": "Em execução",
|
||||||
|
"raw": "Bruto",
|
||||||
|
"preview": "Pré-visualização"
|
||||||
},
|
},
|
||||||
"topic.added": "Tópico adicionado com sucesso",
|
"topic.added": "Tópico adicionado com sucesso",
|
||||||
"upgrade.success.button": "Reiniciar",
|
"upgrade.success.button": "Reiniciar",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { CheckOutlined, ExpandOutlined, LoadingOutlined, WarningOutlined } from '@ant-design/icons'
|
import { CheckOutlined, ExpandOutlined, LoadingOutlined, WarningOutlined } from '@ant-design/icons'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import { Message } from '@renderer/types'
|
import { Message } from '@renderer/types'
|
||||||
import { Collapse, message as antdMessage, Modal, Tooltip } from 'antd'
|
import { Collapse, message as antdMessage, Modal, Tabs, Tooltip } from 'antd'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import { FC, useMemo, useState } from 'react'
|
import { FC, useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -116,6 +116,24 @@ const MessageTools: FC<Props> = ({ message }) => {
|
|||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const renderPreview = (content: string) => {
|
||||||
|
if (!content) return null
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsedResult = JSON.parse(content)
|
||||||
|
switch (parsedResult.content[0]?.type) {
|
||||||
|
case 'text':
|
||||||
|
return <PreviewBlock>{parsedResult.content[0].text}</PreviewBlock>
|
||||||
|
// TODO: support other types
|
||||||
|
default:
|
||||||
|
return <PreviewBlock>{content}</PreviewBlock>
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('failed to render the preview of mcp results:', e)
|
||||||
|
return <PreviewBlock>{content}</PreviewBlock>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CollapseContainer
|
<CollapseContainer
|
||||||
@ -139,18 +157,42 @@ const MessageTools: FC<Props> = ({ message }) => {
|
|||||||
styles={{ body: { maxHeight: '80vh', overflow: 'auto' } }}>
|
styles={{ body: { maxHeight: '80vh', overflow: 'auto' } }}>
|
||||||
{expandedResponse && (
|
{expandedResponse && (
|
||||||
<ExpandedResponseContainer style={{ fontFamily, fontSize }}>
|
<ExpandedResponseContainer style={{ fontFamily, fontSize }}>
|
||||||
<ActionButton
|
{/* mode swtich tabs */}
|
||||||
className="copy-expanded-button"
|
<Tabs
|
||||||
onClick={() => {
|
tabBarExtraContent={
|
||||||
if (expandedResponse) {
|
<ActionButton
|
||||||
navigator.clipboard.writeText(expandedResponse.content)
|
className="copy-expanded-button"
|
||||||
antdMessage.success({ content: t('message.copied'), key: 'copy-expanded' })
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(
|
||||||
|
typeof expandedResponse.content === 'string'
|
||||||
|
? expandedResponse.content
|
||||||
|
: JSON.stringify(expandedResponse.content, null, 2)
|
||||||
|
)
|
||||||
|
antdMessage.success({ content: t('message.copied'), key: 'copy-expanded' })
|
||||||
|
}}
|
||||||
|
aria-label={t('common.copy')}>
|
||||||
|
<i className="iconfont icon-copy"></i>
|
||||||
|
</ActionButton>
|
||||||
|
}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: 'preview',
|
||||||
|
label: t('message.tools.preview'),
|
||||||
|
children: renderPreview(expandedResponse.content)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'raw',
|
||||||
|
label: t('message.tools.raw'),
|
||||||
|
children: (
|
||||||
|
<CodeBlock>
|
||||||
|
{typeof expandedResponse.content === 'string'
|
||||||
|
? expandedResponse.content
|
||||||
|
: JSON.stringify(expandedResponse.content, null, 2)}
|
||||||
|
</CodeBlock>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}}
|
]}
|
||||||
aria-label={t('common.copy')}>
|
/>
|
||||||
<i className="iconfont icon-copy"></i>
|
|
||||||
</ActionButton>
|
|
||||||
<CodeBlock>{expandedResponse.content}</CodeBlock>
|
|
||||||
</ExpandedResponseContainer>
|
</ExpandedResponseContainer>
|
||||||
)}
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
@ -267,6 +309,14 @@ const ToolResponseContainer = styled.div`
|
|||||||
position: relative;
|
position: relative;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const PreviewBlock = styled.div`
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
color: var(--color-text);
|
||||||
|
user-select: text;
|
||||||
|
`
|
||||||
|
|
||||||
const CodeBlock = styled.pre`
|
const CodeBlock = styled.pre`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user