feat: 添加对话压缩功能和上下文使用情况显示
- 新增 context 模块实现 Prune 和 Compaction 压缩策略 - Prune: 将旧工具调用结果替换为占位符 - Compaction: 使用 AI 生成对话摘要 - CLI 提示符显示上下文使用量 [used/available] - 添加 /compact 命令手动压缩对话 - 添加 /context 命令查看上下文详情 - Agent 集成自动压缩 (85%阈值) 和强制压缩功能
This commit is contained in:
+61
-1
@@ -12,6 +12,11 @@ import type { Tool, ToolResult, Message, AgentConfig, ProviderType } from '../ty
|
||||
import { buildZodSchema } from '../types/index.js';
|
||||
import { ToolRegistry } from '../tools/registry.js';
|
||||
import { SessionManager } from '../session/index.js';
|
||||
import {
|
||||
CompressionManager,
|
||||
type TokenUsage,
|
||||
type CompressionConfig,
|
||||
} from '../context/index.js';
|
||||
|
||||
// Provider 工厂函数类型
|
||||
type ProviderFactory = (apiKey: string) => (model: string) => LanguageModel;
|
||||
@@ -45,7 +50,10 @@ export class Agent {
|
||||
// 会话管理器(可选)
|
||||
private sessionManager: SessionManager | null = null;
|
||||
|
||||
constructor(config: AgentConfig) {
|
||||
// 压缩管理器
|
||||
private compressionManager: CompressionManager;
|
||||
|
||||
constructor(config: AgentConfig, compressionConfig?: Partial<CompressionConfig>) {
|
||||
this.config = config;
|
||||
|
||||
const providerFactory = providers[config.provider];
|
||||
@@ -53,6 +61,11 @@ export class Agent {
|
||||
throw new Error(`不支持的 provider: ${config.provider}`);
|
||||
}
|
||||
this.getModel = providerFactory(config.apiKey);
|
||||
|
||||
// 初始化压缩管理器
|
||||
this.compressionManager = new CompressionManager(compressionConfig);
|
||||
// 设置模型用于生成摘要
|
||||
this.compressionManager.setModel(this.getModel(config.model));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,6 +243,17 @@ export class Agent {
|
||||
// 将完整的响应消息添加到历史(包括工具调用和结果)
|
||||
this.conversationHistory.push(...responseMessages);
|
||||
|
||||
// 检查是否需要自动压缩
|
||||
if (this.compressionManager.shouldCompress(this.conversationHistory)) {
|
||||
const result = await this.compressionManager.compress(this.conversationHistory);
|
||||
if (result.freedTokens > 0) {
|
||||
this.conversationHistory = result.messages;
|
||||
if (onStream) {
|
||||
onStream(`\n[自动压缩: 释放了 ${(result.freedTokens / 1000).toFixed(1)}k tokens]\n`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 持久化会话
|
||||
await this.persistSession();
|
||||
|
||||
@@ -294,4 +318,40 @@ export class Agent {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前上下文使用情况
|
||||
*/
|
||||
getContextUsage(): TokenUsage {
|
||||
return this.compressionManager.calculateUsage(this.conversationHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取格式化的上下文使用情况(用于 CLI 显示)
|
||||
*/
|
||||
getContextUsageFormatted(): string {
|
||||
return this.compressionManager.formatUsage(this.conversationHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取压缩管理器
|
||||
*/
|
||||
getCompressionManager(): CompressionManager {
|
||||
return this.compressionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动压缩对话历史(用于 /compact 命令)
|
||||
*/
|
||||
async compactHistory(): Promise<{ freedTokens: number; type: string }> {
|
||||
const result = await this.compressionManager.forceCompress(this.conversationHistory);
|
||||
if (result.freedTokens > 0) {
|
||||
this.conversationHistory = result.messages;
|
||||
await this.persistSession();
|
||||
}
|
||||
return {
|
||||
freedTokens: result.freedTokens,
|
||||
type: result.type,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user