@effect-uai/core 0.9.0 → 0.11.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 (196) hide show
  1. package/dist/{AiError-CrdR1EQi.d.mts → AiError-Bf1pq4BB.d.mts} +8 -3
  2. package/dist/{AiError-CrdR1EQi.d.mts.map → AiError-Bf1pq4BB.d.mts.map} +1 -1
  3. package/dist/{Audio-DDSKCkSe.d.mts → Audio-CR7CSljJ.d.mts} +2 -2
  4. package/dist/{Audio-DDSKCkSe.d.mts.map → Audio-CR7CSljJ.d.mts.map} +1 -1
  5. package/dist/{Image-C_Zjpwhc.d.mts → Image-C4vuBmu0.d.mts} +12 -12
  6. package/dist/{Image-C_Zjpwhc.d.mts.map → Image-C4vuBmu0.d.mts.map} +1 -1
  7. package/dist/{Items-CgKD6Npw.d.mts → Items-BWNu6VGp.d.mts} +118 -92
  8. package/dist/Items-BWNu6VGp.d.mts.map +1 -0
  9. package/dist/{Loop-B5_cqumi.d.mts → Loop-D8nWpowc.d.mts} +2 -2
  10. package/dist/{Loop-B5_cqumi.d.mts.map → Loop-D8nWpowc.d.mts.map} +1 -1
  11. package/dist/{Media-DOLyaygI.d.mts → Media-D_CpcM1Z.d.mts} +1 -1
  12. package/dist/{Media-DOLyaygI.d.mts.map → Media-D_CpcM1Z.d.mts.map} +1 -1
  13. package/dist/{StructuredFormat-CMJFD3sn.d.mts → StructuredFormat-DHaUJBdd.d.mts} +1 -1
  14. package/dist/{StructuredFormat-CMJFD3sn.d.mts.map → StructuredFormat-DHaUJBdd.d.mts.map} +1 -1
  15. package/dist/{Tool-0XUIT2A2.d.mts → Tool-CXFHCQrT.d.mts} +101 -16
  16. package/dist/Tool-CXFHCQrT.d.mts.map +1 -0
  17. package/dist/{ToolEvent-DYrAUJGs.d.mts → ToolEvent-nVijCrvm.d.mts} +2 -2
  18. package/dist/ToolEvent-nVijCrvm.d.mts.map +1 -0
  19. package/dist/{ToolResult-BZd-cEWW.d.mts → ToolResult-CQqKkcDa.d.mts} +10 -4
  20. package/dist/ToolResult-CQqKkcDa.d.mts.map +1 -0
  21. package/dist/{Toolkit-BKC8b8Xo.d.mts → Toolkit-BYPwwu-j.d.mts} +65 -24
  22. package/dist/Toolkit-BYPwwu-j.d.mts.map +1 -0
  23. package/dist/browser/Browser.d.mts +190 -0
  24. package/dist/browser/Browser.d.mts.map +1 -0
  25. package/dist/browser/Browser.mjs +34 -0
  26. package/dist/browser/Browser.mjs.map +1 -0
  27. package/dist/browser/BrowserError.d.mts +141 -0
  28. package/dist/browser/BrowserError.d.mts.map +1 -0
  29. package/dist/browser/BrowserError.mjs +89 -0
  30. package/dist/browser/BrowserError.mjs.map +1 -0
  31. package/dist/browser/BrowserTool.d.mts +59 -0
  32. package/dist/browser/BrowserTool.d.mts.map +1 -0
  33. package/dist/browser/BrowserTool.mjs +86 -0
  34. package/dist/browser/BrowserTool.mjs.map +1 -0
  35. package/dist/{dist-DWgRbDN3.mjs → dist-C0m0QnUP.mjs} +71 -30
  36. package/dist/dist-C0m0QnUP.mjs.map +1 -0
  37. package/dist/{dist-B04dlFHg.mjs → dist-CcRV3-A5.mjs} +8 -8
  38. package/dist/{dist-B04dlFHg.mjs.map → dist-CcRV3-A5.mjs.map} +1 -1
  39. package/dist/domain/AiError.d.mts +2 -2
  40. package/dist/domain/AiError.mjs +22 -3
  41. package/dist/domain/AiError.mjs.map +1 -1
  42. package/dist/domain/Audio.d.mts +1 -1
  43. package/dist/domain/Citation.d.mts +60 -0
  44. package/dist/domain/Citation.d.mts.map +1 -0
  45. package/dist/domain/Citation.mjs +7 -0
  46. package/dist/domain/Citation.mjs.map +1 -0
  47. package/dist/domain/Image.d.mts +1 -1
  48. package/dist/domain/Items.d.mts +1 -1
  49. package/dist/domain/Items.mjs +13 -3
  50. package/dist/domain/Items.mjs.map +1 -1
  51. package/dist/domain/Media.d.mts +1 -1
  52. package/dist/domain/Music.d.mts +1 -1
  53. package/dist/domain/Research.d.mts +37 -0
  54. package/dist/domain/Research.d.mts.map +1 -0
  55. package/dist/domain/Research.mjs +7 -0
  56. package/dist/domain/Research.mjs.map +1 -0
  57. package/dist/domain/Turn.d.mts +92 -10
  58. package/dist/domain/Turn.d.mts.map +1 -1
  59. package/dist/domain/Turn.mjs +8 -1
  60. package/dist/domain/Turn.mjs.map +1 -1
  61. package/dist/domain/Turn.test.mjs +1 -1
  62. package/dist/embedding-model/Embedding.d.mts +1 -1
  63. package/dist/embedding-model/EmbeddingModel.d.mts +1 -1
  64. package/dist/embedding-model/EmbeddingModel.mjs +2 -2
  65. package/dist/embedding-model/EmbeddingModel.mjs.map +1 -1
  66. package/dist/embedding-model/EmbeddingModel.test.mjs +1 -1
  67. package/dist/index.d.mts +22 -13
  68. package/dist/index.mjs +18 -9
  69. package/dist/job/Job.d.mts +80 -0
  70. package/dist/job/Job.d.mts.map +1 -0
  71. package/dist/job/Job.mjs +49 -0
  72. package/dist/job/Job.mjs.map +1 -0
  73. package/dist/language-model/LanguageModel.d.mts +4 -4
  74. package/dist/language-model/LanguageModel.mjs +2 -2
  75. package/dist/language-model/LanguageModel.mjs.map +1 -1
  76. package/dist/language-model/LanguageModel.test.mjs +1 -1
  77. package/dist/loop/Loop.d.mts +1 -1
  78. package/dist/loop/Loop.test.mjs +1 -1
  79. package/dist/music-generator/MusicGenerator.d.mts +2 -2
  80. package/dist/music-generator/MusicGenerator.mjs +4 -4
  81. package/dist/music-generator/MusicGenerator.mjs.map +1 -1
  82. package/dist/music-generator/MusicGenerator.test.mjs +1 -1
  83. package/dist/observability/Metrics.d.mts +1 -1
  84. package/dist/observability/Metrics.test.mjs +2 -2
  85. package/dist/observability/Telemetry.test.mjs +2 -2
  86. package/dist/research/DeepResearch.d.mts +71 -0
  87. package/dist/research/DeepResearch.d.mts.map +1 -0
  88. package/dist/research/DeepResearch.mjs +61 -0
  89. package/dist/research/DeepResearch.mjs.map +1 -0
  90. package/dist/retry/Retry.d.mts +1 -1
  91. package/dist/retry/Retry.test.mjs +1 -1
  92. package/dist/sandbox/Sandbox.mjs +18 -18
  93. package/dist/sandbox/Sandbox.mjs.map +1 -1
  94. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +2 -2
  95. package/dist/speech-synthesizer/SpeechSynthesizer.mjs +8 -8
  96. package/dist/speech-synthesizer/SpeechSynthesizer.mjs.map +1 -1
  97. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs +1 -1
  98. package/dist/streaming/JSONL.d.mts +3 -1
  99. package/dist/streaming/JSONL.d.mts.map +1 -1
  100. package/dist/streaming/JSONL.mjs +5 -11
  101. package/dist/streaming/JSONL.mjs.map +1 -1
  102. package/dist/streaming/JSONL.test.mjs +10 -1
  103. package/dist/streaming/JSONL.test.mjs.map +1 -1
  104. package/dist/streaming/SSE.d.mts +5 -3
  105. package/dist/streaming/SSE.d.mts.map +1 -1
  106. package/dist/streaming/SSE.mjs +28 -38
  107. package/dist/streaming/SSE.mjs.map +1 -1
  108. package/dist/streaming/SSE.test.mjs +54 -4
  109. package/dist/streaming/SSE.test.mjs.map +1 -1
  110. package/dist/structured-format/StructuredFormat.d.mts +1 -1
  111. package/dist/structured-format/StructuredFormat.test.mjs +1 -1
  112. package/dist/testing/MockMusicGenerator.d.mts +1 -1
  113. package/dist/testing/MockProvider.d.mts +1 -1
  114. package/dist/testing/MockSpeechSynthesizer.d.mts +1 -1
  115. package/dist/tool/Approval.d.mts +19 -7
  116. package/dist/tool/Approval.d.mts.map +1 -1
  117. package/dist/tool/Approval.mjs +18 -11
  118. package/dist/tool/Approval.mjs.map +1 -1
  119. package/dist/tool/Approval.test.mjs +47 -8
  120. package/dist/tool/Approval.test.mjs.map +1 -1
  121. package/dist/tool/HistoryCheck.d.mts +2 -2
  122. package/dist/tool/Tool.d.mts +2 -2
  123. package/dist/tool/Tool.mjs +112 -28
  124. package/dist/tool/Tool.mjs.map +1 -1
  125. package/dist/tool/Tool.test.mjs +127 -3
  126. package/dist/tool/Tool.test.mjs.map +1 -1
  127. package/dist/tool/ToolEvent.d.mts +1 -1
  128. package/dist/tool/ToolEvent.mjs +5 -0
  129. package/dist/tool/ToolEvent.mjs.map +1 -1
  130. package/dist/tool/ToolResult.d.mts +2 -2
  131. package/dist/tool/ToolResult.mjs +15 -6
  132. package/dist/tool/ToolResult.mjs.map +1 -1
  133. package/dist/tool/Toolkit.d.mts +2 -2
  134. package/dist/tool/Toolkit.mjs +62 -22
  135. package/dist/tool/Toolkit.mjs.map +1 -1
  136. package/dist/tool/Toolkit.test.mjs +207 -9
  137. package/dist/tool/Toolkit.test.mjs.map +1 -1
  138. package/dist/transcriber/Transcriber.d.mts +2 -2
  139. package/dist/transcriber/Transcriber.mjs +3 -3
  140. package/dist/transcriber/Transcriber.mjs.map +1 -1
  141. package/dist/transcriber/Transcriber.test.mjs +1 -1
  142. package/dist/web-read/WebRead.d.mts +44 -0
  143. package/dist/web-read/WebRead.d.mts.map +1 -0
  144. package/dist/web-read/WebRead.mjs +18 -0
  145. package/dist/web-read/WebRead.mjs.map +1 -0
  146. package/dist/web-read/WebReadTool.d.mts +57 -0
  147. package/dist/web-read/WebReadTool.d.mts.map +1 -0
  148. package/dist/web-read/WebReadTool.mjs +59 -0
  149. package/dist/web-read/WebReadTool.mjs.map +1 -0
  150. package/dist/web-search/WebSearch.d.mts +1 -1
  151. package/dist/web-search/WebSearch.mjs +1 -1
  152. package/dist/web-search/WebSearch.mjs.map +1 -1
  153. package/dist/web-search/WebSearchTool.d.mts +12 -6
  154. package/dist/web-search/WebSearchTool.d.mts.map +1 -1
  155. package/dist/web-search/WebSearchTool.mjs +10 -5
  156. package/dist/web-search/WebSearchTool.mjs.map +1 -1
  157. package/package.json +39 -3
  158. package/src/browser/Browser.ts +268 -0
  159. package/src/browser/BrowserError.ts +145 -0
  160. package/src/browser/BrowserTool.ts +161 -0
  161. package/src/domain/AiError.ts +27 -1
  162. package/src/domain/Citation.ts +64 -0
  163. package/src/domain/Items.ts +14 -4
  164. package/src/domain/Research.ts +42 -0
  165. package/src/domain/Turn.ts +26 -0
  166. package/src/embedding-model/EmbeddingModel.ts +2 -2
  167. package/src/index.ts +9 -0
  168. package/src/job/Job.ts +125 -0
  169. package/src/language-model/LanguageModel.ts +2 -2
  170. package/src/music-generator/MusicGenerator.ts +4 -4
  171. package/src/research/DeepResearch.ts +137 -0
  172. package/src/sandbox/Sandbox.ts +18 -18
  173. package/src/speech-synthesizer/SpeechSynthesizer.ts +8 -8
  174. package/src/streaming/JSONL.test.ts +19 -0
  175. package/src/streaming/JSONL.ts +6 -38
  176. package/src/streaming/SSE.test.ts +86 -3
  177. package/src/streaming/SSE.ts +36 -80
  178. package/src/tool/Approval.test.ts +55 -5
  179. package/src/tool/Approval.ts +72 -27
  180. package/src/tool/Tool.test.ts +151 -1
  181. package/src/tool/Tool.ts +263 -66
  182. package/src/tool/ToolEvent.ts +5 -0
  183. package/src/tool/ToolResult.ts +14 -8
  184. package/src/tool/Toolkit.test.ts +231 -2
  185. package/src/tool/Toolkit.ts +175 -62
  186. package/src/transcriber/Transcriber.ts +3 -3
  187. package/src/web-read/WebRead.ts +70 -0
  188. package/src/web-read/WebReadTool.ts +96 -0
  189. package/src/web-search/WebSearch.ts +1 -1
  190. package/src/web-search/WebSearchTool.ts +11 -5
  191. package/dist/Items-CgKD6Npw.d.mts.map +0 -1
  192. package/dist/Tool-0XUIT2A2.d.mts.map +0 -1
  193. package/dist/ToolEvent-DYrAUJGs.d.mts.map +0 -1
  194. package/dist/ToolResult-BZd-cEWW.d.mts.map +0 -1
  195. package/dist/Toolkit-BKC8b8Xo.d.mts.map +0 -1
  196. package/dist/dist-DWgRbDN3.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { assistantText, systemText, userText } from "./Items.mjs";
