From 34a6b9fd0b5280680133e3a8c818dd5e741a7745 Mon Sep 17 00:00:00 2001 From: thzxx Date: Tue, 7 Apr 2026 19:49:30 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=B8=85=E9=99=A4=E6=89=80=E6=9C=89?= =?UTF-8?q?=20console.log=EF=BC=8C=E4=B8=BB=E8=BF=9B=E7=A8=8B=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=8E=A5=E5=85=A5=E6=89=A7=E8=A1=8C=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/ipc.ts | 13 +++++++++---- src/main/preload.ts | 3 +++ src/main/workspace.ts | 8 +++++++- src/renderer/main.ts | 7 ++++++- src/renderer/types.d.ts | 1 + 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 0ecca14..5dfe504 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -7,6 +7,11 @@ import * as fs from 'fs'; import * as path from 'path'; import { mainWindow } from './main.js'; import { showNotification } from './utils.js'; + +/** 发送日志到渲染进程日志面板 */ +function sendLog(level: 'info' | 'success' | 'warn' | 'error' | 'debug', message: string, detail?: string): void { + mainWindow?.webContents.send('main:log', { level, message, detail }); +} import { handleReadFile, handleWriteFile, @@ -84,7 +89,7 @@ export function setupIPC(): void { // ── Tool Calling IPC ── ipcMain.handle('tool:execute', async (_, toolName: string, args: Record) => { try { - console.log('[IPC] tool:execute', toolName, JSON.stringify(args || {}).slice(0, 200)); + sendLog('debug', `🔧 tool:execute ${toolName}`, JSON.stringify(args || {}).slice(0, 200)); switch (toolName) { case 'read_file': return await handleReadFile(args as { path: string; encoding?: string; start_line?: number; end_line?: number }); case 'write_file': return await handleWriteFile(args as { path: string; content: string; encoding?: string }); @@ -96,7 +101,7 @@ export function setupIPC(): void { default: return { success: false, error: `未知工具: ${toolName}` }; } } catch (err) { - console.error('[IPC] tool:execute 异常:', toolName, err); + sendLog('error', `❌ tool:execute 异常: ${toolName}`, String(err)); return { success: false, error: (err as Error).message || '工具执行异常' }; } }); @@ -139,7 +144,7 @@ export function setupIPC(): void { // 启动命令(流式输出,通过 workspace:output 事件推送) ipcMain.on('workspace:exec', (event, { id, command, cwd }: { id: string; command: string; cwd?: string }) => { - console.log('[IPC] workspace:exec', id, command.slice(0, 200)); + sendLog('info', `🖥️ workspace:exec`, `ID: ${id} | ${command.slice(0, 200)}`); const result = startProcess( id, @@ -163,7 +168,7 @@ export function setupIPC(): void { // 停止命令 ipcMain.on('workspace:kill', (_, id: string) => { - console.log('[IPC] workspace:kill', id); + sendLog('info', `🖥️ workspace:kill`, `ID: ${id}`); killProcess(id); }); } diff --git a/src/main/preload.ts b/src/main/preload.ts index a6fd1a1..317e082 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -39,6 +39,9 @@ contextBridge.exposeInMainWorld('metonaDesktop', { removeAllListeners: (channel: string) => { ipcRenderer.removeAllListeners(channel); }, + onMainLog: (callback: (data: { level: string; message: string; detail?: string }) => void) => { + ipcRenderer.on('main:log', (_: unknown, data: { level: string; message: string; detail?: string }) => callback(data)); + }, workspace: { getDir: () => ipcRenderer.invoke('workspace:getDir'), setDir: (dir: string) => ipcRenderer.invoke('workspace:setDir', dir), diff --git a/src/main/workspace.ts b/src/main/workspace.ts index 6639d5d..e8974c6 100644 --- a/src/main/workspace.ts +++ b/src/main/workspace.ts @@ -7,8 +7,14 @@ import { spawn, ChildProcess } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; import { app } from 'electron'; +import { mainWindow } from './main.js'; import { checkPathAllowed, checkCommandAllowed } from './tool-security.js'; +/** 发送日志到渲染进程日志面板 */ +function sendLog(level: 'info' | 'success' | 'warn' | 'error' | 'debug', message: string, detail?: string): void { + mainWindow?.webContents.send('main:log', { level, message, detail }); +} + export const DEFAULT_WORKSPACE_DIR = path.join(app.getPath('userData'), 'workspace'); /** 活跃进程 Map */ @@ -18,7 +24,7 @@ const activeProcesses = new Map(); export function ensureWorkspaceDir(): void { if (!fs.existsSync(DEFAULT_WORKSPACE_DIR)) { fs.mkdirSync(DEFAULT_WORKSPACE_DIR, { recursive: true }); - console.log('[Workspace] 创建默认工作空间目录:', DEFAULT_WORKSPACE_DIR); + sendLog('info', `📁 创建默认工作空间目录`, DEFAULT_WORKSPACE_DIR); } } diff --git a/src/renderer/main.ts b/src/renderer/main.ts index 7a627fd..580e2a3 100644 --- a/src/renderer/main.ts +++ b/src/renderer/main.ts @@ -26,7 +26,7 @@ import { setToolEnabled } from './services/tool-registry.js'; import { initToolConfirmModal } from './components/tool-confirm-modal.js'; import { initMemoryPanel } from './components/memory-panel.js'; import { initWorkspacePanel } from './components/workspace-panel.js'; -import { initLogPanel } from './services/log-service.js'; +import { initLogPanel, addLog } from './services/log-service.js'; import { logInfo, logSuccess, logError, logDebug, logInit, logWarn } from './services/log-service.js'; import type { ChatSession } from './types.js'; @@ -78,6 +78,11 @@ function setupDesktopIntegration(): void { } }) as EventListener); + // 主进程日志转发到日志面板 + bridge.onMainLog((data: { level: string; message: string; detail?: string }) => { + addLog(data.level as any, data.message, data.detail); + }); + // 退出时释放显存 bridge.onAppQuit(() => { const api = state.get(KEYS.API); diff --git a/src/renderer/types.d.ts b/src/renderer/types.d.ts index 1fd7ab5..5eaee97 100644 --- a/src/renderer/types.d.ts +++ b/src/renderer/types.d.ts @@ -229,6 +229,7 @@ export interface MetonaDesktopAPI { onTrayAction: (callback: (action: string) => void) => void; onAppQuit: (callback: () => void) => void; removeAllListeners: (channel: string) => void; + onMainLog: (callback: (data: { level: string; message: string; detail?: string }) => void) => void; workspace: { getDir: () => Promise<{ dir: string; defaultDir: string }>; setDir: (dir: string) => Promise<{ success: boolean; dir?: string; error?: string }>;