From 9ed48379509cec85959c1bc49ba9083e7494e3b4 Mon Sep 17 00:00:00 2001 From: thzxx Date: Tue, 7 Jul 2026 21:22:24 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=B8=8A=E4=B8=8B=E6=96=87=E5=8E=8B?= =?UTF-8?q?=E7=BC=A9=E9=98=88=E5=80=BC=E4=B8=8E=E6=91=98=E8=A6=81=E6=88=AA?= =?UTF-8?q?=E6=96=AD=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. engine: 压缩阈值改用 contextLength ?? contextWindow, Ollama 小 numCtx 时正确触发压缩 2. main: reloadAdapter 在 provider 切换时同步 contextLength, 非 Ollama 清除避免残留 3. engine: compressMessages 移除每条消息 500 字符截断, 摘要请求是独立 API 调用无需截断 4. delegate-task: 修复 items 缺少 description 的 TS2741 预存错误 --- electron/harness/agent-loop/engine.ts | 8 +++++--- electron/harness/tools/built-in/delegate-task.ts | 2 +- electron/main.ts | 8 ++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/electron/harness/agent-loop/engine.ts b/electron/harness/agent-loop/engine.ts index d98d721..2e0f356 100644 --- a/electron/harness/agent-loop/engine.ts +++ b/electron/harness/agent-loop/engine.ts @@ -400,8 +400,10 @@ export class AgentLoopEngine extends EventEmitter { await this.transitionTo(AgentLoopState.OBSERVING); // === 上下文压缩(基于 token 使用率触发) === + // 有效上下文窗口:Ollama 使用 contextLength (numCtx),其他 Provider 使用 contextWindow + const effectiveContextWindow = this.config.contextLength ?? this.config.contextWindow; const estimatedTokens = this.estimateMessagesTokens(request.messages); - const compressionThreshold = this.config.compressionThreshold * this.config.contextWindow; + const compressionThreshold = this.config.compressionThreshold * effectiveContextWindow; if (estimatedTokens > compressionThreshold && request.messages.length > 10) { await this.transitionTo(AgentLoopState.COMPRESSING); const compressed = await this.compressMessages(request.messages); @@ -537,10 +539,10 @@ export class AgentLoopEngine extends EventEmitter { const toKeep = messages.slice(messages.length - keepRecent); // 构建摘要请求 + // 不截断单条消息——摘要请求是独立 API 调用,不共享主对话上下文窗口 const conversationText = toCompress.map((m) => { const role = m.role.toUpperCase(); - const content = m.content.slice(0, 500); // 每条消息最多 500 字符 - return `[${role}] ${content}`; + return `[${role}] ${m.content}`; }).join('\n\n'); const summaryRequest: MetonaRequest = { diff --git a/electron/harness/tools/built-in/delegate-task.ts b/electron/harness/tools/built-in/delegate-task.ts index 078371c..6303bb5 100644 --- a/electron/harness/tools/built-in/delegate-task.ts +++ b/electron/harness/tools/built-in/delegate-task.ts @@ -25,7 +25,7 @@ export class DelegateTaskTool implements IMetonaTool { }, tools: { type: 'array', - items: { type: 'string' }, + items: { type: 'string', description: 'Tool name' }, description: 'Optional whitelist of tool names the SubAgent can use (e.g. ["read_file", "web_search"]). If omitted, SubAgent inherits all tools.', }, maxIterations: { diff --git a/electron/main.ts b/electron/main.ts index 8547402..5788589 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -232,6 +232,14 @@ async function initialize(): Promise { const reloadAdapter = () => { const newAdapter = createAdapter(); agentLoop.setAdapter(newAdapter); + // Provider 切换时同步 contextLength:仅 Ollama 使用 numCtx 作为有效上下文窗口 + const provider = configService.get('llm.provider') ?? ''; + if (provider === 'ollama') { + const numCtx = configService.get('ollama.numCtx'); + agentLoop.updateConfig({ contextLength: numCtx ?? undefined }); + } else { + agentLoop.updateConfig({ contextLength: undefined }); + } }; // ===== 窗口管理 =====