From 07871765877c49062c7806c1203574fd06c87817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=AA=E5=B3=B0?= <2235113304@qq.com> Date: Thu, 14 Aug 2025 09:07:54 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=96=B0=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron.vite.config.1755071894873.mjs | 104 ++++++++++++++++++ package.json | 3 +- .../presenter/llmProviderPresenter/index.ts | 61 ++++++++++ .../presenter/mcpPresenter/toolManager.ts | 24 +++- src/main/presenter/threadPresenter/index.ts | 48 ++++---- src/renderer/src/components/ChatInput.vue | 39 ++++++- .../message/MessageBlockToolCall.vue | 77 +++++++++++-- src/renderer/src/i18n/zh-CN/chat.json | 1 + src/renderer/src/stores/aiStore.ts | 16 +++ src/renderer/src/stores/chat.ts | 6 + src/renderer/src/stores/mcp.ts | 7 +- src/shared/chat.d.ts | 1 + src/shared/presenter.d.ts | 4 +- 13 files changed, 350 insertions(+), 41 deletions(-) create mode 100644 electron.vite.config.1755071894873.mjs create mode 100644 src/renderer/src/stores/aiStore.ts diff --git a/electron.vite.config.1755071894873.mjs b/electron.vite.config.1755071894873.mjs new file mode 100644 index 000000000..12e52acfe --- /dev/null +++ b/electron.vite.config.1755071894873.mjs @@ -0,0 +1,104 @@ +// electron.vite.config.ts +import { resolve } from "path"; +import { defineConfig, externalizeDepsPlugin } from "electron-vite"; +import vue from "@vitejs/plugin-vue"; +import autoprefixer from "autoprefixer"; +import tailwind from "tailwindcss"; +import vueDevTools from "vite-plugin-vue-devtools"; +import svgLoader from "vite-svg-loader"; +import monacoEditorPlugin from "vite-plugin-monaco-editor-esm"; +import path from "node:path"; +var electron_vite_config_default = defineConfig({ + main: { + plugins: [ + externalizeDepsPlugin({ + exclude: ["mermaid", "dompurify"] + }) + ], + resolve: { + alias: { + "@": resolve("src/main/"), + "@shared": resolve("src/shared") + } + }, + build: { + rollupOptions: { + external: ["sharp", "@duckdb/node-api"], + output: { + inlineDynamicImports: true, + manualChunks: void 0 + // Disable automatic chunk splitting + } + } + } + }, + preload: { + plugins: [externalizeDepsPlugin()], + resolve: { + alias: { + "@shared": resolve("src/shared") + } + }, + build: { + rollupOptions: { + input: { + index: resolve("src/preload/index.ts"), + floating: resolve("src/preload/floating-preload.ts") + } + } + } + }, + renderer: { + optimizeDeps: { + include: [ + "monaco-editor", + "axios" + ] + }, + resolve: { + alias: { + "@": resolve("src/renderer/src"), + "@shell": resolve("src/renderer/shell"), + "@shared": resolve("src/shared"), + vue: "vue/dist/vue.esm-bundler.js" + } + }, + css: { + postcss: { + // @ts-ignore + plugins: [tailwind(), autoprefixer()] + } + }, + server: { + host: "0.0.0.0" + // 防止代理干扰,导致vite-electron之间ws://localhost:5713和http://localhost:5713通信失败、页面组件无法加载 + }, + plugins: [ + monacoEditorPlugin({ + languageWorkers: ["editorWorkerService", "typescript", "css", "html", "json"], + customDistPath(_root, buildOutDir, _base) { + return path.resolve(buildOutDir, "monacoeditorwork"); + } + }), + vue(), + svgLoader(), + vueDevTools({ + // use export LAUNCH_EDITOR=cursor instead + // launchEditor: 'cursor' + }) + ], + build: { + minify: "esbuild", + rollupOptions: { + input: { + shell: resolve("src/renderer/shell/index.html"), + index: resolve("src/renderer/index.html"), + floating: resolve("src/renderer/floating/index.html") + } + } + } + } +}); +export { + electron_vite_config_default as default +}; diff --git a/package.json b/package.json index 5219feee4..ad45b358d 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "https-proxy-agent": "^7.0.6", "jsonrepair": "^3.13.0", "mammoth": "^1.9.0", + "marked": "^16.1.2", "mime-types": "^2.1.35", "nanoid": "^5.1.5", "ollama": "^0.5.16", @@ -152,10 +153,10 @@ "vite-plugin-monaco-editor-esm": "^2.0.2", "vite-plugin-vue-devtools": "^8.0.0", "vite-svg-loader": "^5.1.0", - "vue-renderer-markdown": "^0.0.34", "vitest": "^3.2.4", "vue": "^3.5.18", "vue-i18n": "^11.1.11", + "vue-renderer-markdown": "^0.0.34", "vue-router": "4", "vue-tsc": "^2.2.10", "vue-use-monaco": "^0.0.6", diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index 33b76b575..cf1dce98d 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -821,6 +821,41 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { if (abortController.signal.aborted) break // Check after tool call returns + // 检查是否需要直接返回工具调用结果,不经过AI二次处理 + const directReturnValue = + typeof toolResponse.rawData.directReturn === 'boolean' + ? toolResponse.rawData.directReturn + : toolResponse.rawData.directReturn?.aiChange + console.log('index-toolResponse.rawData.directReturn', directReturnValue) + if (directReturnValue) { + console.log( + `[Agent Loop] Direct return tool result for ${toolCall.name}, skipping AI processing` + ) + + // 直接返回工具调用结果,不继续对话 + yield { + type: 'response', + data: { + eventId, + tool_call: 'end', + tool_call_id: toolCall.id, + tool_call_name: toolCall.name, + tool_call_params: toolCall.arguments, + tool_call_server_name: toolDef.server.name, + tool_call_server_icons: toolDef.server.icons, + tool_call_server_description: toolDef.server.description, + tool_call_response: toolResponse.content, + tool_call_response_raw: toolResponse.rawData, + direct_return: true + } + } + + // 结束agent循环 + console.log(`[Agent Loop] Ending agent loop for direct return, event: ${eventId}`) + needContinueConversation = false + break + } + // Check if permission is required if (toolResponse.rawData.requiresPermission) { console.log( @@ -919,6 +954,19 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { tool_call_response_raw: toolResponse.rawData // Full raw data } } + + // 如果工具响应中包含 directReturn 标志,则直接返回结果,不继续对话 + if (toolResponse.rawData && toolResponse.rawData.directReturn === true) { + console.log( + `[LLMProviderPresenter] Tool response has directReturn flag, ending agent loop` + ) + // 发送结束事件 + yield { + type: 'end', + data: { eventId } + } + return // 结束代理循环 + } } else { // Non-native FC: Add tool execution record to conversation history for next LLM turn. @@ -981,6 +1029,19 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { tool_call_response_raw: toolResponse.rawData // Full raw data for ThreadPresenter to store } } + + // 如果工具响应中包含 directReturn 标志,则直接返回结果,不继续对话 + if (toolResponse.rawData && toolResponse.rawData.directReturn === true) { + console.log( + `[LLMProviderPresenter] Tool response has directReturn flag, ending agent loop` + ) + // 发送结束事件 + yield { + type: 'end', + data: { eventId } + } + return // 结束代理循环 + } } } catch (toolError) { if (abortController.signal.aborted) break // Check after tool error diff --git a/src/main/presenter/mcpPresenter/toolManager.ts b/src/main/presenter/mcpPresenter/toolManager.ts index 1f984e075..612df89b9 100644 --- a/src/main/presenter/mcpPresenter/toolManager.ts +++ b/src/main/presenter/mcpPresenter/toolManager.ts @@ -13,7 +13,16 @@ import { ServerManager } from './serverManager' import { McpClient } from './mcpClient' import { jsonrepair } from 'jsonrepair' import { getErrorMessageLabels } from '@shared/i18n' - +import { ipcMain } from 'electron' +// import { useAiStore } from '@/render/src/stores/aiStore'; +// const aiStore = useAiStore(); +// console.log("MCPToolResponse123",response) +let aiChange = false +ipcMain.on('aiChangeEvent', (event, arg) => { + console.log('收到渲染进程消息aiChangeEvent:', arg) + // 处理逻辑... + aiChange = arg +}) export class ToolManager { private configPresenter: IConfigPresenter private serverManager: ServerManager @@ -429,13 +438,17 @@ export class ToolManager { } else if (result.content) { formattedContent = JSON.stringify(result.content) } - const response: MCPToolResponse = { toolCallId: toolCall.id, content: formattedContent, - isError: result.isError + isError: result.isError, + directReturn: aiChange } - + console.log('MCPToolResponse123', response) + // ipcMain.on('aiChangeEvent', (event, arg) => { + // console.log('收到渲染进程消息aiChangeEvent:', arg); + // // 处理逻辑... + // }); // Trigger event eventBus.send(MCP_EVENTS.TOOL_CALL_RESULT, SendTarget.ALL_WINDOWS, response) @@ -446,7 +459,8 @@ export class ToolManager { return { toolCallId: toolCall.id, content: `Error: Failed to execute tool '${toolCall.function.name}': ${errorMessage}`, - isError: true + isError: true, + directReturn: aiChange } } } diff --git a/src/main/presenter/threadPresenter/index.ts b/src/main/presenter/threadPresenter/index.ts index d8e377891..6048b9cdb 100644 --- a/src/main/presenter/threadPresenter/index.ts +++ b/src/main/presenter/threadPresenter/index.ts @@ -1603,30 +1603,30 @@ export class ThreadPresenter implements IThreadPresenter { // 9. 如果有工具调用结果,发送工具调用结果事件 if (toolCallResponse && toolCall) { // console.log('toolCallResponse', toolCallResponse) - eventBus.sendToRenderer(STREAM_EVENTS.RESPONSE, SendTarget.ALL_WINDOWS, { - eventId: state.message.id, - content: '', - tool_call: 'start', - tool_call_id: toolCall.id, - tool_call_name: toolCall.name, - tool_call_params: toolCall.params, - tool_call_response: toolCallResponse.content, - tool_call_server_name: toolCall.server_name, - tool_call_server_icons: toolCall.server_icons, - tool_call_server_description: toolCall.server_description - }) - eventBus.sendToRenderer(STREAM_EVENTS.RESPONSE, SendTarget.ALL_WINDOWS, { - eventId: state.message.id, - content: '', - tool_call: 'running', - tool_call_id: toolCall.id, - tool_call_name: toolCall.name, - tool_call_params: toolCall.params, - tool_call_response: toolCallResponse.content, - tool_call_server_name: toolCall.server_name, - tool_call_server_icons: toolCall.server_icons, - tool_call_server_description: toolCall.server_description - }) + // eventBus.sendToRenderer(STREAM_EVENTS.RESPONSE, SendTarget.ALL_WINDOWS, { + // eventId: state.message.id, + // content: '', + // tool_call: 'start', + // tool_call_id: toolCall.id, + // tool_call_name: toolCall.name, + // tool_call_params: toolCall.params, + // tool_call_response: toolCallResponse.content, + // tool_call_server_name: toolCall.server_name, + // tool_call_server_icons: toolCall.server_icons, + // tool_call_server_description: toolCall.server_description + // }) + // eventBus.sendToRenderer(STREAM_EVENTS.RESPONSE, SendTarget.ALL_WINDOWS, { + // eventId: state.message.id, + // content: '', + // tool_call: 'running', + // tool_call_id: toolCall.id, + // tool_call_name: toolCall.name, + // tool_call_params: toolCall.params, + // tool_call_response: toolCallResponse.content, + // tool_call_server_name: toolCall.server_name, + // tool_call_server_icons: toolCall.server_icons, + // tool_call_server_description: toolCall.server_description + // }) eventBus.sendToRenderer(STREAM_EVENTS.RESPONSE, SendTarget.ALL_WINDOWS, { eventId: state.message.id, content: '', diff --git a/src/renderer/src/components/ChatInput.vue b/src/renderer/src/components/ChatInput.vue index 7f5f28fec..ec555eabc 100644 --- a/src/renderer/src/components/ChatInput.vue +++ b/src/renderer/src/components/ChatInput.vue @@ -64,6 +64,22 @@ {{ t('chat.input.fileSelect') }} + + + + + + {{ t('chat.input.aiChange') }} + + + { fileInput.value?.click() } +//切换pinia中保存的aiChange状态 +const aiChange = () =>{ +// aiStore.toggleAiChange(); +// console.log("aiChange",aiStore.aiChange) +// console.log("aiChange",aiStore.aiChange) + + // 1. 获取当前值(转换为布尔值) + const currentValue = localStorage.getItem("aiChange"); + const isAiChange = JSON.parse(currentValue) === true; // 字符串比较 + + // 2. 切换值 + const newValue = !isAiChange; + console.log("触发了AiChange",newValue) + // 3. 保存新值 + // localStorage.setItem("aiChange", newValue); + localStorage.setItem("aiChange", JSON.stringify(newValue)); + + window.electron.ipcRenderer.send('aiChangeEvent',{ + aiChange:newValue + }) +} const previewFile = (filePath: string) => { windowPresenter.previewFile(filePath) diff --git a/src/renderer/src/components/message/MessageBlockToolCall.vue b/src/renderer/src/components/message/MessageBlockToolCall.vue index 2f71421ac..c586e9c66 100644 --- a/src/renderer/src/components/message/MessageBlockToolCall.vue +++ b/src/renderer/src/components/message/MessageBlockToolCall.vue @@ -78,22 +78,23 @@ leave-to-class="opacity-0 -translate-y-4 scale-95" >
-
+ -
+
@@ -102,7 +103,9 @@ {{ t('toolCall.responseData') }}
- + + +
@@ -115,8 +118,10 @@ import { Icon } from '@iconify/vue' import { useI18n } from 'vue-i18n' import { AssistantMessageBlock } from '@shared/chat' -import { ref } from 'vue' +import { ref, onMounted, watch } from 'vue' import { JsonObject } from '@/components/json-viewer' +import MarkdownRenderer from '@/components/markdown/MarkdownRenderer.vue' +import TurndownService from 'turndown'; // 创建一个安全的翻译函数 const t = (() => { @@ -148,6 +153,21 @@ const props = defineProps<{ const isExpanded = ref(false) +// 在组件挂载时检查direct_return属性 +onMounted(() => { + console.log("pMessageBlockToolCall-block.tool_call",props.block.tool_call?.direct_return) + if (props.block.tool_call?.direct_return === true) { + isExpanded.value = true + } +}) + +// 监听direct_return属性变化 +watch(() => props.block.tool_call?.direct_return, (newVal) => { + if (newVal === true) { + isExpanded.value = true + } +}) + const toggleExpanded = () => { isExpanded.value = !isExpanded.value } @@ -192,6 +212,49 @@ const parseJson = (jsonStr: string) => { return { raw: jsonStr } } } +//JSON转换markdown方法 +function csvToMarkdownTable(csvString: string): string { + // 按行分割,并去掉空行 + const lines = csvString + .trim() + .split(/\r?\n/) + .filter(line => line.trim()) + + if (lines.length === 0) return '' + + // 解析每行 + const rows = lines.map(line => + line + .split(',') + .map(cell => cell.trim()) // 去掉首尾空格 + ) + + // 表头 + const header = rows[0] + const separator = header.map(() => '---') // 分隔符 + + // 组合表格 + const table = [ + `| ${header.join(' | ')} |`, + `| ${separator.join(' | ')} |`, + ...rows.slice(1).map(row => `| ${row.join(' | ')} |`) + ] + + return table.join('\n') +} +// 提取Markdown内容 +const getMarkdownContent = (content: string) => { + if (!content) return '' + + try { + console.log("getMarkdownContent-content",content) + const markdownContent = csvToMarkdownTable(content); + return markdownContent + } catch (e) { + // 不是JSON格式,直接返回原始内容 + return content + } +} // const simpleIn = computed(() => { // if (!props.block.tool_call) return false diff --git a/src/renderer/src/i18n/zh-CN/chat.json b/src/renderer/src/i18n/zh-CN/chat.json index de273873b..0a0ddf578 100644 --- a/src/renderer/src/i18n/zh-CN/chat.json +++ b/src/renderer/src/i18n/zh-CN/chat.json @@ -5,6 +5,7 @@ "inputArea": "输入区域", "functionSwitch": "功能开关", "fileSelect": "选择文件", + "aiChange":"AI处理结果", "pasteFiles": "支持复制粘贴文件", "dropFiles": "拖拽文件到此处", "promptFilesAdded": "Prompt 文件已添加", diff --git a/src/renderer/src/stores/aiStore.ts b/src/renderer/src/stores/aiStore.ts new file mode 100644 index 000000000..e8a7fba93 --- /dev/null +++ b/src/renderer/src/stores/aiStore.ts @@ -0,0 +1,16 @@ +// stores/aiStore.ts +import { defineStore } from 'pinia' + +export const useAiStore = defineStore('ai', { + state: () => ({ + aiChange: false // 默认值 + }), + actions: { + toggleAiChange() { + this.aiChange = !this.aiChange + }, + setAiChange(value: boolean) { + this.aiChange = value + } + } +}) diff --git a/src/renderer/src/stores/chat.ts b/src/renderer/src/stores/chat.ts index 12e5e7a01..99a1d9271 100644 --- a/src/renderer/src/stores/chat.ts +++ b/src/renderer/src/stores/chat.ts @@ -331,6 +331,7 @@ export const useChatStore = defineStore('chat', () => { queueLength: number estimatedWaitTime?: number } + direct_return?: boolean }) => { // 从缓存中查找消息 const cached = getGeneratingMessagesCache().get(msg.eventId) @@ -465,6 +466,11 @@ export const useChatStore = defineStore('chat', () => { existingToolCallBlock.status = 'success' if (msg.tool_call_response && existingToolCallBlock.tool_call) { existingToolCallBlock.tool_call.response = msg.tool_call_response + + // 如果是直接返回的工具调用结果,添加标记 + if (msg.direct_return) { + existingToolCallBlock.tool_call.direct_return = true + } } } } diff --git a/src/renderer/src/stores/mcp.ts b/src/renderer/src/stores/mcp.ts index 2f77e6f9a..0a481be5c 100644 --- a/src/renderer/src/stores/mcp.ts +++ b/src/renderer/src/stores/mcp.ts @@ -27,6 +27,7 @@ interface MCPToolCallRequest { interface MCPToolCallResult { function_name?: string content: string | { type: string; text: string }[] + directReturn?: boolean } export const useMcpStore = defineStore('mcp', () => { @@ -497,9 +498,13 @@ export const useMcpStore = defineStore('mcp', () => { window.electron.ipcRenderer.on( MCP_EVENTS.TOOL_CALL_RESULT, (_event, result: MCPToolCallResult) => { - console.log(`MCP tool call result:`, result.function_name) + console.log(`MCP tool call result:`, result) + if (result && result.function_name) { toolResults.value[result.function_name] = result.content + const currentValue = localStorage.getItem('aiChange') as string + result.directReturn = JSON.parse(currentValue) + console.log('MCP AIChange', result.directReturn) } } ) diff --git a/src/shared/chat.d.ts b/src/shared/chat.d.ts index 7de7696dc..ccbaaaae3 100644 --- a/src/shared/chat.d.ts +++ b/src/shared/chat.d.ts @@ -125,6 +125,7 @@ export type AssistantMessageBlock = { server_name?: string server_icons?: string server_description?: string + direct_return?: boolean } action_type?: 'tool_call_permission' | 'maximum_tool_calls_reached' | 'rate_limit' image_data?: { diff --git a/src/shared/presenter.d.ts b/src/shared/presenter.d.ts index b73a94f8d..a6e120d65 100644 --- a/src/shared/presenter.d.ts +++ b/src/shared/presenter.d.ts @@ -1050,7 +1050,8 @@ export interface MCPToolResponse { /** 是否需要权限 */ requiresPermission?: boolean - + /** 是否直接返回不再继续喂回判断 */ + directReturn?: boolean | { aiChange: boolean } /** 权限请求信息 */ permissionRequest?: { toolName: string @@ -1257,6 +1258,7 @@ export interface LLMAgentEventData { tool_call_server_name?: string tool_call_server_icons?: string tool_call_server_description?: string + directReturn?: boolean | { aiChange: boolean } tool_call_response_raw?: any tool_call?: 'start' | 'running' | 'end' | 'error' | 'update' | 'permission-required' From 466045f0ebec0c82b4d38a6bcb3a8fc804ee44b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=AA=E5=B3=B0?= <2235113304@qq.com> Date: Thu, 14 Aug 2025 11:26:21 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E5=9B=BE=E6=A0=87ICON?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=8C=89=E9=92=AE=E4=B8=8D=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E6=9C=BA=E4=B8=8D=E5=90=8C=E6=A0=B7=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E5=9C=A8=E6=96=B0=E5=BB=BA=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=97=B6=E5=88=9D=E5=A7=8B=E5=8C=96=E6=9C=AC=E5=9C=B0=E5=8C=96?= =?UTF-8?q?=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/components/ChatInput.vue | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/renderer/src/components/ChatInput.vue b/src/renderer/src/components/ChatInput.vue index ec555eabc..2da2292be 100644 --- a/src/renderer/src/components/ChatInput.vue +++ b/src/renderer/src/components/ChatInput.vue @@ -70,10 +70,11 @@ {{ t('chat.input.aiChange') }} @@ -485,16 +486,15 @@ const openFilePicker = () => { } //切换pinia中保存的aiChange状态 const aiChange = () =>{ -// aiStore.toggleAiChange(); -// console.log("aiChange",aiStore.aiChange) -// console.log("aiChange",aiStore.aiChange) // 1. 获取当前值(转换为布尔值) const currentValue = localStorage.getItem("aiChange"); + console.log("currentValueORI",currentValue) const isAiChange = JSON.parse(currentValue) === true; // 字符串比较 // 2. 切换值 const newValue = !isAiChange; +aiChangeIsActive.value = !(newValue ?? true); console.log("触发了AiChange",newValue) // 3. 保存新值 // localStorage.setItem("aiChange", newValue); @@ -505,6 +505,13 @@ const aiChange = () =>{ }) } +const getInitialValue = () => { + const savedValue = localStorage.getItem('newValue'); + // 如果 localStorage 没有值,可以设置默认行为(例如默认 false) + return savedValue !== null ? !JSON.parse(savedValue) : true; +}; +const aiChangeIsActive = ref(getInitialValue()); + const previewFile = (filePath: string) => { windowPresenter.previewFile(filePath) } @@ -1035,6 +1042,12 @@ onMounted(() => { window.electron.ipcRenderer.on('rate-limit:request-queued', handleRateLimitEvent) statusInterval = window.setInterval(loadRateLimitStatus, 1000) + + window.electron.ipcRenderer.send('aiChangeEvent',{ + aiChange:false + }) + localStorage.setItem("aiChange", 'false'); + aiChangeIsActive.value = true }) onUnmounted(() => { From 3b038eb6a473c0910873413db2eb0a1aa86f9cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=AA=E5=B3=B0?= <2235113304@qq.com> Date: Fri, 15 Aug 2025 09:21:26 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=B8=8D=E5=86=8D=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=8C=81=E4=B9=85=E5=8C=96=E5=AD=98=E5=82=A8=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=83=A8=E5=88=86=E6=B3=A8=E9=87=8A=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=88=87=E6=8D=A2=E4=BA=8C=E6=AC=A1=E6=8A=95=E5=96=82?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/components/ChatInput.vue | 51 ++++++++++++----------- src/renderer/src/stores/mcp.ts | 12 +++--- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/renderer/src/components/ChatInput.vue b/src/renderer/src/components/ChatInput.vue index 2da2292be..446e70f91 100644 --- a/src/renderer/src/components/ChatInput.vue +++ b/src/renderer/src/components/ChatInput.vue @@ -64,7 +64,7 @@ {{ t('chat.input.fileSelect') }} - +