diff --git a/server/routes/agent-chat.js b/server/routes/agent-chat.js index 2ae7298..22e4a74 100644 --- a/server/routes/agent-chat.js +++ b/server/routes/agent-chat.js @@ -238,6 +238,26 @@ function loadFile(agentDir, filename) { // ═══════════════════════════════════════ const BASE_DIR = path.join(__dirname, '../../packages/agent-core/base'); +// ── 启动时预加载 common + type 基类文件到内存(几乎不变的文件,避免每次请求读盘) ── +const _baseFileCache = new Map(); +function _loadBaseFile(filepath) { + if (_baseFileCache.has(filepath)) return _baseFileCache.get(filepath); + try { + const content = fs.readFileSync(filepath, 'utf-8').trim(); + _baseFileCache.set(filepath, content); + return content; + } catch { return ''; } +} +// 预热 common 文件 +['methodology.md', 'tools-base.md', 'capabilities.md'].forEach(f => { + _loadBaseFile(path.join(BASE_DIR, 'common', f)); +}); +// 预热 type 基类 +['master', 'cxo', 'skill', 'orchestrator', 'worker'].forEach(t => { + _loadBaseFile(path.join(BASE_DIR, t, 'agent-base.md')); + _loadBaseFile(path.join(BASE_DIR, t, 'cron-base.json')); +}); + /** * 构建 system prompt — 三层继承 * @@ -282,18 +302,14 @@ function buildSystemPrompt(agentDir, userMessage) { const commonFiles = ['methodology.md', 'tools-base.md', 'capabilities.md']; for (const f of commonFiles) { const fp = path.join(BASE_DIR, 'common', f); - if (fs.existsSync(fp)) { - const content = fs.readFileSync(fp, 'utf-8').trim(); - if (content) parts.push(content); - } + const content = _loadBaseFile(fp); + if (content) parts.push(content); } // ── Layer 2: 类型基类 ── const typeBaseAgent = path.join(BASE_DIR, agentType, 'agent-base.md'); - if (fs.existsSync(typeBaseAgent)) { - const content = fs.readFileSync(typeBaseAgent, 'utf-8').trim(); - if (content) parts.push(content); - } + const typeContent = _loadBaseFile(typeBaseAgent); + if (typeContent) parts.push(typeContent); // ── Layer 3: Agent 专属文件 ── const agentListText = Object.entries(fullSystemConfig.agents || {}) @@ -399,12 +415,13 @@ function buildCronInstructions(agentDir) { // Layer 1: 基类 cron const baseCronPath = path.join(BASE_DIR, agentType, 'cron-base.json'); - if (fs.existsSync(baseCronPath)) { + const baseCronContent = _loadBaseFile(baseCronPath); + if (baseCronContent) { try { - const base = JSON.parse(fs.readFileSync(baseCronPath, 'utf-8')); + const base = JSON.parse(baseCronContent); allCrons = allCrons.concat(base); } catch (err) { - console.error(`[Cron] ⚠️ 读取 ${baseCronPath} 失败:`, err.message); + console.error(`[Cron] ⚠️ 解析 ${baseCronPath} 失败:`, err.message); } } diff --git a/server/routes/tasks.js b/server/routes/tasks.js index 6c7161d..c89ca37 100644 --- a/server/routes/tasks.js +++ b/server/routes/tasks.js @@ -4,9 +4,18 @@ const { TaskService } = require('../services/task-service'); const taskService = new TaskService(); +// ── Task List 缓存 (10秒 TTL) ── +let _taskListCache = null; +let _taskListCacheTime = 0; +const TASK_LIST_CACHE_TTL = 10000; + // GET /api/tasks — 扫描获取系统中聚合的 Task 列表(含父子关系) router.get('/', (req, res) => { try { + if (_taskListCache && Date.now() - _taskListCacheTime < TASK_LIST_CACHE_TTL) { + return res.json(_taskListCache); + } + const tasks = taskService.getAggregatedTasks(); const taskList = tasks.map(t => ({ @@ -24,6 +33,9 @@ router.get('/', (req, res) => { conversationCount: t.conversations.length, })); + _taskListCache = taskList; + _taskListCacheTime = Date.now(); + res.json(taskList); } catch (err) { res.status(500).json({ error: err.message }); diff --git a/server/services/task-service.js b/server/services/task-service.js index 32b2f9a..e7bc46e 100644 --- a/server/services/task-service.js +++ b/server/services/task-service.js @@ -290,7 +290,19 @@ class TaskService { if (fs.existsSync(logPath)) { try { - const logContent = fs.readFileSync(logPath, 'utf-8'); + // 限制最大读取 512KB,超出则只读尾部 + const MAX_LOG_READ = 512 * 1024; + const stat = fs.statSync(logPath); + let logContent; + if (stat.size > MAX_LOG_READ) { + const fd = fs.openSync(logPath, 'r'); + const buf = Buffer.alloc(MAX_LOG_READ); + fs.readSync(fd, buf, 0, MAX_LOG_READ, stat.size - MAX_LOG_READ); + fs.closeSync(fd); + logContent = buf.toString('utf-8'); + } else { + logContent = fs.readFileSync(logPath, 'utf-8'); + } const blocks = this._parseMessagesLog(logContent, conv); timeline.push(...blocks); } catch (e) {