import * as smoltalk from "smoltalk"; import type { CheckpointEdit, StopAt } from "./state/checkpointPatch/index.js"; import { approve, reject } from "./interruptResponse.js"; import type { InterruptApprove, InterruptReject, InterruptResponse } from "./interruptResponse.js"; import { type Run } from "./asyncContext.js"; import { type InvocationOptions } from "./invocationOptions.js"; import { type PausedCheckpoint } from "./pause.js"; import { type ResumeMetadata, type ResumeOverrides } from "./resumeSetup.js"; import { Checkpoint } from "./state/checkpointStore.js"; import { RuntimeContext } from "./state/context.js"; import { GlobalStoreJSON } from "./state/globalStore.js"; import { StateStack, StateStackJSON } from "./state/stateStack.js"; import { Approved, GraphState, Rejected, RunNodeCoreResult } from "./types.js"; import type { HandlerEntry } from "./types.js"; import { type ServedInvocationOutcome } from "./invocationUsage.js"; import type { CheckpointInterrupt, InterruptSummary } from "../statelogClient.js"; export { approve, reject }; export type { InterruptApprove, InterruptReject, InterruptResponse }; /** The minimal result shape the interrupt loop and its reporter operate over: * a local `RunNodeResult` and the remote client's result both satisfy it. */ export type InterruptResult = { data: unknown; }; /** Explicit "not my interrupt — ask the next handler." Identical in effect * to a handler returning nothing, but usable in value position (a match * arm must produce a value). Returning `undefined` keeps working; the * chain normalizes it to this shape at the boundary. */ export declare function pass(): InterruptResponse; export type InterruptData = { messages?: smoltalk.MessageJSON[]; toolCall?: smoltalk.ToolCallJSON; }; export type InterruptState = { stack: StateStackJSON; globals: GlobalStoreJSON; }; export type Interrupt = { type: "interrupt"; effect: string; message: string; origin: string; interruptId: string; data: T; debugger?: boolean; interruptData?: InterruptData; checkpointId?: number; checkpoint?: Checkpoint; state?: InterruptState; runId: string; expectsValue?: boolean; }; /** The `interrupt` field of the handler and resolution events. */ export declare function interruptSummary(intr: InterruptSummary): InterruptSummary; /** What `checkpointCreated` records about the interrupts a run stopped for. */ export declare function checkpointInterrupts(interrupts: Interrupt[]): CheckpointInterrupt[]; export declare function interrupt(opts: { effect: string; message: string; data: T; origin: string; runId: string; interruptId?: string; expectsValue?: boolean; }): Interrupt; export declare function createDebugInterrupt(data: T, checkpointId: number, checkpoint: Checkpoint, runId: string): Interrupt; export declare function isInterrupt(obj: any): obj is Interrupt; export declare function hasInterrupts(data: any): data is Interrupt[]; /** * Called from the generated CLI bootstrap (the `argv[1] === import.meta.url` * block) AFTER a top-level node returns. When a node is run directly from the * command line and produces an interrupt that no handler caught, the interrupt * comes back as an `Interrupt[]` in `result.data` — and the bootstrap would * otherwise just exit silently, leaving the user with no output and no clue. * * This prints a helpful message pointing at the handlers guide and exits * non-zero. It only runs on direct CLI execution: when the compiled module is * imported and the node is called from TypeScript, the bootstrap guard is false * and this is never reached — there, the caller is expected to inspect * `result.data` / `respondToInterrupts` itself, so a returned interrupt is fine. */ export declare function reportUnhandledInterrupts(result: InterruptResult): Promise; /** What a REPL prints when a turn returns interrupts nothing answered: the * turn stopped there, so its reply was never shown. */ export declare function escapedTurnText(interrupts: Interrupt[]): string; export declare function isDebugger(obj: any): obj is Interrupt; export declare function isRejected(obj: any): obj is Rejected; export declare function isApproved(obj: any): obj is Approved; export type HandlerChainOutcome = { kind: "rejected"; value: any; } | { kind: "approved"; value: any; } | { kind: "propagated"; } | { kind: "noResponse"; }; /** The interrupt fields visible to handlers and relayed between processes: * everything identifying WHAT is being decided, without the per-dispatch * bookkeeping (ids, checkpoints) the origin process owns. */ export type InterruptInfo = { effect: string; message: string; data: any; origin: string; expectsValue?: boolean; }; /** Merge two chain-segment outcomes with single-process precedence: * reject > propagate > approve > noResponse. `inner` is the segment closer * to the interrupt (e.g. the child process), `outer` the segment farther * from it (e.g. the parent). A double-approve merges through the EFFECT's * approval merge (effectMerge.ts) — std::guard grants accumulate; every * other effect keeps the historical IPC default, where the outer value * wins but a VALUELESS outer approve defers to the inner value (the * outcome travels as JSON, which cannot distinguish an absent value from * an explicit undefined). */ export declare function mergeChainOutcomes(effect: string, inner: HandlerChainOutcome, outer: HandlerChainOutcome): HandlerChainOutcome; /** The distributed handler chain, evaluated from this process outward: * run the local chain; local reject is final (fail-fast, matching the * single-process short-circuit); otherwise, if this process is itself a * subprocess, consult the parent and merge. Nested subprocesses recurse * through this same function on each hop. * * `interruptId`: the interrupt's id — the CHILD's id when relaying, or the * freshly-minted one at the origin dispatch — so every process's * handlerDecision/interruptResolved statelog events correlate with the * originating interrupt (ids are preserved verbatim end-to-end). * * `parentDecided` lets the origin caller (`interruptWithHandlers`) * attribute the verdict: it distinguishes a verdict the parent hop actually * participated in from one settled purely by local handlers (the * `resolvedBy: "ipc" | "handler"` tag). Neither this function nor * `runHandlerChain` emits terminal statelog events — the origin's * `renderVerdict` is the sole emitter, so relay hops (a parent process * evaluating a child's interrupt) contribute only handlerDecision events * to the shared trace. */ export declare function gatherChainOutcome(run: Run, interruptObj: InterruptInfo, stack: StateStack | undefined, interruptId: string, eligible?: (entry: HandlerEntry) => boolean): Promise<{ outcome: HandlerChainOutcome; parentDecided: boolean; }>; export declare function interruptWithHandlers(run: Run, effect: string, message: string, data: T, origin: string, opts?: { expectsValue?: boolean; eligible?: (entry: HandlerEntry) => boolean; stack?: StateStack; }): Promise[] | Approved | Rejected>; /** * Validate a resume batch. Returns the first problem as a message, or `null` * when the batch is well-formed. `safeParse` never throws — a `null` or * primitive item is a validation error, not a crash. */ export declare function validateResumeBatch(interrupts: unknown, responses: unknown): string | null; export type ResumeCliFromCheckpointArgs = { ctx: RuntimeContext; checkpoint: Checkpoint; overrides?: ResumeOverrides; edits?: CheckpointEdit[]; }; /** Resume a checkpoint as a complete CLI run, including lifecycle events and * trace finalization. Like `runNode`, the result carries the run's `usage` * and `traceId`. */ export declare function resumeCliFromCheckpoint(args: ResumeCliFromCheckpointArgs): Promise; type RespondToInterruptsArgs = { ctx: RuntimeContext; interrupts: Interrupt[]; responses: InterruptResponse[]; overrides?: Record; /** Edits proper, applied after the overrides; `at` is the stop they * are made at, when the caller has a stop record. */ edits?: CheckpointEdit[]; at?: StopAt; metadata?: Record; invocation?: InvocationOptions; abortSignal?: AbortSignal; pauseSignal?: AbortSignal; }; export type ResumeFromCheckpointArgs = { ctx: RuntimeContext; paused: PausedCheckpoint; /** Edits to the paused checkpoint before it runs on. */ edits?: CheckpointEdit[]; metadata?: ResumeMetadata; abortSignal?: AbortSignal; pauseSignal?: AbortSignal; invocation?: InvocationOptions; }; /** Continue a run that an external pause stopped. Keeps the paused run's id, * checks code fingerprints, reinstalls the root policy and budget, and runs * the same loop as an interrupt response, so the result can again be a * value, interrupts, or another paused checkpoint. Takes edits, not the * old overrides; a caller who wants to replay uses rewindFrom. */ export declare function resumeFromCheckpoint(args: ResumeFromCheckpointArgs): Promise; /** Public entry point — returns the resume result with its usage snapshot * attached, or throws the identical original error. */ export declare function respondToInterrupts(args: RespondToInterruptsArgs): Promise; /** Serve-only entry point: hands the resume outcome (result/error + usage * snapshot) to the serve adapter instead of unwrapping it. */ export declare function respondToInterruptsForServe(args: RespondToInterruptsArgs): Promise>>;