pipeai 0.8.4 → 0.9.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Tool, ToolExecutionOptions, UIMessageStreamWriter, FlexibleSchema, streamText, generateText, Output, LanguageModel, ModelMessage, ToolChoice, ToolSet, StopCondition, OnStepFinishEvent, OnFinishEvent, GenerateTextResult as GenerateTextResult$1, StreamTextResult as StreamTextResult$1, UIMessage, UIMessageStreamOnFinishCallback, IdGenerator } from 'ai';
1
+ import { Tool, ToolExecutionOptions, UIMessageStreamWriter, FlexibleSchema, streamText, generateText, Output, LanguageModel, ModelMessage, ToolChoice, ToolSet, StopCondition, OnStepFinishEvent, OnFinishEvent, GenerateTextResult as GenerateTextResult$1, StreamTextResult as StreamTextResult$1, UIMessage, UIMessageStreamOnFinishCallback, IdGenerator, InferUIMessageChunk } from 'ai';
2
2
  import { ZodType } from 'zod';
3
3
 
4
4
  declare const TOOL_PROVIDER_BRAND: unique symbol;
@@ -479,8 +479,8 @@ type WorkflowResult<TOutput> = {
479
479
  readonly snapshot: GateSnapshot;
480
480
  readonly warnings: readonly WorkflowWarning[];
481
481
  };
