feat(agent): opt-in tool-result context pruning

This commit is contained in:
Max Sumrall
2026-01-07 12:02:46 +01:00
committed by Peter Steinberger
parent 937e0265a3
commit eeaa6ea46f
9 changed files with 779 additions and 26 deletions

View File

@@ -0,0 +1,46 @@
import type { ContextPruningToolMatch } from "./settings.js";
function normalizePatterns(patterns?: string[]): string[] {
if (!Array.isArray(patterns)) return [];
return patterns.map((p) => String(p ?? "").trim()).filter(Boolean);
}
type CompiledPattern =
| { kind: "all" }
| { kind: "exact"; value: string }
| { kind: "regex"; value: RegExp };
function compilePattern(pattern: string): CompiledPattern {
if (pattern === "*") return { kind: "all" };
if (!pattern.includes("*")) return { kind: "exact", value: pattern };
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const re = new RegExp(`^${escaped.replaceAll("\\*", ".*")}$`);
return { kind: "regex", value: re };
}
function compilePatterns(patterns?: string[]): CompiledPattern[] {
return normalizePatterns(patterns).map(compilePattern);
}
function matchesAny(toolName: string, patterns: CompiledPattern[]): boolean {
for (const p of patterns) {
if (p.kind === "all") return true;
if (p.kind === "exact" && toolName === p.value) return true;
if (p.kind === "regex" && p.value.test(toolName)) return true;
}
return false;
}
export function makeToolPrunablePredicate(
match: ContextPruningToolMatch,
): (toolName: string) => boolean {
const deny = compilePatterns(match.deny);
const allow = compilePatterns(match.allow);
return (toolName: string) => {
if (matchesAny(toolName, deny)) return false;
if (allow.length === 0) return true;
return matchesAny(toolName, allow);
};
}