autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
156 lines (155 loc) • 5.63 kB
TypeScript
/**
* ContextWindow — Agent 的上下文窗口管理器
*
* 业界最佳实践:
* - OpenAI Compaction: 阈值触发自动压缩,保留关键上下文
* - LangChain trim_messages: 按 token 裁剪,保证消息合法性
* - Anthropic 长上下文: 长文档前置,查询后置
* - Gemini API: functionResponse 必须紧跟 functionCall
*
* 设计不变量:
* 1. messages[0] 始终是原始 user prompt(不可删除)
* 2. assistant(toolCalls) 与其 tool results 是原子单元(不可拆分)
* 3. 每次 AI 调用前自动压缩到 TOKEN_BUDGET 以内
* 4. 不通过追加 user 消息来控制 AI 行为(由 ExplorationTracker 管理)
*
* 三级递进压缩:
* L1 (60-80%): 截断旧的 tool results 内容
* L2 (80-95%): 摘要历史轮次,保留最后 2 轮完整链
* L3 (>95%): 仅保留 prompt + 最后 1 轮 + 已提交列表
*
* @module ContextWindow
*/
/** 工具调用信息 */
interface ToolCallInfo {
id: string;
name: string;
args?: Record<string, unknown>;
}
/** 上下文窗口中的消息 */
export interface ContextMessage {
role: 'user' | 'assistant' | 'tool';
content?: string | null;
toolCalls?: ToolCallInfo[];
toolCallId?: string;
name?: string;
}
/** 工具结果配额 */
interface ToolResultQuota {
maxChars?: number;
maxMatches?: number;
}
/**
* 一组相关消息的原子单元:
* - assistant(toolCalls) + 所有后续 tool results
* - 或单独的 user/assistant 文本消息
*/
export declare class ContextWindow {
#private;
/**
* 模型名 → 上下文窗口大小映射(token 数)。
* 键为正则模式,按优先级从上到下匹配。
* 值为模型的原始上下文窗口上限。
*/
static MODEL_CONTEXT_WINDOWS: (number | RegExp)[][];
/**
* 根据模型名称解析合适的 ContextWindow token 预算。
*
* 策略: 取模型最大上下文窗口的一个安全分片,
* - 超大窗口 (≥400k): 预算 48000(1M 级模型可容纳更多上下文)
* - 大窗口 (≥200k): 预算 32000(tool schemas + system prompt 占显著空间)
* - 中窗口 (≥64k): 预算 24000
* - 小窗口 (≥16k): 预算 12000
* - 微窗口 (<16k): 预算 = 窗口 × 0.7(留 30% 给 prompt/tool schema)
*
* @param modelName 模型名称,如 'gemini-3-flash-preview', 'gpt-5.4-mini'
* @param [opts] - isSystem 为 true 时给予更高预算
* @returns 建议的 token 预算
*/
static resolveTokenBudget(modelName: string, opts?: {
isSystem?: boolean;
}): number;
/** @param [tokenBudget=24000] token 预算上限 */
constructor(tokenBudget?: number);
/** 追加用户消息 */
appendUserMessage(content: string): void;
/**
* 追加阶段过渡引导消息 — 轻量级 user 消息,用于在 ExplorationTracker 阶段转换时
* 向 AI 明确传达新阶段的行为期望。与 appendUserMessage 功能相同,
* 独立命名以便审计和搜索。
*/
appendUserNudge(content: string): void;
/**
* 追加 assistant 消息(含工具调用)
* @param text assistant 文本
* @param toolCalls [{id, name, args}]
*/
appendAssistantWithToolCalls(text: string | null, toolCalls: ToolCallInfo[]): void;
/**
* 追加工具结果(必须紧跟 assistant toolCalls 后)
* @param name 工具名
* @param content 工具返回内容(已经过 ToolResultLimiter 截断)
*/
appendToolResult(toolCallId: string, name: string, content: string): void;
/** 追加 assistant 纯文本消息(无工具调用) */
appendAssistantText(text: string): void;
/**
* 在每次 AI 调用前调用 — 根据 token 使用率执行分级压缩
*
* @returns } 压缩结果
*/
compactIfNeeded(): {
level: number;
removed: number;
};
/** 导出消息(供 AI Provider 使用) */
toMessages(): ContextMessage[];
/** 获取消息数量 */
get length(): number;
/** 获取 token 预算 */
get tokenBudget(): number;
/** 估算当前 token 使用量 */
estimateTokens(): number;
/** 获取 token 使用率 (0-1) */
getTokenUsageRatio(): number;
/**
* 获取动态工具结果配额
* 根据当前 token 使用率返回工具结果的大小限制
* @returns }
*/
getToolResultQuota(): {
maxChars: number;
maxMatches: number;
};
/** 获取压缩日志(用于调试) */
getCompactionLog(): string[];
/** 获取被压缩掉的已提交候选标题 */
getCompactedSubmits(): Set<unknown>;
/**
* 清空消息 — 仅保留首条 prompt
* 用于致命错误后的恢复
*/
resetToPromptOnly(): void;
/**
* Pipeline 阶段隔离 — 清空全部消息。
*
* 用于 PipelineStrategy 在阶段间重置 ContextWindow:
* analyze → (reset) → produce
*
* reactLoop 会将新阶段的 prompt 追加为 messages[0],
* systemPrompt 通过 chatWithTools 参数独立传递,不受影响。
*
* 保留 compactedSubmits 以支持跨阶段提交去重。
*/
resetForNewStage(): void;
}
/**
* 工具结果入口限制器 — 在工具结果进入 ContextWindow 前压缩
*
* @param toolName 工具名
* @param result 工具原始返回
* @param quota 动态配额
* @returns 压缩后的结果字符串
*/
export declare function limitToolResult(toolName: string, result: unknown, quota: ToolResultQuota): string;
export {};