482
- interface WorkflowStreamResult<TOutput> {
483
- stream: ReadableStream;
482
+ interface WorkflowStreamResult<TOutput, UI_MESSAGE extends UIMessage = UIMessage> {
483
+ stream: ReadableStream<InferUIMessageChunk<UI_MESSAGE>>;
484
484
  output: Promise<WorkflowResult<TOutput>>;
485
485
  }
486
486
  /**
@@ -551,6 +551,46 @@ type RepeatOptions<TContext, TOutput> = {
551
551
  maxIterations?: number;
552
552
  };
553
553
  type ElementOf<T> = T extends readonly (infer E)[] ? E : never;
554
+ /**
555
+ * Options for `Workflow.foreach` — shared by the agent / sub-workflow target
556
+ * form and the per-item path-builder callback form.
557
+ */
558
+ interface ForeachOptions<TContext, TOutput, TNextOutput> {
559
+ /** Override the default step id (`foreach:<agentId>` or the body workflow's id). */
560
+ id?: string;
561
+ /**
562
+ * Max items in flight at any moment. **Default: unbounded** (`Infinity` — every
563
+ * item runs concurrently, clamped only by item count). Pass an integer to
564
+ * throttle against provider rate limits. Backed by a worker pool: as soon as
565
+ * one item completes, the next launches — no lockstep batching.
566
+ */
567
+ concurrency?: number;
568
+ /**
569
+ * Per-iteration error handler. Return a `TNextOutput` to substitute, return
570
+ * `Workflow.SKIP` to omit the item, or throw to abort. Invoked sequentially in
571
+ * index order after all items settle. **Bypassed on the abort path.**
572
+ */
573
+ onError?: (params: {
574
+ error: unknown;
575
+ item: ElementOf<TOutput>;
576
+ index: number;
577
+ ctx: Readonly<TContext>;
578
+ }) => MaybePromise<TNextOutput | SkipSentinel>;
579
+ /**
580
+ * **Stream-mode + agent-target only.** When the workflow is run via
581
+ * `.stream(...)`, each item's agent runs in stream mode and this hook decides
582
+ * how its stream surfaces to the writer (`itemIndex` = the item index). Not
583
+ * invoked for sub-workflow bodies (which stream transitively) nor in generate
584
+ * mode.
585
+ */
586
+ handleStream?: (params: {
587
+ result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;
588
+ writer: UIMessageStreamWriter;
589
+ ctx: Readonly<TContext>;
590
+ input: ElementOf<TOutput>;
591
+ itemIndex: number;
592
+ }) => MaybePromise<void>;
593
+ }
554
594
  /**
555
595
  * Brand that makes a *gated* workflow unassignable where gates are forbidden —
556
596
  * `foreach` / `parallel` / `repeat` targets. A nested gate can't suspend one
@@ -640,6 +680,112 @@ interface SchemaWithParse<T = unknown> {
640
680
  parse(data: unknown): T;
641
681
  }
642
682
 
683
+ interface RuntimeState {
684
+ ctx: unknown;
685
+ output: unknown;
686
+ mode: "generate" | "stream";
687
+ writer?: UIMessageStreamWriter;
688
+ suspension?: GateSnapshot;
689
+ warnings?: WorkflowWarning[];
690
+ checkpointFailed?: boolean;
691
+ pendingError?: PendingError;
692
+ runOptions?: RunOptions;
693
+ abortSignal?: AbortSignal;
694
+ stepIndex?: number;
695
+ resumeDescent?: ResumeDescent;
696
+ }
697
+ /**
698
+ * Drives resume re-entry for a gate that suspended inside nested workflows.
699
+ * `remaining` is the list of child start-indices to descend through, one per
700
+ * nesting level, ending with the innermost gate's `resumeFromIndex + 1`. When a
701
+ * `NestedWorkflowStep` consumes the LAST entry it first seeds `state.output`
702
+ * with `seedOutput` (the merged gate response) before running the innermost
703
+ * child from that index.
704
+ */
705
+ type ResumeDescent = {
706
+ readonly remaining: readonly number[];
707
+ readonly seedOutput: unknown;
708
+ };
709
+ type PendingError = {
710
+ error: unknown;
711
+ stepId: string;
712
+ source: "step" | "gate" | "finally" | "catch" | "onCheckpoint";
713
+ };
714
+
715
+ /**
716
+ * Disambiguates observability events for `type: "step"` nodes. Keeps a single
717
+ * `type: "step"` node kind rather than splitting branch/foreach/repeat/
718
+ * parallel/nested into their own run-loop variants.
719
+ */
720
+ type StepCategory = "step" | "nested" | "branch" | "foreach" | "repeat" | "parallel";
721
+ /**
722
+ * Base class for a single workflow step node. The run loop in `workflow.ts`
723
+ * consumes `ReadonlyArray<Step>` directly — every combinator on `Workflow`
724
+ * constructs one of the subclasses in this directory.
725
+ *
726
+ * ## Execution model (the "fat step")
727
+ *
728
+ * The run loop does two things: ask {@link shouldSkip} whether the node runs
729
+ * at all (skipped nodes fire no observability hooks), then call
730
+ * {@link execute}. Everything else is the step's own business — a kind's
731
+ * `execute` runs its work (applying the body-level `when` / `otherwise`
732
+ * decision via {@link applyConditionalSkip}) and captures any thrown error
733
+ * onto `state.pendingError`, exactly the way it writes its result to
734
+ * `state.output`. Errors accumulate on the state; they do not escape.
735
+ *
736
+ * The base {@link execute} is a no-op so kinds with no body of their own need
737
+ * not override it. {@link errorSource} tags which precedence bucket a captured
738
+ * error lands in.
739
+ */
740
+ declare abstract class Step {
741
+ /** Run-loop dispatch discriminant. */
742
+ abstract readonly type: "step" | "gate" | "catch" | "finally";
743
+ /** Identifier, unique per `type`; surfaced in observability and snapshots. */
744
+ abstract readonly id: string;
745
+ /**
746
+ * Observability event subtype for `type: "step"` nodes (agent / transform =
747
+ * `"step"`; nested / branch / foreach / repeat / parallel override).
748
+ * `undefined` on gate / catch / finally nodes, whose `type` IS the event type.
749
+ */
750
+ readonly category?: StepCategory;
751
+ /**
752
+ * The sealed sub-workflow attached to this node, when it has one (`nested`,
753
+ * and workflow-target `foreach` / `repeat`). Consumed by the recursive
754
+ * `stepShapeHash` walk and the resume path-walk in `loadState`.
755
+ */
756
+ readonly nestedWorkflow?: SealedWorkflow<any, any, any, any>;
757
+ /**
758
+ * Precedence source tag a kind writes to `state.pendingError` when it
759
+ * captures a thrown body error. Defaults to `"step"`; kinds with a distinct
760
+ * error-precedence bucket (e.g. `finally`, `catch`, `gate`) override it.
761
+ */
762
+ protected readonly errorSource: PendingError["source"];
763
+ /**
764
+ * The step's body, invoked by the run loop only after {@link shouldSkip}
765
+ * returned `false`. Each kind overrides it to do its work and capture errors
766
+ * onto state. `state.output` is the input on entry and becomes the output on
767
+ * exit; `state.writer` is present in stream mode. The base implementation is
768
+ * a no-op so kinds that carry no body of their own need not override it.
769
+ */
770
+ execute(_state: RuntimeState): Promise<void>;
771
+ /**
772
+ * Run-policy gate, called by the run loop before {@link execute}: return
773
+ * `true` when this step should be skipped silently (no hooks, no output
774
+ * change). The default is the "normal" policy — skip while the flow is
775
+ * suspended or already in error. Overridden by kinds with inverted policies:
776
+ * `catch` runs only when there's an error, `finally` always runs.
777
+ */
778
+ shouldSkip(state: RuntimeState): boolean;
779
+ /**
780
+ * Apply `when` / `otherwise` conditional-skip options. Returns `true` when
781
+ * the body should be skipped — i.e. `when` returned false. On skip,
782
+ * `otherwise` (if present) produces the output; without it the input passes
783
+ * through unchanged. Distinct from {@link shouldSkip}: this is the body-level
784
+ * `when` / `otherwise` decision a kind applies after the policy gate passes.
785
+ */
786
+ protected applyConditionalSkip(state: RuntimeState, options: ConditionalStepOptions<unknown, unknown, unknown> | undefined): Promise<boolean>;
787
+ }
788
+
643
789
  declare class WorkflowBranchError extends Error {
644
790
  readonly branchType: "predicate" | "select";
645
791
  constructor(branchType: "predicate" | "select", message: string);
@@ -668,69 +814,13 @@ declare const ABORT_STEP_ID: "::pipeai::abort";
668
814
  * the same reason as {@link ABORT_STEP_ID}.
669
815
  */
670
816
  declare const GATE_RESUME_STEP_ID: "::pipeai::gate:resume";
817
+
671
818
  /**
672
819
  * Convert a legacy v1 gate snapshot to a v2 gate snapshot. Long-lived
673
820
  * storage (Redis-without-TTL, S3, Postgres) should re-serialize via this
674
821
  * helper before v0.8.0+ drops v1 acceptance.
675
822
  */
676
823
  declare function migrateSnapshot(legacy: LegacyGateSnapshotV1): GateSnapshot;
677
- type StepCategory = "step" | "nested" | "branch" | "foreach" | "repeat" | "parallel";
678
- type StepNode = {
679
- readonly type: "step";
680
- readonly id: string;
681
- readonly execute: (state: RuntimeState) => MaybePromise<void>;
682
- readonly nestedWorkflow?: SealedWorkflow<any, any, any, any>;
683
- /** Disambiguates observability events. Default `"step"`. */
684
- readonly category?: StepCategory;
685
- } | {
686
- readonly type: "catch";
687
- readonly id: string;
688
- readonly execute: (state: RuntimeState) => MaybePromise<void>;
689
- } | {
690
- readonly type: "finally";
691
- readonly id: string;
692
- readonly execute: (state: RuntimeState) => MaybePromise<void>;
693
- } | {
694
- readonly type: "gate";
695
- readonly id: string;
696
- readonly execute: (state: RuntimeState) => MaybePromise<void>;
697
- readonly schema?: SchemaWithParse;
698
- readonly merge?: (params: {
699
- priorOutput: unknown;
700
- response: unknown;
701
- }) => MaybePromise<unknown>;
702
- };
703
- interface RuntimeState {
704
- ctx: unknown;
705
- output: unknown;
706
- mode: "generate" | "stream";
707
- writer?: UIMessageStreamWriter;
708
- suspension?: GateSnapshot;
709
- warnings?: WorkflowWarning[];
710
- checkpointFailed?: boolean;
711
- pendingError?: PendingError;
712
- runOptions?: RunOptions;
713
- abortSignal?: AbortSignal;
714
- stepIndex?: number;
715
- resumeDescent?: ResumeDescent;
716
- }
717
- /**
718
- * Drives resume re-entry for a gate that suspended inside nested workflows.
719
- * `remaining` is the list of child start-indices to descend through, one per
720
- * nesting level, ending with the innermost gate's `resumeFromIndex + 1`. When a
721
- * `NestedWorkflowStep` consumes the LAST entry it first seeds `state.output`
722
- * with `seedOutput` (the merged gate response) before running the innermost
723
- * child from that index.
724
- */
725
- type ResumeDescent = {
726
- readonly remaining: readonly number[];
727
- readonly seedOutput: unknown;
728
- };
729
- type PendingError = {
730
- error: unknown;
731
- stepId: string;
732
- source: "step" | "gate" | "finally" | "catch" | "onCheckpoint";
733
- };
734
824
  /**
735
825
  * Seed for a run: the initial pipeline `output` plus an optional pre-execute
736
826
  * `initialError`. The resume entry points compute these differently (gate
@@ -744,13 +834,12 @@ type StateSeed = {
744
834
  };
745
835
  declare class SealedWorkflow<TContext, TInput = void, TOutput = void, TGates extends Record<string, unknown> = {}> {
746
836
  readonly id?: string;
747
- protected readonly steps: ReadonlyArray<StepNode>;
837
+ protected readonly steps: ReadonlyArray<Step>;
748
838
  protected readonly observability?: WorkflowObservability;
749
839
  private duplicateCheckPassed;
750
- private _cachedExecutableStepCount?;
751
- private _cachedCheckpointableStepCount?;
840
+ private _stepCounts?;
752
841
  private _cachedStepShapeHash?;
753
- protected constructor(steps: ReadonlyArray<StepNode>, id?: string, observability?: WorkflowObservability);
842
+ protected constructor(steps: ReadonlyArray<Step>, id?: string, observability?: WorkflowObservability);
754
843
  /**
755
844
  * Walk the step list once per terminal instance. Rejects:
756
845
  * - Duplicate `(type, id)` pairs.
@@ -759,34 +848,35 @@ declare class SealedWorkflow<TContext, TInput = void, TOutput = void, TGates ext
759
848
  */
760
849
  private ensureDuplicateCheck;
761
850
  /**
762
- * Count of executable nodes i.e. NOT `catch` or `finally`. Drives
763
- * checkpoint auto-cadence so adding cleanup steps doesn't surprise users
764
- * with extra fires. `branch`/`foreach`/`repeat`/`parallel`/`nested` are all
765
- * `type: "step"` internally and count as executable.
851
+ * Two cadence inputs from a single walk:
852
+ * - `executable` nodes that aren't `catch` / `finally`. A graph-size
853
+ * proxy for the catastrophe threshold in {@link validateRunOptions}.
854
+ * - `checkpointable` — `type === "step"` nodes only (this includes
855
+ * branch / foreach / repeat / parallel / nested). Drives the checkpoint
856
+ * auto-cadence denominator: gates suspend/skip and never reach the
857
+ * checkpoint block, so counting them would dilute the "~4 checkpoints
858
+ * across the run" target.
766
859
  */
767
- protected get cachedExecutableStepCount(): number;
768
- /**
769
- * Count of *checkpointable* nodes — `type === "step"` only (this includes
770
- * `branch`/`foreach`/`repeat`/`parallel`/`nested`, all internally `step`).
771
- * Drives the checkpoint auto-cadence denominator. Distinct from
772
- * {@link cachedExecutableStepCount}, which also counts `gate` nodes: gates
773
- * suspend/skip and never reach the checkpoint block, so the runtime
774
- * `executableStepsSeen` counter never advances on them. Counting gates in
775
- * the denominator would dilute the "~4 checkpoints across the run" target.
776
- */
777
- protected get cachedCheckpointableStepCount(): number;
860
+ protected get stepCounts(): {
861
+ executable: number;
862
+ checkpointable: number;
863
+ };
778
864
  /** @internal — used by `computeStepShapeHash` to descend nested workflows. */
779
- getStepsForShapeHash(): ReadonlyArray<StepNode>;
865
+ getStepsForShapeHash(): ReadonlyArray<Step>;
780
866
  protected get cachedStepShapeHash(): string;
781
867
  /**
782
868
  * Validate user-provided RunOptions before a run begins. Throws on
783
869
  * outright errors and on the loud-disaster combo (`freezeSnapshots: true
784
870
  * + checkpointEvery: 1` on a workflow of 8+ steps). Warns once on the
785
- * merely-suspicious combo (`freezeSnapshots: true + cadence <= 2`).
786
- * Plan-of-record: catastrophic combo escape via the
787
- * `"iAcceptThePerformanceCost"` literal.
871
+ * merely-suspicious combo (`freezeSnapshots: true + cadence <= 2`), and on
872
+ * checkpoint-cadence options set without an `onCheckpoint` sink (a no-op
873
+ * that usually signals a forgotten sink).
788
874
  */
789
875
  protected validateRunOptions(opts: RunOptions | undefined): void;
876
+ /** Observability event `type` for a node: a `type: "step"` node reports its
877
+ * `category` (agent / transform default to `"step"`); every other node's
878
+ * `type` IS the event type. */
879
+ private obsEventType;
790
880
  /**
791
881
  * Fire an observability hook safely. Returns `undefined` synchronously when
792
882
  * no hook is registered — avoiding the promise wrapper + microtask that an
@@ -800,9 +890,12 @@ declare class SealedWorkflow<TContext, TInput = void, TOutput = void, TGates ext
800
890
  * Returns the hook's thrown error if any; undefined otherwise. Callers
801
891
  * `await` the result — `await undefined` is sync, so the no-hook path
802
892
  * stays allocation-free.
893
+ *
894
+ * Thin delegate to the free `fireHook` (which takes an explicit
895
+ * observability), kept as a method so the loop's many `this.fireHook` call
896
+ * sites stay unchanged.
803
897
  */
804
898
  protected fireHook<K extends keyof WorkflowObservability, E extends Parameters<NonNullable<WorkflowObservability[K]>>[0]>(state: RuntimeState, name: K, event: E): MaybePromise<unknown>;
805
- protected hasItemHooks(): boolean;
806
899
  /**
807
900
  * Fire `onStepError` for a step-body failure and honor the documented
808
901
  * cause-attachment contract uniformly across every firing path (step, gate,
@@ -822,11 +915,43 @@ declare class SealedWorkflow<TContext, TInput = void, TOutput = void, TGates ext
822
915
  durationMs: number;
823
916
  }): Promise<void>;
824
917
  generate(ctx: TContext, ...args: TInput extends void ? [input?: TInput, opts?: RunOptions] : [input: TInput, opts?: RunOptions]): Promise<WorkflowResult<TOutput>>;
825
- stream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: TContext, ...args: TInput extends void ? [input?: TInput, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions] : [input: TInput, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]): WorkflowStreamResult<TOutput>;
918
+ stream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: TContext, ...args: TInput extends void ? [input?: TInput, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions] : [input: TInput, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]): WorkflowStreamResult<TOutput, UI_MESSAGE>;
826
919
  protected buildResult(state: RuntimeState): WorkflowResult<TOutput>;
827
920
  protected runGenerate(ctx: unknown, startIndex: number, opts: RunOptions | undefined, seed: () => MaybePromise<StateSeed>): Promise<WorkflowResult<TOutput>>;
828
- protected runStream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: unknown, startIndex: number, opts: RunOptions | undefined, options: WorkflowStreamOptions<UI_MESSAGE> | undefined, seed: () => MaybePromise<StateSeed>): WorkflowStreamResult<TOutput>;
921
+ protected runStream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: unknown, startIndex: number, opts: RunOptions | undefined, options: WorkflowStreamOptions<UI_MESSAGE> | undefined, seed: () => MaybePromise<StateSeed>): WorkflowStreamResult<TOutput, UI_MESSAGE>;
829
922
  protected execute(state: RuntimeState, startIndex?: number, opts?: RunOptions, initialError?: PendingError | null): Promise<void>;
923
+ /**
924
+ * Promote a fired abort signal into `state.pendingError` at an iteration
925
+ * boundary. First observation discards any in-progress suspension (the caller
926
+ * asked to stop) and preserves a genuinely-different prior step error as a
927
+ * warning — but NOT one that is itself the abort reason (a nested workflow /
928
+ * concurrent unit that already rethrew it), which would surface a phantom
929
+ * step-failure warning. Subsequent iterations only re-promote if a downstream
930
+ * catch cleared pendingError — `AbortSignal.aborted` is sticky, so the
931
+ * workflow must not resume mid-pipeline just because a catch swallowed one
932
+ * observation.
933
+ */
934
+ private promoteAbort;
935
+ /**
936
+ * Emit a checkpoint after a successful `type:"step"` body. Skipped on
937
+ * pendingError (no clean state to snapshot), on suspension (gate already
938
+ * won), and for catch/finally/gate nodes (not checkpointable). Numeric
939
+ * `checkpointEvery` (default: `max(1, ceil(count/4))`) uses the loop-hoisted
940
+ * `ckptCadence`; the predicate form runs per step. A `when:false`-skipped
941
+ * `type:"step"` node returns normally (its body never ran) and still reaches
942
+ * here — it advances the counter and can itself be a checkpoint boundary,
943
+ * keeping the cadence denominator (`stepCounts.checkpointable`) consistent
944
+ * with the runtime counter.
945
+ */
946
+ private maybeCheckpoint;
947
+ /**
948
+ * Terminal reconciliation after the loop. Re-promotes a swallowed abort
949
+ * (recoverability must not depend on catch position), then resolves the
950
+ * mutually-exclusive precedence tail: checkpointFailed > original-step error
951
+ * > suspension. (A throwing catch/finally never reaches here — it bubbles
952
+ * straight out of the loop, so there is no finally-aggregation branch.)
953
+ */
954
+ private settleRun;
830
955
  /**
831
956
  * Run THIS sealed workflow as a nested step on the caller's run `state`.
832
957
  * Public (internal; not re-exported from index) so `Step` subclasses —
@@ -870,7 +995,7 @@ declare class SealedWorkflow<TContext, TInput = void, TOutput = void, TGates ext
870
995
  private findGateIndex;
871
996
  }
872
997
  interface ResumedWorkflowConfig {
873
- readonly mode: "gate" | "checkpoint";
998
+ readonly mode: "gate";
874
999
  readonly schema?: SchemaWithParse<unknown>;
875
1000
  readonly mergeFn?: (params: {
876
1001
  priorOutput: unknown;
@@ -894,7 +1019,7 @@ declare class ResumedWorkflow<TContext, TResponse = unknown, TOutput = void> ext
894
1019
  private readonly priorOutput;
895
1020
  private readonly nestedRemaining?;
896
1021
  /** @internal */
897
- constructor(steps: ReadonlyArray<StepNode>, startIndex: number, config: ResumedWorkflowConfig);
1022
+ constructor(steps: ReadonlyArray<Step>, startIndex: number, config: ResumedWorkflowConfig);
898
1023
  private validateResponse;
899
1024
  /**
900
1025
  * Seed the run by validating the gate response and merging it with the
@@ -905,23 +1030,27 @@ declare class ResumedWorkflow<TContext, TResponse = unknown, TOutput = void> ext
905
1030
  */
906
1031
  private seedFromResponse;
907
1032
  generate(ctx: TContext, ...args: TResponse extends void ? [response?: TResponse, opts?: RunOptions] : [response: TResponse, opts?: RunOptions]): Promise<WorkflowResult<TOutput>>;
908
- stream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: TContext, ...args: TResponse extends void ? [response?: TResponse, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions] : [response: TResponse, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]): WorkflowStreamResult<TOutput>;
1033
+ stream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: TContext, ...args: TResponse extends void ? [response?: TResponse, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions] : [response: TResponse, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]): WorkflowStreamResult<TOutput, UI_MESSAGE>;
909
1034
  }
