fix: 上下文压缩阈值与摘要截断修复
1. engine: 压缩阈值改用 contextLength ?? contextWindow, Ollama 小 numCtx 时正确触发压缩 2. main: reloadAdapter 在 provider 切换时同步 contextLength, 非 Ollama 清除避免残留 3. engine: compressMessages 移除每条消息 500 字符截断, 摘要请求是独立 API 调用无需截断 4. delegate-task: 修复 items 缺少 description 的 TS2741 预存错误
This commit is contained in:
@@ -400,8 +400,10 @@ export class AgentLoopEngine extends EventEmitter {
|
|||||||
await this.transitionTo(AgentLoopState.OBSERVING);
|
await this.transitionTo(AgentLoopState.OBSERVING);
|
||||||
|
|
||||||
// === 上下文压缩(基于 token 使用率触发) ===
|
// === 上下文压缩(基于 token 使用率触发) ===
|
||||||
|
// 有效上下文窗口:Ollama 使用 contextLength (numCtx),其他 Provider 使用 contextWindow
|
||||||
|
const effectiveContextWindow = this.config.contextLength ?? this.config.contextWindow;
|
||||||
const estimatedTokens = this.estimateMessagesTokens(request.messages);
|
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) {
|
if (estimatedTokens > compressionThreshold && request.messages.length > 10) {
|
||||||
await this.transitionTo(AgentLoopState.COMPRESSING);
|
await this.transitionTo(AgentLoopState.COMPRESSING);
|
||||||
const compressed = await this.compressMessages(request.messages);
|
const compressed = await this.compressMessages(request.messages);
|
||||||
@@ -537,10 +539,10 @@ export class AgentLoopEngine extends EventEmitter {
|
|||||||
const toKeep = messages.slice(messages.length - keepRecent);
|
const toKeep = messages.slice(messages.length - keepRecent);
|
||||||
|
|
||||||
// 构建摘要请求
|
// 构建摘要请求
|
||||||
|
// 不截断单条消息——摘要请求是独立 API 调用,不共享主对话上下文窗口
|
||||||
const conversationText = toCompress.map((m) => {
|
const conversationText = toCompress.map((m) => {
|
||||||
const role = m.role.toUpperCase();
|
const role = m.role.toUpperCase();
|
||||||
const content = m.content.slice(0, 500); // 每条消息最多 500 字符
|
return `[${role}] ${m.content}`;
|
||||||
return `[${role}] ${content}`;
|
|
||||||
}).join('\n\n');
|
}).join('\n\n');
|
||||||
|
|
||||||
const summaryRequest: MetonaRequest = {
|
const summaryRequest: MetonaRequest = {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class DelegateTaskTool implements IMetonaTool {
|
|||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
type: 'array',
|
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.',
|
description: 'Optional whitelist of tool names the SubAgent can use (e.g. ["read_file", "web_search"]). If omitted, SubAgent inherits all tools.',
|
||||||
},
|
},
|
||||||
maxIterations: {
|
maxIterations: {
|
||||||
|
|||||||
@@ -232,6 +232,14 @@ async function initialize(): Promise<void> {
|
|||||||
const reloadAdapter = () => {
|
const reloadAdapter = () => {
|
||||||
const newAdapter = createAdapter();
|
const newAdapter = createAdapter();
|
||||||
agentLoop.setAdapter(newAdapter);
|
agentLoop.setAdapter(newAdapter);
|
||||||
|
// Provider 切换时同步 contextLength:仅 Ollama 使用 numCtx 作为有效上下文窗口
|
||||||
|
const provider = configService.get<string>('llm.provider') ?? '';
|
||||||
|
if (provider === 'ollama') {
|
||||||
|
const numCtx = configService.get<number>('ollama.numCtx');
|
||||||
|
agentLoop.updateConfig({ contextLength: numCtx ?? undefined });
|
||||||
|
} else {
|
||||||
|
agentLoop.updateConfig({ contextLength: undefined });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===== 窗口管理 =====
|
// ===== 窗口管理 =====
|
||||||
|
|||||||
Reference in New Issue
Block a user