pipeai 0.2.1 → 0.3.0

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/README.md CHANGED
@@ -484,13 +484,15 @@ const pipeline = Workflow.create<Ctx>()
484
484
  .step("combine", ({ input }) => input.join("\n\n"));
485
485
  ```
486
486
 
487
- Concurrent processing with batched parallelism:
487
+ Concurrent processing with bounded parallelism:
488
488
 
489
489
  ```ts
490
- // Process 3 items at a time
490
+ // Up to 3 items run simultaneously; the next launches as soon as one finishes.
491
491
  .foreach(summarizer, { concurrency: 3 })
492
492
  ```
493
493
 
494
+ `concurrency` is the **maximum number of items in flight at any moment** — backed by a semaphore. There's no lockstep batching: a slow item never blocks a finished slot from picking up the next pending one.
495
+
494
496
  Works with nested workflows too:
495
497
 
496
498
  ```ts
@@ -503,6 +505,28 @@ const pipeline = Workflow.create<Ctx>()
503
505
  .foreach(processItem, { concurrency: 5 });
504
506
  ```
505
507
 
508
+ #### Per-item error recovery via `onError`
509
+
510
+ By default a single item's failure aborts the whole `foreach`. Pass an `onError` handler to recover individual items — return a substitute value, return `Workflow.SKIP` to drop the failed index from the output array, or rethrow to abort the step (the throw is catchable by a downstream `.catch()`):
511
+
512
+ ```ts
513
+ import { Workflow } from "pipeai";
514
+
515
+ const pipeline = Workflow.create<Ctx>()
516
+ .step("fetch", async ({ ctx }) => ctx.db.urls.getAll())
517
+ .foreach(scraper, {
518
+ concurrency: 5,
519
+ onError: ({ error, item, index }) => {
520
+ // Substitute a placeholder
521
+ if (isTransient(error)) return { url: item, body: "" };
522
+ // Or drop the item entirely (output array is shortened)
523
+ return Workflow.SKIP;
524
+ },
525
+ });
526
+ ```
527
+
528
+ `onError` is invoked sequentially in **index order** after all items settle, so its observable order is deterministic regardless of completion timing. In-flight siblings are never cancelled by another item's failure.
529
+
506
530
  **Type safety:** `foreach()` uses `ElementOf<TOutput>` to extract the array element type. If the previous step doesn't produce an array, the call is rejected at compile time.
507
531
 
508
532
  ### Conditional loops via `repeat()`
@@ -594,7 +618,7 @@ const { stream, output } = pipeline.stream(ctx, initialInput, {
594
618
  | `.step(id, fn)` | Transform the output. `fn` receives `{ ctx, input }` and returns the new output. |
595
619
  | `.branch([...cases])` | Predicate routing. First `when` match wins; case without `when` is default. |
596
620
  | `.branch({ select, agents })` | Key routing. `select` returns a key, runs the matching agent. |
597
- | `.foreach(target, opts?)` | Map each array element through an agent or workflow. `opts.concurrency` controls parallelism (default: 1). |
621
+ | `.foreach(target, opts?)` | Map each array element through an agent or workflow. `opts.concurrency` is the max items in flight (default: 1). `opts.onError` recovers per-item failures; return `Workflow.SKIP` to drop an index. |
598
622
  | `.repeat(target, opts)` | Loop an agent or workflow. Use `{ until }` or `{ while }` (mutually exclusive). `maxIterations` defaults to 10. |
599
623
  | `.gate(id, opts?)` | Human-in-the-loop suspension point. Throws `WorkflowSuspended` with a serializable snapshot. Resume via `loadState(gateId, snapshot)`. |
600
624
  | `.catch(id, fn)` | Handle errors. `fn` receives `{ error, ctx, lastOutput, stepId }` and returns a recovery value. |
package/dist/index.cjs CHANGED
@@ -50,6 +50,28 @@ function resolveValue(value, ctx, input) {
50
50
  }
51
51
  return value;
52
52
  }
53
+ var Semaphore = class {
54
+ available;
55
+ waiters = [];
56
+ constructor(permits) {
57
+ if (!Number.isInteger(permits) || permits < 1) {
58
+ throw new Error(`Semaphore: permits must be a positive integer, got ${permits}`);
59
+ }
60
+ this.available = permits;
61
+ }
62
+ async acquire() {
63
+ if (this.available > 0) {
64
+ this.available--;
65
+ return;
66
+ }
67
+ await new Promise((resolve) => this.waiters.push(resolve));
68
+ }
69
+ release() {
70
+ const next = this.waiters.shift();
71
+ if (next) next();
72
+ else this.available++;
73
+ }
74
+ };
53
75
  async function extractOutput(result, hasStructuredOutput) {
54
76
  if (hasStructuredOutput) {
55
77
  const output = await result.output;
@@ -546,6 +568,12 @@ var ResumedWorkflow = class extends SealedWorkflow {
546
568
  }
547
569
  };
548
570
  var Workflow = class _Workflow extends SealedWorkflow {
571
+ /**
572
+ * Sentinel value for `foreach`'s `onError` handler. Returning `Workflow.SKIP`
573
+ * from `onError` omits the failed item's index from the output array,
574
+ * shortening it relative to the input array.
575
+ */
576
+ static SKIP = /* @__PURE__ */ Symbol("pipeai.foreach.skip");
549
577
  constructor(steps = [], id) {
550
578
  super(steps, id);
551
579
  }
@@ -672,8 +700,24 @@ var Workflow = class _Workflow extends SealedWorkflow {
672
700
  return new _Workflow([...this.steps, node], this.id);
673
701
  }
674
702
  // ── foreach: array iteration ─────────────────────────────────
703
+ /**
704
+ * Map each item of an array through an agent or sub-workflow.
705
+ *
706
+ * @param target Agent or `SealedWorkflow` invoked once per item.
707
+ * @param options.concurrency Max items in flight at any moment (default 1).
708
+ * Backed by a semaphore: as soon as one item completes, the next launches —
709
+ * no lockstep batching.
710
+ * @param options.onError Per-iteration error handler. When provided, a single
711
+ * item's failure no longer aborts the foreach. Return a `TNextOutput` value
712
+ * to substitute for the failed item, return `Workflow.SKIP` to omit the
713
+ * index (shortening the output array), or throw / return a rejected promise
714
+ * to abort the foreach step (the thrown error is caught by any downstream
715
+ * `.catch()`). When omitted, the existing fail-fast behavior is preserved.
716
+ * `onError` is invoked sequentially in index order after all items settle.
717
+ */
675
718
  foreach(target, options) {
676
719
  const concurrency = options?.concurrency ?? 1;
720
+ const onError = options?.onError;
677
721
  const isWorkflow = target instanceof SealedWorkflow;
678
722
  const id = isWorkflow ? target.id ?? "foreach" : `foreach:${target.id}`;
679
723
  const node = {
@@ -686,6 +730,7 @@ var Workflow = class _Workflow extends SealedWorkflow {
686
730
  }
687
731
  const ctx = state.ctx;
688
732
  const results = new Array(items.length);
733
+ const skipped = /* @__PURE__ */ new Set();
689
734
  const executeItem = async (item, index) => {
690
735
  const itemState = { ctx: state.ctx, output: item, mode: "generate" };
691
736
  if (isWorkflow) {
@@ -695,17 +740,47 @@ var Workflow = class _Workflow extends SealedWorkflow {
695
740
  }
696
741
  results[index] = itemState.output;
697
742
  };
743
+ const handleRejection = async (error, item, index) => {
744
+ if (!onError) throw error;
745
+ const recovered = await onError({
746
+ error,
747
+ item,
748
+ index,
749
+ ctx: state.ctx
750
+ });
751
+ if (recovered === _Workflow.SKIP) {
752
+ skipped.add(index);
753
+ } else {
754
+ results[index] = recovered;
755
+ }
756
+ };
698
757
  if (concurrency <= 1) {
699
758
  for (let i = 0; i < items.length; i++) {
700
- await executeItem(items[i], i);
759
+ try {
760
+ await executeItem(items[i], i);
761
+ } catch (error) {
762
+ await handleRejection(error, items[i], i);
763
+ }
701
764
  }
702
765
  } else {
703
- for (let i = 0; i < items.length; i += concurrency) {
704
- const batch = items.slice(i, i + concurrency);
705
- await Promise.all(batch.map((item, j) => executeItem(item, i + j)));
766
+ const sem = new Semaphore(concurrency);
767
+ const failures = [];
768
+ await Promise.all(items.map(async (item, i) => {
769
+ await sem.acquire();
770
+ try {
771
+ await executeItem(item, i);
772
+ } catch (error) {
773
+ failures.push({ index: i, error });
774
+ } finally {
775
+ sem.release();
776
+ }
777
+ }));
778
+ failures.sort((a, b) => a.index - b.index);
779
+ for (const { index, error } of failures) {
780
+ await handleRejection(error, items[index], index);
706
781
  }
707
782
  }
708
- state.output = results;
783
+ state.output = skipped.size === 0 ? results : results.filter((_, i) => !skipped.has(i));
709
784
  }
710
785
  };
711
786
  return new _Workflow([...this.steps, node], this.id);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts"],"sourcesContent":["export { Agent } from \"./agent\";\nexport type {\n AgentConfig,\n GenerateTextResult,\n StreamTextResult,\n OutputType,\n} from \"./agent\";\n\nexport { Workflow, WorkflowBranchError, WorkflowLoopError, WorkflowSuspended } from \"./workflow\";\nexport type { SealedWorkflow, ResumedWorkflow } from \"./workflow\";\nexport type {\n AgentStepHooks,\n StepOptions,\n BranchCase,\n BranchSelect,\n RepeatOptions,\n WorkflowResult,\n WorkflowStreamResult,\n WorkflowStreamOptions,\n WorkflowSnapshot,\n} from \"./workflow\";\n\nexport { defineTool } from \"./tool-provider\";\nexport type { ToolProviderConfig, ToolExecuteOptions, IToolProvider } from \"./tool-provider\";\n\nexport type { MaybePromise, Resolvable } from \"./utils\";\n","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// ── 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 // ── 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 stopWhen?: Resolvable<TContext, TInput, 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 private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\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.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\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,\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(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input, writer: getActiveWriter() })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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 execute: async (toolInput: TInput) => {\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.stream as (ctx: TContext, input: TInput) => Promise<StreamTextResult>)(ctx, toolInput);\n writer.merge(result.toUIMessageStream());\n if (options?.mapOutput) return options.mapOutput(result as unknown as GenerateTextResult);\n return extractOutput(result, this.hasOutput);\n }\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\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\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\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, stopWhen] = 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 resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\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 type { UIMessageStreamWriter } from \"ai\";\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\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 * Extract structured output from an AI SDK result, falling back to text.\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(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\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 { extractOutput, runWithWriter, 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\n// ── Gate / Snapshot Types ─────────────────────────────────────────────\n\nexport interface WorkflowSnapshot {\n readonly version: 1;\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\nexport class WorkflowSuspended extends Error {\n readonly snapshot: WorkflowSnapshot;\n constructor(snapshot: WorkflowSnapshot) {\n super(`Workflow suspended at gate \"${snapshot.gateId}\"`);\n this.name = \"WorkflowSuspended\";\n this.snapshot = snapshot;\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\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\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\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// ── 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\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\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\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\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\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\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 };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\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 // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState, startIndex: number = 0): 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 let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (let i = startIndex; i < this.steps.length; i++) {\n const node = this.steps[i];\n\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\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 } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n if (node.type === \"gate\") {\n if (pendingError) continue; // skip gates while in error state\n // Conditional gate: if condition returns false, skip (passthrough)\n if (node.condition) {\n const shouldSuspend = await node.condition(state);\n if (!shouldSuspend) continue;\n }\n const gatePayload = await node.payload(state);\n throw new WorkflowSuspended({\n version: 1,\n resumeFromIndex: i,\n output: state.output,\n gateId: node.id,\n gatePayload,\n });\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) throw error; // propagate, don't capture\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\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 protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown, any>,\n ): Promise<void> {\n try {\n await workflow.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) {\n throw new Error(\n `Gates inside nested workflows are not yet supported. ` +\n `Gate \"${error.snapshot.gateId}\" was hit inside nested workflow \"${workflow.id ?? \"(anonymous)\"}\". ` +\n `Consider using a conditional gate with \\`condition\\` to skip when criteria are met, ` +\n `or restructure the workflow to use gates at the top level only.`\n );\n }\n throw error;\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 if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools (asTool, defineTool) can access the writer automatically\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\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 if (snapshot.gateId !== gateId) {\n throw new Error(\n `loadState: gate ID mismatch — expected \"${gateId}\" but snapshot has \"${snapshot.gateId}\".`\n );\n }\n const gateIndex = this.findGateIndex(snapshot);\n const gateNode = this.steps[gateIndex] as Extract<StepNode, { type: \"gate\" }>;\n return new ResumedWorkflow<TContext, TGates[K], TOutput>(\n this.steps,\n gateIndex + 1,\n gateNode.schema as SchemaWithParse<TGates[K]> | undefined,\n gateNode.merge,\n snapshot.output,\n );\n }\n\n private findGateIndex(snapshot: WorkflowSnapshot): number {\n if (snapshot.version !== 1) {\n throw new Error(`Unsupported snapshot version: ${snapshot.version}`);\n }\n\n // Fast path: check the hint index first (backward compat + O(1))\n const hint = snapshot.resumeFromIndex;\n if (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\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\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 schema?: SchemaWithParse<TResponse>,\n mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>,\n priorOutput?: unknown,\n ) {\n super(steps);\n this.startIndex = startIndex;\n this.schema = schema;\n this.mergeFn = mergeFn;\n this.priorOutput = priorOutput;\n }\n\n private validateResponse(response: TResponse): TResponse {\n if (this.schema) {\n return this.schema.parse(response);\n }\n return response;\n }\n\n override async generate(\n ctx: TContext,\n ...args: TResponse extends void ? [response?: TResponse] : [response: TResponse]\n ): Promise<WorkflowResult<TOutput>> {\n const response = this.validateResponse(args[0] as TResponse);\n const output = this.mergeFn\n ? await this.mergeFn({ priorOutput: this.priorOutput, response })\n : response;\n const state: RuntimeState = { ctx, output, mode: \"generate\" };\n await this.execute(state, this.startIndex);\n return { output: state.output as TOutput };\n }\n\n override stream(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, options?: WorkflowStreamOptions]\n : [response: TResponse, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const response = this.validateResponse(args[0] as TResponse);\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<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\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const output = mergeFn\n ? await mergeFn({ priorOutput, response })\n : response;\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state, this.startIndex);\n resolveOutput(state.output as TOutput);\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 private constructor(steps: ReadonlyArray<StepNode> = [], id?: string) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\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 // ── 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 execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown, any>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\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 ): 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 ): Workflow<TContext, TInput, TNextOutput, TGates> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\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 throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\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 let agent = config.agents[key];\n if (!agent) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: { concurrency?: number },\n ): Workflow<TContext, TInput, TNextOutput[], TGates> {\n const concurrency = options?.concurrency ?? 1;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\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\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\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 };\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n await executeItem(items[i], i);\n }\n } else {\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n await Promise.all(batch.map((item, j) => executeItem(item, i + j)));\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[], TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput, TGates> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\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 execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\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);\n }\n}\n\n"],"mappings":"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","names":["import_ai","result","import_ai","node"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.ts"],"sourcesContent":["export { Agent } from \"./agent\";\nexport type {\n AgentConfig,\n GenerateTextResult,\n StreamTextResult,\n OutputType,\n} from \"./agent\";\n\nexport { Workflow, WorkflowBranchError, WorkflowLoopError, WorkflowSuspended } from \"./workflow\";\nexport type { SealedWorkflow, ResumedWorkflow } from \"./workflow\";\nexport type {\n AgentStepHooks,\n StepOptions,\n BranchCase,\n BranchSelect,\n RepeatOptions,\n WorkflowResult,\n WorkflowStreamResult,\n WorkflowStreamOptions,\n WorkflowSnapshot,\n} from \"./workflow\";\n\nexport { defineTool } from \"./tool-provider\";\nexport type { ToolProviderConfig, ToolExecuteOptions, IToolProvider } from \"./tool-provider\";\n\nexport type { MaybePromise, Resolvable } from \"./utils\";\n","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// ── 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 // ── 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 stopWhen?: Resolvable<TContext, TInput, 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 private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\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.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\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,\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(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input, writer: getActiveWriter() })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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 execute: async (toolInput: TInput) => {\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.stream as (ctx: TContext, input: TInput) => Promise<StreamTextResult>)(ctx, toolInput);\n writer.merge(result.toUIMessageStream());\n if (options?.mapOutput) return options.mapOutput(result as unknown as GenerateTextResult);\n return extractOutput(result, this.hasOutput);\n }\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\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\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\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, stopWhen] = 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 resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\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 type { UIMessageStreamWriter } from \"ai\";\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\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, falling back to text.\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(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\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 { extractOutput, runWithWriter, Semaphore, 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\n// ── Gate / Snapshot Types ─────────────────────────────────────────────\n\nexport interface WorkflowSnapshot {\n readonly version: 1;\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\nexport class WorkflowSuspended extends Error {\n readonly snapshot: WorkflowSnapshot;\n constructor(snapshot: WorkflowSnapshot) {\n super(`Workflow suspended at gate \"${snapshot.gateId}\"`);\n this.name = \"WorkflowSuspended\";\n this.snapshot = snapshot;\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\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\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\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// ── 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\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\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\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\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\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\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 };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\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 // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState, startIndex: number = 0): 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 let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (let i = startIndex; i < this.steps.length; i++) {\n const node = this.steps[i];\n\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\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 } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n if (node.type === \"gate\") {\n if (pendingError) continue; // skip gates while in error state\n // Conditional gate: if condition returns false, skip (passthrough)\n if (node.condition) {\n const shouldSuspend = await node.condition(state);\n if (!shouldSuspend) continue;\n }\n const gatePayload = await node.payload(state);\n throw new WorkflowSuspended({\n version: 1,\n resumeFromIndex: i,\n output: state.output,\n gateId: node.id,\n gatePayload,\n });\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) throw error; // propagate, don't capture\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\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 protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown, any>,\n ): Promise<void> {\n try {\n await workflow.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) {\n throw new Error(\n `Gates inside nested workflows are not yet supported. ` +\n `Gate \"${error.snapshot.gateId}\" was hit inside nested workflow \"${workflow.id ?? \"(anonymous)\"}\". ` +\n `Consider using a conditional gate with \\`condition\\` to skip when criteria are met, ` +\n `or restructure the workflow to use gates at the top level only.`\n );\n }\n throw error;\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 if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools (asTool, defineTool) can access the writer automatically\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\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 if (snapshot.gateId !== gateId) {\n throw new Error(\n `loadState: gate ID mismatch — expected \"${gateId}\" but snapshot has \"${snapshot.gateId}\".`\n );\n }\n const gateIndex = this.findGateIndex(snapshot);\n const gateNode = this.steps[gateIndex] as Extract<StepNode, { type: \"gate\" }>;\n return new ResumedWorkflow<TContext, TGates[K], TOutput>(\n this.steps,\n gateIndex + 1,\n gateNode.schema as SchemaWithParse<TGates[K]> | undefined,\n gateNode.merge,\n snapshot.output,\n );\n }\n\n private findGateIndex(snapshot: WorkflowSnapshot): number {\n if (snapshot.version !== 1) {\n throw new Error(`Unsupported snapshot version: ${snapshot.version}`);\n }\n\n // Fast path: check the hint index first (backward compat + O(1))\n const hint = snapshot.resumeFromIndex;\n if (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\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\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 schema?: SchemaWithParse<TResponse>,\n mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>,\n priorOutput?: unknown,\n ) {\n super(steps);\n this.startIndex = startIndex;\n this.schema = schema;\n this.mergeFn = mergeFn;\n this.priorOutput = priorOutput;\n }\n\n private validateResponse(response: TResponse): TResponse {\n if (this.schema) {\n return this.schema.parse(response);\n }\n return response;\n }\n\n override async generate(\n ctx: TContext,\n ...args: TResponse extends void ? [response?: TResponse] : [response: TResponse]\n ): Promise<WorkflowResult<TOutput>> {\n const response = this.validateResponse(args[0] as TResponse);\n const output = this.mergeFn\n ? await this.mergeFn({ priorOutput: this.priorOutput, response })\n : response;\n const state: RuntimeState = { ctx, output, mode: \"generate\" };\n await this.execute(state, this.startIndex);\n return { output: state.output as TOutput };\n }\n\n override stream(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, options?: WorkflowStreamOptions]\n : [response: TResponse, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const response = this.validateResponse(args[0] as TResponse);\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<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\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const output = mergeFn\n ? await mergeFn({ priorOutput, response })\n : response;\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state, this.startIndex);\n resolveOutput(state.output as TOutput);\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) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\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 // ── 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 execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown, any>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\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 ): 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 ): Workflow<TContext, TInput, TNextOutput, TGates> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\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 throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\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 let agent = config.agents[key];\n if (!agent) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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.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. When provided, a single\n * item's failure no longer aborts the foreach. Return a `TNextOutput` value\n * to substitute for the failed item, return `Workflow.SKIP` to omit the\n * index (shortening the output array), or throw / return a rejected promise\n * to abort the foreach step (the thrown error is caught by any downstream\n * `.catch()`). When omitted, the existing fail-fast behavior is preserved.\n * `onError` is 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 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 id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\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\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\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 };\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 if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n try {\n await executeItem(items[i], i);\n } catch (error) {\n await handleRejection(error, items[i], i);\n }\n }\n } else {\n // Bounded concurrency via semaphore: at most `concurrency` items run\n // simultaneously; the next one starts as soon as one releases.\n // Failures are buffered and processed in index order AFTER all items\n // settle so onError invocations remain deterministic.\n const sem = new Semaphore(concurrency);\n const failures: Array<{ index: number; error: unknown }> = [];\n\n await Promise.all(items.map(async (item, i) => {\n await sem.acquire();\n try {\n await executeItem(item, i);\n } catch (error) {\n failures.push({ index: i, error });\n } finally {\n sem.release();\n }\n }));\n\n failures.sort((a, b) => a.index - b.index);\n for (const { index, error } of failures) {\n await handleRejection(error, items[index], index);\n }\n }\n\n state.output = skipped.size === 0\n ? results\n : results.filter((_, i) => !skipped.has(i));\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[], TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput, TGates> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\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 execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\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);\n }\n}\n\n"],"mappings":"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","names":["import_ai","result","import_ai","node"]}