910
1035
  declare class CheckpointResumedWorkflow<TContext, TOutput = void> extends SealedWorkflow<TContext, void, TOutput> {
911
1036
  private readonly startIndex;
912
1037
  private readonly priorOutput;
913
1038
  /** @internal */
914
- constructor(steps: ReadonlyArray<StepNode>, startIndex: number, config: ResumedWorkflowConfig);
1039
+ constructor(steps: ReadonlyArray<Step>, startIndex: number, config: {
1040
+ priorOutput?: unknown;
1041
+ observability?: WorkflowObservability;
1042
+ });
915
1043
  generate(ctx: TContext, ...args: [input?: void, opts?: RunOptions]): Promise<WorkflowResult<TOutput>>;
916
- stream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: TContext, ...args: [input?: void, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]): WorkflowStreamResult<TOutput>;
1044
+ stream<UI_MESSAGE extends UIMessage = UIMessage>(ctx: TContext, ...args: [input?: void, options?: WorkflowStreamOptions<UI_MESSAGE>, opts?: RunOptions]): WorkflowStreamResult<TOutput, UI_MESSAGE>;
917
1045
  }
918
1046
  declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends Record<string, unknown> = {}> extends SealedWorkflow<TContext, TInput, TOutput, TGates> {
919
1047
  /**
920
- * Sentinel value for `foreach`'s `onError` handler. Returning `Workflow.SKIP`
921
- * from `onError` omits the failed item's index from the output array,
922
- * shortening it relative to the input array.
1048
+ * Sentinel value for `foreach`/`parallel`'s `onError` handler. Returning
1049
+ * `Workflow.SKIP` omits the failed item (foreach: shortens the output array;
1050
+ * parallel: leaves the slot `undefined`). Aliases the leaf-module `SKIP` so
1051
+ * the step subclasses can compare against it without importing this class.
923
1052
  */
924
- static readonly SKIP: unique symbol;
1053
+ static readonly SKIP: symbol;
925
1054
  private constructor();
926
1055
  static create<TContext, TInput = void>(options?: {
927
1056
  id?: string;
@@ -944,7 +1073,7 @@ declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends R
944
1073
  input: TOutput;
945
1074
  writer?: UIMessageStreamWriter;
946
1075
  }) => MaybePromise<TNextOutput>, options?: InlineStepOptions<TContext, TOutput, TNextOutput>): Workflow<TContext, TInput, TNextOutput, TGates>;
