pipeai 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts","../src/index.ts"],"sourcesContent":["import {\n generateText,\n streamText,\n tool,\n Output,\n type GenerateTextResult as AIGenerateTextResult,\n type StreamTextResult as AIStreamTextResult,\n type UIMessageStreamWriter,\n type ModelMessage,\n type LanguageModel,\n type Tool,\n type ToolSet,\n type StopCondition,\n type ToolChoice,\n type OnStepFinishEvent,\n type OnFinishEvent,\n} from \"ai\";\n\n// Extract the Output interface type from the Output.object return type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type OutputType<T = any> = ReturnType<typeof Output.object<T>>;\nimport type { ZodType } from \"zod\";\nimport { isToolProvider, TOOL_PROVIDER_BRAND, type IToolProvider } from \"./tool-provider\";\nimport { extractOutput, getActiveWriter, resolveValue, type MaybePromise, type Resolvable } from \"./utils\";\n\n// Tools config accepts both AI SDK tools and context-aware ToolProviders\ntype AgentToolSet<TContext> = Record<string, Tool | IToolProvider<TContext>>;\n\n// ── Result type aliases ─────────────────────────────────────────────\n\nexport type GenerateTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIGenerateTextResult<TOOLS, OUTPUT>;\nexport type StreamTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIStreamTextResult<TOOLS, OUTPUT>;\n\n/**\n * The result passed to `asTool` / `asToolProvider`'s `mapOutput`.\n *\n * The same agent may be invoked as a tool from a generate-mode parent\n * (returns `GenerateTextResult`, sync `.text`/`.output`) or from a\n * stream-mode parent (returns `StreamTextResult`, async `.text`/`.output`).\n * The callsite cannot statically tell which mode it is in, so `mapOutput`\n * receives the union and must `await` the relevant fields to support both.\n */\nexport type AsToolMapOutput<TOutput> = (\n result:\n | GenerateTextResult<ToolSet, OutputType<TOutput>>\n | StreamTextResult<ToolSet, OutputType<TOutput>>,\n) => MaybePromise<TOutput>;\n\n// ── AI SDK passthrough types ────────────────────────────────────────\n\n// Extract options types from both AI SDK entry points\ntype StreamTextOptions = Parameters<typeof streamText>[0];\ntype GenerateTextOptions = Parameters<typeof generateText>[0];\n\n// Keys we replace with resolvable or context-enriched versions\ntype ManagedKeys =\n | 'model' | 'system' | 'prompt' | 'messages'\n | 'tools' | 'activeTools' | 'toolChoice' | 'stopWhen'\n | 'output' | 'onFinish' | 'onStepFinish' | 'onError';\n\n// Combine options from both streamText and generateText.\n// Each side contributes its unique props; shared props merge naturally.\n// Stream-only props (onChunk, onAbort) are ignored by generateText.\n// Generate-only props (experimental_include.responseBody) are ignored by streamText.\ntype AIPassthroughOptions =\n Omit<StreamTextOptions, ManagedKeys> &\n Omit<GenerateTextOptions, ManagedKeys>;\n\n// ── Resolved config (output of resolveConfig / resolveConfigAsync) ──\n\ninterface ResolvedAgentConfig {\n model: LanguageModel;\n prompt: string | undefined;\n system: string | undefined;\n messages: ModelMessage[] | undefined;\n tools: Record<string, Tool>;\n activeTools: string[] | undefined;\n toolChoice: ToolChoice<ToolSet> | undefined;\n stopWhen: StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined;\n}\n\n// ── Agent Configuration ─────────────────────────────────────────────\n\nexport interface AgentConfig<\n TContext,\n TInput = void,\n TOutput = void,\n> extends AIPassthroughOptions {\n // ── Custom (not in AI SDK) ──\n id: string;\n description?: string;\n input?: ZodType<TInput>;\n output?: OutputType<TOutput>;\n /**\n * Zod schema used to validate `output` after the AI SDK returns. Distinct\n * from `tool.outputSchema` (AI SDK's tool-execution output schema): this\n * runs **after** the SDK has parsed structured output, as a runtime guard\n * against parse drift. If omitted, the parsed output is trusted as-is.\n */\n validateOutput?: ZodType<TOutput>;\n\n // ── Resolvable (our versions of AI SDK properties) ──\n model: Resolvable<TContext, TInput, LanguageModel>;\n system?: Resolvable<TContext, TInput, string>;\n prompt?: Resolvable<TContext, TInput, string>;\n messages?: Resolvable<TContext, TInput, ModelMessage[]>;\n tools?: Resolvable<TContext, TInput, AgentToolSet<TContext>>;\n activeTools?: Resolvable<TContext, TInput, string[]>;\n toolChoice?: Resolvable<TContext, TInput, ToolChoice<ToolSet>>;\n /**\n * Stop condition(s) for the tool loop. Pass either a single AI-SDK\n * `StopCondition` (which is itself a function) or an array of them.\n *\n * **Not a `Resolvable`.** A `StopCondition` and a `(ctx, input) => StopCondition`\n * resolver are both functions and cannot be safely distinguished at\n * runtime, so this field intentionally does NOT accept the resolver\n * form. If you need per-call dynamic stop conditions, build the agent\n * inside your handler instead of using a static instance.\n */\n stopWhen?: StopCondition<ToolSet> | Array<StopCondition<ToolSet>>;\n\n // ── Context-enriched callbacks (replace AI SDK versions) ──\n // `writer` is available when the agent runs inside a streaming workflow.\n onStepFinish?: (params: { result: OnStepFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onFinish?: (params: { result: OnFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onError?: (params: { error: unknown; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n}\n\n// ── Agent ───────────────────────────────────────────────────────────\n\nexport class Agent<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id: string;\n readonly description: string;\n readonly hasOutput: boolean;\n /**\n * Zod schema used to validate the agent's structured `output` after the AI\n * SDK returns. Distinct from `tool.outputSchema` (which validates tool\n * execution output). Exposed (readonly) so external runners — notably the\n * workflow runtime — can pass it through to `extractOutput` without\n * re-plumbing it.\n */\n readonly validateOutput: ZodType<TOutput> | undefined;\n private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n private readonly _passthrough: Record<string, unknown>;\n private readonly _onStepFinish: AgentConfig<TContext, TInput, TOutput>['onStepFinish'];\n private readonly _onFinish: AgentConfig<TContext, TInput, TOutput>['onFinish'];\n\n constructor(config: AgentConfig<TContext, TInput, TOutput>) {\n this.id = config.id;\n this.description = config.description ?? \"\";\n this.hasOutput = config.output !== undefined;\n this.validateOutput = config.validateOutput;\n this.config = config;\n // NOTE: `stopWhen` is intentionally excluded. A bare `StopCondition` is\n // itself a function (`({ steps }) => boolean`), so the typeof-function\n // resolver heuristic in `resolveValue` would misidentify it as a\n // `(ctx, input) => ...` Resolvable and call it with the wrong shape.\n // For `stopWhen` we always treat a function value as a static\n // StopCondition; dynamic stopWhen must return an array\n // (`(ctx, input) => [stepCountIs(5)]`), which is the unambiguous form.\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice,\n ].some(v => typeof v === \"function\");\n\n // Cache tools when config is static and contains no ToolProviders.\n // Avoids re-iterating the tools map on every generate()/stream() call.\n if (!this._hasDynamicConfig) {\n const rawTools = (config.tools as AgentToolSet<TContext> | undefined) ?? {};\n const hasProvider = Object.values(rawTools).some(v => isToolProvider(v));\n if (!hasProvider) {\n this._resolvedStaticTools = rawTools as Record<string, Tool>;\n }\n }\n\n // Pre-compute the passthrough (AI SDK options we don't manage) once,\n // rather than destructuring on every generate()/stream() call.\n const {\n id: _id, description: _desc, input: _inputSchema, output: _output, validateOutput: _validateOutput,\n model: _m, system: _s, prompt: _p, messages: _msg,\n tools: _t, activeTools: _at, toolChoice: _tc, stopWhen: _sw,\n onStepFinish, onFinish, onError: _onError,\n ...passthrough\n } = config;\n this._passthrough = passthrough;\n this._onStepFinish = onStepFinish;\n this._onFinish = onFinish;\n }\n\n async generate(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: { abortSignal?: AbortSignal }]\n : [input: TInput, options?: { abortSignal?: AbortSignal }]\n ): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const callOptions = args[1] as { abortSignal?: AbortSignal } | undefined;\n return this.generateWithOptions(ctx, input, callOptions ?? {});\n }\n\n async stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: { abortSignal?: AbortSignal }]\n : [input: TInput, options?: { abortSignal?: AbortSignal }]\n ): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const callOptions = args[1] as { abortSignal?: AbortSignal } | undefined;\n return this.streamWithOptions(ctx, input, callOptions ?? {});\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: AsToolMapOutput<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: AsToolMapOutput<TOutput>;\n }): IToolProvider<TContext> {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asToolProvider() requires an input schema`);\n }\n\n return {\n [TOOL_PROVIDER_BRAND]: true as const,\n createTool: (ctx: Readonly<TContext>) => this.createToolInstance(ctx as TContext, options),\n };\n }\n\n private createToolInstance(ctx: TContext, options?: {\n mapOutput?: AsToolMapOutput<TOutput>;\n }): Tool {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asTool() requires an input schema`);\n }\n\n return tool<TInput, TOutput>({\n description: this.description,\n inputSchema: this.config.input,\n // The AI SDK passes a `ToolExecutionOptions` argument that carries\n // `abortSignal`, `toolCallId`, `messages`, etc. Forward `abortSignal` so\n // a parent agent's abort cancels in-flight sub-agent calls instead of\n // leaving them running and producing detached output.\n execute: async (toolInput: TInput, execOptions?: { abortSignal?: AbortSignal }) => {\n const abortSignal = execOptions?.abortSignal;\n // When inside a streaming workflow, automatically use stream() and merge to the active writer.\n // Otherwise fall back to generate().\n const writer = getActiveWriter();\n if (writer) {\n const result = await this.streamWithOptions(ctx, toolInput, { abortSignal });\n writer.merge(result.toUIMessageStream());\n // Drain the text side to release the StreamTextResult anchor — the\n // writer.merge above only consumes the UI-message side, leaving\n // `result.text` pending until awaited.\n //\n // When mapOutput is provided, we explicitly do NOT call extractOutput\n // here: extractOutput throws if `hasOutput` is true but the model\n // returned no structured value, which would block any mapOutput that\n // wanted to recover from missing/malformed structured output by\n // reading `result.text`. mapOutput becomes the user's chance to do\n // their own extraction.\n if (options?.mapOutput) {\n await result.text;\n return options.mapOutput(result);\n }\n return extractOutput(result, this.hasOutput, this.validateOutput);\n }\n const result = await this.generateWithOptions(ctx, toolInput, { abortSignal });\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput, this.validateOutput);\n },\n // TS cannot simplify the SDK's `NeverOptional<TOutput, ...>` conditional in a\n // generic context, so we cast through `unknown` instead of `any`.\n } as unknown as Tool<TInput, TOutput>);\n }\n\n // ── Internal: shared call helpers ─────────────────────────────\n // `generate()` / `stream()` and the `asTool()` wrapper all funnel through\n // these so the abortSignal-forwarding and onError-wrapping logic stays in\n // one place. `extra` carries per-call overrides (currently `abortSignal`).\n\n // If the user-supplied onError callback itself throws, attach the original\n // model error as `.cause` on the new error and rethrow the wrapper. Without\n // this, the original error is silently shadowed.\n private async invokeOnError(error: unknown, ctx: TContext, input: TInput): Promise<void> {\n if (!this.config.onError) return;\n try {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n } catch (handlerError) {\n // Promote non-Error throws (`throw \"boom\"`, `throw 42`, etc.) so we\n // can chain the original error onto a real Error and keep diagnostics\n // intact. Re-throwing the raw non-Error value would drop the chain.\n if (handlerError instanceof Error) {\n if (handlerError.cause === undefined) {\n (handlerError as { cause?: unknown }).cause = error;\n }\n throw handlerError;\n }\n const wrapped = new Error(\n `Agent \"${this.id}\": onError handler threw a non-Error value (${typeof handlerError}): ${String(handlerError)}`,\n );\n (wrapped as { cause?: unknown }).cause = error;\n throw wrapped;\n }\n }\n\n private async generateWithOptions(\n ctx: TContext,\n input: TInput,\n extra: { abortSignal?: AbortSignal },\n ): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n try {\n // The SDK's `Output.object<T>` return type doesn't simplify generically\n // — cast through `unknown` rather than `any` so we keep the boundary\n // narrow without forcing the call site to know SDK option internals.\n return (await generateText({ ...options, ...extra } as unknown as Parameters<typeof generateText>[0])) as GenerateTextResult<ToolSet, OutputType<TOutput>>;\n } catch (error: unknown) {\n await this.invokeOnError(error, ctx, input);\n throw error;\n }\n }\n\n private async streamWithOptions(\n ctx: TContext,\n input: TInput,\n extra: { abortSignal?: AbortSignal },\n ): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n try {\n // Only attach `onError` when the user supplied one. Setting it to\n // `undefined` explicitly suppresses some SDK versions' default\n // rethrow-on-partial-stream-error, silently swallowing stream failures.\n const onErrorOption = this.config.onError\n ? { onError: ({ error }: { error: unknown }) => this.invokeOnError(error, ctx, input) }\n : {};\n return streamText({\n ...options,\n ...extra,\n ...onErrorOption,\n } as unknown as Parameters<typeof streamText>[0]) as StreamTextResult<ToolSet, OutputType<TOutput>>;\n } catch (error: unknown) {\n // streamText typically defers errors to the returned stream, but a\n // synchronous throw (e.g., invalid options) would otherwise bypass\n // onError entirely.\n await this.invokeOnError(error, ctx, input);\n throw error;\n }\n }\n\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, unknown> {\n if (resolved.messages === undefined && resolved.prompt === undefined) {\n throw new Error(\n `Agent \"${this.id}\": neither \\`prompt\\` nor \\`messages\\` was provided. ` +\n `Configure one of them, or supply a Resolvable that returns one based on input.`,\n );\n }\n return {\n ...this._passthrough,\n model: resolved.model,\n tools: resolved.tools,\n activeTools: resolved.activeTools,\n toolChoice: resolved.toolChoice,\n stopWhen: resolved.stopWhen,\n ...(resolved.messages !== undefined\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt }),\n // Use `!== undefined` rather than truthy so an intentional empty\n // `system: \"\"` survives instead of being silently dropped.\n ...(resolved.system !== undefined ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n // Only attach the callback when the user supplied one. Passing\n // `undefined` explicitly can suppress default SDK rethrow behavior in\n // some versions.\n ...(this._onStepFinish\n ? { onStepFinish: (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() }) }\n : {}),\n ...(this._onFinish\n ? { onFinish: (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() }) }\n : {}),\n };\n }\n\n private resolveConfig(ctx: TContext, input: TInput): ResolvedAgentConfig | Promise<ResolvedAgentConfig> {\n if (!this._hasDynamicConfig) {\n return {\n model: this.config.model as LanguageModel,\n prompt: this.config.prompt as string | undefined,\n system: this.config.system as string | undefined,\n messages: this.config.messages as ModelMessage[] | undefined,\n tools: this._resolvedStaticTools ?? this.resolveTools(\n (this.config.tools as AgentToolSet<TContext> | undefined) ?? {}, ctx\n ),\n activeTools: this.config.activeTools as string[] | undefined,\n toolChoice: this.config.toolChoice as ToolChoice<ToolSet> | undefined,\n stopWhen: this.config.stopWhen as StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined,\n };\n }\n return this.resolveConfigAsync(ctx, input);\n }\n\n private async resolveConfigAsync(ctx: TContext, input: TInput): Promise<ResolvedAgentConfig> {\n const [model, prompt, system, messages, rawTools, activeTools, toolChoice] = await Promise.all([\n resolveValue(this.config.model, ctx, input),\n resolveValue(this.config.prompt, ctx, input),\n resolveValue(this.config.system, ctx, input),\n resolveValue(this.config.messages, ctx, input),\n resolveValue(this.config.tools, ctx, input),\n resolveValue(this.config.activeTools, ctx, input),\n resolveValue(this.config.toolChoice, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return {\n model,\n prompt,\n system,\n messages,\n tools,\n activeTools,\n toolChoice,\n // `stopWhen` is always static — see field declaration for why.\n stopWhen: this.config.stopWhen,\n };\n }\n\n private resolveTools(\n tools: AgentToolSet<TContext>,\n ctx: TContext\n ): Record<string, Tool> {\n const entries = Object.entries(tools);\n if (entries.length === 0) return tools as Record<string, Tool>;\n let hasProvider = false;\n const resolved: Record<string, Tool> = {};\n for (const [key, toolOrProvider] of entries) {\n if (isToolProvider<TContext>(toolOrProvider)) {\n hasProvider = true;\n resolved[key] = toolOrProvider.createTool(ctx as Readonly<TContext>);\n } else {\n resolved[key] = toolOrProvider as Tool;\n }\n }\n return hasProvider ? resolved : (tools as Record<string, Tool>);\n }\n}\n","import { tool, type Tool, type ToolExecutionOptions, type FlexibleSchema, type UIMessageStreamWriter } from \"ai\";\nimport { getActiveWriter } from \"./utils\";\n\nexport const TOOL_PROVIDER_BRAND = Symbol.for(\"agent-workflow.ToolProvider\");\n\nexport type ToolExecuteOptions = ToolExecutionOptions & {\n writer?: UIMessageStreamWriter;\n};\n\ntype ToolProviderOptions = NonNullable<Tool[\"providerOptions\"]>;\n\nexport type ToolProviderConfig<TContext, TInput, TOutput> = {\n description?: string;\n input: FlexibleSchema<TInput>;\n outputSchema?: FlexibleSchema<TOutput>;\n providerOptions?: ToolProviderOptions;\n execute: (input: TInput, ctx: Readonly<TContext>, options: ToolExecuteOptions) => Promise<TOutput>;\n};\n\nexport interface IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND]: true;\n createTool(context: Readonly<TContext>): Tool;\n}\n\nexport class ToolProvider<\n TContext,\n TInput = unknown,\n TOutput = unknown,\n> implements IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND] = true as const;\n private readonly config: ToolProviderConfig<TContext, TInput, TOutput>;\n\n constructor(config: ToolProviderConfig<TContext, TInput, TOutput>) {\n this.config = config;\n }\n\n createTool(context: Readonly<TContext>): Tool {\n const { execute, input: inputSchema, ...toolDef } = this.config;\n // The shape matches `Tool<TInput, TOutput>`, but TS cannot simplify the SDK's\n // `NeverOptional<TOutput, ...>` conditional in a generic context, so the literal\n // is not assignable directly. Cast through `unknown` rather than `any` so the\n // return type and call sites still get type-checked.\n return tool<TInput, TOutput>({\n ...toolDef,\n inputSchema,\n execute: (input: TInput, options: ToolExecutionOptions) => execute(input, context, { ...options, writer: getActiveWriter() } as ToolExecuteOptions),\n } as unknown as Tool<TInput, TOutput>);\n }\n}\n\nexport function defineTool<TContext>() {\n return <TInput, TOutput>(\n config: ToolProviderConfig<TContext, TInput, TOutput>\n ): ToolProvider<TContext, TInput, TOutput> => new ToolProvider(config);\n}\n\nexport function isToolProvider<TContext>(obj: unknown): obj is IToolProvider<TContext> {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n TOOL_PROVIDER_BRAND in obj\n );\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createHash } from \"node:crypto\";\nimport type { UIMessageStreamWriter } from \"ai\";\nimport type { ZodType } from \"zod\";\n\n// ── Stream writer context ────────────────────────────────────────────\n// Invisible to the user. The workflow sets the writer before agent execution;\n// tools and sub-agents read it automatically via getActiveWriter().\n\nconst writerStorage = new AsyncLocalStorage<UIMessageStreamWriter>();\n\nexport function runWithWriter<T>(writer: UIMessageStreamWriter, fn: () => T): T {\n return writerStorage.run(writer, fn);\n}\n\n/**\n * Returns the active `UIMessageStreamWriter` if the current async context is\n * running inside a streaming workflow, or `undefined` otherwise.\n *\n * Use from inside a custom `IToolProvider`'s returned `Tool.execute` callback\n * to forward incremental output to the workflow's UI message stream:\n *\n * ```ts\n * import { getActiveWriter, type IToolProvider, TOOL_PROVIDER_BRAND } from \"pipeai\";\n *\n * const myProvider: IToolProvider<MyCtx> = {\n * [TOOL_PROVIDER_BRAND]: true,\n * createTool(ctx) {\n * return tool({\n * execute: async (input) => {\n * const writer = getActiveWriter();\n * // ...stream incremental progress to writer if present...\n * return result;\n * },\n * });\n * },\n * };\n * ```\n *\n * **Important timing note:** call this from *inside* the `Tool.execute`\n * callback, not from inside `createTool` itself. `createTool` runs during\n * agent setup (before the workflow has set the writer); `Tool.execute` runs\n * during tool invocation (when the writer is live).\n */\nexport function getActiveWriter(): UIMessageStreamWriter | undefined {\n return writerStorage.getStore();\n}\n\n// ── Common types ─────────────────────────────────────────────────────\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * A value that can be static or derived from context and input.\n * Used for agent config fields that may need runtime resolution.\n *\n * Functions may return a Promise for async resolution; static values are always sync.\n */\nexport type Resolvable<TCtx, TInput, TValue> =\n | TValue\n | ((ctx: Readonly<TCtx>, input: TInput) => TValue | Promise<TValue>);\n\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue>,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue>;\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue> | undefined,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue> | undefined {\n if (typeof value === \"function\") {\n return (value as (ctx: TCtx, input: TInput) => TValue | Promise<TValue>)(ctx, input);\n }\n return value;\n}\n\n/**\n * Minimal counting semaphore. Up to `permits` callers can hold a permit\n * concurrently; further `acquire()` calls queue FIFO until one is released.\n */\nexport class Semaphore {\n private available: number;\n private waiters: Array<() => void> = [];\n\n constructor(permits: number) {\n if (!Number.isInteger(permits) || permits < 1) {\n throw new Error(`Semaphore: permits must be a positive integer, got ${permits}`);\n }\n this.available = permits;\n }\n\n async acquire(): Promise<void> {\n if (this.available > 0) {\n this.available--;\n return;\n }\n await new Promise<void>(resolve => this.waiters.push(resolve));\n }\n\n release(): void {\n const next = this.waiters.shift();\n if (next) next();\n else this.available++;\n }\n}\n\n/**\n * Extract structured output from an AI SDK result.\n *\n * - When `hasStructuredOutput` is `true`, awaits `result.output`. If the SDK\n * did not produce a structured value, this throws — silent fall-back to raw\n * text would mask schema mismatches at the call site.\n * - When `schema` is provided, the awaited output is validated through the\n * Zod schema before being returned, catching SDK-side parse drift.\n * - When `hasStructuredOutput` is `false`, returns `result.text`.\n *\n * Works for both generate (sync .output/.text) and stream (async .output/.text) results.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function extractOutput(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result: any,\n hasStructuredOutput: boolean,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema?: ZodType<any>,\n): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output === undefined) {\n throw new Error(\n \"Agent: structured output was declared but the model returned none. \" +\n \"This usually means the model produced text that did not match the declared schema, \" +\n \"or the underlying SDK did not parse the structured output.\",\n );\n }\n if (schema) {\n return schema.parse(output);\n }\n return output;\n }\n return await result.text;\n}\n\n/**\n * Recursively freeze an object graph. Cycles are tracked via a WeakSet so we\n * never recurse into the same node twice. Maps/Sets stay structurally frozen\n * but `.set()`/`.add()` still mutate them — Object.freeze doesn't cover those.\n */\nexport function deepFreeze<T>(value: T, seen: WeakSet<object> = new WeakSet()): T {\n if (value === null || typeof value !== \"object\" || seen.has(value as object)) return value;\n // Already-frozen subtree (e.g. user-passed frozen ctx) — its children are\n // either also frozen or intentionally mutable, either way we should not recurse.\n if (Object.isFrozen(value)) return value;\n seen.add(value as object);\n Object.freeze(value);\n for (const key of Reflect.ownKeys(value as object)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n deepFreeze((value as any)[key], seen);\n }\n return value;\n}\n\n// ── stepShapeHash (F1) ───────────────────────────────────────────────\n//\n// Recursive SHA-256 of the workflow's structural shape (index, type, id,\n// nested workflow shapes). Used by checkpoint resume to detect drift —\n// when the user inserts/removes/reorders a step, the hash changes and\n// resume refuses to continue unless explicitly told to via\n// `{ skipShapeCheck: true }`.\n//\n// **Agent identity is NOT in the hash.** Two checkpoints from runs that\n// used different agent configs (same id) hash identically. Version agents\n// by content if resume-trust matters.\n\n/**\n * The minimal shape interface this util needs from a `SealedWorkflow`.\n * Importing the workflow class here would create a circular dependency\n * (utils.ts ← workflow.ts and workflow.ts ← utils.ts); so we accept any\n * object exposing `id` and `getStepsForShapeHash()`.\n */\nexport interface WorkflowShapeHashable {\n readonly id?: string;\n // Returns the StepNode[] for this workflow. Structurally typed to avoid\n // a circular import — the real type is `ReadonlyArray<StepNode>`.\n getStepsForShapeHash(): ReadonlyArray<StepNodeShape>;\n}\n\n/**\n * Structural typing for a StepNode as seen by the shape hasher. Mirrors\n * the actual `StepNode` union without importing it. Adding fields to\n * StepNode without updating this contract won't fail compilation; the\n * dispatch map in workflow.ts (typed via `Record<StepNode[\"type\"], ...>`)\n * is the load-bearing exhaustiveness guard.\n */\nexport interface StepNodeShape {\n readonly type: string;\n readonly id: string;\n}\n\nexport function computeStepShapeHash(\n steps: ReadonlyArray<StepNodeShape>,\n getNested: (node: StepNodeShape) => readonly WorkflowShapeHashable[],\n): string {\n return createHash(\"sha256\").update(canonicalDescriptor(steps, getNested, new WeakSet())).digest(\"hex\");\n}\n\n/**\n * `path` tracks the current DFS stack only — added on entry, removed on exit.\n * Sibling re-visits of the same SealedWorkflow are NOT cycles (shared\n * subgraphs hash identically to two structurally-equivalent distinct\n * instances). Only ancestor re-visits (true cycles) emit the cycle marker.\n */\nfunction canonicalDescriptor(\n steps: ReadonlyArray<StepNodeShape>,\n getNested: (node: StepNodeShape) => readonly WorkflowShapeHashable[],\n path: WeakSet<WorkflowShapeHashable>,\n): string {\n return JSON.stringify(steps.map((s, i) => {\n const triple: (number | string)[] = [i, s.type, s.id];\n for (const inner of getNested(s)) {\n if (path.has(inner)) {\n triple.push(`<cycle:${inner.id ?? \"anon\"}>`);\n continue;\n }\n path.add(inner);\n try {\n triple.push(canonicalDescriptor(inner.getStepsForShapeHash(), getNested, path));\n } finally {\n path.delete(inner);\n }\n }\n return triple;\n }));\n}\n\n// ── warnOnce (F1) — module-level dedup helper ────────────────────────\n\nconst warnedOnceKeys = new Set<string>();\nexport function warnOnce(key: string, message?: string): void {\n if (warnedOnceKeys.has(key)) return;\n warnedOnceKeys.add(key);\n // eslint-disable-next-line no-console\n console.warn(message ?? key);\n}\n\n/**\n * @internal — test-only reset of the warnOnce dedup. Same shape as\n * workflow.ts's `__resetStreamOnErrorOnSuspendWarnForTests`.\n */\nexport function __resetWarnOnceForTests(): void {\n warnedOnceKeys.clear();\n}\n","import {\n createUIMessageStream,\n type UIMessageStreamWriter,\n type ToolSet,\n} from \"ai\";\nimport { type Agent, type GenerateTextResult, type StreamTextResult, type OutputType } from \"./agent\";\nimport { computeStepShapeHash, deepFreeze, extractOutput, runWithWriter, warnOnce, type MaybePromise } from \"./utils\";\n\n// ── Error Types ─────────────────────────────────────────────────────\n\nexport class WorkflowBranchError extends Error {\n constructor(\n public readonly branchType: \"predicate\" | \"select\",\n message: string,\n ) {\n super(message);\n this.name = \"WorkflowBranchError\";\n }\n}\n\nexport class WorkflowLoopError extends Error {\n constructor(\n public readonly iterations: number,\n public readonly maxIterations: number,\n ) {\n super(`Loop exceeded maximum iterations (${maxIterations})`);\n this.name = \"WorkflowLoopError\";\n }\n}\n\nexport class NestedGateUnsupportedError extends Error {\n readonly gateId: string;\n readonly workflowId: string | undefined;\n // Always present; non-gate rejections from concurrent foreach.\n readonly siblingErrors: readonly unknown[];\n // Always present; OTHER suspending items in concurrent foreach.\n readonly siblingSuspensions: readonly { index: number; gateId: string }[];\n\n constructor(\n gateId: string,\n workflowId: string | undefined,\n siblingErrors: readonly unknown[] = [],\n siblingSuspensions: readonly { index: number; gateId: string }[] = [],\n ) {\n super(`Gate \"${gateId}\" hit inside nested workflow \"${workflowId ?? \"(anonymous)\"}\". Nested gates are not yet supported.`);\n this.name = \"NestedGateUnsupportedError\";\n this.gateId = gateId;\n this.workflowId = workflowId;\n this.siblingErrors = siblingErrors;\n this.siblingSuspensions = siblingSuspensions;\n }\n}\n\n// ── Snapshot / Warnings / Run options ────────────────────────────────\n\n/**\n * v2 gate snapshot. The `kind` discriminant differentiates it from\n * checkpoint snapshots. The legacy v1 form is still accepted by `loadState`.\n */\nexport interface GateSnapshot {\n readonly version: 2;\n readonly kind: \"gate\";\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\n/**\n * v2 checkpoint snapshot. Carries a step-shape hash; resume verifies the\n * workflow definition hasn't drifted before continuing.\n */\nexport interface CheckpointSnapshot {\n readonly version: 2;\n readonly kind: \"checkpoint\";\n readonly resumeFromIndex: number; // index of the NEXT step to run\n readonly output: unknown;\n readonly stepShapeHash: string; // SHA-256 hex of canonical recursive shape\n}\n\n/**\n * Legacy v0.4.0 gate-only snapshot. Accepted by `loadState` for one release\n * via the shim path. `kind?: undefined` makes runtime narrowing on\n * `kind === undefined` reachable — JSON round-trips strip the property.\n * Migrate via `migrateSnapshot()` before v0.8.0+.\n */\nexport interface LegacyGateSnapshotV1 {\n readonly version: 1;\n readonly kind?: undefined;\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\nexport type WorkflowSnapshot = GateSnapshot | CheckpointSnapshot | LegacyGateSnapshotV1;\n\nexport interface WorkflowWarning {\n readonly source:\n | \"step\"\n | \"finally\"\n | \"catch\"\n | \"onCheckpoint\"\n | \"onStepStart\"\n | \"onStepFinish\"\n | \"onStepError\"\n | \"foreach-sibling\";\n readonly stepId: string;\n readonly error: unknown;\n}\n\nexport type WorkflowStepType =\n | \"step\"\n | \"nested\"\n | \"gate\"\n | \"catch\"\n | \"finally\"\n | \"branch\"\n | \"foreach\"\n | \"repeat\"\n | \"parallel\";\n\n/**\n * Workflow observability hooks. All optional. Errors thrown inside hooks\n * are captured into `result.warnings` with a matching `source` tag, except\n * `onStepError`, which causes the run to throw the ORIGINAL step error with\n * `error.cause = obsError` (preserving `instanceof` on the original).\n *\n * Per-node firing rules (where \"step-like\" = step / nested / branch /\n * foreach / parallel / repeat):\n * - step-like / gate (cond-true → suspends): onStepStart always; onStepFinish\n * when body returns (suspended: true for gate, false otherwise); onStepError\n * on body throw.\n * - gate (cond false → skip): onStepStart, onStepFinish({ suspended: false }).\n * - catch: onStepStart only when pendingError set; onStepFinish when catchFn\n * returns; onStepError when catchFn throws.\n * - finally: onStepStart always (runs even after suspension); onStepFinish\n * always; onStepError when body throws.\n * - foreach / parallel: emit ALSO per-item events (onItemStart/Finish/Error).\n * - repeat: emit ONLY combinator-level events (no per-iteration events —\n * iteration count is data-dependent and per-item would be misleading).\n *\n * Skip-checked nodes (`state.suspension || pendingError` already set on entry)\n * emit nothing — `.finally()` is the exception.\n */\nexport interface WorkflowObservability {\n onStepStart?: (event: {\n stepId: string;\n type: WorkflowStepType;\n ctx: unknown;\n input: unknown;\n }) => MaybePromise<void>;\n onStepFinish?: (event: {\n stepId: string;\n type: WorkflowStepType;\n ctx: unknown;\n output: unknown;\n durationMs: number;\n suspended: boolean;\n }) => MaybePromise<void>;\n onStepError?: (event: {\n stepId: string;\n type: WorkflowStepType;\n ctx: unknown;\n error: unknown;\n durationMs: number;\n }) => MaybePromise<void>;\n onItemStart?: (event: {\n stepId: string;\n type: \"foreach\" | \"parallel\";\n itemIndex: number | string;\n ctx: unknown;\n input: unknown;\n }) => MaybePromise<void>;\n onItemFinish?: (event: {\n stepId: string;\n type: \"foreach\" | \"parallel\";\n itemIndex: number | string;\n ctx: unknown;\n output: unknown;\n durationMs: number;\n }) => MaybePromise<void>;\n onItemError?: (event: {\n stepId: string;\n type: \"foreach\" | \"parallel\";\n itemIndex: number | string;\n ctx: unknown;\n error: unknown;\n durationMs: number;\n }) => MaybePromise<void>;\n}\n\nexport interface RunOptions {\n /**\n * Step-level checkpoint sink. Called after each successful step body when\n * `checkpointEvery` cadence or `checkpointWhen` predicate fires. Receives a\n * v2 `CheckpointSnapshot` and an `AbortSignal` that aborts on\n * `checkpointTimeout` expiration. Throwing here propagates to the caller\n * as an error — workflow `.catch()` is bypassed for checkpoint failures.\n */\n readonly onCheckpoint?: (snapshot: CheckpointSnapshot, opts: { signal: AbortSignal }) => MaybePromise<void>;\n /**\n * Fire `onCheckpoint` every N executable steps. Mutually exclusive with\n * `checkpointWhen`. Default: `max(1, ceil(executableCount / 4))` —\n * 4 checkpoints across the run, with a floor of every step on tiny pipelines.\n */\n readonly checkpointEvery?: number;\n /**\n * Predicate variant — fire `onCheckpoint` exactly when this returns true.\n * Mutually exclusive with `checkpointEvery`.\n */\n readonly checkpointWhen?: (params: { stepIndex: number; stepId: string; ctx: unknown }) => boolean;\n /**\n * When truthy, deeply freeze the gate / checkpoint snapshot and the\n * `result.warnings` array. Default false. Pass `\"iAcceptThePerformanceCost\"`\n * to bypass `validateRunOptions`' catastrophic-combo guard\n * (freezeSnapshots: true + checkpointEvery: 1 + steps.length >= 8).\n */\n readonly freezeSnapshots?: boolean | \"iAcceptThePerformanceCost\";\n /**\n * Cooperative cancellation signal. Checked at every step boundary inside\n * `execute()` and forwarded to agent calls in `executeAgent`, foreach\n * workers, and nested workflows. When the signal aborts, the workflow\n * tears down to `signal.reason` via the same pending-error path as any\n * other step failure, so `.catch()` handlers still get a chance to\n * observe (or recover from) the abort. `.finally()` bodies still run\n * on the abort path. Unlike `freezeSnapshots`, this option DOES\n * propagate into nested workflows, foreach items, and repeat loops —\n * cancellation should be transitive.\n */\n readonly abortSignal?: AbortSignal;\n /**\n * Maximum ms `onCheckpoint` is allowed to run before its AbortSignal fires.\n * On timeout, a `CheckpointTimeoutError` is raised on the run (catch is\n * bypassed; original error reaches the caller). Default: no timeout.\n */\n readonly checkpointTimeout?: number;\n}\n\n/**\n * Synthetic step id reported when `onCheckpoint` itself throws. Reserved\n * via the construction-time `(type, id)` walk — user step ids may not\n * contain the `::pipeai::` namespace.\n */\nexport const CHECKPOINT_STEP_ID = \"::pipeai::onCheckpoint\" as const;\n\n/**\n * Thrown internally when `onCheckpoint` exceeds `RunOptions.checkpointTimeout`.\n * Surfaces to the caller as the rejection error.\n */\nexport class CheckpointTimeoutError extends Error {\n readonly timeoutMs: number;\n constructor(timeoutMs: number) {\n super(`onCheckpoint exceeded ${timeoutMs}ms timeout`);\n this.name = \"CheckpointTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\nfunction resolveFreezeSnapshots(state: RuntimeState): boolean {\n return state.runOptions?.freezeSnapshots ? true : false;\n}\n\n/**\n * Convert a legacy v1 gate snapshot to a v2 gate snapshot. Long-lived\n * storage (Redis-without-TTL, S3, Postgres) should re-serialize via this\n * helper before v0.8.0+ drops v1 acceptance.\n */\nexport function migrateSnapshot(legacy: LegacyGateSnapshotV1): GateSnapshot {\n if (legacy.version !== 1) {\n throw new Error(`migrateSnapshot: expected v1 snapshot, got version ${(legacy as { version: number }).version}`);\n }\n return {\n version: 2,\n kind: \"gate\",\n resumeFromIndex: legacy.resumeFromIndex,\n output: legacy.output,\n gateId: legacy.gateId,\n gatePayload: legacy.gatePayload,\n };\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\n/**\n * Discriminated union describing one agent invocation's result.\n *\n * - `mode: \"generate\"` — `result` is a `GenerateTextResult`; `.text`, `.output`,\n * `.usage` etc. are synchronous (already-resolved).\n * - `mode: \"stream\"` — `result` is a `StreamTextResult`; the same fields are\n * `Promise`s that you must `await` before reading.\n *\n * The shared field set (`ctx`, `input`) is identical across both modes;\n * narrowing on `mode` is only necessary when you need to touch a\n * mode-specific shape.\n */\nexport type AgentResultParams<TContext, TOutput, TNextOutput> =\n | {\n readonly mode: \"generate\";\n readonly result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>;\n readonly ctx: Readonly<TContext>;\n readonly input: TOutput;\n }\n | {\n readonly mode: \"stream\";\n readonly result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;\n readonly ctx: Readonly<TContext>;\n readonly input: TOutput;\n };\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n /**\n * Transform the agent's result into the next step's input. Fires once per\n * step regardless of generate-vs-stream mode; discriminate on `mode` if you\n * need a mode-specific field. Returning the agent's `result.text` works\n * for both modes (string vs Promise<string>) because `MaybePromise` accepts\n * either.\n *\n * If omitted, the workflow's default extraction is used:\n * - With `agent.output` declared → `extractOutput(result, agent.validateOutput)`\n * - Without `agent.output` → `result.text` (awaited if stream)\n */\n mapResult?: (params: AgentResultParams<TContext, TOutput, TNextOutput>) => MaybePromise<TNextOutput>;\n\n /**\n * Observe the agent's result without changing the step's downstream value.\n * Fires once per step regardless of mode. Use for logging, telemetry,\n * usage accounting, side-effects that should not affect pipeline data\n * flow.\n */\n onResult?: (params: AgentResultParams<TContext, TOutput, TNextOutput>) => MaybePromise<void>;\n\n /**\n * **Stream-mode only.** Override the workflow's default\n * `writer.merge(result.toUIMessageStream())` call so YOU control how the\n * agent's stream reaches the outer workflow's UI message stream. Useful\n * for buffering, transforming, fan-out to multiple writers, or injecting\n * custom UI messages around the agent's output.\n *\n * Has no generate-mode analog because in generate mode there is no stream\n * to merge. If both `handleStream` and `mapResult`/`onResult` are\n * configured, `handleStream` runs first.\n */\n handleStream?: (params: {\n result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;\n writer: UIMessageStreamWriter;\n ctx: Readonly<TContext>;\n }) => MaybePromise<void>;\n}\n\n// ── Step Options ────────────────────────────────────────────────────\n\nexport type StepOptions<TContext, TOutput, TNextOutput> = AgentStepHooks<TContext, TOutput, TNextOutput> & {\n /** Override the default step id (`agent.id`). Required when reusing the same\n * agent across multiple steps in one workflow — the construction-time\n * `(type, id)` walk rejects duplicates. */\n id?: string;\n};\n\n// ── Branch Types ────────────────────────────────────────────────────\n\nexport interface BranchCase<TContext, TOutput, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n when?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n agent: Agent<TContext, TOutput, TNextOutput>;\n}\n\nexport interface BranchSelect<TContext, TOutput, TKeys extends string, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n select: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TKeys>;\n agents: Record<TKeys, Agent<TContext, TOutput, TNextOutput>>;\n fallback?: Agent<TContext, TOutput, TNextOutput>;\n /**\n * Diagnostic hook invoked when `select` returns a key that has no matching\n * entry in `agents`. Fires BEFORE `fallback` is applied or\n * `WorkflowBranchError` is thrown, regardless of whether a `fallback` is\n * configured. Useful for logging typos / unexpected classifier output.\n */\n onUnknownKey?: (params: { key: string; availableKeys: TKeys[]; ctx: Readonly<TContext> }) => void;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport type WorkflowResult<TOutput> =\n | { readonly status: \"complete\"; readonly output: TOutput; readonly warnings: readonly WorkflowWarning[] }\n | { readonly status: \"suspended\"; readonly snapshot: GateSnapshot; readonly warnings: readonly WorkflowWarning[] };\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<WorkflowResult<TOutput>>; // never rejects on suspension; rejects on real errors\n}\n\nexport interface WorkflowStreamOptions {\n onError?: (error: unknown) => string;\n onFinish?: () => MaybePromise<void>;\n}\n\n// ── Loop Types ──────────────────────────────────────────────────────\n\ntype LoopPredicate<TContext, TOutput> = (params: {\n output: TOutput;\n ctx: Readonly<TContext>;\n iterations: number;\n}) => MaybePromise<boolean>;\n\n// Exactly one of `until` or `while` — never both.\nexport type RepeatOptions<TContext, TOutput> =\n | { until: LoopPredicate<TContext, TOutput>; while?: never; maxIterations?: number }\n | { while: LoopPredicate<TContext, TOutput>; until?: never; maxIterations?: number };\n\n// Extracts the element type from an array type. Resolves to `never` for non-arrays,\n// making foreach uncallable at compile time when the previous step doesn't produce an array.\ntype ElementOf<T> = T extends readonly (infer E)[] ? E : never;\n\n// ── parallel() supporting types ─────────────────────────────────────\n\n/** A target for a `parallel()` branch — agent or sealed workflow. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ParallelTarget<TContext, TInput> =\n | Agent<TContext, TInput, any>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n | SealedWorkflow<TContext, TInput, any>;\n\n/** Extract the output type of a single parallel branch target. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype BranchOutput<T> = T extends Agent<any, any, infer O>\n ? O\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n : T extends SealedWorkflow<any, any, infer O>\n ? O\n : never;\n\n/** Output shape for the record form: `{ [K]: BranchOutput<T[K]> }`. */\nexport type ParallelOutputRecord<T extends Record<string, unknown>> = {\n [K in keyof T]: BranchOutput<T[K]>;\n};\n\n/** Output shape for the tuple form: `[O1, O2, ...]`. */\nexport type ParallelOutputTuple<T extends ReadonlyArray<unknown>> = {\n [K in keyof T]: BranchOutput<T[K]>;\n};\n\nexport interface ParallelOptions<TContext> {\n /** Override the default step id. Default: `parallel:record` or `parallel:tuple`. */\n id?: string;\n /**\n * Max branches in flight at any moment. Default: `min(branches.length, 5)`.\n * Pass `Infinity` (or `branches.length`) for full fan-out on >5-branch calls\n * — the default caps at 5 to protect against rate limits and emits a\n * one-time warn when the cap kicks in.\n */\n concurrency?: number;\n /**\n * Per-branch error handler. On the no-suspension path, called once per\n * rejected branch in index order after all settle. Return a value to\n * substitute, return `Workflow.SKIP` to leave the slot undefined (record\n * form only — tuple SKIP would shift indices), or rethrow to abort the\n * parallel.\n *\n * **Bypassed entirely on the suspension path** (any branch hit a nested\n * gate). See README's \"Suspension under `parallel()`\" section.\n */\n onError?: (params: {\n error: unknown;\n /** Branch key in the record form; `undefined` in the tuple form. */\n key?: string;\n /** Branch index in the tuple form; `undefined` in the record form. */\n index?: number;\n ctx: Readonly<TContext>;\n }) => unknown | typeof Workflow.SKIP | Promise<unknown | typeof Workflow.SKIP>;\n}\n\n// ── Schema type (structural — works with Zod, Valibot, ArkType, etc.) ──\n\ninterface SchemaWithParse<T = unknown> {\n parse(data: unknown): T;\n}\n\n// ── Step Node ───────────────────────────────────────────────────────\n\n// `nestedWorkflow` is consumed by the recursive `stepShapeHash` walk; runtime\n// execution goes through the `execute` closure. `category` drives\n// observability event typing — keeps a single `type: \"step\"` variant rather\n// than splitting branch/foreach/repeat/parallel/nested into their own unions.\ntype StepCategory = \"step\" | \"nested\" | \"branch\" | \"foreach\" | \"repeat\" | \"parallel\";\n\ntype StepNode =\n | {\n readonly type: \"step\";\n readonly id: string;\n readonly execute: (state: RuntimeState) => MaybePromise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly nestedWorkflow?: SealedWorkflow<any, any, any, any>;\n /** Disambiguates observability events. Default `\"step\"`. */\n readonly category?: StepCategory;\n }\n | { readonly type: \"catch\"; readonly id: string; readonly catchFn: (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown> }\n | { readonly type: \"finally\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\n | { readonly type: \"gate\"; readonly id: string; readonly payload: (state: RuntimeState) => MaybePromise<unknown>; readonly schema?: SchemaWithParse; readonly condition?: (state: RuntimeState) => MaybePromise<boolean>; readonly merge?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown> };\n\n/**\n * Maps a step node's category (or non-step type) to the observability event\n * `type` field. Drives `WorkflowStepType` reporting.\n */\nfunction getObservabilityType(node: StepNode): WorkflowStepType {\n if (node.type !== \"step\") return node.type;\n return (node.category ?? \"step\") as WorkflowStepType;\n}\n\n/**\n * Returns the nested workflow(s) attached to a step node. The exhaustive\n * switch (no `default`) makes adding a new StepNode variant a TS error.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction getNestedWorkflows(node: StepNode): readonly SealedWorkflow<any, any, any, any>[] {\n switch (node.type) {\n case \"step\": return node.nestedWorkflow ? [node.nestedWorkflow] : [];\n case \"gate\":\n case \"catch\":\n case \"finally\": return [];\n }\n}\n\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\n // Only gates set `suspension`.\n suspension?: GateSnapshot;\n warnings?: WorkflowWarning[];\n checkpointFailed?: boolean;\n // Same RunOptions seen by execute(); reset to undefined inside nested\n // workflows and omitted from foreach itemState so per-run config doesn't\n // leak into nested execution.\n runOptions?: RunOptions;\n // Cooperative cancellation. Held on state separately from runOptions\n // because — unlike freezeSnapshots — abortSignal SHOULD propagate into\n // nested workflows and foreach items.\n abortSignal?: AbortSignal;\n}\n\n// Pending error tracked through a single execute() pass. The `source`\n// discriminant drives the precedence tail\n// (checkpointFailed > finally-wrap > step > suspension) and the onStepError\n// type mapping below.\ntype PendingError = {\n error: unknown;\n stepId: string;\n source: \"step\" | \"finally\" | \"catch\" | \"onCheckpoint\";\n};\n\n/**\n * Map `PendingError.source` to the `WorkflowStepType` value that\n * `onStepError` should report. `onCheckpoint` is mapped to `\"step\"`,\n * consistent with the `{ stepId: CHECKPOINT_STEP_ID, type: \"step\" }` contract.\n * Exhaustive switch — adding a new `source` variant is a compile error.\n */\nfunction pendingErrorSourceToStepType(source: PendingError[\"source\"]): WorkflowStepType {\n switch (source) {\n case \"step\": return \"step\";\n case \"finally\": return \"finally\";\n case \"catch\": return \"catch\";\n case \"onCheckpoint\": return \"step\";\n }\n}\n\n/**\n * Invoke `opts.onCheckpoint(snapshot, { signal })` with optional timeout via\n * AbortSignal. Throws on onCheckpoint failure or timeout\n * (CheckpointTimeoutError). The run loop catches and sets\n * `state.checkpointFailed`, which routes through the precedence tail\n * (checkpointFailed > finally-wrap > original-step > suspension).\n */\nasync function emitCheckpoint(\n state: RuntimeState,\n opts: RunOptions,\n resumeFromIndex: number,\n stepShapeHash: string,\n): Promise<void> {\n if (!opts.onCheckpoint) return;\n const snap: CheckpointSnapshot = {\n version: 2,\n kind: \"checkpoint\",\n resumeFromIndex,\n output: state.output,\n stepShapeHash,\n };\n if (resolveFreezeSnapshots(state)) deepFreeze(snap);\n\n const controller = new AbortController();\n if (opts.checkpointTimeout !== undefined) {\n const timeoutMs = opts.checkpointTimeout;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const callPromise = Promise.resolve(opts.onCheckpoint(snap, { signal: controller.signal }));\n const timeoutPromise = new Promise<never>((_, reject) => {\n controller.signal.addEventListener(\n \"abort\",\n () => reject(new CheckpointTimeoutError(timeoutMs)),\n { once: true },\n );\n });\n // Swallow loser to avoid unhandled rejection on the race.\n callPromise.catch(() => {});\n timeoutPromise.catch(() => {});\n await Promise.race([callPromise, timeoutPromise]);\n } finally {\n clearTimeout(timeoutId);\n }\n } else {\n await opts.onCheckpoint(snap, { signal: controller.signal });\n }\n}\n\n// One-time stream-mode warning when a gate fires with options.onError set.\nlet warnedStreamOnErrorOnSuspend = false;\n\n/**\n * @internal — test-only reset of the one-time stream-mode warn dedup.\n */\nexport function __resetStreamOnErrorOnSuspendWarnForTests(): void {\n warnedStreamOnErrorOnSuspend = false;\n}\n\n/**\n * Push an entry onto state.warnings, allocating the array lazily on first use.\n * Centralizes the `(state.warnings ??= []).push({source, stepId, error})` idiom.\n */\nfunction pushWarning(\n state: RuntimeState,\n source: WorkflowWarning[\"source\"],\n stepId: string,\n error: unknown,\n): void {\n (state.warnings ??= []).push({ source, stepId, error });\n}\n\n/**\n * Demote a pendingError into a warning. Used everywhere a new pendingError is\n * about to overwrite the prior one (finally/catch errors after a step error,\n * abort promoted over an in-flight error, suspension-wins tail).\n */\nfunction demotePendingError(state: RuntimeState, pe: PendingError): void {\n pushWarning(state, pe.source, pe.stepId, pe.error);\n}\n\n/**\n * Emit the one-shot stream-onError-on-suspend warning if applicable.\n */\nfunction maybeWarnStreamOnErrorOnSuspend(\n result: WorkflowResult<unknown>,\n options: WorkflowStreamOptions | undefined,\n): void {\n if (result.status !== \"suspended\" || !options?.onError || warnedStreamOnErrorOnSuspend) return;\n warnedStreamOnErrorOnSuspend = true;\n console.warn(\n \"pipeai: stream() with options.onError suspended at a gate — onError will NOT be invoked for suspension. Discriminate via the resolved output Promise.\"\n );\n}\n\n// ── Sealed Workflow (returned by finally — execution only) ───────────\n\nexport class SealedWorkflow<\n TContext,\n TInput = void,\n TOutput = void,\n TGates extends Record<string, unknown> = {},\n> {\n readonly id?: string;\n protected readonly steps: ReadonlyArray<StepNode>;\n protected readonly observability?: WorkflowObservability;\n // Memoized — see ensureDuplicateCheck().\n private duplicateCheckPassed = false;\n // Memoized lazily per terminal instance — build pipelines once at module\n // load and re-run via generate() to amortize.\n private _cachedExecutableStepCount?: number;\n private _cachedStepShapeHash?: string;\n\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string, observability?: WorkflowObservability) {\n this.steps = steps;\n this.id = id;\n this.observability = observability;\n }\n\n // ── Construction-time validation (memoized per terminal instance) ────\n\n /**\n * Walk the step list once per terminal instance. Rejects:\n * - Duplicate `(type, id)` pairs.\n * - User step ids containing the reserved `::pipeai::` namespace\n * (CHECKPOINT_STEP_ID lives there).\n */\n private ensureDuplicateCheck(): void {\n if (this.duplicateCheckPassed) return;\n const seen = new Map<string, number>();\n for (let i = 0; i < this.steps.length; i++) {\n const node = this.steps[i];\n if (node.id.includes(\"::pipeai::\")) {\n throw new Error(\n `Workflow: step id \"${node.id}\" uses the reserved \"::pipeai::\" namespace at index ${i}.`\n );\n }\n const key = `${node.type}:${node.id}`;\n const prior = seen.get(key);\n if (prior !== undefined) {\n throw new Error(\n `Workflow: duplicate (${node.type}, \"${node.id}\") at indices ${prior} and ${i}. ` +\n `Pass an explicit \\`{ id }\\` (e.g. for back-to-back \\`branch(...)\\` or \\`foreach(agentX).foreach(agentX)\\`) to disambiguate.`\n );\n }\n seen.set(key, i);\n }\n this.duplicateCheckPassed = true;\n }\n\n // ── shape-hash + RunOptions validation ────────────────────────\n\n /**\n * Count of executable nodes — i.e. NOT `catch` or `finally`. Drives\n * checkpoint auto-cadence so adding cleanup steps doesn't surprise users\n * with extra fires. `branch`/`foreach`/`repeat`/`parallel`/`nested` are all\n * `type: \"step\"` internally and count as executable.\n */\n protected get cachedExecutableStepCount(): number {\n if (this._cachedExecutableStepCount !== undefined) return this._cachedExecutableStepCount;\n let n = 0;\n for (const s of this.steps) {\n if (s.type !== \"catch\" && s.type !== \"finally\") n++;\n }\n this._cachedExecutableStepCount = n;\n return n;\n }\n\n /** @internal — used by `computeStepShapeHash` to descend nested workflows. */\n getStepsForShapeHash(): ReadonlyArray<StepNode> {\n return this.steps;\n }\n\n protected get cachedStepShapeHash(): string {\n if (this._cachedStepShapeHash !== undefined) return this._cachedStepShapeHash;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const getNested = (node: any) => getNestedWorkflows(node as StepNode) as unknown as readonly { id?: string; getStepsForShapeHash(): ReadonlyArray<{ type: string; id: string }> }[];\n this._cachedStepShapeHash = computeStepShapeHash(\n this.steps as unknown as ReadonlyArray<{ type: string; id: string }>,\n getNested,\n );\n return this._cachedStepShapeHash;\n }\n\n /**\n * Validate user-provided RunOptions before a run begins. Throws on\n * outright errors and on the loud-disaster combo (`freezeSnapshots: true\n * + checkpointEvery: 1` on a workflow of 8+ steps). Warns once on the\n * merely-suspicious combo (`freezeSnapshots: true + cadence <= 2`).\n * Plan-of-record: catastrophic combo escape via the\n * `\"iAcceptThePerformanceCost\"` literal.\n */\n protected validateRunOptions(opts: RunOptions | undefined): void {\n if (!opts) return;\n // checkpoint-specific validation only applies when onCheckpoint is set.\n if (!opts.onCheckpoint) return;\n if (opts.checkpointEvery !== undefined && opts.checkpointWhen !== undefined) {\n throw new Error(\"RunOptions: checkpointEvery and checkpointWhen are mutually exclusive\");\n }\n if (opts.checkpointEvery !== undefined && (!Number.isInteger(opts.checkpointEvery) || opts.checkpointEvery < 1)) {\n throw new Error(`RunOptions: checkpointEvery must be a positive integer, got ${opts.checkpointEvery}`);\n }\n if (opts.checkpointTimeout !== undefined && (!Number.isFinite(opts.checkpointTimeout) || opts.checkpointTimeout < 1)) {\n throw new Error(`RunOptions: checkpointTimeout must be a finite positive number (ms), got ${opts.checkpointTimeout}`);\n }\n const length = this.cachedExecutableStepCount;\n const cadence = opts.checkpointEvery ?? Math.max(1, Math.ceil(length / 4));\n if (opts.freezeSnapshots && opts.freezeSnapshots !== \"iAcceptThePerformanceCost\" && cadence === 1 && length >= 8) {\n throw new Error(\n `freezeSnapshots+checkpointEvery:1 on a ${length}-step workflow is reliably catastrophic. ` +\n `Set checkpointEvery >= 5, freezeSnapshots: false, or pass \"iAcceptThePerformanceCost\".`\n );\n }\n if (opts.freezeSnapshots && cadence <= 2) {\n warnOnce(\n \"pipeai:freezeSnapshots-low-cadence\",\n \"pipeai: freezeSnapshots+checkpointEvery<=2 compounds graph-walk cost.\",\n );\n }\n }\n\n // ── Observability helpers ─────────────────────────────────────\n\n /**\n * Fire an observability hook safely. Returns `undefined` synchronously when\n * no hook is registered — avoiding the promise wrapper + microtask that an\n * async function would unconditionally allocate on every step boundary.\n *\n * On hook throw:\n * - non-`onStepError` hooks: warning pushed + console.error.\n * - `onStepError`: throw is propagated as a return value; the run loop\n * attaches it as `cause` on the original step error.\n *\n * Returns the hook's thrown error if any; undefined otherwise. Callers\n * `await` the result — `await undefined` is sync, so the no-hook path\n * stays allocation-free.\n */\n protected fireHook<\n K extends keyof WorkflowObservability,\n E extends Parameters<NonNullable<WorkflowObservability[K]>>[0],\n >(\n state: RuntimeState,\n name: K,\n event: E,\n ): MaybePromise<unknown> {\n const hook = this.observability?.[name];\n if (!hook) return undefined;\n return this.fireHookSlow(state, name, event, hook);\n }\n\n private async fireHookSlow<K extends keyof WorkflowObservability>(\n state: RuntimeState,\n name: K,\n event: unknown,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hook: any,\n ): Promise<unknown> {\n try {\n await hook(event);\n return undefined;\n } catch (e) {\n if (name !== \"onStepError\") {\n const stepId = (event as { stepId: string }).stepId;\n pushWarning(state, name as WorkflowWarning[\"source\"], stepId, e);\n // eslint-disable-next-line no-console\n console.error(`pipeai: ${name} hook threw for stepId \"${stepId}\":`, e);\n }\n return e;\n }\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, opts?: RunOptions]\n : [input: TInput, opts?: RunOptions]\n ): Promise<WorkflowResult<TOutput>> {\n this.ensureDuplicateCheck();\n const input = args[0];\n const opts = args[1] as RunOptions | undefined;\n this.validateRunOptions(opts);\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n runOptions: opts,\n abortSignal: opts?.abortSignal,\n };\n\n await this.execute(state, 0, opts);\n\n return this.buildResult(state);\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions, opts?: RunOptions]\n : [input: TInput, options?: WorkflowStreamOptions, opts?: RunOptions]\n ): WorkflowStreamResult<TOutput> {\n this.ensureDuplicateCheck();\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n const opts = args[2] as RunOptions | undefined;\n this.validateRunOptions(opts);\n const abortSignal = opts?.abortSignal;\n\n let resolveOutput!: (value: WorkflowResult<TOutput>) => void;\n let rejectOutput!: (error: unknown) => void;\n const outputPromise = new Promise<WorkflowResult<TOutput>>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n outputPromise.catch(() => {});\n\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"stream\",\n writer,\n runOptions: opts,\n abortSignal,\n };\n\n try {\n await this.execute(state, 0, opts);\n const result = this.buildResult(state);\n maybeWarnStreamOnErrorOnSuspend(result, options);\n resolveOutput(result);\n } catch (error) {\n rejectOutput(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n });\n\n return {\n stream,\n output: outputPromise,\n };\n }\n\n // Helper — converts terminal RuntimeState into a WorkflowResult; freezes\n // snapshot + warnings if requested via runOptions.\n protected buildResult(state: RuntimeState): WorkflowResult<TOutput> {\n const warnings = state.warnings ?? [];\n if (state.suspension && resolveFreezeSnapshots(state)) {\n deepFreeze(warnings);\n }\n if (state.suspension) {\n return { status: \"suspended\", snapshot: state.suspension, warnings };\n }\n return { status: \"complete\", output: state.output as TOutput, warnings };\n }\n\n // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(\n state: RuntimeState,\n startIndex: number = 0,\n opts?: RunOptions,\n initialError: PendingError | null = null,\n ): Promise<void> {\n if (this.steps.length === 0) {\n throw new Error(\"Workflow has no steps. Add at least one step before calling generate() or stream().\");\n }\n\n // Make sure runOptions is plumbed even if the caller didn't initialize state.\n if (opts !== undefined && state.runOptions === undefined) {\n state.runOptions = opts;\n }\n\n // Hoisted once per run — the numeric cadence form has no per-step input,\n // so recomputing it per iteration was pure overhead.\n const ckptCadence = opts?.onCheckpoint && opts.checkpointWhen === undefined\n ? (opts.checkpointEvery ?? Math.max(1, Math.ceil(this.cachedExecutableStepCount / 4)))\n : 0;\n\n // `initialError` lets callers (e.g. ResumedWorkflow.stream) seed the\n // pipeline already-in-error so a pre-execute failure (schema.parse,\n // merge throw) flows through downstream `.catch()` like any other step\n // failure instead of escaping synchronously.\n let pendingError: PendingError | null = initialError;\n\n // Tracks whether the abort signal has already been promoted into\n // pendingError in this execute() pass. On first observation we discard\n // any in-progress suspension (caller asked to stop) and preserve any\n // prior step error as a warning. Subsequent iterations only re-promote\n // if a downstream catch cleared pendingError — the platform semantics\n // of AbortSignal.aborted (sticky once true) say the workflow shouldn't\n // resume mid-pipeline just because a catch swallowed one observation.\n let abortPromoted = false;\n const makeAbortError = (signal: AbortSignal): PendingError => ({\n error: signal.reason ?? new Error(\"Workflow aborted\"),\n stepId: \"abort\",\n source: \"step\",\n });\n\n for (let i = startIndex; i < this.steps.length; i++) {\n // Abort checkpoint — runs at every iteration boundary, before any\n // node dispatch, so finally/catch nodes that come AFTER the abort\n // still get to run (cleanup + recovery contract).\n if (state.abortSignal?.aborted) {\n if (!abortPromoted) {\n abortPromoted = true;\n state.suspension = undefined;\n if (pendingError) demotePendingError(state, pendingError);\n pendingError = makeAbortError(state.abortSignal);\n } else if (!pendingError) {\n // A catch handler swallowed the abort. Re-promote so downstream\n // steps still see the signal as the \"stop\" condition the caller\n // requested.\n pendingError = makeAbortError(state.abortSignal);\n }\n }\n\n const node = this.steps[i];\n\n if (node.type === \"finally\") {\n const stepId = node.id;\n const finStart = performance.now();\n await this.fireHook(state, \"onStepStart\", { stepId, type: \"finally\", ctx: state.ctx, input: state.output });\n try {\n await node.execute(state);\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"finally\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - finStart, suspended: false,\n });\n } catch (e) {\n await this.fireHook(state, \"onStepError\", {\n stepId, type: \"finally\", ctx: state.ctx, error: e,\n durationMs: performance.now() - finStart,\n });\n // Multi-error preservation: never silently overwrite a prior pendingError —\n // push it to warnings before promoting this finally error.\n if (pendingError) demotePendingError(state, pendingError);\n pendingError = { error: e, stepId, source: \"finally\" };\n }\n continue;\n }\n\n if (node.type === \"catch\") {\n // .catch() bypassed on suspension AND on checkpoint failure (checkpoint failure propagates to caller).\n if (state.suspension || !pendingError || state.checkpointFailed) continue;\n const stepId = node.id;\n const cStart = performance.now();\n await this.fireHook(state, \"onStepStart\", { stepId, type: \"catch\", ctx: state.ctx, input: state.output });\n try {\n state.output = await node.catchFn({\n error: pendingError.error,\n ctx: state.ctx,\n lastOutput: state.output,\n stepId: pendingError.stepId,\n });\n pendingError = null;\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"catch\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - cStart, suspended: false,\n });\n } catch (e) {\n await this.fireHook(state, \"onStepError\", {\n stepId, type: \"catch\", ctx: state.ctx, error: e,\n durationMs: performance.now() - cStart,\n });\n if (pendingError) demotePendingError(state, pendingError);\n pendingError = { error: e, stepId, source: \"catch\" };\n }\n continue;\n }\n\n // Skip remaining non-finally/non-catch nodes when suspended or in error state.\n if (state.suspension || pendingError) continue;\n\n if (node.type === \"gate\") {\n // Capture errors from condition/payload callbacks into pendingError so\n // they route through the workflow's .catch() pipeline like any other\n // step error. Without this, a throwing gate callback escapes execute()\n // entirely and bypasses all downstream catch nodes.\n const stepId = node.id;\n const gStart = performance.now();\n await this.fireHook(state, \"onStepStart\", { stepId, type: \"gate\", ctx: state.ctx, input: state.output });\n try {\n if (node.condition && !(await node.condition(state))) {\n // Cond returned false — skip the gate. Fire onStepFinish({ suspended: false }).\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"gate\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - gStart, suspended: false,\n });\n continue;\n }\n const snapshot: GateSnapshot = {\n version: 2,\n kind: \"gate\",\n resumeFromIndex: i,\n output: state.output,\n gateId: node.id,\n gatePayload: await node.payload(state),\n };\n state.suspension = snapshot;\n if (resolveFreezeSnapshots(state)) deepFreeze(snapshot);\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"gate\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - gStart, suspended: true,\n });\n } catch (e) {\n pendingError = { error: e, stepId: node.id, source: \"step\" };\n }\n continue;\n }\n\n // type === \"step\" — driven by `category` for observability type reporting.\n const obsType = getObservabilityType(node);\n const stepId = node.id;\n const sStart = performance.now();\n const stepInput = state.output;\n await this.fireHook(state, \"onStepStart\", { stepId, type: obsType, ctx: state.ctx, input: stepInput });\n try {\n await node.execute(state);\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: obsType, ctx: state.ctx, output: state.output,\n durationMs: performance.now() - sStart, suspended: false,\n });\n } catch (e) {\n pendingError = { error: e, stepId: node.id, source: \"step\" };\n // onStepError special-cases: if the hook throws, attach the obsError as\n // `cause` on the original step error so the original reaches the caller\n // with the failure trail attached. Other hooks' throws become warnings.\n const obsError = await this.fireHook(state, \"onStepError\", {\n stepId, type: obsType, ctx: state.ctx, error: e,\n durationMs: performance.now() - sStart,\n });\n if (obsError !== undefined && typeof e === \"object\" && e !== null) {\n try {\n (e as { cause?: unknown }).cause = obsError;\n } catch {\n // Some objects are frozen / non-extensible — ignore.\n }\n }\n }\n\n // Defensive invariant: only gate nodes set state.suspension, and\n // executeNestedWorkflow/foreach clear inner suspension before rethrowing.\n // A non-undefined value here means a coding bug bypassed that contract.\n // The cast is needed because TS narrowed suspension to undefined at the\n // top-of-loop falsy check and doesn't know the await may have mutated it.\n const leaked = (state as { suspension?: GateSnapshot }).suspension;\n if (leaked) {\n state.suspension = undefined;\n throw new Error(`internal: suspension bubbled from non-gate step \"${node.id}\" (gate \"${leaked.gateId}\").`);\n }\n\n // Emit a checkpoint after a successful step body. Skipped on pendingError\n // (the step threw — no clean state to snapshot) or on suspension (gate\n // already won). Numeric `checkpointEvery` (default: max(1, ceil(count/4)))\n // uses the loop-hoisted `ckptCadence`; predicate form runs per step.\n if (!pendingError && !state.suspension && opts?.onCheckpoint) {\n const shouldCheckpoint = opts.checkpointWhen\n ? opts.checkpointWhen({ stepIndex: i, stepId: node.id, ctx: state.ctx })\n : (i + 1) % ckptCadence === 0;\n if (shouldCheckpoint) {\n const ckptStart = performance.now();\n try {\n await emitCheckpoint(\n state,\n opts,\n i + 1,\n this.cachedStepShapeHash,\n );\n } catch (e) {\n pendingError = { error: e, stepId: CHECKPOINT_STEP_ID, source: \"onCheckpoint\" };\n state.checkpointFailed = true;\n // Route through onStepError with the synthetic CHECKPOINT_STEP_ID\n // and type: \"step\" (matches pendingErrorSourceToStepType(\"onCheckpoint\")).\n await this.fireHook(state, \"onStepError\", {\n stepId: CHECKPOINT_STEP_ID, type: \"step\", ctx: state.ctx, error: e,\n durationMs: performance.now() - ckptStart,\n });\n }\n }\n }\n }\n\n // Tail — mutually exclusive branches.\n // Precedence: checkpointFailed > finally-wrap > original-step > suspension.\n if (pendingError && !state.suspension) {\n if (state.checkpointFailed) {\n // Checkpoint error reaches caller bare; finally errors get console.warn\n // because the rejection path can't carry warnings.\n const warningsArr = state.warnings ?? [];\n const checkpointError = pendingError.source === \"onCheckpoint\"\n ? pendingError.error\n : warningsArr.find(w => w.source === \"onCheckpoint\")?.error;\n const finallyErrors = warningsArr.filter(w => w.source === \"finally\").map(w => w.error);\n const all = pendingError.source === \"finally\"\n ? [...finallyErrors, pendingError.error]\n : finallyErrors;\n if (all.length > 0) {\n console.warn(\n `pipeai: ${all.length} .finally() error(s) suppressed by checkpoint-failure precedence:`,\n all,\n );\n }\n throw checkpointError ?? pendingError.error;\n }\n const isFinallyPath = pendingError.source === \"finally\"\n || (state.warnings?.some(w => w.source === \"finally\") ?? false);\n if (isFinallyPath) {\n // Source order: warnings were pushed in the order errors occurred (step\n // before finally, earlier finally before later finally), so this preserves\n // the chronological sequence the plan specifies. Single-error case included\n // — once any finally is in the picture, the contract is AggregateError.\n const all = [...(state.warnings ?? []).map(w => w.error), pendingError.error];\n throw new AggregateError(all, `Workflow failed with ${all.length} error(s) from .finally() bodies`);\n }\n throw pendingError.error;\n } else if (pendingError && state.suspension) {\n // Suspension wins; preserve the step error as a warning.\n demotePendingError(state, pendingError);\n // Also emit onStepError so observers can see the loss.\n try {\n await this.observability?.onStepError?.({\n stepId: pendingError.stepId,\n type: pendingErrorSourceToStepType(pendingError.source),\n ctx: state.ctx,\n error: pendingError.error,\n durationMs: 0,\n });\n } catch (obsError) {\n pushWarning(state, \"onStepError\", pendingError.stepId, obsError);\n }\n pendingError = null;\n }\n }\n\n // ── Internal: execute a nested workflow within a step/loop ─────\n // Defined on SealedWorkflow (not Workflow) because TypeScript's protected\n // access rules only allow calling workflow.execute() from the same class.\n //\n // Contract: clears any inner suspension before re-throwing as\n // NestedGateUnsupportedError. The outer execute() therefore never observes\n // a leaked `state.suspension` from non-gate nodes (defensive invariant).\n\n protected async executeNestedWorkflow(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n workflow: SealedWorkflow<TContext, unknown, unknown, any>,\n ): Promise<void> {\n // RunOptions is run-scoped — child never inherits parent's runOptions.\n // state.warnings IS propagated (asymmetric on purpose: telemetry > config).\n const savedRunOptions = state.runOptions;\n state.runOptions = undefined;\n try {\n await workflow.execute(state);\n } finally {\n state.runOptions = savedRunOptions;\n }\n if (state.suspension) {\n const gateId = state.suspension.gateId;\n state.suspension = undefined; // clear before throw (load-bearing invariant 1)\n throw new NestedGateUnsupportedError(gateId, workflow.id);\n }\n }\n\n // ── Internal: execute an agent within a step/branch ───────────\n // In stream mode, output extraction awaits the full stream before returning.\n // Streaming benefits the client (incremental output), not pipeline throughput —\n // each step still runs sequentially.\n\n protected async executeAgent<TAgentInput, TNextOutput>(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agent: Agent<TContext, any, TNextOutput>,\n ctx: TContext,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: AgentStepHooks<TContext, any, TNextOutput>,\n ): Promise<void> {\n const input = state.output as TAgentInput;\n const hasStructuredOutput = agent.hasOutput;\n\n const abortSignal = state.abortSignal;\n const agentCallOpts = abortSignal ? { abortSignal } : undefined;\n\n if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools accessed via getActiveWriter() pick it up.\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown, opts?: { abortSignal?: AbortSignal }) => Promise<StreamTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output, agentCallOpts);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n const hookParams = {\n mode: \"stream\",\n result,\n ctx: ctx as Readonly<TContext>,\n input,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as AgentResultParams<TContext, any, TNextOutput>;\n\n if (options?.onResult) {\n await options.onResult(hookParams);\n }\n\n if (options?.mapResult) {\n state.output = await options.mapResult(hookParams);\n } else {\n state.output = await extractOutput(result, hasStructuredOutput, agent.validateOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown, opts?: { abortSignal?: AbortSignal }) => Promise<GenerateTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output, agentCallOpts);\n\n const hookParams = {\n mode: \"generate\",\n result,\n ctx: ctx as Readonly<TContext>,\n input,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as AgentResultParams<TContext, any, TNextOutput>;\n\n if (options?.onResult) {\n await options.onResult(hookParams);\n }\n\n if (options?.mapResult) {\n state.output = await options.mapResult(hookParams);\n } else {\n state.output = await extractOutput(result, hasStructuredOutput, agent.validateOutput);\n }\n }\n }\n\n // ── Gate: load persisted state for resumption ──────────────────\n\n loadState<K extends string & keyof TGates>(\n gateId: K,\n snapshot: WorkflowSnapshot,\n ): ResumedWorkflow<TContext, TGates[K], TOutput> {\n // Reject checkpoint snapshots — they belong to resumeFrom(), not loadState().\n if (snapshot.version === 2 && snapshot.kind === \"checkpoint\") {\n throw new Error(`loadState: received a checkpoint snapshot. Use resumeFrom() for checkpoint resume; loadState() is for gates.`);\n }\n const gateLike = snapshot as GateSnapshot | LegacyGateSnapshotV1;\n if (gateLike.gateId !== gateId) {\n throw new Error(\n `loadState: gate ID mismatch — expected \"${gateId}\" but snapshot has \"${gateLike.gateId}\".`\n );\n }\n this.ensureDuplicateCheck();\n const gateIndex = this.findGateIndex(gateLike);\n const gateNode = this.steps[gateIndex] as Extract<StepNode, { type: \"gate\" }>;\n return new ResumedWorkflow<TContext, TGates[K], TOutput>(this.steps, gateIndex + 1, {\n mode: \"gate\",\n schema: gateNode.schema as SchemaWithParse<TGates[K]> | undefined,\n mergeFn: gateNode.merge,\n priorOutput: gateLike.output,\n snapshot: gateLike,\n observability: this.observability,\n });\n }\n\n // ── Checkpoint resume ──────────────────────────────────────────\n\n /**\n * Resume from a checkpoint snapshot. Validates the step-shape hash unless\n * `{ skipShapeCheck: true }` is passed. Throws on:\n * - gate snapshots (use `loadState` instead)\n * - missing/corrupted `stepShapeHash`\n * - shape mismatch (unless skipped)\n * - out-of-bounds `resumeFromIndex`\n * - 0-step workflow (structural invariant)\n *\n * Returns a `CheckpointResumedWorkflow` whose `generate(ctx, opts?)` takes\n * NO response arg — the state is seeded from the snapshot's output. The\n * matching gate-resume path (`loadState`) keeps the `response` arg.\n */\n resumeFrom(\n snapshot: WorkflowSnapshot,\n options?: { skipShapeCheck?: boolean },\n ): CheckpointResumedWorkflow<TContext, TOutput> {\n // Detect gate snapshots (v2 with kind=\"gate\" OR legacy v1 with gateId).\n const isGate = (snapshot.version === 2 && snapshot.kind === \"gate\")\n || (snapshot.version === 1 && (snapshot as LegacyGateSnapshotV1).gateId !== undefined);\n if (isGate) {\n throw new Error(`resumeFrom: received a gate snapshot. Use loadState() for gate resume; resumeFrom() is for checkpoints.`);\n }\n if (this.steps.length === 0) {\n throw new Error(\"resumeFrom: workflow has no steps; snapshot is structurally invalid.\");\n }\n const ckpt = snapshot as CheckpointSnapshot;\n const idx = ckpt.resumeFromIndex;\n if (!Number.isInteger(idx) || idx < 0 || idx > this.steps.length) {\n throw new Error(`resumeFrom: resumeFromIndex (${idx}) out of bounds for ${this.steps.length}-step workflow.`);\n }\n if (!options?.skipShapeCheck) {\n if (!ckpt.stepShapeHash) {\n throw new Error(\"resumeFrom: snapshot missing stepShapeHash; corrupted or hand-crafted.\");\n }\n this.ensureDuplicateCheck();\n if (this.cachedStepShapeHash !== ckpt.stepShapeHash) {\n throw new Error(\"resumeFrom: workflow shape mismatch; cannot safely resume. Pass { skipShapeCheck: true } to override.\");\n }\n } else {\n this.ensureDuplicateCheck();\n }\n return new CheckpointResumedWorkflow<TContext, TOutput>(this.steps, idx, {\n mode: \"checkpoint\",\n priorOutput: ckpt.output,\n snapshot: ckpt,\n observability: this.observability,\n });\n }\n\n /**\n * Append a `.finally()` body to a sealed workflow, returning another sealed\n * workflow. Allows multi-finally chains (`.finally().finally()`). A throwing\n * `.finally` body does NOT abort subsequent ones — they all run.\n */\n finally(\n id: string,\n fn: (params: { ctx: Readonly<TContext> }) => MaybePromise<void>,\n ): SealedWorkflow<TContext, TInput, TOutput, TGates> {\n const node: StepNode = {\n type: \"finally\",\n id,\n execute: async (state) => {\n await fn({ ctx: state.ctx as Readonly<TContext> });\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new SealedWorkflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id, this.observability);\n }\n\n private findGateIndex(snapshot: GateSnapshot | LegacyGateSnapshotV1): number {\n // Accepted: v1 (legacy gate-only) and v2 (gate or checkpoint). Gate-flavor\n // v2 is discriminated by kind === \"gate\"; legacy v1 has no `kind`.\n if (snapshot.version !== 1 && snapshot.version !== 2) {\n throw new Error(`Unsupported snapshot version: ${(snapshot as { version: number }).version}`);\n }\n\n // Fast path — only when the hint is a sane integer in range AND points at the right gate.\n // Rejects -1, NaN, Infinity, 999999, fractional indices.\n const hint = snapshot.resumeFromIndex;\n if (Number.isInteger(hint) && hint >= 0 && hint < this.steps.length) {\n const node = this.steps[hint];\n if (node.type === \"gate\" && node.id === snapshot.gateId) {\n return hint;\n }\n }\n\n // Fallback — scan all steps by gate id (reorder-tolerant).\n for (let i = 0; i < this.steps.length; i++) {\n const node = this.steps[i];\n if (node.type === \"gate\" && node.id === snapshot.gateId) {\n return i;\n }\n }\n\n throw new Error(\n `Gate \"${snapshot.gateId}\" not found in workflow. The workflow definition may have changed since the snapshot was created.`\n );\n }\n}\n\n// ── Resumed Workflow ──────────────────────────────────────────────────\n\ninterface ResumedWorkflowConfig {\n readonly mode: \"gate\" | \"checkpoint\";\n readonly schema?: SchemaWithParse<unknown>;\n readonly mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>;\n readonly priorOutput?: unknown;\n readonly snapshot?: WorkflowSnapshot;\n readonly observability?: WorkflowObservability;\n}\n\nexport class ResumedWorkflow<\n TContext,\n TResponse = unknown,\n TOutput = void,\n> extends SealedWorkflow<TContext, TResponse, TOutput> {\n private readonly startIndex: number;\n private readonly schema?: SchemaWithParse<TResponse>;\n private readonly mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>;\n private readonly priorOutput: unknown;\n\n /** @internal */\n constructor(\n steps: ReadonlyArray<StepNode>,\n startIndex: number,\n config: ResumedWorkflowConfig,\n ) {\n super(steps, undefined, config.observability);\n this.startIndex = startIndex;\n this.schema = config.schema as SchemaWithParse<TResponse> | undefined;\n this.mergeFn = config.mergeFn;\n this.priorOutput = config.priorOutput;\n }\n\n private validateResponse(response: TResponse): TResponse {\n if (this.schema) {\n return this.schema.parse(response) as TResponse;\n }\n return response;\n }\n\n override async generate(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, opts?: RunOptions]\n : [response: TResponse, opts?: RunOptions]\n ): Promise<WorkflowResult<TOutput>> {\n const rawResponse = args[0] as TResponse;\n const opts = args[1] as RunOptions | undefined;\n // Run prep (schema.parse + mergeFn) inside the workflow's error pipeline\n // so a downstream `.catch()` can observe failures here. Without this,\n // a schema/merge throw would reject the promise raw, bypassing catch.\n let output: unknown = this.priorOutput;\n let initialError: PendingError | null = null;\n try {\n const response = this.validateResponse(rawResponse);\n output = this.mergeFn\n ? await this.mergeFn({ priorOutput: this.priorOutput, response })\n : response;\n } catch (error) {\n initialError = { error, stepId: \"gate:resume\", source: \"step\" };\n }\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"generate\",\n runOptions: opts,\n abortSignal: opts?.abortSignal,\n };\n await this.execute(state, this.startIndex, opts, initialError);\n return this.buildResult(state);\n }\n\n override stream(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, options?: WorkflowStreamOptions, opts?: RunOptions]\n : [response: TResponse, options?: WorkflowStreamOptions, opts?: RunOptions]\n ): WorkflowStreamResult<TOutput> {\n const rawResponse = args[0] as TResponse;\n const options = args[1] as WorkflowStreamOptions | undefined;\n const opts = args[2] as RunOptions | undefined;\n const abortSignal = opts?.abortSignal;\n\n let resolveOutput!: (value: WorkflowResult<TOutput>) => void;\n let rejectOutput!: (error: unknown) => void;\n const outputPromise = new Promise<WorkflowResult<TOutput>>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n outputPromise.catch(() => {});\n\n const mergeFn = this.mergeFn;\n const priorOutput = this.priorOutput;\n const startIndex = this.startIndex;\n\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n // Run prep (schema.parse + mergeFn) inside the error pipeline (same as\n // generate()). Without this, a schema parse throw escapes synchronously\n // from .stream(...) and bypasses any downstream .catch().\n let output: unknown = priorOutput;\n let initialError: PendingError | null = null;\n try {\n const response = this.validateResponse(rawResponse);\n output = mergeFn\n ? await mergeFn({ priorOutput, response })\n : response;\n } catch (error) {\n initialError = { error, stepId: \"gate:resume\", source: \"step\" };\n }\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"stream\",\n writer,\n runOptions: opts,\n abortSignal,\n };\n\n try {\n await this.execute(state, startIndex, opts, initialError);\n const result = this.buildResult(state);\n maybeWarnStreamOnErrorOnSuspend(result, options);\n resolveOutput(result);\n } catch (error) {\n rejectOutput(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n });\n\n return { stream, output: outputPromise };\n }\n}\n\n// ── Checkpoint-Resumed Workflow ──────────────────────────────────────\n//\n// Used by `resumeFrom()`. Same step list, different entry index — no\n// gate-merge logic (no response argument) because the state is seeded\n// from the checkpoint snapshot's `output`. To keep gate-resume's\n// `loadState` form ergonomic, this is a separate class instead of\n// overloading ResumedWorkflow's generate().\n\nexport class CheckpointResumedWorkflow<\n TContext,\n TOutput = void,\n> extends SealedWorkflow<TContext, void, TOutput> {\n private readonly startIndex: number;\n private readonly priorOutput: unknown;\n\n /** @internal */\n constructor(\n steps: ReadonlyArray<StepNode>,\n startIndex: number,\n config: ResumedWorkflowConfig,\n ) {\n super(steps, undefined, config.observability);\n this.startIndex = startIndex;\n this.priorOutput = config.priorOutput;\n }\n\n // Override with widened arg list compatible with parent's `[input?, opts?]`.\n // Inputs are ignored — state is seeded from the snapshot's `output` field.\n override async generate(\n ctx: TContext,\n ...args: [input?: void, opts?: RunOptions]\n ): Promise<WorkflowResult<TOutput>> {\n const opts = args[1];\n this.validateRunOptions(opts);\n const state: RuntimeState = {\n ctx,\n output: this.priorOutput,\n mode: \"generate\",\n runOptions: opts,\n };\n await this.execute(state, this.startIndex, opts);\n return this.buildResult(state);\n }\n\n override stream(\n ctx: TContext,\n ...args: [input?: void, options?: WorkflowStreamOptions, opts?: RunOptions]\n ): WorkflowStreamResult<TOutput> {\n const options = args[1];\n const opts = args[2];\n this.validateRunOptions(opts);\n\n let resolveOutput!: (value: WorkflowResult<TOutput>) => void;\n let rejectOutput!: (error: unknown) => void;\n const outputPromise = new Promise<WorkflowResult<TOutput>>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n outputPromise.catch(() => {});\n\n const priorOutput = this.priorOutput;\n const startIndex = this.startIndex;\n\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: priorOutput,\n mode: \"stream\",\n writer,\n runOptions: opts,\n };\n try {\n await this.execute(state, startIndex, opts);\n const result = this.buildResult(state);\n maybeWarnStreamOnErrorOnSuspend(result, options);\n resolveOutput(result);\n } catch (error) {\n rejectOutput(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n });\n\n return { stream, output: outputPromise };\n }\n}\n\n// ── Workflow ────────────────────────────────────────────────────────\n\nexport class Workflow<\n TContext,\n TInput = void,\n TOutput = void,\n TGates extends Record<string, unknown> = {},\n> extends SealedWorkflow<TContext, TInput, TOutput, TGates> {\n\n /**\n * Sentinel value for `foreach`'s `onError` handler. Returning `Workflow.SKIP`\n * from `onError` omits the failed item's index from the output array,\n * shortening it relative to the input array.\n */\n static readonly SKIP: unique symbol = Symbol(\"pipeai.foreach.skip\");\n\n private constructor(steps: ReadonlyArray<StepNode> = [], id?: string, observability?: WorkflowObservability) {\n super(steps, id, observability);\n }\n\n static create<TContext, TInput = void>(\n options?: { id?: string; observability?: WorkflowObservability },\n ): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id, options?.observability);\n }\n\n static from<TContext, TInput, TOutput>(\n agent: Agent<TContext, TInput, TOutput>,\n options?: StepOptions<TContext, TInput, TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, any>([]).step(agent, options);\n }\n\n // Builder helper — append a step and return a re-typed Workflow.\n // Centralizes the `[...steps, node] as any` + new Workflow + observability/id\n // forwarding pattern used by every combinator method.\n private appendStep<TNext, TG extends Record<string, unknown> = TGates>(\n node: StepNode,\n ): Workflow<TContext, TInput, TNext, TG> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNext, TG>([...this.steps, node] as any, this.id, this.observability);\n }\n\n // ── step: agent overload ──────────────────────────────────────\n\n step<TNextOutput>(\n agent: Agent<TContext, TOutput, TNextOutput>,\n options?: StepOptions<TContext, TOutput, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── step: nested workflow overload ─────────────────────────────\n\n step<TNextOutput>(\n workflow: SealedWorkflow<TContext, TOutput, TNextOutput>,\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── step: transform overload (replaces map + tap) ─────────────\n\n step<TNextOutput>(\n id: string,\n fn: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── step: implementation ──────────────────────────────────────\n\n step<TNextOutput>(\n target: Agent<TContext, TOutput, TNextOutput> | SealedWorkflow<TContext, TOutput, TNextOutput> | string,\n optionsOrFn?: StepOptions<TContext, TOutput, TNextOutput> | ((params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>)\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n // Nested workflow overload: step(workflow)\n if (target instanceof SealedWorkflow) {\n const workflow = target;\n const node: StepNode = {\n type: \"step\",\n id: workflow.id ?? \"nested-workflow\",\n nestedWorkflow: workflow, // Feeds the recursive stepShapeHash walk.\n category: \"nested\", // Observability event type.\n execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown, any>);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // Transform overload: step(id, fn)\n if (typeof target === \"string\") {\n if (typeof optionsOrFn !== \"function\") {\n throw new Error(`Workflow step(\"${target}\"): second argument must be a function`);\n }\n const fn = optionsOrFn as (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n const node: StepNode = {\n type: \"step\",\n id: target,\n execute: async (state) => {\n state.output = await fn({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n });\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // Agent overload: step(agent, options?)\n const agent = target;\n const options = optionsOrFn as StepOptions<TContext, TOutput, TNextOutput> | undefined;\n const node: StepNode = {\n type: \"step\",\n id: options?.id ?? agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // ── gate: human-in-the-loop suspension point ────────────────\n\n gate<TResponse = TOutput, Id extends string = string>(\n id: Id & (Id extends keyof TGates ? never : Id),\n options?: {\n payload?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<unknown>;\n schema?: SchemaWithParse<TResponse>;\n condition?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n merge?: (params: { priorOutput: TOutput; response: TResponse }) => MaybePromise<TResponse>;\n }\n ): Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>> {\n if (this.steps.some(s => s.type === \"gate\" && s.id === id)) {\n throw new Error(`Workflow: duplicate gate ID \"${id}\". Each gate must have a unique identifier.`);\n }\n const node: StepNode = {\n type: \"gate\",\n id,\n schema: options?.schema,\n condition: options?.condition\n ? async (state) => options.condition!({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n })\n : undefined,\n merge: options?.merge\n ? (params) => options.merge!(params as { priorOutput: TOutput; response: TResponse })\n : undefined,\n payload: async (state) => {\n if (options?.payload) {\n return options.payload({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n });\n }\n return state.output;\n },\n };\n return this.appendStep<TResponse, TGates & Record<Id, TResponse>>(node);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[],\n options?: { id?: string },\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── branch: key routing (select) ──────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>,\n options?: { id?: string },\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── branch: implementation ────────────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n casesOrConfig: BranchCase<TContext, TOutput, TNextOutput>[] | BranchSelect<TContext, TOutput, TKeys, TNextOutput>,\n options?: { id?: string },\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig, options?.id);\n }\n return this.branchSelect(casesOrConfig, options?.id);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[],\n explicitId?: string,\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: explicitId ?? \"branch:predicate\",\n category: \"branch\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n\n for (const branchCase of cases) {\n if (branchCase.when) {\n const match = await branchCase.when({ ctx, input });\n if (!match) continue;\n }\n\n // Matched (or no `when` = default)\n await this.executeAgent(state, branchCase.agent, ctx, branchCase);\n return;\n }\n\n // Render the input defensively — JSON.stringify throws on cyclic /\n // BigInt / function-valued inputs, which would mask the real branch\n // mismatch with a serialization error.\n let inputRepr: string;\n try {\n inputRepr = JSON.stringify(input);\n if (inputRepr === undefined) inputRepr = String(input);\n } catch {\n inputRepr = `[unserializable ${typeof input}]`;\n }\n throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${inputRepr}`);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>,\n explicitId?: string,\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: explicitId ?? \"branch:select\",\n category: \"branch\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n const key = await config.select({ ctx, input });\n\n // Distinguish \"key not declared at all\" from \"key present but value\n // is `undefined`\" (e.g. `agents: { bug: cond ? agentA : undefined }`).\n // The latter is a user-side bug — fail loud rather than silently\n // falling back, since the fallback obscures the misconfiguration.\n //\n // Use Object.prototype.hasOwnProperty.call (not `in`) so untrusted\n // classifier output like \"toString\"/\"constructor\"/\"__proto__\" doesn't\n // resolve to a Object.prototype method and crash executeAgent with an\n // opaque \"agent.generate is not a function\".\n const keyDeclared = Object.prototype.hasOwnProperty.call(config.agents, key);\n if (keyDeclared && (config.agents as Record<string, unknown>)[key] === undefined) {\n throw new WorkflowBranchError(\n \"select\",\n `Agent for key \"${key}\" was declared but the value is undefined. ` +\n `This usually means a conditional spread set the value to undefined. ` +\n `Available keys: ${Object.keys(config.agents).join(\", \")}`,\n );\n }\n let agent = keyDeclared ? config.agents[key] : undefined;\n if (!agent) {\n if (config.onUnknownKey) {\n config.onUnknownKey({\n key,\n availableKeys: Object.keys(config.agents) as TKeys[],\n ctx: ctx as Readonly<TContext>,\n });\n }\n if (config.fallback) {\n agent = config.fallback;\n } else {\n throw new WorkflowBranchError(\"select\", `No agent found for key \"${key}\" and no fallback provided. Available keys: ${Object.keys(config.agents).join(\", \")}`);\n }\n }\n\n await this.executeAgent(state, agent, ctx, config);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n /**\n * Map each item of an array through an agent or sub-workflow.\n *\n * @param target Agent or `SealedWorkflow` invoked once per item.\n * @param options.id Override the default step id (`foreach:<agentId>` or\n * the workflow's id). Required when chaining multiple foreach over the same\n * target — the construction-time `(type, id)` walk rejects duplicates.\n * @param options.concurrency Max items in flight at any moment (default 1).\n * Backed by a semaphore: as soon as one item completes, the next launches —\n * no lockstep batching.\n * @param options.onError Per-iteration error handler. **Bypassed entirely on\n * the suspension path** (when any item hits a nested gate) — see the\n * foreach concurrency hazards in the README. Otherwise: return a\n * `TNextOutput` value to substitute, return `Workflow.SKIP` to omit, throw\n * to abort. Invoked sequentially in index order after all items settle.\n */\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: {\n id?: string;\n concurrency?: number;\n onError?: (params: {\n error: unknown;\n item: ElementOf<TOutput>;\n index: number;\n ctx: Readonly<TContext>;\n }) => MaybePromise<TNextOutput | typeof Workflow.SKIP>;\n },\n ): Workflow<TContext, TInput, TNextOutput[], TGates> {\n const concurrency = options?.concurrency ?? 1;\n const onError = options?.onError;\n const isWorkflow = target instanceof SealedWorkflow;\n const defaultId = isWorkflow\n ? (target.id ?? \"foreach\")\n : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n const id = options?.id ?? defaultId;\n\n const node: StepNode = {\n type: \"step\",\n id,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n nestedWorkflow: isWorkflow ? (target as SealedWorkflow<any, any, any, any>) : undefined,\n category: \"foreach\",\n execute: async (state) => {\n const items = state.output;\n if (!Array.isArray(items)) {\n throw new Error(`foreach \"${id}\": expected array input, got ${typeof items}`);\n }\n\n const ctx = state.ctx as TContext;\n const results: unknown[] = new Array(items.length);\n const skipped = new Set<number>();\n const itemStates: (RuntimeState | undefined)[] = new Array(items.length);\n\n const executeItem = async (item: unknown, index: number) => {\n // itemState explicitly omits runOptions — per-run config never crosses\n // the foreach boundary. abortSignal IS propagated though, since\n // cancellation must be transitive across the foreach barrier.\n const itemState: RuntimeState = {\n ctx: state.ctx,\n output: item,\n mode: \"generate\",\n abortSignal: state.abortSignal,\n };\n itemStates[index] = itemState;\n const itemStart = performance.now();\n await this.fireHook(state, \"onItemStart\", {\n stepId: id, type: \"foreach\", itemIndex: index, ctx: state.ctx, input: item,\n });\n try {\n if (isWorkflow) {\n await this.executeNestedWorkflow(itemState, target as SealedWorkflow<TContext, unknown, unknown, any>);\n } else {\n await this.executeAgent(itemState, target as Agent<TContext, unknown, TNextOutput>, ctx);\n }\n results[index] = itemState.output;\n await this.fireHook(state, \"onItemFinish\", {\n stepId: id, type: \"foreach\", itemIndex: index, ctx: state.ctx, output: itemState.output,\n durationMs: performance.now() - itemStart,\n });\n } catch (error) {\n await this.fireHook(state, \"onItemError\", {\n stepId: id, type: \"foreach\", itemIndex: index, ctx: state.ctx, error,\n durationMs: performance.now() - itemStart,\n });\n throw error;\n }\n };\n\n // Merge per-item warnings into the parent state, namespaced.\n // Runs on EVERY exit path (success, suspension, or onError throw).\n const mergeItemWarnings = () => {\n for (let idx = 0; idx < items.length; idx++) {\n const its = itemStates[idx];\n if (!its?.warnings) continue;\n for (const w of its.warnings) {\n pushWarning(state, w.source, `${id}[${idx}]:${w.stepId}`, w.error);\n }\n }\n };\n\n const handleRejection = async (error: unknown, item: unknown, index: number) => {\n if (!onError) throw error;\n const recovered = await onError({\n error,\n item: item as ElementOf<TOutput>,\n index,\n ctx: state.ctx as Readonly<TContext>,\n });\n if (recovered === Workflow.SKIP) {\n skipped.add(index);\n } else {\n results[index] = recovered;\n }\n };\n\n // Collect rejections, then partition + branch.\n type Failure = { index: number; error: unknown };\n const failures: Failure[] = [];\n\n // Cooperative cancellation: bail before launching each item so a\n // large foreach doesn't fire off all items just because the parent's\n // abortSignal triggered mid-iteration. In-flight items already running\n // can't be yanked back, but their executeAgent call forwarded the\n // signal so the SDK side will tear them down.\n const signal = state.abortSignal;\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n if (signal?.aborted) {\n failures.push({ index: i, error: signal.reason ?? new Error(\"Workflow aborted\") });\n continue;\n }\n try {\n await executeItem(items[i], i);\n } catch (error) {\n failures.push({ index: i, error });\n }\n }\n } else {\n // Worker pool: O(concurrency) async closures share a counter rather\n // than O(N) closures all queuing on a semaphore. The shared\n // `nextIndex++` is safe because JS is single-threaded — the\n // read+increment is synchronous and the following `await` yields\n // AFTER the index is captured.\n let nextIndex = 0;\n const worker = async () => {\n while (true) {\n const i = nextIndex++;\n if (i >= items.length) return;\n if (signal?.aborted) {\n failures.push({ index: i, error: signal.reason ?? new Error(\"Workflow aborted\") });\n continue;\n }\n try {\n await executeItem(items[i], i);\n } catch (error) {\n failures.push({ index: i, error });\n }\n }\n };\n const workers = Array.from(\n { length: Math.min(concurrency, items.length) },\n () => worker(),\n );\n await Promise.all(workers);\n }\n\n failures.sort((a, b) => a.index - b.index);\n\n // Partition into gate vs non-gate rejections.\n const gateFailures: { index: number; error: NestedGateUnsupportedError }[] = [];\n const nonGateFailures: Failure[] = [];\n for (const f of failures) {\n if (f.error instanceof NestedGateUnsupportedError) {\n gateFailures.push({ index: f.index, error: f.error });\n } else {\n nonGateFailures.push(f);\n }\n }\n\n // Always merge per-item warnings before deciding which path to take.\n mergeItemWarnings();\n\n if (gateFailures.length > 0) {\n // Suspension path — onError is bypassed entirely. Non-gate rejections\n // become foreach-sibling warnings. Lowest-index marker wins.\n for (const nr of nonGateFailures) {\n pushWarning(state, \"foreach-sibling\", `${id}[${nr.index}]`, nr.error);\n }\n const lowest = gateFailures[0];\n const otherSuspensions = gateFailures.slice(1).map(g => ({\n index: g.index,\n gateId: g.error.gateId,\n }));\n const siblingErrors = nonGateFailures.map(nr => nr.error);\n throw new NestedGateUnsupportedError(\n lowest.error.gateId,\n lowest.error.workflowId,\n siblingErrors,\n otherSuspensions,\n );\n }\n\n // No suspension — run onError per existing semantics in index order.\n for (const { index, error } of nonGateFailures) {\n await handleRejection(error, items[index], index);\n }\n\n state.output = skipped.size === 0\n ? results\n : results.filter((_, i) => !skipped.has(i));\n },\n };\n return this.appendStep<TNextOutput[]>(node);\n }\n\n // ── parallel: fan-out combinator ────────────────────────────────\n //\n // Same input fed to each branch. Generate mode only — writer is NOT threaded\n // through (interleaving multiple agent streams into one writer is not\n // supported). For SealedWorkflow branches, a nested gate throws\n // NestedGateUnsupportedError (same machinery as foreach concurrent).\n //\n // Default concurrency: `min(branches.length, 5)` — most users want fan-out,\n // not lockstep batching. Warn-once when branch count exceeds the 5 cap so\n // users notice unexpected rate-limit pressure.\n\n /** Record-form overload. Returns `{ [K]: BranchOutput<T[K]> }`. */\n parallel<TBranches extends Record<string, ParallelTarget<TContext, TOutput>>>(\n branches: TBranches,\n options?: ParallelOptions<TContext>,\n ): Workflow<TContext, TInput, ParallelOutputRecord<TBranches>, TGates>;\n\n /** Tuple-form overload. Returns `[O1, O2, ...]`. Use `as const`. */\n parallel<TBranches extends ReadonlyArray<ParallelTarget<TContext, TOutput>>>(\n branches: TBranches,\n options?: ParallelOptions<TContext>,\n ): Workflow<TContext, TInput, ParallelOutputTuple<TBranches>, TGates>;\n\n // Implementation\n parallel(\n branches: Record<string, ParallelTarget<TContext, TOutput>> | ReadonlyArray<ParallelTarget<TContext, TOutput>>,\n options?: ParallelOptions<TContext>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Workflow<TContext, TInput, any, TGates> {\n const isTuple = Array.isArray(branches);\n const entries: Array<{ key: string | number; index: number; target: ParallelTarget<TContext, TOutput> }> = isTuple\n ? (branches as ReadonlyArray<ParallelTarget<TContext, TOutput>>).map((target, i) => ({ key: i, index: i, target }))\n : Object.entries(branches as Record<string, ParallelTarget<TContext, TOutput>>).map(([k, t], i) => ({ key: k, index: i, target: t }));\n const branchCount = entries.length;\n const requestedConcurrency = options?.concurrency;\n let effectiveConcurrency: number;\n if (requestedConcurrency === undefined) {\n effectiveConcurrency = Math.min(branchCount, 5);\n } else {\n effectiveConcurrency = requestedConcurrency;\n }\n // Warn-once when >5 branches without explicit concurrency override.\n if (requestedConcurrency === undefined && branchCount > 5) {\n warnOnce(\n \"pipeai:parallel-cap\",\n `pipeai: parallel() with ${branchCount} branches capped at concurrency 5 by default. Pass { concurrency: ${branchCount} } (or Infinity) to opt in, or set { concurrency: N } if you want fewer.`,\n );\n }\n const onError = options?.onError;\n const id = options?.id ?? (isTuple ? \"parallel:tuple\" : \"parallel:record\");\n\n const node: StepNode = {\n type: \"step\",\n id,\n category: \"parallel\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output;\n const results: Record<string | number, unknown> = (isTuple ? new Array(branchCount) : {}) as Record<string | number, unknown>;\n const branchStates: (RuntimeState | undefined)[] = new Array(branchCount);\n\n const executeBranch = async ({ key, index, target }: { key: string | number; index: number; target: ParallelTarget<TContext, TOutput> }) => {\n // Per-branch itemState — same isolation as foreach (no runOptions).\n const branchState: RuntimeState = { ctx: state.ctx, output: input, mode: \"generate\" };\n branchStates[index] = branchState;\n const branchStart = performance.now();\n // itemIndex is the key for record form, numeric index for tuple form.\n const itemIndex: string | number = isTuple ? index : (key as string);\n await this.fireHook(state, \"onItemStart\", {\n stepId: id, type: \"parallel\", itemIndex, ctx: state.ctx, input,\n });\n try {\n if (target instanceof SealedWorkflow) {\n await this.executeNestedWorkflow(branchState, target as SealedWorkflow<TContext, unknown, unknown, any>);\n } else {\n await this.executeAgent(branchState, target as Agent<TContext, unknown, unknown>, ctx);\n }\n results[key] = branchState.output;\n await this.fireHook(state, \"onItemFinish\", {\n stepId: id, type: \"parallel\", itemIndex, ctx: state.ctx, output: branchState.output,\n durationMs: performance.now() - branchStart,\n });\n } catch (error) {\n await this.fireHook(state, \"onItemError\", {\n stepId: id, type: \"parallel\", itemIndex, ctx: state.ctx, error,\n durationMs: performance.now() - branchStart,\n });\n throw error;\n }\n };\n\n // Same partition + suspension contract as foreach concurrent.\n type Failure = { key: string | number; index: number; error: unknown };\n const failures: Failure[] = [];\n\n const eff = Number.isFinite(effectiveConcurrency) ? Math.max(1, effectiveConcurrency) : branchCount;\n if (eff <= 1) {\n for (const e of entries) {\n try {\n await executeBranch(e);\n } catch (error) {\n failures.push({ key: e.key, index: e.index, error });\n }\n }\n } else {\n // Worker pool (same shape as foreach): K closures share a counter\n // instead of N closures queuing on a semaphore.\n let nextIndex = 0;\n const worker = async () => {\n while (true) {\n const i = nextIndex++;\n if (i >= branchCount) return;\n const e = entries[i];\n try {\n await executeBranch(e);\n } catch (error) {\n failures.push({ key: e.key, index: e.index, error });\n }\n }\n };\n const workers = Array.from(\n { length: Math.min(eff, branchCount) },\n () => worker(),\n );\n await Promise.all(workers);\n }\n\n // Always merge per-branch warnings into the parent, namespaced.\n for (let idx = 0; idx < branchCount; idx++) {\n const bs = branchStates[idx];\n if (!bs?.warnings) continue;\n for (const w of bs.warnings) {\n pushWarning(state, w.source, `${id}[${entries[idx].key}]:${w.stepId}`, w.error);\n }\n }\n\n // Partition rejections into gate vs non-gate.\n const gateFailures: { key: string | number; index: number; error: NestedGateUnsupportedError }[] = [];\n const nonGateFailures: Failure[] = [];\n for (const f of failures) {\n if (f.error instanceof NestedGateUnsupportedError) gateFailures.push({ key: f.key, index: f.index, error: f.error });\n else nonGateFailures.push(f);\n }\n gateFailures.sort((a, b) => a.index - b.index);\n nonGateFailures.sort((a, b) => a.index - b.index);\n\n if (gateFailures.length > 0) {\n // Suspension path — onError bypassed; non-gate rejections become warnings.\n for (const nr of nonGateFailures) {\n pushWarning(state, \"foreach-sibling\", `${id}[${nr.key}]`, nr.error);\n }\n const lowest = gateFailures[0];\n const otherSuspensions = gateFailures.slice(1).map(g => ({ index: g.index, gateId: g.error.gateId }));\n const siblingErrors = nonGateFailures.map(nr => nr.error);\n throw new NestedGateUnsupportedError(\n lowest.error.gateId,\n lowest.error.workflowId,\n siblingErrors,\n otherSuspensions,\n );\n }\n\n // No suspension — handle non-gate failures via onError or rethrow.\n for (const { key, index, error } of nonGateFailures) {\n if (!onError) throw error;\n const recovered = await onError({\n error,\n key: isTuple ? undefined : (key as string),\n index: isTuple ? (index) : undefined,\n ctx: state.ctx as Readonly<TContext>,\n });\n if (recovered === Workflow.SKIP) {\n // Record form: leave the key as `undefined`. Tuple form: same — the\n // slot stays `undefined`. The output type accepts SKIP only on the\n // record form at compile time.\n results[key] = undefined;\n } else {\n results[key] = recovered;\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this.appendStep<any>(node);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput> & { id?: string },\n ): Workflow<TContext, TInput, TOutput, TGates> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const defaultId = isWorkflow\n ? (target.id ?? \"repeat\")\n : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\n const id = options.id ?? defaultId;\n const predicate: LoopPredicate<TContext, TOutput> = options.until\n ?? (async (p) => !(await options.while!(p)));\n\n const node: StepNode = {\n type: \"step\",\n id,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n nestedWorkflow: isWorkflow ? (target as SealedWorkflow<any, any, any, any>) : undefined,\n category: \"repeat\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\n // Cancellation checkpoint between iterations. The body's executeAgent\n // already forwards the signal so an in-flight call cancels too, but\n // the explicit check here covers SealedWorkflow bodies and transform-\n // only loops where the signal wouldn't otherwise propagate.\n if (state.abortSignal?.aborted) {\n throw state.abortSignal.reason ?? new Error(\"Workflow aborted\");\n }\n\n if (isWorkflow) {\n await this.executeNestedWorkflow(state, target as SealedWorkflow<TContext, unknown, unknown, any>);\n } else {\n await this.executeAgent(state, target as Agent<TContext, TOutput, TOutput>, ctx);\n }\n\n const done = await predicate({\n output: state.output as TOutput,\n ctx: ctx as Readonly<TContext>,\n iterations: i,\n });\n if (done) return;\n }\n\n throw new WorkflowLoopError(maxIterations, maxIterations);\n },\n };\n return this.appendStep<TOutput>(node);\n }\n\n // ── catch ─────────────────────────────────────────────────────\n\n catch(\n id: string,\n fn: (params: { error: unknown; ctx: Readonly<TContext>; lastOutput: TOutput; stepId: string }) => MaybePromise<TOutput>\n ): Workflow<TContext, TInput, TOutput, TGates> {\n if (!this.steps.some(s => s.type === \"step\")) {\n throw new Error(`Workflow: catch(\"${id}\") requires at least one preceding step.`);\n }\n const node: StepNode = {\n type: \"catch\",\n id,\n catchFn: fn as (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown>,\n };\n return this.appendStep<TOutput>(node);\n }\n\n // `.finally()` is inherited from SealedWorkflow now (it lives there so\n // multi-finally chains are possible — `.finally().finally()`).\n}\n","export { Agent } from \"./agent\";\nexport type {\n AgentConfig,\n GenerateTextResult,\n StreamTextResult,\n OutputType,\n AsToolMapOutput,\n} from \"./agent\";\n\nexport {\n Workflow,\n WorkflowBranchError,\n WorkflowLoopError,\n NestedGateUnsupportedError,\n CheckpointTimeoutError,\n CHECKPOINT_STEP_ID,\n migrateSnapshot,\n} from \"./workflow\";\n\n// `SKIP` is a unique-symbol sentinel returned from `foreach`'s `onError` to\n// omit an item from the output array. It mirrors `Workflow.SKIP` and is\n// re-exported here so consumers who only `import type { SealedWorkflow }` can\n// still reach the runtime value without importing the full `Workflow` class.\nimport { Workflow as _WorkflowForSkip } from \"./workflow\";\nexport const SKIP = _WorkflowForSkip.SKIP;\nexport type { SealedWorkflow, ResumedWorkflow, CheckpointResumedWorkflow } from \"./workflow\";\nexport type {\n AgentStepHooks,\n AgentResultParams,\n StepOptions,\n BranchCase,\n BranchSelect,\n RepeatOptions,\n WorkflowResult,\n WorkflowStreamResult,\n WorkflowStreamOptions,\n WorkflowSnapshot,\n GateSnapshot,\n CheckpointSnapshot,\n LegacyGateSnapshotV1,\n WorkflowWarning,\n WorkflowStepType,\n WorkflowObservability,\n RunOptions,\n ParallelTarget,\n ParallelOutputRecord,\n ParallelOutputTuple,\n ParallelOptions,\n} from \"./workflow\";\n\nexport { defineTool, ToolProvider, isToolProvider, TOOL_PROVIDER_BRAND } from \"./tool-provider\";\nexport type { ToolProviderConfig, ToolExecuteOptions, IToolProvider } from \"./tool-provider\";\n\nexport { getActiveWriter } from \"./utils\";\nexport type { MaybePromise, Resolvable } from \"./utils\";\n"],"mappings":"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","names":["tool","tool","result","stepId","node"]}
1
+ {"version":3,"sources":["../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts","../src/index.ts"],"sourcesContent":["import {\n generateText,\n streamText,\n tool,\n Output,\n type GenerateTextResult as AIGenerateTextResult,\n type StreamTextResult as AIStreamTextResult,\n type UIMessageStreamWriter,\n type ModelMessage,\n type LanguageModel,\n type Tool,\n type ToolSet,\n type StopCondition,\n type ToolChoice,\n type OnStepFinishEvent,\n type OnFinishEvent,\n} from \"ai\";\n\n// Extract the Output interface type from the Output.object return type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type OutputType<T = any> = ReturnType<typeof Output.object<T>>;\nimport type { ZodType } from \"zod\";\nimport { isToolProvider, TOOL_PROVIDER_BRAND, type IToolProvider } from \"./tool-provider\";\nimport { extractOutput, getActiveWriter, resolveValue, type MaybePromise, type Resolvable } from \"./utils\";\n\n// Tools config accepts both AI SDK tools and context-aware ToolProviders\ntype AgentToolSet<TContext> = Record<string, Tool | IToolProvider<TContext>>;\n\n// ── Result type aliases ─────────────────────────────────────────────\n\nexport type GenerateTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIGenerateTextResult<TOOLS, OUTPUT>;\nexport type StreamTextResult<TOOLS extends ToolSet = ToolSet, OUTPUT extends OutputType = OutputType> = AIStreamTextResult<TOOLS, OUTPUT>;\n\n/**\n * The result passed to `asTool` / `asToolProvider`'s `mapOutput`.\n *\n * The same agent may be invoked as a tool from a generate-mode parent\n * (returns `GenerateTextResult`, sync `.text`/`.output`) or from a\n * stream-mode parent (returns `StreamTextResult`, async `.text`/`.output`).\n * The callsite cannot statically tell which mode it is in, so `mapOutput`\n * receives the union and must `await` the relevant fields to support both.\n */\nexport type AsToolMapOutput<TOutput> = (\n result:\n | GenerateTextResult<ToolSet, OutputType<TOutput>>\n | StreamTextResult<ToolSet, OutputType<TOutput>>,\n) => MaybePromise<TOutput>;\n\n// ── AI SDK passthrough types ────────────────────────────────────────\n\n// Extract options types from both AI SDK entry points\ntype StreamTextOptions = Parameters<typeof streamText>[0];\ntype GenerateTextOptions = Parameters<typeof generateText>[0];\n\n// Keys we replace with resolvable or context-enriched versions\ntype ManagedKeys =\n | 'model' | 'system' | 'prompt' | 'messages'\n | 'tools' | 'activeTools' | 'toolChoice' | 'stopWhen'\n | 'output' | 'onFinish' | 'onStepFinish' | 'onError';\n\n// Combine options from both streamText and generateText.\n// Each side contributes its unique props; shared props merge naturally.\n// Stream-only props (onChunk, onAbort) are ignored by generateText.\n// Generate-only props (experimental_include.responseBody) are ignored by streamText.\ntype AIPassthroughOptions =\n Omit<StreamTextOptions, ManagedKeys> &\n Omit<GenerateTextOptions, ManagedKeys>;\n\n// ── Resolved config (output of resolveConfig / resolveConfigAsync) ──\n\ninterface ResolvedAgentConfig {\n model: LanguageModel;\n prompt: string | undefined;\n system: string | undefined;\n messages: ModelMessage[] | undefined;\n tools: Record<string, Tool>;\n activeTools: string[] | undefined;\n toolChoice: ToolChoice<ToolSet> | undefined;\n stopWhen: StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined;\n}\n\n// ── Agent Configuration ─────────────────────────────────────────────\n\nexport interface AgentConfig<\n TContext,\n TInput = void,\n TOutput = void,\n> extends AIPassthroughOptions {\n // ── Custom (not in AI SDK) ──\n id: string;\n description?: string;\n input?: ZodType<TInput>;\n output?: OutputType<TOutput>;\n /**\n * Zod schema used to validate `output` after the AI SDK returns. Distinct\n * from `tool.outputSchema` (AI SDK's tool-execution output schema): this\n * runs **after** the SDK has parsed structured output, as a runtime guard\n * against parse drift. If omitted, the parsed output is trusted as-is.\n */\n validateOutput?: ZodType<TOutput>;\n\n // ── Resolvable (our versions of AI SDK properties) ──\n model: Resolvable<TContext, TInput, LanguageModel>;\n system?: Resolvable<TContext, TInput, string>;\n prompt?: Resolvable<TContext, TInput, string>;\n messages?: Resolvable<TContext, TInput, ModelMessage[]>;\n tools?: Resolvable<TContext, TInput, AgentToolSet<TContext>>;\n activeTools?: Resolvable<TContext, TInput, string[]>;\n toolChoice?: Resolvable<TContext, TInput, ToolChoice<ToolSet>>;\n /**\n * Stop condition(s) for the tool loop. Pass either a single AI-SDK\n * `StopCondition` (which is itself a function) or an array of them.\n *\n * **Not a `Resolvable`.** A `StopCondition` and a `(ctx, input) => StopCondition`\n * resolver are both functions and cannot be safely distinguished at\n * runtime, so this field intentionally does NOT accept the resolver\n * form. If you need per-call dynamic stop conditions, build the agent\n * inside your handler instead of using a static instance.\n */\n stopWhen?: StopCondition<ToolSet> | Array<StopCondition<ToolSet>>;\n\n // ── Context-enriched callbacks (replace AI SDK versions) ──\n // `writer` is available when the agent runs inside a streaming workflow.\n onStepFinish?: (params: { result: OnStepFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onFinish?: (params: { result: OnFinishEvent; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n onError?: (params: { error: unknown; ctx: Readonly<TContext>; input: TInput; writer?: UIMessageStreamWriter }) => MaybePromise<void>;\n}\n\n// ── Agent ───────────────────────────────────────────────────────────\n\nexport class Agent<\n TContext,\n TInput = void,\n TOutput = void,\n> {\n readonly id: string;\n readonly description: string;\n readonly hasOutput: boolean;\n /**\n * Zod schema used to validate the agent's structured `output` after the AI\n * SDK returns. Distinct from `tool.outputSchema` (which validates tool\n * execution output). Exposed (readonly) so external runners — notably the\n * workflow runtime — can pass it through to `extractOutput` without\n * re-plumbing it.\n */\n readonly validateOutput: ZodType<TOutput> | undefined;\n private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n private readonly _passthrough: Record<string, unknown>;\n private readonly _onStepFinish: AgentConfig<TContext, TInput, TOutput>['onStepFinish'];\n private readonly _onFinish: AgentConfig<TContext, TInput, TOutput>['onFinish'];\n\n constructor(config: AgentConfig<TContext, TInput, TOutput>) {\n this.id = config.id;\n this.description = config.description ?? \"\";\n this.hasOutput = config.output !== undefined;\n this.validateOutput = config.validateOutput;\n this.config = config;\n // NOTE: `stopWhen` is intentionally excluded. A bare `StopCondition` is\n // itself a function (`({ steps }) => boolean`), so the typeof-function\n // resolver heuristic in `resolveValue` would misidentify it as a\n // `(ctx, input) => ...` Resolvable and call it with the wrong shape.\n // For `stopWhen` we always treat a function value as a static\n // StopCondition; dynamic stopWhen must return an array\n // (`(ctx, input) => [stepCountIs(5)]`), which is the unambiguous form.\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice,\n ].some(v => typeof v === \"function\");\n\n // Cache tools when config is static and contains no ToolProviders.\n // Avoids re-iterating the tools map on every generate()/stream() call.\n if (!this._hasDynamicConfig) {\n const rawTools = (config.tools as AgentToolSet<TContext> | undefined) ?? {};\n const hasProvider = Object.values(rawTools).some(v => isToolProvider(v));\n if (!hasProvider) {\n this._resolvedStaticTools = rawTools as Record<string, Tool>;\n }\n }\n\n // Pre-compute the passthrough (AI SDK options we don't manage) once,\n // rather than destructuring on every generate()/stream() call.\n const {\n id: _id, description: _desc, input: _inputSchema, output: _output, validateOutput: _validateOutput,\n model: _m, system: _s, prompt: _p, messages: _msg,\n tools: _t, activeTools: _at, toolChoice: _tc, stopWhen: _sw,\n onStepFinish, onFinish, onError: _onError,\n ...passthrough\n } = config;\n this._passthrough = passthrough;\n this._onStepFinish = onStepFinish;\n this._onFinish = onFinish;\n }\n\n async generate(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: { abortSignal?: AbortSignal }]\n : [input: TInput, options?: { abortSignal?: AbortSignal }]\n ): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const callOptions = args[1] as { abortSignal?: AbortSignal } | undefined;\n return this.generateWithOptions(ctx, input, callOptions ?? {});\n }\n\n async stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: { abortSignal?: AbortSignal }]\n : [input: TInput, options?: { abortSignal?: AbortSignal }]\n ): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const callOptions = args[1] as { abortSignal?: AbortSignal } | undefined;\n return this.streamWithOptions(ctx, input, callOptions ?? {});\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: AsToolMapOutput<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: AsToolMapOutput<TOutput>;\n }): IToolProvider<TContext> {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asToolProvider() requires an input schema`);\n }\n\n return {\n [TOOL_PROVIDER_BRAND]: true as const,\n createTool: (ctx: Readonly<TContext>) => this.createToolInstance(ctx as TContext, options),\n };\n }\n\n private createToolInstance(ctx: TContext, options?: {\n mapOutput?: AsToolMapOutput<TOutput>;\n }): Tool {\n if (!this.config.input) {\n throw new Error(`Agent \"${this.id}\": asTool() requires an input schema`);\n }\n\n return tool<TInput, TOutput>({\n description: this.description,\n inputSchema: this.config.input,\n // The AI SDK passes a `ToolExecutionOptions` argument that carries\n // `abortSignal`, `toolCallId`, `messages`, etc. Forward `abortSignal` so\n // a parent agent's abort cancels in-flight sub-agent calls instead of\n // leaving them running and producing detached output.\n execute: async (toolInput: TInput, execOptions?: { abortSignal?: AbortSignal }) => {\n const abortSignal = execOptions?.abortSignal;\n // When inside a streaming workflow, automatically use stream() and merge to the active writer.\n // Otherwise fall back to generate().\n const writer = getActiveWriter();\n if (writer) {\n const result = await this.streamWithOptions(ctx, toolInput, { abortSignal });\n writer.merge(result.toUIMessageStream());\n // Drain the text side to release the StreamTextResult anchor — the\n // writer.merge above only consumes the UI-message side, leaving\n // `result.text` pending until awaited.\n //\n // When mapOutput is provided, we explicitly do NOT call extractOutput\n // here: extractOutput throws if `hasOutput` is true but the model\n // returned no structured value, which would block any mapOutput that\n // wanted to recover from missing/malformed structured output by\n // reading `result.text`. mapOutput becomes the user's chance to do\n // their own extraction.\n if (options?.mapOutput) {\n await result.text;\n return options.mapOutput(result);\n }\n return extractOutput(result, this.hasOutput, this.validateOutput);\n }\n const result = await this.generateWithOptions(ctx, toolInput, { abortSignal });\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput, this.validateOutput);\n },\n // TS cannot simplify the SDK's `NeverOptional<TOutput, ...>` conditional in a\n // generic context, so we cast through `unknown` instead of `any`.\n } as unknown as Tool<TInput, TOutput>);\n }\n\n // ── Internal: shared call helpers ─────────────────────────────\n // `generate()` / `stream()` and the `asTool()` wrapper all funnel through\n // these so the abortSignal-forwarding and onError-wrapping logic stays in\n // one place. `extra` carries per-call overrides (currently `abortSignal`).\n\n // If the user-supplied onError callback itself throws, attach the original\n // model error as `.cause` on the new error and rethrow the wrapper. Without\n // this, the original error is silently shadowed.\n private async invokeOnError(error: unknown, ctx: TContext, input: TInput): Promise<void> {\n if (!this.config.onError) return;\n try {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n } catch (handlerError) {\n // Promote non-Error throws (`throw \"boom\"`, `throw 42`, etc.) so we\n // can chain the original error onto a real Error and keep diagnostics\n // intact. Re-throwing the raw non-Error value would drop the chain.\n if (handlerError instanceof Error) {\n if (handlerError.cause === undefined) {\n (handlerError as { cause?: unknown }).cause = error;\n }\n throw handlerError;\n }\n const wrapped = new Error(\n `Agent \"${this.id}\": onError handler threw a non-Error value (${typeof handlerError}): ${String(handlerError)}`,\n );\n (wrapped as { cause?: unknown }).cause = error;\n throw wrapped;\n }\n }\n\n private async generateWithOptions(\n ctx: TContext,\n input: TInput,\n extra: { abortSignal?: AbortSignal },\n ): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n try {\n // The SDK's `Output.object<T>` return type doesn't simplify generically\n // — cast through `unknown` rather than `any` so we keep the boundary\n // narrow without forcing the call site to know SDK option internals.\n return (await generateText({ ...options, ...extra } as unknown as Parameters<typeof generateText>[0])) as GenerateTextResult<ToolSet, OutputType<TOutput>>;\n } catch (error: unknown) {\n await this.invokeOnError(error, ctx, input);\n throw error;\n }\n }\n\n private async streamWithOptions(\n ctx: TContext,\n input: TInput,\n extra: { abortSignal?: AbortSignal },\n ): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n try {\n // Only attach `onError` when the user supplied one. Setting it to\n // `undefined` explicitly suppresses some SDK versions' default\n // rethrow-on-partial-stream-error, silently swallowing stream failures.\n const onErrorOption = this.config.onError\n ? { onError: ({ error }: { error: unknown }) => this.invokeOnError(error, ctx, input) }\n : {};\n return streamText({\n ...options,\n ...extra,\n ...onErrorOption,\n } as unknown as Parameters<typeof streamText>[0]) as StreamTextResult<ToolSet, OutputType<TOutput>>;\n } catch (error: unknown) {\n // streamText typically defers errors to the returned stream, but a\n // synchronous throw (e.g., invalid options) would otherwise bypass\n // onError entirely.\n await this.invokeOnError(error, ctx, input);\n throw error;\n }\n }\n\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, unknown> {\n if (resolved.messages === undefined && resolved.prompt === undefined) {\n throw new Error(\n `Agent \"${this.id}\": neither \\`prompt\\` nor \\`messages\\` was provided. ` +\n `Configure one of them, or supply a Resolvable that returns one based on input.`,\n );\n }\n return {\n ...this._passthrough,\n model: resolved.model,\n tools: resolved.tools,\n activeTools: resolved.activeTools,\n toolChoice: resolved.toolChoice,\n stopWhen: resolved.stopWhen,\n ...(resolved.messages !== undefined\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt }),\n // Use `!== undefined` rather than truthy so an intentional empty\n // `system: \"\"` survives instead of being silently dropped.\n ...(resolved.system !== undefined ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n // Only attach the callback when the user supplied one. Passing\n // `undefined` explicitly can suppress default SDK rethrow behavior in\n // some versions.\n ...(this._onStepFinish\n ? { onStepFinish: (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() }) }\n : {}),\n ...(this._onFinish\n ? { onFinish: (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() }) }\n : {}),\n };\n }\n\n private resolveConfig(ctx: TContext, input: TInput): ResolvedAgentConfig | Promise<ResolvedAgentConfig> {\n if (!this._hasDynamicConfig) {\n return {\n model: this.config.model as LanguageModel,\n prompt: this.config.prompt as string | undefined,\n system: this.config.system as string | undefined,\n messages: this.config.messages as ModelMessage[] | undefined,\n tools: this._resolvedStaticTools ?? this.resolveTools(\n (this.config.tools as AgentToolSet<TContext> | undefined) ?? {}, ctx\n ),\n activeTools: this.config.activeTools as string[] | undefined,\n toolChoice: this.config.toolChoice as ToolChoice<ToolSet> | undefined,\n stopWhen: this.config.stopWhen as StopCondition<ToolSet> | Array<StopCondition<ToolSet>> | undefined,\n };\n }\n return this.resolveConfigAsync(ctx, input);\n }\n\n private async resolveConfigAsync(ctx: TContext, input: TInput): Promise<ResolvedAgentConfig> {\n const [model, prompt, system, messages, rawTools, activeTools, toolChoice] = await Promise.all([\n resolveValue(this.config.model, ctx, input),\n resolveValue(this.config.prompt, ctx, input),\n resolveValue(this.config.system, ctx, input),\n resolveValue(this.config.messages, ctx, input),\n resolveValue(this.config.tools, ctx, input),\n resolveValue(this.config.activeTools, ctx, input),\n resolveValue(this.config.toolChoice, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return {\n model,\n prompt,\n system,\n messages,\n tools,\n activeTools,\n toolChoice,\n // `stopWhen` is always static — see field declaration for why.\n stopWhen: this.config.stopWhen,\n };\n }\n\n private resolveTools(\n tools: AgentToolSet<TContext>,\n ctx: TContext\n ): Record<string, Tool> {\n const entries = Object.entries(tools);\n if (entries.length === 0) return tools as Record<string, Tool>;\n let hasProvider = false;\n const resolved: Record<string, Tool> = {};\n for (const [key, toolOrProvider] of entries) {\n if (isToolProvider<TContext>(toolOrProvider)) {\n hasProvider = true;\n resolved[key] = toolOrProvider.createTool(ctx as Readonly<TContext>);\n } else {\n resolved[key] = toolOrProvider as Tool;\n }\n }\n return hasProvider ? resolved : (tools as Record<string, Tool>);\n }\n}\n","import { tool, type Tool, type ToolExecutionOptions, type FlexibleSchema, type UIMessageStreamWriter } from \"ai\";\nimport { getActiveWriter } from \"./utils\";\n\nexport const TOOL_PROVIDER_BRAND = Symbol.for(\"agent-workflow.ToolProvider\");\n\nexport type ToolExecuteOptions = ToolExecutionOptions & {\n writer?: UIMessageStreamWriter;\n};\n\ntype ToolProviderOptions = NonNullable<Tool[\"providerOptions\"]>;\n\nexport type ToolProviderConfig<TContext, TInput, TOutput> = {\n description?: string;\n input: FlexibleSchema<TInput>;\n outputSchema?: FlexibleSchema<TOutput>;\n providerOptions?: ToolProviderOptions;\n execute: (input: TInput, ctx: Readonly<TContext>, options: ToolExecuteOptions) => Promise<TOutput>;\n};\n\nexport interface IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND]: true;\n createTool(context: Readonly<TContext>): Tool;\n}\n\nexport class ToolProvider<\n TContext,\n TInput = unknown,\n TOutput = unknown,\n> implements IToolProvider<TContext> {\n readonly [TOOL_PROVIDER_BRAND] = true as const;\n private readonly config: ToolProviderConfig<TContext, TInput, TOutput>;\n\n constructor(config: ToolProviderConfig<TContext, TInput, TOutput>) {\n this.config = config;\n }\n\n createTool(context: Readonly<TContext>): Tool {\n const { execute, input: inputSchema, ...toolDef } = this.config;\n // The shape matches `Tool<TInput, TOutput>`, but TS cannot simplify the SDK's\n // `NeverOptional<TOutput, ...>` conditional in a generic context, so the literal\n // is not assignable directly. Cast through `unknown` rather than `any` so the\n // return type and call sites still get type-checked.\n return tool<TInput, TOutput>({\n ...toolDef,\n inputSchema,\n execute: (input: TInput, options: ToolExecutionOptions) => execute(input, context, { ...options, writer: getActiveWriter() } as ToolExecuteOptions),\n } as unknown as Tool<TInput, TOutput>);\n }\n}\n\nexport function defineTool<TContext>() {\n return <TInput, TOutput>(\n config: ToolProviderConfig<TContext, TInput, TOutput>\n ): ToolProvider<TContext, TInput, TOutput> => new ToolProvider(config);\n}\n\nexport function isToolProvider<TContext>(obj: unknown): obj is IToolProvider<TContext> {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n TOOL_PROVIDER_BRAND in obj\n );\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createHash } from \"node:crypto\";\nimport type { UIMessageStreamWriter } from \"ai\";\nimport type { ZodType } from \"zod\";\n\n// ── Stream writer context ────────────────────────────────────────────\n// Invisible to the user. The workflow sets the writer before agent execution;\n// tools and sub-agents read it automatically via getActiveWriter().\n\nconst writerStorage = new AsyncLocalStorage<UIMessageStreamWriter>();\n\nexport function runWithWriter<T>(writer: UIMessageStreamWriter, fn: () => T): T {\n return writerStorage.run(writer, fn);\n}\n\n/**\n * Returns the active `UIMessageStreamWriter` if the current async context is\n * running inside a streaming workflow, or `undefined` otherwise.\n *\n * Use from inside a custom `IToolProvider`'s returned `Tool.execute` callback\n * to forward incremental output to the workflow's UI message stream:\n *\n * ```ts\n * import { getActiveWriter, type IToolProvider, TOOL_PROVIDER_BRAND } from \"pipeai\";\n *\n * const myProvider: IToolProvider<MyCtx> = {\n * [TOOL_PROVIDER_BRAND]: true,\n * createTool(ctx) {\n * return tool({\n * execute: async (input) => {\n * const writer = getActiveWriter();\n * // ...stream incremental progress to writer if present...\n * return result;\n * },\n * });\n * },\n * };\n * ```\n *\n * **Important timing note:** call this from *inside* the `Tool.execute`\n * callback, not from inside `createTool` itself. `createTool` runs during\n * agent setup (before the workflow has set the writer); `Tool.execute` runs\n * during tool invocation (when the writer is live).\n */\nexport function getActiveWriter(): UIMessageStreamWriter | undefined {\n return writerStorage.getStore();\n}\n\n// ── Common types ─────────────────────────────────────────────────────\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * A value that can be static or derived from context and input.\n * Used for agent config fields that may need runtime resolution.\n *\n * Functions may return a Promise for async resolution; static values are always sync.\n */\nexport type Resolvable<TCtx, TInput, TValue> =\n | TValue\n | ((ctx: Readonly<TCtx>, input: TInput) => TValue | Promise<TValue>);\n\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue>,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue>;\nexport function resolveValue<TCtx, TInput, TValue>(\n value: Resolvable<TCtx, TInput, TValue> | undefined,\n ctx: TCtx,\n input: TInput\n): TValue | Promise<TValue> | undefined {\n if (typeof value === \"function\") {\n return (value as (ctx: TCtx, input: TInput) => TValue | Promise<TValue>)(ctx, input);\n }\n return value;\n}\n\n/**\n * Minimal counting semaphore. Up to `permits` callers can hold a permit\n * concurrently; further `acquire()` calls queue FIFO until one is released.\n */\nexport class Semaphore {\n private available: number;\n private waiters: Array<() => void> = [];\n\n constructor(permits: number) {\n if (!Number.isInteger(permits) || permits < 1) {\n throw new Error(`Semaphore: permits must be a positive integer, got ${permits}`);\n }\n this.available = permits;\n }\n\n async acquire(): Promise<void> {\n if (this.available > 0) {\n this.available--;\n return;\n }\n await new Promise<void>(resolve => this.waiters.push(resolve));\n }\n\n release(): void {\n const next = this.waiters.shift();\n if (next) next();\n else this.available++;\n }\n}\n\n/**\n * Extract structured output from an AI SDK result.\n *\n * - When `hasStructuredOutput` is `true`, awaits `result.output`. If the SDK\n * did not produce a structured value, this throws — silent fall-back to raw\n * text would mask schema mismatches at the call site.\n * - When `schema` is provided, the awaited output is validated through the\n * Zod schema before being returned, catching SDK-side parse drift.\n * - When `hasStructuredOutput` is `false`, returns `result.text`.\n *\n * Works for both generate (sync .output/.text) and stream (async .output/.text) results.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function extractOutput(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result: any,\n hasStructuredOutput: boolean,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema?: ZodType<any>,\n): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output === undefined) {\n throw new Error(\n \"Agent: structured output was declared but the model returned none. \" +\n \"This usually means the model produced text that did not match the declared schema, \" +\n \"or the underlying SDK did not parse the structured output.\",\n );\n }\n if (schema) {\n return schema.parse(output);\n }\n return output;\n }\n return await result.text;\n}\n\n/**\n * Recursively freeze an object graph. Cycles are tracked via a WeakSet so we\n * never recurse into the same node twice. Maps/Sets stay structurally frozen\n * but `.set()`/`.add()` still mutate them — Object.freeze doesn't cover those.\n */\nexport function deepFreeze<T>(value: T, seen: WeakSet<object> = new WeakSet()): T {\n if (value === null || typeof value !== \"object\" || seen.has(value as object)) return value;\n // Already-frozen subtree (e.g. user-passed frozen ctx) — its children are\n // either also frozen or intentionally mutable, either way we should not recurse.\n if (Object.isFrozen(value)) return value;\n seen.add(value as object);\n Object.freeze(value);\n for (const key of Reflect.ownKeys(value as object)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n deepFreeze((value as any)[key], seen);\n }\n return value;\n}\n\n// ── stepShapeHash (F1) ───────────────────────────────────────────────\n//\n// Recursive SHA-256 of the workflow's structural shape (index, type, id,\n// nested workflow shapes). Used by checkpoint resume to detect drift —\n// when the user inserts/removes/reorders a step, the hash changes and\n// resume refuses to continue unless explicitly told to via\n// `{ skipShapeCheck: true }`.\n//\n// **Agent identity is NOT in the hash.** Two checkpoints from runs that\n// used different agent configs (same id) hash identically. Version agents\n// by content if resume-trust matters.\n\n/**\n * The minimal shape interface this util needs from a `SealedWorkflow`.\n * Importing the workflow class here would create a circular dependency\n * (utils.ts ← workflow.ts and workflow.ts ← utils.ts); so we accept any\n * object exposing `id` and `getStepsForShapeHash()`.\n */\nexport interface WorkflowShapeHashable {\n readonly id?: string;\n // Returns the StepNode[] for this workflow. Structurally typed to avoid\n // a circular import — the real type is `ReadonlyArray<StepNode>`.\n getStepsForShapeHash(): ReadonlyArray<StepNodeShape>;\n}\n\n/**\n * Structural typing for a StepNode as seen by the shape hasher. Mirrors\n * the actual `StepNode` union without importing it. Adding fields to\n * StepNode without updating this contract won't fail compilation; the\n * dispatch map in workflow.ts (typed via `Record<StepNode[\"type\"], ...>`)\n * is the load-bearing exhaustiveness guard.\n */\nexport interface StepNodeShape {\n readonly type: string;\n readonly id: string;\n}\n\nexport function computeStepShapeHash(\n steps: ReadonlyArray<StepNodeShape>,\n getNested: (node: StepNodeShape) => readonly WorkflowShapeHashable[],\n): string {\n return createHash(\"sha256\").update(canonicalDescriptor(steps, getNested, new WeakSet())).digest(\"hex\");\n}\n\n/**\n * `path` tracks the current DFS stack only — added on entry, removed on exit.\n * Sibling re-visits of the same SealedWorkflow are NOT cycles (shared\n * subgraphs hash identically to two structurally-equivalent distinct\n * instances). Only ancestor re-visits (true cycles) emit the cycle marker.\n */\nfunction canonicalDescriptor(\n steps: ReadonlyArray<StepNodeShape>,\n getNested: (node: StepNodeShape) => readonly WorkflowShapeHashable[],\n path: WeakSet<WorkflowShapeHashable>,\n): string {\n return JSON.stringify(steps.map((s, i) => {\n const triple: (number | string)[] = [i, s.type, s.id];\n for (const inner of getNested(s)) {\n if (path.has(inner)) {\n triple.push(`<cycle:${inner.id ?? \"anon\"}>`);\n continue;\n }\n path.add(inner);\n try {\n triple.push(canonicalDescriptor(inner.getStepsForShapeHash(), getNested, path));\n } finally {\n path.delete(inner);\n }\n }\n return triple;\n }));\n}\n\n// ── warnOnce (F1) — module-level dedup helper ────────────────────────\n\nconst warnedOnceKeys = new Set<string>();\nexport function warnOnce(key: string, message?: string): void {\n if (warnedOnceKeys.has(key)) return;\n warnedOnceKeys.add(key);\n // eslint-disable-next-line no-console\n console.warn(message ?? key);\n}\n\n/**\n * @internal — test-only reset of the warnOnce dedup. Same shape as\n * workflow.ts's `__resetStreamOnErrorOnSuspendWarnForTests`.\n */\nexport function __resetWarnOnceForTests(): void {\n warnedOnceKeys.clear();\n}\n","import {\n createUIMessageStream,\n type UIMessage,\n type UIMessageStreamWriter,\n type UIMessageStreamOnFinishCallback,\n type IdGenerator,\n type ToolSet,\n} from \"ai\";\nimport { type Agent, type GenerateTextResult, type StreamTextResult, type OutputType } from \"./agent\";\nimport { computeStepShapeHash, deepFreeze, extractOutput, runWithWriter, warnOnce, type MaybePromise } from \"./utils\";\n\n// ── Error Types ─────────────────────────────────────────────────────\n\nexport class WorkflowBranchError extends Error {\n constructor(\n public readonly branchType: \"predicate\" | \"select\",\n message: string,\n ) {\n super(message);\n this.name = \"WorkflowBranchError\";\n }\n}\n\nexport class WorkflowLoopError extends Error {\n constructor(\n public readonly iterations: number,\n public readonly maxIterations: number,\n ) {\n super(`Loop exceeded maximum iterations (${maxIterations})`);\n this.name = \"WorkflowLoopError\";\n }\n}\n\nexport class NestedGateUnsupportedError extends Error {\n readonly gateId: string;\n readonly workflowId: string | undefined;\n // Always present; non-gate rejections from concurrent foreach.\n readonly siblingErrors: readonly unknown[];\n // Always present; OTHER suspending items in concurrent foreach.\n readonly siblingSuspensions: readonly { index: number; gateId: string }[];\n\n constructor(\n gateId: string,\n workflowId: string | undefined,\n siblingErrors: readonly unknown[] = [],\n siblingSuspensions: readonly { index: number; gateId: string }[] = [],\n ) {\n super(`Gate \"${gateId}\" hit inside nested workflow \"${workflowId ?? \"(anonymous)\"}\". Nested gates are not yet supported.`);\n this.name = \"NestedGateUnsupportedError\";\n this.gateId = gateId;\n this.workflowId = workflowId;\n this.siblingErrors = siblingErrors;\n this.siblingSuspensions = siblingSuspensions;\n }\n}\n\n// ── Snapshot / Warnings / Run options ────────────────────────────────\n\n/**\n * v2 gate snapshot. The `kind` discriminant differentiates it from\n * checkpoint snapshots. The legacy v1 form is still accepted by `loadState`.\n */\nexport interface GateSnapshot {\n readonly version: 2;\n readonly kind: \"gate\";\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\n/**\n * v2 checkpoint snapshot. Carries a step-shape hash; resume verifies the\n * workflow definition hasn't drifted before continuing.\n */\nexport interface CheckpointSnapshot {\n readonly version: 2;\n readonly kind: \"checkpoint\";\n readonly resumeFromIndex: number; // index of the NEXT step to run\n readonly output: unknown;\n readonly stepShapeHash: string; // SHA-256 hex of canonical recursive shape\n}\n\n/**\n * Legacy v0.4.0 gate-only snapshot. Accepted by `loadState` for one release\n * via the shim path. `kind?: undefined` makes runtime narrowing on\n * `kind === undefined` reachable — JSON round-trips strip the property.\n * Migrate via `migrateSnapshot()` before v0.8.0+.\n */\nexport interface LegacyGateSnapshotV1 {\n readonly version: 1;\n readonly kind?: undefined;\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\nexport type WorkflowSnapshot = GateSnapshot | CheckpointSnapshot | LegacyGateSnapshotV1;\n\nexport interface WorkflowWarning {\n readonly source:\n | \"step\"\n | \"finally\"\n | \"catch\"\n | \"onCheckpoint\"\n | \"onStepStart\"\n | \"onStepFinish\"\n | \"onStepError\"\n | \"foreach-sibling\";\n readonly stepId: string;\n readonly error: unknown;\n}\n\nexport type WorkflowStepType =\n | \"step\"\n | \"nested\"\n | \"gate\"\n | \"catch\"\n | \"finally\"\n | \"branch\"\n | \"foreach\"\n | \"repeat\"\n | \"parallel\";\n\n/**\n * Workflow observability hooks. All optional. Errors thrown inside hooks\n * are captured into `result.warnings` with a matching `source` tag, except\n * `onStepError`, which causes the run to throw the ORIGINAL step error with\n * `error.cause = obsError` (preserving `instanceof` on the original).\n *\n * Per-node firing rules (where \"step-like\" = step / nested / branch /\n * foreach / parallel / repeat):\n * - step-like / gate (cond-true → suspends): onStepStart always; onStepFinish\n * when body returns (suspended: true for gate, false otherwise); onStepError\n * on body throw.\n * - gate (cond false → skip): onStepStart, onStepFinish({ suspended: false }).\n * - catch: onStepStart only when pendingError set; onStepFinish when catchFn\n * returns; onStepError when catchFn throws.\n * - finally: onStepStart always (runs even after suspension); onStepFinish\n * always; onStepError when body throws.\n * - foreach / parallel: emit ALSO per-item events (onItemStart/Finish/Error).\n * - repeat: emit ONLY combinator-level events (no per-iteration events —\n * iteration count is data-dependent and per-item would be misleading).\n *\n * Skip-checked nodes (`state.suspension || pendingError` already set on entry)\n * emit nothing — `.finally()` is the exception.\n */\nexport interface WorkflowObservability {\n onStepStart?: (event: {\n stepId: string;\n type: WorkflowStepType;\n ctx: unknown;\n input: unknown;\n }) => MaybePromise<void>;\n onStepFinish?: (event: {\n stepId: string;\n type: WorkflowStepType;\n ctx: unknown;\n output: unknown;\n durationMs: number;\n suspended: boolean;\n }) => MaybePromise<void>;\n onStepError?: (event: {\n stepId: string;\n type: WorkflowStepType;\n ctx: unknown;\n error: unknown;\n durationMs: number;\n }) => MaybePromise<void>;\n onItemStart?: (event: {\n stepId: string;\n type: \"foreach\" | \"parallel\";\n itemIndex: number | string;\n ctx: unknown;\n input: unknown;\n }) => MaybePromise<void>;\n onItemFinish?: (event: {\n stepId: string;\n type: \"foreach\" | \"parallel\";\n itemIndex: number | string;\n ctx: unknown;\n output: unknown;\n durationMs: number;\n }) => MaybePromise<void>;\n onItemError?: (event: {\n stepId: string;\n type: \"foreach\" | \"parallel\";\n itemIndex: number | string;\n ctx: unknown;\n error: unknown;\n durationMs: number;\n }) => MaybePromise<void>;\n}\n\nexport interface RunOptions {\n /**\n * Step-level checkpoint sink. Called after each successful step body when\n * `checkpointEvery` cadence or `checkpointWhen` predicate fires. Receives a\n * v2 `CheckpointSnapshot` and an `AbortSignal` that aborts on\n * `checkpointTimeout` expiration. Throwing here propagates to the caller\n * as an error — workflow `.catch()` is bypassed for checkpoint failures.\n */\n readonly onCheckpoint?: (snapshot: CheckpointSnapshot, opts: { signal: AbortSignal }) => MaybePromise<void>;\n /**\n * Fire `onCheckpoint` every N executable steps. Mutually exclusive with\n * `checkpointWhen`. Default: `max(1, ceil(executableCount / 4))` —\n * 4 checkpoints across the run, with a floor of every step on tiny pipelines.\n */\n readonly checkpointEvery?: number;\n /**\n * Predicate variant — fire `onCheckpoint` exactly when this returns true.\n * Mutually exclusive with `checkpointEvery`.\n */\n readonly checkpointWhen?: (params: { stepIndex: number; stepId: string; ctx: unknown }) => boolean;\n /**\n * When truthy, deeply freeze the gate / checkpoint snapshot and the\n * `result.warnings` array. Default false. Pass `\"iAcceptThePerformanceCost\"`\n * to bypass `validateRunOptions`' catastrophic-combo guard\n * (freezeSnapshots: true + checkpointEvery: 1 + steps.length >= 8).\n */\n readonly freezeSnapshots?: boolean | \"iAcceptThePerformanceCost\";\n /**\n * Cooperative cancellation signal. Checked at every step boundary inside\n * `execute()` and forwarded to agent calls in `executeAgent`, foreach\n * workers, and nested workflows. When the signal aborts, the workflow\n * tears down to `signal.reason` via the same pending-error path as any\n * other step failure, so `.catch()` handlers still get a chance to\n * observe (or recover from) the abort. `.finally()` bodies still run\n * on the abort path. Unlike `freezeSnapshots`, this option DOES\n * propagate into nested workflows, foreach items, and repeat loops —\n * cancellation should be transitive.\n */\n readonly abortSignal?: AbortSignal;\n /**\n * Maximum ms `onCheckpoint` is allowed to run before its AbortSignal fires.\n * On timeout, a `CheckpointTimeoutError` is raised on the run (catch is\n * bypassed; original error reaches the caller). Default: no timeout.\n */\n readonly checkpointTimeout?: number;\n}\n\n/**\n * Synthetic step id reported when `onCheckpoint` itself throws. Reserved\n * via the construction-time `(type, id)` walk — user step ids may not\n * contain the `::pipeai::` namespace.\n */\nexport const CHECKPOINT_STEP_ID = \"::pipeai::onCheckpoint\" as const;\n\n/**\n * Thrown internally when `onCheckpoint` exceeds `RunOptions.checkpointTimeout`.\n * Surfaces to the caller as the rejection error.\n */\nexport class CheckpointTimeoutError extends Error {\n readonly timeoutMs: number;\n constructor(timeoutMs: number) {\n super(`onCheckpoint exceeded ${timeoutMs}ms timeout`);\n this.name = \"CheckpointTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\nfunction resolveFreezeSnapshots(state: RuntimeState): boolean {\n return state.runOptions?.freezeSnapshots ? true : false;\n}\n\n/**\n * Convert a legacy v1 gate snapshot to a v2 gate snapshot. Long-lived\n * storage (Redis-without-TTL, S3, Postgres) should re-serialize via this\n * helper before v0.8.0+ drops v1 acceptance.\n */\nexport function migrateSnapshot(legacy: LegacyGateSnapshotV1): GateSnapshot {\n if (legacy.version !== 1) {\n throw new Error(`migrateSnapshot: expected v1 snapshot, got version ${(legacy as { version: number }).version}`);\n }\n return {\n version: 2,\n kind: \"gate\",\n resumeFromIndex: legacy.resumeFromIndex,\n output: legacy.output,\n gateId: legacy.gateId,\n gatePayload: legacy.gatePayload,\n };\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\n/**\n * Discriminated union describing one agent invocation's result.\n *\n * - `mode: \"generate\"` — `result` is a `GenerateTextResult`; `.text`, `.output`,\n * `.usage` etc. are synchronous (already-resolved).\n * - `mode: \"stream\"` — `result` is a `StreamTextResult`; the same fields are\n * `Promise`s that you must `await` before reading.\n *\n * The shared field set (`ctx`, `input`) is identical across both modes;\n * narrowing on `mode` is only necessary when you need to touch a\n * mode-specific shape.\n */\nexport type AgentResultParams<TContext, TOutput, TNextOutput> =\n | {\n readonly mode: \"generate\";\n readonly result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>;\n readonly ctx: Readonly<TContext>;\n readonly input: TOutput;\n }\n | {\n readonly mode: \"stream\";\n readonly result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;\n readonly ctx: Readonly<TContext>;\n readonly input: TOutput;\n };\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n /**\n * Transform the agent's result into the next step's input. Fires once per\n * step regardless of generate-vs-stream mode; discriminate on `mode` if you\n * need a mode-specific field. Returning the agent's `result.text` works\n * for both modes (string vs Promise<string>) because `MaybePromise` accepts\n * either.\n *\n * If omitted, the workflow's default extraction is used:\n * - With `agent.output` declared → `extractOutput(result, agent.validateOutput)`\n * - Without `agent.output` → `result.text` (awaited if stream)\n */\n mapResult?: (params: AgentResultParams<TContext, TOutput, TNextOutput>) => MaybePromise<TNextOutput>;\n\n /**\n * Observe the agent's result without changing the step's downstream value.\n * Fires once per step regardless of mode. Use for logging, telemetry,\n * usage accounting, side-effects that should not affect pipeline data\n * flow.\n */\n onResult?: (params: AgentResultParams<TContext, TOutput, TNextOutput>) => MaybePromise<void>;\n\n /**\n * **Stream-mode only.** Override the workflow's default\n * `writer.merge(result.toUIMessageStream())` call so YOU control how the\n * agent's stream reaches the outer workflow's UI message stream. Useful\n * for buffering, transforming, fan-out to multiple writers, or injecting\n * custom UI messages around the agent's output.\n *\n * Has no generate-mode analog because in generate mode there is no stream\n * to merge. If both `handleStream` and `mapResult`/`onResult` are\n * configured, `handleStream` runs first.\n */\n handleStream?: (params: {\n result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;\n writer: UIMessageStreamWriter;\n ctx: Readonly<TContext>;\n input: TOutput;\n }) => MaybePromise<void>;\n}\n\n// ── Step Options ────────────────────────────────────────────────────\n\nexport type StepOptions<TContext, TOutput, TNextOutput> = AgentStepHooks<TContext, TOutput, TNextOutput> & {\n /** Override the default step id (`agent.id`). Required when reusing the same\n * agent across multiple steps in one workflow — the construction-time\n * `(type, id)` walk rejects duplicates. */\n id?: string;\n};\n\n// ── Branch Types ────────────────────────────────────────────────────\n\nexport interface BranchCase<TContext, TOutput, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n when?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n agent: Agent<TContext, TOutput, TNextOutput>;\n}\n\nexport interface BranchSelect<TContext, TOutput, TKeys extends string, TNextOutput> extends AgentStepHooks<TContext, TOutput, TNextOutput> {\n select: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TKeys>;\n agents: Record<TKeys, Agent<TContext, TOutput, TNextOutput>>;\n fallback?: Agent<TContext, TOutput, TNextOutput>;\n /**\n * Diagnostic hook invoked when `select` returns a key that has no matching\n * entry in `agents`. Fires BEFORE `fallback` is applied or\n * `WorkflowBranchError` is thrown, regardless of whether a `fallback` is\n * configured. Useful for logging typos / unexpected classifier output.\n */\n onUnknownKey?: (params: { key: string; availableKeys: TKeys[]; ctx: Readonly<TContext> }) => void;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport type WorkflowResult<TOutput> =\n | { readonly status: \"complete\"; readonly output: TOutput; readonly warnings: readonly WorkflowWarning[] }\n | { readonly status: \"suspended\"; readonly snapshot: GateSnapshot; readonly warnings: readonly WorkflowWarning[] };\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<WorkflowResult<TOutput>>; // never rejects on suspension; rejects on real errors\n}\n\n/**\n * Options for `Workflow.stream` / `ResumedWorkflow.stream` /\n * `CheckpointResumedWorkflow.stream`. Forwarded verbatim to the AI SDK's\n * `createUIMessageStream`.\n *\n * Generic over the UI message shape so consumers with a custom\n * `UIMessage<METADATA, DATA_PARTS, TOOLS>` get their narrowed type in\n * `onFinish` / `originalMessages` instead of the unparameterized default.\n *\n * Note: AI SDK's `createUIMessageStream` ALSO accepts an `onStepFinish`\n * (per-token-step) callback. We intentionally do NOT expose it here — there\n * are already two clearer step-finish callbacks at different granularities:\n * - `Agent.onStepFinish` for per-model-call observation, and\n * - `WorkflowObservability.onStepFinish` for per-workflow-step observation.\n * Adding a third one named the same thing on `WorkflowStreamOptions` would\n * be confusing. Reach for one of the two above instead.\n */\nexport interface WorkflowStreamOptions<UI_MESSAGE extends UIMessage = UIMessage> {\n /**\n * Map an unknown error into a user-visible string. Forwarded as-is to\n * `createUIMessageStream`'s `onError`. Returning `string` is required by\n * the AI SDK — the string is what the stream emits to clients.\n */\n onError?: (error: unknown) => string;\n /**\n * Prior `UIMessage`s the stream should continue from. When provided, the\n * AI SDK assumes persistence mode and assigns a response-message id.\n * Used for chat resumption / continuation flows.\n */\n originalMessages?: UI_MESSAGE[];\n /**\n * Fires once the stream finishes, with the full payload the AI SDK\n * delivers: the updated `messages` array, the freshly-emitted\n * `responseMessage`, `isAborted` / `isContinuation` flags, and the\n * `finishReason`. Use this for persistence, analytics, or downstream\n * notification.\n */\n onFinish?: UIMessageStreamOnFinishCallback<UI_MESSAGE>;\n /**\n * Override the response message-id generator. Forwarded to\n * `createUIMessageStream`'s `generateId` option. Useful for deterministic\n * IDs in tests or coordinating with a server-side ID space.\n */\n generateId?: IdGenerator;\n}\n\n// ── Loop Types ──────────────────────────────────────────────────────\n\ntype LoopPredicate<TContext, TOutput> = (params: {\n output: TOutput;\n ctx: Readonly<TContext>;\n iterations: number;\n}) => MaybePromise<boolean>;\n\n// Exactly one of `until` or `while` — never both.\nexport type RepeatOptions<TContext, TOutput> =\n | { until: LoopPredicate<TContext, TOutput>; while?: never; maxIterations?: number }\n | { while: LoopPredicate<TContext, TOutput>; until?: never; maxIterations?: number };\n\n// Extracts the element type from an array type. Resolves to `never` for non-arrays,\n// making foreach uncallable at compile time when the previous step doesn't produce an array.\ntype ElementOf<T> = T extends readonly (infer E)[] ? E : never;\n\n// ── parallel() supporting types ─────────────────────────────────────\n\n/** A target for a `parallel()` branch — agent or sealed workflow. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ParallelTarget<TContext, TInput> =\n | Agent<TContext, TInput, any>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n | SealedWorkflow<TContext, TInput, any>;\n\n/** Extract the output type of a single parallel branch target. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype BranchOutput<T> = T extends Agent<any, any, infer O>\n ? O\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n : T extends SealedWorkflow<any, any, infer O>\n ? O\n : never;\n\n/** Output shape for the record form: `{ [K]: BranchOutput<T[K]> }`. */\nexport type ParallelOutputRecord<T extends Record<string, unknown>> = {\n [K in keyof T]: BranchOutput<T[K]>;\n};\n\n/** Output shape for the tuple form: `[O1, O2, ...]`. */\nexport type ParallelOutputTuple<T extends ReadonlyArray<unknown>> = {\n [K in keyof T]: BranchOutput<T[K]>;\n};\n\nexport interface ParallelOptions<TContext> {\n /** Override the default step id. Default: `parallel:record` or `parallel:tuple`. */\n id?: string;\n /**\n * Max branches in flight at any moment. Default: `min(branches.length, 5)`.\n * Pass `Infinity` (or `branches.length`) for full fan-out on >5-branch calls\n * — the default caps at 5 to protect against rate limits and emits a\n * one-time warn when the cap kicks in.\n */\n concurrency?: number;\n /**\n * Per-branch error handler. On the no-suspension path, called once per\n * rejected branch in index order after all settle. Return a value to\n * substitute, return `Workflow.SKIP` to leave the slot undefined (record\n * form only — tuple SKIP would shift indices), or rethrow to abort the\n * parallel.\n *\n * **Bypassed entirely on the suspension path** (any branch hit a nested\n * gate). See README's \"Suspension under `parallel()`\" section.\n */\n onError?: (params: {\n error: unknown;\n /** Branch key in the record form; `undefined` in the tuple form. */\n key?: string;\n /** Branch index in the tuple form; `undefined` in the record form. */\n index?: number;\n ctx: Readonly<TContext>;\n }) => unknown | typeof Workflow.SKIP | Promise<unknown | typeof Workflow.SKIP>;\n}\n\n// ── Schema type (structural — works with Zod, Valibot, ArkType, etc.) ──\n\ninterface SchemaWithParse<T = unknown> {\n parse(data: unknown): T;\n}\n\n// ── Step Node ───────────────────────────────────────────────────────\n\n// `nestedWorkflow` is consumed by the recursive `stepShapeHash` walk; runtime\n// execution goes through the `execute` closure. `category` drives\n// observability event typing — keeps a single `type: \"step\"` variant rather\n// than splitting branch/foreach/repeat/parallel/nested into their own unions.\ntype StepCategory = \"step\" | \"nested\" | \"branch\" | \"foreach\" | \"repeat\" | \"parallel\";\n\ntype StepNode =\n | {\n readonly type: \"step\";\n readonly id: string;\n readonly execute: (state: RuntimeState) => MaybePromise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n readonly nestedWorkflow?: SealedWorkflow<any, any, any, any>;\n /** Disambiguates observability events. Default `\"step\"`. */\n readonly category?: StepCategory;\n }\n | { readonly type: \"catch\"; readonly id: string; readonly catchFn: (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown> }\n | { readonly type: \"finally\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\n | { readonly type: \"gate\"; readonly id: string; readonly payload: (state: RuntimeState) => MaybePromise<unknown>; readonly schema?: SchemaWithParse; readonly condition?: (state: RuntimeState) => MaybePromise<boolean>; readonly merge?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown> };\n\n/**\n * Maps a step node's category (or non-step type) to the observability event\n * `type` field. Drives `WorkflowStepType` reporting.\n */\nfunction getObservabilityType(node: StepNode): WorkflowStepType {\n if (node.type !== \"step\") return node.type;\n return (node.category ?? \"step\") as WorkflowStepType;\n}\n\n/**\n * Returns the nested workflow(s) attached to a step node. The exhaustive\n * switch (no `default`) makes adding a new StepNode variant a TS error.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction getNestedWorkflows(node: StepNode): readonly SealedWorkflow<any, any, any, any>[] {\n switch (node.type) {\n case \"step\": return node.nestedWorkflow ? [node.nestedWorkflow] : [];\n case \"gate\":\n case \"catch\":\n case \"finally\": return [];\n }\n}\n\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\n // Only gates set `suspension`.\n suspension?: GateSnapshot;\n warnings?: WorkflowWarning[];\n checkpointFailed?: boolean;\n // Same RunOptions seen by execute(); reset to undefined inside nested\n // workflows and omitted from foreach itemState so per-run config doesn't\n // leak into nested execution.\n runOptions?: RunOptions;\n // Cooperative cancellation. Held on state separately from runOptions\n // because — unlike freezeSnapshots — abortSignal SHOULD propagate into\n // nested workflows and foreach items.\n abortSignal?: AbortSignal;\n}\n\n// Pending error tracked through a single execute() pass. The `source`\n// discriminant drives the precedence tail\n// (checkpointFailed > finally-wrap > step > suspension) and the onStepError\n// type mapping below.\ntype PendingError = {\n error: unknown;\n stepId: string;\n source: \"step\" | \"finally\" | \"catch\" | \"onCheckpoint\";\n};\n\n/**\n * Map `PendingError.source` to the `WorkflowStepType` value that\n * `onStepError` should report. `onCheckpoint` is mapped to `\"step\"`,\n * consistent with the `{ stepId: CHECKPOINT_STEP_ID, type: \"step\" }` contract.\n * Exhaustive switch — adding a new `source` variant is a compile error.\n */\nfunction pendingErrorSourceToStepType(source: PendingError[\"source\"]): WorkflowStepType {\n switch (source) {\n case \"step\": return \"step\";\n case \"finally\": return \"finally\";\n case \"catch\": return \"catch\";\n case \"onCheckpoint\": return \"step\";\n }\n}\n\n/**\n * Invoke `opts.onCheckpoint(snapshot, { signal })` with optional timeout via\n * AbortSignal. Throws on onCheckpoint failure or timeout\n * (CheckpointTimeoutError). The run loop catches and sets\n * `state.checkpointFailed`, which routes through the precedence tail\n * (checkpointFailed > finally-wrap > original-step > suspension).\n */\nasync function emitCheckpoint(\n state: RuntimeState,\n opts: RunOptions,\n resumeFromIndex: number,\n stepShapeHash: string,\n): Promise<void> {\n if (!opts.onCheckpoint) return;\n const snap: CheckpointSnapshot = {\n version: 2,\n kind: \"checkpoint\",\n resumeFromIndex,\n output: state.output,\n stepShapeHash,\n };\n if (resolveFreezeSnapshots(state)) deepFreeze(snap);\n\n const controller = new AbortController();\n if (opts.checkpointTimeout !== undefined) {\n const timeoutMs = opts.checkpointTimeout;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const callPromise = Promise.resolve(opts.onCheckpoint(snap, { signal: controller.signal }));\n const timeoutPromise = new Promise<never>((_, reject) => {\n controller.signal.addEventListener(\n \"abort\",\n () => reject(new CheckpointTimeoutError(timeoutMs)),\n { once: true },\n );\n });\n // Swallow loser to avoid unhandled rejection on the race.\n callPromise.catch(() => {});\n timeoutPromise.catch(() => {});\n await Promise.race([callPromise, timeoutPromise]);\n } finally {\n clearTimeout(timeoutId);\n }\n } else {\n await opts.onCheckpoint(snap, { signal: controller.signal });\n }\n}\n\n// One-time stream-mode warning when a gate fires with options.onError set.\nlet warnedStreamOnErrorOnSuspend = false;\n\n/**\n * @internal — test-only reset of the one-time stream-mode warn dedup.\n */\nexport function __resetStreamOnErrorOnSuspendWarnForTests(): void {\n warnedStreamOnErrorOnSuspend = false;\n}\n\n/**\n * Push an entry onto state.warnings, allocating the array lazily on first use.\n * Centralizes the `(state.warnings ??= []).push({source, stepId, error})` idiom.\n */\nfunction pushWarning(\n state: RuntimeState,\n source: WorkflowWarning[\"source\"],\n stepId: string,\n error: unknown,\n): void {\n (state.warnings ??= []).push({ source, stepId, error });\n}\n\n/**\n * Demote a pendingError into a warning. Used everywhere a new pendingError is\n * about to overwrite the prior one (finally/catch errors after a step error,\n * abort promoted over an in-flight error, suspension-wins tail).\n */\nfunction demotePendingError(state: RuntimeState, pe: PendingError): void {\n pushWarning(state, pe.source, pe.stepId, pe.error);\n}\n\n/**\n * Emit the one-shot stream-onError-on-suspend warning if applicable.\n */\nfunction maybeWarnStreamOnErrorOnSuspend(\n result: WorkflowResult<unknown>,\n options: { onError?: (error: unknown) => string } | undefined,\n): void {\n if (result.status !== \"suspended\" || !options?.onError || warnedStreamOnErrorOnSuspend) return;\n warnedStreamOnErrorOnSuspend = true;\n console.warn(\n \"pipeai: stream() with options.onError suspended at a gate — onError will NOT be invoked for suspension. Discriminate via the resolved output Promise.\"\n );\n}\n\n// ── Sealed Workflow (returned by finally — execution only) ───────────\n\nexport class SealedWorkflow<\n TContext,\n TInput = void,\n TOutput = void,\n TGates extends Record<string, unknown> = {},\n> {\n readonly id?: string;\n protected readonly steps: ReadonlyArray<StepNode>;\n protected readonly observability?: WorkflowObservability;\n // Memoized — see ensureDuplicateCheck().\n private duplicateCheckPassed = false;\n // Memoized lazily per terminal instance — build pipelines once at module\n // load and re-run via generate() to amortize.\n private _cachedExecutableStepCount?: number;\n private _cachedStepShapeHash?: string;\n\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string, observability?: WorkflowObservability) {\n this.steps = steps;\n this.id = id;\n this.observability = observability;\n }\n\n // ── Construction-time validation (memoized per terminal instance) ────\n\n /**\n * Walk the step list once per terminal instance. Rejects:\n * - Duplicate `(type, id)` pairs.\n * - User step ids containing the reserved `::pipeai::` namespace\n * (CHECKPOINT_STEP_ID lives there).\n */\n private ensureDuplicateCheck(): void {\n if (this.duplicateCheckPassed) return;\n const seen = new Map<string, number>();\n for (let i = 0; i < this.steps.length; i++) {\n const node = this.steps[i];\n if (node.id.includes(\"::pipeai::\")) {\n throw new Error(\n `Workflow: step id \"${node.id}\" uses the reserved \"::pipeai::\" namespace at index ${i}.`\n );\n }\n const key = `${node.type}:${node.id}`;\n const prior = seen.get(key);\n if (prior !== undefined) {\n throw new Error(\n `Workflow: duplicate (${node.type}, \"${node.id}\") at indices ${prior} and ${i}. ` +\n `Pass an explicit \\`{ id }\\` (e.g. for back-to-back \\`branch(...)\\` or \\`foreach(agentX).foreach(agentX)\\`) to disambiguate.`\n );\n }\n seen.set(key, i);\n }\n this.duplicateCheckPassed = true;\n }\n\n // ── shape-hash + RunOptions validation ────────────────────────\n\n /**\n * Count of executable nodes — i.e. NOT `catch` or `finally`. Drives\n * checkpoint auto-cadence so adding cleanup steps doesn't surprise users\n * with extra fires. `branch`/`foreach`/`repeat`/`parallel`/`nested` are all\n * `type: \"step\"` internally and count as executable.\n */\n protected get cachedExecutableStepCount(): number {\n if (this._cachedExecutableStepCount !== undefined) return this._cachedExecutableStepCount;\n let n = 0;\n for (const s of this.steps) {\n if (s.type !== \"catch\" && s.type !== \"finally\") n++;\n }\n this._cachedExecutableStepCount = n;\n return n;\n }\n\n /** @internal — used by `computeStepShapeHash` to descend nested workflows. */\n getStepsForShapeHash(): ReadonlyArray<StepNode> {\n return this.steps;\n }\n\n protected get cachedStepShapeHash(): string {\n if (this._cachedStepShapeHash !== undefined) return this._cachedStepShapeHash;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const getNested = (node: any) => getNestedWorkflows(node as StepNode) as unknown as readonly { id?: string; getStepsForShapeHash(): ReadonlyArray<{ type: string; id: string }> }[];\n this._cachedStepShapeHash = computeStepShapeHash(\n this.steps as unknown as ReadonlyArray<{ type: string; id: string }>,\n getNested,\n );\n return this._cachedStepShapeHash;\n }\n\n /**\n * Validate user-provided RunOptions before a run begins. Throws on\n * outright errors and on the loud-disaster combo (`freezeSnapshots: true\n * + checkpointEvery: 1` on a workflow of 8+ steps). Warns once on the\n * merely-suspicious combo (`freezeSnapshots: true + cadence <= 2`).\n * Plan-of-record: catastrophic combo escape via the\n * `\"iAcceptThePerformanceCost\"` literal.\n */\n protected validateRunOptions(opts: RunOptions | undefined): void {\n if (!opts) return;\n // checkpoint-specific validation only applies when onCheckpoint is set.\n if (!opts.onCheckpoint) return;\n if (opts.checkpointEvery !== undefined && opts.checkpointWhen !== undefined) {\n throw new Error(\"RunOptions: checkpointEvery and checkpointWhen are mutually exclusive\");\n }\n if (opts.checkpointEvery !== undefined && (!Number.isInteger(opts.checkpointEvery) || opts.checkpointEvery < 1)) {\n throw new Error(`RunOptions: checkpointEvery must be a positive integer, got ${opts.checkpointEvery}`);\n }\n if (opts.checkpointTimeout !== undefined && (!Number.isFinite(opts.checkpointTimeout) || opts.checkpointTimeout < 1)) {\n throw new Error(`RunOptions: checkpointTimeout must be a finite positive number (ms), got ${opts.checkpointTimeout}`);\n }\n const length = this.cachedExecutableStepCount;\n const cadence = opts.checkpointEvery ?? Math.max(1, Math.ceil(length / 4));\n if (opts.freezeSnapshots && opts.freezeSnapshots !== \"iAcceptThePerformanceCost\" && cadence === 1 && length >= 8) {\n throw new Error(\n `freezeSnapshots+checkpointEvery:1 on a ${length}-step workflow is reliably catastrophic. ` +\n `Set checkpointEvery >= 5, freezeSnapshots: false, or pass \"iAcceptThePerformanceCost\".`\n );\n }\n if (opts.freezeSnapshots && cadence <= 2) {\n warnOnce(\n \"pipeai:freezeSnapshots-low-cadence\",\n \"pipeai: freezeSnapshots+checkpointEvery<=2 compounds graph-walk cost.\",\n );\n }\n }\n\n // ── Observability helpers ─────────────────────────────────────\n\n /**\n * Fire an observability hook safely. Returns `undefined` synchronously when\n * no hook is registered — avoiding the promise wrapper + microtask that an\n * async function would unconditionally allocate on every step boundary.\n *\n * On hook throw:\n * - non-`onStepError` hooks: warning pushed + console.error.\n * - `onStepError`: throw is propagated as a return value; the run loop\n * attaches it as `cause` on the original step error.\n *\n * Returns the hook's thrown error if any; undefined otherwise. Callers\n * `await` the result — `await undefined` is sync, so the no-hook path\n * stays allocation-free.\n */\n protected fireHook<\n K extends keyof WorkflowObservability,\n E extends Parameters<NonNullable<WorkflowObservability[K]>>[0],\n >(\n state: RuntimeState,\n name: K,\n event: E,\n ): MaybePromise<unknown> {\n const hook = this.observability?.[name];\n if (!hook) return undefined;\n return this.fireHookSlow(state, name, event, hook);\n }\n\n private async fireHookSlow<K extends keyof WorkflowObservability>(\n state: RuntimeState,\n name: K,\n event: unknown,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n hook: any,\n ): Promise<unknown> {\n try {\n await hook(event);\n return undefined;\n } catch (e) {\n if (name !== \"onStepError\") {\n const stepId = (event as { stepId: string }).stepId;\n pushWarning(state, name as WorkflowWarning[\"source\"], stepId, e);\n // eslint-disable-next-line no-console\n console.error(`pipeai: ${name} hook threw for stepId \"${stepId}\":`, e);\n }\n return e;\n }\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, opts?: RunOptions]\n : [input: TInput, opts?: RunOptions]\n ): Promise<WorkflowResult<TOutput>> {\n this.ensureDuplicateCheck();\n const input = args[0];\n const opts = args[1] as RunOptions | undefined;\n this.validateRunOptions(opts);\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n runOptions: opts,\n abortSignal: opts?.abortSignal,\n };\n\n await this.execute(state, 0, opts);\n\n return this.buildResult(state);\n }\n\n stream<UI_MESSAGE extends UIMessage = UIMessage>(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]\n : [input: TInput, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]\n ): WorkflowStreamResult<TOutput> {\n this.ensureDuplicateCheck();\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions<UI_MESSAGE> | undefined;\n const opts = args[2] as RunOptions | undefined;\n this.validateRunOptions(opts);\n const abortSignal = opts?.abortSignal;\n\n let resolveOutput!: (value: WorkflowResult<TOutput>) => void;\n let rejectOutput!: (error: unknown) => void;\n const outputPromise = new Promise<WorkflowResult<TOutput>>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n outputPromise.catch(() => {});\n\n const stream = createUIMessageStream<UI_MESSAGE>({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"stream\",\n writer,\n runOptions: opts,\n abortSignal,\n };\n\n try {\n await this.execute(state, 0, opts);\n const result = this.buildResult(state);\n maybeWarnStreamOnErrorOnSuspend(result, options);\n resolveOutput(result);\n } catch (error) {\n rejectOutput(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n ...(options?.originalMessages ? { originalMessages: options.originalMessages } : {}),\n ...(options?.generateId ? { generateId: options.generateId } : {}),\n });\n\n return {\n stream,\n output: outputPromise,\n };\n }\n\n // Helper — converts terminal RuntimeState into a WorkflowResult; freezes\n // snapshot + warnings if requested via runOptions.\n protected buildResult(state: RuntimeState): WorkflowResult<TOutput> {\n const warnings = state.warnings ?? [];\n if (state.suspension && resolveFreezeSnapshots(state)) {\n deepFreeze(warnings);\n }\n if (state.suspension) {\n return { status: \"suspended\", snapshot: state.suspension, warnings };\n }\n return { status: \"complete\", output: state.output as TOutput, warnings };\n }\n\n // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(\n state: RuntimeState,\n startIndex: number = 0,\n opts?: RunOptions,\n initialError: PendingError | null = null,\n ): Promise<void> {\n if (this.steps.length === 0) {\n throw new Error(\"Workflow has no steps. Add at least one step before calling generate() or stream().\");\n }\n\n // Make sure runOptions is plumbed even if the caller didn't initialize state.\n if (opts !== undefined && state.runOptions === undefined) {\n state.runOptions = opts;\n }\n\n // Hoisted once per run — the numeric cadence form has no per-step input,\n // so recomputing it per iteration was pure overhead.\n const ckptCadence = opts?.onCheckpoint && opts.checkpointWhen === undefined\n ? (opts.checkpointEvery ?? Math.max(1, Math.ceil(this.cachedExecutableStepCount / 4)))\n : 0;\n\n // `initialError` lets callers (e.g. ResumedWorkflow.stream) seed the\n // pipeline already-in-error so a pre-execute failure (schema.parse,\n // merge throw) flows through downstream `.catch()` like any other step\n // failure instead of escaping synchronously.\n let pendingError: PendingError | null = initialError;\n\n // Tracks whether the abort signal has already been promoted into\n // pendingError in this execute() pass. On first observation we discard\n // any in-progress suspension (caller asked to stop) and preserve any\n // prior step error as a warning. Subsequent iterations only re-promote\n // if a downstream catch cleared pendingError — the platform semantics\n // of AbortSignal.aborted (sticky once true) say the workflow shouldn't\n // resume mid-pipeline just because a catch swallowed one observation.\n let abortPromoted = false;\n const makeAbortError = (signal: AbortSignal): PendingError => ({\n error: signal.reason ?? new Error(\"Workflow aborted\"),\n stepId: \"abort\",\n source: \"step\",\n });\n\n for (let i = startIndex; i < this.steps.length; i++) {\n // Abort checkpoint — runs at every iteration boundary, before any\n // node dispatch, so finally/catch nodes that come AFTER the abort\n // still get to run (cleanup + recovery contract).\n if (state.abortSignal?.aborted) {\n if (!abortPromoted) {\n abortPromoted = true;\n state.suspension = undefined;\n if (pendingError) demotePendingError(state, pendingError);\n pendingError = makeAbortError(state.abortSignal);\n } else if (!pendingError) {\n // A catch handler swallowed the abort. Re-promote so downstream\n // steps still see the signal as the \"stop\" condition the caller\n // requested.\n pendingError = makeAbortError(state.abortSignal);\n }\n }\n\n const node = this.steps[i];\n\n if (node.type === \"finally\") {\n const stepId = node.id;\n const finStart = performance.now();\n await this.fireHook(state, \"onStepStart\", { stepId, type: \"finally\", ctx: state.ctx, input: state.output });\n try {\n await node.execute(state);\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"finally\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - finStart, suspended: false,\n });\n } catch (e) {\n await this.fireHook(state, \"onStepError\", {\n stepId, type: \"finally\", ctx: state.ctx, error: e,\n durationMs: performance.now() - finStart,\n });\n // Multi-error preservation: never silently overwrite a prior pendingError —\n // push it to warnings before promoting this finally error.\n if (pendingError) demotePendingError(state, pendingError);\n pendingError = { error: e, stepId, source: \"finally\" };\n }\n continue;\n }\n\n if (node.type === \"catch\") {\n // .catch() bypassed on suspension AND on checkpoint failure (checkpoint failure propagates to caller).\n if (state.suspension || !pendingError || state.checkpointFailed) continue;\n const stepId = node.id;\n const cStart = performance.now();\n await this.fireHook(state, \"onStepStart\", { stepId, type: \"catch\", ctx: state.ctx, input: state.output });\n try {\n state.output = await node.catchFn({\n error: pendingError.error,\n ctx: state.ctx,\n lastOutput: state.output,\n stepId: pendingError.stepId,\n });\n pendingError = null;\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"catch\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - cStart, suspended: false,\n });\n } catch (e) {\n await this.fireHook(state, \"onStepError\", {\n stepId, type: \"catch\", ctx: state.ctx, error: e,\n durationMs: performance.now() - cStart,\n });\n if (pendingError) demotePendingError(state, pendingError);\n pendingError = { error: e, stepId, source: \"catch\" };\n }\n continue;\n }\n\n // Skip remaining non-finally/non-catch nodes when suspended or in error state.\n if (state.suspension || pendingError) continue;\n\n if (node.type === \"gate\") {\n // Capture errors from condition/payload callbacks into pendingError so\n // they route through the workflow's .catch() pipeline like any other\n // step error. Without this, a throwing gate callback escapes execute()\n // entirely and bypasses all downstream catch nodes.\n const stepId = node.id;\n const gStart = performance.now();\n await this.fireHook(state, \"onStepStart\", { stepId, type: \"gate\", ctx: state.ctx, input: state.output });\n try {\n if (node.condition && !(await node.condition(state))) {\n // Cond returned false — skip the gate. Fire onStepFinish({ suspended: false }).\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"gate\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - gStart, suspended: false,\n });\n continue;\n }\n const snapshot: GateSnapshot = {\n version: 2,\n kind: \"gate\",\n resumeFromIndex: i,\n output: state.output,\n gateId: node.id,\n gatePayload: await node.payload(state),\n };\n state.suspension = snapshot;\n if (resolveFreezeSnapshots(state)) deepFreeze(snapshot);\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: \"gate\", ctx: state.ctx, output: state.output,\n durationMs: performance.now() - gStart, suspended: true,\n });\n } catch (e) {\n pendingError = { error: e, stepId: node.id, source: \"step\" };\n }\n continue;\n }\n\n // type === \"step\" — driven by `category` for observability type reporting.\n const obsType = getObservabilityType(node);\n const stepId = node.id;\n const sStart = performance.now();\n const stepInput = state.output;\n await this.fireHook(state, \"onStepStart\", { stepId, type: obsType, ctx: state.ctx, input: stepInput });\n try {\n await node.execute(state);\n await this.fireHook(state, \"onStepFinish\", {\n stepId, type: obsType, ctx: state.ctx, output: state.output,\n durationMs: performance.now() - sStart, suspended: false,\n });\n } catch (e) {\n pendingError = { error: e, stepId: node.id, source: \"step\" };\n // onStepError special-cases: if the hook throws, attach the obsError as\n // `cause` on the original step error so the original reaches the caller\n // with the failure trail attached. Other hooks' throws become warnings.\n const obsError = await this.fireHook(state, \"onStepError\", {\n stepId, type: obsType, ctx: state.ctx, error: e,\n durationMs: performance.now() - sStart,\n });\n if (obsError !== undefined && typeof e === \"object\" && e !== null) {\n try {\n (e as { cause?: unknown }).cause = obsError;\n } catch {\n // Some objects are frozen / non-extensible — ignore.\n }\n }\n }\n\n // Defensive invariant: only gate nodes set state.suspension, and\n // executeNestedWorkflow/foreach clear inner suspension before rethrowing.\n // A non-undefined value here means a coding bug bypassed that contract.\n // The cast is needed because TS narrowed suspension to undefined at the\n // top-of-loop falsy check and doesn't know the await may have mutated it.\n const leaked = (state as { suspension?: GateSnapshot }).suspension;\n if (leaked) {\n state.suspension = undefined;\n throw new Error(`internal: suspension bubbled from non-gate step \"${node.id}\" (gate \"${leaked.gateId}\").`);\n }\n\n // Emit a checkpoint after a successful step body. Skipped on pendingError\n // (the step threw — no clean state to snapshot) or on suspension (gate\n // already won). Numeric `checkpointEvery` (default: max(1, ceil(count/4)))\n // uses the loop-hoisted `ckptCadence`; predicate form runs per step.\n if (!pendingError && !state.suspension && opts?.onCheckpoint) {\n const shouldCheckpoint = opts.checkpointWhen\n ? opts.checkpointWhen({ stepIndex: i, stepId: node.id, ctx: state.ctx })\n : (i + 1) % ckptCadence === 0;\n if (shouldCheckpoint) {\n const ckptStart = performance.now();\n try {\n await emitCheckpoint(\n state,\n opts,\n i + 1,\n this.cachedStepShapeHash,\n );\n } catch (e) {\n pendingError = { error: e, stepId: CHECKPOINT_STEP_ID, source: \"onCheckpoint\" };\n state.checkpointFailed = true;\n // Route through onStepError with the synthetic CHECKPOINT_STEP_ID\n // and type: \"step\" (matches pendingErrorSourceToStepType(\"onCheckpoint\")).\n await this.fireHook(state, \"onStepError\", {\n stepId: CHECKPOINT_STEP_ID, type: \"step\", ctx: state.ctx, error: e,\n durationMs: performance.now() - ckptStart,\n });\n }\n }\n }\n }\n\n // Tail — mutually exclusive branches.\n // Precedence: checkpointFailed > finally-wrap > original-step > suspension.\n if (pendingError && !state.suspension) {\n if (state.checkpointFailed) {\n // Checkpoint error reaches caller bare; finally errors get console.warn\n // because the rejection path can't carry warnings.\n const warningsArr = state.warnings ?? [];\n const checkpointError = pendingError.source === \"onCheckpoint\"\n ? pendingError.error\n : warningsArr.find(w => w.source === \"onCheckpoint\")?.error;\n const finallyErrors = warningsArr.filter(w => w.source === \"finally\").map(w => w.error);\n const all = pendingError.source === \"finally\"\n ? [...finallyErrors, pendingError.error]\n : finallyErrors;\n if (all.length > 0) {\n console.warn(\n `pipeai: ${all.length} .finally() error(s) suppressed by checkpoint-failure precedence:`,\n all,\n );\n }\n throw checkpointError ?? pendingError.error;\n }\n const isFinallyPath = pendingError.source === \"finally\"\n || (state.warnings?.some(w => w.source === \"finally\") ?? false);\n if (isFinallyPath) {\n // Source order: warnings were pushed in the order errors occurred (step\n // before finally, earlier finally before later finally), so this preserves\n // the chronological sequence the plan specifies. Single-error case included\n // — once any finally is in the picture, the contract is AggregateError.\n const all = [...(state.warnings ?? []).map(w => w.error), pendingError.error];\n throw new AggregateError(all, `Workflow failed with ${all.length} error(s) from .finally() bodies`);\n }\n throw pendingError.error;\n } else if (pendingError && state.suspension) {\n // Suspension wins; preserve the step error as a warning.\n demotePendingError(state, pendingError);\n // Also emit onStepError so observers can see the loss.\n try {\n await this.observability?.onStepError?.({\n stepId: pendingError.stepId,\n type: pendingErrorSourceToStepType(pendingError.source),\n ctx: state.ctx,\n error: pendingError.error,\n durationMs: 0,\n });\n } catch (obsError) {\n pushWarning(state, \"onStepError\", pendingError.stepId, obsError);\n }\n pendingError = null;\n }\n }\n\n // ── Internal: execute a nested workflow within a step/loop ─────\n // Defined on SealedWorkflow (not Workflow) because TypeScript's protected\n // access rules only allow calling workflow.execute() from the same class.\n //\n // Contract: clears any inner suspension before re-throwing as\n // NestedGateUnsupportedError. The outer execute() therefore never observes\n // a leaked `state.suspension` from non-gate nodes (defensive invariant).\n\n protected async executeNestedWorkflow(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n workflow: SealedWorkflow<TContext, unknown, unknown, any>,\n ): Promise<void> {\n // RunOptions is run-scoped — child never inherits parent's runOptions.\n // state.warnings IS propagated (asymmetric on purpose: telemetry > config).\n const savedRunOptions = state.runOptions;\n state.runOptions = undefined;\n try {\n await workflow.execute(state);\n } finally {\n state.runOptions = savedRunOptions;\n }\n if (state.suspension) {\n const gateId = state.suspension.gateId;\n state.suspension = undefined; // clear before throw (load-bearing invariant 1)\n throw new NestedGateUnsupportedError(gateId, workflow.id);\n }\n }\n\n // ── Internal: execute an agent within a step/branch ───────────\n // In stream mode, output extraction awaits the full stream before returning.\n // Streaming benefits the client (incremental output), not pipeline throughput —\n // each step still runs sequentially.\n\n protected async executeAgent<TAgentInput, TNextOutput>(\n state: RuntimeState,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agent: Agent<TContext, any, TNextOutput>,\n ctx: TContext,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: AgentStepHooks<TContext, any, TNextOutput>,\n ): Promise<void> {\n const input = state.output as TAgentInput;\n const hasStructuredOutput = agent.hasOutput;\n\n const abortSignal = state.abortSignal;\n const agentCallOpts = abortSignal ? { abortSignal } : undefined;\n\n if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools accessed via getActiveWriter() pick it up.\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown, opts?: { abortSignal?: AbortSignal }) => Promise<StreamTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output, agentCallOpts);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx, input });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n const hookParams = {\n mode: \"stream\",\n result,\n ctx: ctx as Readonly<TContext>,\n input,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as AgentResultParams<TContext, any, TNextOutput>;\n\n if (options?.onResult) {\n await options.onResult(hookParams);\n }\n\n if (options?.mapResult) {\n state.output = await options.mapResult(hookParams);\n } else {\n state.output = await extractOutput(result, hasStructuredOutput, agent.validateOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown, opts?: { abortSignal?: AbortSignal }) => Promise<GenerateTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output, agentCallOpts);\n\n const hookParams = {\n mode: \"generate\",\n result,\n ctx: ctx as Readonly<TContext>,\n input,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as AgentResultParams<TContext, any, TNextOutput>;\n\n if (options?.onResult) {\n await options.onResult(hookParams);\n }\n\n if (options?.mapResult) {\n state.output = await options.mapResult(hookParams);\n } else {\n state.output = await extractOutput(result, hasStructuredOutput, agent.validateOutput);\n }\n }\n }\n\n // ── Gate: load persisted state for resumption ──────────────────\n\n loadState<K extends string & keyof TGates>(\n gateId: K,\n snapshot: WorkflowSnapshot,\n ): ResumedWorkflow<TContext, TGates[K], TOutput> {\n // Reject checkpoint snapshots — they belong to resumeFrom(), not loadState().\n if (snapshot.version === 2 && snapshot.kind === \"checkpoint\") {\n throw new Error(`loadState: received a checkpoint snapshot. Use resumeFrom() for checkpoint resume; loadState() is for gates.`);\n }\n const gateLike = snapshot as GateSnapshot | LegacyGateSnapshotV1;\n if (gateLike.gateId !== gateId) {\n throw new Error(\n `loadState: gate ID mismatch — expected \"${gateId}\" but snapshot has \"${gateLike.gateId}\".`\n );\n }\n this.ensureDuplicateCheck();\n const gateIndex = this.findGateIndex(gateLike);\n const gateNode = this.steps[gateIndex] as Extract<StepNode, { type: \"gate\" }>;\n return new ResumedWorkflow<TContext, TGates[K], TOutput>(this.steps, gateIndex + 1, {\n mode: \"gate\",\n schema: gateNode.schema as SchemaWithParse<TGates[K]> | undefined,\n mergeFn: gateNode.merge,\n priorOutput: gateLike.output,\n snapshot: gateLike,\n observability: this.observability,\n });\n }\n\n // ── Checkpoint resume ──────────────────────────────────────────\n\n /**\n * Resume from a checkpoint snapshot. Validates the step-shape hash unless\n * `{ skipShapeCheck: true }` is passed. Throws on:\n * - gate snapshots (use `loadState` instead)\n * - missing/corrupted `stepShapeHash`\n * - shape mismatch (unless skipped)\n * - out-of-bounds `resumeFromIndex`\n * - 0-step workflow (structural invariant)\n *\n * Returns a `CheckpointResumedWorkflow` whose `generate(ctx, opts?)` takes\n * NO response arg — the state is seeded from the snapshot's output. The\n * matching gate-resume path (`loadState`) keeps the `response` arg.\n */\n resumeFrom(\n snapshot: WorkflowSnapshot,\n options?: { skipShapeCheck?: boolean },\n ): CheckpointResumedWorkflow<TContext, TOutput> {\n // Detect gate snapshots (v2 with kind=\"gate\" OR legacy v1 with gateId).\n const isGate = (snapshot.version === 2 && snapshot.kind === \"gate\")\n || (snapshot.version === 1 && (snapshot as LegacyGateSnapshotV1).gateId !== undefined);\n if (isGate) {\n throw new Error(`resumeFrom: received a gate snapshot. Use loadState() for gate resume; resumeFrom() is for checkpoints.`);\n }\n if (this.steps.length === 0) {\n throw new Error(\"resumeFrom: workflow has no steps; snapshot is structurally invalid.\");\n }\n const ckpt = snapshot as CheckpointSnapshot;\n const idx = ckpt.resumeFromIndex;\n if (!Number.isInteger(idx) || idx < 0 || idx > this.steps.length) {\n throw new Error(`resumeFrom: resumeFromIndex (${idx}) out of bounds for ${this.steps.length}-step workflow.`);\n }\n if (!options?.skipShapeCheck) {\n if (!ckpt.stepShapeHash) {\n throw new Error(\"resumeFrom: snapshot missing stepShapeHash; corrupted or hand-crafted.\");\n }\n this.ensureDuplicateCheck();\n if (this.cachedStepShapeHash !== ckpt.stepShapeHash) {\n throw new Error(\"resumeFrom: workflow shape mismatch; cannot safely resume. Pass { skipShapeCheck: true } to override.\");\n }\n } else {\n this.ensureDuplicateCheck();\n }\n return new CheckpointResumedWorkflow<TContext, TOutput>(this.steps, idx, {\n mode: \"checkpoint\",\n priorOutput: ckpt.output,\n snapshot: ckpt,\n observability: this.observability,\n });\n }\n\n /**\n * Append a `.finally()` body to a sealed workflow, returning another sealed\n * workflow. Allows multi-finally chains (`.finally().finally()`). A throwing\n * `.finally` body does NOT abort subsequent ones — they all run.\n */\n finally(\n id: string,\n fn: (params: { ctx: Readonly<TContext> }) => MaybePromise<void>,\n ): SealedWorkflow<TContext, TInput, TOutput, TGates> {\n const node: StepNode = {\n type: \"finally\",\n id,\n execute: async (state) => {\n await fn({ ctx: state.ctx as Readonly<TContext> });\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new SealedWorkflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id, this.observability);\n }\n\n private findGateIndex(snapshot: GateSnapshot | LegacyGateSnapshotV1): number {\n // Accepted: v1 (legacy gate-only) and v2 (gate or checkpoint). Gate-flavor\n // v2 is discriminated by kind === \"gate\"; legacy v1 has no `kind`.\n if (snapshot.version !== 1 && snapshot.version !== 2) {\n throw new Error(`Unsupported snapshot version: ${(snapshot as { version: number }).version}`);\n }\n\n // Fast path — only when the hint is a sane integer in range AND points at the right gate.\n // Rejects -1, NaN, Infinity, 999999, fractional indices.\n const hint = snapshot.resumeFromIndex;\n if (Number.isInteger(hint) && hint >= 0 && hint < this.steps.length) {\n const node = this.steps[hint];\n if (node.type === \"gate\" && node.id === snapshot.gateId) {\n return hint;\n }\n }\n\n // Fallback — scan all steps by gate id (reorder-tolerant).\n for (let i = 0; i < this.steps.length; i++) {\n const node = this.steps[i];\n if (node.type === \"gate\" && node.id === snapshot.gateId) {\n return i;\n }\n }\n\n throw new Error(\n `Gate \"${snapshot.gateId}\" not found in workflow. The workflow definition may have changed since the snapshot was created.`\n );\n }\n}\n\n// ── Resumed Workflow ──────────────────────────────────────────────────\n\ninterface ResumedWorkflowConfig {\n readonly mode: \"gate\" | \"checkpoint\";\n readonly schema?: SchemaWithParse<unknown>;\n readonly mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>;\n readonly priorOutput?: unknown;\n readonly snapshot?: WorkflowSnapshot;\n readonly observability?: WorkflowObservability;\n}\n\nexport class ResumedWorkflow<\n TContext,\n TResponse = unknown,\n TOutput = void,\n> extends SealedWorkflow<TContext, TResponse, TOutput> {\n private readonly startIndex: number;\n private readonly schema?: SchemaWithParse<TResponse>;\n private readonly mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>;\n private readonly priorOutput: unknown;\n\n /** @internal */\n constructor(\n steps: ReadonlyArray<StepNode>,\n startIndex: number,\n config: ResumedWorkflowConfig,\n ) {\n super(steps, undefined, config.observability);\n this.startIndex = startIndex;\n this.schema = config.schema as SchemaWithParse<TResponse> | undefined;\n this.mergeFn = config.mergeFn;\n this.priorOutput = config.priorOutput;\n }\n\n private validateResponse(response: TResponse): TResponse {\n if (this.schema) {\n return this.schema.parse(response) as TResponse;\n }\n return response;\n }\n\n override async generate(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, opts?: RunOptions]\n : [response: TResponse, opts?: RunOptions]\n ): Promise<WorkflowResult<TOutput>> {\n const rawResponse = args[0] as TResponse;\n const opts = args[1] as RunOptions | undefined;\n // Run prep (schema.parse + mergeFn) inside the workflow's error pipeline\n // so a downstream `.catch()` can observe failures here. Without this,\n // a schema/merge throw would reject the promise raw, bypassing catch.\n let output: unknown = this.priorOutput;\n let initialError: PendingError | null = null;\n try {\n const response = this.validateResponse(rawResponse);\n output = this.mergeFn\n ? await this.mergeFn({ priorOutput: this.priorOutput, response })\n : response;\n } catch (error) {\n initialError = { error, stepId: \"gate:resume\", source: \"step\" };\n }\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"generate\",\n runOptions: opts,\n abortSignal: opts?.abortSignal,\n };\n await this.execute(state, this.startIndex, opts, initialError);\n return this.buildResult(state);\n }\n\n override stream<UI_MESSAGE extends UIMessage = UIMessage>(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]\n : [response: TResponse, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]\n ): WorkflowStreamResult<TOutput> {\n const rawResponse = args[0] as TResponse;\n const options = args[1] as WorkflowStreamOptions<UI_MESSAGE> | undefined;\n const opts = args[2] as RunOptions | undefined;\n const abortSignal = opts?.abortSignal;\n\n let resolveOutput!: (value: WorkflowResult<TOutput>) => void;\n let rejectOutput!: (error: unknown) => void;\n const outputPromise = new Promise<WorkflowResult<TOutput>>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n outputPromise.catch(() => {});\n\n const mergeFn = this.mergeFn;\n const priorOutput = this.priorOutput;\n const startIndex = this.startIndex;\n\n const stream = createUIMessageStream<UI_MESSAGE>({\n execute: async ({ writer }) => {\n // Run prep (schema.parse + mergeFn) inside the error pipeline (same as\n // generate()). Without this, a schema parse throw escapes synchronously\n // from .stream(...) and bypasses any downstream .catch().\n let output: unknown = priorOutput;\n let initialError: PendingError | null = null;\n try {\n const response = this.validateResponse(rawResponse);\n output = mergeFn\n ? await mergeFn({ priorOutput, response })\n : response;\n } catch (error) {\n initialError = { error, stepId: \"gate:resume\", source: \"step\" };\n }\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"stream\",\n writer,\n runOptions: opts,\n abortSignal,\n };\n\n try {\n await this.execute(state, startIndex, opts, initialError);\n const result = this.buildResult(state);\n maybeWarnStreamOnErrorOnSuspend(result, options);\n resolveOutput(result);\n } catch (error) {\n rejectOutput(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n ...(options?.originalMessages ? { originalMessages: options.originalMessages } : {}),\n ...(options?.generateId ? { generateId: options.generateId } : {}),\n });\n\n return { stream, output: outputPromise };\n }\n}\n\n// ── Checkpoint-Resumed Workflow ──────────────────────────────────────\n//\n// Used by `resumeFrom()`. Same step list, different entry index — no\n// gate-merge logic (no response argument) because the state is seeded\n// from the checkpoint snapshot's `output`. To keep gate-resume's\n// `loadState` form ergonomic, this is a separate class instead of\n// overloading ResumedWorkflow's generate().\n\nexport class CheckpointResumedWorkflow<\n TContext,\n TOutput = void,\n> extends SealedWorkflow<TContext, void, TOutput> {\n private readonly startIndex: number;\n private readonly priorOutput: unknown;\n\n /** @internal */\n constructor(\n steps: ReadonlyArray<StepNode>,\n startIndex: number,\n config: ResumedWorkflowConfig,\n ) {\n super(steps, undefined, config.observability);\n this.startIndex = startIndex;\n this.priorOutput = config.priorOutput;\n }\n\n // Override with widened arg list compatible with parent's `[input?, opts?]`.\n // Inputs are ignored — state is seeded from the snapshot's `output` field.\n override async generate(\n ctx: TContext,\n ...args: [input?: void, opts?: RunOptions]\n ): Promise<WorkflowResult<TOutput>> {\n const opts = args[1];\n this.validateRunOptions(opts);\n const state: RuntimeState = {\n ctx,\n output: this.priorOutput,\n mode: \"generate\",\n runOptions: opts,\n };\n await this.execute(state, this.startIndex, opts);\n return this.buildResult(state);\n }\n\n override stream<UI_MESSAGE extends UIMessage = UIMessage>(\n ctx: TContext,\n ...args: [input?: void, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]\n ): WorkflowStreamResult<TOutput> {\n const options = args[1];\n const opts = args[2];\n this.validateRunOptions(opts);\n\n let resolveOutput!: (value: WorkflowResult<TOutput>) => void;\n let rejectOutput!: (error: unknown) => void;\n const outputPromise = new Promise<WorkflowResult<TOutput>>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n outputPromise.catch(() => {});\n\n const priorOutput = this.priorOutput;\n const startIndex = this.startIndex;\n\n const stream = createUIMessageStream<UI_MESSAGE>({\n execute: async ({ writer }) => {\n const state: RuntimeState = {\n ctx,\n output: priorOutput,\n mode: \"stream\",\n writer,\n runOptions: opts,\n };\n try {\n await this.execute(state, startIndex, opts);\n const result = this.buildResult(state);\n maybeWarnStreamOnErrorOnSuspend(result, options);\n resolveOutput(result);\n } catch (error) {\n rejectOutput(error);\n throw error;\n }\n },\n ...(options?.onError ? { onError: options.onError } : {}),\n ...(options?.onFinish ? { onFinish: options.onFinish } : {}),\n ...(options?.originalMessages ? { originalMessages: options.originalMessages } : {}),\n ...(options?.generateId ? { generateId: options.generateId } : {}),\n });\n\n return { stream, output: outputPromise };\n }\n}\n\n// ── Workflow ────────────────────────────────────────────────────────\n\nexport class Workflow<\n TContext,\n TInput = void,\n TOutput = void,\n TGates extends Record<string, unknown> = {},\n> extends SealedWorkflow<TContext, TInput, TOutput, TGates> {\n\n /**\n * Sentinel value for `foreach`'s `onError` handler. Returning `Workflow.SKIP`\n * from `onError` omits the failed item's index from the output array,\n * shortening it relative to the input array.\n */\n static readonly SKIP: unique symbol = Symbol(\"pipeai.foreach.skip\");\n\n private constructor(steps: ReadonlyArray<StepNode> = [], id?: string, observability?: WorkflowObservability) {\n super(steps, id, observability);\n }\n\n static create<TContext, TInput = void>(\n options?: { id?: string; observability?: WorkflowObservability },\n ): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id, options?.observability);\n }\n\n static from<TContext, TInput, TOutput>(\n agent: Agent<TContext, TInput, TOutput>,\n options?: StepOptions<TContext, TInput, TOutput>\n ): Workflow<TContext, TInput, TOutput> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, any>([]).step(agent, options);\n }\n\n // Builder helper — append a step and return a re-typed Workflow.\n // Centralizes the `[...steps, node] as any` + new Workflow + observability/id\n // forwarding pattern used by every combinator method.\n private appendStep<TNext, TG extends Record<string, unknown> = TGates>(\n node: StepNode,\n ): Workflow<TContext, TInput, TNext, TG> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNext, TG>([...this.steps, node] as any, this.id, this.observability);\n }\n\n // ── step: agent overload ──────────────────────────────────────\n\n step<TNextOutput>(\n agent: Agent<TContext, TOutput, TNextOutput>,\n options?: StepOptions<TContext, TOutput, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── step: nested workflow overload ─────────────────────────────\n\n step<TNextOutput>(\n workflow: SealedWorkflow<TContext, TOutput, TNextOutput>,\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── step: transform overload (replaces map + tap) ─────────────\n\n step<TNextOutput>(\n id: string,\n fn: (params: { ctx: Readonly<TContext>; input: TOutput; writer?: UIMessageStreamWriter }) => MaybePromise<TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── step: implementation ──────────────────────────────────────\n\n step<TNextOutput>(\n target: Agent<TContext, TOutput, TNextOutput> | SealedWorkflow<TContext, TOutput, TNextOutput> | string,\n optionsOrFn?: StepOptions<TContext, TOutput, TNextOutput> | ((params: { ctx: Readonly<TContext>; input: TOutput; writer?: UIMessageStreamWriter }) => MaybePromise<TNextOutput>)\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n // Nested workflow overload: step(workflow)\n if (target instanceof SealedWorkflow) {\n const workflow = target;\n const node: StepNode = {\n type: \"step\",\n id: workflow.id ?? \"nested-workflow\",\n nestedWorkflow: workflow, // Feeds the recursive stepShapeHash walk.\n category: \"nested\", // Observability event type.\n execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown, any>);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // Transform overload: step(id, fn)\n if (typeof target === \"string\") {\n if (typeof optionsOrFn !== \"function\") {\n throw new Error(`Workflow step(\"${target}\"): second argument must be a function`);\n }\n const fn = optionsOrFn as (params: { ctx: Readonly<TContext>; input: TOutput; writer?: UIMessageStreamWriter }) => MaybePromise<TNextOutput>;\n const node: StepNode = {\n type: \"step\",\n id: target,\n execute: async (state) => {\n state.output = await fn({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n // Present in stream mode (undefined in generate mode), letting the\n // inline step emit UIMessageChunk parts onto the workflow's stream.\n writer: state.writer,\n });\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // Agent overload: step(agent, options?)\n const agent = target;\n const options = optionsOrFn as StepOptions<TContext, TOutput, TNextOutput> | undefined;\n const node: StepNode = {\n type: \"step\",\n id: options?.id ?? agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // ── gate: human-in-the-loop suspension point ────────────────\n\n gate<TResponse = TOutput, Id extends string = string>(\n id: Id & (Id extends keyof TGates ? never : Id),\n options?: {\n payload?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<unknown>;\n schema?: SchemaWithParse<TResponse>;\n condition?: (params: { ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<boolean>;\n merge?: (params: { priorOutput: TOutput; response: TResponse }) => MaybePromise<TResponse>;\n }\n ): Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>> {\n if (this.steps.some(s => s.type === \"gate\" && s.id === id)) {\n throw new Error(`Workflow: duplicate gate ID \"${id}\". Each gate must have a unique identifier.`);\n }\n const node: StepNode = {\n type: \"gate\",\n id,\n schema: options?.schema,\n condition: options?.condition\n ? async (state) => options.condition!({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n })\n : undefined,\n merge: options?.merge\n ? (params) => options.merge!(params as { priorOutput: TOutput; response: TResponse })\n : undefined,\n payload: async (state) => {\n if (options?.payload) {\n return options.payload({\n ctx: state.ctx as Readonly<TContext>,\n input: state.output as TOutput,\n });\n }\n return state.output;\n },\n };\n return this.appendStep<TResponse, TGates & Record<Id, TResponse>>(node);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[],\n options?: { id?: string },\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── branch: key routing (select) ──────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>,\n options?: { id?: string },\n ): Workflow<TContext, TInput, TNextOutput, TGates>;\n\n // ── branch: implementation ────────────────────────────────────\n\n branch<TKeys extends string, TNextOutput>(\n casesOrConfig: BranchCase<TContext, TOutput, TNextOutput>[] | BranchSelect<TContext, TOutput, TKeys, TNextOutput>,\n options?: { id?: string },\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig, options?.id);\n }\n return this.branchSelect(casesOrConfig, options?.id);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[],\n explicitId?: string,\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: explicitId ?? \"branch:predicate\",\n category: \"branch\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n\n for (const branchCase of cases) {\n if (branchCase.when) {\n const match = await branchCase.when({ ctx, input });\n if (!match) continue;\n }\n\n // Matched (or no `when` = default)\n await this.executeAgent(state, branchCase.agent, ctx, branchCase);\n return;\n }\n\n // Render the input defensively — JSON.stringify throws on cyclic /\n // BigInt / function-valued inputs, which would mask the real branch\n // mismatch with a serialization error.\n let inputRepr: string;\n try {\n inputRepr = JSON.stringify(input);\n if (inputRepr === undefined) inputRepr = String(input);\n } catch {\n inputRepr = `[unserializable ${typeof input}]`;\n }\n throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${inputRepr}`);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>,\n explicitId?: string,\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: explicitId ?? \"branch:select\",\n category: \"branch\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output as TOutput;\n const key = await config.select({ ctx, input });\n\n // Distinguish \"key not declared at all\" from \"key present but value\n // is `undefined`\" (e.g. `agents: { bug: cond ? agentA : undefined }`).\n // The latter is a user-side bug — fail loud rather than silently\n // falling back, since the fallback obscures the misconfiguration.\n //\n // Use Object.prototype.hasOwnProperty.call (not `in`) so untrusted\n // classifier output like \"toString\"/\"constructor\"/\"__proto__\" doesn't\n // resolve to a Object.prototype method and crash executeAgent with an\n // opaque \"agent.generate is not a function\".\n const keyDeclared = Object.prototype.hasOwnProperty.call(config.agents, key);\n if (keyDeclared && (config.agents as Record<string, unknown>)[key] === undefined) {\n throw new WorkflowBranchError(\n \"select\",\n `Agent for key \"${key}\" was declared but the value is undefined. ` +\n `This usually means a conditional spread set the value to undefined. ` +\n `Available keys: ${Object.keys(config.agents).join(\", \")}`,\n );\n }\n let agent = keyDeclared ? config.agents[key] : undefined;\n if (!agent) {\n if (config.onUnknownKey) {\n config.onUnknownKey({\n key,\n availableKeys: Object.keys(config.agents) as TKeys[],\n ctx: ctx as Readonly<TContext>,\n });\n }\n if (config.fallback) {\n agent = config.fallback;\n } else {\n throw new WorkflowBranchError(\"select\", `No agent found for key \"${key}\" and no fallback provided. Available keys: ${Object.keys(config.agents).join(\", \")}`);\n }\n }\n\n await this.executeAgent(state, agent, ctx, config);\n },\n };\n return this.appendStep<TNextOutput>(node);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n /**\n * Map each item of an array through an agent or sub-workflow.\n *\n * @param target Agent or `SealedWorkflow` invoked once per item.\n * @param options.id Override the default step id (`foreach:<agentId>` or\n * the workflow's id). Required when chaining multiple foreach over the same\n * target — the construction-time `(type, id)` walk rejects duplicates.\n * @param options.concurrency Max items in flight at any moment (default 1).\n * Backed by a semaphore: as soon as one item completes, the next launches —\n * no lockstep batching.\n * @param options.onError Per-iteration error handler. **Bypassed entirely on\n * the suspension path** (when any item hits a nested gate) — see the\n * foreach concurrency hazards in the README. Otherwise: return a\n * `TNextOutput` value to substitute, return `Workflow.SKIP` to omit, throw\n * to abort. Invoked sequentially in index order after all items settle.\n */\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: {\n id?: string;\n concurrency?: number;\n onError?: (params: {\n error: unknown;\n item: ElementOf<TOutput>;\n index: number;\n ctx: Readonly<TContext>;\n }) => MaybePromise<TNextOutput | typeof Workflow.SKIP>;\n },\n ): Workflow<TContext, TInput, TNextOutput[], TGates> {\n const concurrency = options?.concurrency ?? 1;\n const onError = options?.onError;\n const isWorkflow = target instanceof SealedWorkflow;\n const defaultId = isWorkflow\n ? (target.id ?? \"foreach\")\n : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n const id = options?.id ?? defaultId;\n\n const node: StepNode = {\n type: \"step\",\n id,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n nestedWorkflow: isWorkflow ? (target as SealedWorkflow<any, any, any, any>) : undefined,\n category: \"foreach\",\n execute: async (state) => {\n const items = state.output;\n if (!Array.isArray(items)) {\n throw new Error(`foreach \"${id}\": expected array input, got ${typeof items}`);\n }\n\n const ctx = state.ctx as TContext;\n const results: unknown[] = new Array(items.length);\n const skipped = new Set<number>();\n const itemStates: (RuntimeState | undefined)[] = new Array(items.length);\n\n const executeItem = async (item: unknown, index: number) => {\n // itemState explicitly omits runOptions — per-run config never crosses\n // the foreach boundary. abortSignal IS propagated though, since\n // cancellation must be transitive across the foreach barrier.\n const itemState: RuntimeState = {\n ctx: state.ctx,\n output: item,\n mode: \"generate\",\n abortSignal: state.abortSignal,\n };\n itemStates[index] = itemState;\n const itemStart = performance.now();\n await this.fireHook(state, \"onItemStart\", {\n stepId: id, type: \"foreach\", itemIndex: index, ctx: state.ctx, input: item,\n });\n try {\n if (isWorkflow) {\n await this.executeNestedWorkflow(itemState, target as SealedWorkflow<TContext, unknown, unknown, any>);\n } else {\n await this.executeAgent(itemState, target as Agent<TContext, unknown, TNextOutput>, ctx);\n }\n results[index] = itemState.output;\n await this.fireHook(state, \"onItemFinish\", {\n stepId: id, type: \"foreach\", itemIndex: index, ctx: state.ctx, output: itemState.output,\n durationMs: performance.now() - itemStart,\n });\n } catch (error) {\n await this.fireHook(state, \"onItemError\", {\n stepId: id, type: \"foreach\", itemIndex: index, ctx: state.ctx, error,\n durationMs: performance.now() - itemStart,\n });\n throw error;\n }\n };\n\n // Merge per-item warnings into the parent state, namespaced.\n // Runs on EVERY exit path (success, suspension, or onError throw).\n const mergeItemWarnings = () => {\n for (let idx = 0; idx < items.length; idx++) {\n const its = itemStates[idx];\n if (!its?.warnings) continue;\n for (const w of its.warnings) {\n pushWarning(state, w.source, `${id}[${idx}]:${w.stepId}`, w.error);\n }\n }\n };\n\n const handleRejection = async (error: unknown, item: unknown, index: number) => {\n if (!onError) throw error;\n const recovered = await onError({\n error,\n item: item as ElementOf<TOutput>,\n index,\n ctx: state.ctx as Readonly<TContext>,\n });\n if (recovered === Workflow.SKIP) {\n skipped.add(index);\n } else {\n results[index] = recovered;\n }\n };\n\n // Collect rejections, then partition + branch.\n type Failure = { index: number; error: unknown };\n const failures: Failure[] = [];\n\n // Cooperative cancellation: bail before launching each item so a\n // large foreach doesn't fire off all items just because the parent's\n // abortSignal triggered mid-iteration. In-flight items already running\n // can't be yanked back, but their executeAgent call forwarded the\n // signal so the SDK side will tear them down.\n const signal = state.abortSignal;\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n if (signal?.aborted) {\n failures.push({ index: i, error: signal.reason ?? new Error(\"Workflow aborted\") });\n continue;\n }\n try {\n await executeItem(items[i], i);\n } catch (error) {\n failures.push({ index: i, error });\n }\n }\n } else {\n // Worker pool: O(concurrency) async closures share a counter rather\n // than O(N) closures all queuing on a semaphore. The shared\n // `nextIndex++` is safe because JS is single-threaded — the\n // read+increment is synchronous and the following `await` yields\n // AFTER the index is captured.\n let nextIndex = 0;\n const worker = async () => {\n while (true) {\n const i = nextIndex++;\n if (i >= items.length) return;\n if (signal?.aborted) {\n failures.push({ index: i, error: signal.reason ?? new Error(\"Workflow aborted\") });\n continue;\n }\n try {\n await executeItem(items[i], i);\n } catch (error) {\n failures.push({ index: i, error });\n }\n }\n };\n const workers = Array.from(\n { length: Math.min(concurrency, items.length) },\n () => worker(),\n );\n await Promise.all(workers);\n }\n\n failures.sort((a, b) => a.index - b.index);\n\n // Partition into gate vs non-gate rejections.\n const gateFailures: { index: number; error: NestedGateUnsupportedError }[] = [];\n const nonGateFailures: Failure[] = [];\n for (const f of failures) {\n if (f.error instanceof NestedGateUnsupportedError) {\n gateFailures.push({ index: f.index, error: f.error });\n } else {\n nonGateFailures.push(f);\n }\n }\n\n // Always merge per-item warnings before deciding which path to take.\n mergeItemWarnings();\n\n if (gateFailures.length > 0) {\n // Suspension path — onError is bypassed entirely. Non-gate rejections\n // become foreach-sibling warnings. Lowest-index marker wins.\n for (const nr of nonGateFailures) {\n pushWarning(state, \"foreach-sibling\", `${id}[${nr.index}]`, nr.error);\n }\n const lowest = gateFailures[0];\n const otherSuspensions = gateFailures.slice(1).map(g => ({\n index: g.index,\n gateId: g.error.gateId,\n }));\n const siblingErrors = nonGateFailures.map(nr => nr.error);\n throw new NestedGateUnsupportedError(\n lowest.error.gateId,\n lowest.error.workflowId,\n siblingErrors,\n otherSuspensions,\n );\n }\n\n // No suspension — run onError per existing semantics in index order.\n for (const { index, error } of nonGateFailures) {\n await handleRejection(error, items[index], index);\n }\n\n state.output = skipped.size === 0\n ? results\n : results.filter((_, i) => !skipped.has(i));\n },\n };\n return this.appendStep<TNextOutput[]>(node);\n }\n\n // ── parallel: fan-out combinator ────────────────────────────────\n //\n // Same input fed to each branch. Generate mode only — writer is NOT threaded\n // through (interleaving multiple agent streams into one writer is not\n // supported). For SealedWorkflow branches, a nested gate throws\n // NestedGateUnsupportedError (same machinery as foreach concurrent).\n //\n // Default concurrency: `min(branches.length, 5)` — most users want fan-out,\n // not lockstep batching. Warn-once when branch count exceeds the 5 cap so\n // users notice unexpected rate-limit pressure.\n\n /** Record-form overload. Returns `{ [K]: BranchOutput<T[K]> }`. */\n parallel<TBranches extends Record<string, ParallelTarget<TContext, TOutput>>>(\n branches: TBranches,\n options?: ParallelOptions<TContext>,\n ): Workflow<TContext, TInput, ParallelOutputRecord<TBranches>, TGates>;\n\n /** Tuple-form overload. Returns `[O1, O2, ...]`. Use `as const`. */\n parallel<TBranches extends ReadonlyArray<ParallelTarget<TContext, TOutput>>>(\n branches: TBranches,\n options?: ParallelOptions<TContext>,\n ): Workflow<TContext, TInput, ParallelOutputTuple<TBranches>, TGates>;\n\n // Implementation\n parallel(\n branches: Record<string, ParallelTarget<TContext, TOutput>> | ReadonlyArray<ParallelTarget<TContext, TOutput>>,\n options?: ParallelOptions<TContext>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Workflow<TContext, TInput, any, TGates> {\n const isTuple = Array.isArray(branches);\n const entries: Array<{ key: string | number; index: number; target: ParallelTarget<TContext, TOutput> }> = isTuple\n ? (branches as ReadonlyArray<ParallelTarget<TContext, TOutput>>).map((target, i) => ({ key: i, index: i, target }))\n : Object.entries(branches as Record<string, ParallelTarget<TContext, TOutput>>).map(([k, t], i) => ({ key: k, index: i, target: t }));\n const branchCount = entries.length;\n const requestedConcurrency = options?.concurrency;\n let effectiveConcurrency: number;\n if (requestedConcurrency === undefined) {\n effectiveConcurrency = Math.min(branchCount, 5);\n } else {\n effectiveConcurrency = requestedConcurrency;\n }\n // Warn-once when >5 branches without explicit concurrency override.\n if (requestedConcurrency === undefined && branchCount > 5) {\n warnOnce(\n \"pipeai:parallel-cap\",\n `pipeai: parallel() with ${branchCount} branches capped at concurrency 5 by default. Pass { concurrency: ${branchCount} } (or Infinity) to opt in, or set { concurrency: N } if you want fewer.`,\n );\n }\n const onError = options?.onError;\n const id = options?.id ?? (isTuple ? \"parallel:tuple\" : \"parallel:record\");\n\n const node: StepNode = {\n type: \"step\",\n id,\n category: \"parallel\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n const input = state.output;\n const results: Record<string | number, unknown> = (isTuple ? new Array(branchCount) : {}) as Record<string | number, unknown>;\n const branchStates: (RuntimeState | undefined)[] = new Array(branchCount);\n\n const executeBranch = async ({ key, index, target }: { key: string | number; index: number; target: ParallelTarget<TContext, TOutput> }) => {\n // Per-branch itemState — same isolation as foreach (no runOptions).\n const branchState: RuntimeState = { ctx: state.ctx, output: input, mode: \"generate\" };\n branchStates[index] = branchState;\n const branchStart = performance.now();\n // itemIndex is the key for record form, numeric index for tuple form.\n const itemIndex: string | number = isTuple ? index : (key as string);\n await this.fireHook(state, \"onItemStart\", {\n stepId: id, type: \"parallel\", itemIndex, ctx: state.ctx, input,\n });\n try {\n if (target instanceof SealedWorkflow) {\n await this.executeNestedWorkflow(branchState, target as SealedWorkflow<TContext, unknown, unknown, any>);\n } else {\n await this.executeAgent(branchState, target as Agent<TContext, unknown, unknown>, ctx);\n }\n results[key] = branchState.output;\n await this.fireHook(state, \"onItemFinish\", {\n stepId: id, type: \"parallel\", itemIndex, ctx: state.ctx, output: branchState.output,\n durationMs: performance.now() - branchStart,\n });\n } catch (error) {\n await this.fireHook(state, \"onItemError\", {\n stepId: id, type: \"parallel\", itemIndex, ctx: state.ctx, error,\n durationMs: performance.now() - branchStart,\n });\n throw error;\n }\n };\n\n // Same partition + suspension contract as foreach concurrent.\n type Failure = { key: string | number; index: number; error: unknown };\n const failures: Failure[] = [];\n\n const eff = Number.isFinite(effectiveConcurrency) ? Math.max(1, effectiveConcurrency) : branchCount;\n if (eff <= 1) {\n for (const e of entries) {\n try {\n await executeBranch(e);\n } catch (error) {\n failures.push({ key: e.key, index: e.index, error });\n }\n }\n } else {\n // Worker pool (same shape as foreach): K closures share a counter\n // instead of N closures queuing on a semaphore.\n let nextIndex = 0;\n const worker = async () => {\n while (true) {\n const i = nextIndex++;\n if (i >= branchCount) return;\n const e = entries[i];\n try {\n await executeBranch(e);\n } catch (error) {\n failures.push({ key: e.key, index: e.index, error });\n }\n }\n };\n const workers = Array.from(\n { length: Math.min(eff, branchCount) },\n () => worker(),\n );\n await Promise.all(workers);\n }\n\n // Always merge per-branch warnings into the parent, namespaced.\n for (let idx = 0; idx < branchCount; idx++) {\n const bs = branchStates[idx];\n if (!bs?.warnings) continue;\n for (const w of bs.warnings) {\n pushWarning(state, w.source, `${id}[${entries[idx].key}]:${w.stepId}`, w.error);\n }\n }\n\n // Partition rejections into gate vs non-gate.\n const gateFailures: { key: string | number; index: number; error: NestedGateUnsupportedError }[] = [];\n const nonGateFailures: Failure[] = [];\n for (const f of failures) {\n if (f.error instanceof NestedGateUnsupportedError) gateFailures.push({ key: f.key, index: f.index, error: f.error });\n else nonGateFailures.push(f);\n }\n gateFailures.sort((a, b) => a.index - b.index);\n nonGateFailures.sort((a, b) => a.index - b.index);\n\n if (gateFailures.length > 0) {\n // Suspension path — onError bypassed; non-gate rejections become warnings.\n for (const nr of nonGateFailures) {\n pushWarning(state, \"foreach-sibling\", `${id}[${nr.key}]`, nr.error);\n }\n const lowest = gateFailures[0];\n const otherSuspensions = gateFailures.slice(1).map(g => ({ index: g.index, gateId: g.error.gateId }));\n const siblingErrors = nonGateFailures.map(nr => nr.error);\n throw new NestedGateUnsupportedError(\n lowest.error.gateId,\n lowest.error.workflowId,\n siblingErrors,\n otherSuspensions,\n );\n }\n\n // No suspension — handle non-gate failures via onError or rethrow.\n for (const { key, index, error } of nonGateFailures) {\n if (!onError) throw error;\n const recovered = await onError({\n error,\n key: isTuple ? undefined : (key as string),\n index: isTuple ? (index) : undefined,\n ctx: state.ctx as Readonly<TContext>,\n });\n if (recovered === Workflow.SKIP) {\n // Record form: leave the key as `undefined`. Tuple form: same — the\n // slot stays `undefined`. The output type accepts SKIP only on the\n // record form at compile time.\n results[key] = undefined;\n } else {\n results[key] = recovered;\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return this.appendStep<any>(node);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput> & { id?: string },\n ): Workflow<TContext, TInput, TOutput, TGates> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const defaultId = isWorkflow\n ? (target.id ?? \"repeat\")\n : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\n const id = options.id ?? defaultId;\n const predicate: LoopPredicate<TContext, TOutput> = options.until\n ?? (async (p) => !(await options.while!(p)));\n\n const node: StepNode = {\n type: \"step\",\n id,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n nestedWorkflow: isWorkflow ? (target as SealedWorkflow<any, any, any, any>) : undefined,\n category: \"repeat\",\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\n // Cancellation checkpoint between iterations. The body's executeAgent\n // already forwards the signal so an in-flight call cancels too, but\n // the explicit check here covers SealedWorkflow bodies and transform-\n // only loops where the signal wouldn't otherwise propagate.\n if (state.abortSignal?.aborted) {\n throw state.abortSignal.reason ?? new Error(\"Workflow aborted\");\n }\n\n if (isWorkflow) {\n await this.executeNestedWorkflow(state, target as SealedWorkflow<TContext, unknown, unknown, any>);\n } else {\n await this.executeAgent(state, target as Agent<TContext, TOutput, TOutput>, ctx);\n }\n\n const done = await predicate({\n output: state.output as TOutput,\n ctx: ctx as Readonly<TContext>,\n iterations: i,\n });\n if (done) return;\n }\n\n throw new WorkflowLoopError(maxIterations, maxIterations);\n },\n };\n return this.appendStep<TOutput>(node);\n }\n\n // ── catch ─────────────────────────────────────────────────────\n\n catch(\n id: string,\n fn: (params: { error: unknown; ctx: Readonly<TContext>; lastOutput: TOutput; stepId: string }) => MaybePromise<TOutput>\n ): Workflow<TContext, TInput, TOutput, TGates> {\n if (!this.steps.some(s => s.type === \"step\")) {\n throw new Error(`Workflow: catch(\"${id}\") requires at least one preceding step.`);\n }\n const node: StepNode = {\n type: \"catch\",\n id,\n catchFn: fn as (params: { error: unknown; ctx: unknown; lastOutput: unknown; stepId: string }) => MaybePromise<unknown>,\n };\n return this.appendStep<TOutput>(node);\n }\n\n // `.finally()` is inherited from SealedWorkflow now (it lives there so\n // multi-finally chains are possible — `.finally().finally()`).\n}\n","export { Agent } from \"./agent\";\nexport type {\n AgentConfig,\n GenerateTextResult,\n StreamTextResult,\n OutputType,\n AsToolMapOutput,\n} from \"./agent\";\n\nexport {\n Workflow,\n WorkflowBranchError,\n WorkflowLoopError,\n NestedGateUnsupportedError,\n CheckpointTimeoutError,\n CHECKPOINT_STEP_ID,\n migrateSnapshot,\n} from \"./workflow\";\n\n// `SKIP` is a unique-symbol sentinel returned from `foreach`'s `onError` to\n// omit an item from the output array. It mirrors `Workflow.SKIP` and is\n// re-exported here so consumers who only `import type { SealedWorkflow }` can\n// still reach the runtime value without importing the full `Workflow` class.\nimport { Workflow as _WorkflowForSkip } from \"./workflow\";\nexport const SKIP = _WorkflowForSkip.SKIP;\nexport type { SealedWorkflow, ResumedWorkflow, CheckpointResumedWorkflow } from \"./workflow\";\nexport type {\n AgentStepHooks,\n AgentResultParams,\n StepOptions,\n BranchCase,\n BranchSelect,\n RepeatOptions,\n WorkflowResult,\n WorkflowStreamResult,\n WorkflowStreamOptions,\n WorkflowSnapshot,\n GateSnapshot,\n CheckpointSnapshot,\n LegacyGateSnapshotV1,\n WorkflowWarning,\n WorkflowStepType,\n WorkflowObservability,\n RunOptions,\n ParallelTarget,\n ParallelOutputRecord,\n ParallelOutputTuple,\n ParallelOptions,\n} from \"./workflow\";\n\nexport { defineTool, ToolProvider, isToolProvider, TOOL_PROVIDER_BRAND } from \"./tool-provider\";\nexport type { ToolProviderConfig, ToolExecuteOptions, IToolProvider } from \"./tool-provider\";\n\nexport { getActiveWriter } from \"./utils\";\nexport type { MaybePromise, Resolvable } from \"./utils\";\n"],"mappings":"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","names":["tool","tool","result","stepId","node"]}