/** * Sequence — sequential composition of runners (steps chained one after another). * * Pattern: Builder (GoF) + Adapter over footprintjs's `addSubFlowChartNext`. * Role: core-flow/ layer — pure control flow, no LLM deps. * Each step's output becomes the next step's input; default * mapping is string chaining (step N's return → step N+1's * `{ message }`). Custom mapping via `.mapBetween(fn)` between * any two steps. * Emits: agentfootprint.composition.enter / exit (via compositionRecorder). */ import { type FlowchartCheckpoint, type RunOptions } from 'footprintjs'; import type { StructureRecorder } from 'footprintjs'; import type { GroupMetadata, GroupTranslator } from '../core/translator.js'; import type { RunnerPauseOutcome } from '../core/pause.js'; import type { Runner } from '../core/runner.js'; import { RunnerBase } from '../core/RunnerBase.js'; export interface SequenceOptions { /** Human-friendly name for events + topology. Default: 'Sequence'. */ readonly name?: string; /** Stable id used for topology + events. Default: 'sequence'. */ readonly id?: string; /** * Optional build-time recorders passed through to footprintjs's * `flowChart()` factory. Each recorder observes per-node build * events (`onStageAdded` / `onSubflowMounted` / etc.) for this * composition's internal chart (Seed + each step mount + Finalize). * * Cascade: each step runner attaches its OWN recorders at its own * construction time. footprintjs does NOT propagate StructureRecorders * into mounted subflows — attach the same recorders to every nested * composition for full coverage. * * When omitted, no build-time observation is wired up. */ readonly structureRecorders?: readonly StructureRecorder[]; /** * Optional per-COMPOSITION translator (UI-agnostic). See * `core/translator.ts`. When attached, `runner.getUIGroup()` invokes * it with the Sequence's `GroupMetadata` (kind `'Sequence'`, id, * name, ordered steps, no extras) and returns whatever shape the * translator produces. When omitted, `getUIGroup()` returns * `undefined`. */ readonly groupTranslator?: GroupTranslator; } export interface SequenceInput { readonly message: string; } export type SequenceOutput = string; type StepChild = Runner<{ message: string; }, string>; interface StepEntry { readonly id: string; readonly runner: StepChild; /** Mapper applied BEFORE this step's run(). */ readonly mapFromPrev: (prev: string) => { message: string; }; /** Optional per-method translator override for THIS step only. */ readonly groupTranslator?: GroupTranslator; } /** * Options bag accepted by `SequenceBuilder.step()` for per-method * overrides. Backwards-compatible — when omitted the legacy two-arg * `.step(id, runner)` signature still works. */ export interface SequenceStepOptions { /** Per-method translator override. See `StepEntry.groupTranslator`. */ readonly groupTranslator?: GroupTranslator; } export declare class Sequence extends RunnerBase { readonly name: string; readonly id: string; private readonly steps; private readonly opts; private currentRunContext; constructor(opts: SequenceOptions, steps: readonly StepEntry[]); static create(opts?: SequenceOptions): SequenceBuilder; protected getGroupTranslator(): GroupTranslator | undefined; /** Sequence is a flat ordered list of steps. One member per step, * preserving definition order so the consumer can render them * linearly (default Lens UX). Per-method overrides (L1c) take * precedence over the step runner's own translator. */ protected buildUIGroupMetadata(): GroupMetadata; run(input: SequenceInput, options?: RunOptions): Promise; resume(checkpoint: FlowchartCheckpoint, input?: unknown, options?: RunOptions): Promise; private createExecutor; private finalizeResult; private buildChart; } /** * Fluent builder. Reads as natural English: * Sequence.create().step('a', A).pipeVia(fn).step('b', B).build() * → "Sequence: step A, pipe via fn, step B." * * `step(id, runner)` adds a sequential step. `pipeVia(fn)` customises * the transformation of the previous step's output before it feeds the * next step (otherwise the default string-chain mapper is used). */ export declare class SequenceBuilder { private readonly opts; private readonly steps; /** Pending pipeVia transformer for the NEXT step (consumed on .step()). */ private pendingPipe?; private readonly seenIds; constructor(opts: SequenceOptions); /** * Add a step. Runner must accept `{ message: string }` and return `string`. * First step receives the Sequence input; subsequent steps receive the * previous step's output (via the default string-chain mapper, or via * the transformer set by a preceding `.pipeVia(fn)` call). * * Optional third arg `opts.groupTranslator` overrides the runner's * own constructor-level translator for THIS step only — only its * `member.uiGroup` flips to the override's output. */ step(id: string, runner: StepChild, opts?: SequenceStepOptions): this; /** * Transform the previous step's string output before it reaches the * next step. Consumed once by the next `.step()` call. Default * mapping is `(prev) => ({ message: prev })`. * * Reads as English: `.step('a', A).pipeVia(fn).step('b', B)` * → "step A, pipe via fn, step B" */ pipeVia(fn: (prev: string) => { message: string; }): this; build(): Sequence; } export {};