diff --git a/CHANGELOG.md b/CHANGELOG.md index 4486c14..ad03904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ - 修复 bug:流式传输进行 function calling 时,多工具的索引串流导致的 JSON Schema 反序列化失败 - 修复 bug:大模型返回大量重复错误信息 - 新特性:支持一次对话同时调用多个工具 +- UI:优化代码高亮的滚动条 +- 新特性:resources/list 协议的内容点击就会直接渲染,无需二次发送 +- 新特性:resources prompts tools 的结果的 json 模式支持高亮 ## [main] 0.0.7 - 优化页面布局,使得调试窗口可以显示更多内容 diff --git a/renderer/src/components/json-render/index.vue b/renderer/src/components/json-render/index.vue new file mode 100644 index 0000000..edf0df2 --- /dev/null +++ b/renderer/src/components/json-render/index.vue @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/renderer/src/components/main-panel/chat/chat-box/options/resource.vue b/renderer/src/components/main-panel/chat/chat-box/options/resource.vue index 66a9953..a3846fd 100644 --- a/renderer/src/components/main-panel/chat/chat-box/options/resource.vue +++ b/renderer/src/components/main-panel/chat/chat-box/options/resource.vue @@ -7,7 +7,7 @@
- +
`; - - // 添加复制按钮(右上角) - container += ` -
-
${lang || ''}
- -
- `; - - if (lang && Prism.languages[lang]) { - // 使用 Prism 高亮代码 - const highlightedCode = Prism.highlight(str, Prism.languages[lang], lang); - // 添加代码区域 - container += `
${highlightedCode}
`; - } else { - // 普通代码块 - container += `
${escapeHtml(str)}
`; - } - - container += `
`; - return container; +interface HighlightOption { + needTools?: boolean } +// 导出默认的 highlight 函数 +export default function highlight(option: HighlightOption = {}) { + const { + needTools = true + } = option; + + return (str: string, lang: string) => { + + if (needTools) { + // 创建代码块容器 + let container = `
`; + + // 添加复制按钮(右上角) + container += ` +
+
${lang || ''}
+ +
+ `; + + if (lang && Prism.languages[lang]) { + // 使用 Prism 高亮代码 + const highlightedCode = Prism.highlight(str, Prism.languages[lang], lang); + // 添加代码区域 + container += `
${highlightedCode}
`; + } else { + // 普通代码块 + container += `
${escapeHtml(str)}
`; + } + + container += `
`; + return container; + } else { + return Prism.highlight(str, Prism.languages[lang], lang); + } + } +} + + // 全局复制函数 (window as any).copyCode = function (button: HTMLElement) { const codeBlock = button.closest('.openmcp-code-block'); if (!codeBlock) return; const codeElement = codeBlock.querySelector('code'); const code = codeElement?.textContent || ''; - + navigator.clipboard.writeText(code).then(() => { const originalText = button.textContent; button.textContent = '已复制'; diff --git a/renderer/src/components/main-panel/chat/markdown/markdown.ts b/renderer/src/components/main-panel/chat/markdown/markdown.ts index 9c3f420..1535517 100644 --- a/renderer/src/components/main-panel/chat/markdown/markdown.ts +++ b/renderer/src/components/main-panel/chat/markdown/markdown.ts @@ -3,7 +3,7 @@ import MarkdownKatex from './markdown-katex'; import MarkdownHighlight from './markdown-highlight'; const md = new MarkdownIt({ - highlight: MarkdownHighlight, + highlight: MarkdownHighlight({ needTools: true }), }); md.use(MarkdownKatex, { @@ -18,6 +18,35 @@ export const markdownToHtml = (markdown: string) => { return md.render(markdown); }; +const pureHighLightMd = new MarkdownIt({ + highlight: MarkdownHighlight({ needTools: false }), +}); + export const copyToClipboard = (text: string) => { return navigator.clipboard.writeText(text); }; + +const tryParseJson = (text: string) => { + try { + return JSON.parse(text); + } catch (error) { + return text; + } +} + + +const prettifyObj = (obj: object | string) => { + const rawObj = typeof obj === 'string' ? tryParseJson(obj) : obj; + return JSON.stringify(rawObj, null, 2); +} + +export const renderJson = (obj: object | string | undefined) => { + if (!obj) { + return 'Invalid JSON'; + } + + const jsonString = prettifyObj(obj); + const md = "```json\n" + jsonString + "\n```"; + const html = pureHighLightMd.render(md); + return html; +} \ No newline at end of file diff --git a/renderer/src/components/main-panel/chat/markdown/prism/prism.css b/renderer/src/components/main-panel/chat/markdown/prism/prism.css index 9408867..27b6826 100644 --- a/renderer/src/components/main-panel/chat/markdown/prism/prism.css +++ b/renderer/src/components/main-panel/chat/markdown/prism/prism.css @@ -36,7 +36,6 @@ max-height: inherit; height: inherit; display: block; - overflow: auto; background-color: unset !important; } @@ -251,7 +250,6 @@ max-height: inherit; height: inherit; display: block; - overflow: auto; background-color: unset !important; } diff --git a/renderer/src/components/main-panel/chat/message/toolcall-result-item.vue b/renderer/src/components/main-panel/chat/message/toolcall-result-item.vue index c2dcc58..d507380 100644 --- a/renderer/src/components/main-panel/chat/message/toolcall-result-item.vue +++ b/renderer/src/components/main-panel/chat/message/toolcall-result-item.vue @@ -1,5 +1,5 @@ @@ -36,6 +36,7 @@ import { defineComponent, defineProps, computed, ref } from 'vue'; import { useI18n } from 'vue-i18n'; import { tabs } from '../panel'; import { PromptStorage } from './prompts'; +import JsonRender from '@/components/json-render/index.vue'; defineComponent({ name: 'prompt-logger' }); const { t } = useI18n(); @@ -52,13 +53,6 @@ const tabStorage = tab.storage as PromptStorage; const showRawJson = ref(false); -const formattedJson = computed(() => { - try { - return JSON.stringify(tabStorage.lastPromptGetResponse, null, 2); - } catch { - return 'Invalid JSON'; - } -});