/** * The relay: the chain somebody is walking by hand. * * A flow is a chain our code walks. This is a chain with the user as the * runner: one step per command, and between two of them a human reads * the output, changes their mind, picks the next agent and the model it runs * on. What was missing for that is exactly one thing - somewhere to keep the * output of step *n* so step *n+1* can be handed it. That is this file. * * It keeps the material, and owns the life of a step around it - begun before * anything runs, finished once it has - and nothing else: no spawning, no pi, * no terminal. The commands in `commands/step.ts` and `commands/swarm.ts` do * those. The split is what lets the whole dataflow of a hand-walked chain be * asserted on without a session. * * **The carried output never reaches the main session's context.** That is the * point of the relay rather than the conversation: the window stays a console, * and what the model gets to read is what `/quote` puts there on purpose. */ import { type Usage } from "../src/index.ts"; /** What ran a step. An entry an older session wrote may say `pipeline`, and is drawn as it says. */ export type StepKind = "agent" | "flow" | "swarm"; /** One step that ran: what it was asked, and what came back. */ export type RelayStep = { /** Unique within the chain, so `--from` can name it. `coder`, then `coder-2`. */ id: string; /** The flow or agent that ran it, as it was named on the command line. */ name: string; /** What ran it: one agent, a flow, or several copies of one agent. */ kind: StepKind; /** What the user typed for this step, without the output it carried in. */ instruction: string; /** Which step's output it was handed, if any. */ from?: string; /** What it produced - the material the next step may carry. */ output: string; /** What it cost. Summed over the chain by {@link chainUsage}. */ usage: Usage; /** Where this step's transcripts and `usage.json` landed. */ dir: string; }; /** A chain in progress: the steps that ran, and the folder they all export into. */ export type Relay = { /** In the order they ran. A failed step is not here - it produced no material. */ steps: RelayStep[]; /** `runs//`, made once for the whole chain rather than per step. */ dir: string; }; /** The chain being walked, or `undefined` before the first step of one. */ export declare function currentChain(): Relay | undefined; /** Starts a chain exporting into `dir`, replacing whatever was being walked. */ export declare function startChain(dir: string): Relay; /** Drops the chain. The next step starts a new one, in a new folder. */ export declare function forgetChain(): void; /** * Appends a finished step under the id it ran with. * * Only successful steps get here: a step that failed produced nothing to carry, * and recording it would make `--from last` hand the next agent an error * message. The chain is left exactly where it was, which is also what lets the * same command be retried on another model. * * The id comes from {@link stepId}, taken before the step ran so that its * folder and its entry carry the same name. A second step under an id the * chain already holds is a programming error, and throws. */ export declare function recordStep(relay: Relay, step: RelayStep): RelayStep; /** `coder` while it is free, then `coder-2`: an id a user can type. */ export declare function stepId(relay: Relay, name: string): string; /** * Where the step about to run exports: `runs//-/`. * * One chain, one folder, one step per numbered subfolder: a chain walked by * hand is still a run, and it leaves the same trace as one walked by `/run`. * Numbered by position so the folders read in the order the steps ran, and * named by id so the folder and the transcript entry say the same thing. */ export declare function stepDir(relay: Relay, id: string): string; /** A step begun: the chain it runs in, the id it runs under, and where it exports. */ export type BegunStep = { relay: Relay; id: string; dir: string; }; /** * Begins a step of the chain in this terminal. * * Continues the chain being walked, or starts one in a fresh folder, and names * the step and its export folder **before** anything runs, so the folder, the * record and the entry carry one name whatever happens in between. */ export declare function beginStep(name: string, runDir: () => string): BegunStep; /** What a finished step brings to the chain: everything it keeps but what {@link beginStep} named. */ export type StepOutcome = Omit; /** * Finishes a step: records it under the id it began with, and leaves its entry * in the transcript through the door it is handed. * * One call, because the two acts belong together. A step recorded and never * drawn is invisible to the person walking the chain; one drawn and never * recorded cannot be carried on. Two commands ended a stage by hand in eight * steps each, reading the door off their raw dependencies where a forgotten * one failed in silence. */ export declare function finishStep(begun: BegunStep, outcome: StepOutcome, appendEntry: AppendEntry): RelayStep; /** `customType` of the transcript entry a finished step leaves behind. */ export declare const STEP_ENTRY = "chain-step"; /** How a finished step reaches the transcript, and only the transcript. Injected, so a test can catch it. */ export type AppendEntry = (customType: string, data: StepEntry) => void; /** * What {@link STEP_ENTRY} carries, and the renderer in `index.ts` draws. * * Less than a {@link RelayStep}: the entry is written into the session file, so * it holds what the transcript shows and not what the chain needs to carry on. */ export type StepEntry = { /** The step's id in the chain, which is also what `--from` takes. */ id: string; /** What ran it: one agent, a flow, or a swarm of one agent's copies. */ kind: StepKind; /** The step whose output it was handed, when it was handed one. */ from?: string; /** What it produced, in full - this is a transcript entry, not a summary. */ output: string; /** Turns, so the entry says what it cost without expanding anything. */ turns: number; /** Where this step's transcripts landed. */ dir: string; }; /** The entry a recorded step leaves in the transcript. */ export declare function entryOf(step: RelayStep): StepEntry; /** * What `--from` names: a step id, `last` (the default), or `none`. * * Throws on a name nothing answers to, listing what the chain does hold - * a typo here costs a whole step of real work otherwise. */ export declare function stepFrom(relay: Relay | undefined, from: string | undefined): RelayStep | undefined; /** * What the step is actually asked: the instruction under `## Request`, then * the output it carries under the step it came from. A first step carries * nothing and is passed through verbatim, exactly as `/run` passes its * request - a lone instruction under a heading is noise. Empty parts are * dropped rather than left as a heading with nothing under it. */ export declare function chainInput(instruction: string, previous?: RelayStep): string; /** * Every step's usage, summed - `wallMs` included, as the sum of the steps' own. * * A chain walked by hand spends most of its life waiting for a human, and * counting that as work would be an estimate; the steps' wall times add up * because they ran one after another. See {@link chainLines}. */ export declare function chainUsage(relay: Relay): Usage; /** * `/chain`, as lines - the chain so far, and where it went. * * Kept away from the terminal so it can be asserted on directly, the same split * as `/flows` and `/agents`. The wall time shown is the sum of the steps' * own, not the age of the chain: a chain walked by hand spends most of its life * waiting for a human, and counting that as work would be an estimate. */ export declare function chainLines(relay: Relay | undefined): string[]; /** * A result, framed for the conversation. * * pi hands custom messages to the model as **user** messages, and an * unattributed report arriving in that slot reads as an instruction. Naming * what ran and what it was asked turns it back into what it is: a result * somebody chose to show. One framing for a step `/quote` sends and a flow * `/run` sends, so the two read alike. */ export declare function framed(what: string, asked: string, output: string): string; /** A step, framed for the conversation - what `/quote` sends. */ export declare function stepAnswer(step: RelayStep): string; //# sourceMappingURL=relay.d.ts.map