/** * `PipelineClient` — pipeline DSL surface, refactored against the SDK 2.0 task primitive. * * The pipeline DSL chains user lambdas that typically call * `client.tasks.start(...)` under the hood. The 1.x pipeline runner * (which wrapped `QodoSDK.run`) is gone. * * The DSL is intentionally pure orchestration — each step is a TypeScript async * function. Steps that want to talk to QAR call `client.tasks.start(...)` * (exposed on the step context) and await the result. No new wire shape; * the pipeline runner is a state machine over a sequence of immutable * entries. * * The builder is immutable on each chain call so consumers can fork a * partial pipeline safely. */ import type { JsonObject } from '../qar/json.js'; import type { QodoClient } from './QodoClient.js'; /** * One step in a pipeline. The closure receives a typed context carrying the * accumulated state, the execution id, the step name, and the owning * {@link QodoClient}. Returning a JSON-shaped object patches the state for * downstream steps; returning `undefined` (or an empty object) leaves state * unchanged. * * Strict typing on the return is deliberate: pipeline state is a public * concept that consumer code inspects, so we don't widen to `any`. */ export type PipelineStepFn = (ctx: PipelineStepContext) => JsonObject | void | Promise; /** Context passed to each step's closure. */ export interface PipelineStepContext { /** Accumulated state from prior steps. */ readonly state: JsonObject; /** The pipeline's per-execution correlation id (UUIDv7-shaped). */ readonly executionId: string; /** Step name, set by the builder. */ readonly stepName: string; /** * The {@link QodoClient} the pipeline was built from. Exposed so step * closures can call `client.tasks.start(...)` (or any other sub-client) * without closing over an external variable. Matches the 1.x DSL convention * (`{ sdk, state }`). */ readonly client: QodoClient; } /** * A gate predicate evaluated between steps. The return value is coerced with * `Boolean(...)` — anything truthy continues the pipeline, anything falsy * stops it. Sync or async. * * Widened past `boolean` so consumers can write the natural JS shape * `gate(name, (s) => s.issues.length)` (a number) or * `gate(name, (s) => s.issues)` (an array) without an extra `!!` or * `=== true` cast. */ export type PipelineGateFn = (state: JsonObject) => unknown; /** * Per-step error strategy. * * - `fail-fast` (default) — step throws → `execute()` rethrows. * - `continue` — step throws → error is recorded on the step log and the * pipeline keeps going; state is not mutated by the failed step. * - `collect` — same as `continue`, plus the aggregated errors are exposed on * {@link PipelineResult.errors} for the caller to inspect after the run * completes. */ export type PipelineErrorStrategy = 'fail-fast' | 'continue' | 'collect'; /** Final result returned by `PipelineBuilder.execute()`. */ export interface PipelineResult { /** Final accumulated state after the last step ran (or the gate short-circuited). */ readonly state: JsonObject; /** Per-entry log in execution order. Parallel groups produce one entry per branch. */ readonly steps: readonly PipelineStepLog[]; /** * Errors collected under `collect` strategy, keyed by step name. Empty * array if no step failed or the strategy was `fail-fast` / `continue`. */ readonly errors: readonly PipelineStepError[]; /** * True if a gate predicate returned falsy and short-circuited execution. * Consumers can distinguish "gate stopped us" from "ran to completion". */ readonly gated: boolean; } /** Per-step execution record. */ export interface PipelineStepLog { readonly name: string; readonly success: boolean; readonly durationMs: number; readonly error?: string; } /** Collected-mode error record. */ export interface PipelineStepError { readonly name: string; readonly error: string; } /** Symbol key for the hook-bearing internal execute path. */ export declare const PIPELINE_TRACE_HOOKS: unique symbol; /** * Fluent builder. Each chain method returns a new instance — the builder is * structurally immutable so a consumer can fan out a base pipeline into * multiple variants. */ export declare class PipelineBuilder { /** * Reach this via {@link PipelineClient.build} — that's the public entry * point. The constructor signature stays exported (not strip-tagged) so * the published `.d.ts` carries a real `(client)` signature; without it, * the strip-tag compiler step would synthesize an implicit no-arg * `new PipelineBuilder()` for consumers, and pipelines built that way * would see `ctx.client === undefined`. The multi-arg chain-extension * shape lives on the private `cloneWith` helper so the internal * `PipelineEntry` type doesn't leak into the published declarations. */ constructor(client: QodoClient); /** Build a new builder that shares this builder's client but swaps in the supplied chain state. */ private cloneWith; /** Append a sequential step. */ step(name: string, fn: PipelineStepFn): PipelineBuilder; /** * Run a group of steps in parallel. Every branch sees the same input state; * branches that succeed contribute their returned patches to the merged * state in declaration order (later in the array wins on key conflicts). * Branch failures are governed by the *currently active* error strategy. */ parallel(steps: ReadonlyArray<{ readonly name: string; readonly fn: PipelineStepFn; }>): PipelineBuilder; /** * Insert a gate predicate. Falsy → pipeline short-circuits and `execute()` * resolves with `gated: true` and the current accumulated state. Truthy → * continue. */ gate(name: string, fn: PipelineGateFn): PipelineBuilder; /** * Set the per-step error strategy for subsequent steps. Doesn't retroactively * change strategies on entries already in the chain — each entry records the * strategy in effect at the moment it was appended. */ onError(strategy: PipelineErrorStrategy): PipelineBuilder; /** Execute the pipeline against the given initial state. */ execute(initialState?: JsonObject): Promise; private executeInternal; } /** * Entry point for the pipeline DSL. Reachable via `client.pipeline.build()`. */ export declare class PipelineClient { /** * Construction is intended for use by `QodoClient`; consumers reach a live * instance via `client.pipeline`. The constructor signature is kept * undecorated so the strip-tag compiler step doesn't erase it from the * published `.d.ts` — otherwise a synthesized no-arg constructor would let * consumers build a `PipelineClient` with no client reference, producing * pipelines whose steps see `ctx.client === undefined`. */ constructor(client: QodoClient); /** Construct a fresh `PipelineBuilder` bound to this client. */ build(): PipelineBuilder; } //# sourceMappingURL=PipelineClient.d.ts.map