refactor: 清理渲染进程全部 58 处 console.log/warn/error
- 所有错误日志统一走 logService(logError/logWarn/logInfo) - 无 logService 的地方补上对应调用 - 纯调试 trace 直接删除(桌面应用看不到 console) - ollama.ts 流式解析错误改为静默跳过(非关键) - 执行日志面板信息量不变
This commit is contained in:
@@ -89,9 +89,7 @@ export class OllamaAPI {
|
|||||||
fetchOptions.signal = abortController.signal;
|
fetchOptions.signal = abortController.signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[OllamaAPI] chatStream 请求:', `${this.baseUrl}/api/chat`, 'messages:', params.messages.length, 'tools:', params.tools?.length || 0);
|
|
||||||
const response = await this._request('/api/chat', fetchOptions);
|
const response = await this._request('/api/chat', fetchOptions);
|
||||||
console.log('[OllamaAPI] chatStream 响应状态:', response.status);
|
|
||||||
const reader = response.body!.getReader();
|
const reader = response.body!.getReader();
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
let buffer = '';
|
let buffer = '';
|
||||||
@@ -105,7 +103,6 @@ export class OllamaAPI {
|
|||||||
while (true) {
|
while (true) {
|
||||||
const { done, value } = await reader.read();
|
const { done, value } = await reader.read();
|
||||||
if (done) {
|
if (done) {
|
||||||
console.log('[OllamaAPI] 流读取结束 (reader done)');
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,12 +116,10 @@ export class OllamaAPI {
|
|||||||
const chunk: OllamaStreamChunk = JSON.parse(line);
|
const chunk: OllamaStreamChunk = JSON.parse(line);
|
||||||
if (onChunk) onChunk(chunk);
|
if (onChunk) onChunk(chunk);
|
||||||
if (chunk.done) {
|
if (chunk.done) {
|
||||||
console.log('[OllamaAPI] 收到 done:true, eval_count:', chunk.eval_count);
|
|
||||||
reader.cancel();
|
reader.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.warn('[OllamaAPI] 流式数据解析警告:', (err as Error).message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { state, KEYS } from '../state/state.js';
|
import { state, KEYS } from '../state/state.js';
|
||||||
|
import { logError } from '../services/log-service.js';
|
||||||
import { marked } from '../utils/marked-config.js';
|
import { marked } from '../utils/marked-config.js';
|
||||||
import { escapeHtml, formatTime } from '../utils/utils.js';
|
import { escapeHtml, formatTime } from '../utils/utils.js';
|
||||||
import type { ChatSession, ChatMessage, ToolCallRecord } from '../types.js';
|
import type { ChatSession, ChatMessage, ToolCallRecord } from '../types.js';
|
||||||
@@ -396,7 +397,7 @@ async function nativeSaveFile(defaultName: string, content: string): Promise<voi
|
|||||||
if (!filePath) return;
|
if (!filePath) return;
|
||||||
const result = await bridge.fs.writeFile(filePath, content, 'utf-8');
|
const result = await bridge.fs.writeFile(filePath, content, 'utf-8');
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
console.error('[ChatArea] 导出失败:', result.error);
|
logError('导出失败', result.error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 回退
|
// 回退
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ async function handleImagePaths(paths: string[]): Promise<void> {
|
|||||||
pendingImages.push({ name, base64 });
|
pendingImages.push({ name, base64 });
|
||||||
logInfo(`图片已添加: ${name}`, formatSize(binary.length));
|
logInfo(`图片已添加: ${name}`, formatSize(binary.length));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[InputArea] 图片读取失败:', err);
|
logError('图片读取失败', (err as Error).message);
|
||||||
appendSystemMessage(`❌ 读取 ${name} 失败`);
|
appendSystemMessage(`❌ 读取 ${name} 失败`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@ async function handleTextFilePaths(paths: string[]): Promise<void> {
|
|||||||
logInfo(`文件已添加: ${name}`, formatSize(size));
|
logInfo(`文件已添加: ${name}`, formatSize(size));
|
||||||
renderFilePreviews();
|
renderFilePreviews();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[InputArea] 文件读取失败:', err);
|
logError('文件读取失败', (err as Error).message);
|
||||||
appendSystemMessage(`❌ 读取 ${name} 失败`);
|
appendSystemMessage(`❌ 读取 ${name} 失败`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,7 +445,7 @@ export async function sendMessage(): Promise<void> {
|
|||||||
appendSystemMessage('🧠 知识库未检索到相关内容,使用通用知识回答', 'rag-status');
|
appendSystemMessage('🧠 知识库未检索到相关内容,使用通用知识回答', 'rag-status');
|
||||||
}
|
}
|
||||||
} catch (ragErr) {
|
} catch (ragErr) {
|
||||||
console.error('[RAG] 检索失败:', ragErr);
|
logError('RAG 检索失败', (ragErr as Error).message);
|
||||||
appendSystemMessage(`🧠 知识库检索失败: ${(ragErr as Error).message}`, 'rag-status');
|
appendSystemMessage(`🧠 知识库检索失败: ${(ragErr as Error).message}`, 'rag-status');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,9 +520,9 @@ export async function sendMessage(): Promise<void> {
|
|||||||
currentSession2.title
|
currentSession2.title
|
||||||
).then(count => {
|
).then(count => {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
console.log(`[Memory] 自动提取了 ${count} 条记忆`);
|
logInfo(`自动提取了 ${count} 条记忆`);
|
||||||
}
|
}
|
||||||
}).catch(err => console.warn('[Memory] 提取失败:', err));
|
}).catch(err => logError('记忆提取失败', (err as Error).message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -728,7 +728,6 @@ async function sendMessageWithAgentLoop(text: string, currentSession: ChatSessio
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[AgentLoop] 错误:', err);
|
|
||||||
logError('Agent Loop 错误', (err as Error).message);
|
logError('Agent Loop 错误', (err as Error).message);
|
||||||
|
|
||||||
if ((err as Error).name === 'AbortError') {
|
if ((err as Error).name === 'AbortError') {
|
||||||
@@ -793,6 +792,6 @@ async function saveCurrentSession(): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
await db.saveSession(currentSession);
|
await db.saveSession(currentSession);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[InputArea] 保存会话失败:', err);
|
logError('保存会话失败', (err as Error).message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { formatSize, escapeHtml, truncate } from '../utils/utils.js';
|
|||||||
import { showToast } from './toast.js';
|
import { showToast } from './toast.js';
|
||||||
import { showConfirm } from './prompt-modal.js';
|
import { showConfirm } from './prompt-modal.js';
|
||||||
import { OllamaAPI } from '../api/ollama.js';
|
import { OllamaAPI } from '../api/ollama.js';
|
||||||
import { logRAG, logError } from '../services/log-service.js';
|
import { logRAG, logError, logWarn } from '../services/log-service.js';
|
||||||
import type { VectorCollection, SearchResult } from '../types.js';
|
import type { VectorCollection, SearchResult } from '../types.js';
|
||||||
|
|
||||||
let kbModalEl: HTMLElement;
|
let kbModalEl: HTMLElement;
|
||||||
@@ -85,7 +85,7 @@ export async function performRagRetrieval(query: string): Promise<{ context: str
|
|||||||
if (!context) return null;
|
if (!context) return null;
|
||||||
return { context, results, ragPrompt: buildRagSystemPrompt(context) };
|
return { context, results, ragPrompt: buildRagSystemPrompt(context) };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('[KB] RAG 检索失败:', err);
|
logWarn('RAG 检索失败', (err as Error).message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,10 +267,8 @@ async function handleDocUpload(paths: string[]): Promise<void> {
|
|||||||
logRAG(`文档上传: ${name}`, `${kbResult.chunkCount} 个分块`);
|
logRAG(`文档上传: ${name}`, `${kbResult.chunkCount} 个分块`);
|
||||||
successCount++;
|
successCount++;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[KB] 文档处理失败:', err);
|
logError(`RAG 文档处理失败: ${name}`, (err as Error).message);
|
||||||
const fileName = filePath.split(/[/\\]/).pop() || filePath;
|
showToast(`${name} 处理失败: ${(err as Error).message}`, 'error');
|
||||||
showToast(`${fileName} 处理失败: ${(err as Error).message}`, 'error');
|
|
||||||
logError(`RAG 文档处理失败: ${fileName}`, (err as Error).message);
|
|
||||||
failCount++;
|
failCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,6 +320,6 @@ async function populateEmbedModels(): Promise<void> {
|
|||||||
select.innerHTML = '<option value="">未检测到嵌入模型,请先 ollama pull</option>';
|
select.innerHTML = '<option value="">未检测到嵌入模型,请先 ollama pull</option>';
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('[KB] 加载模型列表失败:', err);
|
logWarn('加载嵌入模型列表失败', (err as Error).message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ export async function loadModels(): Promise<void> {
|
|||||||
|
|
||||||
filterEmbedModels(data.models);
|
filterEmbedModels(data.models);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[ModelBar] 加载模型失败:', err);
|
|
||||||
logError('加载模型列表失败', (err as Error).message);
|
logError('加载模型列表失败', (err as Error).message);
|
||||||
modelSelectEl.innerHTML = '<option value="">加载失败 - 检查连接</option>';
|
modelSelectEl.innerHTML = '<option value="">加载失败 - 检查连接</option>';
|
||||||
badgeThinkEl.style.display = 'none'; badgeVisionEl.style.display = 'none';
|
badgeThinkEl.style.display = 'none'; badgeVisionEl.style.display = 'none';
|
||||||
@@ -169,7 +168,6 @@ async function checkModelCapability(modelName: string): Promise<void> {
|
|||||||
logDebug(`能力检测: ${modelName}`, capabilities.join(', '));
|
logDebug(`能力检测: ${modelName}`, capabilities.join(', '));
|
||||||
applyCapability(modelName, caps);
|
applyCapability(modelName, caps);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('[ModelBar] 获取模型能力失败:', err);
|
|
||||||
logWarn(`能力检测失败: ${modelName}`, (err as Error).message);
|
logWarn(`能力检测失败: ${modelName}`, (err as Error).message);
|
||||||
const fallback = { think: false, vision: false, tools: false, completion: true };
|
const fallback = { think: false, vision: false, tools: false, completion: true };
|
||||||
modelCapabilityCache.set(modelName, fallback);
|
modelCapabilityCache.set(modelName, fallback);
|
||||||
|
|||||||
@@ -232,7 +232,6 @@ async function exportAllSessions(): Promise<void> {
|
|||||||
showToast(`已导出 ${sessions.length} 个会话(已加密)`, 'success');
|
showToast(`已导出 ${sessions.length} 个会话(已加密)`, 'success');
|
||||||
logSuccess(`导出完成: ${sessions.length} 个会话`);
|
logSuccess(`导出完成: ${sessions.length} 个会话`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Settings] 导出失败:', err);
|
|
||||||
showToast(`导出失败: ${(err as Error).message}`, 'error');
|
showToast(`导出失败: ${(err as Error).message}`, 'error');
|
||||||
logError('导出失败', (err as Error).message);
|
logError('导出失败', (err as Error).message);
|
||||||
}
|
}
|
||||||
@@ -276,7 +275,6 @@ async function importSessions(filePath: string): Promise<void> {
|
|||||||
showToast(`导入完成:${result.imported} 个会话${result.skipped > 0 ? `,跳过 ${result.skipped} 个` : ''}`, 'success', 4000);
|
showToast(`导入完成:${result.imported} 个会话${result.skipped > 0 ? `,跳过 ${result.skipped} 个` : ''}`, 'success', 4000);
|
||||||
logSuccess(`导入完成: ${result.imported} 个, 跳过 ${result.skipped} 个`);
|
logSuccess(`导入完成: ${result.imported} 个, 跳过 ${result.skipped} 个`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Settings] 导入失败:', err);
|
|
||||||
showToast(`导入失败: ${(err as Error).message}`, 'error');
|
showToast(`导入失败: ${(err as Error).message}`, 'error');
|
||||||
logError('导入失败', (err as Error).message);
|
logError('导入失败', (err as Error).message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,10 @@ export class ChatDB {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const request = indexedDB.open(this.dbName, this.version);
|
const request = indexedDB.open(this.dbName, this.version);
|
||||||
request.onerror = () => {
|
request.onerror = () => {
|
||||||
console.error('[ChatDB] 数据库打开失败:', request.error);
|
|
||||||
reject(request.error);
|
reject(request.error);
|
||||||
};
|
};
|
||||||
request.onsuccess = () => {
|
request.onsuccess = () => {
|
||||||
this.db = request.result;
|
this.db = request.result;
|
||||||
console.log('[ChatDB] 数据库已连接');
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
request.onupgradeneeded = (event) => {
|
request.onupgradeneeded = (event) => {
|
||||||
|
|||||||
+4
-11
@@ -26,7 +26,7 @@ import { setToolEnabled } from './services/tool-registry.js';
|
|||||||
import { initToolConfirmModal } from './components/tool-confirm-modal.js';
|
import { initToolConfirmModal } from './components/tool-confirm-modal.js';
|
||||||
import { initMemoryPanel } from './components/memory-panel.js';
|
import { initMemoryPanel } from './components/memory-panel.js';
|
||||||
import { initLogPanel } from './services/log-service.js';
|
import { initLogPanel } from './services/log-service.js';
|
||||||
import { logInfo, logSuccess, logError, logDebug, logInit } from './services/log-service.js';
|
import { logInfo, logSuccess, logError, logDebug, logInit, logWarn } from './services/log-service.js';
|
||||||
import type { ChatSession } from './types.js';
|
import type { ChatSession } from './types.js';
|
||||||
|
|
||||||
function initHelpModal(): void {
|
function initHelpModal(): void {
|
||||||
@@ -51,8 +51,6 @@ function setupDesktopIntegration(): void {
|
|||||||
|
|
||||||
logInit('桌面集成...');
|
logInit('桌面集成...');
|
||||||
|
|
||||||
console.log('[Desktop Integration] 初始化桌面集成...');
|
|
||||||
|
|
||||||
bridge.onMenuAction((action: string) => {
|
bridge.onMenuAction((action: string) => {
|
||||||
logInfo(`菜单操作: ${action}`);
|
logInfo(`菜单操作: ${action}`);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
@@ -87,12 +85,9 @@ function setupDesktopIntegration(): void {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('[Desktop Integration] 桌面集成完成 ✓');
|
|
||||||
logSuccess('桌面集成完成');
|
logSuccess('桌面集成完成');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[Metona] TypeScript + Electron v3.0.0 ' + new Date().toISOString());
|
|
||||||
|
|
||||||
function createNewSession(): ChatSession {
|
function createNewSession(): ChatSession {
|
||||||
const selectedModel = (document.querySelector('#modelSelect') as HTMLSelectElement)?.value || '';
|
const selectedModel = (document.querySelector('#modelSelect') as HTMLSelectElement)?.value || '';
|
||||||
const defaultModel = selectedModel || state.get<string>('_defaultModel', '');
|
const defaultModel = selectedModel || state.get<string>('_defaultModel', '');
|
||||||
@@ -121,7 +116,7 @@ async function startNewSession(): Promise<void> {
|
|||||||
await api.chat({ model, messages: [], keep_alive: 0 } as any);
|
await api.chat({ model, messages: [], keep_alive: 0 } as any);
|
||||||
logDebug('释放旧模型显存');
|
logDebug('释放旧模型显存');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('[App] 释放显存失败:', e);
|
logWarn('释放显存失败', (e as Error).message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,10 +243,8 @@ async function init(): Promise<void> {
|
|||||||
|
|
||||||
(document.querySelector('#chatInput') as HTMLElement)?.focus();
|
(document.querySelector('#chatInput') as HTMLElement)?.focus();
|
||||||
|
|
||||||
console.log('[App] 初始化完成');
|
|
||||||
logSuccess('应用初始化完成');
|
logSuccess('应用初始化完成');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[App] 初始化失败:', err);
|
|
||||||
logError('初始化失败', (err as Error).message);
|
logError('初始化失败', (err as Error).message);
|
||||||
if (!api!) {
|
if (!api!) {
|
||||||
api = new OllamaAPI();
|
api = new OllamaAPI();
|
||||||
@@ -290,12 +283,12 @@ function bindGlobalEvents(): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('error', (e) => {
|
window.addEventListener('error', (e) => {
|
||||||
console.error('[App] 未捕获错误:', e.error || e.message);
|
logError('未捕获错误', (e.error as Error)?.message || e.message);
|
||||||
showToast(`发生错误: ${e.message}`, 'error', 5000);
|
showToast(`发生错误: ${e.message}`, 'error', 5000);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('unhandledrejection', (e) => {
|
window.addEventListener('unhandledrejection', (e) => {
|
||||||
console.error('[App] 未处理 Promise 拒绝:', e.reason);
|
logError('未处理 Promise 拒绝', (e.reason as Error)?.message || String(e.reason));
|
||||||
const msg = e.reason?.message || String(e.reason);
|
const msg = e.reason?.message || String(e.reason);
|
||||||
showToast(`操作失败: ${msg}`, 'error', 5000);
|
showToast(`操作失败: ${msg}`, 'error', 5000);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ export async function runAgentLoop(
|
|||||||
// 检查模型是否支持 Tool Calling
|
// 检查模型是否支持 Tool Calling
|
||||||
const modelSupportsTools = state.get<boolean>('modelSupportsTools', false);
|
const modelSupportsTools = state.get<boolean>('modelSupportsTools', false);
|
||||||
if (!modelSupportsTools) {
|
if (!modelSupportsTools) {
|
||||||
console.warn(`[AgentEngine] 模型 ${model} 未声明 tools 能力,Agent Loop 可能不稳定`);
|
|
||||||
logWarn(`模型 ${model} 不支持 Tool Calling`, 'Agent Loop 可能不稳定');
|
logWarn(`模型 ${model} 不支持 Tool Calling`, 'Agent Loop 可能不稳定');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +107,6 @@ export async function runAgentLoop(
|
|||||||
|
|
||||||
// 全局超时检查
|
// 全局超时检查
|
||||||
if (Date.now() - loopStartTime > MAX_LOOP_TIME) {
|
if (Date.now() - loopStartTime > MAX_LOOP_TIME) {
|
||||||
console.warn('[AgentEngine] 达到最大运行时间(5分钟),自动停止');
|
|
||||||
logWarn('Agent Loop 达到最大运行时间(5分钟),自动停止');
|
logWarn('Agent Loop 达到最大运行时间(5分钟),自动停止');
|
||||||
callbacks.onDone(content || '(达到最大运行时间限制)', allToolRecords);
|
callbacks.onDone(content || '(达到最大运行时间限制)', allToolRecords);
|
||||||
return;
|
return;
|
||||||
@@ -122,7 +120,6 @@ export async function runAgentLoop(
|
|||||||
}
|
}
|
||||||
|
|
||||||
logAgentLoop(loopCount, MAX_LOOPS);
|
logAgentLoop(loopCount, MAX_LOOPS);
|
||||||
console.log(`[AgentEngine] ===== Loop #${loopCount} 开始, messages: ${messages.length}, tools: ${useTools} =====`);
|
|
||||||
|
|
||||||
let thinking = '';
|
let thinking = '';
|
||||||
content = '';
|
content = '';
|
||||||
@@ -133,7 +130,6 @@ export async function runAgentLoop(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 带超时保护的流式调用
|
// 带超时保护的流式调用
|
||||||
console.log('[AgentEngine] 开始流式调用, model:', model, 'think:', state.get<boolean>('thinkEnabled', false));
|
|
||||||
await Promise.race([
|
await Promise.race([
|
||||||
api.chatStream(
|
api.chatStream(
|
||||||
{
|
{
|
||||||
@@ -188,7 +184,6 @@ export async function runAgentLoop(
|
|||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[AgentEngine] 流式调用错误:', (err as Error).message, 'aborted:', abortController.signal.aborted);
|
|
||||||
if (abortController.signal.aborted) {
|
if (abortController.signal.aborted) {
|
||||||
logInfo('流式调用已中止');
|
logInfo('流式调用已中止');
|
||||||
if (content || thinking) {
|
if (content || thinking) {
|
||||||
@@ -203,7 +198,6 @@ export async function runAgentLoop(
|
|||||||
}
|
}
|
||||||
// 超时错误 — 保留已生成的内容
|
// 超时错误 — 保留已生成的内容
|
||||||
if ((err as Error).message.includes('超时')) {
|
if ((err as Error).message.includes('超时')) {
|
||||||
console.warn('[AgentEngine] 流式调用超时:', (err as Error).message);
|
|
||||||
logError('流式调用超时(2分钟无数据)', (err as Error).message);
|
logError('流式调用超时(2分钟无数据)', (err as Error).message);
|
||||||
if (content || thinking) {
|
if (content || thinking) {
|
||||||
messages.push({
|
messages.push({
|
||||||
@@ -231,7 +225,6 @@ export async function runAgentLoop(
|
|||||||
messages.push(assistantMsg);
|
messages.push(assistantMsg);
|
||||||
|
|
||||||
logModelResponse(content.length, toolCalls.length);
|
logModelResponse(content.length, toolCalls.length);
|
||||||
console.log('[AgentEngine] 流式完成, toolCalls:', toolCalls.length, 'content:', content.length);
|
|
||||||
|
|
||||||
if (toolCalls.length === 0) {
|
if (toolCalls.length === 0) {
|
||||||
logInfo('无工具调用,Agent Loop 结束');
|
logInfo('无工具调用,Agent Loop 结束');
|
||||||
@@ -239,27 +232,20 @@ export async function runAgentLoop(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[AgentEngine] 开始处理工具调用:', toolCalls.map(c => c.function.name));
|
|
||||||
|
|
||||||
for (const call of toolCalls) {
|
for (const call of toolCalls) {
|
||||||
// 检查是否已中止
|
// 检查是否已中止
|
||||||
if (abortController.signal.aborted) {
|
if (abortController.signal.aborted) {
|
||||||
console.log('[AgentEngine] Abort 信号已设置,退出');
|
|
||||||
callbacks.onDone(content, allToolRecords.length > 0 ? allToolRecords : undefined);
|
callbacks.onDone(content, allToolRecords.length > 0 ? allToolRecords : undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks.onToolCallStart(call);
|
callbacks.onToolCallStart(call);
|
||||||
logToolStart(call.function.name, JSON.stringify(call.function.arguments));
|
logToolStart(call.function.name, JSON.stringify(call.function.arguments));
|
||||||
console.log('[AgentEngine] 工具调用:', call.function.name, call.function.arguments);
|
|
||||||
|
|
||||||
if (needsConfirmation(call.function.name)) {
|
if (needsConfirmation(call.function.name)) {
|
||||||
console.log('[AgentEngine] 需要确认,弹出确认框:', call.function.name);
|
|
||||||
const confirmed = await callbacks.onConfirmTool(call);
|
const confirmed = await callbacks.onConfirmTool(call);
|
||||||
console.log('[AgentEngine] 用户确认结果:', confirmed, 'abort:', abortController.signal.aborted);
|
|
||||||
// 确认后再次检查是否已中止
|
// 确认后再次检查是否已中止
|
||||||
if (abortController.signal.aborted) {
|
if (abortController.signal.aborted) {
|
||||||
console.log('[AgentEngine] 确认后 Abort 信号已设置,退出');
|
|
||||||
callbacks.onDone(content, allToolRecords.length > 0 ? allToolRecords : undefined);
|
callbacks.onDone(content, allToolRecords.length > 0 ? allToolRecords : undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -286,16 +272,11 @@ export async function runAgentLoop(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 工具执行超时保护
|
// 工具执行超时保护
|
||||||
console.log('[AgentEngine] 执行工具:', call.function.name);
|
|
||||||
logInfo(`执行工具: ${call.function.name}`, JSON.stringify(call.function.arguments));
|
logInfo(`执行工具: ${call.function.name}`, JSON.stringify(call.function.arguments));
|
||||||
const result = await Promise.race([
|
const result = await Promise.race([
|
||||||
executeTool(call.function.name, call.function.arguments).then(r => {
|
executeTool(call.function.name, call.function.arguments).catch(err =>
|
||||||
console.log('[AgentEngine] executeTool resolve:', call.function.name, r);
|
({ success: false, error: err?.message || String(err) }) as ToolResult
|
||||||
return r;
|
),
|
||||||
}).catch(err => {
|
|
||||||
console.error('[AgentEngine] executeTool reject:', call.function.name, err);
|
|
||||||
return { success: false, error: err?.message || String(err) } as ToolResult;
|
|
||||||
}),
|
|
||||||
new Promise<ToolResult>((_, reject) =>
|
new Promise<ToolResult>((_, reject) =>
|
||||||
setTimeout(() => reject(new Error('工具执行超时(30秒)')), TOOL_EXEC_TIMEOUT)
|
setTimeout(() => reject(new Error('工具执行超时(30秒)')), TOOL_EXEC_TIMEOUT)
|
||||||
)
|
)
|
||||||
@@ -309,18 +290,15 @@ export async function runAgentLoop(
|
|||||||
};
|
};
|
||||||
allToolRecords.push(record);
|
allToolRecords.push(record);
|
||||||
|
|
||||||
console.log('[AgentEngine] 工具结果:', call.function.name, result.success, result);
|
|
||||||
messages.push({
|
messages.push({
|
||||||
role: 'tool',
|
role: 'tool',
|
||||||
tool_name: call.function.name,
|
tool_name: call.function.name,
|
||||||
content: JSON.stringify(result)
|
content: JSON.stringify(result)
|
||||||
});
|
});
|
||||||
console.log('[AgentEngine] 当前 messages 数量:', messages.length);
|
|
||||||
callbacks.onToolCallResult(call.function.name, result, call);
|
callbacks.onToolCallResult(call.function.name, result, call);
|
||||||
logToolResult(call.function.name, result.success, result.success ? undefined : result.error);
|
logToolResult(call.function.name, result.success, result.success ? undefined : result.error);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const errorMsg = (err as Error).message;
|
const errorMsg = (err as Error).message;
|
||||||
console.error(`[AgentEngine] 工具执行失败 (${call.function.name}):`, errorMsg);
|
|
||||||
logError(`工具执行失败: ${call.function.name}`, errorMsg);
|
logError(`工具执行失败: ${call.function.name}`, errorMsg);
|
||||||
const record: ToolCallRecord = {
|
const record: ToolCallRecord = {
|
||||||
name: call.function.name,
|
name: call.function.name,
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ export async function initMemoryManager(): Promise<void> {
|
|||||||
memoryCache = await db.getAllMemories();
|
memoryCache = await db.getAllMemories();
|
||||||
state.set('memoryEntries', memoryCache);
|
state.set('memoryEntries', memoryCache);
|
||||||
|
|
||||||
console.log(`[Memory] 初始化完成,加载 ${memoryCache.length} 条记忆`);
|
|
||||||
logMemory(`初始化完成, 加载 ${memoryCache.length} 条`);
|
logMemory(`初始化完成, 加载 ${memoryCache.length} 条`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +322,6 @@ ${conversationText.slice(0, 4000)}
|
|||||||
if (count > 0) logMemory(`自动提取 ${count} 条`);
|
if (count > 0) logMemory(`自动提取 ${count} 条`);
|
||||||
return count;
|
return count;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('[Memory] 自动提取失败:', err);
|
|
||||||
logWarn('记忆自动提取失败', (err as Error).message);
|
logWarn('记忆自动提取失败', (err as Error).message);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ToolDefinition, ToolResult } from '../types.js';
|
import type { ToolDefinition, ToolResult } from '../types.js';
|
||||||
import { logToolResult, logError } from './log-service.js';
|
import { logToolStart, logToolResult, logError } from './log-service.js';
|
||||||
|
|
||||||
export const TOOL_DEFINITIONS: ToolDefinition[] = [
|
export const TOOL_DEFINITIONS: ToolDefinition[] = [
|
||||||
{
|
{
|
||||||
@@ -159,7 +159,7 @@ export async function executeTool(toolName: string, args: Record<string, unknown
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[ToolRegistry] 开始执行:', toolName, args);
|
logToolStart(toolName, JSON.stringify(args));
|
||||||
// IPC 调用 + 25 秒硬超时(比 agent-engine 的 30 秒先触发)
|
// IPC 调用 + 25 秒硬超时(比 agent-engine 的 30 秒先触发)
|
||||||
const result = await Promise.race([
|
const result = await Promise.race([
|
||||||
bridge.tool.execute(toolName, args),
|
bridge.tool.execute(toolName, args),
|
||||||
@@ -167,11 +167,10 @@ export async function executeTool(toolName: string, args: Record<string, unknown
|
|||||||
setTimeout(() => reject(new Error(`工具 ${toolName} IPC 超时(25秒)`)), 25000)
|
setTimeout(() => reject(new Error(`工具 ${toolName} IPC 超时(25秒)`)), 25000)
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
console.log('[ToolRegistry] 执行完成:', toolName, result);
|
logToolResult(toolName, result.success, result.success ? undefined : result.error);
|
||||||
return result;
|
return result;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logError(`工具异常: ${toolName}`, (err as Error).message);
|
logError(`工具异常: ${toolName}`, (err as Error).message);
|
||||||
console.error('[ToolRegistry] 执行异常:', toolName, err);
|
|
||||||
return { success: false, error: (err as Error).message };
|
return { success: false, error: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,6 @@ export class VectorStore {
|
|||||||
return saved;
|
return saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[VectorStore] 构建 IVF 索引: ${colId} (${vectors.length} 向量)`);
|
|
||||||
const index = this._buildIVFIndex(vectors);
|
const index = this._buildIVFIndex(vectors);
|
||||||
index.collectionId = colId;
|
index.collectionId = colId;
|
||||||
index.version = this._indexVersion(vectors);
|
index.version = this._indexVersion(vectors);
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class AppState {
|
|||||||
}
|
}
|
||||||
const old = this._state[key];
|
const old = this._state[key];
|
||||||
if (old == null || typeof old !== 'object') {
|
if (old == null || typeof old !== 'object') {
|
||||||
console.warn(`[State] setIn 失败: ${key} 不是对象`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newRoot = Array.isArray(old) ? [...(old as unknown[])] : { ...(old as Record<string, unknown>) };
|
const newRoot = Array.isArray(old) ? [...(old as unknown[])] : { ...(old as Record<string, unknown>) };
|
||||||
@@ -111,7 +110,6 @@ class AppState {
|
|||||||
if (!this._listeners.has(key)) return;
|
if (!this._listeners.has(key)) return;
|
||||||
for (const cb of this._listeners.get(key)!) {
|
for (const cb of this._listeners.get(key)!) {
|
||||||
try { cb(value, old); } catch (e) {
|
try { cb(value, old); } catch (e) {
|
||||||
console.error(`[State] 监听器错误 (${key}):`, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ export function sanitize(html: string): string {
|
|||||||
|
|
||||||
return root.innerHTML;
|
return root.innerHTML;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('[Sanitizer] 净化失败:', e);
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user