2
2
  import { assistantText as assistantText$1, assistantTexts } from "./Turn.mjs";
3
- import { a as describe, n as globalExpect, o as it } from "../dist-B04dlFHg.mjs";
3
+ import { c as it, n as globalExpect, o as describe } from "../dist-CcRV3-A5.mjs";
4
4
  //#region src/domain/Turn.test.ts
5
5
  const turnOf = (items) => ({
6
6
  items,
@@ -1,4 +1,4 @@
1
- import { i as ImageSource } from "../Image-C_Zjpwhc.mjs";
1
+ import { i as ImageSource } from "../Image-C4vuBmu0.mjs";
2
2
 
3
3
  //#region src/embedding-model/Embedding.d.ts
4
4
  declare namespace Embedding_d_exports {
@@ -1,4 +1,4 @@
1
- import { t as AiError } from "../AiError-CrdR1EQi.mjs";
1
+ import { t as AiError } from "../AiError-Bf1pq4BB.mjs";
2
2
  import { EmbedInput, EmbeddingFor, ResponseEncoding, Usage } from "./Embedding.mjs";
3
3
  import { Context, Effect } from "effect";
4
4
 
@@ -10,9 +10,9 @@ var EmbeddingModel_exports = /* @__PURE__ */ __exportAll({
10
10
  });
11
11
  var EmbeddingModel = class extends Context.Service()("@betalyra/effect-uai/EmbeddingModel") {};
12
12
  /** Embed a single input. */
13
- const embed = (request) => Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embed(request));
13
+ const embed = (request) => Effect.flatMap(EmbeddingModel, (m) => m.embed(request));
14
14
  /** Embed a batch in one provider call. Same `task` for every input. */
15
- const embedMany = (request) => Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embedMany(request));
15
+ const embedMany = (request) => Effect.flatMap(EmbeddingModel, (m) => m.embedMany(request));
16
16
  /**
17
17
  * Guard a requested `encoding` against a provider's supported set. Returns
18
18
  * `void` when the encoding is unset or supported, and fails
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddingModel.mjs","names":["AiError.Unsupported"],"sources":["../../src/embedding-model/EmbeddingModel.ts"],"sourcesContent":["import { Context, Effect } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { EmbeddingFor, EmbedInput, ResponseEncoding, Usage } from \"./Embedding.js\"\n\n/**\n * Output representation requested from the provider. Cross-provider dense\n * quantization only, the same vector at different storage cost:\n * - `float32`: universal default.\n * - `int8`: ~4x smaller, minimal recall loss on most benchmarks. Supported\n * by Cohere, Voyage, Jina (binary only), Mixedbread.\n * - `binary`: ~32x smaller, meaningful recall loss but pairs well with a\n * float32 reranker pass over a small candidate set.\n *\n * Non-dense representations (`sparse`, `multivector`) are a different vector\n * *structure*, not a storage option, and are produced by Jina only. They\n * live on `JinaEncoding`, not here (the same widening pattern `task` uses).\n * The response `Embedding` union still carries all arms, see\n * {@link ResponseEncoding}.\n *\n * Each provider's typed request narrows this to its supported set. On the\n * generic `EmbeddingModel` path, a provider that emits float32 only (OpenAI,\n * Gemini) rejects a non-float32 encoding with `AiError.Unsupported`\n * (bucket 1) via {@link assertEncoding}, rather than silently returning a\n * mislabeled float32 vector.\n */\nexport type EmbedEncoding = \"float32\" | \"int8\" | \"binary\"\n\n/**\n * Cross-provider single-embed request. Mirrors the shape of\n * `LanguageModel.CommonRequest`: cross-cutting fields here, vendor\n * specifics in the provider's typed request.\n *\n * Provider-specific extensions (Cohere widened `task` enum, Jina LoRA\n * tasks, Mixedbread free-form `prompt`, etc.) live in that provider's own\n * request interface, which extends this and narrows `model` / widens\n * `task`.\n */\nexport type CommonEmbedRequest = {\n readonly input: EmbedInput\n /**\n * Model identifier. Each provider narrows this to its typed literal\n * union, so code that yields a typed provider tag gets autocompletion.\n */\n readonly model: string\n /**\n * Retrieval-task hint. Applies to the input. OpenAI ignores this;\n * Mixedbread doesn't have it; Cohere v3+ requires it on the wire (typed\n * as required in `CohereEmbedRequest`). Provider-specific task enums\n * (classification, clustering, code retrieval, …) live on the\n * provider's own request type.\n */\n readonly task?: \"query\" | \"document\"\n /**\n * Matryoshka truncation. Default: provider's native dimension.\n * Discrete-value providers (Cohere, Vertex `multimodalembedding@001`)\n * narrow this to a literal union in their typed request.\n */\n readonly dimensions?: number\n /**\n * Output representation - see {@link EmbedEncoding}. Dense float32 is the\n * default; provider layers reject unsupported values up front with\n * `InvalidRequest`.\n */\n readonly encoding?: EmbedEncoding\n}\n\n/**\n * Cross-provider batch-embed request. One `task` for the whole batch -\n * mixed-task batches aren't a real provider feature (rerankers exist for\n * that).\n */\nexport type CommonEmbedManyRequest = Omit<CommonEmbedRequest, \"input\"> & {\n readonly inputs: ReadonlyArray<EmbedInput>\n}\n\n/**\n * Single-embed response. The `embedding` type is determined by the\n * request's `encoding` field via `EmbeddingFor<E>` — callers that don't\n * specify an encoding get a `Float32Embedding` directly with no runtime\n * narrowing. Defaults to `undefined` for back-compat with consumers that\n * use the bare `EmbedResponse` name.\n */\nexport type EmbedResponse<E extends ResponseEncoding | undefined = undefined> = {\n readonly embedding: EmbeddingFor<E>\n readonly usage: Usage\n}\n\n/** Batch-embed response. Same encoding rule as {@link EmbedResponse}. */\nexport type EmbedManyResponse<E extends ResponseEncoding | undefined = undefined> = {\n readonly embeddings: ReadonlyArray<EmbeddingFor<E>>\n readonly usage: Usage\n}\n\nexport type EmbeddingModelService = {\n readonly embed: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedResponse<E>, AiError.AiError>\n readonly embedMany: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedManyResponse<E>, AiError.AiError>\n}\n\nexport class EmbeddingModel extends Context.Service<EmbeddingModel, EmbeddingModelService>()(\n \"@betalyra/effect-uai/EmbeddingModel\",\n) {}\n\n/** Embed a single input. */\nexport const embed = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embed(request))\n\n/** Embed a batch in one provider call. Same `task` for every input. */\nexport const embedMany = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedManyResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel.asEffect(), (m) => m.embedMany(request))\n\n/**\n * Guard a requested `encoding` against a provider's supported set. Returns\n * `void` when the encoding is unset or supported, and fails\n * `AiError.Unsupported` (bucket 1) otherwise.\n *\n * Used by the generic-tag registration of providers that emit a strict\n * subset of `EmbedEncoding`: OpenAI / Gemini pass `[\"float32\"]`, Jina passes\n * `[\"float32\", \"binary\"]`. Without this guard, a non-supported encoding on\n * the generic path silently returns a float32 vector mislabeled as the\n * requested type (the `as`-cast lie), which breaks downstream storage and\n * vector math.\n */\nexport const assertEncoding = (\n encoding: EmbedEncoding | undefined,\n supported: ReadonlyArray<EmbedEncoding>,\n provider: string,\n): Effect.Effect<void, AiError.AiError> =>\n encoding === undefined || supported.includes(encoding)\n ? Effect.void\n : Effect.fail(\n new AiError.Unsupported({\n provider,\n capability: \"encoding\",\n reason: `${provider} emits ${supported.join(\" / \")} only; encoding=\"${encoding}\" is unavailable.`,\n }),\n )\n"],"mappings":";;;;;;;;;;AAsGA,IAAa,iBAAb,cAAoC,QAAQ,SAAgD,CAC1F,sCACD,CAAC;;AAGF,MAAa,SACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,MAAM,QAAQ,CAAC;;AAGpE,MAAa,aACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,UAAU,QAAQ,CAAC;;;;;;;;;;;;;AAcxE,MAAa,kBACX,UACA,WACA,aAEA,aAAa,KAAA,KAAa,UAAU,SAAS,SAAS,GAClD,OAAO,OACP,OAAO,KACL,IAAIA,YAAoB;CACtB;CACA,YAAY;CACZ,QAAQ,GAAG,SAAS,SAAS,UAAU,KAAK,MAAM,CAAC,mBAAmB,SAAS;CAChF,CAAC,CACH"}
1
+ {"version":3,"file":"EmbeddingModel.mjs","names":["AiError.Unsupported"],"sources":["../../src/embedding-model/EmbeddingModel.ts"],"sourcesContent":["import { Context, Effect } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { EmbeddingFor, EmbedInput, ResponseEncoding, Usage } from \"./Embedding.js\"\n\n/**\n * Output representation requested from the provider. Cross-provider dense\n * quantization only, the same vector at different storage cost:\n * - `float32`: universal default.\n * - `int8`: ~4x smaller, minimal recall loss on most benchmarks. Supported\n * by Cohere, Voyage, Jina (binary only), Mixedbread.\n * - `binary`: ~32x smaller, meaningful recall loss but pairs well with a\n * float32 reranker pass over a small candidate set.\n *\n * Non-dense representations (`sparse`, `multivector`) are a different vector\n * *structure*, not a storage option, and are produced by Jina only. They\n * live on `JinaEncoding`, not here (the same widening pattern `task` uses).\n * The response `Embedding` union still carries all arms, see\n * {@link ResponseEncoding}.\n *\n * Each provider's typed request narrows this to its supported set. On the\n * generic `EmbeddingModel` path, a provider that emits float32 only (OpenAI,\n * Gemini) rejects a non-float32 encoding with `AiError.Unsupported`\n * (bucket 1) via {@link assertEncoding}, rather than silently returning a\n * mislabeled float32 vector.\n */\nexport type EmbedEncoding = \"float32\" | \"int8\" | \"binary\"\n\n/**\n * Cross-provider single-embed request. Mirrors the shape of\n * `LanguageModel.CommonRequest`: cross-cutting fields here, vendor\n * specifics in the provider's typed request.\n *\n * Provider-specific extensions (Cohere widened `task` enum, Jina LoRA\n * tasks, Mixedbread free-form `prompt`, etc.) live in that provider's own\n * request interface, which extends this and narrows `model` / widens\n * `task`.\n */\nexport type CommonEmbedRequest = {\n readonly input: EmbedInput\n /**\n * Model identifier. Each provider narrows this to its typed literal\n * union, so code that yields a typed provider tag gets autocompletion.\n */\n readonly model: string\n /**\n * Retrieval-task hint. Applies to the input. OpenAI ignores this;\n * Mixedbread doesn't have it; Cohere v3+ requires it on the wire (typed\n * as required in `CohereEmbedRequest`). Provider-specific task enums\n * (classification, clustering, code retrieval, …) live on the\n * provider's own request type.\n */\n readonly task?: \"query\" | \"document\"\n /**\n * Matryoshka truncation. Default: provider's native dimension.\n * Discrete-value providers (Cohere, Vertex `multimodalembedding@001`)\n * narrow this to a literal union in their typed request.\n */\n readonly dimensions?: number\n /**\n * Output representation - see {@link EmbedEncoding}. Dense float32 is the\n * default; provider layers reject unsupported values up front with\n * `InvalidRequest`.\n */\n readonly encoding?: EmbedEncoding\n}\n\n/**\n * Cross-provider batch-embed request. One `task` for the whole batch -\n * mixed-task batches aren't a real provider feature (rerankers exist for\n * that).\n */\nexport type CommonEmbedManyRequest = Omit<CommonEmbedRequest, \"input\"> & {\n readonly inputs: ReadonlyArray<EmbedInput>\n}\n\n/**\n * Single-embed response. The `embedding` type is determined by the\n * request's `encoding` field via `EmbeddingFor<E>` — callers that don't\n * specify an encoding get a `Float32Embedding` directly with no runtime\n * narrowing. Defaults to `undefined` for back-compat with consumers that\n * use the bare `EmbedResponse` name.\n */\nexport type EmbedResponse<E extends ResponseEncoding | undefined = undefined> = {\n readonly embedding: EmbeddingFor<E>\n readonly usage: Usage\n}\n\n/** Batch-embed response. Same encoding rule as {@link EmbedResponse}. */\nexport type EmbedManyResponse<E extends ResponseEncoding | undefined = undefined> = {\n readonly embeddings: ReadonlyArray<EmbeddingFor<E>>\n readonly usage: Usage\n}\n\nexport type EmbeddingModelService = {\n readonly embed: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedResponse<E>, AiError.AiError>\n readonly embedMany: <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n ) => Effect.Effect<EmbedManyResponse<E>, AiError.AiError>\n}\n\nexport class EmbeddingModel extends Context.Service<EmbeddingModel, EmbeddingModelService>()(\n \"@betalyra/effect-uai/EmbeddingModel\",\n) {}\n\n/** Embed a single input. */\nexport const embed = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel, (m) => m.embed(request))\n\n/** Embed a batch in one provider call. Same `task` for every input. */\nexport const embedMany = <E extends EmbedEncoding | undefined = undefined>(\n request: Omit<CommonEmbedManyRequest, \"encoding\"> & { readonly encoding?: E },\n): Effect.Effect<EmbedManyResponse<E>, AiError.AiError, EmbeddingModel> =>\n Effect.flatMap(EmbeddingModel, (m) => m.embedMany(request))\n\n/**\n * Guard a requested `encoding` against a provider's supported set. Returns\n * `void` when the encoding is unset or supported, and fails\n * `AiError.Unsupported` (bucket 1) otherwise.\n *\n * Used by the generic-tag registration of providers that emit a strict\n * subset of `EmbedEncoding`: OpenAI / Gemini pass `[\"float32\"]`, Jina passes\n * `[\"float32\", \"binary\"]`. Without this guard, a non-supported encoding on\n * the generic path silently returns a float32 vector mislabeled as the\n * requested type (the `as`-cast lie), which breaks downstream storage and\n * vector math.\n */\nexport const assertEncoding = (\n encoding: EmbedEncoding | undefined,\n supported: ReadonlyArray<EmbedEncoding>,\n provider: string,\n): Effect.Effect<void, AiError.AiError> =>\n encoding === undefined || supported.includes(encoding)\n ? Effect.void\n : Effect.fail(\n new AiError.Unsupported({\n provider,\n capability: \"encoding\",\n reason: `${provider} emits ${supported.join(\" / \")} only; encoding=\"${encoding}\" is unavailable.`,\n }),\n )\n"],"mappings":";;;;;;;;;;AAsGA,IAAa,iBAAb,cAAoC,QAAQ,SAAgD,CAC1F,sCACD,CAAC;;AAGF,MAAa,SACX,YAEA,OAAO,QAAQ,iBAAiB,MAAM,EAAE,MAAM,QAAQ,CAAC;;AAGzD,MAAa,aACX,YAEA,OAAO,QAAQ,iBAAiB,MAAM,EAAE,UAAU,QAAQ,CAAC;;;;;;;;;;;;;AAc7D,MAAa,kBACX,UACA,WACA,aAEA,aAAa,KAAA,KAAa,UAAU,SAAS,SAAS,GAClD,OAAO,OACP,OAAO,KACL,IAAIA,YAAoB;CACtB;CACA,YAAY;CACZ,QAAQ,GAAG,SAAS,SAAS,UAAU,KAAK,MAAM,CAAC,mBAAmB,SAAS;CAChF,CAAC,CACH"}
@@ -1,5 +1,5 @@
1
1
  import { embed, embedMany } from "./EmbeddingModel.mjs";
