fix: 补充执行日志 + 清理死代码
日志补充: - browser.ts: 全部 8 个函数新增 sendLog (打开/截图/JS/提取/点击/输入/滚动/关闭) - mcp-manager.ts: callTool 新增工具调用日志 死代码清理: - skill-manager.ts: 删除 getAllSkillsForUI, deleteSkillById, clearAllSkills (39 行) - memory-manager.ts: 删除 getVectorSearchResults (4 行) - mcp-manager.ts: 删除 isServerRunning
This commit is contained in:
+31
-17
@@ -4,7 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { BrowserWindow } from 'electron';
|
import { BrowserWindow } from 'electron';
|
||||||
import * as path from 'path';
|
import { mainWindow } from './main.js';
|
||||||
|
|
||||||
|
function sendLog(level: 'info' | 'success' | 'warn' | 'error', message: string, detail?: string): void {
|
||||||
|
mainWindow?.webContents.send('main:log', { level, message, detail });
|
||||||
|
}
|
||||||
|
|
||||||
let agentBrowser: BrowserWindow | null = null;
|
let agentBrowser: BrowserWindow | null = null;
|
||||||
|
|
||||||
@@ -15,12 +19,12 @@ function getAgentBrowser(): BrowserWindow {
|
|||||||
agentBrowser = new BrowserWindow({
|
agentBrowser = new BrowserWindow({
|
||||||
width: 1280,
|
width: 1280,
|
||||||
height: 800,
|
height: 800,
|
||||||
show: false, // 隐藏窗口
|
show: false,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
sandbox: true,
|
sandbox: true,
|
||||||
webSecurity: false, // 允许跨域(Agent 需要)
|
webSecurity: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -32,14 +36,14 @@ function getAgentBrowser(): BrowserWindow {
|
|||||||
export async function browserOpen(url: string): Promise<{ success: boolean; title?: string; url?: string; error?: string }> {
|
export async function browserOpen(url: string): Promise<{ success: boolean; title?: string; url?: string; error?: string }> {
|
||||||
try {
|
try {
|
||||||
const win = getAgentBrowser();
|
const win = getAgentBrowser();
|
||||||
|
sendLog('info', `🌐 browser 打开`, url.slice(0, 100));
|
||||||
await win.loadURL(url);
|
await win.loadURL(url);
|
||||||
await new Promise(r => setTimeout(r, 1000)); // 等待页面渲染
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
return {
|
const title = win.webContents.getTitle();
|
||||||
success: true,
|
sendLog('success', `🌐 browser 已加载`, title);
|
||||||
title: win.webContents.getTitle(),
|
return { success: true, title, url: win.webContents.getURL() };
|
||||||
url: win.webContents.getURL()
|
|
||||||
};
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🌐 browser 打开失败`, (err as Error).message);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,8 +57,10 @@ export async function browserScreenshot(): Promise<{ success: boolean; png?: str
|
|||||||
}
|
}
|
||||||
const image = await win.webContents.capturePage();
|
const image = await win.webContents.capturePage();
|
||||||
const buffer = image.toPNG();
|
const buffer = image.toPNG();
|
||||||
|
sendLog('info', `🌐 browser 截图`, `${buffer.length} bytes`);
|
||||||
return { success: true, png: buffer.toString('base64') };
|
return { success: true, png: buffer.toString('base64') };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🌐 browser 截图失败`, (err as Error).message);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,12 +72,13 @@ export async function browserEvaluate(js: string): Promise<{ success: boolean; r
|
|||||||
if (win.webContents.getURL() === 'about:blank') {
|
if (win.webContents.getURL() === 'about:blank') {
|
||||||
return { success: false, error: '浏览器未加载任何页面' };
|
return { success: false, error: '浏览器未加载任何页面' };
|
||||||
}
|
}
|
||||||
|
sendLog('info', `🌐 browser 执行 JS`, js.slice(0, 100));
|
||||||
const result = await win.webContents.executeJavaScript(js, true);
|
const result = await win.webContents.executeJavaScript(js, true);
|
||||||
return {
|
const resultStr = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
||||||
success: true,
|
sendLog('success', `🌐 browser JS 完成`, resultStr?.slice(0, 100));
|
||||||
result: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
|
return { success: true, result: resultStr };
|
||||||
};
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🌐 browser JS 失败`, (err as Error).message);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,7 +94,6 @@ export async function browserExtract(): Promise<{ success: boolean; title?: stri
|
|||||||
const result = await win.webContents.executeJavaScript(`
|
const result = await win.webContents.executeJavaScript(`
|
||||||
(() => {
|
(() => {
|
||||||
const title = document.title;
|
const title = document.title;
|
||||||
// 提取正文文本
|
|
||||||
const getText = (el) => {
|
const getText = (el) => {
|
||||||
if (!el) return '';
|
if (!el) return '';
|
||||||
const clone = el.cloneNode(true);
|
const clone = el.cloneNode(true);
|
||||||
@@ -96,8 +102,6 @@ export async function browserExtract(): Promise<{ success: boolean; title?: stri
|
|||||||
};
|
};
|
||||||
const body = getText(document.body);
|
const body = getText(document.body);
|
||||||
const text = body.length > 15000 ? body.slice(0, 15000) + '\\n... (已截断)' : body;
|
const text = body.length > 15000 ? body.slice(0, 15000) + '\\n... (已截断)' : body;
|
||||||
|
|
||||||
// 提取链接
|
|
||||||
const links = [];
|
const links = [];
|
||||||
document.querySelectorAll('a[href]').forEach(a => {
|
document.querySelectorAll('a[href]').forEach(a => {
|
||||||
const href = a.href;
|
const href = a.href;
|
||||||
@@ -106,13 +110,14 @@ export async function browserExtract(): Promise<{ success: boolean; title?: stri
|
|||||||
links.push({ text: text.slice(0, 100), href });
|
links.push({ text: text.slice(0, 100), href });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { title, text, links: links.slice(0, 50) };
|
return { title, text, links: links.slice(0, 50) };
|
||||||
})()
|
})()
|
||||||
`, true);
|
`, true);
|
||||||
|
|
||||||
|
sendLog('success', `🌐 browser 提取完成`, `标题: ${result.title}, 文本: ${result.text?.length || 0}字, 链接: ${result.links?.length || 0}个`);
|
||||||
return { success: true, ...result };
|
return { success: true, ...result };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🌐 browser 提取失败`, (err as Error).message);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,10 +126,13 @@ export async function browserExtract(): Promise<{ success: boolean; title?: stri
|
|||||||
export async function browserClick(selector: string): Promise<{ success: boolean; error?: string }> {
|
export async function browserClick(selector: string): Promise<{ success: boolean; error?: string }> {
|
||||||
try {
|
try {
|
||||||
const win = getAgentBrowser();
|
const win = getAgentBrowser();
|
||||||
|
sendLog('info', `🌐 browser 点击`, selector);
|
||||||
await win.webContents.executeJavaScript(`document.querySelector('${selector.replace(/'/g, "\\'")}').click()`, true);
|
await win.webContents.executeJavaScript(`document.querySelector('${selector.replace(/'/g, "\\'")}').click()`, true);
|
||||||
await new Promise(r => setTimeout(r, 500));
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
sendLog('success', `🌐 browser 点击完成`, selector);
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🌐 browser 点击失败`, `${selector}: ${(err as Error).message}`);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,6 +143,7 @@ export async function browserType(selector: string, text: string): Promise<{ suc
|
|||||||
const win = getAgentBrowser();
|
const win = getAgentBrowser();
|
||||||
const escapedSelector = selector.replace(/'/g, "\\'");
|
const escapedSelector = selector.replace(/'/g, "\\'");
|
||||||
const escapedText = text.replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
const escapedText = text.replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
||||||
|
sendLog('info', `🌐 browser 输入`, `${selector}: ${text.slice(0, 50)}`);
|
||||||
await win.webContents.executeJavaScript(`
|
await win.webContents.executeJavaScript(`
|
||||||
(() => {
|
(() => {
|
||||||
const el = document.querySelector('${escapedSelector}');
|
const el = document.querySelector('${escapedSelector}');
|
||||||
@@ -145,8 +154,10 @@ export async function browserType(selector: string, text: string): Promise<{ suc
|
|||||||
el.dispatchEvent(new Event('change', { bubbles: true }));
|
el.dispatchEvent(new Event('change', { bubbles: true }));
|
||||||
})()
|
})()
|
||||||
`, true);
|
`, true);
|
||||||
|
sendLog('success', `🌐 browser 输入完成`, selector);
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🌐 browser 输入失败`, `${selector}: ${(err as Error).message}`);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,8 +172,10 @@ export async function browserScroll(direction: 'down' | 'up' | 'top' | 'bottom')
|
|||||||
: 'window.scrollTo(0, document.body.scrollHeight)';
|
: 'window.scrollTo(0, document.body.scrollHeight)';
|
||||||
await win.webContents.executeJavaScript(js, true);
|
await win.webContents.executeJavaScript(js, true);
|
||||||
await new Promise(r => setTimeout(r, 300));
|
await new Promise(r => setTimeout(r, 300));
|
||||||
|
sendLog('info', `🌐 browser 滚动`, direction);
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🌐 browser 滚动失败`, (err as Error).message);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,6 +184,7 @@ export async function browserScroll(direction: 'down' | 'up' | 'top' | 'bottom')
|
|||||||
export function browserClose(): void {
|
export function browserClose(): void {
|
||||||
if (agentBrowser && !agentBrowser.isDestroyed()) {
|
if (agentBrowser && !agentBrowser.isDestroyed()) {
|
||||||
agentBrowser.close();
|
agentBrowser.close();
|
||||||
|
sendLog('info', '🌐 browser 已关闭');
|
||||||
}
|
}
|
||||||
agentBrowser = null;
|
agentBrowser = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,10 +240,14 @@ export async function callTool(serverName: string, toolName: string, args: Recor
|
|||||||
return { success: false, error: `MCP 服务器 ${serverName} 未运行` };
|
return { success: false, error: `MCP 服务器 ${serverName} 未运行` };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendLog('info', `🔌 MCP 调用工具`, `${serverName}/${toolName} ${JSON.stringify(args || {}).slice(0, 100)}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await sendRequest(server, 'tools/call', { name: toolName, arguments: args });
|
const result = await sendRequest(server, 'tools/call', { name: toolName, arguments: args });
|
||||||
|
sendLog('success', `🔌 MCP 工具完成`, `${serverName}/${toolName}`);
|
||||||
return { success: true, result };
|
return { success: true, result };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
sendLog('error', `🔌 MCP 工具失败`, `${serverName}/${toolName}: ${(err as Error).message}`);
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,8 +293,3 @@ export function getServerStatuses(): Array<{ name: string; running: boolean; too
|
|||||||
return statuses;
|
return statuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 检查服务器是否在运行 */
|
|
||||||
export function isServerRunning(name: string): boolean {
|
|
||||||
const server = servers.get(name);
|
|
||||||
return !!server && server.initialized;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -170,10 +170,6 @@ function triggerVectorSearch(query: string, limit: number): void {
|
|||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出:获取向量搜索结果(供 UI 使用)
|
|
||||||
export function getVectorSearchResults(query: string): MemorySearchResult[] {
|
|
||||||
return vectorSearchCache.get(query) || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关键词搜索
|
// 关键词搜索
|
||||||
function searchMemoriesByKeyword(query: string, limit: number): MemorySearchResult[] {
|
function searchMemoriesByKeyword(query: string, limit: number): MemorySearchResult[] {
|
||||||
|
|||||||
@@ -182,45 +182,6 @@ export function buildSkillContext(skills: Skill[]): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有技能(用于 UI 展示)
|
|
||||||
*/
|
|
||||||
export async function getAllSkillsForUI(): Promise<Skill[]> {
|
|
||||||
const bridge = (window as any).metonaDesktop;
|
|
||||||
if (!bridge?.db?.getAllSkills) return [];
|
|
||||||
try {
|
|
||||||
return await bridge.db.getAllSkills();
|
|
||||||
} catch {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除技能
|
|
||||||
*/
|
|
||||||
export async function deleteSkillById(id: string): Promise<boolean> {
|
|
||||||
const bridge = (window as any).metonaDesktop;
|
|
||||||
if (!bridge?.db?.deleteSkill) return false;
|
|
||||||
try {
|
|
||||||
await bridge.db.deleteSkill(id);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空所有技能
|
|
||||||
*/
|
|
||||||
export async function clearAllSkills(): Promise<boolean> {
|
|
||||||
const bridge = (window as any).metonaDesktop;
|
|
||||||
if (!bridge?.db?.clearAllSkills) return false;
|
|
||||||
try {
|
|
||||||
await bridge.db.clearAllSkills();
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── 辅助函数 ──
|
// ── 辅助函数 ──
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user