package/dist/index.d.cts CHANGED
@@ -254,6 +254,12 @@ declare class ResumedWorkflow<TContext, TResponse = unknown, TOutput = void> ext
254
254
  stream(ctx: TContext, ...args: TResponse extends void ? [response?: TResponse, options?: WorkflowStreamOptions] : [response: TResponse, options?: WorkflowStreamOptions]): WorkflowStreamResult<TOutput>;
255
255
  }
256
256
  declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends Record<string, unknown> = {}> extends SealedWorkflow<TContext, TInput, TOutput, TGates> {
257
+ /**
258
+ * Sentinel value for `foreach`'s `onError` handler. Returning `Workflow.SKIP`
259
+ * from `onError` omits the failed item's index from the output array,
260
+ * shortening it relative to the input array.
261
+ */
262
+ static readonly SKIP: unique symbol;
257
263
  private constructor();
258
264
  static create<TContext, TInput = void>(options?: {
259
265
  id?: string;
@@ -284,8 +290,29 @@ declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends R
284
290
  branch<TKeys extends string, TNextOutput>(config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>): Workflow<TContext, TInput, TNextOutput, TGates>;
285
291
  private branchPredicate;
286
292
  private branchSelect;
293
+ /**
294
+ * Map each item of an array through an agent or sub-workflow.
295
+ *
296
+ * @param target Agent or `SealedWorkflow` invoked once per item.
297
+ * @param options.concurrency Max items in flight at any moment (default 1).
298
+ * Backed by a semaphore: as soon as one item completes, the next launches —
299
+ * no lockstep batching.
300
+ * @param options.onError Per-iteration error handler. When provided, a single
301
+ * item's failure no longer aborts the foreach. Return a `TNextOutput` value
302
+ * to substitute for the failed item, return `Workflow.SKIP` to omit the
303
+ * index (shortening the output array), or throw / return a rejected promise
304
+ * to abort the foreach step (the thrown error is caught by any downstream
305
+ * `.catch()`). When omitted, the existing fail-fast behavior is preserved.
306
+ * `onError` is invoked sequentially in index order after all items settle.
307
+ */
287
308
  foreach<TNextOutput>(target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>, options?: {
288
309
  concurrency?: number;
310
+ onError?: (params: {
311
+ error: unknown;
312
+ item: ElementOf<TOutput>;
313
+ index: number;
314
+ ctx: Readonly<TContext>;
315
+ }) => MaybePromise<TNextOutput | typeof Workflow.SKIP>;
289
316
  }): Workflow<TContext, TInput, TNextOutput[], TGates>;
290
317
  repeat(target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>, options: RepeatOptions<TContext, TOutput>): Workflow<TContext, TInput, TOutput, TGates>;
291
318
  catch(id: string, fn: (params: {
package/dist/index.d.ts CHANGED
@@ -254,6 +254,12 @@ declare class ResumedWorkflow<TContext, TResponse = unknown, TOutput = void> ext
254
254
  stream(ctx: TContext, ...args: TResponse extends void ? [response?: TResponse, options?: WorkflowStreamOptions] : [response: TResponse, options?: WorkflowStreamOptions]): WorkflowStreamResult<TOutput>;
255
255
  }
256
256
  declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends Record<string, unknown> = {}> extends SealedWorkflow<TContext, TInput, TOutput, TGates> {
257
+ /**
258
+ * Sentinel value for `foreach`'s `onError` handler. Returning `Workflow.SKIP`
259
+ * from `onError` omits the failed item's index from the output array,
260
+ * shortening it relative to the input array.
261
+ */
262
+ static readonly SKIP: unique symbol;
257
263
  private constructor();
258
264
  static create<TContext, TInput = void>(options?: {
259
265
  id?: string;
@@ -284,8 +290,29 @@ declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends R
284
290
  branch<TKeys extends string, TNextOutput>(config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>): Workflow<TContext, TInput, TNextOutput, TGates>;
285
291
  private branchPredicate;
286
292
  private branchSelect;
293
+ /**
294
+ * Map each item of an array through an agent or sub-workflow.
295
+ *
296
+ * @param target Agent or `SealedWorkflow` invoked once per item.
297
+ * @param options.concurrency Max items in flight at any moment (default 1).
298
+ * Backed by a semaphore: as soon as one item completes, the next launches —
299
+ * no lockstep batching.
300
+ * @param options.onError Per-iteration error handler. When provided, a single
301
+ * item's failure no longer aborts the foreach. Return a `TNextOutput` value
302
+ * to substitute for the failed item, return `Workflow.SKIP` to omit the
303
+ * index (shortening the output array), or throw / return a rejected promise
304
+ * to abort the foreach step (the thrown error is caught by any downstream
305
+ * `.catch()`). When omitted, the existing fail-fast behavior is preserved.
306
+ * `onError` is invoked sequentially in index order after all items settle.
307
+ */
287
308
  foreach<TNextOutput>(target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>, options?: {
288
309
  concurrency?: number;
310
+ onError?: (params: {
311
+ error: unknown;
312
+ item: ElementOf<TOutput>;
313
+ index: number;
314
+ ctx: Readonly<TContext>;
315
+ }) => MaybePromise<TNextOutput | typeof Workflow.SKIP>;
289
316
  }): Workflow<TContext, TInput, TNextOutput[], TGates>;
290
317
  repeat(target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>, options: RepeatOptions<TContext, TOutput>): Workflow<TContext, TInput, TOutput, TGates>;
291
318
  catch(id: string, fn: (params: {
package/dist/index.js CHANGED
@@ -23,6 +23,28 @@ function resolveValue(value, ctx, input) {
23
23
  }
24
24
  return value;
25
25
  }
26
+ var Semaphore = class {
27
+ available;
28
+ waiters = [];
29
+ constructor(permits) {
30
+ if (!Number.isInteger(permits) || permits < 1) {
31
+ throw new Error(`Semaphore: permits must be a positive integer, got ${permits}`);
32
+ }
33
+ this.available = permits;
34
+ }
35
+ async acquire() {
36
+ if (this.available > 0) {
37
+ this.available--;
38
+ return;
39
+ }
40
+ await new Promise((resolve) => this.waiters.push(resolve));
41
+ }
42
+ release() {
43
+ const next = this.waiters.shift();
44
+ if (next) next();
45
+ else this.available++;
46
+ }
47
+ };
26
48
  async function extractOutput(result, hasStructuredOutput) {
27
49
  if (hasStructuredOutput) {
28
50
  const output = await result.output;
@@ -521,6 +543,12 @@ var ResumedWorkflow = class extends SealedWorkflow {
521
543
  }
522
544
  };
523
545
  var Workflow = class _Workflow extends SealedWorkflow {
546
+ /**
547
+ * Sentinel value for `foreach`'s `onError` handler. Returning `Workflow.SKIP`
548
+ * from `onError` omits the failed item's index from the output array,
549
+ * shortening it relative to the input array.
550
+ */
551
+ static SKIP = /* @__PURE__ */ Symbol("pipeai.foreach.skip");
524
552
  constructor(steps = [], id) {
525
553
  super(steps, id);
526
554
  }
@@ -647,8 +675,24 @@ var Workflow = class _Workflow extends SealedWorkflow {
647
675
  return new _Workflow([...this.steps, node], this.id);
648
676
  }
649
677
  // ── foreach: array iteration ─────────────────────────────────
678
+ /**
679
+ * Map each item of an array through an agent or sub-workflow.
680
+ *
681
+ * @param target Agent or `SealedWorkflow` invoked once per item.
682
+ * @param options.concurrency Max items in flight at any moment (default 1).
683
+ * Backed by a semaphore: as soon as one item completes, the next launches —
684
+ * no lockstep batching.
685
+ * @param options.onError Per-iteration error handler. When provided, a single
686
+ * item's failure no longer aborts the foreach. Return a `TNextOutput` value
687
+ * to substitute for the failed item, return `Workflow.SKIP` to omit the
688
+ * index (shortening the output array), or throw / return a rejected promise
689
+ * to abort the foreach step (the thrown error is caught by any downstream
690
+ * `.catch()`). When omitted, the existing fail-fast behavior is preserved.
691
+ * `onError` is invoked sequentially in index order after all items settle.
692
+ */
650
693
  foreach(target, options) {
651
694
  const concurrency = options?.concurrency ?? 1;
695
+ const onError = options?.onError;
652
696
  const isWorkflow = target instanceof SealedWorkflow;
653
697
  const id = isWorkflow ? target.id ?? "foreach" : `foreach:${target.id}`;
654
698
  const node = {
@@ -661,6 +705,7 @@ var Workflow = class _Workflow extends SealedWorkflow {
661
705
  }
662
706
  const ctx = state.ctx;
663
707
  const results = new Array(items.length);
708
+ const skipped = /* @__PURE__ */ new Set();
664
709
  const executeItem = async (item, index) => {
665
710
  const itemState = { ctx: state.ctx, output: item, mode: "generate" };
666
711
  if (isWorkflow) {
@@ -670,17 +715,47 @@ var Workflow = class _Workflow extends SealedWorkflow {
670
715
  }
671
716
  results[index] = itemState.output;
672
717
  };
718
+ const handleRejection = async (error, item, index) => {
719
+ if (!onError) throw error;
720
+ const recovered = await onError({
721
+ error,
722
+ item,
723
+ index,
724
+ ctx: state.ctx
725
+ });
726
+ if (recovered === _Workflow.SKIP) {
727
+ skipped.add(index);
728
+ } else {
729
+ results[index] = recovered;
730
+ }
731
+ };
673
732
  if (concurrency <= 1) {
674
733
  for (let i = 0; i < items.length; i++) {
675
- await executeItem(items[i], i);
734
+ try {
735
+ await executeItem(items[i], i);
736
+ } catch (error) {
737
+ await handleRejection(error, items[i], i);
738
+ }
676
739
  }
677
740
  } else {
678
- for (let i = 0; i < items.length; i += concurrency) {
679
- const batch = items.slice(i, i + concurrency);
680
- await Promise.all(batch.map((item, j) => executeItem(item, i + j)));
741
+ const sem = new Semaphore(concurrency);
742
+ const failures = [];
743
+ await Promise.all(items.map(async (item, i) => {
744
+ await sem.acquire();
745
+ try {
746
+ await executeItem(item, i);
747
+ } catch (error) {
748
+ failures.push({ index: i, error });
749
+ } finally {
750
+ sem.release();
751
+ }
752
+ }));
753
+ failures.sort((a, b) => a.index - b.index);
754
+ for (const { index, error } of failures) {
755
+ await handleRejection(error, items[index], index);
681
756
  }
682
757
  }
683
- state.output = results;
758
+ state.output = skipped.size === 0 ? results : results.filter((_, i) => !skipped.has(i));
684
759
  }
685
760
  };
686
761
  return new _Workflow([...this.steps, node], this.id);
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"],"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// ── 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 // ── 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 stopWhen?: Resolvable<TContext, TInput, 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 private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\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.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\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,\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(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input, writer: getActiveWriter() })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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 execute: async (toolInput: TInput) => {\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.stream as (ctx: TContext, input: TInput) => Promise<StreamTextResult>)(ctx, toolInput);\n writer.merge(result.toUIMessageStream());\n if (options?.mapOutput) return options.mapOutput(result as unknown as GenerateTextResult);\n return extractOutput(result, this.hasOutput);\n }\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\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\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\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, stopWhen] = 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 resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\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 type { UIMessageStreamWriter } from \"ai\";\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\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 * Extract structured output from an AI SDK result, falling back to text.\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(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\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 { extractOutput, runWithWriter, 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\n// ── Gate / Snapshot Types ─────────────────────────────────────────────\n\nexport interface WorkflowSnapshot {\n readonly version: 1;\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\nexport class WorkflowSuspended extends Error {\n readonly snapshot: WorkflowSnapshot;\n constructor(snapshot: WorkflowSnapshot) {\n super(`Workflow suspended at gate \"${snapshot.gateId}\"`);\n this.name = \"WorkflowSuspended\";\n this.snapshot = snapshot;\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\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\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\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// ── 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\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\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\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\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\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\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 };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\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 // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState, startIndex: number = 0): 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 let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (let i = startIndex; i < this.steps.length; i++) {\n const node = this.steps[i];\n\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\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 } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n if (node.type === \"gate\") {\n if (pendingError) continue; // skip gates while in error state\n // Conditional gate: if condition returns false, skip (passthrough)\n if (node.condition) {\n const shouldSuspend = await node.condition(state);\n if (!shouldSuspend) continue;\n }\n const gatePayload = await node.payload(state);\n throw new WorkflowSuspended({\n version: 1,\n resumeFromIndex: i,\n output: state.output,\n gateId: node.id,\n gatePayload,\n });\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) throw error; // propagate, don't capture\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\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 protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown, any>,\n ): Promise<void> {\n try {\n await workflow.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) {\n throw new Error(\n `Gates inside nested workflows are not yet supported. ` +\n `Gate \"${error.snapshot.gateId}\" was hit inside nested workflow \"${workflow.id ?? \"(anonymous)\"}\". ` +\n `Consider using a conditional gate with \\`condition\\` to skip when criteria are met, ` +\n `or restructure the workflow to use gates at the top level only.`\n );\n }\n throw error;\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 if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools (asTool, defineTool) can access the writer automatically\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\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 if (snapshot.gateId !== gateId) {\n throw new Error(\n `loadState: gate ID mismatch — expected \"${gateId}\" but snapshot has \"${snapshot.gateId}\".`\n );\n }\n const gateIndex = this.findGateIndex(snapshot);\n const gateNode = this.steps[gateIndex] as Extract<StepNode, { type: \"gate\" }>;\n return new ResumedWorkflow<TContext, TGates[K], TOutput>(\n this.steps,\n gateIndex + 1,\n gateNode.schema as SchemaWithParse<TGates[K]> | undefined,\n gateNode.merge,\n snapshot.output,\n );\n }\n\n private findGateIndex(snapshot: WorkflowSnapshot): number {\n if (snapshot.version !== 1) {\n throw new Error(`Unsupported snapshot version: ${snapshot.version}`);\n }\n\n // Fast path: check the hint index first (backward compat + O(1))\n const hint = snapshot.resumeFromIndex;\n if (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\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\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 schema?: SchemaWithParse<TResponse>,\n mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>,\n priorOutput?: unknown,\n ) {\n super(steps);\n this.startIndex = startIndex;\n this.schema = schema;\n this.mergeFn = mergeFn;\n this.priorOutput = priorOutput;\n }\n\n private validateResponse(response: TResponse): TResponse {\n if (this.schema) {\n return this.schema.parse(response);\n }\n return response;\n }\n\n override async generate(\n ctx: TContext,\n ...args: TResponse extends void ? [response?: TResponse] : [response: TResponse]\n ): Promise<WorkflowResult<TOutput>> {\n const response = this.validateResponse(args[0] as TResponse);\n const output = this.mergeFn\n ? await this.mergeFn({ priorOutput: this.priorOutput, response })\n : response;\n const state: RuntimeState = { ctx, output, mode: \"generate\" };\n await this.execute(state, this.startIndex);\n return { output: state.output as TOutput };\n }\n\n override stream(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, options?: WorkflowStreamOptions]\n : [response: TResponse, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const response = this.validateResponse(args[0] as TResponse);\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<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\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const output = mergeFn\n ? await mergeFn({ priorOutput, response })\n : response;\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state, this.startIndex);\n resolveOutput(state.output as TOutput);\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 private constructor(steps: ReadonlyArray<StepNode> = [], id?: string) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\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 // ── 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 execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown, any>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\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 ): 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 ): Workflow<TContext, TInput, TNextOutput, TGates> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\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 throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\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 let agent = config.agents[key];\n if (!agent) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── foreach: array iteration ─────────────────────────────────\n\n foreach<TNextOutput>(\n target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput>,\n options?: { concurrency?: number },\n ): Workflow<TContext, TInput, TNextOutput[], TGates> {\n const concurrency = options?.concurrency ?? 1;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\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\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\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 };\n\n if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n await executeItem(items[i], i);\n }\n } else {\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n await Promise.all(batch.map((item, j) => executeItem(item, i + j)));\n }\n }\n\n state.output = results;\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[], TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput, TGates> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\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 execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\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);\n }\n}\n\n"],"mappings":"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","names":["tool","tool","result","node"]}
1
+ {"version":3,"sources":["../src/agent.ts","../src/tool-provider.ts","../src/utils.ts","../src/workflow.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// ── 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 // ── 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 stopWhen?: Resolvable<TContext, TInput, 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 private readonly config: AgentConfig<TContext, TInput, TOutput>;\n private readonly _hasDynamicConfig: boolean;\n private readonly _resolvedStaticTools: Record<string, Tool> | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _passthrough: Record<string, any>;\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.config = config;\n this._hasDynamicConfig = [\n config.model, config.system, config.prompt,\n config.messages, config.tools, config.activeTools,\n config.toolChoice, config.stopWhen,\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,\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(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<GenerateTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await generateText(options as any);\n } catch (error: unknown) {\n if (this.config.onError) {\n await this.config.onError({ error, ctx, input, writer: getActiveWriter() });\n }\n throw error;\n }\n }\n\n async stream(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<StreamTextResult<ToolSet, OutputType<TOutput>>> {\n const input = args[0] as TInput;\n const resolved = await this.resolveConfig(ctx, input);\n const options = this.buildCallOptions(resolved, ctx, input);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return streamText({\n ...options,\n onError: this.config.onError\n ? ({ error }: { error: unknown }) => this.config.onError!({ error, ctx, input, writer: getActiveWriter() })\n : undefined,\n } as any);\n }\n\n asTool(ctx: TContext, options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<TOutput>;\n }): Tool {\n return this.createToolInstance(ctx, options);\n }\n\n asToolProvider(options?: {\n mapOutput?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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?: (result: GenerateTextResult<ToolSet, OutputType<TOutput>>) => MaybePromise<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 execute: async (toolInput: TInput) => {\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.stream as (ctx: TContext, input: TInput) => Promise<StreamTextResult>)(ctx, toolInput);\n writer.merge(result.toUIMessageStream());\n if (options?.mapOutput) return options.mapOutput(result as unknown as GenerateTextResult);\n return extractOutput(result, this.hasOutput);\n }\n const result = await (this.generate as (ctx: TContext, input: TInput) => Promise<GenerateTextResult>)(ctx, toolInput);\n if (options?.mapOutput) return options.mapOutput(result);\n return extractOutput(result, this.hasOutput);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private buildCallOptions(resolved: ResolvedAgentConfig, ctx: TContext, input: TInput): Record<string, any> {\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\n ? { messages: resolved.messages }\n : { prompt: resolved.prompt ?? \"\" }),\n ...(resolved.system ? { system: resolved.system } : {}),\n ...(this.config.output ? { output: this.config.output } : {}),\n onStepFinish: this._onStepFinish\n ? (event: OnStepFinishEvent) => this._onStepFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\n onFinish: this._onFinish\n ? (event: OnFinishEvent) => this._onFinish!({ result: event, ctx, input, writer: getActiveWriter() })\n : undefined,\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, stopWhen] = 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 resolveValue(this.config.stopWhen, ctx, input),\n ]);\n const tools = this.resolveTools(rawTools ?? {}, ctx);\n return { model, prompt, system, messages, tools, activeTools, toolChoice, stopWhen };\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 type { UIMessageStreamWriter } from \"ai\";\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\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, falling back to text.\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(result: any, hasStructuredOutput: boolean): Promise<unknown> {\n if (hasStructuredOutput) {\n const output = await result.output;\n if (output !== undefined) return output;\n }\n return await result.text;\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 { extractOutput, runWithWriter, Semaphore, 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\n// ── Gate / Snapshot Types ─────────────────────────────────────────────\n\nexport interface WorkflowSnapshot {\n readonly version: 1;\n readonly resumeFromIndex: number;\n readonly output: unknown;\n readonly gateId: string;\n readonly gatePayload: unknown;\n}\n\nexport class WorkflowSuspended extends Error {\n readonly snapshot: WorkflowSnapshot;\n constructor(snapshot: WorkflowSnapshot) {\n super(`Workflow suspended at gate \"${snapshot.gateId}\"`);\n this.name = \"WorkflowSuspended\";\n this.snapshot = snapshot;\n }\n}\n\n// ── Shared Agent Step Hooks ─────────────────────────────────────────\n\nexport interface AgentStepHooks<TContext, TOutput, TNextOutput> {\n mapGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n mapStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<TNextOutput>;\n onGenerateResult?: (params: { result: GenerateTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\n onStreamResult?: (params: { result: StreamTextResult<ToolSet, OutputType<TNextOutput>>; ctx: Readonly<TContext>; input: TOutput }) => MaybePromise<void>;\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\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n agents: Record<TKeys, Agent<TContext, any, TNextOutput>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fallback?: Agent<TContext, any, TNextOutput>;\n}\n\n// ── Result Types ────────────────────────────────────────────────────\n\nexport interface WorkflowResult<TOutput> {\n output: TOutput;\n}\n\nexport interface WorkflowStreamResult<TOutput> {\n stream: ReadableStream;\n output: Promise<TOutput>;\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// ── 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\ntype StepNode =\n | { readonly type: \"step\"; readonly id: string; readonly execute: (state: RuntimeState) => MaybePromise<void> }\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\ninterface RuntimeState {\n ctx: unknown;\n output: unknown;\n mode: \"generate\" | \"stream\";\n writer?: UIMessageStreamWriter;\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\n protected constructor(steps: ReadonlyArray<StepNode>, id?: string) {\n this.steps = steps;\n this.id = id;\n }\n\n // ── Execution ─────────────────────────────────────────────────\n\n async generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput] : [input: TInput]): Promise<WorkflowResult<TOutput>> {\n const input = args[0];\n const state: RuntimeState = {\n ctx,\n output: input,\n mode: \"generate\",\n };\n\n await this.execute(state);\n\n return {\n output: state.output as TOutput,\n };\n }\n\n stream(\n ctx: TContext,\n ...args: TInput extends void\n ? [input?: TInput, options?: WorkflowStreamOptions]\n : [input: TInput, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const input = args[0];\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<TOutput>((res, rej) => {\n resolveOutput = res;\n rejectOutput = rej;\n });\n\n // Prevent unhandled rejection warning if the consumer never awaits `output`.\n // The original promise still rejects normally when awaited.\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 };\n\n try {\n await this.execute(state);\n resolveOutput(state.output as TOutput);\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 // ── Internal: execute pipeline ────────────────────────────────\n\n protected async execute(state: RuntimeState, startIndex: number = 0): 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 let pendingError: { error: unknown; stepId: string } | null = null;\n\n for (let i = startIndex; i < this.steps.length; i++) {\n const node = this.steps[i];\n\n if (node.type === \"finally\") {\n await node.execute(state);\n continue;\n }\n\n if (node.type === \"catch\") {\n if (!pendingError) continue;\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 } catch (catchError) {\n pendingError = { error: catchError, stepId: node.id };\n }\n continue;\n }\n\n if (node.type === \"gate\") {\n if (pendingError) continue; // skip gates while in error state\n // Conditional gate: if condition returns false, skip (passthrough)\n if (node.condition) {\n const shouldSuspend = await node.condition(state);\n if (!shouldSuspend) continue;\n }\n const gatePayload = await node.payload(state);\n throw new WorkflowSuspended({\n version: 1,\n resumeFromIndex: i,\n output: state.output,\n gateId: node.id,\n gatePayload,\n });\n }\n\n // type === \"step\" — skip while in error state\n if (pendingError) continue;\n\n try {\n await node.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) throw error; // propagate, don't capture\n pendingError = { error, stepId: node.id };\n }\n }\n\n if (pendingError) throw pendingError.error;\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 protected async executeNestedWorkflow(\n state: RuntimeState,\n workflow: SealedWorkflow<TContext, unknown, unknown, any>,\n ): Promise<void> {\n try {\n await workflow.execute(state);\n } catch (error) {\n if (error instanceof WorkflowSuspended) {\n throw new Error(\n `Gates inside nested workflows are not yet supported. ` +\n `Gate \"${error.snapshot.gateId}\" was hit inside nested workflow \"${workflow.id ?? \"(anonymous)\"}\". ` +\n `Consider using a conditional gate with \\`condition\\` to skip when criteria are met, ` +\n `or restructure the workflow to use gates at the top level only.`\n );\n }\n throw error;\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 if (state.mode === \"stream\" && state.writer) {\n const writer = state.writer;\n // Run inside writer context so tools (asTool, defineTool) can access the writer automatically\n await runWithWriter(writer, async () => {\n const result = await (agent.stream as (ctx: TContext, input: unknown) => Promise<StreamTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.handleStream) {\n await options.handleStream({ result, writer, ctx });\n } else {\n writer.merge(result.toUIMessageStream());\n }\n\n if (options?.onStreamResult) {\n await options.onStreamResult({ result, ctx, input });\n }\n\n if (options?.mapStreamResult) {\n state.output = await options.mapStreamResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\n }\n });\n } else {\n const result = await (agent.generate as (ctx: TContext, input: unknown) => Promise<GenerateTextResult<ToolSet, OutputType<TNextOutput>>>)(ctx, state.output);\n\n if (options?.onGenerateResult) {\n await options.onGenerateResult({ result, ctx, input });\n }\n\n if (options?.mapGenerateResult) {\n state.output = await options.mapGenerateResult({ result, ctx, input });\n } else {\n state.output = await extractOutput(result, hasStructuredOutput);\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 if (snapshot.gateId !== gateId) {\n throw new Error(\n `loadState: gate ID mismatch — expected \"${gateId}\" but snapshot has \"${snapshot.gateId}\".`\n );\n }\n const gateIndex = this.findGateIndex(snapshot);\n const gateNode = this.steps[gateIndex] as Extract<StepNode, { type: \"gate\" }>;\n return new ResumedWorkflow<TContext, TGates[K], TOutput>(\n this.steps,\n gateIndex + 1,\n gateNode.schema as SchemaWithParse<TGates[K]> | undefined,\n gateNode.merge,\n snapshot.output,\n );\n }\n\n private findGateIndex(snapshot: WorkflowSnapshot): number {\n if (snapshot.version !== 1) {\n throw new Error(`Unsupported snapshot version: ${snapshot.version}`);\n }\n\n // Fast path: check the hint index first (backward compat + O(1))\n const hint = snapshot.resumeFromIndex;\n if (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\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\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 schema?: SchemaWithParse<TResponse>,\n mergeFn?: (params: { priorOutput: unknown; response: unknown }) => MaybePromise<unknown>,\n priorOutput?: unknown,\n ) {\n super(steps);\n this.startIndex = startIndex;\n this.schema = schema;\n this.mergeFn = mergeFn;\n this.priorOutput = priorOutput;\n }\n\n private validateResponse(response: TResponse): TResponse {\n if (this.schema) {\n return this.schema.parse(response);\n }\n return response;\n }\n\n override async generate(\n ctx: TContext,\n ...args: TResponse extends void ? [response?: TResponse] : [response: TResponse]\n ): Promise<WorkflowResult<TOutput>> {\n const response = this.validateResponse(args[0] as TResponse);\n const output = this.mergeFn\n ? await this.mergeFn({ priorOutput: this.priorOutput, response })\n : response;\n const state: RuntimeState = { ctx, output, mode: \"generate\" };\n await this.execute(state, this.startIndex);\n return { output: state.output as TOutput };\n }\n\n override stream(\n ctx: TContext,\n ...args: TResponse extends void\n ? [response?: TResponse, options?: WorkflowStreamOptions]\n : [response: TResponse, options?: WorkflowStreamOptions]\n ): WorkflowStreamResult<TOutput> {\n const response = this.validateResponse(args[0] as TResponse);\n const options = args[1] as WorkflowStreamOptions | undefined;\n\n let resolveOutput: (value: TOutput) => void;\n let rejectOutput: (error: unknown) => void;\n const outputPromise = new Promise<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\n const stream = createUIMessageStream({\n execute: async ({ writer }) => {\n const output = mergeFn\n ? await mergeFn({ priorOutput, response })\n : response;\n const state: RuntimeState = {\n ctx,\n output,\n mode: \"stream\",\n writer,\n };\n\n try {\n await this.execute(state, this.startIndex);\n resolveOutput(state.output as TOutput);\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) {\n super(steps, id);\n }\n\n static create<TContext, TInput = void>(options?: { id?: string }): Workflow<TContext, TInput, TInput> {\n return new Workflow<TContext, TInput, TInput>([], options?.id);\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 // ── 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 execute: async (state) => {\n await this.executeNestedWorkflow(state, workflow as SealedWorkflow<TContext, unknown, unknown, any>);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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: agent.id,\n execute: async (state) => {\n const ctx = state.ctx as TContext;\n await this.executeAgent(state, agent, ctx, options);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>>([...this.steps, node] as any, this.id);\n }\n\n // ── branch: predicate routing (array) ─────────────────────────\n\n branch<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\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 ): 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 ): Workflow<TContext, TInput, TNextOutput, TGates> {\n if (Array.isArray(casesOrConfig)) {\n return this.branchPredicate(casesOrConfig);\n }\n return this.branchSelect(casesOrConfig);\n }\n\n private branchPredicate<TNextOutput>(\n cases: BranchCase<TContext, TOutput, TNextOutput>[]\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:predicate\",\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 throw new WorkflowBranchError(\"predicate\", `No branch matched and no default branch (a case without \\`when\\`) was provided. Input: ${JSON.stringify(input)}`);\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n private branchSelect<TKeys extends string, TNextOutput>(\n config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>\n ): Workflow<TContext, TInput, TNextOutput, TGates> {\n const node: StepNode = {\n type: \"step\",\n id: \"branch:select\",\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 let agent = config.agents[key];\n if (!agent) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput, TGates>([...this.steps, node] as any, this.id);\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.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. When provided, a single\n * item's failure no longer aborts the foreach. Return a `TNextOutput` value\n * to substitute for the failed item, return `Workflow.SKIP` to omit the\n * index (shortening the output array), or throw / return a rejected promise\n * to abort the foreach step (the thrown error is caught by any downstream\n * `.catch()`). When omitted, the existing fail-fast behavior is preserved.\n * `onError` is 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 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 id = isWorkflow ? (target.id ?? \"foreach\") : `foreach:${(target as Agent<TContext, ElementOf<TOutput>, TNextOutput>).id}`;\n\n const node: StepNode = {\n type: \"step\",\n id,\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\n // Streaming is intentionally not propagated to foreach items —\n // each item runs in generate mode because merging interleaved\n // streams from parallel items into a single writer is not supported.\n const executeItem = async (item: unknown, index: number) => {\n const itemState: RuntimeState = { ctx: state.ctx, output: item, mode: \"generate\" };\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 };\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 if (concurrency <= 1) {\n for (let i = 0; i < items.length; i++) {\n try {\n await executeItem(items[i], i);\n } catch (error) {\n await handleRejection(error, items[i], i);\n }\n }\n } else {\n // Bounded concurrency via semaphore: at most `concurrency` items run\n // simultaneously; the next one starts as soon as one releases.\n // Failures are buffered and processed in index order AFTER all items\n // settle so onError invocations remain deterministic.\n const sem = new Semaphore(concurrency);\n const failures: Array<{ index: number; error: unknown }> = [];\n\n await Promise.all(items.map(async (item, i) => {\n await sem.acquire();\n try {\n await executeItem(item, i);\n } catch (error) {\n failures.push({ index: i, error });\n } finally {\n sem.release();\n }\n }));\n\n failures.sort((a, b) => a.index - b.index);\n for (const { index, error } of failures) {\n await handleRejection(error, items[index], index);\n }\n }\n\n state.output = skipped.size === 0\n ? results\n : results.filter((_, i) => !skipped.has(i));\n },\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TNextOutput[], TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── repeat: conditional loop ─────────────────────────────────\n\n repeat(\n target: Agent<TContext, TOutput, TOutput> | SealedWorkflow<TContext, TOutput, TOutput>,\n options: RepeatOptions<TContext, TOutput>,\n ): Workflow<TContext, TInput, TOutput, TGates> {\n const maxIterations = options.maxIterations ?? 10;\n const isWorkflow = target instanceof SealedWorkflow;\n const id = isWorkflow ? (target.id ?? \"repeat\") : `repeat:${(target as Agent<TContext, TOutput, TOutput>).id}`;\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 execute: async (state) => {\n const ctx = state.ctx as TContext;\n\n for (let i = 1; i <= maxIterations; i++) {\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new Workflow<TContext, TInput, TOutput, TGates>([...this.steps, node] as any, this.id);\n }\n\n // ── finally (terminal — returns sealed workflow) ──────────────\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);\n }\n}\n\n"],"mappings":"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","names":["tool","tool","result","node"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pipeai",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "A typed multi-agent workflow pipeline built on top of the Vercel AI SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",