2
- import { a as describe, o as it, t as import_dist } from "../dist-B04dlFHg.mjs";
2
+ import { c as it, o as describe, t as import_dist } from "../dist-CcRV3-A5.mjs";
3
3
  //#region src/embedding-model/EmbeddingModel.test.ts
4
4
  describe("EmbedResponse<E> conditional narrowing", () => {
5
5
  it("defaults to Float32Embedding when E is undefined", () => {
package/dist/index.d.mts CHANGED
@@ -1,20 +1,27 @@
1
+ import { t as BrowserError_d_exports } from "./browser/BrowserError.mjs";
2
+ import { t as Browser_d_exports } from "./browser/Browser.mjs";
3
+ import { a as Media_d_exports } from "./Media-D_CpcM1Z.mjs";
4
+ import { o as Image_d_exports } from "./Image-C4vuBmu0.mjs";
5
+ import { u as Items_d_exports } from "./Items-BWNu6VGp.mjs";
6
+ import { _ as Tool_d_exports } from "./Tool-CXFHCQrT.mjs";
7
+ import { t as BrowserTool_d_exports } from "./browser/BrowserTool.mjs";
1
8
  import { t as Capabilities_d_exports } from "./capabilities/Capabilities.mjs";
2
- import { n as AiError_d_exports } from "./AiError-CrdR1EQi.mjs";
3
- import { a as Media_d_exports } from "./Media-DOLyaygI.mjs";
4
- import { o as Audio_d_exports } from "./Audio-DDSKCkSe.mjs";
5
- import { o as Image_d_exports } from "./Image-C_Zjpwhc.mjs";
6
- import { u as Items_d_exports } from "./Items-CgKD6Npw.mjs";
9
+ import { n as AiError_d_exports } from "./AiError-Bf1pq4BB.mjs";
10
+ import { o as Audio_d_exports } from "./Audio-CR7CSljJ.mjs";
11
+ import { t as Citation_d_exports } from "./domain/Citation.mjs";
7
12
  import { t as Music_d_exports } from "./domain/Music.mjs";
8
- import { t as Transcript_d_exports } from "./domain/Transcript.mjs";
9
- import { a as StructuredFormat_d_exports } from "./StructuredFormat-CMJFD3sn.mjs";
13
+ import { t as Job_d_exports } from "./job/Job.mjs";
14
+ import { a as StructuredFormat_d_exports } from "./StructuredFormat-DHaUJBdd.mjs";
10
15
  import { t as Turn_d_exports } from "./domain/Turn.mjs";
16
+ import { t as Research_d_exports } from "./domain/Research.mjs";
17
+ import { t as Transcript_d_exports } from "./domain/Transcript.mjs";
11
18
  import { t as Embedding_d_exports } from "./embedding-model/Embedding.mjs";
12
19
  import { t as EmbeddingModel_d_exports } from "./embedding-model/EmbeddingModel.mjs";
13
- import { t as Loop_d_exports } from "./Loop-B5_cqumi.mjs";
14
- import { m as Tool_d_exports } from "./Tool-0XUIT2A2.mjs";
15
- import { n as ToolResult_d_exports } from "./ToolResult-BZd-cEWW.mjs";
16
- import { n as ToolEvent_d_exports } from "./ToolEvent-DYrAUJGs.mjs";
17
- import { c as Toolkit_d_exports } from "./Toolkit-BKC8b8Xo.mjs";
20
+ import { t as DeepResearch_d_exports } from "./research/DeepResearch.mjs";
21
+ import { t as Loop_d_exports } from "./Loop-D8nWpowc.mjs";
22
+ import { n as ToolResult_d_exports } from "./ToolResult-CQqKkcDa.mjs";
23
+ import { n as ToolEvent_d_exports } from "./ToolEvent-nVijCrvm.mjs";
24
+ import { l as Toolkit_d_exports } from "./Toolkit-BYPwwu-j.mjs";
18
25
  import { t as LanguageModel_d_exports } from "./language-model/LanguageModel.mjs";
19
26
  import { t as MusicGenerator_d_exports } from "./music-generator/MusicGenerator.mjs";
20
27
  import { t as Memory_d_exports } from "./sandbox/Memory.mjs";
@@ -24,6 +31,8 @@ import { t as SandboxImage_d_exports } from "./sandbox/SandboxImage.mjs";
24
31
  import { t as SandboxNetwork_d_exports } from "./sandbox/SandboxNetwork.mjs";
25
32
  import { t as SpeechSynthesizer_d_exports } from "./speech-synthesizer/SpeechSynthesizer.mjs";
26
33
  import { t as Transcriber_d_exports } from "./transcriber/Transcriber.mjs";
34
+ import { t as WebRead_d_exports } from "./web-read/WebRead.mjs";
35
+ import { t as WebReadTool_d_exports } from "./web-read/WebReadTool.mjs";
27
36
  import { t as WebSearch_d_exports } from "./web-search/WebSearch.mjs";
28
37
  import { t as WebSearchTool_d_exports } from "./web-search/WebSearchTool.mjs";
29
38
  import { t as Vector_d_exports } from "./math/Vector.mjs";
@@ -35,4 +44,4 @@ import { t as Lines_d_exports } from "./streaming/Lines.mjs";
35
44
  import { t as SSE_d_exports } from "./streaming/SSE.mjs";
36
45
  import { t as Metrics_d_exports } from "./observability/Metrics.mjs";
37
46
  import { t as Telemetry_d_exports } from "./observability/Telemetry.mjs";
38
- export { AiError_d_exports as AiError, Approval_d_exports as Approval, Audio_d_exports as Audio, Capabilities_d_exports as Capabilities, Embedding_d_exports as Embedding, EmbeddingModel_d_exports as EmbeddingModel, HistoryCheck_d_exports as HistoryCheck, Image_d_exports as Image, Items_d_exports as Items, JSONL_d_exports as JSONL, LanguageModel_d_exports as LanguageModel, Lines_d_exports as Lines, Loop_d_exports as Loop, Media_d_exports as Media, Memory_d_exports as Memory, Metrics_d_exports as Metrics, Music_d_exports as Music, MusicGenerator_d_exports as MusicGenerator, Retry_d_exports as Retry, SSE_d_exports as SSE, Sandbox_d_exports as Sandbox, SandboxError_d_exports as SandboxError, SandboxImage_d_exports as SandboxImage, SandboxNetwork_d_exports as SandboxNetwork, SpeechSynthesizer_d_exports as SpeechSynthesizer, StructuredFormat_d_exports as StructuredFormat, Telemetry_d_exports as Telemetry, Tool_d_exports as Tool, ToolEvent_d_exports as ToolEvent, ToolResult_d_exports as ToolResult, Toolkit_d_exports as Toolkit, Transcriber_d_exports as Transcriber, Transcript_d_exports as Transcript, Turn_d_exports as Turn, Vector_d_exports as Vector, WebSearch_d_exports as WebSearch, WebSearchTool_d_exports as WebSearchTool };
47
+ export { AiError_d_exports as AiError, Approval_d_exports as Approval, Audio_d_exports as Audio, Browser_d_exports as Browser, BrowserError_d_exports as BrowserError, BrowserTool_d_exports as BrowserTool, Capabilities_d_exports as Capabilities, Citation_d_exports as Citation, DeepResearch_d_exports as DeepResearch, Embedding_d_exports as Embedding, EmbeddingModel_d_exports as EmbeddingModel, HistoryCheck_d_exports as HistoryCheck, Image_d_exports as Image, Items_d_exports as Items, JSONL_d_exports as JSONL, Job_d_exports as Job, LanguageModel_d_exports as LanguageModel, Lines_d_exports as Lines, Loop_d_exports as Loop, Media_d_exports as Media, Memory_d_exports as Memory, Metrics_d_exports as Metrics, Music_d_exports as Music, MusicGenerator_d_exports as MusicGenerator, Research_d_exports as Research, Retry_d_exports as Retry, SSE_d_exports as SSE, Sandbox_d_exports as Sandbox, SandboxError_d_exports as SandboxError, SandboxImage_d_exports as SandboxImage, SandboxNetwork_d_exports as SandboxNetwork, SpeechSynthesizer_d_exports as SpeechSynthesizer, StructuredFormat_d_exports as StructuredFormat, Telemetry_d_exports as Telemetry, Tool_d_exports as Tool, ToolEvent_d_exports as ToolEvent, ToolResult_d_exports as ToolResult, Toolkit_d_exports as Toolkit, Transcriber_d_exports as Transcriber, Transcript_d_exports as Transcript, Turn_d_exports as Turn, Vector_d_exports as Vector, WebRead_d_exports as WebRead, WebReadTool_d_exports as WebReadTool, WebSearch_d_exports as WebSearch, WebSearchTool_d_exports as WebSearchTool };
package/dist/index.mjs CHANGED
@@ -1,13 +1,25 @@
1
1
  import { t as AiError_exports } from "./domain/AiError.mjs";
2
2
  import { t as Audio_exports } from "./domain/Audio.mjs";
3
- import { t as Capabilities_exports } from "./capabilities/Capabilities.mjs";
3
+ import { t as Browser_exports } from "./browser/Browser.mjs";
4
+ import { t as BrowserError_exports } from "./browser/BrowserError.mjs";
4
5
  import { t as Image_exports } from "./domain/Image.mjs";
5
6
  import { t as Items_exports } from "./domain/Items.mjs";
7
+ import { t as ToolResult_exports } from "./tool/ToolResult.mjs";
8
+ import { t as Tool_exports } from "./tool/Tool.mjs";
9
+ import { t as StructuredFormat_exports } from "./structured-format/StructuredFormat.mjs";
10
+ import { t as Turn_exports } from "./domain/Turn.mjs";
11
+ import { t as Loop_exports } from "./loop/Loop.mjs";
12
+ import { t as ToolEvent_exports } from "./tool/ToolEvent.mjs";
13
+ import { t as Toolkit_exports } from "./tool/Toolkit.mjs";
14
+ import { t as BrowserTool_exports } from "./browser/BrowserTool.mjs";
15
+ import { t as Capabilities_exports } from "./capabilities/Capabilities.mjs";
16
+ import { t as Citation_exports } from "./domain/Citation.mjs";
17
+ import { t as Job_exports } from "./job/Job.mjs";
18
+ import { t as DeepResearch_exports } from "./research/DeepResearch.mjs";
6
19
  import { t as Media_exports } from "./domain/Media.mjs";
7
20
  import { t as Music_exports } from "./domain/Music.mjs";
21
+ import { t as Research_exports } from "./domain/Research.mjs";
8
22
  import { t as Transcript_exports } from "./domain/Transcript.mjs";
9
- import { t as StructuredFormat_exports } from "./structured-format/StructuredFormat.mjs";
10
- import { t as Turn_exports } from "./domain/Turn.mjs";
11
23
  import { t as Embedding_exports } from "./embedding-model/Embedding.mjs";
12
24
  import { t as EmbeddingModel_exports } from "./embedding-model/EmbeddingModel.mjs";
13
25
  import { t as LanguageModel_exports } from "./language-model/LanguageModel.mjs";
@@ -19,15 +31,12 @@ import { t as SandboxImage_exports } from "./sandbox/SandboxImage.mjs";
19
31
  import { t as SandboxNetwork_exports } from "./sandbox/SandboxNetwork.mjs";
20
32
  import { t as SpeechSynthesizer_exports } from "./speech-synthesizer/SpeechSynthesizer.mjs";
21
33
  import { t as Transcriber_exports } from "./transcriber/Transcriber.mjs";
34
+ import { t as WebRead_exports } from "./web-read/WebRead.mjs";
35
+ import { t as WebReadTool_exports } from "./web-read/WebReadTool.mjs";
22
36
  import { t as WebSearch_exports } from "./web-search/WebSearch.mjs";
23
- import { t as Tool_exports } from "./tool/Tool.mjs";
24
37
  import { t as WebSearchTool_exports } from "./web-search/WebSearchTool.mjs";
25
38
  import { t as Vector_exports } from "./math/Vector.mjs";
26
- import { t as Loop_exports } from "./loop/Loop.mjs";
27
39
  import { t as Retry_exports } from "./retry/Retry.mjs";
28
- import { t as ToolResult_exports } from "./tool/ToolResult.mjs";
29
- import { t as ToolEvent_exports } from "./tool/ToolEvent.mjs";
30
- import { t as Toolkit_exports } from "./tool/Toolkit.mjs";
31
40
  import { t as Approval_exports } from "./tool/Approval.mjs";
32
41
  import { t as HistoryCheck_exports } from "./tool/HistoryCheck.mjs";
33
42
  import { t as JSONL_exports } from "./streaming/JSONL.mjs";
@@ -35,4 +44,4 @@ import { t as Lines_exports } from "./streaming/Lines.mjs";
35
44
  import { t as SSE_exports } from "./streaming/SSE.mjs";
36
45
  import { t as Metrics_exports } from "./observability/Metrics.mjs";
37
46
  import { t as Telemetry_exports } from "./observability/Telemetry.mjs";
38
- export { AiError_exports as AiError, Approval_exports as Approval, Audio_exports as Audio, Capabilities_exports as Capabilities, Embedding_exports as Embedding, EmbeddingModel_exports as EmbeddingModel, HistoryCheck_exports as HistoryCheck, Image_exports as Image, Items_exports as Items, JSONL_exports as JSONL, LanguageModel_exports as LanguageModel, Lines_exports as Lines, Loop_exports as Loop, Media_exports as Media, Memory_exports as Memory, Metrics_exports as Metrics, Music_exports as Music, MusicGenerator_exports as MusicGenerator, Retry_exports as Retry, SSE_exports as SSE, Sandbox_exports as Sandbox, SandboxError_exports as SandboxError, SandboxImage_exports as SandboxImage, SandboxNetwork_exports as SandboxNetwork, SpeechSynthesizer_exports as SpeechSynthesizer, StructuredFormat_exports as StructuredFormat, Telemetry_exports as Telemetry, Tool_exports as Tool, ToolEvent_exports as ToolEvent, ToolResult_exports as ToolResult, Toolkit_exports as Toolkit, Transcriber_exports as Transcriber, Transcript_exports as Transcript, Turn_exports as Turn, Vector_exports as Vector, WebSearch_exports as WebSearch, WebSearchTool_exports as WebSearchTool };
47
+ export { AiError_exports as AiError, Approval_exports as Approval, Audio_exports as Audio, Browser_exports as Browser, BrowserError_exports as BrowserError, BrowserTool_exports as BrowserTool, Capabilities_exports as Capabilities, Citation_exports as Citation, DeepResearch_exports as DeepResearch, Embedding_exports as Embedding, EmbeddingModel_exports as EmbeddingModel, HistoryCheck_exports as HistoryCheck, Image_exports as Image, Items_exports as Items, JSONL_exports as JSONL, Job_exports as Job, LanguageModel_exports as LanguageModel, Lines_exports as Lines, Loop_exports as Loop, Media_exports as Media, Memory_exports as Memory, Metrics_exports as Metrics, Music_exports as Music, MusicGenerator_exports as MusicGenerator, Research_exports as Research, Retry_exports as Retry, SSE_exports as SSE, Sandbox_exports as Sandbox, SandboxError_exports as SandboxError, SandboxImage_exports as SandboxImage, SandboxNetwork_exports as SandboxNetwork, SpeechSynthesizer_exports as SpeechSynthesizer, StructuredFormat_exports as StructuredFormat, Telemetry_exports as Telemetry, Tool_exports as Tool, ToolEvent_exports as ToolEvent, ToolResult_exports as ToolResult, Toolkit_exports as Toolkit, Transcriber_exports as Transcriber, Transcript_exports as Transcript, Turn_exports as Turn, Vector_exports as Vector, WebRead_exports as WebRead, WebReadTool_exports as WebReadTool, WebSearch_exports as WebSearch, WebSearchTool_exports as WebSearchTool };
@@ -0,0 +1,80 @@
1
+ import { t as AiError } from "../AiError-Bf1pq4BB.mjs";
2
+ import { Duration, Effect } from "effect";
3
+
4
+ //#region src/job/Job.d.ts
5
+ declare namespace Job_d_exports {
6
+ export { JobConfig, JobOps, JobRef, JobState, collect, isSettled, jobRef, run };
7
+ }
8
+ /**
9
+ * Normalized state of a provider-hosted background job. Implementors map their
10
+ * provider's status vocabulary onto these four states. The terminal states
11
+ * carry their payload: `Succeeded` the collected result, `Failed` an optional
12
+ * reason and the raw provider error. This mirrors the wire, where a single
13
+ * poll response returns both status and (when done) the result.
14
+ */
15
+ type JobState<A> = {
16
+ readonly _tag: "Pending";
17
+ } | {
18
+ readonly _tag: "Running";
19
+ } | {
20
+ readonly _tag: "Succeeded";
21
+ readonly result: A;
22
+ } | {
23
+ readonly _tag: "Failed";
24
+ readonly reason?: string;
25
+ readonly raw?: unknown;
26
+ };
27
+ /** The two states that end a poll loop. */
28
+ declare const isSettled: <A>(state: JobState<A>) => state is Extract<JobState<A>, {
29
+ _tag: "Succeeded" | "Failed";
30
+ }>;
31
+ declare const ResultType: unique symbol;
32
+ /**
33
+ * Opaque, provider-tagged handle to a running background job. Jobs can run for
34
+ * minutes and outlive a single process, so the handle is detachable: submit
35
+ * now, collect later. `provider` tags who owns `id`.
36
+ *
37
+ * Parameterized by the result type `A` it collects to, so a ref cannot be
38
+ * crossed between capabilities (a `JobRef<Turn>` is not a `JobRef<VideoResult>`).
39
+ * The brand is phantom: the runtime value is just `{ _tag, provider, id }`, so
40
+ * a ref stays plain serializable data for persistence across restarts.
41
+ */
42
+ type JobRef<A = unknown> = {
43
+ readonly _tag: "JobRef";
44
+ readonly provider: string;
45
+ readonly id: string;
46
+ readonly [ResultType]?: A;
47
+ };
48
+ declare const jobRef: <A = unknown>(provider: string, id: string) => JobRef<A>;
49
+ /**
50
+ * The three wire operations a poll-based async job supplies. `run` / `collect`
51
+ * drive the submit -> poll -> settle cadence around them, so an implementor
52
+ * states only its provider calls, not the loop. `poll` returns the current
53
+ * `JobState`, carrying the result in `Succeeded`. Generic over the collected
54
+ * `Result`.
55
+ */
56
+ type JobOps<Result> = {
57
+ readonly submit: Effect.Effect<JobRef<Result>, AiError>;
58
+ readonly poll: (ref: JobRef<Result>) => Effect.Effect<JobState<Result>, AiError>;
59
+ readonly cancel: (ref: JobRef<Result>) => Effect.Effect<void, AiError>;
60
+ };
61
+ type JobConfig = {
62
+ /** Cadence between status fetches. Default 10 seconds, jittered. */readonly pollInterval?: Duration.Input; /** Overall wait cap; exceeding it fails `Timeout`. Default 45 minutes. */
63
+ readonly timeout?: Duration.Input;
64
+ };
65
+ /**
66
+ * Poll `poll(ref)` on a jittered fixed cadence until the job settles, then
67
+ * return the result or fail `GenerationFailed`. Bounded by `timeout`, which
68
+ * fails `Timeout` if the job never settles. Takes the poll op alone (not the
69
+ * full `JobOps`) so a detached `collect(ref)` needs no submit-bound request.
70
+ */
71
+ declare const collect: <Result>(poll: (ref: JobRef<Result>) => Effect.Effect<JobState<Result>, AiError>, ref: JobRef<Result>, config?: JobConfig) => Effect.Effect<Result, AiError>;
72
+ /**
73
+ * Submit, then poll to completion. Best-effort cancels the server job if the
74
+ * caller interrupts (where the provider supports it). The one-call path; use
75
+ * `ops.submit` + `collect` directly for the detached case.
76
+ */
77
+ declare const run: <Result>(ops: JobOps<Result>, config?: JobConfig) => Effect.Effect<Result, AiError>;
78
+ //#endregion
79
+ export { JobConfig, JobOps, JobRef, JobState, collect, isSettled, jobRef, run, Job_d_exports as t };
80
+ //# sourceMappingURL=Job.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Job.d.mts","names":[],"sources":["../../src/job/Job.ts"],"mappings":";;;;;;;;;;;;;;KAcY,QAAA;EAAA,SACG,IAAA;AAAA;EAAA,SACA,IAAA;AAAA;EAAA,SACA,IAAA;EAAA,SAA4B,MAAA,EAAQ,CAAA;AAAA;EAAA,SACpC,IAAA;EAAA,SAAyB,MAAA;EAAA,SAA0B,GAAA;AAAA;;cAGrD,SAAA,MACX,KAAA,EAAO,QAAA,CAAS,CAAA,MACf,KAAA,IAAS,OAAA,CAAQ,QAAA,CAAS,CAAA;EAAM,IAAA;AAAA;AAAA,cAGrB,UAAA;;;;;AALd;;;;;;KAiBY,MAAA;EAAA,SACD,IAAA;EAAA,SACA,QAAA;EAAA,SACA,EAAA;EAAA,UACC,UAAA,IAAc,CAAA;AAAA;AAAA,cAGb,MAAA,gBAAuB,QAAA,UAAkB,EAAA,aAAa,MAAA,CAAO,CAAA;;;;;;;;KAiB9D,MAAA;EAAA,SACD,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,OAAA;EAAA,SACtC,IAAA,GAAO,GAAA,EAAK,MAAA,CAAO,MAAA,MAAY,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,OAAA;EAAA,SAC/D,MAAA,GAAS,GAAA,EAAK,MAAA,CAAO,MAAA,MAAY,MAAA,CAAO,MAAA,OAAa,OAAA;AAAA;AAAA,KAGpD,SAAA;EA9BA,6EAgCD,YAAA,GAAe,QAAA,CAAS,KAAA,EAhCjB;EAAA,SAkCP,OAAA,GAAU,QAAA,CAAS,KAAA;AAAA;;;;;;;cAYjB,OAAA,WACX,IAAA,GAAO,GAAA,EAAK,MAAA,CAAO,MAAA,MAAY,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,OAAA,GAC/D,GAAA,EAAK,MAAA,CAAO,MAAA,GACZ,MAAA,GAAS,SAAA,KACR,MAAA,CAAO,MAAA,CAAO,MAAA,EAAQ,OAAA;AA3CzB;;;;;AAAA,cAuEa,GAAA,WACX,GAAA,EAAK,MAAA,CAAO,MAAA,GACZ,MAAA,GAAS,SAAA,KACR,MAAA,CAAO,MAAA,CAAO,MAAA,EAAQ,OAAA"}
@@ -0,0 +1,49 @@
1
+ import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
2
+ import { GenerationFailed, Timeout } from "../domain/AiError.mjs";
3
+ import { Effect, Schedule } from "effect";
4
+ //#region src/job/Job.ts
5
+ var Job_exports = /* @__PURE__ */ __exportAll({
6
+ collect: () => collect,
7
+ isSettled: () => isSettled,
8
+ jobRef: () => jobRef,
9
+ run: () => run
10
+ });
11
+ /** The two states that end a poll loop. */
12
+ const isSettled = (state) => state._tag === "Succeeded" || state._tag === "Failed";
13
+ const jobRef = (provider, id) => ({
14
+ _tag: "JobRef",
15
+ provider,
16
+ id
17
+ });
18
+ const DEFAULT_POLL_INTERVAL = "10 seconds";
19
+ const DEFAULT_TIMEOUT = "45 minutes";
20
+ /**
21
+ * Poll `poll(ref)` on a jittered fixed cadence until the job settles, then
22
+ * return the result or fail `GenerationFailed`. Bounded by `timeout`, which
23
+ * fails `Timeout` if the job never settles. Takes the poll op alone (not the
24
+ * full `JobOps`) so a detached `collect(ref)` needs no submit-bound request.
25
+ */
26
+ const collect = (poll, ref, config) => poll(ref).pipe(Effect.repeat({
27
+ schedule: Schedule.jittered(Schedule.spaced(config?.pollInterval ?? DEFAULT_POLL_INTERVAL)),
28
+ until: isSettled
29
+ }), Effect.flatMap((state) => state._tag === "Succeeded" ? Effect.succeed(state.result) : Effect.fail(new GenerationFailed({
30
+ provider: ref.provider,
31
+ message: state._tag === "Failed" ? state.reason ?? "job failed" : "job failed",
32
+ raw: state._tag === "Failed" ? state.raw ?? ref : ref
33
+ }))), Effect.timeoutOrElse({
34
+ duration: config?.timeout ?? DEFAULT_TIMEOUT,
35
+ orElse: () => Effect.fail(new Timeout({
36
+ provider: ref.provider,
37
+ raw: ref
38
+ }))
39
+ }));
40
+ /**
41
+ * Submit, then poll to completion. Best-effort cancels the server job if the
42
+ * caller interrupts (where the provider supports it). The one-call path; use
43
+ * `ops.submit` + `collect` directly for the detached case.
44
+ */
45
+ const run = (ops, config) => ops.submit.pipe(Effect.flatMap((ref) => collect(ops.poll, ref, config).pipe(Effect.onInterrupt(() => Effect.ignore(ops.cancel(ref))))));
46
+ //#endregion
47
+ export { collect, isSettled, jobRef, run, Job_exports as t };
48
+
49
+ //# sourceMappingURL=Job.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Job.mjs","names":["AiError.GenerationFailed","AiError.Timeout"],"sources":["../../src/job/Job.ts"],"sourcesContent":["import { Duration, Effect, Schedule } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\n\n// ---------------------------------------------------------------------------\n// Status + handle\n// ---------------------------------------------------------------------------\n\n/**\n * Normalized state of a provider-hosted background job. Implementors map their\n * provider's status vocabulary onto these four states. The terminal states\n * carry their payload: `Succeeded` the collected result, `Failed` an optional\n * reason and the raw provider error. This mirrors the wire, where a single\n * poll response returns both status and (when done) the result.\n */\nexport type JobState<A> =\n | { readonly _tag: \"Pending\" }\n | { readonly _tag: \"Running\" }\n | { readonly _tag: \"Succeeded\"; readonly result: A }\n | { readonly _tag: \"Failed\"; readonly reason?: string; readonly raw?: unknown }\n\n/** The two states that end a poll loop. */\nexport const isSettled = <A>(\n state: JobState<A>,\n): state is Extract<JobState<A>, { _tag: \"Succeeded\" | \"Failed\" }> =>\n state._tag === \"Succeeded\" || state._tag === \"Failed\"\n\ndeclare const ResultType: unique symbol\n\n/**\n * Opaque, provider-tagged handle to a running background job. Jobs can run for\n * minutes and outlive a single process, so the handle is detachable: submit\n * now, collect later. `provider` tags who owns `id`.\n *\n * Parameterized by the result type `A` it collects to, so a ref cannot be\n * crossed between capabilities (a `JobRef<Turn>` is not a `JobRef<VideoResult>`).\n * The brand is phantom: the runtime value is just `{ _tag, provider, id }`, so\n * a ref stays plain serializable data for persistence across restarts.\n */\nexport type JobRef<A = unknown> = {\n readonly _tag: \"JobRef\"\n readonly provider: string\n readonly id: string\n readonly [ResultType]?: A\n}\n\nexport const jobRef = <A = unknown>(provider: string, id: string): JobRef<A> => ({\n _tag: \"JobRef\",\n provider,\n id,\n})\n\n// ---------------------------------------------------------------------------\n// Poll driver\n// ---------------------------------------------------------------------------\n\n/**\n * The three wire operations a poll-based async job supplies. `run` / `collect`\n * drive the submit -> poll -> settle cadence around them, so an implementor\n * states only its provider calls, not the loop. `poll` returns the current\n * `JobState`, carrying the result in `Succeeded`. Generic over the collected\n * `Result`.\n */\nexport type JobOps<Result> = {\n readonly submit: Effect.Effect<JobRef<Result>, AiError.AiError>\n readonly poll: (ref: JobRef<Result>) => Effect.Effect<JobState<Result>, AiError.AiError>\n readonly cancel: (ref: JobRef<Result>) => Effect.Effect<void, AiError.AiError>\n}\n\nexport type JobConfig = {\n /** Cadence between status fetches. Default 10 seconds, jittered. */\n readonly pollInterval?: Duration.Input\n /** Overall wait cap; exceeding it fails `Timeout`. Default 45 minutes. */\n readonly timeout?: Duration.Input\n}\n\nconst DEFAULT_POLL_INTERVAL: Duration.Input = \"10 seconds\"\nconst DEFAULT_TIMEOUT: Duration.Input = \"45 minutes\"\n\n/**\n * Poll `poll(ref)` on a jittered fixed cadence until the job settles, then\n * return the result or fail `GenerationFailed`. Bounded by `timeout`, which\n * fails `Timeout` if the job never settles. Takes the poll op alone (not the\n * full `JobOps`) so a detached `collect(ref)` needs no submit-bound request.\n */\nexport const collect = <Result>(\n poll: (ref: JobRef<Result>) => Effect.Effect<JobState<Result>, AiError.AiError>,\n ref: JobRef<Result>,\n config?: JobConfig,\n): Effect.Effect<Result, AiError.AiError> =>\n poll(ref).pipe(\n Effect.repeat({\n schedule: Schedule.jittered(Schedule.spaced(config?.pollInterval ?? DEFAULT_POLL_INTERVAL)),\n until: isSettled,\n }),\n Effect.flatMap((state) =>\n state._tag === \"Succeeded\"\n ? Effect.succeed(state.result)\n : Effect.fail(\n new AiError.GenerationFailed({\n provider: ref.provider,\n message: state._tag === \"Failed\" ? (state.reason ?? \"job failed\") : \"job failed\",\n raw: state._tag === \"Failed\" ? (state.raw ?? ref) : ref,\n }),\n ),\n ),\n Effect.timeoutOrElse({\n duration: config?.timeout ?? DEFAULT_TIMEOUT,\n orElse: () => Effect.fail(new AiError.Timeout({ provider: ref.provider, raw: ref })),\n }),\n )\n\n/**\n * Submit, then poll to completion. Best-effort cancels the server job if the\n * caller interrupts (where the provider supports it). The one-call path; use\n * `ops.submit` + `collect` directly for the detached case.\n */\nexport const run = <Result>(\n ops: JobOps<Result>,\n config?: JobConfig,\n): Effect.Effect<Result, AiError.AiError> =>\n ops.submit.pipe(\n Effect.flatMap((ref) =>\n collect(ops.poll, ref, config).pipe(Effect.onInterrupt(() => Effect.ignore(ops.cancel(ref)))),\n ),\n )\n"],"mappings":";;;;;;;;;;;AAqBA,MAAa,aACX,UAEA,MAAM,SAAS,eAAe,MAAM,SAAS;AAqB/C,MAAa,UAAuB,UAAkB,QAA2B;CAC/E,MAAM;CACN;CACA;CACD;AA0BD,MAAM,wBAAwC;AAC9C,MAAM,kBAAkC;;;;;;;AAQxC,MAAa,WACX,MACA,KACA,WAEA,KAAK,IAAI,CAAC,KACR,OAAO,OAAO;CACZ,UAAU,SAAS,SAAS,SAAS,OAAO,QAAQ,gBAAgB,sBAAsB,CAAC;CAC3F,OAAO;CACR,CAAC,EACF,OAAO,SAAS,UACd,MAAM,SAAS,cACX,OAAO,QAAQ,MAAM,OAAO,GAC5B,OAAO,KACL,IAAIA,iBAAyB;CAC3B,UAAU,IAAI;CACd,SAAS,MAAM,SAAS,WAAY,MAAM,UAAU,eAAgB;CACpE,KAAK,MAAM,SAAS,WAAY,MAAM,OAAO,MAAO;CACrD,CAAC,CACH,CACN,EACD,OAAO,cAAc;CACnB,UAAU,QAAQ,WAAW;CAC7B,cAAc,OAAO,KAAK,IAAIC,QAAgB;EAAE,UAAU,IAAI;EAAU,KAAK;EAAK,CAAC,CAAC;CACrF,CAAC,CACH;;;;;;AAOH,MAAa,OACX,KACA,WAEA,IAAI,OAAO,KACT,OAAO,SAAS,QACd,QAAQ,IAAI,MAAM,KAAK,OAAO,CAAC,KAAK,OAAO,kBAAkB,OAAO,OAAO,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,CAC9F,CACF"}
@@ -1,8 +1,8 @@
1
- import { t as AiError } from "../AiError-CrdR1EQi.mjs";
2
- import { o as HistoryItem } from "../Items-CgKD6Npw.mjs";
3
- import { i as StructuredFormat } from "../StructuredFormat-CMJFD3sn.mjs";
1
+ import { o as HistoryItem } from "../Items-BWNu6VGp.mjs";
2
+ import { t as AiError } from "../AiError-Bf1pq4BB.mjs";
3
+ import { i as StructuredFormat } from "../StructuredFormat-DHaUJBdd.mjs";
4
4
  import { Turn, TurnEvent } from "../domain/Turn.mjs";
5
- import { o as Toolkit } from "../Toolkit-BKC8b8Xo.mjs";
5
+ import { o as Toolkit } from "../Toolkit-BYPwwu-j.mjs";
6
6
  import { Context, Effect, Stream } from "effect";
7
7
 
8
8
  //#region src/language-model/LanguageModel.d.ts
@@ -13,14 +13,14 @@ var LanguageModel = class extends Context.Service()("@betalyra/effect-uai/Langua
13
13
  /**
14
14
  * Stream the deltas of a single turn.
15
15
  */
16
- const streamTurn = (request) => Stream.unwrap(Effect.map(LanguageModel.asEffect(), (m) => m.streamTurn(request)));
16
+ const streamTurn = (request) => Stream.unwrap(Effect.map(LanguageModel, (m) => m.streamTurn(request)));
17
17
  /**
18
18
  * Drain a single turn and return the assembled `Turn`. Delegates to the
19
19
  * service's `turn` method — providers with a native complete endpoint
20
20
  * can override; the rest get the default streamTurn-drain via
21
21
  * {@link turnFromStream}.
22
22
  */
23
- const turn = (request) => Effect.flatMap(LanguageModel.asEffect(), (m) => m.turn(request));
23
+ const turn = (request) => Effect.flatMap(LanguageModel, (m) => m.turn(request));
24
24
  /**
25
25
  * Build a `turn` implementation from a `streamTurn` implementation.
26
26
  * Providers without a native non-streaming endpoint use this to
@@ -1 +1 @@
1
- {"version":3,"file":"LanguageModel.mjs","names":["Arr","AiError.IncompleteTurn"],"sources":["../../src/language-model/LanguageModel.ts"],"sourcesContent":["import { Array as Arr, Context, Effect, Option, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { HistoryItem } from \"../domain/Items.js\"\nimport type * as StructuredFormat from \"../structured-format/StructuredFormat.js\"\nimport type { Toolkit } from \"../tool/Toolkit.js\"\nimport { isTurnComplete, type Turn, type TurnEvent } from \"../domain/Turn.js\"\n\n/**\n * Cross-provider request shape. Every call carries its own `history` and\n * `model` - models are not bound at layer construction. Anything specific\n * to a single provider (reasoning effort, prompt caching, store flags,\n * ...) lives in that provider's own request interface, which extends this.\n */\nexport type CommonRequest = {\n readonly history: ReadonlyArray<HistoryItem>\n /**\n * Model identifier. Each provider narrows this to its typed literal union,\n * so code that yields a typed provider tag gets autocompletion.\n */\n readonly model: string\n /**\n * The model-visible tools for this request, as a `Toolkit`. The provider\n * renders it to wire descriptors (`Tool.descriptorsOf`); omit it for a turn\n * with no tools.\n */\n readonly tools?: Toolkit\n readonly toolChoice?:\n | \"auto\"\n | \"required\"\n | \"none\"\n | { readonly type: \"function\"; readonly name: string }\n readonly temperature?: number\n readonly topP?: number\n readonly maxOutputTokens?: number\n /**\n * Schema-bound JSON output. The provider constrains the wire to match the\n * schema; pair with `Turn.decodeStructured` for runtime validation. Supported\n * across all current providers (OpenAI Responses json_schema, Anthropic\n * `output_config`, Gemini `responseJsonSchema`).\n */\n readonly structured?: StructuredFormat.StructuredFormat<unknown>\n}\n\nexport type LanguageModelService = {\n readonly streamTurn: (request: CommonRequest) => Stream.Stream<TurnEvent, AiError.AiError>\n /**\n * Drain a single turn and return the assembled `Turn` from the\n * terminal `TurnComplete` event. Fails with `IncompleteTurn` if the\n * stream ends without one.\n *\n * Most providers derive this from `streamTurn` via\n * {@link turnFromStream}; providers with a native non-streaming\n * endpoint may override with a cheaper direct call.\n */\n readonly turn: (request: CommonRequest) => Effect.Effect<Turn, AiError.AiError>\n}\n\nexport class LanguageModel extends Context.Service<LanguageModel, LanguageModelService>()(\n \"@betalyra/effect-uai/LanguageModel\",\n) {}\n\n/**\n * Stream the deltas of a single turn.\n */\nexport const streamTurn = (\n request: CommonRequest,\n): Stream.Stream<TurnEvent, AiError.AiError, LanguageModel> =>\n Stream.unwrap(Effect.map(LanguageModel.asEffect(), (m) => m.streamTurn(request)))\n\n/**\n * Drain a single turn and return the assembled `Turn`. Delegates to the\n * service's `turn` method — providers with a native complete endpoint\n * can override; the rest get the default streamTurn-drain via\n * {@link turnFromStream}.\n */\nexport const turn = (request: CommonRequest): Effect.Effect<Turn, AiError.AiError, LanguageModel> =>\n Effect.flatMap(LanguageModel.asEffect(), (m) => m.turn(request))\n\n/**\n * Build a `turn` implementation from a `streamTurn` implementation.\n * Providers without a native non-streaming endpoint use this to\n * populate the service's `turn` field. Generic over the request type so\n * provider-typed services (with their narrowed request) can reuse it.\n */\nexport const turnFromStream =\n <Req>(streamTurn: (request: Req) => Stream.Stream<TurnEvent, AiError.AiError>) =>\n (request: Req): Effect.Effect<Turn, AiError.AiError> =>\n streamTurn(request).pipe(\n Stream.runCollect,\n Effect.flatMap((events) =>\n Arr.findLast(events, isTurnComplete).pipe(\n Option.match({\n onNone: () => Effect.fail(new AiError.IncompleteTurn({})),\n onSome: (e) => Effect.succeed(e.turn),\n }),\n ),\n ),\n )\n"],"mappings":";;;;;;;;;;;AAyDA,IAAa,gBAAb,cAAmC,QAAQ,SAA8C,CACvF,qCACD,CAAC;;;;AAKF,MAAa,cACX,YAEA,OAAO,OAAO,OAAO,IAAI,cAAc,UAAU,GAAG,MAAM,EAAE,WAAW,QAAQ,CAAC,CAAC;;;;;;;AAQnF,MAAa,QAAQ,YACnB,OAAO,QAAQ,cAAc,UAAU,GAAG,MAAM,EAAE,KAAK,QAAQ,CAAC;;;;;;;AAQlE,MAAa,kBACL,gBACL,YACC,WAAW,QAAQ,CAAC,KAClB,OAAO,YACP,OAAO,SAAS,WACdA,MAAI,SAAS,QAAQ,eAAe,CAAC,KACnC,OAAO,MAAM;CACX,cAAc,OAAO,KAAK,IAAIC,eAAuB,EAAE,CAAC,CAAC;CACzD,SAAS,MAAM,OAAO,QAAQ,EAAE,KAAK;CACtC,CAAC,CACH,CACF,CACF"}
1
+ {"version":3,"file":"LanguageModel.mjs","names":["Arr","AiError.IncompleteTurn"],"sources":["../../src/language-model/LanguageModel.ts"],"sourcesContent":["import { Array as Arr, Context, Effect, Option, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { HistoryItem } from \"../domain/Items.js\"\nimport type * as StructuredFormat from \"../structured-format/StructuredFormat.js\"\nimport type { Toolkit } from \"../tool/Toolkit.js\"\nimport { isTurnComplete, type Turn, type TurnEvent } from \"../domain/Turn.js\"\n\n/**\n * Cross-provider request shape. Every call carries its own `history` and\n * `model` - models are not bound at layer construction. Anything specific\n * to a single provider (reasoning effort, prompt caching, store flags,\n * ...) lives in that provider's own request interface, which extends this.\n */\nexport type CommonRequest = {\n readonly history: ReadonlyArray<HistoryItem>\n /**\n * Model identifier. Each provider narrows this to its typed literal union,\n * so code that yields a typed provider tag gets autocompletion.\n */\n readonly model: string\n /**\n * The model-visible tools for this request, as a `Toolkit`. The provider\n * renders it to wire descriptors (`Tool.descriptorsOf`); omit it for a turn\n * with no tools.\n */\n readonly tools?: Toolkit\n readonly toolChoice?:\n | \"auto\"\n | \"required\"\n | \"none\"\n | { readonly type: \"function\"; readonly name: string }\n readonly temperature?: number\n readonly topP?: number\n readonly maxOutputTokens?: number\n /**\n * Schema-bound JSON output. The provider constrains the wire to match the\n * schema; pair with `Turn.decodeStructured` for runtime validation. Supported\n * across all current providers (OpenAI Responses json_schema, Anthropic\n * `output_config`, Gemini `responseJsonSchema`).\n */\n readonly structured?: StructuredFormat.StructuredFormat<unknown>\n}\n\nexport type LanguageModelService = {\n readonly streamTurn: (request: CommonRequest) => Stream.Stream<TurnEvent, AiError.AiError>\n /**\n * Drain a single turn and return the assembled `Turn` from the\n * terminal `TurnComplete` event. Fails with `IncompleteTurn` if the\n * stream ends without one.\n *\n * Most providers derive this from `streamTurn` via\n * {@link turnFromStream}; providers with a native non-streaming\n * endpoint may override with a cheaper direct call.\n */\n readonly turn: (request: CommonRequest) => Effect.Effect<Turn, AiError.AiError>\n}\n\nexport class LanguageModel extends Context.Service<LanguageModel, LanguageModelService>()(\n \"@betalyra/effect-uai/LanguageModel\",\n) {}\n\n/**\n * Stream the deltas of a single turn.\n */\nexport const streamTurn = (\n request: CommonRequest,\n): Stream.Stream<TurnEvent, AiError.AiError, LanguageModel> =>\n Stream.unwrap(Effect.map(LanguageModel, (m) => m.streamTurn(request)))\n\n/**\n * Drain a single turn and return the assembled `Turn`. Delegates to the\n * service's `turn` method — providers with a native complete endpoint\n * can override; the rest get the default streamTurn-drain via\n * {@link turnFromStream}.\n */\nexport const turn = (request: CommonRequest): Effect.Effect<Turn, AiError.AiError, LanguageModel> =>\n Effect.flatMap(LanguageModel, (m) => m.turn(request))\n\n/**\n * Build a `turn` implementation from a `streamTurn` implementation.\n * Providers without a native non-streaming endpoint use this to\n * populate the service's `turn` field. Generic over the request type so\n * provider-typed services (with their narrowed request) can reuse it.\n */\nexport const turnFromStream =\n <Req>(streamTurn: (request: Req) => Stream.Stream<TurnEvent, AiError.AiError>) =>\n (request: Req): Effect.Effect<Turn, AiError.AiError> =>\n streamTurn(request).pipe(\n Stream.runCollect,\n Effect.flatMap((events) =>\n Arr.findLast(events, isTurnComplete).pipe(\n Option.match({\n onNone: () => Effect.fail(new AiError.IncompleteTurn({})),\n onSome: (e) => Effect.succeed(e.turn),\n }),\n ),\n ),\n )\n"],"mappings":";;;;;;;;;;;AAyDA,IAAa,gBAAb,cAAmC,QAAQ,SAA8C,CACvF,qCACD,CAAC;;;;AAKF,MAAa,cACX,YAEA,OAAO,OAAO,OAAO,IAAI,gBAAgB,MAAM,EAAE,WAAW,QAAQ,CAAC,CAAC;;;;;;;AAQxE,MAAa,QAAQ,YACnB,OAAO,QAAQ,gBAAgB,MAAM,EAAE,KAAK,QAAQ,CAAC;;;;;;;AAQvD,MAAa,kBACL,gBACL,YACC,WAAW,QAAQ,CAAC,KAClB,OAAO,YACP,OAAO,SAAS,WACdA,MAAI,SAAS,QAAQ,eAAe,CAAC,KACnC,OAAO,MAAM;CACX,cAAc,OAAO,KAAK,IAAIC,eAAuB,EAAE,CAAC,CAAC;CACzD,SAAS,MAAM,OAAO,QAAQ,EAAE,KAAK;CACtC,CAAC,CACH,CACF,CACF"}
@@ -2,7 +2,7 @@ import { IncompleteTurn, RateLimited } from "../domain/AiError.mjs";
2
2
  import { assistantText, userText } from "../domain/Items.mjs";
3
3
  import { TurnEvent } from "../domain/Turn.mjs";
4
4
  import { LanguageModel, turn, turnFromStream } from "./LanguageModel.mjs";
5
- import { a as describe, n as globalExpect, o as it } from "../dist-B04dlFHg.mjs";
5
+ import { c as it, n as globalExpect, o as describe } from "../dist-CcRV3-A5.mjs";
6
6
  import { layer } from "../testing/MockProvider.mjs";
7
7
  import { Cause, Effect, Exit, Layer, Option, Stream } from "effect";
8
8
  //#region src/language-model/LanguageModel.test.ts
@@ -1,2 +1,2 @@
1
- import { a as StopWith, c as loopOver, d as onTurnComplete, f as stop, i as Stop, l as loopWithState, n as Next, o as Value, p as value, r as Step, s as loop, u as next } from "../Loop-B5_cqumi.mjs";
1
+ import { a as StopWith, c as loopOver, d as onTurnComplete, f as stop, i as Stop, l as loopWithState, n as Next, o as Value, p as value, r as Step, s as loop, u as next } from "../Loop-D8nWpowc.mjs";
2
2
  export { Next, Step, Stop, StopWith, Value, loop, loopOver, loopWithState, next, onTurnComplete, stop, value };
@@ -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 { a as describe, n as globalExpect, o as it, t as import_dist } from "../dist-B04dlFHg.mjs";
4
+ import { c as it, n as globalExpect, o as describe, t as import_dist } from "../dist-CcRV3-A5.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", () => {
@@ -1,5 +1,5 @@
1
- import { t as AiError } from "../AiError-CrdR1EQi.mjs";
2
- import { n as AudioChunk } from "../Audio-DDSKCkSe.mjs";
1
+ import { t as AiError } from "../AiError-Bf1pq4BB.mjs";
2
+ import { n as AudioChunk } from "../Audio-CR7CSljJ.mjs";
3
3
  import { CommonGenerateMusicRequest, CommonStreamGenerateMusicRequest, GenerateResult, MusicResult, MusicSection, MusicSessionControl, MusicSessionInput, MusicStreamEvent, Watermark, WeightedPrompt } from "../domain/Music.mjs";
4
4
  import { Context, Effect, Stream } from "effect";
5
5
 
@@ -21,9 +21,9 @@ var MusicGenerator = class extends Context.Service()("@betalyra/effect-uai/Music
21
21
  */
22
22
  var MusicInteractiveSession = class extends Context.Service()("@betalyra/effect-uai/capability/MusicInteractiveSession") {};
23
23
  /** One-shot generation. Returns the full `GenerateResult`. */
24
- const generate = (request) => Effect.flatMap(MusicGenerator.asEffect(), (s) => s.generate(request));
24
+ const generate = (request) => Effect.flatMap(MusicGenerator, (s) => s.generate(request));
25
25
  /** Prompt in, audio chunks out. */
26
- const streamGeneration = (request) => Stream.unwrap(Effect.map(MusicGenerator.asEffect(), (s) => s.streamGeneration(request)));
26
+ const streamGeneration = (request) => Stream.unwrap(Effect.map(MusicGenerator, (s) => s.streamGeneration(request)));
27
27
  /**
28
28
  * Bidirectional generation. Dual-arity: pipeable (data-last) and
29
29
  * direct (data-first). Requires `MusicInteractiveSession` in R,
@@ -49,8 +49,8 @@ const streamGeneration = (request) => Stream.unwrap(Effect.map(MusicGenerator.as
49
49
  * ```
50
50
  */
51
51
  const streamGenerationFrom = Function.dual(2, (input, request) => Stream.unwrap(Effect.gen(function* () {
52
- const s = yield* MusicGenerator.asEffect();
53
- yield* MusicInteractiveSession.asEffect();
52
+ const s = yield* MusicGenerator;
53
+ yield* MusicInteractiveSession;
54
54
  return s.streamGenerationFrom(input, request);
55
55
  })));
56
56
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"MusicGenerator.mjs","names":[],"sources":["../../src/music-generator/MusicGenerator.ts"],"sourcesContent":["import { Context, Effect, Function, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n GenerateResult,\n MusicSessionInput,\n MusicStreamEvent,\n} from \"../domain/Music.js\"\nimport type { AudioChunk } from \"../domain/Audio.js\"\n\nexport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n GenerateResult,\n MusicResult,\n MusicSection,\n MusicSessionControl,\n MusicSessionInput,\n MusicStreamEvent,\n Watermark,\n WeightedPrompt,\n} from \"../domain/Music.js\"\n\nexport type MusicGeneratorService = {\n /**\n * One-shot. Prompt in, full audio bytes out. Universally supported.\n * Async/poll-based providers (Suno, Mureka) hide their poll loop\n * inside the adapter, caller still sees a single `Effect`.\n *\n * Returns `GenerateResult` with `primary` plus a `variants` array.\n * Suno and Mureka always return 2 tracks; every other provider\n * returns 1 (and `primary === variants[0]`).\n */\n readonly generate: (\n request: CommonGenerateMusicRequest,\n ) => Effect.Effect<GenerateResult, AiError.AiError>\n /**\n * Prompt in, audio chunks streamed out. Providers without a native\n * chunked-output endpoint (Lyria 3 sync, Mureka, MiniMax, Stable\n * Audio) emulate this by calling `generate` and emitting a single\n * `AudioChunk`, first-class, no `Unsupported`.\n */\n readonly streamGeneration: (\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n /**\n * Bidirectional session: a `Stream` of `MusicSessionInput` (prompts\n * + playback control) flows in, a `Stream` of `MusicStreamEvent`\n * flows out. The session WS / RPC is acquired on first pull and\n * released when the output stream is finalized via `Stream.scoped`.\n *\n * Cross-provider callers send `prompts` (steer the active\n * generation) and `control` (play / pause / stop / reset) — the two\n * actions that converge across interactive-media protocols.\n * Provider-specific model knobs (Lyria RealTime's density /\n * brightness / mute-stems / BPM / scale, etc.) live on the\n * provider-typed service (`LyriaRealtimeGenerator.streamGenerationFrom`),\n * which extends this union with its own `config` variant.\n *\n * Output is `MusicStreamEvent`: `audio` chunks alongside in-band\n * `warning` and `filteredPrompt` events the model emits server-side.\n *\n * Gated by the `MusicInteractiveSession` capability marker on the\n * top-level helper. Providers without bidirectional support don't\n * ship the marker, so calls fail at `Effect.provide` with a type\n * error.\n */\n readonly streamGenerationFrom: <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<MusicStreamEvent, AiError.AiError | E, R>\n}\n\nexport class MusicGenerator extends Context.Service<MusicGenerator, MusicGeneratorService>()(\n \"@betalyra/effect-uai/MusicGenerator\",\n) {}\n\n/**\n * Capability marker, provided by provider layers whose\n * `streamGenerationFrom` is wired up at the wire level. Currently only\n * Lyria RealTime (via the BidiGenerateMusic WebSocket) ships it.\n * Calling `streamGenerationFrom` while only a non-interactive Layer is\n * in scope fails at `Effect.provide` with a type error.\n *\n * Phantom: the value is `void`; providers register with\n * `Layer.succeed(MusicInteractiveSession, undefined)`.\n */\nexport class MusicInteractiveSession extends Context.Service<MusicInteractiveSession, void>()(\n \"@betalyra/effect-uai/capability/MusicInteractiveSession\",\n) {}\n\n/** One-shot generation. Returns the full `GenerateResult`. */\nexport const generate = (\n request: CommonGenerateMusicRequest,\n): Effect.Effect<GenerateResult, AiError.AiError, MusicGenerator> =>\n Effect.flatMap(MusicGenerator.asEffect(), (s) => s.generate(request))\n\n/** Prompt in, audio chunks out. */\nexport const streamGeneration = (\n request: CommonStreamGenerateMusicRequest,\n): Stream.Stream<AudioChunk, AiError.AiError, MusicGenerator> =>\n Stream.unwrap(Effect.map(MusicGenerator.asEffect(), (s) => s.streamGeneration(request)))\n\n/**\n * Bidirectional generation. Dual-arity: pipeable (data-last) and\n * direct (data-first). Requires `MusicInteractiveSession` in R,\n * providers without bidirectional support are a type error at provide\n * time.\n *\n * On the cross-provider surface, `input` is `Stream<unknown>` and\n * output is `Stream<MusicStreamEvent>`. Use the provider-typed\n * service (`LyriaRealtimeGenerator`) when you want to construct\n * typed session messages.\n *\n * @example\n * ```ts\n * // Generic surface (opaque input):\n * const audio = inputs.pipe(\n * MusicGenerator.streamGenerationFrom({ model: \"lyria-realtime-exp\", prompt: \"\" }),\n * )\n *\n * // Lyria-typed surface (full config knobs):\n * const audio = inputs.pipe(\n * LyriaRealtimeGenerator.streamGenerationFrom({ model: \"lyria-realtime-exp\", prompt: \"\" }),\n * )\n * ```\n */\nexport const streamGenerationFrom: {\n (\n request: CommonStreamGenerateMusicRequest,\n ): <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n ) => Stream.Stream<\n MusicStreamEvent,\n AiError.AiError | E,\n R | MusicGenerator | MusicInteractiveSession\n >\n <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ): Stream.Stream<\n MusicStreamEvent,\n AiError.AiError | E,\n R | MusicGenerator | MusicInteractiveSession\n >\n} = Function.dual(\n 2,\n <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ): Stream.Stream<\n MusicStreamEvent,\n AiError.AiError | E,\n R | MusicGenerator | MusicInteractiveSession\n > =>\n Stream.unwrap(\n Effect.gen(function* () {\n const s = yield* MusicGenerator.asEffect()\n yield* MusicInteractiveSession.asEffect()\n return s.streamGenerationFrom(input, request)\n }),\n ),\n)\n"],"mappings":";;;;;;;;;;AA0EA,IAAa,iBAAb,cAAoC,QAAQ,SAAgD,CAC1F,sCACD,CAAC;;;;;;;;;;;AAYF,IAAa,0BAAb,cAA6C,QAAQ,SAAwC,CAC3F,0DACD,CAAC;;AAGF,MAAa,YACX,YAEA,OAAO,QAAQ,eAAe,UAAU,GAAG,MAAM,EAAE,SAAS,QAAQ,CAAC;;AAGvE,MAAa,oBACX,YAEA,OAAO,OAAO,OAAO,IAAI,eAAe,UAAU,GAAG,MAAM,EAAE,iBAAiB,QAAQ,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0B1F,MAAa,uBAkBT,SAAS,KACX,IAEE,OACA,YAMA,OAAO,OACL,OAAO,IAAI,aAAa;CACtB,MAAM,IAAI,OAAO,eAAe,UAAU;AAC1C,QAAO,wBAAwB,UAAU;AACzC,QAAO,EAAE,qBAAqB,OAAO,QAAQ;EAC7C,CACH,CACJ"}
1
+ {"version":3,"file":"MusicGenerator.mjs","names":[],"sources":["../../src/music-generator/MusicGenerator.ts"],"sourcesContent":["import { Context, Effect, Function, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n GenerateResult,\n MusicSessionInput,\n MusicStreamEvent,\n} from \"../domain/Music.js\"\nimport type { AudioChunk } from \"../domain/Audio.js\"\n\nexport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n GenerateResult,\n MusicResult,\n MusicSection,\n MusicSessionControl,\n MusicSessionInput,\n MusicStreamEvent,\n Watermark,\n WeightedPrompt,\n} from \"../domain/Music.js\"\n\nexport type MusicGeneratorService = {\n /**\n * One-shot. Prompt in, full audio bytes out. Universally supported.\n * Async/poll-based providers (Suno, Mureka) hide their poll loop\n * inside the adapter, caller still sees a single `Effect`.\n *\n * Returns `GenerateResult` with `primary` plus a `variants` array.\n * Suno and Mureka always return 2 tracks; every other provider\n * returns 1 (and `primary === variants[0]`).\n */\n readonly generate: (\n request: CommonGenerateMusicRequest,\n ) => Effect.Effect<GenerateResult, AiError.AiError>\n /**\n * Prompt in, audio chunks streamed out. Providers without a native\n * chunked-output endpoint (Lyria 3 sync, Mureka, MiniMax, Stable\n * Audio) emulate this by calling `generate` and emitting a single\n * `AudioChunk`, first-class, no `Unsupported`.\n */\n readonly streamGeneration: (\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n /**\n * Bidirectional session: a `Stream` of `MusicSessionInput` (prompts\n * + playback control) flows in, a `Stream` of `MusicStreamEvent`\n * flows out. The session WS / RPC is acquired on first pull and\n * released when the output stream is finalized via `Stream.scoped`.\n *\n * Cross-provider callers send `prompts` (steer the active\n * generation) and `control` (play / pause / stop / reset) — the two\n * actions that converge across interactive-media protocols.\n * Provider-specific model knobs (Lyria RealTime's density /\n * brightness / mute-stems / BPM / scale, etc.) live on the\n * provider-typed service (`LyriaRealtimeGenerator.streamGenerationFrom`),\n * which extends this union with its own `config` variant.\n *\n * Output is `MusicStreamEvent`: `audio` chunks alongside in-band\n * `warning` and `filteredPrompt` events the model emits server-side.\n *\n * Gated by the `MusicInteractiveSession` capability marker on the\n * top-level helper. Providers without bidirectional support don't\n * ship the marker, so calls fail at `Effect.provide` with a type\n * error.\n */\n readonly streamGenerationFrom: <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<MusicStreamEvent, AiError.AiError | E, R>\n}\n\nexport class MusicGenerator extends Context.Service<MusicGenerator, MusicGeneratorService>()(\n \"@betalyra/effect-uai/MusicGenerator\",\n) {}\n\n/**\n * Capability marker, provided by provider layers whose\n * `streamGenerationFrom` is wired up at the wire level. Currently only\n * Lyria RealTime (via the BidiGenerateMusic WebSocket) ships it.\n * Calling `streamGenerationFrom` while only a non-interactive Layer is\n * in scope fails at `Effect.provide` with a type error.\n *\n * Phantom: the value is `void`; providers register with\n * `Layer.succeed(MusicInteractiveSession, undefined)`.\n */\nexport class MusicInteractiveSession extends Context.Service<MusicInteractiveSession, void>()(\n \"@betalyra/effect-uai/capability/MusicInteractiveSession\",\n) {}\n\n/** One-shot generation. Returns the full `GenerateResult`. */\nexport const generate = (\n request: CommonGenerateMusicRequest,\n): Effect.Effect<GenerateResult, AiError.AiError, MusicGenerator> =>\n Effect.flatMap(MusicGenerator, (s) => s.generate(request))\n\n/** Prompt in, audio chunks out. */\nexport const streamGeneration = (\n request: CommonStreamGenerateMusicRequest,\n): Stream.Stream<AudioChunk, AiError.AiError, MusicGenerator> =>\n Stream.unwrap(Effect.map(MusicGenerator, (s) => s.streamGeneration(request)))\n\n/**\n * Bidirectional generation. Dual-arity: pipeable (data-last) and\n * direct (data-first). Requires `MusicInteractiveSession` in R,\n * providers without bidirectional support are a type error at provide\n * time.\n *\n * On the cross-provider surface, `input` is `Stream<unknown>` and\n * output is `Stream<MusicStreamEvent>`. Use the provider-typed\n * service (`LyriaRealtimeGenerator`) when you want to construct\n * typed session messages.\n *\n * @example\n * ```ts\n * // Generic surface (opaque input):\n * const audio = inputs.pipe(\n * MusicGenerator.streamGenerationFrom({ model: \"lyria-realtime-exp\", prompt: \"\" }),\n * )\n *\n * // Lyria-typed surface (full config knobs):\n * const audio = inputs.pipe(\n * LyriaRealtimeGenerator.streamGenerationFrom({ model: \"lyria-realtime-exp\", prompt: \"\" }),\n * )\n * ```\n */\nexport const streamGenerationFrom: {\n (\n request: CommonStreamGenerateMusicRequest,\n ): <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n ) => Stream.Stream<\n MusicStreamEvent,\n AiError.AiError | E,\n R | MusicGenerator | MusicInteractiveSession\n >\n <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ): Stream.Stream<\n MusicStreamEvent,\n AiError.AiError | E,\n R | MusicGenerator | MusicInteractiveSession\n >\n} = Function.dual(\n 2,\n <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ): Stream.Stream<\n MusicStreamEvent,\n AiError.AiError | E,\n R | MusicGenerator | MusicInteractiveSession\n > =>\n Stream.unwrap(\n Effect.gen(function* () {\n const s = yield* MusicGenerator\n yield* MusicInteractiveSession\n return s.streamGenerationFrom(input, request)\n }),\n ),\n)\n"],"mappings":";;;;;;;;;;AA0EA,IAAa,iBAAb,cAAoC,QAAQ,SAAgD,CAC1F,sCACD,CAAC;;;;;;;;;;;AAYF,IAAa,0BAAb,cAA6C,QAAQ,SAAwC,CAC3F,0DACD,CAAC;;AAGF,MAAa,YACX,YAEA,OAAO,QAAQ,iBAAiB,MAAM,EAAE,SAAS,QAAQ,CAAC;;AAG5D,MAAa,oBACX,YAEA,OAAO,OAAO,OAAO,IAAI,iBAAiB,MAAM,EAAE,iBAAiB,QAAQ,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0B/E,MAAa,uBAkBT,SAAS,KACX,IAEE,OACA,YAMA,OAAO,OACL,OAAO,IAAI,aAAa;CACtB,MAAM,IAAI,OAAO;AACjB,QAAO;AACP,QAAO,EAAE,qBAAqB,OAAO,QAAQ;EAC7C,CACH,CACJ"}
@@ -1,6 +1,6 @@
1
1
  import { audioEvent, controlInput, promptsInput, singleVariant } from "../domain/Music.mjs";
2
2
  import { generate, streamGeneration, streamGenerationFrom } from "./MusicGenerator.mjs";
3
- import { a as describe, n as globalExpect, o as it, t as import_dist } from "../dist-B04dlFHg.mjs";
3
+ import { c as it, n as globalExpect, o as describe, t as import_dist } from "../dist-CcRV3-A5.mjs";
4
4
  import { layer, layerWithoutInteractive } from "../testing/MockMusicGenerator.mjs";
5
5
  import { Duration, Effect, Stream } from "effect";
6
6
  //#region src/music-generator/MusicGenerator.test.ts
@@ -1,4 +1,4 @@
1
- import { x as Usage } from "../Items-CgKD6Npw.mjs";
1
+ import { x as Usage } from "../Items-BWNu6VGp.mjs";
2
2
  import { TurnEvent } from "../domain/Turn.mjs";
3
3
  import { Duration, Effect, Option, Stream } from "effect";
4
4
 
@@ -1,7 +1,7 @@
1
1
  import { TurnEvent } from "../domain/Turn.mjs";
2
2
  import { computeThroughputTick, isMetricEvent, makeEvent, metricEvents, throughput, timeToCompletion, timeToFirstToken, tokenTotals } from "./Metrics.mjs";
3
- import { a as describe, n as globalExpect } from "../dist-B04dlFHg.mjs";
4
- import { t as it } from "../dist-DWgRbDN3.mjs";
3
+ import { n as globalExpect, o as describe } from "../dist-CcRV3-A5.mjs";
4
+ import { t as it } from "../dist-C0m0QnUP.mjs";
5
5
  import { Array, Duration, Effect, Fiber, Option, Stream } from "effect";
6
6
  import * as TestClock from "effect/testing/TestClock";
7
7
  //#region src/observability/Metrics.test.ts
@@ -1,7 +1,7 @@
1
1
  import { makeEvent } from "./Metrics.mjs";
2
2
  import { layerOtlp, record } from "./Telemetry.mjs";
3
- import { a as describe, n as globalExpect } from "../dist-B04dlFHg.mjs";
4
- import { t as it } from "../dist-DWgRbDN3.mjs";
3
+ import { n as globalExpect, o as describe } from "../dist-CcRV3-A5.mjs";
4
+ import { t as it } from "../dist-C0m0QnUP.mjs";
5
5
  import { Array, Duration, Effect, Layer, Metric, Option, Ref, Stream } from "effect";
6
6
  import { HttpClient, HttpClientResponse } from "effect/unstable/http";
7
7
  //#region src/observability/Telemetry.test.ts