import type { GuardExceededError } from "./guard.js"; import type { StateStack } from "./state/stateStack.js"; import type { RuntimeContext } from "./state/context.js"; import { type Interrupt } from "./interrupts.js"; import type { SourceLocationOpts } from "./state/checkpointStore.js"; /** * Cost-guard trips as interrupts (resumable-guards PR 2). * * The raising site is a dedicated idempotent gate step in `runPrompt` * (`pr.step("…guardGate…", () => raiseGuardTripsUntilClear(...))`), * placed immediately before each LLM request step. The gate LOOPS until * the stack is clear: one answered question does not mean the gate is * clear — approving the inner guard's trip can leave (or push) an OUTER * guard over its own limit, and each budget is owed its own question. * Because the gate runs before the request step and nothing paid happens * between them, not a cent can leak while a question is out. * * The gate body is idempotent by construction, which is what lets it * live in a PromptRunner step: on resume it re-detects, finds the * persisted interrupt id for the still-open trip in `stack.other`, and * applies the recorded answer instead of re-asking. * * Contract per trip: RESOLVING (approve applied, or someone else's * answer landed while we were parked) continues the loop — the caller * must never treat one resolution as clearance. REJECTING throws the * original GuardExceededError from the gate, and everything downstream — * AbortedResult, the level rule, finalize, the guard boundary's * conversion to success(draft)/failure — runs exactly as it always has. * UNANSWERED returns the Interrupt[] so PromptRunner.step's bailout * machinery (message snapshot, checkpoint, PromptBailout) surfaces it. */ export declare function raiseGuardTripsUntilClear(ctx: RuntimeContext, stack: StateStack, detect?: () => GuardExceededError | null): Promise; /** Control-flow signal thrown by _runPrompt's cancellation classifier * when an in-flight request died to a NON-ROOT guard trip on this * stack: the surrounding request-step wrapper in runPrompt catches it, * runs a retry gate (which raises the trip resumably), and — on * approve — re-issues the request from the current thread state. The * cancelled generation is honestly gone; the retry is a fresh request. * Never escapes runPrompt. */ export declare class GuardTripRetry extends Error { readonly guardId: string; constructor(guardId: string); } /** The RUNNER surface for the same question the prompt gates ask: called * at step entry (before shouldSkip's consuming walk) when * `stack.firstRaisableTrip()` found an over-budget armed guard — * PR 3's time trips, which unlike cost trips become detectable at * arbitrary step boundaries. Approve applies and execution continues * into the step; reject throws the trip (identical unwind to the old * shouldSkip throw); unanswered checkpoints at THIS step and halts the * runner (the agency.interrupt dance — the caller returns without * running the step body, and Runner.step's halt handling does the * rest). Returns true iff the runner halted. */ export declare function raiseGuardTripsAtStep(args: { ctx: RuntimeContext; stack: StateStack; location: SourceLocationOpts; isNodeContext: boolean; threads: unknown; halt: (payload: unknown) => void; }): Promise;