947
- gate<TResponse = TOutput, Id extends string = string>(id: Id & (Id extends keyof TGates ? never : Id), options?: {
1076
+ gate<TResponse = TOutput, TMerged = TResponse, Id extends string = string>(id: Id & (Id extends keyof TGates ? never : Id), options?: {
948
1077
  payload?: (params: {
949
1078
  ctx: Readonly<TContext>;
950
1079
  input: TOutput;
@@ -957,16 +1086,14 @@ declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends R
957
1086
  merge?: (params: {
958
1087
  priorOutput: TOutput;
959
1088
  response: TResponse;
960
- }) => MaybePromise<TResponse>;
961
- }): Workflow<TContext, TInput, TResponse, TGates & Record<Id, TResponse>>;
1089
+ }) => MaybePromise<TMerged>;
1090
+ }): Workflow<TContext, TInput, TMerged, TGates & Record<Id, TResponse>>;
962
1091
  branch<TNextOutput>(cases: BranchCase<TContext, TOutput, TNextOutput>[], options?: {
963
1092
  id?: string;
964
1093
  }): Workflow<TContext, TInput, TNextOutput, TGates>;
965
1094
  branch<TKeys extends string, TNextOutput>(config: BranchSelect<TContext, TOutput, TKeys, TNextOutput>, options?: {
966
1095
  id?: string;
967
1096
  }): Workflow<TContext, TInput, TNextOutput, TGates>;
