import type { CompressionStrategy, CompressionDecision, CompressionContext } from './compression-strategy'; import type { Message } from '@agforge/core'; /** * 阈值压缩策略配置选项。 */ export type ThresholdCompressionStrategyOptions = { /** * 异步压缩阈值(0-1)。 * 当 context 使用率超过此阈值时触发异步压缩。 * @default 0.5 */ asyncThreshold?: number; /** * 同步压缩阈值(0-1)。 * 当 context 使用率超过此阈值时触发同步压缩。 * 必须大于 asyncThreshold。 * @default 0.7 */ syncThreshold?: number; /** * 压缩目标比例(0-1)。 * 压缩后的 token 数量占 maxContextTokens 的比例。 * @default 0.3 */ targetRatio?: number; /** * 保留最近的完整对话轮数。 * * 一轮完整对话定义为:从一个 user 消息开始,到下一个 user 消息之前的所有消息。 * 例如:user → assistant(tool_calls) → tool1 → tool2 → assistant 为一轮完整对话。 * * 设为 0 表示不保留任何消息(全部压缩)。 * @default 5 */ keepRecentRounds?: number; /** * 是否保留第一条系统消息。 * @default true */ preserveFirstSystem?: boolean; /** * 最小可压缩消息数量。 * 如果待压缩的消息少于此数量,则跳过压缩。 * @default 4 */ minCompressableMessages?: number; /** * Token 估算函数。 * 用于估算消息列表的 token 数量。 * @default 简单的字符数估算(每 4 个字符约等于 1 个 token) */ estimateTokens?: (messages: ReadonlyArray) => number; }; /** * 基于阈值的压缩策略。 * * 职责: * 1. 根据 context window 使用率决定压缩模式(none/async/sync) * 2. 分离消息:哪些需要压缩,哪些保留 * 3. 设定压缩目标 token 数量 * * 消息分区逻辑: * - 保留第一条系统消息(可配置) * - 保留最近 N 轮对话(可配置) * - 其余消息作为待压缩部分 */ export declare class ThresholdCompressionStrategy implements CompressionStrategy { private readonly asyncThreshold; private readonly syncThreshold; private readonly targetRatio; private readonly keepRecentRounds; private readonly preserveFirstSystem; private readonly minCompressableMessages; private readonly estimateTokens; constructor(options?: ThresholdCompressionStrategyOptions); shouldCompress(context: CompressionContext): CompressionDecision; /** * 创建不压缩的决策。 * 所有消息都保留,不压缩。 */ private createNoCompressionDecision; /** * 分离消息:哪些需要压缩,哪些保留。 * * 分区逻辑: * 1. 提取第一条系统消息(如果配置了 preserveFirstSystem) * 2. 从后向前找到最近 N 轮完整对话的边界 * 3. 边界之前的消息作为待压缩部分,边界之后的作为保留部分 * * 完整对话轮次定义: * - 从一个 user 消息开始 * - 到下一个 user 消息之前结束(不含下一个 user) * - 例如:user → assistant(tool_calls) → tool1 → tool2 → assistant 为一轮 */ private splitMessages; /** * 从后向前找到 N 轮完整对话的起始边界索引。 * * @param messages - 对话消息列表(不含系统消息) * @param rounds - 要保留的轮数 * @returns 边界索引(该索引之前的消息将被压缩,该索引及之后的消息将被保留) */ private findRoundBoundary; }