feat: /compress 上下文压缩 + Skill 渐进式加载

This commit is contained in:
Metona Dev
2026-04-24 12:35:49 +08:00
parent fe85251738
commit 8e53a411d6
5 changed files with 220 additions and 43 deletions
+17 -1
View File
@@ -17,7 +17,7 @@ import { showToast } from '../components/toast.js';
import { logInfo, logWarn, logError, logToolStart, logToolResult, logAgentLoop, logModelResponse } from './log-service.js';
import { getWorkspaceDirPath } from '../components/workspace-panel.js';
import { generateId } from '../utils/utils.js';
import { buildContext, estimateTokens } from './context-manager.js';
import { buildContext, estimateTokens, shouldAutoCompress, compressWithLLM, AUTO_COMPRESS_THRESHOLD } from './context-manager.js';
import type {
OllamaMessage,
OllamaStreamChunk,
@@ -497,6 +497,22 @@ export async function runAgentLoop(
messages.length = 0;
messages.push(...contextResult);
// 自动压缩:当上下文 token 超过 context window 的 50% 时,调用 LLM 摘要压缩
if (shouldAutoCompress(messages, numCtx)) {
logInfo(`自动上下文压缩触发: tokens≈${estimateTokens(messages.map(m => m.content || '').join(''))} > ${Math.floor(numCtx * AUTO_COMPRESS_THRESHOLD)} (50% of ${numCtx})`);
try {
const compressed = await compressWithLLM(messages, api, model, { abortController });
if (compressed.length < messages.length || estimateTokens(compressed.map(m => m.content || '').join('')) < estimateTokens(messages.map(m => m.content || '').join(''))) {
messages.length = 0;
messages.push(...compressed);
logSuccess(`自动上下文压缩完成: 剩余 ${messages.length} 条消息`);
}
} catch (err) {
if ((err as Error).name === 'AbortError') throw err;
logWarn('自动上下文压缩失败,继续使用当前上下文', (err as Error).message);
}
}
logInfo(`ReAct Agent Loop 启动: ${model}`, `工具: ${useTools ? '开启' : '关闭'}, 记忆: ${isMemoryEnabled() ? '开启' : '关闭'}, tokens≈${estimateTokens(messages.map(m => m.content || '').join(''))}`);
// 迭代预算:从 state 读取,默认 85