/** * GS2-106 — the continue hint: after a recorded `gth ask` or `gth exec` run, one line on stderr * naming the command that continues the conversation, e.g. `gth ask --resume "…"`. * * ## The gate, and why each condition is in it * * The hint is a promise that pasting it works. So it is printed only when every condition a * resume would check already holds, and the checks are the resume seam's own, not a copy: * * - **The caller asked for it** (`SingleShotOptions.announceResumeHint`). `runSingleShot` has five * callers; `ask` and `exec` are a person reading what came back, while `batch`, `eval`, * `gth-batch` and `workflow` are harnesses whose cells every resume surface refuses anyway. A * default-on hint would print a command that fails, hundreds of times per run. * - **The run was recorded.** History off, or a store that would not take the row, leaves nothing * to resume. * - **The thread is durable and its link was not cut.** A store that did not open ran the turn in * memory; a checkpoint write that failed mid-run cut the conversation's link to its thread. Either * way the row exists and the resume seam refuses it. * - **The thread has a checkpoint and ends cleanly** ({@link threadTail}). A run that stopped at an * approval, with a tool call nobody answered, is exactly what `ask`/`exec --resume` refuse; the * same predicate decides both, so the hint cannot offer what the seam will turn down. * * ## What it names * * The run id, never the integer: the integer is only meaningful in this one database, and a * recreated database hands the same integers out again. A row written before run ids existed has * none, and one is never minted at resume time, so its hint falls back to the integer and `debug` * says why. The verb is the one just run — `ask` or `exec` — because that is the one the person * already knows the arguments of. * * ## Rungs * * `output.resumeHint`, on the `output.header` rungs, defaulted HERE (at the read site) to * `compact`: `none` prints nothing, `compact` the one line, `debug` the line plus the integer id and * the history file — and, when there is no hint, the reason there is none. * * On stderr (`displayNotice`), so `gth ask … > answer.txt` keeps only the answer. */ import type { GthConfig } from '#src/config.js'; import type { GthOutputHeaderRung } from '#src/config/schema.js'; import type { GthCommand } from '#src/core/types.js'; import type { SessionCheckpointer } from '#src/history/sessionCheckpointer.js'; /** Whether a finished run can be continued, and if not, why — the fact behind the hint. */ export type SingleShotResumability = { resumable: true; } | { resumable: false; reason: 'history-off' | 'not-recorded' | 'store-unavailable' | 'link-cut' | 'no-checkpoint' | 'pending-tool-call'; }; /** The rung in force. An unset key is `compact`: the hint is shown by default. */ export declare function resolveResumeHintRung(config: Pick): GthOutputHeaderRung; /** * Decide whether the run just recorded can be resumed, reading the thread's latest checkpoint. * Called after the record and before the checkpointer closes. Never throws: a checkpoint that * cannot be read counts as no checkpoint, because the hint must never be what breaks a run. */ export declare function resumabilityOf(config: GthConfig, checkpointer: SessionCheckpointer, recorded: { conversationId: number; } | undefined): Promise; /** The command that continues the conversation, exactly as it must be typed. */ export declare function resumeHintCommand(command: 'ask' | 'exec', id: string | number): string; /** * Print the hint — or, under `debug`, the reason there is none. Only `ask` and `exec` have a * command to name; any other caller prints nothing whatever the rung. */ export declare function announceResumeHint(config: GthConfig, command: GthCommand, recorded: { conversationId: number; runId: string | null; } | undefined, resumability: SingleShotResumability): void;