/** * The step runtime: executes a validated {@link MediaPlan} as an `@nhtio/middleware` onion, * one stage per step, with consumer interceptors wrapping every step. * * @remarks * Internal sibling of the `@nhtio/adk/batteries/media` entry. A fresh `Runner` is minted per * execution (middleware runners are single-use), so the same compiled chain can be awaited * repeatedly. Each step stage: * * 1. runs the consumer's `use` interceptors (the documented seam for DLP/AV scanning, caching * via `shortCircuit(bytes)`, byte limits, and telemetry — the battery ships no built-in * scanner/cache/limiter: those are policies, this is the seam), then * 2. dispatches to the verb's registered {@link StepImpl}, validating the output at the step * boundary so a misbehaving engine produces a clear error instead of corrupt bytes. * * Steps stream bytes in memory; nothing touches disk except inside a binary engine's * `ScratchWorkspace`. Adjacent `image.*` steps are fused by the compiler before execution so * a resize→format→rotate chain costs a single decode/encode. */ import type { NextFn } from '@nhtio/middleware'; import type { EngineRegistry } from "./registry"; import type { MediaPlan, MediaStep, MediaArgValue } from "./plan"; /** A single in-flight value travelling between steps. */ export interface StepPayload { /** The raw content bytes. */ bytes: Uint8Array; /** The content MIME type. */ mimeType: string; /** The filename (extension informs format dispatch). */ filename: string; } /** * What a step produces. `media` continues the chain (or terminates as bytes); `media-list` * and `data` are terminal-only shapes enforced by the plan compiler. */ export type StepResult = { kind: 'media'; payload: StepPayload; } | { kind: 'media-list'; payloads: StepPayload[]; } | { kind: 'data'; data: unknown; asText?: string; }; /** The mutable execution context threaded through interceptors and step impls. */ export interface StepContext { /** The whole plan being executed. */ readonly plan: MediaPlan; /** Zero-based index of the current step. */ readonly stepIndex: number; /** The current step. */ readonly step: MediaStep; /** The input payload for this step. */ payload: StepPayload; /** Abort signal threaded from the caller. */ readonly signal?: AbortSignal; /** Scratchpad shared across the execution (interceptors may stash timings, hashes…). */ readonly stash: Map; /** * Short-circuit this step: skip the implementation and continue the chain with `bytes` * (the cache idiom). Throws internally — call it, don't return it. */ shortCircuit(payload: StepPayload): never; /** The deployment's engine registry — ordered, capability-filtered dispatch. */ readonly engines: EngineRegistry; /** * Resolve another media participating in this step (merge/diff targets), by ref id. * Supplied by the pipeline from its configured media resolver. */ resolveRef(id: string): Promise; } /** One verb's implementation. Registered into the runtime's step registry. */ export type StepImpl = (ctx: StepContext) => Promise; /** Consumer step interceptor — the `use` seam. Same onion shape as the tool batteries. */ export type MediaStepMiddlewareFn = (ctx: StepContext, next: NextFn) => void | Promise; /** Options for {@link executePlan}. */ export interface ExecutePlanOptions { /** The input payload the first step consumes. */ input: StepPayload; /** Verb id → implementation registry. */ steps: ReadonlyMap; /** Consumer interceptors wrapping every step. */ use: readonly MediaStepMiddlewareFn[]; /** The deployment's engine registry. */ engines: EngineRegistry; /** Media-ref resolution for multi-input verbs. */ resolveRef: StepContext['resolveRef']; /** Abort signal. */ signal?: AbortSignal; } /** The settled result of executing a whole plan. */ export type PlanResult = StepResult; /** * Execute a validated plan. Returns the final step's result; intermediate steps must produce * `media` results (the compiler guarantees non-terminal steps are media-shaped). * * @param plan - The validated plan. * @param options - Input payload, step registry, interceptors, engine access. * @returns The terminal step's result. */ export declare const executePlan: (plan: MediaPlan, options: ExecutePlanOptions) => Promise; /** Convenience: read a step arg with a typed cast (validation already ran). */ export declare const argOf: (step: MediaStep, name: string) => T | undefined;