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<string> = 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;
}
