import { DebuggerState } from "./debuggerState.js"; import type { AgencyCallbacks } from "../runtime/hooks.js"; import { Checkpoint } from "../runtime/state/checkpointStore.js"; import { type DebuggerIO } from "./types.js"; import type { RunUsage } from "../runtime/invocationUsage.js"; import { type AttachFunctions, type LegOptions } from "../runtime/attachedDebugger.js"; import type { FunctionParameter } from "../types.js"; import type { TraceHeader } from "../runtime/trace/types.js"; import type { InvocationOptions } from "../runtime/invocationOptions.js"; /** The four functions a driver drives a program through: a compiled * module exports them bound to its `__globalCtx`, and the runtime binds * them to a context for the attach server (`attachFunctionsFor`). */ export type ModuleFunctions = AttachFunctions; /** One attached run's visit to the driver: what its leg was started * with, which every resume and rewind passes back, and the usage of the * last leg the driver ran for it. Carried with the call rather than kept * on the driver, because runs interleave: the driver holds the UI only * while it waits for the person, and lets go while a leg runs. */ type AttachedSession = { leg: LegOptions; usage?: RunUsage; }; type DriverOpts = { mod: ModuleFunctions; rewindSize: number; ui: DebuggerIO; checkpoints?: Checkpoint[]; traceHeader?: TraceHeader; /** The policy and budget the debugged run is started with. The driver * adds the `input()` routing; `driver.invocation` is the result, which * the node call spreads (the generated node function takes its options * flat) and every resume and rewind takes whole. */ invocation?: InvocationOptions; /** The driver is installed on a program something else is running * (`attach`). It then answers only debug stops, hands the program's * own interrupts and the final value back to whoever is running it, * resumes with that caller's options, and leaves the terminal alone. */ attached?: boolean; }; type DriverRunOpts = Partial<{ interceptConsole: boolean; }>; export declare class DebuggerDriver { private mod; private ui; /** The invocation the debugged run is called with, and every resume * and rewind: the policy and budget from the run flags, and `input()` * routed to the UI's text field. */ readonly invocation: InvocationOptions; debuggerState: DebuggerState; private originalConsoleLog; private originalConsoleError; private programFinished; /** What `set` has queued for the next resume. The UI shows a copy * beside the current values; the driver owns it. */ /** The edits queued at the stop, applied once by the next resume. */ private pendingEdits; /** The applied lines of the last accepted preview, one per write; an * edit can lower to several writes, so the lines of a new edit are * the ones past these. */ private pendingApplied; private readonly attached; /** Attached: the runs whose steps were let through because another * run owns the debugger, each told once in the activity log. */ private ignoredRuns; /** The `waitForCommand` in progress, kept when a stop is answered some * other way (a detach, the caller's cancel), so the next stop takes * the key the person then presses rather than asking twice. */ private commandInFlight; private detachRequested; private detachWaiters; constructor(opts: DriverOpts); promptForNodeArgs(parameters: FunctionParameter[]): Promise; /** Install this driver on the module's running program. The runtime * finds it through the state it installs, so nothing else is told. */ attach(): void; /** Remove this driver from the program. A stop the driver is waiting * at is answered with `continue`; with nothing pending the next step * costs nothing again. */ detach(): void; private runAttached; /** The program finished in a leg the caller ran: a line in the log and * a render that does not wait. The next run to stop is debugged next. */ private finishedAttached; /** A call on the UI. Attached, the UI reporting the other side gone is * a detach, and the call has no answer; any other failure is the * caller's. */ private uiCall; /** A render from a callback, which the program does not wait for. */ private renderInBackground; /** Whether the driver has been detached from the program it was on, * so its callbacks, still composed into the leg that was running, do * nothing more. */ private detachedNow; /** Show the stop and take the person's command. Attached, the answer * is `continue` when the driver is detached meanwhile, when the IO * reports the other side gone, or when the caller cancels the run: the * resume then lands the cancel the usual way. */ private attendStop; private nextCommand; private takeCommand; /** The options every resume and rewind carries. Attached, they are the * caller's own, with the driver's hooks added to the caller's and the * key that marks the call as the debugger's; the state itself reaches * the new leg through the slot the module shares. */ private resumeOptions; private interceptConsole; private restoreConsole; getCallbacks(): AgencyCallbacks; run(initialResult: any, _opts?: DriverRunOpts, session?: AttachedSession | undefined): Promise; /** Ask the person about each interrupt in `asked`, in order, and resume * with one answer per interrupt of `batch`. A debug stop in the same * batch is answered with an approve, which the resume never reads. */ private handleInterrupts; /** One interrupt's answer, asked for until the input is one of * approve, reject, or resolve with a value. A guard trip takes a * grant, a disarm, a message, or a reject instead; a raise that * expects a value, such as a `question`, takes the typed text. */ private askAbout; /** The answer to a raise used as a value (`const x = raise ...`, or * `question` from `std::agent`): the typed text, as a string, the way * the CLI's approval prompt takes it. `resolve ` gives a JSON * value when the rest parses as JSON, so a number or a list can be * given while an answer that happens to start with the word stays * whole; `reject` rejects, and a bare `approve` resolves the variable * to `true`. */ private askForValue; /** A guard trip's answer comes from the form (`showGuardTripForm`), * which only offers answers the runtime accepts. */ private askAboutGuardTrip; /** Resume the program with one response per interrupt of `batch`, in * the batch's order: the answer given for it, else an approve. The * runtime insists on a response for every interrupt in the batch. * `shown` is the interrupt the panes showed while the person decided. */ private respond; private handleCommand; /** The checkpoints the rewind selector and the checkpoints panel show: * the rolling window and the program's own pinned ones. */ private checkpointsToShow; /** Queue `edits` after checking them against the stop's checkpoint: * on a refusal every reason is logged and the list is unchanged; on * success the list grows, the applied lines are logged, and the UI * is told so it can draw the preview. */ private queueEdits; private dropEdits; /** The queued edits, cleared: a resume applies them once. */ private takeEdits; /** Whether the driver is showing a stop and waiting on the person. A * pause lands whenever it is not: in a leg the driver resumed, and, * attached, while the program runs on after the caller answered its * own interrupt, which is no leg of the driver's. */ private atStop; /** Attached: the debugged run ended and no run has taken the debugger * since, so there is nothing to pause; the next run's first step * (`ownerChanged`) clears it. */ private betweenRuns; /** The person asked the running program to stop at its next * statement: stepping mode, which the next step honours, with the * step target cleared so `next` over a call stops inside it too. A * call in flight is not interrupted; the stop comes when it returns. * At a stop, or after the run ended, a pause changes nothing. */ private pauseRequested; private resumeInterrupt; /** Move on from a debug stop: every stop in the batch is approved, an * answer the resume never reads, and pending overrides are applied. */ private resume; private rewindTo; } export {};