import type { BudgetDimension, BudgetMeter } from "./agent/budget.js"; import type { HumanInputResult } from "@boardwalk-labs/workflow"; /** The stable key a responder answers a budget gate by (`boardwalk respond budget …`). */ export declare const BUDGET_GATE_KEY = "budget"; /** Preset approvals per dimension, plus the open-ended `other` answer. Kept small: the point is a * fast decision. These strings ARE the wire options — backend/web render them verbatim. */ export declare const BUDGET_PRESETS: Record; export declare const BUDGET_CHOICE_CANCEL = "cancel"; /** The port the gate needs from the host — narrowed so tests don't build a whole WorkflowHost. */ export interface BudgetClearancePort { budgetClearance(gate: { prompt: string; inputSpec: unknown; }): Promise; } /** Raised when a responder answers `cancel`: the run stops, deliberately, at the user's word. */ export declare class BudgetGateCancelled extends Error { constructor(); } /** * The gate's question. It states the two numbers that matter (spent vs. cap) so the responder can * decide without opening the dashboard, and names the run's own manifest cap field so it's obvious * WHICH cap was hit (not the org's credit balance — a different failure with a different fix). */ export declare function budgetGatePrompt(dimension: BudgetDimension, spent: number, cap: number): string; /** The gate's response form — a choice, so the common answers are one click / one word. */ export declare function budgetGateInputSpec(dimension: BudgetDimension): unknown; /** * Interpret an answer as the NEW absolute cap for `dimension`, or null to cancel the run. * * `+` is an INCREMENT on the current cap (the presets); a bare amount is an ABSOLUTE new * cap (the "set a cap" escape hatch, via the choice's `other` entry). Anything unrecognized is * treated as cancel rather than guessed at — silently resuming a run on a misread answer spends * real money. See the module header for the full per-dimension grammar. */ export declare function resolveBudgetAnswer(dimension: BudgetDimension, answer: string, currentCap: number): number | null; /** * Budget clearance, awaited at every park point (see the module header). Fast path: no breach ⇒ * resolve immediately (the overwhelming majority of calls). On a breach of ANY dimension: park at * a gate, then apply the answer to the live meter and let the call proceed. * * The park's own wall-clock is EXCLUDED from the compute cap (`meter.excludeIdle`): parked time is * not compute (SUSPEND_POLICY Decision 3.4), and on the snapshot fleet the guest clock resyncs * across the frozen window — without the exclusion a compute park would re-breach the instant it * woke, forever. `usage.get()` polled DURING a park may transiently show the parked wall-clock as * compute spend; the exclusion lands when the park resolves. */ export declare class BudgetGate { private readonly meter; private readonly host; private readonly now; constructor(meter: BudgetMeter, host: BudgetClearancePort, now?: () => number); clear(): Promise; } /** How often the watcher samples the meter. Coarse is fine: compute presets are minutes. */ export declare const DEFAULT_COMPUTE_WATCH_INTERVAL_MS = 15000; /** * Detects a `max_compute_seconds` breach BETWEEN park points. `usd`/`tokens` only move at the * `streamModel` seam, but compute burns continuously — a breach can land mid-shell, mid-turn, or * mid-program-compute, far from any model call. * * WHY THIS ONLY DETECTS AND DOES NOT PARK — true park-anywhere needs fleet-host work. The freeze * machinery is quiescence-gated: `budgetClearance` may only be entered from a work-tracked seam * (its `freezeWait` steps the CALLER out of the work count; from a timer context that corrupts the * count and could freeze around live in-flight work, which SUSPEND_POLICY Decision 1 forbids). A * timer-initiated park would need (a) a host-agent-initiated out-of-band VM pause that does not * require runner quiescence, plus a wake path that re-arms the runner-side gate and applies the * answer to the meter, and (b) on hold-only substrates a program-process stop (SIGSTOP) in the * program runner. Until that lands, the honest contract is: the watcher logs the breach the moment * it happens, and the run PARKS AT ITS NEXT SEAM (`streamModel`, `sleep`, `shell`, * `workflows.call`) via the same {@link BudgetGate.clear} every park point awaits. */ export declare class ComputeBreachWatcher { private readonly meter; private readonly opts; private timer; private announced; constructor(meter: BudgetMeter, opts?: { runId: string; intervalMs?: number; }); /** True while a compute breach is standing (sampled; resets when an approval clears it). */ get breachDetected(): boolean; start(): void; stop(): void; /** One sample tick (exposed for tests — real ticks come from the interval). */ sample(): void; }