@effect-uai/core 0.8.0 → 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.
Files changed (132) hide show
  1. package/dist/{AiError-CAX_48RU.d.mts → AiError-CrdR1EQi.d.mts} +2 -2
  2. package/dist/{AiError-CAX_48RU.d.mts.map → AiError-CrdR1EQi.d.mts.map} +1 -1
  3. package/dist/{Audio-DPlTsNdz.d.mts → Audio-DDSKCkSe.d.mts} +2 -2
  4. package/dist/{Audio-DPlTsNdz.d.mts.map → Audio-DDSKCkSe.d.mts.map} +1 -1
  5. package/dist/{Image-HNmMpMTh.d.mts → Image-C_Zjpwhc.d.mts} +2 -2
  6. package/dist/{Image-HNmMpMTh.d.mts.map → Image-C_Zjpwhc.d.mts.map} +1 -1
  7. package/dist/{Items-7ljaVxH_.d.mts → Items-CgKD6Npw.d.mts} +13 -13
  8. package/dist/{Items-7ljaVxH_.d.mts.map → Items-CgKD6Npw.d.mts.map} +1 -1
  9. package/dist/Loop-B5_cqumi.d.mts +173 -0
  10. package/dist/Loop-B5_cqumi.d.mts.map +1 -0
  11. package/dist/{Media-D_CpcM1Z.d.mts → Media-DOLyaygI.d.mts} +1 -1
  12. package/dist/{Media-D_CpcM1Z.d.mts.map → Media-DOLyaygI.d.mts.map} +1 -1
  13. package/dist/{SandboxError-BvKypkJm.d.mts → SandboxError-CIrVDOMV.d.mts} +2 -2
  14. package/dist/{SandboxError-BvKypkJm.d.mts.map → SandboxError-CIrVDOMV.d.mts.map} +1 -1
  15. package/dist/{StructuredFormat-BbN4dosH.d.mts → StructuredFormat-CMJFD3sn.d.mts} +2 -2
  16. package/dist/{StructuredFormat-BbN4dosH.d.mts.map → StructuredFormat-CMJFD3sn.d.mts.map} +1 -1
  17. package/dist/Tool-0XUIT2A2.d.mts +232 -0
  18. package/dist/Tool-0XUIT2A2.d.mts.map +1 -0
  19. package/dist/ToolEvent-DYrAUJGs.d.mts +151 -0
  20. package/dist/ToolEvent-DYrAUJGs.d.mts.map +1 -0
  21. package/dist/ToolResult-BZd-cEWW.d.mts +151 -0
  22. package/dist/ToolResult-BZd-cEWW.d.mts.map +1 -0
  23. package/dist/Toolkit-BKC8b8Xo.d.mts +155 -0
  24. package/dist/Toolkit-BKC8b8Xo.d.mts.map +1 -0
  25. package/dist/{dist-DV5ISja1.mjs → dist-B04dlFHg.mjs} +3 -3
  26. package/dist/{dist-DV5ISja1.mjs.map → dist-B04dlFHg.mjs.map} +1 -1
  27. package/dist/dist-DWgRbDN3.mjs +140 -0
  28. package/dist/dist-DWgRbDN3.mjs.map +1 -0
  29. package/dist/domain/AiError.d.mts +1 -1
  30. package/dist/domain/Audio.d.mts +1 -1
  31. package/dist/domain/Image.d.mts +1 -1
  32. package/dist/domain/Items.d.mts +1 -1
  33. package/dist/domain/Media.d.mts +1 -1
  34. package/dist/domain/Music.d.mts +1 -1
  35. package/dist/domain/Turn.d.mts +4 -4
  36. package/dist/domain/Turn.test.mjs +1 -1
  37. package/dist/embedding-model/Embedding.d.mts +1 -1
  38. package/dist/embedding-model/EmbeddingModel.d.mts +1 -1
  39. package/dist/embedding-model/EmbeddingModel.test.mjs +1 -1
  40. package/dist/embedding-model/EmbeddingModel.test.mjs.map +1 -1
  41. package/dist/index.d.mts +14 -13
  42. package/dist/index.mjs +2 -1
  43. package/dist/language-model/LanguageModel.d.mts +10 -5
  44. package/dist/language-model/LanguageModel.d.mts.map +1 -1
  45. package/dist/language-model/LanguageModel.mjs.map +1 -1
  46. package/dist/language-model/LanguageModel.test.mjs +1 -1
  47. package/dist/loop/Loop.d.mts +2 -141
  48. package/dist/loop/Loop.mjs +16 -20
  49. package/dist/loop/Loop.mjs.map +1 -1
  50. package/dist/loop/Loop.test.mjs +18 -1
  51. package/dist/loop/Loop.test.mjs.map +1 -1
  52. package/dist/{magic-string.es-BgIV5Mu3.mjs → magic-string.es-Dk-MMA0F.mjs} +1 -1
  53. package/dist/{magic-string.es-BgIV5Mu3.mjs.map → magic-string.es-Dk-MMA0F.mjs.map} +1 -1
  54. package/dist/music-generator/MusicGenerator.d.mts +2 -2
  55. package/dist/music-generator/MusicGenerator.test.mjs +1 -1
  56. package/dist/observability/Metrics.d.mts +116 -28
  57. package/dist/observability/Metrics.d.mts.map +1 -1
  58. package/dist/observability/Metrics.mjs +250 -38
  59. package/dist/observability/Metrics.mjs.map +1 -1
  60. package/dist/observability/Metrics.test.d.mts +1 -0
  61. package/dist/observability/Metrics.test.mjs +187 -0
  62. package/dist/observability/Metrics.test.mjs.map +1 -0
  63. package/dist/observability/Telemetry.d.mts +37 -0
  64. package/dist/observability/Telemetry.d.mts.map +1 -0
  65. package/dist/observability/Telemetry.mjs +57 -0
  66. package/dist/observability/Telemetry.mjs.map +1 -0
  67. package/dist/observability/Telemetry.test.d.mts +1 -0
  68. package/dist/observability/Telemetry.test.mjs +92 -0
  69. package/dist/observability/Telemetry.test.mjs.map +1 -0
  70. package/dist/retry/Retry.d.mts +2 -2
  71. package/dist/retry/Retry.test.mjs +1 -1
  72. package/dist/sandbox/Sandbox.d.mts +1 -1
  73. package/dist/sandbox/SandboxError.d.mts +1 -1
  74. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +2 -2
  75. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs +1 -1
  76. package/dist/streaming/JSONL.d.mts +1 -1
  77. package/dist/streaming/JSONL.test.mjs +1 -1
  78. package/dist/streaming/SSE.test.mjs +1 -1
  79. package/dist/structured-format/StructuredFormat.d.mts +1 -1
  80. package/dist/structured-format/StructuredFormat.mjs.map +1 -1
  81. package/dist/structured-format/StructuredFormat.test.mjs +1 -1
  82. package/dist/testing/MockMusicGenerator.d.mts +1 -1
  83. package/dist/testing/MockProvider.d.mts +1 -1
  84. package/dist/testing/MockSpeechSynthesizer.d.mts +1 -1
  85. package/dist/tool/Approval.d.mts +3 -3
  86. package/dist/tool/Approval.test.mjs +35 -34
  87. package/dist/tool/Approval.test.mjs.map +1 -1
  88. package/dist/tool/HistoryCheck.d.mts +2 -2
  89. package/dist/tool/Tool.d.mts +2 -2
  90. package/dist/tool/Tool.mjs +112 -22
  91. package/dist/tool/Tool.mjs.map +1 -1
  92. package/dist/tool/Tool.test.mjs +41 -3
  93. package/dist/tool/Tool.test.mjs.map +1 -1
  94. package/dist/tool/ToolEvent.d.mts +2 -151
  95. package/dist/tool/ToolResult.d.mts +2 -138
  96. package/dist/tool/ToolResult.mjs +18 -3
  97. package/dist/tool/ToolResult.mjs.map +1 -1
  98. package/dist/tool/Toolkit.d.mts +2 -73
  99. package/dist/tool/Toolkit.mjs +106 -28
  100. package/dist/tool/Toolkit.mjs.map +1 -1
  101. package/dist/tool/Toolkit.test.mjs +113 -7
  102. package/dist/tool/Toolkit.test.mjs.map +1 -1
  103. package/dist/transcriber/Transcriber.d.mts +2 -2
  104. package/dist/transcriber/Transcriber.test.mjs +1 -1
  105. package/dist/web-search/WebSearch.d.mts +1 -1
  106. package/dist/web-search/WebSearchTool.d.mts +2 -2
  107. package/dist/web-search/WebSearchTool.d.mts.map +1 -1
  108. package/dist/web-search/WebSearchTool.mjs.map +1 -1
  109. package/package.json +1 -1
  110. package/src/embedding-model/EmbeddingModel.test.ts +4 -0
  111. package/src/index.ts +1 -0
  112. package/src/language-model/LanguageModel.ts +7 -2
  113. package/src/loop/Loop.test.ts +22 -0
  114. package/src/loop/Loop.ts +27 -4
  115. package/src/observability/Metrics.test.ts +266 -0
  116. package/src/observability/Metrics.ts +505 -65
  117. package/src/observability/Telemetry.test.ts +123 -0
  118. package/src/observability/Telemetry.ts +96 -0
  119. package/src/structured-format/StructuredFormat.ts +4 -0
  120. package/src/tool/Approval.test.ts +22 -21
  121. package/src/tool/Tool.test.ts +55 -2
  122. package/src/tool/Tool.ts +221 -55
  123. package/src/tool/ToolResult.ts +22 -1
  124. package/src/tool/Toolkit.test.ts +168 -7
  125. package/src/tool/Toolkit.ts +336 -99
  126. package/src/web-search/WebSearchTool.ts +1 -1
  127. package/dist/Tool-BKiieFXk.d.mts +0 -102
  128. package/dist/Tool-BKiieFXk.d.mts.map +0 -1
  129. package/dist/loop/Loop.d.mts.map +0 -1
  130. package/dist/tool/ToolEvent.d.mts.map +0 -1
  131. package/dist/tool/ToolResult.d.mts.map +0 -1
  132. package/dist/tool/Toolkit.d.mts.map +0 -1