968
- private branchPredicate;
969
- private branchSelect;
970
1097
  /**
971
1098
  * Map each item of an array through an agent or sub-workflow.
972
1099
  *
@@ -990,32 +1117,8 @@ declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends R
990
1117
  * failures at indices AFTER the throwing one are neither recovered nor
991
1118
  * surfaced as warnings.
992
1119
  */
993
- foreach<TNextOutput, TG extends Record<string, unknown> = {}>(target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | (SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput, TG> & NoGates<TG>), options?: {
994
- id?: string;
995
- concurrency?: number;
996
- onError?: (params: {
997
- error: unknown;
998
- item: ElementOf<TOutput>;
999
- index: number;
1000
- ctx: Readonly<TContext>;
1001
- }) => MaybePromise<TNextOutput | typeof Workflow.SKIP>;
1002
- /**
1003
- * **Stream-mode + agent-target only.** When the workflow is run via
1004
- * `.stream(...)`, each item's agent runs in stream mode and this hook
1005
- * decides how its stream surfaces to the writer (`itemIndex` = the item
1006
- * index). Without it, agent items run in generate mode (no auto-merge —
1007
- * unlike a single `.step(agent)`, foreach never auto-merges N streams).
1008
- * Not invoked for `SealedWorkflow` targets (which stream transitively via
1009
- * their own steps) nor in generate mode.
1010
- */
1011
- handleStream?: (params: {
1012
- result: StreamTextResult<ToolSet, OutputType<TNextOutput>>;
1013
- writer: UIMessageStreamWriter;
1014
- ctx: Readonly<TContext>;
1015
- input: ElementOf<TOutput>;
1016
- itemIndex: number;
1017
- }) => MaybePromise<void>;
1018
- }): Workflow<TContext, TInput, TNextOutput[], TGates>;
1120
+ foreach<TNextOutput, TG extends Record<string, unknown> = {}>(target: Agent<TContext, ElementOf<TOutput>, TNextOutput> | (SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput, TG> & NoGates<TG>), options?: ForeachOptions<TContext, TOutput, TNextOutput>): Workflow<TContext, TInput, TNextOutput[], TGates>;
1121
+ foreach<TNextOutput, TG extends Record<string, unknown> = {}>(build: (path: Workflow<TContext, ElementOf<TOutput>, ElementOf<TOutput>>) => (SealedWorkflow<TContext, ElementOf<TOutput>, TNextOutput, TG> & NoGates<TG>), options?: ForeachOptions<TContext, TOutput, TNextOutput>): Workflow<TContext, TInput, TNextOutput[], TGates>;
1019
1122
  /** Record-form + `onError`. Values are `BranchOutput | undefined` (SKIP-able). */
