From c78ac6acd7f3af6757b6ab61a48f5f0e92cc7cee Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Thu, 15 Jan 2026 14:01:43 +0800 Subject: [PATCH] feat: enhance iPython tool rendering with Shiki syntax highlighting --- dashboard/package.json | 2 +- dashboard/src/components/chat/MessageList.vue | 137 +++++++++++++++--- 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/dashboard/package.json b/dashboard/package.json index d4c0ef485..87bacdab7 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -28,7 +28,7 @@ "katex": "^0.16.27", "lodash": "4.17.21", "markdown-it": "^14.1.0", - "markstream-vue": "0.0.3-beta.7", + "markstream-vue": "^0.0.6-beta.1", "mermaid": "^11.12.2", "pinia": "2.1.6", "pinyin-pro": "^3.26.0", diff --git a/dashboard/src/components/chat/MessageList.vue b/dashboard/src/components/chat/MessageList.vue index 78aafefc2..987827bf0 100644 --- a/dashboard/src/components/chat/MessageList.vue +++ b/dashboard/src/components/chat/MessageList.vue @@ -147,24 +147,44 @@ borderTopColor: 'rgba(100, 140, 200, 0.3)', backgroundColor: 'rgba(30, 45, 70, 0.5)' } : {}"> -
- ID: - {{ toolCall.id - }} -
-
- Args: -
{{
-                                                            JSON.stringify(toolCall.args, null, 2) }}
-
-
- Result: -
{{ formatToolResult(toolCall.result) }}
+                                                
+                                                
+                                                
+                                                
+                                                
                                             
@@ -305,6 +325,7 @@ import 'markstream-vue/index.css' import 'katex/dist/katex.min.css' import 'highlight.js/styles/github.css'; import axios from 'axios'; +import { createHighlighter } from 'shiki'; enableKatex(); enableMermaid(); @@ -363,15 +384,19 @@ export default { imagePreview: { show: false, url: '' - } + }, + // Shiki highlighter + shikiHighlighter: null, + shikiReady: false }; }, - mounted() { + async mounted() { this.initCodeCopyButtons(); this.initImageClickEvents(); this.addScrollListener(); this.scrollToBottom(); this.startElapsedTimeTimer(); + await this.initShiki(); }, updated() { this.initCodeCopyButtons(); @@ -903,6 +928,52 @@ export default { setTimeout(() => { this.imagePreview.url = ''; }, 300); + }, + + // Initialize Shiki highlighter + async initShiki() { + try { + this.shikiHighlighter = await createHighlighter({ + themes: ['nord', 'github-light'], + langs: ['python'] + }); + this.shikiReady = true; + } catch (err) { + console.error('Failed to initialize Shiki:', err); + } + }, + + // Check if tool is iPython executor + isIPythonTool(toolCall) { + return toolCall.name === 'astrbot_execute_ipython'; + }, + + // Get iPython code from tool args + getIPythonCode(toolCall) { + try { + if (toolCall.args && toolCall.args.code) { + return toolCall.args.code; + } + } catch (err) { + console.error('Failed to get iPython code:', err); + } + return null; + }, + + // Highlight iPython code with Shiki + highlightIPythonCode(code) { + if (!this.shikiReady || !this.shikiHighlighter || !code) { + return ''; + } + try { + return this.shikiHighlighter.codeToHtml(code, { + lang: 'python', + theme: this.isDark ? 'nord' : 'github-light' + }); + } catch (err) { + console.error('Failed to highlight code:', err); + return `
${code}
`; + } } } } @@ -1623,6 +1694,34 @@ export default { max-height: 300px; background-color: transparent; } + +/* iPython Tool Special Styles */ +.ipython-code-container { + margin-bottom: 12px; +} + +.ipython-label { + margin-bottom: 8px; +} + +.ipython-code-highlighted { + border-radius: 6px; + overflow-x: auto; + font-size: 13px; + line-height: 1.5; +} + +.ipython-code-highlighted :deep(pre) { + margin: 0; + padding: 12px; + border-radius: 6px; + overflow-x: auto; +} + +.ipython-code-highlighted :deep(code) { + font-family: 'Fira Code', 'Consolas', monospace; + font-size: 13px; +}