import { join } from "node:path"; import { loadScopedConfig } from "../../src/shared/config"; import type { OutputGuardConfig, ToolGuardRule } from "./types"; export const DEFAULT_CONFIG: OutputGuardConfig = { enabled: true, defaultMaxChars: 16_000, defaultHeadRatio: 0.5, tools: { bash: { maxChars: 24_000, headRatio: 0.2, hint: "pipe through head/tail, add filters, or narrow the command" }, grep: { maxChars: 16_000, headRatio: 0.8, hint: "add path/glob filters or use a more specific pattern" }, rg: { maxChars: 16_000, headRatio: 0.8, hint: "add path/glob filters, use --max-count, or narrow the pattern" }, read: { maxChars: 24_000, headRatio: 0.9, hint: "use offset/limit to read specific sections" }, fd: { maxChars: 12_000, headRatio: 0.8, hint: "add --max-depth, --extension, or a more specific pattern" }, find: { maxChars: 12_000, headRatio: 0.8, hint: "add -maxdepth, -name, or -type filters" }, }, exempt: [ "web_search", "web_read", "docs_search", "check_search_tools", "verify_search_tools", "check_vera", // Subagent returns are already synthesized by the child agent // per its briefing; truncating defeats the round-trip cost of delegation. "subagent", ], notifications: { showTruncation: true, }, }; export function resolveToolRule(config: OutputGuardConfig, toolName: string): ToolGuardRule { const override = config.tools[toolName]; return { maxChars: override?.maxChars ?? config.defaultMaxChars, headRatio: override?.headRatio ?? config.defaultHeadRatio, hint: override?.hint, }; } export function loadOutputGuardConfig(cwd: string): { config: OutputGuardConfig; source: string } { return loadScopedConfig, OutputGuardConfig>( cwd, join("config", "output-guard.json"), DEFAULT_CONFIG, (defaults, input) => { if (!input) return defaults; const tools: Record> = { ...defaults.tools }; if (input.tools) { for (const [name, rule] of Object.entries(input.tools)) { tools[name] = { ...tools[name], ...rule }; } } const exempt = input.exempt ?? defaults.exempt; return { enabled: input.enabled ?? defaults.enabled, defaultMaxChars: input.defaultMaxChars ?? defaults.defaultMaxChars, defaultHeadRatio: input.defaultHeadRatio ?? defaults.defaultHeadRatio, tools, exempt, notifications: { showTruncation: input.notifications?.showTruncation ?? defaults.notifications.showTruncation, }, }; }, ); }