/** * Pipeline — Koa-style middleware chain with named middleware * and position-aware insertion. Generic over input type T. */ export type NextFn = (value: T) => Promise; export type MiddlewareHandler = (value: T, next: NextFn) => Promise; /** * Called when a middleware crashes (throws or rejects). Used by the * Pipeline's error boundary to log the offender without aborting the run. * * Return `'rethrow'` to propagate the error (default for core middleware), * or `'swallow'` to abort descent into the crashing middleware: its caller's * `await next()` resolves with the value that was about to flow into the * crashed middleware. The crashed middleware AND every middleware after it in * the chain are skipped (they never run); UPSTREAM middleware, already paused * at their own `await next()`, resume their post-`next()` work normally. It * does NOT continue at the next sibling middleware. Plugin middleware should * usually be swallowed so one bad plugin can't kill an agent run. */ export type PipelineErrorPolicy = 'rethrow' | 'swallow'; export interface PipelineErrorEvent { middleware: string; owner?: string | undefined; err: unknown; } export type PipelineErrorHandler = (ev: PipelineErrorEvent) => PipelineErrorPolicy | Promise; export interface Middleware { name: string; handler: MiddlewareHandler; owner?: string | undefined; } export interface PipelineOptions { /** When true and the target middleware is not found, operations silently no-op instead of throwing. */ optional?: boolean | undefined; } /** * Read-only view of a pipeline. Returned to consumers (plugins, hooks) * so they can inspect but not mutate the chain. */ export interface ReadonlyPipeline { readonly size: number; list(): readonly string[]; run(input: T): Promise; } export declare class Pipeline { private readonly chain; private errorHandler?; /** * Optional operational logger. When set, the `swallow` error-boundary path * emits a structured warning so a swallowed middleware crash is never * completely silent (P2 #7, before-release.md). Without a logger, the * swallow path still works but the crash is invisible — host code should * always wire one. */ private logger?; /** * Install an error boundary. When a middleware throws or rejects, the * handler is called and decides whether to swallow (continue with the * pre-handler value) or rethrow. Without a handler, errors propagate. * * Wire one per pipeline at boot — the host CLI typically installs a * single boundary that logs to the operational log and emits a * `pipeline.error` event for /diag. */ setErrorHandler(handler: PipelineErrorHandler | undefined): this; /** * Set the operational logger used by the swallow error-boundary path. * Without this, a swallowed middleware crash is completely silent. */ setLogger(logger: { warn: (msg: string, ctx?: unknown) => void | undefined; } | undefined): this; use(mw: Middleware | Middleware): this; prepend(mw: Middleware): this; /** * Insert middleware at an explicit index. Out-of-range indices are clamped. * Use this when insertBefore/insertAfter are insufficient (e.g. to place * a middleware at a known position regardless of named targets). */ insertAt(index: number, mw: Middleware): this; /** * Insert mw immediately before the first occurrence of target. * If called multiple times with the same target, each call inserts * before the target's current position — so after insertBefore('B', X) * then insertBefore('B', Y), the order is Y → X → B. */ insertBefore(target: string, mw: Middleware, opts?: PipelineOptions): this; /** * Insert mw immediately after the first occurrence of target. * If called multiple times with the same target, each call inserts * after the target's current position — so after insertAfter('B', X) * then insertAfter('B', Y), the order is B → X → Y. */ insertAfter(target: string, mw: Middleware, opts?: PipelineOptions): this; replace(target: string, mw: Middleware, opts?: PipelineOptions): this; remove(name: string, opts?: PipelineOptions): this; list(): readonly string[]; size(): number; /** Return a read-only view suitable for passing to plugins. */ asReadonly(): ReadonlyPipeline; run(input: T): Promise; private indexOf; private ensureUnique; } //# sourceMappingURL=pipeline.d.ts.map