@@ -24,6 +24,10 @@ import { Array, Cause, Channel, Data, Effect, Exit, Function, Match, Option, Ref
24
24
  * your values before them (`values.pipe(Stream.concat(Loop.next(state)))`).
25
25
  */
26
26
  var Loop_exports = /* @__PURE__ */ __exportAll({
27
+ Next: () => Next,
28
+ Stop: () => Stop,
29
+ StopWith: () => StopWith,
30
+ Value: () => Value,
27
31
  loop: () => loop,
28
32
  loopOver: () => loopOver,
29
33
  loopWithState: () => loopWithState,
@@ -33,6 +37,15 @@ var Loop_exports = /* @__PURE__ */ __exportAll({
33
37
  value: () => value
34
38
  });
35
39
  const Step = Data.taggedEnum();
40
+ /**
41
+ * Bare step constructors, so a loop body can emit `Value(...)`, `Next(...)`,
42
+ * `Stop()`, `StopWith(...)` directly inside a `Stream.make(...)` without the
43
+ * `Step.` prefix. (The `Step` object itself can't be exported under that name
44
+ * because it collides with the exported `Step` type.) For the common cases
45
+ * prefer the `value` / `next` / `stop` helpers, which also handle the
46
+ * single-element-stream wrapping for `next` / `stop`.
47
+ */
48
+ const { Value, Next, Stop, StopWith } = Step;
36
49
  /** Wrap a value so it flows through the loop to downstream consumers. */
37
50
  const value = (a) => Step.Value({ value: a });
38
51
  /**
@@ -49,31 +62,14 @@ const next = (state) => Stream.succeed(Step.Next({ state }));
49
62
  * return it directly from a loop body.
50
63
  */
51
64
  const stop = (state) => Stream.succeed(state === void 0 ? Step.Stop() : Step.StopWith({ state }));
52
- /**
53
- * Lift a provider's `Stream<TurnEvent>` into a loop body's `Stream<Step<TurnEvent | A, S>>`.
54
- * Each delta passes through as `value(delta)` (including the terminal
55
- * `TurnComplete`, so the consumer sees turn boundaries naturally). Once
56
- * the terminal arrives, `then(turn)` runs and its returned stream of loop
57
- * steps (typically tool outputs followed by `next(state)` or `stop()`) is
58
- * concatenated.
59
- *
60
- * Pre-pipe transforms (`Stream.tap` / `Stream.map` / `Stream.filter`) on
61
- * the raw delta stream cover anything an `emit`-style callback would do.
62
- *
63
- * If the upstream ends without a `TurnComplete`, the resulting stream
64
- * fails with `AiError.IncompleteTurn`. Catch it via `Stream.catchTag` if
65
- * you want to recover.
66
- *
67
- * Dual: data-first `onTurnComplete(deltas, then)` and data-last
68
- * `deltas.pipe(onTurnComplete(then))` both work.
69
- */
70
65
  const onTurnComplete = Function.dual(2, (deltas, then) => Stream.unwrap(Effect.gen(function* () {
71
66
  const turnRef = yield* Ref.make(Option.none());
72
67
  const events = deltas.pipe(Stream.tap((delta) => isTurnComplete(delta) ? Ref.set(turnRef, Option.some(delta.turn)) : Effect.void), Stream.map(value));
73
68
  const continuation = Stream.unwrap(Effect.gen(function* () {
74
69
  const opt = yield* Ref.get(turnRef);
75
70
  if (Option.isNone(opt)) return yield* new IncompleteTurn({});
76
- return yield* then(opt.value);
71
+ const result = then(opt.value);
72
+ return Effect.isEffect(result) ? yield* result : result;
77
73
  }));
78
74
  return Stream.concat(events, continuation);
79
75
  })));
@@ -212,6 +208,6 @@ const loopWithState = (initial, body) => Effect.gen(function* () {
212
208
  };
213
209
  });
214
210
  //#endregion
215
- export { loop, loopOver, loopWithState, next, onTurnComplete, stop, Loop_exports as t, value };
211
+ export { Next, Stop, StopWith, Value, loop, loopOver, loopWithState, next, onTurnComplete, stop, Loop_exports as t, value };
216
212
 
217
213
  //# sourceMappingURL=Loop.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Loop.mjs","names":["Arr"],"sources":["../../src/loop/Loop.ts"],"sourcesContent":["/**\n * Pull-based `loop` for state-threaded sub-streams.\n *\n * Each iteration runs a body that returns a `Stream<Step<A, S>>`. The body\n * emits values via `Loop.value(a)` and signals iteration control via\n * `Loop.next(state)` (continue with new state) or `Loop.stop()` (terminate).\n * The loop unwraps `Value` steps back to `A` for downstream consumers, so\n * the resulting stream is a plain `Stream<A>`.\n *\n * The next body stream is only pulled when downstream pulls the outer\n * stream - no producer fiber, no queue buffering. Cancellation, failures,\n * scoped resources, and backpressure stay aligned with normal Stream\n * semantics.\n *\n * Convention: a `Next` or `Stop` step is the terminal element of a body's\n * iteration. Values emitted in the same chunk after one are discarded\n * (their producing side effects may already have run). The `Loop.next` /\n * `Loop.stop` helpers each emit a single terminal step, so concatenate\n * your values before them (`values.pipe(Stream.concat(Loop.next(state)))`).\n */\nimport {\n Array as Arr,\n Cause,\n Channel,\n Data,\n Effect,\n Exit,\n Function,\n Match,\n Option,\n Ref,\n Scope,\n Stream,\n SubscriptionRef,\n} from \"effect\"\nimport { IncompleteTurn } from \"../domain/AiError.js\"\nimport { isTurnComplete, type Turn, type TurnEvent } from \"../domain/Turn.js\"\n\n// ---------------------------------------------------------------------------\n// Step type - the body's emit shape\n// ---------------------------------------------------------------------------\n\n/**\n * The tagged union a body emits per pull. `Value` carries a payload that\n * flows downstream. `Next` ends the current iteration and continues with a\n * new state. `Stop` ends the loop entirely with no carried state.\n * `StopWith` also ends the loop but carries a final state that `loopOver`\n * will thread to the next input and `loopWithState` will write to its\n * `SubscriptionRef` before the loop ends. Plain `loop` has no next\n * iteration to apply it to and treats `StopWith` like `Stop`.\n *\n * `Stop` is intentionally `{}` so the bare `stop()` helper doesn't\n * constrain `S` from a body's stream type — every body has a `Stop`\n * variant in its union, and forcing `S` to flow through it would break\n * inference whenever the body never uses `next` / `stop(state)`.\n */\nexport type Step<A, S> = Data.TaggedEnum<{\n Value: { readonly value: A }\n Next: { readonly state: S }\n Stop: {}\n StopWith: { readonly state: S }\n}>\n\ninterface StepDef extends Data.TaggedEnum.WithGenerics<2> {\n readonly taggedEnum: Step<this[\"A\"], this[\"B\"]>\n}\n\nconst Step = Data.taggedEnum<StepDef>()\n\n/** Wrap a value so it flows through the loop to downstream consumers. */\nexport const value = <A>(a: A): Step<A, never> => Step.Value({ value: a })\n\n/**\n * End the current iteration and continue with a new state. Emits a single\n * terminal `Next` step as a one-element stream, so it slots directly into a\n * loop body or after a run of values: `values.pipe(Stream.concat(next(s)))`.\n */\nexport const next = <S>(state: S): Stream.Stream<Step<never, S>> =>\n Stream.succeed(Step.Next({ state }))\n\n/**\n * End the loop. Called with no argument it emits a bare `Stop`; called with\n * a state it emits `StopWith(state)` — `loopOver` threads that final state\n * to the next input and `loopWithState` writes it to its `SubscriptionRef`\n * before the loop ends. Either way it returns a single-element stream, so\n * return it directly from a loop body.\n */\nexport const stop = <S = never>(state?: S): Stream.Stream<Step<never, S>> =>\n Stream.succeed<Step<never, S>>(state === undefined ? Step.Stop() : Step.StopWith({ state }))\n\n// ---------------------------------------------------------------------------\n// onTurnComplete - turn-aware stream operator for loop bodies\n// ---------------------------------------------------------------------------\n\n/**\n * Lift a provider's `Stream<TurnEvent>` into a loop body's `Stream<Step<TurnEvent | A, S>>`.\n * Each delta passes through as `value(delta)` (including the terminal\n * `TurnComplete`, so the consumer sees turn boundaries naturally). Once\n * the terminal arrives, `then(turn)` runs and its returned stream of loop\n * steps (typically tool outputs followed by `next(state)` or `stop()`) is\n * concatenated.\n *\n * Pre-pipe transforms (`Stream.tap` / `Stream.map` / `Stream.filter`) on\n * the raw delta stream cover anything an `emit`-style callback would do.\n *\n * If the upstream ends without a `TurnComplete`, the resulting stream\n * fails with `AiError.IncompleteTurn`. Catch it via `Stream.catchTag` if\n * you want to recover.\n *\n * Dual: data-first `onTurnComplete(deltas, then)` and data-last\n * `deltas.pipe(onTurnComplete(then))` both work.\n */\nexport const onTurnComplete: {\n <S, A, E2 = never, R2 = never>(\n then: (turn: Turn) => Effect.Effect<Stream.Stream<Step<A, S>, E2, R2>, E2, R2>,\n ): <E, R>(\n deltas: Stream.Stream<TurnEvent, E, R>,\n ) => Stream.Stream<Step<TurnEvent | A, S>, E | E2 | IncompleteTurn, R | R2>\n <S, A, E, R, E2 = never, R2 = never>(\n deltas: Stream.Stream<TurnEvent, E, R>,\n then: (turn: Turn) => Effect.Effect<Stream.Stream<Step<A, S>, E2, R2>, E2, R2>,\n ): Stream.Stream<Step<TurnEvent | A, S>, E | E2 | IncompleteTurn, R | R2>\n} = Function.dual(\n 2,\n <S, A, E, R, E2, R2>(\n deltas: Stream.Stream<TurnEvent, E, R>,\n then: (turn: Turn) => Effect.Effect<Stream.Stream<Step<A, S>, E2, R2>, E2, R2>,\n ): Stream.Stream<Step<TurnEvent | A, S>, E | E2 | IncompleteTurn, R | R2> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const turnRef = yield* Ref.make<Option.Option<Turn>>(Option.none())\n\n const events: Stream.Stream<Step<TurnEvent, S>, E, R> = deltas.pipe(\n Stream.tap((delta) =>\n isTurnComplete(delta) ? Ref.set(turnRef, Option.some(delta.turn)) : Effect.void,\n ),\n Stream.map(value),\n )\n\n const continuation = Stream.unwrap(\n Effect.gen(function* () {\n const opt = yield* Ref.get(turnRef)\n if (Option.isNone(opt)) return yield* new IncompleteTurn({})\n return yield* then(opt.value)\n }),\n )\n\n return Stream.concat(events, continuation)\n }),\n ),\n)\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst isNonEmpty = <A>(array: ReadonlyArray<A>): array is readonly [A, ...Array<A>] =>\n array.length > 0\n\ntype CurrentBody<S, A, E, R> = {\n readonly scope: Scope.Closeable\n readonly pull: Effect.Effect<ReadonlyArray<Step<A, S>>, E | Cause.Done<void>, R>\n}\n\nconst closeBody = <S, A, E, R>(\n current: CurrentBody<S, A, E, R>,\n exit: Exit.Exit<unknown, unknown>,\n) => Scope.close(current.scope, exit)\n\n/**\n * Walk a chunk of `Step<A, S>` until a terminal `Next` or `Stop` is found.\n * Returns the unwrapped values seen so far and (optionally) the terminal\n * step. Anything in the chunk after the terminal is discarded - its\n * producing side effects may have run, but downstream never sees it.\n */\nconst partitionChunk = <A, S>(\n chunk: ReadonlyArray<Step<A, S>>,\n): {\n readonly values: ReadonlyArray<A>\n readonly decision: Option.Option<Step<A, S>>\n} => {\n const [valueSteps, rest] = Arr.span(\n chunk,\n (e): e is Step<A, S> & { _tag: \"Value\" } => e._tag === \"Value\",\n )\n return {\n values: valueSteps.map((e) => e.value),\n decision: Arr.head(rest),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\ntype LoopBody<S, A, E, R> = (\n state: S,\n) => Stream.Stream<Step<A, S>, E, R> | Effect.Effect<Stream.Stream<Step<A, S>, E, R>, E, R>\n\n/**\n * Drive a state-threaded loop body. Each iteration runs `body(state)` to get\n * a `Stream<Step<A, S>>`; values flow downstream, `next(s)` continues with\n * a new state, `stop()` ends the loop. See the file header for the full\n * pull-based execution model.\n *\n * Dual: data-first `loop(initial, body)` and data-last `loop(body)(initial)`\n * (or `pipe(initial, loop(body))`) both work.\n */\nexport const loop: {\n <S, A, E, R>(body: LoopBody<S, A, E, R>): (initial: S) => Stream.Stream<A, E, R>\n <S, A, E, R>(initial: S, body: LoopBody<S, A, E, R>): Stream.Stream<A, E, R>\n} = Function.dual(\n 2,\n <S, A, E, R>(initial: S, body: LoopBody<S, A, E, R>): Stream.Stream<A, E, R> =>\n Stream.scoped(\n Stream.fromPull(\n Effect.gen(function* () {\n const outerScope = yield* Effect.scope\n let state = initial\n let current: CurrentBody<S, A, E, R> | undefined\n let done = false\n\n const closeActive = (\n active: CurrentBody<S, A, E, R>,\n exit: Exit.Exit<unknown, unknown>,\n ) => {\n const isActive = current === active\n if (isActive) current = undefined\n // Scope.close is idempotent. Multiple paths can race to close the\n // active body during cancellation/failure, so closing twice is safe.\n return closeBody(active, exit)\n }\n\n yield* Scope.addFinalizerExit(outerScope, (exit) =>\n current === undefined ? Effect.void : closeActive(current, exit),\n )\n\n const pull = Effect.gen(function* () {\n while (true) {\n if (done) return yield* Cause.done()\n\n if (current === undefined) {\n const result = body(state)\n const stream = Effect.isEffect(result) ? Stream.unwrap(result) : result\n const bodyScope = yield* Scope.fork(outerScope)\n const bodyPull = yield* Channel.toPullScoped(\n Stream.toChannel(stream),\n bodyScope,\n ).pipe(Effect.onError((cause) => Scope.close(bodyScope, Exit.failCause(cause))))\n current = { scope: bodyScope, pull: bodyPull }\n }\n\n const active = current\n const chunk = yield* active.pull.pipe(\n Effect.catchIf(Cause.isDone, () =>\n closeActive(active, Exit.void).pipe(\n Effect.as(undefined as ReadonlyArray<Step<A, S>> | undefined),\n ),\n ),\n Effect.onError((cause) => closeActive(active, Exit.failCause(cause))),\n )\n\n if (chunk === undefined) {\n done = true\n return yield* Cause.done()\n }\n\n const { values, decision } = partitionChunk(chunk)\n\n if (Option.isSome(decision)) {\n yield* closeActive(active, Exit.void)\n if (decision.value._tag === \"Stop\" || decision.value._tag === \"StopWith\") {\n // `loop` has no next iteration to apply StopWith's state to;\n // the state lands in `loopOver`'s outer ref or\n // `loopWithState`'s SubscriptionRef via their taps.\n done = true\n } else if (decision.value._tag === \"Next\") {\n state = decision.value.state\n }\n }\n\n // Emit the values seen so far if any. Chunks from a Stream pull\n // are non-empty, so when `decision` is `None` every step was\n // a `Value` and `values` is non-empty here. With a decision and\n // no preceding values, fall through to the next iteration.\n if (isNonEmpty(values)) return values\n }\n })\n\n return pull\n }),\n ),\n ),\n)\n\n// ---------------------------------------------------------------------------\n// loopOver - stream-driven sibling of loop. One input item runs a full\n// multi-turn inner loop.\n// ---------------------------------------------------------------------------\n\ntype LoopOverBody<S, I, A, E, R> = (\n state: S,\n input: I,\n) => Stream.Stream<Step<A, S>, E, R> | Effect.Effect<Stream.Stream<Step<A, S>, E, R>, E, R>\n\n/**\n * Input-driven sibling of `loop`. For each item pulled from the input\n * stream, runs an inner seed-driven `loop` whose body is\n * `(s) => body(s, item)`. State is threaded across input items.\n *\n * **Per-input semantics — the body emits standard `Step<A, S>`:**\n * - `value(a)`: emit `a` downstream\n * - `next(s)`: re-run the body with the SAME input and new state `s`\n * (multi-turn within one input — e.g. multiple model turns + tool\n * calls for one document)\n * - `stop()`: end this input's inner loop, advance to the next input\n * (state preserved)\n * - body stream ending without a decision: same as `stop()` (advance)\n *\n * **Outer termination:** the input stream ending. To halt programmatically\n * from within, end the input stream upstream (`Stream.takeWhile`, a\n * `SubscriptionRef` gate, etc.). Reserving `stop()` for per-item\n * advancement is what makes the common \"stream of documents, multi-turn\n * conversation per document\" shape readable.\n *\n * Dual: data-first `loopOver(input, initial, body)` and data-last\n * `input.pipe(loopOver(initial, body))` both work.\n */\nexport const loopOver: {\n <S, I, A, E, R>(\n initial: S,\n body: LoopOverBody<S, I, A, E, R>,\n ): <EI, RI>(input: Stream.Stream<I, EI, RI>) => Stream.Stream<A, E | EI, R | RI>\n <S, I, A, E, R, EI, RI>(\n input: Stream.Stream<I, EI, RI>,\n initial: S,\n body: LoopOverBody<S, I, A, E, R>,\n ): Stream.Stream<A, E | EI, R | RI>\n} = Function.dual(\n 3,\n <S, I, A, E, R, EI, RI>(\n input: Stream.Stream<I, EI, RI>,\n initial: S,\n body: LoopOverBody<S, I, A, E, R>,\n ): Stream.Stream<A, E | EI, R | RI> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const stateRef = yield* Ref.make<S>(initial)\n return input.pipe(\n Stream.flatMap((item) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const state = yield* Ref.get(stateRef)\n // Capture Next states (and stop(state)'s final state) into the\n // outer ref so the LAST state seen in this input's inner\n // loop is what the next input starts from.\n const wrappedBody = (s: S) => {\n const result = body(s, item)\n const stream = Effect.isEffect(result) ? Stream.unwrap(result) : result\n return stream.pipe(\n Stream.tap((step) =>\n Match.value(step).pipe(\n Match.tags({\n Next: (e) => Ref.set(stateRef, e.state),\n StopWith: (e) => Ref.set(stateRef, e.state),\n }),\n Match.orElse(() => Effect.void),\n ),\n ),\n )\n }\n return loop(state, wrappedBody)\n }),\n ),\n ),\n )\n }),\n ),\n)\n\n// ---------------------------------------------------------------------------\n// loopWithState - same body protocol, plus a live state observable.\n// ---------------------------------------------------------------------------\n\n/**\n * Like `loop`, but exposes the current loop state as a `SubscriptionRef`\n * alongside the value stream.\n *\n * Allocates one `SubscriptionRef<S>` seeded with `initial`, then runs the\n * loop with a wrapped body that taps every `Next(s)` step into the ref\n * before forwarding it. The caller decides how to consume both channels:\n *\n * - **Final state**: drain the stream, then `SubscriptionRef.get(state)`\n * - the ref holds the state from the last `Next` (or `initial` if the\n * loop ended without advancing).\n * - **Live transitions**: `SubscriptionRef.changes(state)` is a\n * `Stream<S>` of every state observed; subscribe alongside the value\n * stream.\n * - **Mid-iteration peek**: `SubscriptionRef.get(state)` at any time.\n *\n * The returned stream and ref are independent of each other - the ref\n * lives outside the stream's scope, so reading it after the stream\n * completes is safe.\n */\nexport const loopWithState = <S, A, E, R>(\n initial: S,\n body: LoopBody<S, A, E, R>,\n): Effect.Effect<{\n readonly stream: Stream.Stream<A, E, R>\n readonly state: SubscriptionRef.SubscriptionRef<S>\n}> =>\n Effect.gen(function* () {\n const stateRef = yield* SubscriptionRef.make(initial)\n\n const tap = (stream: Stream.Stream<Step<A, S>, E, R>): Stream.Stream<Step<A, S>, E, R> =>\n stream.pipe(\n Stream.tap((step) =>\n Match.value(step).pipe(\n Match.tags({\n Next: (e) => SubscriptionRef.set(stateRef, e.state),\n StopWith: (e) => SubscriptionRef.set(stateRef, e.state),\n }),\n Match.orElse(() => Effect.void),\n ),\n ),\n )\n\n const wrappedBody: LoopBody<S, A, E, R> = (s) => {\n const result = body(s)\n return Effect.isEffect(result) ? Effect.map(result, tap) : tap(result)\n }\n\n return {\n stream: loop(initial, wrappedBody),\n state: stateRef,\n }\n })\n"],"mappings":"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"}
1
+ {"version":3,"file":"Loop.mjs","names":["Arr"],"sources":["../../src/loop/Loop.ts"],"sourcesContent":["/**\n * Pull-based `loop` for state-threaded sub-streams.\n *\n * Each iteration runs a body that returns a `Stream<Step<A, S>>`. The body\n * emits values via `Loop.value(a)` and signals iteration control via\n * `Loop.next(state)` (continue with new state) or `Loop.stop()` (terminate).\n * The loop unwraps `Value` steps back to `A` for downstream consumers, so\n * the resulting stream is a plain `Stream<A>`.\n *\n * The next body stream is only pulled when downstream pulls the outer\n * stream - no producer fiber, no queue buffering. Cancellation, failures,\n * scoped resources, and backpressure stay aligned with normal Stream\n * semantics.\n *\n * Convention: a `Next` or `Stop` step is the terminal element of a body's\n * iteration. Values emitted in the same chunk after one are discarded\n * (their producing side effects may already have run). The `Loop.next` /\n * `Loop.stop` helpers each emit a single terminal step, so concatenate\n * your values before them (`values.pipe(Stream.concat(Loop.next(state)))`).\n */\nimport {\n Array as Arr,\n Cause,\n Channel,\n Data,\n Effect,\n Exit,\n Function,\n Match,\n Option,\n Ref,\n Scope,\n Stream,\n SubscriptionRef,\n} from \"effect\"\nimport { IncompleteTurn } from \"../domain/AiError.js\"\nimport { isTurnComplete, type Turn, type TurnEvent } from \"../domain/Turn.js\"\n\n// ---------------------------------------------------------------------------\n// Step type - the body's emit shape\n// ---------------------------------------------------------------------------\n\n/**\n * The tagged union a body emits per pull. `Value` carries a payload that\n * flows downstream. `Next` ends the current iteration and continues with a\n * new state. `Stop` ends the loop entirely with no carried state.\n * `StopWith` also ends the loop but carries a final state that `loopOver`\n * will thread to the next input and `loopWithState` will write to its\n * `SubscriptionRef` before the loop ends. Plain `loop` has no next\n * iteration to apply it to and treats `StopWith` like `Stop`.\n *\n * `Stop` is intentionally `{}` so the bare `stop()` helper doesn't\n * constrain `S` from a body's stream type — every body has a `Stop`\n * variant in its union, and forcing `S` to flow through it would break\n * inference whenever the body never uses `next` / `stop(state)`.\n */\nexport type Step<A, S> = Data.TaggedEnum<{\n Value: { readonly value: A }\n Next: { readonly state: S }\n Stop: {}\n StopWith: { readonly state: S }\n}>\n\ninterface StepDef extends Data.TaggedEnum.WithGenerics<2> {\n readonly taggedEnum: Step<this[\"A\"], this[\"B\"]>\n}\n\nconst Step = Data.taggedEnum<StepDef>()\n\n/**\n * Bare step constructors, so a loop body can emit `Value(...)`, `Next(...)`,\n * `Stop()`, `StopWith(...)` directly inside a `Stream.make(...)` without the\n * `Step.` prefix. (The `Step` object itself can't be exported under that name\n * because it collides with the exported `Step` type.) For the common cases\n * prefer the `value` / `next` / `stop` helpers, which also handle the\n * single-element-stream wrapping for `next` / `stop`.\n */\nexport const { Value, Next, Stop, StopWith } = Step\n\n/** Wrap a value so it flows through the loop to downstream consumers. */\nexport const value = <A>(a: A): Step<A, never> => Step.Value({ value: a })\n\n/**\n * End the current iteration and continue with a new state. Emits a single\n * terminal `Next` step as a one-element stream, so it slots directly into a\n * loop body or after a run of values: `values.pipe(Stream.concat(next(s)))`.\n */\nexport const next = <S>(state: S): Stream.Stream<Step<never, S>> =>\n Stream.succeed(Step.Next({ state }))\n\n/**\n * End the loop. Called with no argument it emits a bare `Stop`; called with\n * a state it emits `StopWith(state)` — `loopOver` threads that final state\n * to the next input and `loopWithState` writes it to its `SubscriptionRef`\n * before the loop ends. Either way it returns a single-element stream, so\n * return it directly from a loop body.\n */\nexport const stop = <S = never>(state?: S): Stream.Stream<Step<never, S>> =>\n Stream.succeed<Step<never, S>>(state === undefined ? Step.Stop() : Step.StopWith({ state }))\n\n// ---------------------------------------------------------------------------\n// onTurnComplete - turn-aware stream operator for loop bodies\n// ---------------------------------------------------------------------------\n\n/**\n * Lift a provider's `Stream<TurnEvent>` into a loop body's `Stream<Step<TurnEvent | A, S>>`.\n * Each delta passes through as `value(delta)` (including the terminal\n * `TurnComplete`, so the consumer sees turn boundaries naturally). Once\n * the terminal arrives, `then(turn)` runs and its returned stream of loop\n * steps (typically tool outputs followed by `next(state)` or `stop()`) is\n * concatenated.\n *\n * Pre-pipe transforms (`Stream.tap` / `Stream.map` / `Stream.filter`) on\n * the raw delta stream cover anything an `emit`-style callback would do.\n *\n * `then` may return the step stream directly, or an `Effect` that produces\n * it (for branches that need to read a `Ref`, decode tool args, log, etc.).\n * Mirrors `loop`'s body: return a bare `stop()` / `next(s)` where no effect\n * is needed, lift to `Effect` only where one is.\n *\n * If the upstream ends without a `TurnComplete`, the resulting stream\n * fails with `AiError.IncompleteTurn`. Catch it via `Stream.catchTag` if\n * you want to recover.\n *\n * Dual: data-first `onTurnComplete(deltas, then)` and data-last\n * `deltas.pipe(onTurnComplete(then))` both work.\n */\ntype TurnContinuation<S, A, E2, R2> =\n | Stream.Stream<Step<A, S>, E2, R2>\n | Effect.Effect<Stream.Stream<Step<A, S>, E2, R2>, E2, R2>\n\nexport const onTurnComplete: {\n <S, A, E2 = never, R2 = never>(\n then: (turn: Turn) => TurnContinuation<S, A, E2, R2>,\n ): <E, R>(\n deltas: Stream.Stream<TurnEvent, E, R>,\n ) => Stream.Stream<Step<TurnEvent | A, S>, E | E2 | IncompleteTurn, R | R2>\n <S, A, E, R, E2 = never, R2 = never>(\n deltas: Stream.Stream<TurnEvent, E, R>,\n then: (turn: Turn) => TurnContinuation<S, A, E2, R2>,\n ): Stream.Stream<Step<TurnEvent | A, S>, E | E2 | IncompleteTurn, R | R2>\n} = Function.dual(\n 2,\n <S, A, E, R, E2, R2>(\n deltas: Stream.Stream<TurnEvent, E, R>,\n then: (turn: Turn) => TurnContinuation<S, A, E2, R2>,\n ): Stream.Stream<Step<TurnEvent | A, S>, E | E2 | IncompleteTurn, R | R2> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const turnRef = yield* Ref.make<Option.Option<Turn>>(Option.none())\n\n const events: Stream.Stream<Step<TurnEvent, S>, E, R> = deltas.pipe(\n Stream.tap((delta) =>\n isTurnComplete(delta) ? Ref.set(turnRef, Option.some(delta.turn)) : Effect.void,\n ),\n Stream.map(value),\n )\n\n const continuation = Stream.unwrap(\n Effect.gen(function* () {\n const opt = yield* Ref.get(turnRef)\n if (Option.isNone(opt)) return yield* new IncompleteTurn({})\n const result = then(opt.value)\n return Effect.isEffect(result) ? yield* result : result\n }),\n )\n\n return Stream.concat(events, continuation)\n }),\n ),\n)\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst isNonEmpty = <A>(array: ReadonlyArray<A>): array is readonly [A, ...Array<A>] =>\n array.length > 0\n\ntype CurrentBody<S, A, E, R> = {\n readonly scope: Scope.Closeable\n readonly pull: Effect.Effect<ReadonlyArray<Step<A, S>>, E | Cause.Done<void>, R>\n}\n\nconst closeBody = <S, A, E, R>(\n current: CurrentBody<S, A, E, R>,\n exit: Exit.Exit<unknown, unknown>,\n) => Scope.close(current.scope, exit)\n\n/**\n * Walk a chunk of `Step<A, S>` until a terminal `Next` or `Stop` is found.\n * Returns the unwrapped values seen so far and (optionally) the terminal\n * step. Anything in the chunk after the terminal is discarded - its\n * producing side effects may have run, but downstream never sees it.\n */\nconst partitionChunk = <A, S>(\n chunk: ReadonlyArray<Step<A, S>>,\n): {\n readonly values: ReadonlyArray<A>\n readonly decision: Option.Option<Step<A, S>>\n} => {\n const [valueSteps, rest] = Arr.span(\n chunk,\n (e): e is Step<A, S> & { _tag: \"Value\" } => e._tag === \"Value\",\n )\n return {\n values: valueSteps.map((e) => e.value),\n decision: Arr.head(rest),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\ntype LoopBody<S, A, E, R> = (\n state: S,\n) => Stream.Stream<Step<A, S>, E, R> | Effect.Effect<Stream.Stream<Step<A, S>, E, R>, E, R>\n\n/**\n * Drive a state-threaded loop body. Each iteration runs `body(state)` to get\n * a `Stream<Step<A, S>>`; values flow downstream, `next(s)` continues with\n * a new state, `stop()` ends the loop. See the file header for the full\n * pull-based execution model.\n *\n * Dual: data-first `loop(initial, body)` and data-last `loop(body)(initial)`\n * (or `pipe(initial, loop(body))`) both work.\n */\nexport const loop: {\n <S, A, E, R>(body: LoopBody<S, A, E, R>): (initial: S) => Stream.Stream<A, E, R>\n <S, A, E, R>(initial: S, body: LoopBody<S, A, E, R>): Stream.Stream<A, E, R>\n} = Function.dual(\n 2,\n <S, A, E, R>(initial: S, body: LoopBody<S, A, E, R>): Stream.Stream<A, E, R> =>\n Stream.scoped(\n Stream.fromPull(\n Effect.gen(function* () {\n const outerScope = yield* Effect.scope\n let state = initial\n let current: CurrentBody<S, A, E, R> | undefined\n let done = false\n\n const closeActive = (\n active: CurrentBody<S, A, E, R>,\n exit: Exit.Exit<unknown, unknown>,\n ) => {\n const isActive = current === active\n if (isActive) current = undefined\n // Scope.close is idempotent. Multiple paths can race to close the\n // active body during cancellation/failure, so closing twice is safe.\n return closeBody(active, exit)\n }\n\n yield* Scope.addFinalizerExit(outerScope, (exit) =>\n current === undefined ? Effect.void : closeActive(current, exit),\n )\n\n const pull = Effect.gen(function* () {\n while (true) {\n if (done) return yield* Cause.done()\n\n if (current === undefined) {\n const result = body(state)\n const stream = Effect.isEffect(result) ? Stream.unwrap(result) : result\n const bodyScope = yield* Scope.fork(outerScope)\n const bodyPull = yield* Channel.toPullScoped(\n Stream.toChannel(stream),\n bodyScope,\n ).pipe(Effect.onError((cause) => Scope.close(bodyScope, Exit.failCause(cause))))\n current = { scope: bodyScope, pull: bodyPull }\n }\n\n const active = current\n const chunk = yield* active.pull.pipe(\n Effect.catchIf(Cause.isDone, () =>\n closeActive(active, Exit.void).pipe(\n Effect.as(undefined as ReadonlyArray<Step<A, S>> | undefined),\n ),\n ),\n Effect.onError((cause) => closeActive(active, Exit.failCause(cause))),\n )\n\n if (chunk === undefined) {\n done = true\n return yield* Cause.done()\n }\n\n const { values, decision } = partitionChunk(chunk)\n\n if (Option.isSome(decision)) {\n yield* closeActive(active, Exit.void)\n if (decision.value._tag === \"Stop\" || decision.value._tag === \"StopWith\") {\n // `loop` has no next iteration to apply StopWith's state to;\n // the state lands in `loopOver`'s outer ref or\n // `loopWithState`'s SubscriptionRef via their taps.\n done = true\n } else if (decision.value._tag === \"Next\") {\n state = decision.value.state\n }\n }\n\n // Emit the values seen so far if any. Chunks from a Stream pull\n // are non-empty, so when `decision` is `None` every step was\n // a `Value` and `values` is non-empty here. With a decision and\n // no preceding values, fall through to the next iteration.\n if (isNonEmpty(values)) return values\n }\n })\n\n // `Stream.fromPull` expects the generator to RETURN the pull effect,\n // not run it; `return yield* pull` would execute a pull and break it.\n // @effect-diagnostics-next-line effect/returnEffectInGen:off\n return pull\n }),\n ),\n ),\n)\n\n// ---------------------------------------------------------------------------\n// loopOver - stream-driven sibling of loop. One input item runs a full\n// multi-turn inner loop.\n// ---------------------------------------------------------------------------\n\ntype LoopOverBody<S, I, A, E, R> = (\n state: S,\n input: I,\n) => Stream.Stream<Step<A, S>, E, R> | Effect.Effect<Stream.Stream<Step<A, S>, E, R>, E, R>\n\n/**\n * Input-driven sibling of `loop`. For each item pulled from the input\n * stream, runs an inner seed-driven `loop` whose body is\n * `(s) => body(s, item)`. State is threaded across input items.\n *\n * **Per-input semantics — the body emits standard `Step<A, S>`:**\n * - `value(a)`: emit `a` downstream\n * - `next(s)`: re-run the body with the SAME input and new state `s`\n * (multi-turn within one input — e.g. multiple model turns + tool\n * calls for one document)\n * - `stop()`: end this input's inner loop, advance to the next input\n * (state preserved)\n * - body stream ending without a decision: same as `stop()` (advance)\n *\n * **Outer termination:** the input stream ending. To halt programmatically\n * from within, end the input stream upstream (`Stream.takeWhile`, a\n * `SubscriptionRef` gate, etc.). Reserving `stop()` for per-item\n * advancement is what makes the common \"stream of documents, multi-turn\n * conversation per document\" shape readable.\n *\n * Dual: data-first `loopOver(input, initial, body)` and data-last\n * `input.pipe(loopOver(initial, body))` both work.\n */\nexport const loopOver: {\n <S, I, A, E, R>(\n initial: S,\n body: LoopOverBody<S, I, A, E, R>,\n ): <EI, RI>(input: Stream.Stream<I, EI, RI>) => Stream.Stream<A, E | EI, R | RI>\n <S, I, A, E, R, EI, RI>(\n input: Stream.Stream<I, EI, RI>,\n initial: S,\n body: LoopOverBody<S, I, A, E, R>,\n ): Stream.Stream<A, E | EI, R | RI>\n} = Function.dual(\n 3,\n <S, I, A, E, R, EI, RI>(\n input: Stream.Stream<I, EI, RI>,\n initial: S,\n body: LoopOverBody<S, I, A, E, R>,\n ): Stream.Stream<A, E | EI, R | RI> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const stateRef = yield* Ref.make<S>(initial)\n return input.pipe(\n Stream.flatMap((item) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const state = yield* Ref.get(stateRef)\n // Capture Next states (and stop(state)'s final state) into the\n // outer ref so the LAST state seen in this input's inner\n // loop is what the next input starts from.\n const wrappedBody = (s: S) => {\n const result = body(s, item)\n const stream = Effect.isEffect(result) ? Stream.unwrap(result) : result\n return stream.pipe(\n Stream.tap((step) =>\n Match.value(step).pipe(\n Match.tags({\n Next: (e) => Ref.set(stateRef, e.state),\n StopWith: (e) => Ref.set(stateRef, e.state),\n }),\n Match.orElse(() => Effect.void),\n ),\n ),\n )\n }\n return loop(state, wrappedBody)\n }),\n ),\n ),\n )\n }),\n ),\n)\n\n// ---------------------------------------------------------------------------\n// loopWithState - same body protocol, plus a live state observable.\n// ---------------------------------------------------------------------------\n\n/**\n * Like `loop`, but exposes the current loop state as a `SubscriptionRef`\n * alongside the value stream.\n *\n * Allocates one `SubscriptionRef<S>` seeded with `initial`, then runs the\n * loop with a wrapped body that taps every `Next(s)` step into the ref\n * before forwarding it. The caller decides how to consume both channels:\n *\n * - **Final state**: drain the stream, then `SubscriptionRef.get(state)`\n * - the ref holds the state from the last `Next` (or `initial` if the\n * loop ended without advancing).\n * - **Live transitions**: `SubscriptionRef.changes(state)` is a\n * `Stream<S>` of every state observed; subscribe alongside the value\n * stream.\n * - **Mid-iteration peek**: `SubscriptionRef.get(state)` at any time.\n *\n * The returned stream and ref are independent of each other - the ref\n * lives outside the stream's scope, so reading it after the stream\n * completes is safe.\n */\nexport const loopWithState = <S, A, E, R>(\n initial: S,\n body: LoopBody<S, A, E, R>,\n): Effect.Effect<{\n readonly stream: Stream.Stream<A, E, R>\n readonly state: SubscriptionRef.SubscriptionRef<S>\n}> =>\n Effect.gen(function* () {\n const stateRef = yield* SubscriptionRef.make(initial)\n\n const tap = (stream: Stream.Stream<Step<A, S>, E, R>): Stream.Stream<Step<A, S>, E, R> =>\n stream.pipe(\n Stream.tap((step) =>\n Match.value(step).pipe(\n Match.tags({\n Next: (e) => SubscriptionRef.set(stateRef, e.state),\n StopWith: (e) => SubscriptionRef.set(stateRef, e.state),\n }),\n Match.orElse(() => Effect.void),\n ),\n ),\n )\n\n const wrappedBody: LoopBody<S, A, E, R> = (s) => {\n const result = body(s)\n return Effect.isEffect(result) ? Effect.map(result, tap) : tap(result)\n }\n\n return {\n stream: loop(initial, wrappedBody),\n state: stateRef,\n }\n })\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { RateLimited } from "../domain/AiError.mjs";
2
2
  import { TurnEvent } from "../domain/Turn.mjs";
3
3
  import { loop, loopOver, loopWithState, next, onTurnComplete, stop, value } from "./Loop.mjs";
4
- import { i as it, n as globalExpect, r as describe, t as import_dist } from "../dist-DV5ISja1.mjs";
4
+ import { a as describe, n as globalExpect, o as it, t as import_dist } from "../dist-B04dlFHg.mjs";
5
5
  import { Deferred, Effect, Fiber, Latch, Ref, Stream, SubscriptionRef, pipe } from "effect";
6
6
  //#region src/loop/Loop.test.ts
7
7
  describe("Loop.loop", () => {
@@ -98,6 +98,23 @@ describe("Loop.loop", () => {
98
98
  globalExpect(a.length).toBe(3);
99
99
  globalExpect(b.length).toBe(3);
100
100
  });
101
+ it("onTurnComplete: handler may return a step stream directly (not just Effect<Stream>)", async () => {
102
+ const turnComplete = TurnEvent.TurnComplete({ turn: {
103
+ items: [],
104
+ usage: {
105
+ input_tokens: 0,
106
+ output_tokens: 0
107
+ },
108
+ stop_reason: "stop"
109
+ } });
110
+ const deltas = Stream.fromIterable([TurnEvent.TextDelta({ text: "hi" }), turnComplete]);
111
+ const plain = deltas.pipe(onTurnComplete(() => stop()));
112
+ const effectful = deltas.pipe(onTurnComplete(() => Effect.sync(() => stop())));
113
+ const a = await Effect.runPromise(Stream.runCollect(plain));
114
+ const b = await Effect.runPromise(Stream.runCollect(effectful));
115
+ globalExpect(a.length).toBe(3);
116
+ globalExpect(b.length).toBe(3);
117
+ });
101
118
  it("is stack-safe and linear-time across many iterations", async () => {
102
119
  const N = 1e5;
103
120
  const stream = loop(0, (n) => n >= N ? Stream.succeed(value(n)).pipe(Stream.concat(stop())) : Stream.succeed(value(n)).pipe(Stream.concat(next(n + 1))));
@@ -1 +1 @@
1
- {"version":3,"file":"Loop.test.mjs","names":["AiError.RateLimited"],"sources":["../../src/loop/Loop.test.ts"],"sourcesContent":["import { Deferred, Effect, Fiber, Latch, pipe, Ref, Stream, SubscriptionRef } from \"effect\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport * as AiError from \"../domain/AiError.js\"\nimport { TurnEvent } from \"../domain/Turn.js\"\nimport {\n type Step,\n loop,\n loopOver,\n loopWithState,\n next,\n onTurnComplete,\n stop,\n value,\n} from \"./Loop.js\"\n\ndescribe(\"Loop.loop\", () => {\n it(\"threads state across iterations and emits each iteration's substream in order\", async () => {\n // Each iter emits [n, n + 0.5] then continues; final iter emits [n] and stops.\n const stream = loop(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n, n + 0.5]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([0, 0.5, 1, 1.5, 2, 2.5, 3])\n })\n\n it(\"supports iterations that emit zero values and only decide\", async () => {\n // Every iteration emits nothing, just bumps state; stops at 5.\n const stream = loop(0, (n: number) => (n >= 5 ? stop() : next(n + 1)))\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([])\n })\n\n it(\"supports Effect-returning bodies directly (no Stream.unwrap needed)\", async () => {\n // Each iter yields an Effect that doubles the state, then emits it.\n // Body returns Effect<Stream> directly; loop unwraps internally.\n const stream = loop(1, (n: number) =>\n Effect.gen(function* () {\n const doubled = yield* Effect.succeed(n * 2)\n return doubled >= 16\n ? Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(next(doubled)))\n }),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([2, 4, 8, 16])\n })\n\n it(\"still accepts Stream.unwrap-wrapped bodies for backward compatibility\", async () => {\n const stream = loop(1, (n: number) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const doubled = yield* Effect.succeed(n * 2)\n return doubled >= 4\n ? Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(next(doubled)))\n }),\n ),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([2, 4])\n })\n\n it(\"propagates errors from the body's stream\", async () => {\n const boom = new Error(\"boom\")\n const stream = loop(\n 0,\n (n: number): Stream.Stream<Step<number, number>, Error> =>\n n === 2 ? Stream.fail(boom) : Stream.succeed(value(n)).pipe(Stream.concat(next(n + 1))),\n )\n\n const result = await Effect.runPromiseExit(Stream.runCollect(stream))\n expect(result._tag).toBe(\"Failure\")\n })\n\n it(\"terminates silently if the body emits no Decision (mirrors paginate's silent stop)\", async () => {\n // No decision emitted - loop just ends after the body's stream completes.\n const stream = loop(0, (n: number) => Stream.fromIterable([value(n), value(n + 1)]))\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([0, 1])\n })\n\n it(\"short-circuits the body's stream when a Decision is seen\", async () => {\n // Body emits value(n), then a Next decision, then value(n+10). Once the\n // decision is encountered, the body is closed - `n+10` is never pulled, so\n // it never flows to the outer stream. This is the correct behavior: a\n // decision marks \"I'm done with this iteration\"; anything after it is dead.\n const stream = loop(0, (n: number) =>\n n >= 2\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(\n Stream.concat(next(n + 1)),\n Stream.concat(Stream.succeed(value(n + 10))),\n ),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([0, 1, 2])\n })\n\n it(\"type: data-last (pipe) form preserves the body's E channel\", () => {\n // Regression for the prior inference bug: when used as\n // `pipe(initial, loop(body))`, the body's E must propagate to the outer\n // stream instead of collapsing to `never`. Generics live on the outer\n // return of each overload, so neither calling form can erase them.\n const result = pipe(\n { count: 0 },\n loop((_state) => Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null }))),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited>()\n })\n\n it(\"type: data-first form preserves the body's E channel\", () => {\n const result = loop({ count: 0 }, (_state) =>\n Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null })),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited>()\n })\n\n it(\"type: onTurnComplete inside loop infers S and A from the handler without annotation\", () => {\n // Regression: when piped through loop, onTurnComplete's handler return\n // type (Stream<Step<A, S>>) is the single source of truth for the loop\n // body's element type. The previous workaround required explicit\n // <S, A> at the call site. Now the loop's outer-return generics pull\n // them through automatically.\n type LoopState = { readonly turns: number }\n type ToolEvent = { readonly _tag: \"tool\"; readonly name: string }\n\n const result = pipe(\n { turns: 0 } as LoopState,\n loop((state) =>\n Effect.gen(function* () {\n const deltas: Stream.Stream<TurnEvent> = Stream.empty\n return deltas.pipe(\n onTurnComplete(() =>\n Effect.sync(() =>\n state.turns >= 1\n ? stop()\n : Stream.succeed<ToolEvent>({ _tag: \"tool\", name: \"x\" }).pipe(\n Stream.map(value),\n Stream.concat(next({ turns: state.turns + 1 })),\n ),\n ),\n ),\n )\n }),\n ),\n )\n\n type Element = typeof result extends Stream.Stream<infer X, unknown, unknown> ? X : never\n expectTypeOf<Element>().toEqualTypeOf<TurnEvent | ToolEvent>()\n })\n\n it(\"onTurnComplete: data-first form (Function.dual) works at runtime\", async () => {\n // Pin both calling forms: deltas.pipe(onTurnComplete(handler)) and\n // onTurnComplete(deltas, handler). Same dispatch as loop's dual.\n const turnComplete: TurnEvent = TurnEvent.TurnComplete({\n turn: { items: [], usage: { input_tokens: 0, output_tokens: 0 }, stop_reason: \"stop\" },\n })\n const textDelta: TurnEvent = TurnEvent.TextDelta({ text: \"hi\" })\n const deltas: Stream.Stream<TurnEvent> = Stream.fromIterable([textDelta, turnComplete])\n\n const dataFirst = onTurnComplete(deltas, () => Effect.sync(() => stop()))\n const dataLast = deltas.pipe(onTurnComplete(() => Effect.sync(() => stop())))\n\n const a = await Effect.runPromise(Stream.runCollect(dataFirst))\n const b = await Effect.runPromise(Stream.runCollect(dataLast))\n\n // Two value(delta) wraps + one stop sentinel from the handler.\n expect(a.length).toBe(3)\n expect(b.length).toBe(3)\n })\n\n it(\"is stack-safe and linear-time across many iterations\", async () => {\n // 100k iterations far exceeds V8's typical stack depth (~10–15k frames).\n const N = 100_000\n const stream = loop(0, (n: number) =>\n n >= N\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(Stream.concat(next(n + 1))),\n )\n\n const count = await Effect.runPromise(\n Stream.runFold(\n stream,\n (): number => 0,\n (acc) => acc + 1,\n ),\n )\n expect(count).toBe(N + 1) // 0..N inclusive\n }, 10_000)\n})\n\n// ---------------------------------------------------------------------------\n// Mock LLM scenario - proves the loop forwards deltas in real time and\n// correctly threads tool-result events between turns.\n// ---------------------------------------------------------------------------\n\ntype Delta =\n | { readonly type: \"text\"; readonly text: string }\n | { readonly type: \"tool_call\"; readonly id: string; readonly name: string }\n\ntype HistoryItem =\n | { readonly type: \"user\"; readonly text: string }\n | { readonly type: \"assistant\"; readonly text: string }\n | { readonly type: \"tool_call\"; readonly id: string; readonly name: string }\n | { readonly type: \"tool_result\"; readonly id: string; readonly output: string }\n\ntype UiEvent =\n | { readonly type: \"text\"; readonly text: string }\n | { readonly type: \"tool_started\"; readonly id: string; readonly name: string }\n | { readonly type: \"tool_result\"; readonly id: string; readonly output: string }\n\ninterface MockModel {\n readonly streamTurn: (history: ReadonlyArray<HistoryItem>) => Stream.Stream<Delta>\n}\n\ninterface State {\n readonly history: ReadonlyArray<HistoryItem>\n readonly model: MockModel\n}\n\ninterface ToolOutcome {\n readonly output: string\n readonly nextModel?: MockModel\n}\n\ntype ToolRunner = (call: { id: string; name: string }) => ToolOutcome\n\nconst scriptedModel = (script: ReadonlyArray<ReadonlyArray<Delta>>): MockModel => {\n let i = 0\n return {\n streamTurn: () => {\n const turn = script[i] ?? []\n i += 1\n return Stream.fromIterable(turn)\n },\n }\n}\n\n/**\n * Body factored out so both tests share it. Per iteration:\n * 1. Stream the model's deltas; tap captures texts + tool calls into Refs.\n * 2. flatMap projects deltas into UiEvents forwarded to the outer stream.\n * 3. Continuation reads the captured calls; if any, runs them, emits\n * tool_result events, builds the next state (with model swap if a tool\n * asked for one), and emits `next(state)`. Otherwise `stop()`.\n */\nconst conversationLoop = (initial: State, runTool: ToolRunner) =>\n loop(initial, (state) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const textsRef = yield* Ref.make<ReadonlyArray<string>>([])\n const toolCallsRef = yield* Ref.make<\n ReadonlyArray<{ readonly id: string; readonly name: string }>\n >([])\n\n const deltas: Stream.Stream<Step<UiEvent, State>> = state.model\n .streamTurn(state.history)\n .pipe(\n Stream.tap((d) =>\n d.type === \"text\"\n ? Ref.update(textsRef, (t) => [...t, d.text])\n : Ref.update(toolCallsRef, (t) => [...t, { id: d.id, name: d.name }]),\n ),\n Stream.flatMap(\n (d): Stream.Stream<Step<UiEvent, State>> =>\n d.type === \"text\"\n ? Stream.fromIterable([value<UiEvent>({ type: \"text\", text: d.text })])\n : Stream.fromIterable([\n value<UiEvent>({ type: \"tool_started\", id: d.id, name: d.name }),\n ]),\n ),\n )\n\n const continuation: Stream.Stream<Step<UiEvent, State>> = Stream.unwrap(\n Effect.gen(function* () {\n const texts = yield* Ref.get(textsRef)\n const toolCalls = yield* Ref.get(toolCallsRef)\n\n if (toolCalls.length === 0) {\n return stop()\n }\n\n const turnItems: ReadonlyArray<HistoryItem> = [\n ...(texts.length > 0 ? [{ type: \"assistant\" as const, text: texts.join(\"\") }] : []),\n ...toolCalls.map(\n (tc): HistoryItem => ({ type: \"tool_call\", id: tc.id, name: tc.name }),\n ),\n ]\n\n const outcomes = toolCalls.map((call) => ({ call, outcome: runTool(call) }))\n\n const events: ReadonlyArray<UiEvent> = outcomes.map(({ call, outcome }) => ({\n type: \"tool_result\",\n id: call.id,\n output: outcome.output,\n }))\n\n const resultItems: ReadonlyArray<HistoryItem> = outcomes.map(\n ({ call, outcome }): HistoryItem => ({\n type: \"tool_result\",\n id: call.id,\n output: outcome.output,\n }),\n )\n\n // Last requested model wins; default to the current one.\n const nextModel = outcomes.reduce(\n (m, { outcome }) => outcome.nextModel ?? m,\n state.model,\n )\n\n const nextState: State = {\n history: [...state.history, ...turnItems, ...resultItems],\n model: nextModel,\n }\n\n return Stream.fromIterable(events).pipe(\n Stream.map(value),\n Stream.concat(next(nextState)),\n )\n }),\n )\n\n return Stream.concat(deltas, continuation)\n }),\n ),\n )\n\ndescribe(\"Loop.loop - LLM-style scenarios\", () => {\n it(\"forwards text deltas, tool start, tool result, and post-tool text in order\", async () => {\n const m = scriptedModel([\n [\n { type: \"text\", text: \"hello\" },\n { type: \"text\", text: \" \" },\n { type: \"text\", text: \"world\" },\n { type: \"tool_call\", id: \"c1\", name: \"get_time\" },\n ],\n [\n { type: \"text\", text: \" time is \" },\n { type: \"text\", text: \"12:00\" },\n ],\n ])\n\n const runTool: ToolRunner = (call) => ({\n output: call.name === \"get_time\" ? \"12:00\" : \"?\",\n })\n\n const initial: State = {\n history: [{ type: \"user\", text: \"what time is it?\" }],\n model: m,\n }\n\n const events = await Effect.runPromise(Stream.runCollect(conversationLoop(initial, runTool)))\n\n expect(events).toEqual([\n { type: \"text\", text: \"hello\" },\n { type: \"text\", text: \" \" },\n { type: \"text\", text: \"world\" },\n { type: \"tool_started\", id: \"c1\", name: \"get_time\" },\n { type: \"tool_result\", id: \"c1\", output: \"12:00\" },\n { type: \"text\", text: \" time is \" },\n { type: \"text\", text: \"12:00\" },\n ])\n })\n\n it(\"model swap mid-stream: m1 calls upgrade, m2 finishes the response\", async () => {\n const m2 = scriptedModel([\n [\n { type: \"text\", text: \"I am m2.\" },\n { type: \"text\", text: \" The answer is 42.\" },\n ],\n ])\n\n const m1 = scriptedModel([\n [\n { type: \"text\", text: \"Hard question.\" },\n { type: \"text\", text: \" Upgrading.\" },\n { type: \"tool_call\", id: \"u1\", name: \"upgrade\" },\n ],\n ])\n\n const runTool: ToolRunner = (call) =>\n call.name === \"upgrade\" ? { output: \"ok\", nextModel: m2 } : { output: \"?\" }\n\n const initial: State = {\n history: [{ type: \"user\", text: \"what is the meaning of life?\" }],\n model: m1,\n }\n\n const events = await Effect.runPromise(Stream.runCollect(conversationLoop(initial, runTool)))\n\n expect(events).toEqual([\n { type: \"text\", text: \"Hard question.\" },\n { type: \"text\", text: \" Upgrading.\" },\n { type: \"tool_started\", id: \"u1\", name: \"upgrade\" },\n { type: \"tool_result\", id: \"u1\", output: \"ok\" },\n { type: \"text\", text: \"I am m2.\" },\n { type: \"text\", text: \" The answer is 42.\" },\n ])\n })\n})\n\ndescribe(\"Loop.loop - pull-specific stream semantics\", () => {\n it(\"does not start the next iteration when downstream only takes the first value\", async () => {\n const bodyCalls = await Effect.runPromise(\n Effect.gen(function* () {\n const callsRef = yield* Ref.make(0)\n const stream = loop(0, (n: number) =>\n Stream.unwrap(\n Ref.update(callsRef, (calls) => calls + 1).pipe(\n Effect.as(\n n >= 10\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(Stream.concat(next(n + 1))),\n ),\n ),\n ),\n )\n\n yield* stream.pipe(Stream.take(1), Stream.runCollect)\n return yield* Ref.get(callsRef)\n }),\n )\n\n expect(bodyCalls).toBe(1)\n })\n\n it(\"propagates defects from the body instead of leaving the consumer waiting\", async () => {\n const defect = new Error(\"defect\")\n const stream = loop(0, () => Stream.die(defect))\n\n const result = await Effect.runPromiseExit(Stream.runCollect(stream))\n\n expect(result._tag).toBe(\"Failure\")\n })\n\n it(\"runs body finalizers when a Decision short-circuits the body\", async () => {\n const releases = await Effect.runPromise(\n Effect.gen(function* () {\n const releasesRef = yield* Ref.make<ReadonlyArray<number>>([])\n const stream = loop(0, (n: number) =>\n (n >= 1\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(\n Stream.concat(next(n + 1)),\n Stream.concat(Stream.succeed(value(n + 10))),\n )\n ).pipe(Stream.ensuring(Ref.update(releasesRef, (values) => [...values, n]))),\n )\n\n const values = yield* Stream.runCollect(stream)\n expect(values).toEqual([0, 1])\n return yield* Ref.get(releasesRef)\n }),\n )\n\n expect(releases).toEqual([0, 1])\n })\n\n it(\"runs the active body finalizer when the downstream consumer is interrupted\", async () => {\n const releases = await Effect.runPromise(\n Effect.gen(function* () {\n const started = yield* Deferred.make<void>()\n const releasesRef = yield* Ref.make(0)\n const body = (): Stream.Stream<Step<number, never>> =>\n Stream.concat(\n Stream.fromEffect(Deferred.succeed(started, undefined).pipe(Effect.as(value(0)))),\n Stream.never,\n ).pipe(Stream.ensuring(Ref.update(releasesRef, (n) => n + 1)))\n const stream = loop(0, body)\n\n const fiber = yield* Effect.forkChild(Stream.runCollect(stream))\n yield* Deferred.await(started)\n yield* Fiber.interrupt(fiber)\n\n return yield* Ref.get(releasesRef)\n }),\n )\n\n expect(releases).toBe(1)\n })\n\n it(\"does not create a body scope if constructing the body stream defects\", async () => {\n const defect = new Error(\"body construction failed\")\n const result = await Effect.runPromiseExit(\n Stream.runCollect(\n loop(0, (): Stream.Stream<Step<number, never>> => {\n throw defect\n }),\n ),\n )\n\n expect(result._tag).toBe(\"Failure\")\n })\n})\n\ndescribe(\"Loop.loopWithState\", () => {\n it(\"exposes the final state in the SubscriptionRef after the stream completes\", async () => {\n const program = Effect.gen(function* () {\n const { stream, state } = yield* loopWithState(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n const values = yield* Stream.runCollect(stream)\n const finalState = yield* SubscriptionRef.get(state)\n return { values: Array.from(values), finalState }\n })\n\n const { values, finalState } = await Effect.runPromise(program)\n expect(values).toEqual([0, 1, 2, 3])\n // Last `next(state)` was `next(3)` before the iteration that emitted Stop.\n expect(finalState).toBe(3)\n })\n\n it(\"the state ref starts at `initial` and stays there if the loop stops without advancing\", async () => {\n const program = Effect.gen(function* () {\n const { stream, state } = yield* loopWithState({ count: 7 }, () => stop())\n yield* Stream.runDrain(stream)\n return yield* SubscriptionRef.get(state)\n })\n\n expect(await Effect.runPromise(program)).toEqual({ count: 7 })\n })\n\n it(\"a downstream consumer can read the live state between emitted values\", async () => {\n // Body emits one value per iteration, then advances. A `Stream.runForEach`\n // consumer reads the ref each time a value arrives — proving the ref\n // tracks loop state without the body needing to surface it.\n const program = Effect.gen(function* () {\n const { stream, state } = yield* loopWithState(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n const seen: Array<{ value: number; stateAfter: number }> = []\n yield* Stream.runForEach(stream, (v) =>\n Effect.gen(function* () {\n seen.push({ value: v, stateAfter: yield* SubscriptionRef.get(state) })\n }),\n )\n return seen\n })\n\n // For each iter `n`, the consumer reads the ref between values: it sees\n // the iteration's input state. The terminal iter (n=3) stops without\n // advancing, so its read still shows 3.\n expect(await Effect.runPromise(program)).toEqual([\n { value: 0, stateAfter: 0 },\n { value: 1, stateAfter: 1 },\n { value: 2, stateAfter: 2 },\n { value: 3, stateAfter: 3 },\n ])\n })\n\n it(\"SubscriptionRef.changes emits every state transition to a concurrent observer\", async () => {\n const program = Effect.gen(function* () {\n const start = yield* Latch.make(false)\n\n // Body waits on the latch in iter 0 so the observer can subscribe first.\n const { stream, state } = yield* loopWithState(0, (n: number) =>\n Effect.gen(function* () {\n if (n === 0) yield* Latch.await(start)\n return n >= 3 ? stop() : next(n + 1)\n }),\n )\n\n // Fork the observer; take 4 distinct states (initial + 3 transitions).\n const observerFiber = yield* Effect.forkChild(\n SubscriptionRef.changes(state).pipe(Stream.take(4), Stream.runCollect),\n )\n\n // Give the observer fiber a chance to actually subscribe before the\n // loop starts advancing the ref. Without this, the loop could finish\n // before the observer's pubsub subscription is in place.\n yield* Effect.sleep(\"10 millis\")\n\n yield* Latch.open(start)\n yield* Stream.runDrain(stream)\n\n return Array.from(yield* Fiber.join(observerFiber))\n })\n\n // initial 0, then next(1), next(2), next(3) — four distinct states.\n expect(await Effect.runPromise(program)).toEqual([0, 1, 2, 3])\n })\n\n it(\"does not interfere with the body's value stream\", async () => {\n const program = Effect.gen(function* () {\n const { stream } = yield* loopWithState(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n, n + 0.5]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n return Array.from(yield* Stream.runCollect(stream))\n })\n\n expect(await Effect.runPromise(program)).toEqual([0, 0.5, 1, 1.5, 2, 2.5, 3])\n })\n})\n\ndescribe(\"Loop.loopOver\", () => {\n it(\"runs a multi-turn inner loop per input until the body emits stop\", async () => {\n // Per input: emit (input + turnsSoFar) twice, then stop. State counts\n // total turns ACROSS inputs. Demonstrates that `next(s)` continues with\n // the SAME input, multiple times per input — not one body call per item.\n const result = await Effect.runPromise(\n Stream.fromIterable([\"a\", \"b\"]).pipe(\n loopOver(0, (turns: number, input: string) => {\n if (turns >= 2 * (input === \"a\" ? 1 : 2)) return stop()\n return Stream.succeed(value(`${input}:${turns}`)).pipe(Stream.concat(next(turns + 1)))\n }),\n Stream.runCollect,\n ),\n )\n\n // input=\"a\": turns 0,1 → emit \"a:0\",\"a:1\"; turns=2 → stop. State threads.\n // input=\"b\": turns 2,3 → emit \"b:2\",\"b:3\"; turns=4 → stop.\n expect(result).toEqual([\"a:0\", \"a:1\", \"b:2\", \"b:3\"])\n })\n\n it(\"threads state across inputs (audio-pipeline shape)\", async () => {\n // History accumulates across inputs. Each input emits its joined view of\n // history+input, then `stop(state)` ends the inner loop AND carries the\n // updated history to the next input.\n const result = await Effect.runPromise(\n Stream.fromIterable([\"x\", \"y\", \"z\"]).pipe(\n loopOver([] as ReadonlyArray<string>, (history: ReadonlyArray<string>, input: string) =>\n Stream.succeed(value([...history, input].join(\",\"))).pipe(\n Stream.concat(stop([...history, input])),\n ),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\"x\", \"x,y\", \"x,y,z\"])\n })\n\n it(\"simulates a stream of documents with multi-turn tool calls per document\", async () => {\n // Document arrives → model \"thinks\" (one text turn) → calls a tool\n // (one tool turn) → emits final text (one text turn) → done.\n // Three turns per document, two documents.\n type Turn =\n | { readonly kind: \"text\"; readonly doc: string; readonly text: string }\n | { readonly kind: \"tool\"; readonly doc: string; readonly tool: string }\n type State = { readonly turn: number; readonly totalTurns: number }\n\n const result = await Effect.runPromise(\n Stream.fromIterable([\"doc1\", \"doc2\"]).pipe(\n loopOver({ turn: 0, totalTurns: 0 } as State, (state, doc: string) => {\n // Each document runs three turns then stops.\n if (state.turn === 0) {\n return Stream.succeed(value<Turn>({ kind: \"text\", doc, text: \"thinking\" })).pipe(\n Stream.concat(next({ turn: 1, totalTurns: state.totalTurns + 1 })),\n )\n }\n if (state.turn === 1) {\n return Stream.succeed(value<Turn>({ kind: \"tool\", doc, tool: \"search\" })).pipe(\n Stream.concat(next({ turn: 2, totalTurns: state.totalTurns + 1 })),\n )\n }\n // Final turn — `stop(state)` emits the final value, advances state\n // (reset turn to 0 for the next document, bump totalTurns), and\n // ends this document's inner loop in one shot.\n return Stream.succeed(value<Turn>({ kind: \"text\", doc, text: \"final\" })).pipe(\n Stream.concat(stop({ turn: 0, totalTurns: state.totalTurns + 1 })),\n )\n }),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\n { kind: \"text\", doc: \"doc1\", text: \"thinking\" },\n { kind: \"tool\", doc: \"doc1\", tool: \"search\" },\n { kind: \"text\", doc: \"doc1\", text: \"final\" },\n { kind: \"text\", doc: \"doc2\", text: \"thinking\" },\n { kind: \"tool\", doc: \"doc2\", tool: \"search\" },\n { kind: \"text\", doc: \"doc2\", text: \"final\" },\n ])\n })\n\n it(\"ends cleanly when the input stream ends mid-conversation\", async () => {\n // Single-input case: body advances via `next` then stops cleanly.\n const result = await Effect.runPromise(\n Stream.fromIterable([\"only\"]).pipe(\n loopOver(0, (turns: number, input: string) =>\n turns >= 2\n ? stop()\n : Stream.succeed(value(`${input}:${turns}`)).pipe(Stream.concat(next(turns + 1))),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\"only:0\", \"only:1\"])\n })\n\n it(\"body's `stop()` advances to the next input (does NOT halt the whole stream)\", async () => {\n // Three inputs, body always stops on its first emission. All three\n // are processed — `stop()` is per-input, not global. To halt the whole\n // stream, end the INPUT stream upstream.\n const result = await Effect.runPromise(\n Stream.fromIterable([1, 2, 3]).pipe(\n loopOver(0, (_state: number, input: number) =>\n Stream.succeed(value(input * 10)).pipe(Stream.concat(stop())),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([10, 20, 30])\n })\n\n it(\"data-first form (Function.dual) runs identically to data-last\", async () => {\n const inputs = Stream.fromIterable([1, 2])\n const result = await Effect.runPromise(\n Stream.runCollect(\n loopOver(inputs, 0, (state: number, input: number) =>\n state >= input\n ? stop()\n : Stream.succeed(value(state + input)).pipe(Stream.concat(next(state + 1))),\n ),\n ),\n )\n\n // input=1: state=0 → emit 1, state→1; state=1≥1 → stop.\n // input=2: state=1 → emit 3, state→2; state=2≥2 → stop.\n expect(result).toEqual([1, 3])\n })\n\n it(\"supports Effect-returning bodies (parity with loop)\", async () => {\n const result = await Effect.runPromise(\n Stream.fromIterable([\"a\"]).pipe(\n loopOver(0, (turns: number, input: string) =>\n Effect.gen(function* () {\n const cur = yield* Effect.succeed(turns)\n if (cur >= 2) return stop()\n return Stream.succeed(value(`${input}:${cur}`)).pipe(Stream.concat(next(cur + 1)))\n }),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\"a:0\", \"a:1\"])\n })\n\n it(\"type: data-last (pipe) form preserves the body's E channel\", () => {\n const result = pipe(\n Stream.fromIterable([1]),\n loopOver(0, (_state: number, _input: number) =>\n Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null })),\n ),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited>()\n })\n\n it(\"type: data-first form preserves the body's E channel and unifies with input's E\", () => {\n const input: Stream.Stream<number, Error> = Stream.fail(new Error(\"boom\"))\n const result = loopOver(input, 0, (_state: number, _i: number) =>\n Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null })),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited | Error>()\n })\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"Loop.test.mjs","names":["AiError.RateLimited"],"sources":["../../src/loop/Loop.test.ts"],"sourcesContent":["import { Deferred, Effect, Fiber, Latch, pipe, Ref, Stream, SubscriptionRef } from \"effect\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport * as AiError from \"../domain/AiError.js\"\nimport { TurnEvent } from \"../domain/Turn.js\"\nimport {\n type Step,\n loop,\n loopOver,\n loopWithState,\n next,\n onTurnComplete,\n stop,\n value,\n} from \"./Loop.js\"\n\ndescribe(\"Loop.loop\", () => {\n it(\"threads state across iterations and emits each iteration's substream in order\", async () => {\n // Each iter emits [n, n + 0.5] then continues; final iter emits [n] and stops.\n const stream = loop(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n, n + 0.5]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([0, 0.5, 1, 1.5, 2, 2.5, 3])\n })\n\n it(\"supports iterations that emit zero values and only decide\", async () => {\n // Every iteration emits nothing, just bumps state; stops at 5.\n const stream = loop(0, (n: number) => (n >= 5 ? stop() : next(n + 1)))\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([])\n })\n\n it(\"supports Effect-returning bodies directly (no Stream.unwrap needed)\", async () => {\n // Each iter yields an Effect that doubles the state, then emits it.\n // Body returns Effect<Stream> directly; loop unwraps internally.\n const stream = loop(1, (n: number) =>\n Effect.gen(function* () {\n const doubled = yield* Effect.succeed(n * 2)\n return doubled >= 16\n ? Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(next(doubled)))\n }),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([2, 4, 8, 16])\n })\n\n it(\"still accepts Stream.unwrap-wrapped bodies for backward compatibility\", async () => {\n const stream = loop(1, (n: number) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const doubled = yield* Effect.succeed(n * 2)\n return doubled >= 4\n ? Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([doubled]).pipe(Stream.map(value), Stream.concat(next(doubled)))\n }),\n ),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([2, 4])\n })\n\n it(\"propagates errors from the body's stream\", async () => {\n const boom = new Error(\"boom\")\n const stream = loop(\n 0,\n (n: number): Stream.Stream<Step<number, number>, Error> =>\n n === 2 ? Stream.fail(boom) : Stream.succeed(value(n)).pipe(Stream.concat(next(n + 1))),\n )\n\n const result = await Effect.runPromiseExit(Stream.runCollect(stream))\n expect(result._tag).toBe(\"Failure\")\n })\n\n it(\"terminates silently if the body emits no Decision (mirrors paginate's silent stop)\", async () => {\n // No decision emitted - loop just ends after the body's stream completes.\n const stream = loop(0, (n: number) => Stream.fromIterable([value(n), value(n + 1)]))\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([0, 1])\n })\n\n it(\"short-circuits the body's stream when a Decision is seen\", async () => {\n // Body emits value(n), then a Next decision, then value(n+10). Once the\n // decision is encountered, the body is closed - `n+10` is never pulled, so\n // it never flows to the outer stream. This is the correct behavior: a\n // decision marks \"I'm done with this iteration\"; anything after it is dead.\n const stream = loop(0, (n: number) =>\n n >= 2\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(\n Stream.concat(next(n + 1)),\n Stream.concat(Stream.succeed(value(n + 10))),\n ),\n )\n\n const result = await Effect.runPromise(Stream.runCollect(stream))\n expect(result).toEqual([0, 1, 2])\n })\n\n it(\"type: data-last (pipe) form preserves the body's E channel\", () => {\n // Regression for the prior inference bug: when used as\n // `pipe(initial, loop(body))`, the body's E must propagate to the outer\n // stream instead of collapsing to `never`. Generics live on the outer\n // return of each overload, so neither calling form can erase them.\n const result = pipe(\n { count: 0 },\n loop((_state) => Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null }))),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited>()\n })\n\n it(\"type: data-first form preserves the body's E channel\", () => {\n const result = loop({ count: 0 }, (_state) =>\n Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null })),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited>()\n })\n\n it(\"type: onTurnComplete inside loop infers S and A from the handler without annotation\", () => {\n // Regression: when piped through loop, onTurnComplete's handler return\n // type (Stream<Step<A, S>>) is the single source of truth for the loop\n // body's element type. The previous workaround required explicit\n // <S, A> at the call site. Now the loop's outer-return generics pull\n // them through automatically.\n type LoopState = { readonly turns: number }\n type ToolEvent = { readonly _tag: \"tool\"; readonly name: string }\n\n const result = pipe(\n { turns: 0 } as LoopState,\n loop((state) =>\n Effect.gen(function* () {\n const deltas: Stream.Stream<TurnEvent> = Stream.empty\n return deltas.pipe(\n onTurnComplete(() =>\n Effect.sync(() =>\n state.turns >= 1\n ? stop()\n : Stream.succeed<ToolEvent>({ _tag: \"tool\", name: \"x\" }).pipe(\n Stream.map(value),\n Stream.concat(next({ turns: state.turns + 1 })),\n ),\n ),\n ),\n )\n }),\n ),\n )\n\n type Element = typeof result extends Stream.Stream<infer X, unknown, unknown> ? X : never\n expectTypeOf<Element>().toEqualTypeOf<TurnEvent | ToolEvent>()\n })\n\n it(\"onTurnComplete: data-first form (Function.dual) works at runtime\", async () => {\n // Pin both calling forms: deltas.pipe(onTurnComplete(handler)) and\n // onTurnComplete(deltas, handler). Same dispatch as loop's dual.\n const turnComplete: TurnEvent = TurnEvent.TurnComplete({\n turn: { items: [], usage: { input_tokens: 0, output_tokens: 0 }, stop_reason: \"stop\" },\n })\n const textDelta: TurnEvent = TurnEvent.TextDelta({ text: \"hi\" })\n const deltas: Stream.Stream<TurnEvent> = Stream.fromIterable([textDelta, turnComplete])\n\n const dataFirst = onTurnComplete(deltas, () => Effect.sync(() => stop()))\n const dataLast = deltas.pipe(onTurnComplete(() => Effect.sync(() => stop())))\n\n const a = await Effect.runPromise(Stream.runCollect(dataFirst))\n const b = await Effect.runPromise(Stream.runCollect(dataLast))\n\n // Two value(delta) wraps + one stop sentinel from the handler.\n expect(a.length).toBe(3)\n expect(b.length).toBe(3)\n })\n\n it(\"onTurnComplete: handler may return a step stream directly (not just Effect<Stream>)\", async () => {\n // The handler can skip the Effect wrapper when no effect is needed -\n // bare stop() / next(s), mirroring loop's body.\n const turnComplete: TurnEvent = TurnEvent.TurnComplete({\n turn: { items: [], usage: { input_tokens: 0, output_tokens: 0 }, stop_reason: \"stop\" },\n })\n const deltas: Stream.Stream<TurnEvent> = Stream.fromIterable([\n TurnEvent.TextDelta({ text: \"hi\" }),\n turnComplete,\n ])\n\n const plain = deltas.pipe(onTurnComplete(() => stop()))\n const effectful = deltas.pipe(onTurnComplete(() => Effect.sync(() => stop())))\n\n const a = await Effect.runPromise(Stream.runCollect(plain))\n const b = await Effect.runPromise(Stream.runCollect(effectful))\n\n // Two value(delta) wraps + one stop sentinel; both return forms behave identically.\n expect(a.length).toBe(3)\n expect(b.length).toBe(3)\n })\n\n it(\"is stack-safe and linear-time across many iterations\", async () => {\n // 100k iterations far exceeds V8's typical stack depth (~10–15k frames).\n const N = 100_000\n const stream = loop(0, (n: number) =>\n n >= N\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(Stream.concat(next(n + 1))),\n )\n\n const count = await Effect.runPromise(\n Stream.runFold(\n stream,\n (): number => 0,\n (acc) => acc + 1,\n ),\n )\n expect(count).toBe(N + 1) // 0..N inclusive\n }, 10_000)\n})\n\n// ---------------------------------------------------------------------------\n// Mock LLM scenario - proves the loop forwards deltas in real time and\n// correctly threads tool-result events between turns.\n// ---------------------------------------------------------------------------\n\ntype Delta =\n | { readonly type: \"text\"; readonly text: string }\n | { readonly type: \"tool_call\"; readonly id: string; readonly name: string }\n\ntype HistoryItem =\n | { readonly type: \"user\"; readonly text: string }\n | { readonly type: \"assistant\"; readonly text: string }\n | { readonly type: \"tool_call\"; readonly id: string; readonly name: string }\n | { readonly type: \"tool_result\"; readonly id: string; readonly output: string }\n\ntype UiEvent =\n | { readonly type: \"text\"; readonly text: string }\n | { readonly type: \"tool_started\"; readonly id: string; readonly name: string }\n | { readonly type: \"tool_result\"; readonly id: string; readonly output: string }\n\ninterface MockModel {\n readonly streamTurn: (history: ReadonlyArray<HistoryItem>) => Stream.Stream<Delta>\n}\n\ninterface State {\n readonly history: ReadonlyArray<HistoryItem>\n readonly model: MockModel\n}\n\ninterface ToolOutcome {\n readonly output: string\n readonly nextModel?: MockModel\n}\n\ntype ToolRunner = (call: { id: string; name: string }) => ToolOutcome\n\nconst scriptedModel = (script: ReadonlyArray<ReadonlyArray<Delta>>): MockModel => {\n let i = 0\n return {\n streamTurn: () => {\n const turn = script[i] ?? []\n i += 1\n return Stream.fromIterable(turn)\n },\n }\n}\n\n/**\n * Body factored out so both tests share it. Per iteration:\n * 1. Stream the model's deltas; tap captures texts + tool calls into Refs.\n * 2. flatMap projects deltas into UiEvents forwarded to the outer stream.\n * 3. Continuation reads the captured calls; if any, runs them, emits\n * tool_result events, builds the next state (with model swap if a tool\n * asked for one), and emits `next(state)`. Otherwise `stop()`.\n */\nconst conversationLoop = (initial: State, runTool: ToolRunner) =>\n loop(initial, (state) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const textsRef = yield* Ref.make<ReadonlyArray<string>>([])\n const toolCallsRef = yield* Ref.make<\n ReadonlyArray<{ readonly id: string; readonly name: string }>\n >([])\n\n const deltas: Stream.Stream<Step<UiEvent, State>> = state.model\n .streamTurn(state.history)\n .pipe(\n Stream.tap((d) =>\n d.type === \"text\"\n ? Ref.update(textsRef, (t) => [...t, d.text])\n : Ref.update(toolCallsRef, (t) => [...t, { id: d.id, name: d.name }]),\n ),\n Stream.flatMap(\n (d): Stream.Stream<Step<UiEvent, State>> =>\n d.type === \"text\"\n ? Stream.fromIterable([value<UiEvent>({ type: \"text\", text: d.text })])\n : Stream.fromIterable([\n value<UiEvent>({ type: \"tool_started\", id: d.id, name: d.name }),\n ]),\n ),\n )\n\n const continuation: Stream.Stream<Step<UiEvent, State>> = Stream.unwrap(\n Effect.gen(function* () {\n const texts = yield* Ref.get(textsRef)\n const toolCalls = yield* Ref.get(toolCallsRef)\n\n if (toolCalls.length === 0) {\n return stop()\n }\n\n const turnItems: ReadonlyArray<HistoryItem> = [\n ...(texts.length > 0 ? [{ type: \"assistant\" as const, text: texts.join(\"\") }] : []),\n ...toolCalls.map(\n (tc): HistoryItem => ({ type: \"tool_call\", id: tc.id, name: tc.name }),\n ),\n ]\n\n const outcomes = toolCalls.map((call) => ({ call, outcome: runTool(call) }))\n\n const events: ReadonlyArray<UiEvent> = outcomes.map(({ call, outcome }) => ({\n type: \"tool_result\",\n id: call.id,\n output: outcome.output,\n }))\n\n const resultItems: ReadonlyArray<HistoryItem> = outcomes.map(\n ({ call, outcome }): HistoryItem => ({\n type: \"tool_result\",\n id: call.id,\n output: outcome.output,\n }),\n )\n\n // Last requested model wins; default to the current one.\n const nextModel = outcomes.reduce(\n (m, { outcome }) => outcome.nextModel ?? m,\n state.model,\n )\n\n const nextState: State = {\n history: [...state.history, ...turnItems, ...resultItems],\n model: nextModel,\n }\n\n return Stream.fromIterable(events).pipe(\n Stream.map(value),\n Stream.concat(next(nextState)),\n )\n }),\n )\n\n return Stream.concat(deltas, continuation)\n }),\n ),\n )\n\ndescribe(\"Loop.loop - LLM-style scenarios\", () => {\n it(\"forwards text deltas, tool start, tool result, and post-tool text in order\", async () => {\n const m = scriptedModel([\n [\n { type: \"text\", text: \"hello\" },\n { type: \"text\", text: \" \" },\n { type: \"text\", text: \"world\" },\n { type: \"tool_call\", id: \"c1\", name: \"get_time\" },\n ],\n [\n { type: \"text\", text: \" time is \" },\n { type: \"text\", text: \"12:00\" },\n ],\n ])\n\n const runTool: ToolRunner = (call) => ({\n output: call.name === \"get_time\" ? \"12:00\" : \"?\",\n })\n\n const initial: State = {\n history: [{ type: \"user\", text: \"what time is it?\" }],\n model: m,\n }\n\n const events = await Effect.runPromise(Stream.runCollect(conversationLoop(initial, runTool)))\n\n expect(events).toEqual([\n { type: \"text\", text: \"hello\" },\n { type: \"text\", text: \" \" },\n { type: \"text\", text: \"world\" },\n { type: \"tool_started\", id: \"c1\", name: \"get_time\" },\n { type: \"tool_result\", id: \"c1\", output: \"12:00\" },\n { type: \"text\", text: \" time is \" },\n { type: \"text\", text: \"12:00\" },\n ])\n })\n\n it(\"model swap mid-stream: m1 calls upgrade, m2 finishes the response\", async () => {\n const m2 = scriptedModel([\n [\n { type: \"text\", text: \"I am m2.\" },\n { type: \"text\", text: \" The answer is 42.\" },\n ],\n ])\n\n const m1 = scriptedModel([\n [\n { type: \"text\", text: \"Hard question.\" },\n { type: \"text\", text: \" Upgrading.\" },\n { type: \"tool_call\", id: \"u1\", name: \"upgrade\" },\n ],\n ])\n\n const runTool: ToolRunner = (call) =>\n call.name === \"upgrade\" ? { output: \"ok\", nextModel: m2 } : { output: \"?\" }\n\n const initial: State = {\n history: [{ type: \"user\", text: \"what is the meaning of life?\" }],\n model: m1,\n }\n\n const events = await Effect.runPromise(Stream.runCollect(conversationLoop(initial, runTool)))\n\n expect(events).toEqual([\n { type: \"text\", text: \"Hard question.\" },\n { type: \"text\", text: \" Upgrading.\" },\n { type: \"tool_started\", id: \"u1\", name: \"upgrade\" },\n { type: \"tool_result\", id: \"u1\", output: \"ok\" },\n { type: \"text\", text: \"I am m2.\" },\n { type: \"text\", text: \" The answer is 42.\" },\n ])\n })\n})\n\ndescribe(\"Loop.loop - pull-specific stream semantics\", () => {\n it(\"does not start the next iteration when downstream only takes the first value\", async () => {\n const bodyCalls = await Effect.runPromise(\n Effect.gen(function* () {\n const callsRef = yield* Ref.make(0)\n const stream = loop(0, (n: number) =>\n Stream.unwrap(\n Ref.update(callsRef, (calls) => calls + 1).pipe(\n Effect.as(\n n >= 10\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(Stream.concat(next(n + 1))),\n ),\n ),\n ),\n )\n\n yield* stream.pipe(Stream.take(1), Stream.runCollect)\n return yield* Ref.get(callsRef)\n }),\n )\n\n expect(bodyCalls).toBe(1)\n })\n\n it(\"propagates defects from the body instead of leaving the consumer waiting\", async () => {\n const defect = new Error(\"defect\")\n const stream = loop(0, () => Stream.die(defect))\n\n const result = await Effect.runPromiseExit(Stream.runCollect(stream))\n\n expect(result._tag).toBe(\"Failure\")\n })\n\n it(\"runs body finalizers when a Decision short-circuits the body\", async () => {\n const releases = await Effect.runPromise(\n Effect.gen(function* () {\n const releasesRef = yield* Ref.make<ReadonlyArray<number>>([])\n const stream = loop(0, (n: number) =>\n (n >= 1\n ? Stream.succeed(value(n)).pipe(Stream.concat(stop()))\n : Stream.succeed(value(n)).pipe(\n Stream.concat(next(n + 1)),\n Stream.concat(Stream.succeed(value(n + 10))),\n )\n ).pipe(Stream.ensuring(Ref.update(releasesRef, (values) => [...values, n]))),\n )\n\n const values = yield* Stream.runCollect(stream)\n expect(values).toEqual([0, 1])\n return yield* Ref.get(releasesRef)\n }),\n )\n\n expect(releases).toEqual([0, 1])\n })\n\n it(\"runs the active body finalizer when the downstream consumer is interrupted\", async () => {\n const releases = await Effect.runPromise(\n Effect.gen(function* () {\n const started = yield* Deferred.make<void>()\n const releasesRef = yield* Ref.make(0)\n const body = (): Stream.Stream<Step<number, never>> =>\n Stream.concat(\n Stream.fromEffect(Deferred.succeed(started, undefined).pipe(Effect.as(value(0)))),\n Stream.never,\n ).pipe(Stream.ensuring(Ref.update(releasesRef, (n) => n + 1)))\n const stream = loop(0, body)\n\n const fiber = yield* Effect.forkChild(Stream.runCollect(stream))\n yield* Deferred.await(started)\n yield* Fiber.interrupt(fiber)\n\n return yield* Ref.get(releasesRef)\n }),\n )\n\n expect(releases).toBe(1)\n })\n\n it(\"does not create a body scope if constructing the body stream defects\", async () => {\n const defect = new Error(\"body construction failed\")\n const result = await Effect.runPromiseExit(\n Stream.runCollect(\n loop(0, (): Stream.Stream<Step<number, never>> => {\n throw defect\n }),\n ),\n )\n\n expect(result._tag).toBe(\"Failure\")\n })\n})\n\ndescribe(\"Loop.loopWithState\", () => {\n it(\"exposes the final state in the SubscriptionRef after the stream completes\", async () => {\n const program = Effect.gen(function* () {\n const { stream, state } = yield* loopWithState(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n const values = yield* Stream.runCollect(stream)\n const finalState = yield* SubscriptionRef.get(state)\n return { values: Array.from(values), finalState }\n })\n\n const { values, finalState } = await Effect.runPromise(program)\n expect(values).toEqual([0, 1, 2, 3])\n // Last `next(state)` was `next(3)` before the iteration that emitted Stop.\n expect(finalState).toBe(3)\n })\n\n it(\"the state ref starts at `initial` and stays there if the loop stops without advancing\", async () => {\n const program = Effect.gen(function* () {\n const { stream, state } = yield* loopWithState({ count: 7 }, () => stop())\n yield* Stream.runDrain(stream)\n return yield* SubscriptionRef.get(state)\n })\n\n expect(await Effect.runPromise(program)).toEqual({ count: 7 })\n })\n\n it(\"a downstream consumer can read the live state between emitted values\", async () => {\n // Body emits one value per iteration, then advances. A `Stream.runForEach`\n // consumer reads the ref each time a value arrives — proving the ref\n // tracks loop state without the body needing to surface it.\n const program = Effect.gen(function* () {\n const { stream, state } = yield* loopWithState(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n const seen: Array<{ value: number; stateAfter: number }> = []\n yield* Stream.runForEach(stream, (v) =>\n Effect.gen(function* () {\n seen.push({ value: v, stateAfter: yield* SubscriptionRef.get(state) })\n }),\n )\n return seen\n })\n\n // For each iter `n`, the consumer reads the ref between values: it sees\n // the iteration's input state. The terminal iter (n=3) stops without\n // advancing, so its read still shows 3.\n expect(await Effect.runPromise(program)).toEqual([\n { value: 0, stateAfter: 0 },\n { value: 1, stateAfter: 1 },\n { value: 2, stateAfter: 2 },\n { value: 3, stateAfter: 3 },\n ])\n })\n\n it(\"SubscriptionRef.changes emits every state transition to a concurrent observer\", async () => {\n const program = Effect.gen(function* () {\n const start = yield* Latch.make(false)\n\n // Body waits on the latch in iter 0 so the observer can subscribe first.\n const { stream, state } = yield* loopWithState(0, (n: number) =>\n Effect.gen(function* () {\n if (n === 0) yield* Latch.await(start)\n return n >= 3 ? stop() : next(n + 1)\n }),\n )\n\n // Fork the observer; take 4 distinct states (initial + 3 transitions).\n const observerFiber = yield* Effect.forkChild(\n SubscriptionRef.changes(state).pipe(Stream.take(4), Stream.runCollect),\n )\n\n // Give the observer fiber a chance to actually subscribe before the\n // loop starts advancing the ref. Without this, the loop could finish\n // before the observer's pubsub subscription is in place.\n yield* Effect.sleep(\"10 millis\")\n\n yield* Latch.open(start)\n yield* Stream.runDrain(stream)\n\n return Array.from(yield* Fiber.join(observerFiber))\n })\n\n // initial 0, then next(1), next(2), next(3) — four distinct states.\n expect(await Effect.runPromise(program)).toEqual([0, 1, 2, 3])\n })\n\n it(\"does not interfere with the body's value stream\", async () => {\n const program = Effect.gen(function* () {\n const { stream } = yield* loopWithState(0, (n: number) =>\n n >= 3\n ? Stream.fromIterable([n]).pipe(Stream.map(value), Stream.concat(stop()))\n : Stream.fromIterable([n, n + 0.5]).pipe(Stream.map(value), Stream.concat(next(n + 1))),\n )\n return Array.from(yield* Stream.runCollect(stream))\n })\n\n expect(await Effect.runPromise(program)).toEqual([0, 0.5, 1, 1.5, 2, 2.5, 3])\n })\n})\n\ndescribe(\"Loop.loopOver\", () => {\n it(\"runs a multi-turn inner loop per input until the body emits stop\", async () => {\n // Per input: emit (input + turnsSoFar) twice, then stop. State counts\n // total turns ACROSS inputs. Demonstrates that `next(s)` continues with\n // the SAME input, multiple times per input — not one body call per item.\n const result = await Effect.runPromise(\n Stream.fromIterable([\"a\", \"b\"]).pipe(\n loopOver(0, (turns: number, input: string) => {\n if (turns >= 2 * (input === \"a\" ? 1 : 2)) return stop()\n return Stream.succeed(value(`${input}:${turns}`)).pipe(Stream.concat(next(turns + 1)))\n }),\n Stream.runCollect,\n ),\n )\n\n // input=\"a\": turns 0,1 → emit \"a:0\",\"a:1\"; turns=2 → stop. State threads.\n // input=\"b\": turns 2,3 → emit \"b:2\",\"b:3\"; turns=4 → stop.\n expect(result).toEqual([\"a:0\", \"a:1\", \"b:2\", \"b:3\"])\n })\n\n it(\"threads state across inputs (audio-pipeline shape)\", async () => {\n // History accumulates across inputs. Each input emits its joined view of\n // history+input, then `stop(state)` ends the inner loop AND carries the\n // updated history to the next input.\n const result = await Effect.runPromise(\n Stream.fromIterable([\"x\", \"y\", \"z\"]).pipe(\n loopOver([] as ReadonlyArray<string>, (history: ReadonlyArray<string>, input: string) =>\n Stream.succeed(value([...history, input].join(\",\"))).pipe(\n Stream.concat(stop([...history, input])),\n ),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\"x\", \"x,y\", \"x,y,z\"])\n })\n\n it(\"simulates a stream of documents with multi-turn tool calls per document\", async () => {\n // Document arrives → model \"thinks\" (one text turn) → calls a tool\n // (one tool turn) → emits final text (one text turn) → done.\n // Three turns per document, two documents.\n type Turn =\n | { readonly kind: \"text\"; readonly doc: string; readonly text: string }\n | { readonly kind: \"tool\"; readonly doc: string; readonly tool: string }\n type State = { readonly turn: number; readonly totalTurns: number }\n\n const result = await Effect.runPromise(\n Stream.fromIterable([\"doc1\", \"doc2\"]).pipe(\n loopOver({ turn: 0, totalTurns: 0 } as State, (state, doc: string) => {\n // Each document runs three turns then stops.\n if (state.turn === 0) {\n return Stream.succeed(value<Turn>({ kind: \"text\", doc, text: \"thinking\" })).pipe(\n Stream.concat(next({ turn: 1, totalTurns: state.totalTurns + 1 })),\n )\n }\n if (state.turn === 1) {\n return Stream.succeed(value<Turn>({ kind: \"tool\", doc, tool: \"search\" })).pipe(\n Stream.concat(next({ turn: 2, totalTurns: state.totalTurns + 1 })),\n )\n }\n // Final turn — `stop(state)` emits the final value, advances state\n // (reset turn to 0 for the next document, bump totalTurns), and\n // ends this document's inner loop in one shot.\n return Stream.succeed(value<Turn>({ kind: \"text\", doc, text: \"final\" })).pipe(\n Stream.concat(stop({ turn: 0, totalTurns: state.totalTurns + 1 })),\n )\n }),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\n { kind: \"text\", doc: \"doc1\", text: \"thinking\" },\n { kind: \"tool\", doc: \"doc1\", tool: \"search\" },\n { kind: \"text\", doc: \"doc1\", text: \"final\" },\n { kind: \"text\", doc: \"doc2\", text: \"thinking\" },\n { kind: \"tool\", doc: \"doc2\", tool: \"search\" },\n { kind: \"text\", doc: \"doc2\", text: \"final\" },\n ])\n })\n\n it(\"ends cleanly when the input stream ends mid-conversation\", async () => {\n // Single-input case: body advances via `next` then stops cleanly.\n const result = await Effect.runPromise(\n Stream.fromIterable([\"only\"]).pipe(\n loopOver(0, (turns: number, input: string) =>\n turns >= 2\n ? stop()\n : Stream.succeed(value(`${input}:${turns}`)).pipe(Stream.concat(next(turns + 1))),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\"only:0\", \"only:1\"])\n })\n\n it(\"body's `stop()` advances to the next input (does NOT halt the whole stream)\", async () => {\n // Three inputs, body always stops on its first emission. All three\n // are processed — `stop()` is per-input, not global. To halt the whole\n // stream, end the INPUT stream upstream.\n const result = await Effect.runPromise(\n Stream.fromIterable([1, 2, 3]).pipe(\n loopOver(0, (_state: number, input: number) =>\n Stream.succeed(value(input * 10)).pipe(Stream.concat(stop())),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([10, 20, 30])\n })\n\n it(\"data-first form (Function.dual) runs identically to data-last\", async () => {\n const inputs = Stream.fromIterable([1, 2])\n const result = await Effect.runPromise(\n Stream.runCollect(\n loopOver(inputs, 0, (state: number, input: number) =>\n state >= input\n ? stop()\n : Stream.succeed(value(state + input)).pipe(Stream.concat(next(state + 1))),\n ),\n ),\n )\n\n // input=1: state=0 → emit 1, state→1; state=1≥1 → stop.\n // input=2: state=1 → emit 3, state→2; state=2≥2 → stop.\n expect(result).toEqual([1, 3])\n })\n\n it(\"supports Effect-returning bodies (parity with loop)\", async () => {\n const result = await Effect.runPromise(\n Stream.fromIterable([\"a\"]).pipe(\n loopOver(0, (turns: number, input: string) =>\n Effect.gen(function* () {\n const cur = yield* Effect.succeed(turns)\n if (cur >= 2) return stop()\n return Stream.succeed(value(`${input}:${cur}`)).pipe(Stream.concat(next(cur + 1)))\n }),\n ),\n Stream.runCollect,\n ),\n )\n\n expect(result).toEqual([\"a:0\", \"a:1\"])\n })\n\n it(\"type: data-last (pipe) form preserves the body's E channel\", () => {\n const result = pipe(\n Stream.fromIterable([1]),\n loopOver(0, (_state: number, _input: number) =>\n Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null })),\n ),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited>()\n })\n\n it(\"type: data-first form preserves the body's E channel and unifies with input's E\", () => {\n const input: Stream.Stream<number, Error> = Stream.fail(new Error(\"boom\"))\n const result = loopOver(input, 0, (_state: number, _i: number) =>\n Stream.fail(new AiError.RateLimited({ provider: \"test\", raw: null })),\n )\n type E = typeof result extends Stream.Stream<unknown, infer X, unknown> ? X : never\n expectTypeOf<E>().toEqualTypeOf<AiError.RateLimited | Error>()\n })\n})\n"],"mappings":"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"}
@@ -1010,4 +1010,4 @@ var MagicString = class MagicString {
1010
1010
  //#endregion
1011
1011
  export { MagicString as default };
1012
1012
 
1013
- //# sourceMappingURL=magic-string.es-BgIV5Mu3.mjs.map
1013
+ //# sourceMappingURL=magic-string.es-Dk-MMA0F.mjs.map