1020
1123
  parallel<TBranches extends Record<string, ParallelTarget<TContext, TOutput>>>(branches: TBranches & {
1021
1124
  [K in keyof TBranches]: GatelessBranch<TBranches[K]>;
@@ -1049,4 +1152,4 @@ declare class Workflow<TContext, TInput = void, TOutput = void, TGates extends R
1049
1152
 
1050
1153
  declare const SKIP: symbol;
1051
1154
 
1052
- export { ABORT_STEP_ID, Agent, type AgentConfig, type AgentResultParams, type AgentStepHooks, type AsToolMapOutput, type BranchCase, type BranchSelect, CHECKPOINT_STEP_ID, CheckpointResumedWorkflow, type CheckpointSnapshot, GATE_RESUME_STEP_ID, type GateSnapshot, type GenerateTextResult, type IToolProvider, type LegacyGateSnapshotV1, type MaybePromise, type OutputType, type ParallelOptions, type ParallelOutputRecord, type ParallelOutputTuple, type ParallelTarget, type RepeatOptions, type Resolvable, ResumedWorkflow, type RunOptions, SKIP, SealedWorkflow, type StepOptions, type StreamTextResult, TOOL_PROVIDER_BRAND, type ToolExecuteOptions, ToolProvider, type ToolProviderConfig, Workflow, WorkflowBranchError, WorkflowLoopError, type WorkflowObservability, type WorkflowResult, type WorkflowSnapshot, type WorkflowStepType, type WorkflowStreamOptions, type WorkflowStreamResult, type WorkflowWarning, defineTool, isToolProvider, migrateSnapshot };
1155
+ export { ABORT_STEP_ID, Agent, type AgentConfig, type AgentResultParams, type AgentStepHooks, type AsToolMapOutput, type BranchCase, type BranchSelect, CHECKPOINT_STEP_ID, CheckpointResumedWorkflow, type CheckpointSnapshot, type ForeachOptions, GATE_RESUME_STEP_ID, type GateSnapshot, type GenerateTextResult, type IToolProvider, type LegacyGateSnapshotV1, type MaybePromise, type OutputType, type ParallelOptions, type ParallelOutputRecord, type ParallelOutputTuple, type ParallelTarget, type RepeatOptions, type Resolvable, ResumedWorkflow, type RunOptions, SKIP, SealedWorkflow, type StepOptions, type StreamTextResult, TOOL_PROVIDER_BRAND, type ToolExecuteOptions, ToolProvider, type ToolProviderConfig, Workflow, WorkflowBranchError, WorkflowLoopError, type WorkflowObservability, type WorkflowResult, type WorkflowSnapshot, type WorkflowStepType, type WorkflowStreamOptions, type WorkflowStreamResult, type WorkflowWarning, defineTool, isToolProvider, migrateSnapshot };