import type { Agent } from '../../types/api.js'; import { READ_ONLY_TOOL_NAMES } from '../tools.js'; // v1.8.2: tool-call budget defaults. Resolved per-turn by resolveToolBudget. // - Agent with explicit max_tool_calls: that value. // - Agent with read-only-only tools: BUDGET_READ_ONLY (50). // - Agent with any non-read-only tool: BUDGET_NON_READ_ONLY (10). // - No agent (raw chat): BUDGET_NO_AGENT (50). // v1.13.7: bumped BUDGET_NO_AGENT 15→30 to match BUDGET_READ_ONLY. Every tool // in ALL_TOOLS today is read-only (see services/tools.ts comment at // READ_ONLY_TOOL_NAMES); the cautious 15-cap was a forward-looking guard for // write tools that haven't landed yet. No-agent mode gets the same toolset as // an all-read-only agent at runtime, so they should share the same budget. // v1.13.12: bumped read-only caps 30→50. Real recon sessions were hitting 30 // with ~3 turns wasted on codecontext parse failures (empty node_modules // files); legitimate need was ~27, and Architect-class system overviews want // deeper recon than a 30-cap permits. Headroom of 20 absorbs failure-retry // turns + deeper exploration without changing the safety floor materially — // the doom-loop guard (3 identical calls → abort) catches the actual failure // mode this cap was guarding against. export const BUDGET_READ_ONLY = 100; export const BUDGET_NON_READ_ONLY = 100; export const BUDGET_NO_AGENT = 100; const READ_ONLY_SET: ReadonlySet = new Set(READ_ONLY_TOOL_NAMES); export function resolveToolBudget(agent: Agent | null): number { if (agent?.max_tool_calls != null) return agent.max_tool_calls; if (!agent) return BUDGET_NO_AGENT; const allReadOnly = agent.tools.every((t) => READ_ONLY_SET.has(t)); return allReadOnly ? BUDGET_READ_ONLY : BUDGET_NON_READ_ONLY; }