@effect-uai/core 0.12.0 → 0.13.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 (301) hide show
  1. package/dist/{AiError-Bf1pq4BB.d.mts → AiError-eLV9t1lU.d.mts} +12 -16
  2. package/dist/AiError-eLV9t1lU.d.mts.map +1 -0
  3. package/dist/{Audio-CR7CSljJ.d.mts → Audio-60lKKHxS.d.mts} +4 -5
  4. package/dist/Audio-60lKKHxS.d.mts.map +1 -0
  5. package/dist/{Image-C4vuBmu0.d.mts → Image-BK8-4H6s.d.mts} +12 -14
  6. package/dist/Image-BK8-4H6s.d.mts.map +1 -0
  7. package/dist/{Items-BKQgqJ8A.d.mts → Items-SfUabNuB.d.mts} +74 -76
  8. package/dist/Items-SfUabNuB.d.mts.map +1 -0
  9. package/dist/{Loop-D8nWpowc.d.mts → Loop-B54AB1ME.d.mts} +19 -21
  10. package/dist/Loop-B54AB1ME.d.mts.map +1 -0
  11. package/dist/{Media-D_CpcM1Z.d.mts → Media-DwgpifPD.d.mts} +1 -1
  12. package/dist/Media-DwgpifPD.d.mts.map +1 -0
  13. package/dist/{SandboxError-CIrVDOMV.d.mts → SandboxError-BN8b28Bh.d.mts} +11 -15
  14. package/dist/SandboxError-BN8b28Bh.d.mts.map +1 -0
  15. package/dist/{StructuredFormat-DHaUJBdd.d.mts → StructuredFormat-BlZhyOsi.d.mts} +3 -7
  16. package/dist/StructuredFormat-BlZhyOsi.d.mts.map +1 -0
  17. package/dist/{Tool-u5bag8SO.d.mts → Tool-DE-rnvkw.d.mts} +5 -8
  18. package/dist/Tool-DE-rnvkw.d.mts.map +1 -0
  19. package/dist/{ToolEvent-BBfOdhF_.d.mts → ToolEvent-D99MGQYH.d.mts} +56 -63
  20. package/dist/ToolEvent-D99MGQYH.d.mts.map +1 -0
  21. package/dist/{ToolResult-CRpmkBXR.d.mts → ToolResult-Cj8ChodL.d.mts} +49 -54
  22. package/dist/ToolResult-Cj8ChodL.d.mts.map +1 -0
  23. package/dist/{Toolkit-D4mQvhjq.d.mts → Toolkit-BEZrNPTI.d.mts} +13 -16
  24. package/dist/Toolkit-BEZrNPTI.d.mts.map +1 -0
  25. package/dist/browser/Browser.d.mts +11 -7
  26. package/dist/browser/Browser.d.mts.map +1 -1
  27. package/dist/browser/Browser.mjs +1 -1
  28. package/dist/browser/Browser.mjs.map +1 -1
  29. package/dist/browser/BrowserError.d.mts +9 -13
  30. package/dist/browser/BrowserError.d.mts.map +1 -1
  31. package/dist/browser/BrowserError.mjs +1 -1
  32. package/dist/browser/BrowserError.mjs.map +1 -1
  33. package/dist/browser/BrowserTool.d.mts +33 -36
  34. package/dist/browser/BrowserTool.d.mts.map +1 -1
  35. package/dist/browser/BrowserTool.mjs +1 -1
  36. package/dist/browser/BrowserTool.mjs.map +1 -1
  37. package/dist/capabilities/Capabilities.d.mts +8 -6
  38. package/dist/capabilities/Capabilities.d.mts.map +1 -1
  39. package/dist/capabilities/Capabilities.mjs +1 -1
  40. package/dist/capabilities/Capabilities.mjs.map +1 -1
  41. package/dist/chunker/Chunker.d.mts +32 -0
  42. package/dist/chunker/Chunker.d.mts.map +1 -0
  43. package/dist/chunker/Chunker.mjs +14 -0
  44. package/dist/chunker/Chunker.mjs.map +1 -0
  45. package/dist/dist-BaenoU1A.mjs +145 -0
  46. package/dist/dist-BaenoU1A.mjs.map +1 -0
  47. package/dist/{dist-C0m0QnUP.mjs → dist-nohcnkD6.mjs} +16 -15
  48. package/dist/dist-nohcnkD6.mjs.map +1 -0
  49. package/dist/domain/AiError.d.mts +1 -1
  50. package/dist/domain/AiError.mjs +1 -1
  51. package/dist/domain/AiError.mjs.map +1 -1
  52. package/dist/domain/Audio.d.mts +1 -1
  53. package/dist/domain/Audio.mjs +1 -1
  54. package/dist/domain/Citation.d.mts +0 -2
  55. package/dist/domain/Citation.d.mts.map +1 -1
  56. package/dist/domain/Citation.mjs +1 -1
  57. package/dist/domain/Image.d.mts +1 -1
  58. package/dist/domain/Image.mjs +1 -1
  59. package/dist/domain/Image.mjs.map +1 -1
  60. package/dist/domain/Items.d.mts +1 -1
  61. package/dist/domain/Items.mjs +1 -1
  62. package/dist/domain/Items.mjs.map +1 -1
  63. package/dist/domain/Media.d.mts +1 -1
  64. package/dist/domain/Media.mjs +1 -1
  65. package/dist/domain/Music.d.mts +18 -11
  66. package/dist/domain/Music.d.mts.map +1 -1
  67. package/dist/domain/Music.mjs +1 -1
  68. package/dist/domain/Music.mjs.map +1 -1
  69. package/dist/domain/Research.d.mts +3 -4
  70. package/dist/domain/Research.d.mts.map +1 -1
  71. package/dist/domain/Research.mjs +1 -1
  72. package/dist/domain/Transcript.d.mts +2 -3
  73. package/dist/domain/Transcript.d.mts.map +1 -1
  74. package/dist/domain/Transcript.mjs +1 -1
  75. package/dist/domain/Turn.d.mts +143 -164
  76. package/dist/domain/Turn.d.mts.map +1 -1
  77. package/dist/domain/Turn.mjs +1 -1
  78. package/dist/domain/Turn.mjs.map +1 -1
  79. package/dist/domain/Turn.test.d.mts +1 -1
  80. package/dist/domain/Turn.test.mjs +28 -18
  81. package/dist/domain/Turn.test.mjs.map +1 -1
  82. package/dist/embedding-model/Embedding.d.mts +1 -3
  83. package/dist/embedding-model/Embedding.d.mts.map +1 -1
  84. package/dist/embedding-model/Embedding.mjs +1 -1
  85. package/dist/embedding-model/EmbeddingModel.d.mts +1 -3
  86. package/dist/embedding-model/EmbeddingModel.d.mts.map +1 -1
  87. package/dist/embedding-model/EmbeddingModel.mjs +1 -1
  88. package/dist/embedding-model/EmbeddingModel.mjs.map +1 -1
  89. package/dist/embedding-model/EmbeddingModel.test.d.mts +1 -1
  90. package/dist/embedding-model/EmbeddingModel.test.mjs +14 -9
  91. package/dist/embedding-model/EmbeddingModel.test.mjs.map +1 -1
  92. package/dist/index.d.mts +16 -13
  93. package/dist/index.mjs +4 -1
  94. package/dist/job/Job.d.mts +4 -4
  95. package/dist/job/Job.d.mts.map +1 -1
  96. package/dist/job/Job.mjs +1 -1
  97. package/dist/job/Job.mjs.map +1 -1
  98. package/dist/language-model/LanguageModel.d.mts +4 -6
  99. package/dist/language-model/LanguageModel.d.mts.map +1 -1
  100. package/dist/language-model/LanguageModel.mjs +1 -1
  101. package/dist/language-model/LanguageModel.mjs.map +1 -1
  102. package/dist/language-model/LanguageModel.test.d.mts +1 -1
  103. package/dist/language-model/LanguageModel.test.mjs +6 -3
  104. package/dist/language-model/LanguageModel.test.mjs.map +1 -1
  105. package/dist/loop/Loop.d.mts +1 -1
  106. package/dist/loop/Loop.mjs +1 -1
  107. package/dist/loop/Loop.mjs.map +1 -1
  108. package/dist/loop/Loop.test.d.mts +1 -1
  109. package/dist/loop/Loop.test.mjs +60 -34
  110. package/dist/loop/Loop.test.mjs.map +1 -1
  111. package/dist/{magic-string.es-Dk-MMA0F.mjs → magic-string.es-CB2hOw9v.mjs} +14 -13
  112. package/dist/{magic-string.es-Dk-MMA0F.mjs.map → magic-string.es-CB2hOw9v.mjs.map} +1 -1
  113. package/dist/math/Vector.d.mts +0 -2
  114. package/dist/math/Vector.d.mts.map +1 -1
  115. package/dist/math/Vector.mjs +1 -1
  116. package/dist/math/Vector.mjs.map +1 -1
  117. package/dist/music-generator/MusicGenerator.d.mts +2 -4
  118. package/dist/music-generator/MusicGenerator.d.mts.map +1 -1
  119. package/dist/music-generator/MusicGenerator.mjs +1 -1
  120. package/dist/music-generator/MusicGenerator.mjs.map +1 -1
  121. package/dist/music-generator/MusicGenerator.test.d.mts +1 -1
  122. package/dist/music-generator/MusicGenerator.test.mjs +19 -10
  123. package/dist/music-generator/MusicGenerator.test.mjs.map +1 -1
  124. package/dist/observability/Metrics.d.mts +10 -7
  125. package/dist/observability/Metrics.d.mts.map +1 -1
  126. package/dist/observability/Metrics.mjs +1 -1
  127. package/dist/observability/Metrics.mjs.map +1 -1
  128. package/dist/observability/Metrics.test.d.mts +1 -1
  129. package/dist/observability/Metrics.test.mjs +50 -28
  130. package/dist/observability/Metrics.test.mjs.map +1 -1
  131. package/dist/observability/Telemetry.d.mts +2 -3
  132. package/dist/observability/Telemetry.d.mts.map +1 -1
  133. package/dist/observability/Telemetry.mjs +1 -1
  134. package/dist/observability/Telemetry.mjs.map +1 -1
  135. package/dist/observability/Telemetry.test.d.mts +1 -1
  136. package/dist/observability/Telemetry.test.mjs +15 -7
  137. package/dist/observability/Telemetry.test.mjs.map +1 -1
  138. package/dist/reranker/Reranker.d.mts +46 -0
  139. package/dist/reranker/Reranker.d.mts.map +1 -0
  140. package/dist/reranker/Reranker.mjs +14 -0
  141. package/dist/reranker/Reranker.mjs.map +1 -0
  142. package/dist/research/DeepResearch.d.mts +1 -3
  143. package/dist/research/DeepResearch.d.mts.map +1 -1
  144. package/dist/research/DeepResearch.mjs +1 -1
  145. package/dist/research/DeepResearch.mjs.map +1 -1
  146. package/dist/retry/Retry.d.mts +2 -6
  147. package/dist/retry/Retry.d.mts.map +1 -1
  148. package/dist/retry/Retry.mjs +1 -1
  149. package/dist/retry/Retry.mjs.map +1 -1
  150. package/dist/retry/Retry.test.d.mts +1 -1
  151. package/dist/retry/Retry.test.mjs +6 -3
  152. package/dist/retry/Retry.test.mjs.map +1 -1
  153. package/dist/sandbox/Memory.d.mts +0 -2
  154. package/dist/sandbox/Memory.d.mts.map +1 -1
  155. package/dist/sandbox/Memory.mjs +4 -4
  156. package/dist/sandbox/Memory.mjs.map +1 -1
  157. package/dist/sandbox/Sandbox.d.mts +144 -156
  158. package/dist/sandbox/Sandbox.d.mts.map +1 -1
  159. package/dist/sandbox/Sandbox.mjs +1 -1
  160. package/dist/sandbox/Sandbox.mjs.map +1 -1
  161. package/dist/sandbox/SandboxError.d.mts +1 -1
  162. package/dist/sandbox/SandboxError.mjs +1 -1
  163. package/dist/sandbox/SandboxError.mjs.map +1 -1
  164. package/dist/sandbox/SandboxImage.d.mts +0 -2
  165. package/dist/sandbox/SandboxImage.d.mts.map +1 -1
  166. package/dist/sandbox/SandboxImage.mjs +1 -1
  167. package/dist/sandbox/SandboxImage.mjs.map +1 -1
  168. package/dist/sandbox/SandboxNetwork.d.mts +0 -2
  169. package/dist/sandbox/SandboxNetwork.d.mts.map +1 -1
  170. package/dist/sandbox/SandboxNetwork.mjs +1 -1
  171. package/dist/sandbox/SandboxNetwork.mjs.map +1 -1
  172. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +8 -7
  173. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts.map +1 -1
  174. package/dist/speech-synthesizer/SpeechSynthesizer.mjs +1 -1
  175. package/dist/speech-synthesizer/SpeechSynthesizer.mjs.map +1 -1
  176. package/dist/speech-synthesizer/SpeechSynthesizer.test.d.mts +1 -1
  177. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs +31 -16
  178. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs.map +1 -1
  179. package/dist/streaming/JSONL.d.mts +1 -5
  180. package/dist/streaming/JSONL.d.mts.map +1 -1
  181. package/dist/streaming/JSONL.mjs +1 -1
  182. package/dist/streaming/JSONL.mjs.map +1 -1
  183. package/dist/streaming/JSONL.test.d.mts +1 -1
  184. package/dist/streaming/JSONL.test.mjs +16 -8
  185. package/dist/streaming/JSONL.test.mjs.map +1 -1
  186. package/dist/streaming/Lines.d.mts +0 -2
  187. package/dist/streaming/Lines.d.mts.map +1 -1
  188. package/dist/streaming/Lines.mjs +1 -1
  189. package/dist/streaming/Lines.mjs.map +1 -1
  190. package/dist/streaming/SSE.d.mts +0 -2
  191. package/dist/streaming/SSE.d.mts.map +1 -1
  192. package/dist/streaming/SSE.mjs +1 -1
  193. package/dist/streaming/SSE.mjs.map +1 -1
  194. package/dist/streaming/SSE.test.d.mts +1 -1
  195. package/dist/streaming/SSE.test.mjs +34 -17
  196. package/dist/streaming/SSE.test.mjs.map +1 -1
  197. package/dist/structured-format/StructuredFormat.d.mts +1 -1
  198. package/dist/structured-format/StructuredFormat.mjs +1 -1
  199. package/dist/structured-format/StructuredFormat.mjs.map +1 -1
  200. package/dist/structured-format/StructuredFormat.test.d.mts +1 -1
  201. package/dist/structured-format/StructuredFormat.test.mjs +7 -4
  202. package/dist/structured-format/StructuredFormat.test.mjs.map +1 -1
  203. package/dist/{dist-CcRV3-A5.mjs → test.DNmyFkvJ-YPzDR0Co.mjs} +1644 -5172
  204. package/dist/test.DNmyFkvJ-YPzDR0Co.mjs.map +1 -0
  205. package/dist/testing/MockMusicGenerator.d.mts +4 -3
  206. package/dist/testing/MockMusicGenerator.d.mts.map +1 -1
  207. package/dist/testing/MockMusicGenerator.mjs.map +1 -1
  208. package/dist/testing/MockProvider.d.mts +1 -2
  209. package/dist/testing/MockProvider.d.mts.map +1 -1
  210. package/dist/testing/MockProvider.mjs.map +1 -1
  211. package/dist/testing/MockSandbox.d.mts +256 -290
  212. package/dist/testing/MockSandbox.d.mts.map +1 -1
  213. package/dist/testing/MockSandbox.mjs.map +1 -1
  214. package/dist/testing/MockSpeechSynthesizer.d.mts +10 -6
  215. package/dist/testing/MockSpeechSynthesizer.d.mts.map +1 -1
  216. package/dist/testing/MockSpeechSynthesizer.mjs.map +1 -1
  217. package/dist/testing/MockTranscriber.d.mts +3 -2
  218. package/dist/testing/MockTranscriber.d.mts.map +1 -1
  219. package/dist/testing/MockTranscriber.mjs.map +1 -1
  220. package/dist/tokenizer/Tokenizer.d.mts +22 -0
  221. package/dist/tokenizer/Tokenizer.d.mts.map +1 -0
  222. package/dist/tokenizer/Tokenizer.mjs +9 -0
  223. package/dist/tokenizer/Tokenizer.mjs.map +1 -0
  224. package/dist/tool/Approval.d.mts +31 -36
  225. package/dist/tool/Approval.d.mts.map +1 -1
  226. package/dist/tool/Approval.mjs +1 -1
  227. package/dist/tool/Approval.mjs.map +1 -1
  228. package/dist/tool/Approval.test.d.mts +1 -1
  229. package/dist/tool/Approval.test.mjs +37 -24
  230. package/dist/tool/Approval.test.mjs.map +1 -1
  231. package/dist/tool/HistoryCheck.d.mts +2 -4
  232. package/dist/tool/HistoryCheck.d.mts.map +1 -1
  233. package/dist/tool/HistoryCheck.mjs +1 -1
  234. package/dist/tool/HistoryCheck.mjs.map +1 -1
  235. package/dist/tool/Tool.d.mts +1 -1
  236. package/dist/tool/Tool.mjs +4 -4
  237. package/dist/tool/Tool.mjs.map +1 -1
  238. package/dist/tool/Tool.test.d.mts +1 -1
  239. package/dist/tool/Tool.test.mjs +23 -11
  240. package/dist/tool/Tool.test.mjs.map +1 -1
  241. package/dist/tool/ToolEvent.d.mts +1 -1
  242. package/dist/tool/ToolEvent.mjs +1 -1
  243. package/dist/tool/ToolEvent.mjs.map +1 -1
  244. package/dist/tool/ToolResult.d.mts +1 -1
  245. package/dist/tool/ToolResult.mjs +1 -1
  246. package/dist/tool/ToolResult.mjs.map +1 -1
  247. package/dist/tool/Toolkit.d.mts +1 -1
  248. package/dist/tool/Toolkit.mjs +4 -3
  249. package/dist/tool/Toolkit.mjs.map +1 -1
  250. package/dist/tool/Toolkit.test.d.mts +1 -1
  251. package/dist/tool/Toolkit.test.mjs +40 -21
  252. package/dist/tool/Toolkit.test.mjs.map +1 -1
  253. package/dist/transcriber/Transcriber.d.mts +6 -6
  254. package/dist/transcriber/Transcriber.d.mts.map +1 -1
  255. package/dist/transcriber/Transcriber.mjs +1 -1
  256. package/dist/transcriber/Transcriber.mjs.map +1 -1
  257. package/dist/transcriber/Transcriber.test.d.mts +1 -1
  258. package/dist/transcriber/Transcriber.test.mjs +20 -10
  259. package/dist/transcriber/Transcriber.test.mjs.map +1 -1
  260. package/dist/utils-CiH_DjFW.mjs +3918 -0
  261. package/dist/utils-CiH_DjFW.mjs.map +1 -0
  262. package/dist/web-read/WebRead.d.mts +15 -9
  263. package/dist/web-read/WebRead.d.mts.map +1 -1
  264. package/dist/web-read/WebRead.mjs +1 -1
  265. package/dist/web-read/WebRead.mjs.map +1 -1
  266. package/dist/web-read/WebReadTool.d.mts +4 -5
  267. package/dist/web-read/WebReadTool.d.mts.map +1 -1
  268. package/dist/web-read/WebReadTool.mjs +1 -1
  269. package/dist/web-read/WebReadTool.mjs.map +1 -1
  270. package/dist/web-search/WebSearch.d.mts +22 -13
  271. package/dist/web-search/WebSearch.d.mts.map +1 -1
  272. package/dist/web-search/WebSearch.mjs +1 -1
  273. package/dist/web-search/WebSearch.mjs.map +1 -1
  274. package/dist/web-search/WebSearchTool.d.mts +6 -6
  275. package/dist/web-search/WebSearchTool.d.mts.map +1 -1
  276. package/dist/web-search/WebSearchTool.mjs +1 -1
  277. package/dist/web-search/WebSearchTool.mjs.map +1 -1
  278. package/package.json +16 -4
  279. package/src/chunker/Chunker.ts +34 -0
  280. package/src/index.ts +3 -0
  281. package/src/loop/Loop.test.ts +13 -14
  282. package/src/loop/Loop.ts +74 -76
  283. package/src/reranker/Reranker.ts +51 -0
  284. package/src/testing/MockProvider.ts +8 -9
  285. package/src/tokenizer/Tokenizer.ts +19 -0
  286. package/src/tool/Tool.ts +13 -13
  287. package/dist/AiError-Bf1pq4BB.d.mts.map +0 -1
  288. package/dist/Audio-CR7CSljJ.d.mts.map +0 -1
  289. package/dist/Image-C4vuBmu0.d.mts.map +0 -1
  290. package/dist/Items-BKQgqJ8A.d.mts.map +0 -1
  291. package/dist/Loop-D8nWpowc.d.mts.map +0 -1
  292. package/dist/Media-D_CpcM1Z.d.mts.map +0 -1
  293. package/dist/SandboxError-CIrVDOMV.d.mts.map +0 -1
  294. package/dist/StructuredFormat-DHaUJBdd.d.mts.map +0 -1
  295. package/dist/Tool-u5bag8SO.d.mts.map +0 -1
  296. package/dist/ToolEvent-BBfOdhF_.d.mts.map +0 -1
  297. package/dist/ToolResult-CRpmkBXR.d.mts.map +0 -1
  298. package/dist/Toolkit-D4mQvhjq.d.mts.map +0 -1
  299. package/dist/dist-C0m0QnUP.mjs.map +0 -1
  300. package/dist/dist-CcRV3-A5.mjs.map +0 -1
  301. /package/dist/{chunk-uyGKjUfl.mjs → rolldown-runtime-EAsCxrDo.mjs} +0 -0
@@ -1,12 +1,11 @@
1
1
  import { Duration, Layer, Stream } from "effect";
2
2
  import { HttpClient } from "effect/unstable/http";
3
-
4
- //#region src/observability/Telemetry.d.ts
5
3
  declare namespace Telemetry_d_exports {
6
4
  export { LayerOtlpOptions, RecordOptions, layerOtlp, record };
7
5
  }
8
6
  type RecordOptions = {
9
- /** Attributes applied to every recorded metric, e.g. `{ model, provider }`. */readonly attributes?: Readonly<Record<string, string>>;
7
+ /** Attributes applied to every recorded metric, e.g. `{ model, provider }`. */
8
+ readonly attributes?: Readonly<Record<string, string>>;
10
9
  };
11
10
  /**
12
11
  * Record every measurement on every metric event into effect `Metric`
@@ -1 +1 @@
1
- {"version":3,"file":"Telemetry.d.mts","names":[],"sources":["../../src/observability/Telemetry.ts"],"mappings":";;;;;;;KAqDY,aAAA;0FAED,UAAA,GAAa,QAAA,CAAS,MAAA;AAAA;;;;;;AAFjC;;;cAaa,MAAA,GACV,OAAA,GAAU,aAAA,eACD,IAAA,EAAM,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,CAAA,EAAG,CAAA,MAAK,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,CAAA,EAAG,CAAA;AAAA,KASnD,gBAAA;EAAA,SACD,GAAA;EAAA,SACA,QAAA;IAAA,SACE,WAAA;IAAA,SACA,cAAA;EAAA;EAAA,SAEF,cAAA,GAAiB,QAAA,CAAS,KAAA;AAAA;;;;;;;cASxB,SAAA,GACX,OAAA,EAAS,gBAAA,KACR,KAAA,CAAM,KAAA,eAAoB,UAAA,CAAW,UAAA"}
1
+ {"version":3,"file":"Telemetry.d.mts","names":[],"sources":["../../src/observability/Telemetry.ts"],"mappings":";;;;;KAqDY;;WAED,aAAa,SAAS;;;;;;;;;;cAWpB,SAAM,UACN,mBACV,GAAG,GAAG,GAAC,MAAQ,OAAO,OAAO,GAAG,GAAG,OAAK,OAAO,OAAO,GAAG,GAAG;KASnD;WACD;WACA;aACE;aACA;;WAEF,iBAAiB,SAAS;;;;;;;;cASxB,YAAS,SACX,qBACR,MAAM,oBAAoB,WAAW"}
@@ -1,4 +1,4 @@
1
- import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
1
+ import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
2
2
  import { isMetricEvent } from "./Metrics.mjs";
3
3
  import { Effect, Layer, Match, Metric, Stream } from "effect";
4
4
  import { OtlpMetrics, OtlpSerialization } from "effect/unstable/observability";
@@ -1 +1 @@
1
- {"version":3,"file":"Telemetry.mjs","names":[],"sources":["../../src/observability/Telemetry.ts"],"sourcesContent":["import { Duration, Effect, Layer, Match, Metric, Stream } from \"effect\"\nimport type { HttpClient } from \"effect/unstable/http\"\nimport { OtlpMetrics, OtlpSerialization } from \"effect/unstable/observability\"\nimport { isMetricEvent, type Measurement, type MetricEvent } from \"./Metrics.js\"\n\n// ---------------------------------------------------------------------------\n// The agnostic recorder\n// ---------------------------------------------------------------------------\n\n/**\n * Histogram bucket boundaries used for every histogram measurement (the only\n * built-in one is throughput). Custom histogram metrics share these; a metric\n * that needs bespoke boundaries can update its own instrument directly instead\n * of routing through `record`.\n */\nconst histogramBoundaries = Metric.exponentialBoundaries({ start: 1, factor: 2, count: 16 })\n\n/**\n * Build the effect `Metric` instrument a measurement maps to. Dispatches on\n * `kind`, never on the event `_tag`, so a new built-in or custom metric needs\n * no change here. Instruments dedupe by name in the global registry, so a fresh\n * instance per call accumulates onto the same series (no cache needed).\n */\nconst buildInstrument = (m: Measurement): Metric.Metric<any, any> =>\n Match.value(m.kind).pipe(\n Match.when(\"counter\", () => Metric.counter(m.name, { incremental: true })),\n Match.when(\"histogram\", () => Metric.histogram(m.name, { boundaries: histogramBoundaries })),\n Match.when(\"timer\", () => Metric.timer(m.name)),\n Match.when(\"gauge\", () => Metric.gauge(m.name)),\n Match.exhaustive,\n )\n\nconst mergeAttributes = (\n base: Readonly<Record<string, string>> | undefined,\n extra: Readonly<Record<string, string>> | undefined,\n): Readonly<Record<string, string>> | undefined =>\n base === undefined ? extra : extra === undefined ? base : { ...base, ...extra }\n\nconst recordEvent = (\n ev: MetricEvent,\n baseAttributes: Readonly<Record<string, string>> | undefined,\n): Effect.Effect<void> =>\n Effect.forEach(\n ev.measurements,\n (m) => {\n const attributes = mergeAttributes(baseAttributes, m.attributes)\n const base = buildInstrument(m)\n const instrument = attributes === undefined ? base : Metric.withAttributes(base, attributes)\n return Metric.update(instrument, m.value)\n },\n { discard: true },\n )\n\nexport type RecordOptions = {\n /** Attributes applied to every recorded metric, e.g. `{ model, provider }`. */\n readonly attributes?: Readonly<Record<string, string>>\n}\n\n/**\n * Record every measurement on every metric event into effect `Metric`\n * instruments, then pass events through unchanged. Matches events structurally\n * (`isMetricEvent`), so it records built-in and custom metrics alike, and\n * dispatches on `measurement.kind`, never on the event tag. Sits mid-pipeline\n * before the transport. Provide an OTLP (or Prometheus) layer to export the\n * instruments it populates.\n */\nexport const record =\n (options?: RecordOptions) =>\n <A, E, R>(self: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>\n self.pipe(\n Stream.tap((ev) => (isMetricEvent(ev) ? recordEvent(ev, options?.attributes) : Effect.void)),\n )\n\n// ---------------------------------------------------------------------------\n// OTLP wiring\n// ---------------------------------------------------------------------------\n\nexport type LayerOtlpOptions = {\n readonly url: string\n readonly resource?: {\n readonly serviceName?: string\n readonly serviceVersion?: string\n }\n readonly exportInterval?: Duration.Input\n}\n\n/**\n * Convenience layer that exports recorded metrics over OTLP. Provides the JSON\n * serializer and leaves `HttpClient` as a requirement, so the platform's client\n * (FetchHttpClient, NodeHttpClient, ...) is provided at the edge. This keeps\n * the library platform-independent.\n */\nexport const layerOtlp = (\n options: LayerOtlpOptions,\n): Layer.Layer<never, never, HttpClient.HttpClient> =>\n OtlpMetrics.layer(options).pipe(Layer.provide(OtlpSerialization.layerJson))\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,sBAAsB,OAAO,sBAAsB;CAAE,OAAO;CAAG,QAAQ;CAAG,OAAO;CAAI,CAAC;;;;;;;AAQ5F,MAAM,mBAAmB,MACvB,MAAM,MAAM,EAAE,KAAK,CAAC,KAClB,MAAM,KAAK,iBAAiB,OAAO,QAAQ,EAAE,MAAM,EAAE,aAAa,MAAM,CAAC,CAAC,EAC1E,MAAM,KAAK,mBAAmB,OAAO,UAAU,EAAE,MAAM,EAAE,YAAY,qBAAqB,CAAC,CAAC,EAC5F,MAAM,KAAK,eAAe,OAAO,MAAM,EAAE,KAAK,CAAC,EAC/C,MAAM,KAAK,eAAe,OAAO,MAAM,EAAE,KAAK,CAAC,EAC/C,MAAM,WACP;AAEH,MAAM,mBACJ,MACA,UAEA,SAAS,KAAA,IAAY,QAAQ,UAAU,KAAA,IAAY,OAAO;CAAE,GAAG;CAAM,GAAG;CAAO;AAEjF,MAAM,eACJ,IACA,mBAEA,OAAO,QACL,GAAG,eACF,MAAM;CACL,MAAM,aAAa,gBAAgB,gBAAgB,EAAE,WAAW;CAChE,MAAM,OAAO,gBAAgB,EAAE;CAC/B,MAAM,aAAa,eAAe,KAAA,IAAY,OAAO,OAAO,eAAe,MAAM,WAAW;AAC5F,QAAO,OAAO,OAAO,YAAY,EAAE,MAAM;GAE3C,EAAE,SAAS,MAAM,CAClB;;;;;;;;;AAeH,MAAa,UACV,aACS,SACR,KAAK,KACH,OAAO,KAAK,OAAQ,cAAc,GAAG,GAAG,YAAY,IAAI,SAAS,WAAW,GAAG,OAAO,KAAM,CAC7F;;;;;;;AAqBL,MAAa,aACX,YAEA,YAAY,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,kBAAkB,UAAU,CAAC"}
1
+ {"version":3,"file":"Telemetry.mjs","names":[],"sources":["../../src/observability/Telemetry.ts"],"sourcesContent":["import { Duration, Effect, Layer, Match, Metric, Stream } from \"effect\"\nimport type { HttpClient } from \"effect/unstable/http\"\nimport { OtlpMetrics, OtlpSerialization } from \"effect/unstable/observability\"\nimport { isMetricEvent, type Measurement, type MetricEvent } from \"./Metrics.js\"\n\n// ---------------------------------------------------------------------------\n// The agnostic recorder\n// ---------------------------------------------------------------------------\n\n/**\n * Histogram bucket boundaries used for every histogram measurement (the only\n * built-in one is throughput). Custom histogram metrics share these; a metric\n * that needs bespoke boundaries can update its own instrument directly instead\n * of routing through `record`.\n */\nconst histogramBoundaries = Metric.exponentialBoundaries({ start: 1, factor: 2, count: 16 })\n\n/**\n * Build the effect `Metric` instrument a measurement maps to. Dispatches on\n * `kind`, never on the event `_tag`, so a new built-in or custom metric needs\n * no change here. Instruments dedupe by name in the global registry, so a fresh\n * instance per call accumulates onto the same series (no cache needed).\n */\nconst buildInstrument = (m: Measurement): Metric.Metric<any, any> =>\n Match.value(m.kind).pipe(\n Match.when(\"counter\", () => Metric.counter(m.name, { incremental: true })),\n Match.when(\"histogram\", () => Metric.histogram(m.name, { boundaries: histogramBoundaries })),\n Match.when(\"timer\", () => Metric.timer(m.name)),\n Match.when(\"gauge\", () => Metric.gauge(m.name)),\n Match.exhaustive,\n )\n\nconst mergeAttributes = (\n base: Readonly<Record<string, string>> | undefined,\n extra: Readonly<Record<string, string>> | undefined,\n): Readonly<Record<string, string>> | undefined =>\n base === undefined ? extra : extra === undefined ? base : { ...base, ...extra }\n\nconst recordEvent = (\n ev: MetricEvent,\n baseAttributes: Readonly<Record<string, string>> | undefined,\n): Effect.Effect<void> =>\n Effect.forEach(\n ev.measurements,\n (m) => {\n const attributes = mergeAttributes(baseAttributes, m.attributes)\n const base = buildInstrument(m)\n const instrument = attributes === undefined ? base : Metric.withAttributes(base, attributes)\n return Metric.update(instrument, m.value)\n },\n { discard: true },\n )\n\nexport type RecordOptions = {\n /** Attributes applied to every recorded metric, e.g. `{ model, provider }`. */\n readonly attributes?: Readonly<Record<string, string>>\n}\n\n/**\n * Record every measurement on every metric event into effect `Metric`\n * instruments, then pass events through unchanged. Matches events structurally\n * (`isMetricEvent`), so it records built-in and custom metrics alike, and\n * dispatches on `measurement.kind`, never on the event tag. Sits mid-pipeline\n * before the transport. Provide an OTLP (or Prometheus) layer to export the\n * instruments it populates.\n */\nexport const record =\n (options?: RecordOptions) =>\n <A, E, R>(self: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>\n self.pipe(\n Stream.tap((ev) => (isMetricEvent(ev) ? recordEvent(ev, options?.attributes) : Effect.void)),\n )\n\n// ---------------------------------------------------------------------------\n// OTLP wiring\n// ---------------------------------------------------------------------------\n\nexport type LayerOtlpOptions = {\n readonly url: string\n readonly resource?: {\n readonly serviceName?: string\n readonly serviceVersion?: string\n }\n readonly exportInterval?: Duration.Input\n}\n\n/**\n * Convenience layer that exports recorded metrics over OTLP. Provides the JSON\n * serializer and leaves `HttpClient` as a requirement, so the platform's client\n * (FetchHttpClient, NodeHttpClient, ...) is provided at the edge. This keeps\n * the library platform-independent.\n */\nexport const layerOtlp = (\n options: LayerOtlpOptions,\n): Layer.Layer<never, never, HttpClient.HttpClient> =>\n OtlpMetrics.layer(options).pipe(Layer.provide(OtlpSerialization.layerJson))\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,sBAAsB,OAAO,sBAAsB;CAAE,OAAO;CAAG,QAAQ;CAAG,OAAO;AAAG,CAAC;;;;;;;AAQ3F,MAAM,mBAAmB,MACvB,MAAM,MAAM,EAAE,IAAI,CAAC,CAAC,KAClB,MAAM,KAAK,iBAAiB,OAAO,QAAQ,EAAE,MAAM,EAAE,aAAa,KAAK,CAAC,CAAC,GACzE,MAAM,KAAK,mBAAmB,OAAO,UAAU,EAAE,MAAM,EAAE,YAAY,oBAAoB,CAAC,CAAC,GAC3F,MAAM,KAAK,eAAe,OAAO,MAAM,EAAE,IAAI,CAAC,GAC9C,MAAM,KAAK,eAAe,OAAO,MAAM,EAAE,IAAI,CAAC,GAC9C,MAAM,UACR;AAEF,MAAM,mBACJ,MACA,UAEA,SAAS,KAAA,IAAY,QAAQ,UAAU,KAAA,IAAY,OAAO;CAAE,GAAG;CAAM,GAAG;AAAM;AAEhF,MAAM,eACJ,IACA,mBAEA,OAAO,QACL,GAAG,eACF,MAAM;CACL,MAAM,aAAa,gBAAgB,gBAAgB,EAAE,UAAU;CAC/D,MAAM,OAAO,gBAAgB,CAAC;CAC9B,MAAM,aAAa,eAAe,KAAA,IAAY,OAAO,OAAO,eAAe,MAAM,UAAU;CAC3F,OAAO,OAAO,OAAO,YAAY,EAAE,KAAK;AAC1C,GACA,EAAE,SAAS,KAAK,CAClB;;;;;;;;;AAeF,MAAa,UACV,aACS,SACR,KAAK,KACH,OAAO,KAAK,OAAQ,cAAc,EAAE,IAAI,YAAY,IAAI,SAAS,UAAU,IAAI,OAAO,IAAK,CAC7F;;;;;;;AAqBJ,MAAa,aACX,YAEA,YAAY,MAAM,OAAO,CAAC,CAAC,KAAK,MAAM,QAAQ,kBAAkB,SAAS,CAAC"}
@@ -1 +1 @@
1
- export { };
1
+ export {}
@@ -1,7 +1,8 @@
1
1
  import { makeEvent } from "./Metrics.mjs";
2
2
  import { layerOtlp, record } from "./Telemetry.mjs";
3
- import { n as globalExpect, o as describe } from "../dist-CcRV3-A5.mjs";
4
- import { t as it } from "../dist-C0m0QnUP.mjs";
3
+ import { o as describe } from "../utils-CiH_DjFW.mjs";
4
+ import { n as globalExpect } from "../test.DNmyFkvJ-YPzDR0Co.mjs";
5
+ import { t as it } from "../dist-nohcnkD6.mjs";
5
6
  import { Array, Duration, Effect, Layer, Metric, Option, Ref, Stream } from "effect";
6
7
  import { HttpClient, HttpClientResponse } from "effect/unstable/http";
7
8
  //#region src/observability/Telemetry.test.ts
@@ -20,7 +21,8 @@ describe("record", () => {
20
21
  value: 5
21
22
  }]);
22
23
  yield* Stream.make(ev, ev).pipe(record(), Stream.runDrain);
23
- const c = findById(yield* Metric.snapshot, "rec_counter");
24
+ const snap = yield* Metric.snapshot;
25
+ const c = findById(snap, "rec_counter");
24
26
  globalExpect(c.type).toBe("Counter");
25
27
  globalExpect(c.state.count).toBe(10);
26
28
  })));
@@ -31,7 +33,8 @@ describe("record", () => {
31
33
  value: Duration.millis(100)
32
34
  }]);
33
35
  yield* Stream.make(ev).pipe(record(), Stream.runDrain);
34
- const h = findById(yield* Metric.snapshot, "rec_timer");
36
+ const snap = yield* Metric.snapshot;
37
+ const h = findById(snap, "rec_timer");
35
38
  globalExpect(h.type).toBe("Histogram");
36
39
  globalExpect(h.state.count).toBe(1);
37
40
  })));
@@ -42,7 +45,9 @@ describe("record", () => {
42
45
  value: 1
43
46
  }]);
44
47
  yield* Stream.make(ev).pipe(record({ attributes: { model: "test-model" } }), Stream.runDrain);
45
- globalExpect(findById(yield* Metric.snapshot, "rec_attr").attributes).toMatchObject({ model: "test-model" });
48
+ const snap = yield* Metric.snapshot;
49
+ const c = findById(snap, "rec_attr");
50
+ globalExpect(c.attributes).toMatchObject({ model: "test-model" });
46
51
  })));
47
52
  it.effect("records a custom metric with a novel name, unchanged recorder", () => isolated(Effect.gen(function* () {
48
53
  const custom = makeEvent({
@@ -55,10 +60,13 @@ describe("record", () => {
55
60
  }]
56
61
  });
57
62
  yield* Stream.make(custom).pipe(record(), Stream.runDrain);
58
- globalExpect(findById(yield* Metric.snapshot, "myapp_tool_latency_total").state.count).toBe(3);
63
+ const snap = yield* Metric.snapshot;
64
+ const c = findById(snap, "myapp_tool_latency_total");
65
+ globalExpect(c.state.count).toBe(3);
59
66
  })));
60
67
  it.effect("passes non-metric elements through untouched", () => isolated(Effect.gen(function* () {
61
- globalExpect(yield* Stream.make("a", "b", "c").pipe(record(), Stream.runCollect)).toEqual([
68
+ const out = yield* Stream.make("a", "b", "c").pipe(record(), Stream.runCollect);
69
+ globalExpect(out).toEqual([
62
70
  "a",
63
71
  "b",
64
72
  "c"
@@ -1 +1 @@
1
- {"version":3,"file":"Telemetry.test.mjs","names":["Arr"],"sources":["../../src/observability/Telemetry.test.ts"],"sourcesContent":["import { describe, it } from \"@effect/vitest\"\nimport { Array as Arr, Duration, Effect, Layer, Metric, Option, Ref, Stream } from \"effect\"\nimport { type HttpBody, HttpClient, HttpClientResponse } from \"effect/unstable/http\"\nimport { expect } from \"vitest\"\nimport { type Measurement, makeEvent } from \"./Metrics.js\"\nimport { layerOtlp, record } from \"./Telemetry.js\"\n\nconst event = (measurements: ReadonlyArray<Measurement>) =>\n makeEvent({ _tag: \"Test\", turnIndex: 0, measurements })\n\n// Each test gets a fresh registry so instruments do not leak across tests.\nconst isolated = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Effect.provideService(self, Metric.MetricRegistry, new Map())\n\nconst findById = (snap: ReadonlyArray<Metric.Metric.Snapshot>, id: string) =>\n Option.getOrThrow(Arr.findFirst(snap, (s) => s.id === id))\n\ndescribe(\"record\", () => {\n it.effect(\"accumulates a counter measurement across events\", () =>\n isolated(\n Effect.gen(function* () {\n const ev = event([{ name: \"rec_counter\", kind: \"counter\", value: 5 }])\n yield* Stream.make(ev, ev).pipe(record(), Stream.runDrain)\n const snap = yield* Metric.snapshot\n const c = findById(snap, \"rec_counter\")\n expect(c.type).toBe(\"Counter\")\n expect((c.state as { readonly count: number }).count).toBe(10)\n }),\n ),\n )\n\n it.effect(\"records a timer measurement as a histogram observation\", () =>\n isolated(\n Effect.gen(function* () {\n const ev = event([{ name: \"rec_timer\", kind: \"timer\", value: Duration.millis(100) }])\n yield* Stream.make(ev).pipe(record(), Stream.runDrain)\n const snap = yield* Metric.snapshot\n const h = findById(snap, \"rec_timer\")\n expect(h.type).toBe(\"Histogram\")\n expect((h.state as { readonly count: number }).count).toBe(1)\n }),\n ),\n )\n\n it.effect(\"applies base attributes to every recorded metric\", () =>\n isolated(\n Effect.gen(function* () {\n const ev = event([{ name: \"rec_attr\", kind: \"counter\", value: 1 }])\n yield* Stream.make(ev).pipe(\n record({ attributes: { model: \"test-model\" } }),\n Stream.runDrain,\n )\n const snap = yield* Metric.snapshot\n const c = findById(snap, \"rec_attr\")\n expect(c.attributes).toMatchObject({ model: \"test-model\" })\n }),\n ),\n )\n\n it.effect(\"records a custom metric with a novel name, unchanged recorder\", () =>\n isolated(\n Effect.gen(function* () {\n // A user-defined event the recorder has never seen: still exported.\n const custom = makeEvent({\n _tag: \"ToolLatency\",\n turnIndex: 0,\n measurements: [{ name: \"myapp_tool_latency_total\", kind: \"counter\", value: 3 }],\n })\n yield* Stream.make(custom).pipe(record(), Stream.runDrain)\n const snap = yield* Metric.snapshot\n const c = findById(snap, \"myapp_tool_latency_total\")\n expect((c.state as { readonly count: number }).count).toBe(3)\n }),\n ),\n )\n\n it.effect(\"passes non-metric elements through untouched\", () =>\n isolated(\n Effect.gen(function* () {\n const out = yield* Stream.make(\"a\", \"b\", \"c\").pipe(record(), Stream.runCollect)\n expect(out).toEqual([\"a\", \"b\", \"c\"])\n }),\n ),\n )\n})\n\nconst bodyToString = (body: HttpBody.HttpBody): string =>\n body._tag === \"Uint8Array\" ? new TextDecoder().decode(body.body) : \"\"\n\ndescribe(\"layerOtlp\", () => {\n it.effect(\"exports recorded metrics over OTLP via a mock HttpClient\", () =>\n isolated(\n Effect.gen(function* () {\n const bodies = yield* Ref.make<ReadonlyArray<string>>([])\n const mockClient = HttpClient.make((request) =>\n Ref.update(bodies, (b) => [...b, bodyToString(request.body)]).pipe(\n Effect.as(HttpClientResponse.fromWeb(request, new Response(\"{}\", { status: 200 }))),\n ),\n )\n const clientLayer = Layer.succeed(HttpClient.HttpClient, mockClient)\n const ev = event([{ name: \"otlp_export_counter\", kind: \"counter\", value: 3 }])\n\n // Provide the OTLP layer scoped to the recording program. The exporter\n // flushes on scope close (interval is long, so we rely on the flush).\n yield* Stream.make(ev).pipe(\n record(),\n Stream.runDrain,\n Effect.provide(\n layerOtlp({\n url: \"http://localhost:4318/v1/metrics\",\n resource: { serviceName: \"test-service\" },\n exportInterval: \"10 minutes\",\n }).pipe(Layer.provide(clientLayer)),\n ),\n )\n\n const captured = yield* Ref.get(bodies)\n expect(captured.length).toBeGreaterThanOrEqual(1)\n expect(captured.join(\"\\n\")).toContain(\"otlp_export_counter\")\n }),\n ),\n )\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"Telemetry.test.mjs","names":["Arr"],"sources":["../../src/observability/Telemetry.test.ts"],"sourcesContent":["import { describe, it } from \"@effect/vitest\"\nimport { Array as Arr, Duration, Effect, Layer, Metric, Option, Ref, Stream } from \"effect\"\nimport { type HttpBody, HttpClient, HttpClientResponse } from \"effect/unstable/http\"\nimport { expect } from \"vitest\"\nimport { type Measurement, makeEvent } from \"./Metrics.js\"\nimport { layerOtlp, record } from \"./Telemetry.js\"\n\nconst event = (measurements: ReadonlyArray<Measurement>) =>\n makeEvent({ _tag: \"Test\", turnIndex: 0, measurements })\n\n// Each test gets a fresh registry so instruments do not leak across tests.\nconst isolated = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Effect.provideService(self, Metric.MetricRegistry, new Map())\n\nconst findById = (snap: ReadonlyArray<Metric.Metric.Snapshot>, id: string) =>\n Option.getOrThrow(Arr.findFirst(snap, (s) => s.id === id))\n\ndescribe(\"record\", () => {\n it.effect(\"accumulates a counter measurement across events\", () =>\n isolated(\n Effect.gen(function* () {\n const ev = event([{ name: \"rec_counter\", kind: \"counter\", value: 5 }])\n yield* Stream.make(ev, ev).pipe(record(), Stream.runDrain)\n const snap = yield* Metric.snapshot\n const c = findById(snap, \"rec_counter\")\n expect(c.type).toBe(\"Counter\")\n expect((c.state as { readonly count: number }).count).toBe(10)\n }),\n ),\n )\n\n it.effect(\"records a timer measurement as a histogram observation\", () =>\n isolated(\n Effect.gen(function* () {\n const ev = event([{ name: \"rec_timer\", kind: \"timer\", value: Duration.millis(100) }])\n yield* Stream.make(ev).pipe(record(), Stream.runDrain)\n const snap = yield* Metric.snapshot\n const h = findById(snap, \"rec_timer\")\n expect(h.type).toBe(\"Histogram\")\n expect((h.state as { readonly count: number }).count).toBe(1)\n }),\n ),\n )\n\n it.effect(\"applies base attributes to every recorded metric\", () =>\n isolated(\n Effect.gen(function* () {\n const ev = event([{ name: \"rec_attr\", kind: \"counter\", value: 1 }])\n yield* Stream.make(ev).pipe(\n record({ attributes: { model: \"test-model\" } }),\n Stream.runDrain,\n )\n const snap = yield* Metric.snapshot\n const c = findById(snap, \"rec_attr\")\n expect(c.attributes).toMatchObject({ model: \"test-model\" })\n }),\n ),\n )\n\n it.effect(\"records a custom metric with a novel name, unchanged recorder\", () =>\n isolated(\n Effect.gen(function* () {\n // A user-defined event the recorder has never seen: still exported.\n const custom = makeEvent({\n _tag: \"ToolLatency\",\n turnIndex: 0,\n measurements: [{ name: \"myapp_tool_latency_total\", kind: \"counter\", value: 3 }],\n })\n yield* Stream.make(custom).pipe(record(), Stream.runDrain)\n const snap = yield* Metric.snapshot\n const c = findById(snap, \"myapp_tool_latency_total\")\n expect((c.state as { readonly count: number }).count).toBe(3)\n }),\n ),\n )\n\n it.effect(\"passes non-metric elements through untouched\", () =>\n isolated(\n Effect.gen(function* () {\n const out = yield* Stream.make(\"a\", \"b\", \"c\").pipe(record(), Stream.runCollect)\n expect(out).toEqual([\"a\", \"b\", \"c\"])\n }),\n ),\n )\n})\n\nconst bodyToString = (body: HttpBody.HttpBody): string =>\n body._tag === \"Uint8Array\" ? new TextDecoder().decode(body.body) : \"\"\n\ndescribe(\"layerOtlp\", () => {\n it.effect(\"exports recorded metrics over OTLP via a mock HttpClient\", () =>\n isolated(\n Effect.gen(function* () {\n const bodies = yield* Ref.make<ReadonlyArray<string>>([])\n const mockClient = HttpClient.make((request) =>\n Ref.update(bodies, (b) => [...b, bodyToString(request.body)]).pipe(\n Effect.as(HttpClientResponse.fromWeb(request, new Response(\"{}\", { status: 200 }))),\n ),\n )\n const clientLayer = Layer.succeed(HttpClient.HttpClient, mockClient)\n const ev = event([{ name: \"otlp_export_counter\", kind: \"counter\", value: 3 }])\n\n // Provide the OTLP layer scoped to the recording program. The exporter\n // flushes on scope close (interval is long, so we rely on the flush).\n yield* Stream.make(ev).pipe(\n record(),\n Stream.runDrain,\n Effect.provide(\n layerOtlp({\n url: \"http://localhost:4318/v1/metrics\",\n resource: { serviceName: \"test-service\" },\n exportInterval: \"10 minutes\",\n }).pipe(Layer.provide(clientLayer)),\n ),\n )\n\n const captured = yield* Ref.get(bodies)\n expect(captured.length).toBeGreaterThanOrEqual(1)\n expect(captured.join(\"\\n\")).toContain(\"otlp_export_counter\")\n }),\n ),\n )\n})\n"],"mappings":";;;;;;;;AAOA,MAAM,SAAS,iBACb,UAAU;CAAE,MAAM;CAAQ,WAAW;CAAG;AAAa,CAAC;AAGxD,MAAM,YAAqB,SACzB,OAAO,eAAe,MAAM,OAAO,gCAAgB,IAAI,IAAI,CAAC;AAE9D,MAAM,YAAY,MAA6C,OAC7D,OAAO,WAAWA,MAAI,UAAU,OAAO,MAAM,EAAE,OAAO,EAAE,CAAC;AAE3D,SAAS,gBAAgB;CACvB,GAAG,OAAO,yDACR,SACE,OAAO,IAAI,aAAa;EACtB,MAAM,KAAK,MAAM,CAAC;GAAE,MAAM;GAAe,MAAM;GAAW,OAAO;EAAE,CAAC,CAAC;EACrE,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,OAAO,GAAG,OAAO,QAAQ;EACzD,MAAM,OAAO,OAAO,OAAO;EAC3B,MAAM,IAAI,SAAS,MAAM,aAAa;EACtC,aAAO,EAAE,IAAI,CAAC,CAAC,KAAK,SAAS;EAC7B,aAAQ,EAAE,MAAqC,KAAK,CAAC,CAAC,KAAK,EAAE;CAC/D,CAAC,CACH,CACF;CAEA,GAAG,OAAO,gEACR,SACE,OAAO,IAAI,aAAa;EACtB,MAAM,KAAK,MAAM,CAAC;GAAE,MAAM;GAAa,MAAM;GAAS,OAAO,SAAS,OAAO,GAAG;EAAE,CAAC,CAAC;EACpF,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,KAAK,OAAO,GAAG,OAAO,QAAQ;EACrD,MAAM,OAAO,OAAO,OAAO;EAC3B,MAAM,IAAI,SAAS,MAAM,WAAW;EACpC,aAAO,EAAE,IAAI,CAAC,CAAC,KAAK,WAAW;EAC/B,aAAQ,EAAE,MAAqC,KAAK,CAAC,CAAC,KAAK,CAAC;CAC9D,CAAC,CACH,CACF;CAEA,GAAG,OAAO,0DACR,SACE,OAAO,IAAI,aAAa;EACtB,MAAM,KAAK,MAAM,CAAC;GAAE,MAAM;GAAY,MAAM;GAAW,OAAO;EAAE,CAAC,CAAC;EAClE,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,KACrB,OAAO,EAAE,YAAY,EAAE,OAAO,aAAa,EAAE,CAAC,GAC9C,OAAO,QACT;EACA,MAAM,OAAO,OAAO,OAAO;EAC3B,MAAM,IAAI,SAAS,MAAM,UAAU;EACnC,aAAO,EAAE,UAAU,CAAC,CAAC,cAAc,EAAE,OAAO,aAAa,CAAC;CAC5D,CAAC,CACH,CACF;CAEA,GAAG,OAAO,uEACR,SACE,OAAO,IAAI,aAAa;EAEtB,MAAM,SAAS,UAAU;GACvB,MAAM;GACN,WAAW;GACX,cAAc,CAAC;IAAE,MAAM;IAA4B,MAAM;IAAW,OAAO;GAAE,CAAC;EAChF,CAAC;EACD,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK,OAAO,GAAG,OAAO,QAAQ;EACzD,MAAM,OAAO,OAAO,OAAO;EAC3B,MAAM,IAAI,SAAS,MAAM,0BAA0B;EACnD,aAAQ,EAAE,MAAqC,KAAK,CAAC,CAAC,KAAK,CAAC;CAC9D,CAAC,CACH,CACF;CAEA,GAAG,OAAO,sDACR,SACE,OAAO,IAAI,aAAa;EACtB,MAAM,MAAM,OAAO,OAAO,KAAK,KAAK,KAAK,GAAG,CAAC,CAAC,KAAK,OAAO,GAAG,OAAO,UAAU;EAC9E,aAAO,GAAG,CAAC,CAAC,QAAQ;GAAC;GAAK;GAAK;EAAG,CAAC;CACrC,CAAC,CACH,CACF;AACF,CAAC;AAED,MAAM,gBAAgB,SACpB,KAAK,SAAS,eAAe,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI;AAErE,SAAS,mBAAmB;CAC1B,GAAG,OAAO,kEACR,SACE,OAAO,IAAI,aAAa;EACtB,MAAM,SAAS,OAAO,IAAI,KAA4B,CAAC,CAAC;EACxD,MAAM,aAAa,WAAW,MAAM,YAClC,IAAI,OAAO,SAAS,MAAM,CAAC,GAAG,GAAG,aAAa,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,KAC5D,OAAO,GAAG,mBAAmB,QAAQ,SAAS,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC,CACpF,CACF;EACA,MAAM,cAAc,MAAM,QAAQ,WAAW,YAAY,UAAU;EACnE,MAAM,KAAK,MAAM,CAAC;GAAE,MAAM;GAAuB,MAAM;GAAW,OAAO;EAAE,CAAC,CAAC;EAI7E,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,KACrB,OAAO,GACP,OAAO,UACP,OAAO,QACL,UAAU;GACR,KAAK;GACL,UAAU,EAAE,aAAa,eAAe;GACxC,gBAAgB;EAClB,CAAC,CAAC,CAAC,KAAK,MAAM,QAAQ,WAAW,CAAC,CACpC,CACF;EAEA,MAAM,WAAW,OAAO,IAAI,IAAI,MAAM;EACtC,aAAO,SAAS,MAAM,CAAC,CAAC,uBAAuB,CAAC;EAChD,aAAO,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,qBAAqB;CAC7D,CAAC,CACH,CACF;AACF,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { t as AiError } from "../AiError-eLV9t1lU.mjs";
2
+ import { Context, Effect } from "effect";
3
+ declare namespace Reranker_d_exports {
4
+ export { CommonRerankRequest, RerankResponse, RerankResult, RerankUsage, Reranker, RerankerService, rerank };
5
+ }
6
+ /**
7
+ * Cross-provider rerank request. Vendor knobs (multimodal documents,
8
+ * instruction fields, truncation) live on the provider's typed request.
9
+ */
10
+ type CommonRerankRequest = {
11
+ readonly query: string;
12
+ readonly documents: ReadonlyArray<string>;
13
+ /** Each provider narrows this to its typed literal union. */
14
+ readonly model: string;
15
+ /** Keep only the top N results. Default: all documents. */
16
+ readonly topN?: number;
17
+ };
18
+ type RerankResult = {
19
+ /** Position in the request's `documents`. */
20
+ readonly index: number;
21
+ readonly score: number;
22
+ };
23
+ /** Optional throughout: some providers bill per search unit, not per token. */
24
+ type RerankUsage = {
25
+ readonly totalTokens?: number;
26
+ };
27
+ /**
28
+ * Score contract: `results` is sorted descending, higher is better. Scores
29
+ * order candidates within one call; no range or calibration is promised and
30
+ * they are not comparable across requests. Implementors must sort descending
31
+ * if the wire does not.
32
+ */
33
+ type RerankResponse = {
34
+ readonly results: ReadonlyArray<RerankResult>;
35
+ readonly usage: RerankUsage;
36
+ };
37
+ type RerankerService = {
38
+ readonly rerank: (request: CommonRerankRequest) => Effect.Effect<RerankResponse, AiError>;
39
+ };
40
+ declare const Reranker_base: Context.ServiceClass<Reranker, "@betalyra/effect-uai/Reranker", RerankerService>;
41
+ declare class Reranker extends Reranker_base {}
42
+ /** Score a candidate set against a query, best first. */
43
+ declare const rerank: (request: CommonRerankRequest) => Effect.Effect<RerankResponse, AiError, Reranker>;
44
+ //#endregion
45
+ export { CommonRerankRequest, RerankResponse, RerankResult, RerankUsage, Reranker, RerankerService, rerank, Reranker_d_exports as t };
46
+ //# sourceMappingURL=Reranker.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Reranker.d.mts","names":[],"sources":["../../src/reranker/Reranker.ts"],"mappings":";;;;;;;;;KAOY;WACD;WACA,WAAW;;WAEX;;WAEA;;KAGC;;WAED;WACA;;;KAIC;WACD;;;;;;;;KASC;WACD,SAAS,cAAc;WACvB,OAAO;;KAGN;WACD,SAAS,SAAS,wBAAwB,OAAO,OAAO,gBAAgB;;;cAGtE,iBAAiB;;cAKjB,SAAM,SACR,wBACR,OAAO,OAAO,gBAAgB,SAAiB"}
@@ -0,0 +1,14 @@
1
+ import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
2
+ import { Context, Effect } from "effect";
3
+ //#region src/reranker/Reranker.ts
4
+ var Reranker_exports = /* @__PURE__ */ __exportAll({
5
+ Reranker: () => Reranker,
6
+ rerank: () => rerank
7
+ });
8
+ var Reranker = class extends Context.Service()("@betalyra/effect-uai/Reranker") {};
9
+ /** Score a candidate set against a query, best first. */
10
+ const rerank = (request) => Effect.flatMap(Reranker, (r) => r.rerank(request));
11
+ //#endregion
12
+ export { Reranker, rerank, Reranker_exports as t };
13
+
14
+ //# sourceMappingURL=Reranker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Reranker.mjs","names":[],"sources":["../../src/reranker/Reranker.ts"],"sourcesContent":["import { Context, Effect } from \"effect\"\nimport type * as AiError from \"../domain/AiError.js\"\n\n/**\n * Cross-provider rerank request. Vendor knobs (multimodal documents,\n * instruction fields, truncation) live on the provider's typed request.\n */\nexport type CommonRerankRequest = {\n readonly query: string\n readonly documents: ReadonlyArray<string>\n /** Each provider narrows this to its typed literal union. */\n readonly model: string\n /** Keep only the top N results. Default: all documents. */\n readonly topN?: number\n}\n\nexport type RerankResult = {\n /** Position in the request's `documents`. */\n readonly index: number\n readonly score: number\n}\n\n/** Optional throughout: some providers bill per search unit, not per token. */\nexport type RerankUsage = {\n readonly totalTokens?: number\n}\n\n/**\n * Score contract: `results` is sorted descending, higher is better. Scores\n * order candidates within one call; no range or calibration is promised and\n * they are not comparable across requests. Implementors must sort descending\n * if the wire does not.\n */\nexport type RerankResponse = {\n readonly results: ReadonlyArray<RerankResult>\n readonly usage: RerankUsage\n}\n\nexport type RerankerService = {\n readonly rerank: (request: CommonRerankRequest) => Effect.Effect<RerankResponse, AiError.AiError>\n}\n\nexport class Reranker extends Context.Service<Reranker, RerankerService>()(\n \"@betalyra/effect-uai/Reranker\",\n) {}\n\n/** Score a candidate set against a query, best first. */\nexport const rerank = (\n request: CommonRerankRequest,\n): Effect.Effect<RerankResponse, AiError.AiError, Reranker> =>\n Effect.flatMap(Reranker, (r) => r.rerank(request))\n"],"mappings":";;;;;;;AA0CA,IAAa,WAAb,cAA8B,QAAQ,QAAmC,CAAC,CACxE,+BACF,CAAC,CAAC,CAAC;;AAGH,MAAa,UACX,YAEA,OAAO,QAAQ,WAAW,MAAM,EAAE,OAAO,OAAO,CAAC"}
@@ -1,10 +1,8 @@
1
- import { t as AiError } from "../AiError-Bf1pq4BB.mjs";
1
+ import { t as AiError } from "../AiError-eLV9t1lU.mjs";
2
2
  import { JobConfig } from "../job/Job.mjs";
3
3
  import { Turn, TurnEvent } from "../domain/Turn.mjs";
4
4
  import { ResearchJobRef, ResearchRequest, ResearchState } from "../domain/Research.mjs";
5
5
  import { Context, Effect, Stream } from "effect";
6
-
7
- //#region src/research/DeepResearch.d.ts
8
6
  declare namespace DeepResearch_d_exports {
9
7
  export { DeepResearch, DeepResearchService, DeepResearchServiceShape, ResearchJobOps, ResearchJobRef, ResearchRequest, ResearchState, cancel, collect, fromJob, research, researchStream, status, streamFrom, submit };
10
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DeepResearch.d.mts","names":[],"sources":["../../src/research/DeepResearch.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;KAuBY,wBAAA;EAAA,SACD,MAAA,GAAS,OAAA,EAAS,GAAA,KAAQ,MAAA,CAAO,MAAA,CAAO,cAAA,EAAgB,OAAA;EAAA,SACxD,MAAA,GAAS,GAAA,EAAK,cAAA,KAAmB,MAAA,CAAO,MAAA,CAAO,aAAA,EAAe,OAAA;EAAA,SAC9D,OAAA,GAAU,GAAA,EAAK,cAAA,KAAmB,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,OAAA;EAAA,SACtD,UAAA,GAAa,GAAA,EAAK,cAAA,KAAmB,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA;EAAA,SAC9D,MAAA,GAAS,GAAA,EAAK,cAAA,KAAmB,MAAA,CAAO,MAAA,OAAa,OAAA;EAAA,SACrD,QAAA,GAAW,OAAA,EAAS,GAAA,KAAQ,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,OAAA;EAAA,SAChD,cAAA,GAAiB,OAAA,EAAS,GAAA,KAAQ,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA;AAAA;AAAA,KAG1D,mBAAA,GAAsB,wBAAA,CAAyB,eAAA;AAAA,cAAgB,iBAAA;cAE9D,YAAA,SAAqB,iBAAA;;;KAWtB,cAAA;EAAA,SACD,MAAA,GAAS,OAAA,EAAS,GAAA,KAAQ,MAAA,CAAO,MAAA,CAAO,cAAA,EAAgB,OAAA;EAAA,SACxD,IAAA,GAAO,GAAA,EAAK,cAAA,KAAmB,MAAA,CAAO,MAAA,CAAO,aAAA,EAAe,OAAA;EAAA,SAC5D,MAAA,GAAS,GAAA,EAAK,cAAA,KAAmB,MAAA,CAAO,MAAA,OAAa,OAAA;EAAA,SACrD,UAAA,IAAc,GAAA,EAAK,cAAA,KAAmB,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA;AAAA;;;;;;;;;;cA2B7D,OAAA,eAAuB,eAAA,EAClC,GAAA,EAAK,cAAA,CAAe,GAAA,GACpB,MAAA,GAAS,SAAA,KACR,wBAAA,CAAyB,GAAA;;cAqBf,QAAA,GACX,OAAA,EAAS,eAAA,KACR,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,OAAA,EAAiB,YAAA;;cAI3B,cAAA,GACX,OAAA,EAAS,eAAA,KACR,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA,EAAiB,YAAA;;cAIhC,MAAA,GACX,OAAA,EAAS,eAAA,KACR,MAAA,CAAO,MAAA,CAAO,cAAA,EAAgB,OAAA,EAAiB,YAAA;;cAIrC,MAAA,GACX,GAAA,EAAK,cAAA,KACJ,MAAA,CAAO,MAAA,CAAO,aAAA,EAAe,OAAA,EAAiB,YAAA;;cAIpC,OAAA,GAAW,GAAA,EAAK,cAAA,KAAiB,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,OAAA,EAAiB,YAAA;;cAItE,UAAA,GACX,GAAA,EAAK,cAAA,KACJ,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA,EAAiB,YAAA;;cAIhC,MAAA,GAAU,GAAA,EAAK,cAAA,KAAiB,MAAA,CAAO,MAAA,OAAa,OAAA,EAAiB,YAAA"}
1
+ {"version":3,"file":"DeepResearch.d.mts","names":[],"sources":["../../src/research/DeepResearch.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;KAuBY,yBAAyB;WAC1B,SAAS,SAAS,QAAQ,OAAO,OAAO,gBAAgB;WACxD,SAAS,KAAK,mBAAmB,OAAO,OAAO,eAAe;WAC9D,UAAU,KAAK,mBAAmB,OAAO,OAAO,MAAM;WACtD,aAAa,KAAK,mBAAmB,OAAO,OAAO,WAAW;WAC9D,SAAS,KAAK,mBAAmB,OAAO,aAAa;WACrD,WAAW,SAAS,QAAQ,OAAO,OAAO,MAAM;WAChD,iBAAiB,SAAS,QAAQ,OAAO,OAAO,WAAW;;KAG1D,sBAAsB,yBAAyB;;cAE9C,qBAAqB;;;KAWtB,eAAe;WAChB,SAAS,SAAS,QAAQ,OAAO,OAAO,gBAAgB;WACxD,OAAO,KAAK,mBAAmB,OAAO,OAAO,eAAe;WAC5D,SAAS,KAAK,mBAAmB,OAAO,aAAa;WACrD,cAAc,KAAK,mBAAmB,OAAO,OAAO,WAAW;;;;;;;;;;;cA2B7D,UAAW,YAAY,iBAAe,KAC5C,eAAe,MAAI,SACf,cACR,yBAAyB;;cAqBf,WAAQ,SACV,oBACR,OAAO,OAAO,MAAM,SAAiB;;cAI3B,iBAAc,SAChB,oBACR,OAAO,OAAO,WAAW,SAAiB;;cAIhC,SAAM,SACR,oBACR,OAAO,OAAO,gBAAgB,SAAiB;;cAIrC,SAAM,KACZ,mBACJ,OAAO,OAAO,eAAe,SAAiB;;cAIpC,UAAO,KAAS,mBAAiB,OAAO,OAAO,MAAM,SAAiB;;cAItE,aAAU,KAChB,mBACJ,OAAO,OAAO,WAAW,SAAiB;;cAIhC,SAAM,KAAS,mBAAiB,OAAO,aAAa,SAAiB"}
@@ -1,4 +1,4 @@
1
- import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
1
+ import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
2
2
  import { TurnEvent } from "../domain/Turn.mjs";
3
3
  import { collect as collect$1, run } from "../job/Job.mjs";
4
4
  import { Context, Effect, Stream } from "effect";
@@ -1 +1 @@
1
- {"version":3,"file":"DeepResearch.mjs","names":["Job.collect","Job.run"],"sources":["../../src/research/DeepResearch.ts"],"sourcesContent":["import { Context, Effect, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport * as Job from \"../job/Job.js\"\nimport type { ResearchJobRef, ResearchRequest, ResearchState } from \"../domain/Research.js\"\nimport type { Turn } from \"../domain/Turn.js\"\nimport { TurnEvent } from \"../domain/Turn.js\"\n\nexport type { ResearchJobRef, ResearchRequest, ResearchState } from \"../domain/Research.js\"\n\n/**\n * Deep research: submit a question, watch a long-running background job, collect\n * one cited report. Every provider is modeled as a job (`submit` / `poll` /\n * `cancel`), so the surface is uniform. The convenience derivations\n * (`research` / `researchStream` / `collect` / `status`) are the same for every\n * provider and are built once by {@link fromJob}, so an implementor states only\n * its wire calls, never the poll loop.\n *\n * `research` is the blocking one-liner (submit then poll to the terminal `Turn`);\n * `researchStream` forwards live progress as `TurnEvent`s, terminating in\n * `TurnComplete` whose `turn` is the value `research` / `collect` return. The job\n * ref is plain serializable data, so it can be persisted and collected from a\n * later process where the provider's job is server-backed.\n */\nexport type DeepResearchServiceShape<Req> = {\n readonly submit: (request: Req) => Effect.Effect<ResearchJobRef, AiError.AiError>\n readonly status: (ref: ResearchJobRef) => Effect.Effect<ResearchState, AiError.AiError>\n readonly collect: (ref: ResearchJobRef) => Effect.Effect<Turn, AiError.AiError>\n readonly streamFrom: (ref: ResearchJobRef) => Stream.Stream<TurnEvent, AiError.AiError>\n readonly cancel: (ref: ResearchJobRef) => Effect.Effect<void, AiError.AiError>\n readonly research: (request: Req) => Effect.Effect<Turn, AiError.AiError>\n readonly researchStream: (request: Req) => Stream.Stream<TurnEvent, AiError.AiError>\n}\n\nexport type DeepResearchService = DeepResearchServiceShape<ResearchRequest>\n\nexport class DeepResearch extends Context.Service<DeepResearch, DeepResearchService>()(\n \"@betalyra/effect-uai/DeepResearch\",\n) {}\n\n// ---------------------------------------------------------------------------\n// fromJob: build the whole service from the three job ops (+ an optional real\n// live stream). The derivations are identical for every provider.\n// ---------------------------------------------------------------------------\n\n/** The wire ops a provider supplies. `streamFrom` is optional: poll-only jobs\n * get a synthesized stream ({@link synthesizedStream}) in its place. */\nexport type ResearchJobOps<Req> = {\n readonly submit: (request: Req) => Effect.Effect<ResearchJobRef, AiError.AiError>\n readonly poll: (ref: ResearchJobRef) => Effect.Effect<ResearchState, AiError.AiError>\n readonly cancel: (ref: ResearchJobRef) => Effect.Effect<void, AiError.AiError>\n readonly streamFrom?: (ref: ResearchJobRef) => Stream.Stream<TurnEvent, AiError.AiError>\n}\n\n// A poll-only job has no event stream, so synthesize one: a leading \"searching\"\n// progress event, then the terminal `TurnComplete` off the poll loop. Honest\n// low-fidelity progress, not a fabricated per-search feed.\nconst synthesizedStream = <Req>(\n ops: ResearchJobOps<Req>,\n ref: ResearchJobRef,\n config?: Job.JobConfig,\n): Stream.Stream<TurnEvent, AiError.AiError> =>\n Stream.concat(\n Stream.make(TurnEvent.WebSearchCall({ status: \"searching\" })),\n Stream.map(Stream.fromEffect(Job.collect(ops.poll, ref, config)), (turn) =>\n TurnEvent.TurnComplete({ turn }),\n ),\n )\n\n/**\n * Assemble a {@link DeepResearchServiceShape} from the job ops. `research` is\n * `submit` then poll-to-settle (best-effort cancel on interrupt, via\n * {@link Job.run}); `collect` / `status` are the detached equivalents;\n * `researchStream` submits then attaches. Generic over the request type so a\n * provider-typed tag keeps its narrowed `submit`. `config` tunes the poll\n * cadence and overall timeout of every derived poll loop (see\n * {@link Job.JobConfig} for the defaults).\n */\nexport const fromJob = <Req extends ResearchRequest>(\n ops: ResearchJobOps<Req>,\n config?: Job.JobConfig,\n): DeepResearchServiceShape<Req> => {\n const streamFrom =\n ops.streamFrom ?? ((ref: ResearchJobRef) => synthesizedStream(ops, ref, config))\n return {\n submit: ops.submit,\n status: ops.poll,\n collect: (ref) => Job.collect(ops.poll, ref, config),\n cancel: ops.cancel,\n streamFrom,\n research: (request) =>\n Job.run({ submit: ops.submit(request), poll: ops.poll, cancel: ops.cancel }, config),\n researchStream: (request) => Stream.unwrap(Effect.map(ops.submit(request), streamFrom)),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Top-level accessors over the generic tag. Portable code uses these; they\n// require only `DeepResearch` in `R`.\n// ---------------------------------------------------------------------------\n\n/** Submit and poll to the terminal `Turn`. Cancels the job on interrupt. */\nexport const research = (\n request: ResearchRequest,\n): Effect.Effect<Turn, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.research(request))\n\n/** Submit and forward live progress, terminating in `TurnComplete`. */\nexport const researchStream = (\n request: ResearchRequest,\n): Stream.Stream<TurnEvent, AiError.AiError, DeepResearch> =>\n Stream.unwrap(Effect.map(DeepResearch, (s) => s.researchStream(request)))\n\n/** Submit a detached job and return its ref. */\nexport const submit = (\n request: ResearchRequest,\n): Effect.Effect<ResearchJobRef, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.submit(request))\n\n/** Current state of a job. */\nexport const status = (\n ref: ResearchJobRef,\n): Effect.Effect<ResearchState, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.status(ref))\n\n/** Poll a detached job to completion. */\nexport const collect = (ref: ResearchJobRef): Effect.Effect<Turn, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.collect(ref))\n\n/** Attach a live progress stream to a job (call again to re-attach). */\nexport const streamFrom = (\n ref: ResearchJobRef,\n): Stream.Stream<TurnEvent, AiError.AiError, DeepResearch> =>\n Stream.unwrap(Effect.map(DeepResearch, (s) => s.streamFrom(ref)))\n\n/** Cancel a running job. */\nexport const cancel = (ref: ResearchJobRef): Effect.Effect<void, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.cancel(ref))\n"],"mappings":";;;;;;;;;;;;;;;;AAmCA,IAAa,eAAb,cAAkC,QAAQ,SAA4C,CACpF,oCACD,CAAC;AAmBF,MAAM,qBACJ,KACA,KACA,WAEA,OAAO,OACL,OAAO,KAAK,UAAU,cAAc,EAAE,QAAQ,aAAa,CAAC,CAAC,EAC7D,OAAO,IAAI,OAAO,WAAWA,UAAY,IAAI,MAAM,KAAK,OAAO,CAAC,GAAG,SACjE,UAAU,aAAa,EAAE,MAAM,CAAC,CACjC,CACF;;;;;;;;;;AAWH,MAAa,WACX,KACA,WACkC;CAClC,MAAM,aACJ,IAAI,gBAAgB,QAAwB,kBAAkB,KAAK,KAAK,OAAO;AACjF,QAAO;EACL,QAAQ,IAAI;EACZ,QAAQ,IAAI;EACZ,UAAU,QAAQA,UAAY,IAAI,MAAM,KAAK,OAAO;EACpD,QAAQ,IAAI;EACZ;EACA,WAAW,YACTC,IAAQ;GAAE,QAAQ,IAAI,OAAO,QAAQ;GAAE,MAAM,IAAI;GAAM,QAAQ,IAAI;GAAQ,EAAE,OAAO;EACtF,iBAAiB,YAAY,OAAO,OAAO,OAAO,IAAI,IAAI,OAAO,QAAQ,EAAE,WAAW,CAAC;EACxF;;;AASH,MAAa,YACX,YAEA,OAAO,QAAQ,eAAe,MAAM,EAAE,SAAS,QAAQ,CAAC;;AAG1D,MAAa,kBACX,YAEA,OAAO,OAAO,OAAO,IAAI,eAAe,MAAM,EAAE,eAAe,QAAQ,CAAC,CAAC;;AAG3E,MAAa,UACX,YAEA,OAAO,QAAQ,eAAe,MAAM,EAAE,OAAO,QAAQ,CAAC;;AAGxD,MAAa,UACX,QAEA,OAAO,QAAQ,eAAe,MAAM,EAAE,OAAO,IAAI,CAAC;;AAGpD,MAAa,WAAW,QACtB,OAAO,QAAQ,eAAe,MAAM,EAAE,QAAQ,IAAI,CAAC;;AAGrD,MAAa,cACX,QAEA,OAAO,OAAO,OAAO,IAAI,eAAe,MAAM,EAAE,WAAW,IAAI,CAAC,CAAC;;AAGnE,MAAa,UAAU,QACrB,OAAO,QAAQ,eAAe,MAAM,EAAE,OAAO,IAAI,CAAC"}
1
+ {"version":3,"file":"DeepResearch.mjs","names":["Job.collect","Job.run"],"sources":["../../src/research/DeepResearch.ts"],"sourcesContent":["import { Context, Effect, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport * as Job from \"../job/Job.js\"\nimport type { ResearchJobRef, ResearchRequest, ResearchState } from \"../domain/Research.js\"\nimport type { Turn } from \"../domain/Turn.js\"\nimport { TurnEvent } from \"../domain/Turn.js\"\n\nexport type { ResearchJobRef, ResearchRequest, ResearchState } from \"../domain/Research.js\"\n\n/**\n * Deep research: submit a question, watch a long-running background job, collect\n * one cited report. Every provider is modeled as a job (`submit` / `poll` /\n * `cancel`), so the surface is uniform. The convenience derivations\n * (`research` / `researchStream` / `collect` / `status`) are the same for every\n * provider and are built once by {@link fromJob}, so an implementor states only\n * its wire calls, never the poll loop.\n *\n * `research` is the blocking one-liner (submit then poll to the terminal `Turn`);\n * `researchStream` forwards live progress as `TurnEvent`s, terminating in\n * `TurnComplete` whose `turn` is the value `research` / `collect` return. The job\n * ref is plain serializable data, so it can be persisted and collected from a\n * later process where the provider's job is server-backed.\n */\nexport type DeepResearchServiceShape<Req> = {\n readonly submit: (request: Req) => Effect.Effect<ResearchJobRef, AiError.AiError>\n readonly status: (ref: ResearchJobRef) => Effect.Effect<ResearchState, AiError.AiError>\n readonly collect: (ref: ResearchJobRef) => Effect.Effect<Turn, AiError.AiError>\n readonly streamFrom: (ref: ResearchJobRef) => Stream.Stream<TurnEvent, AiError.AiError>\n readonly cancel: (ref: ResearchJobRef) => Effect.Effect<void, AiError.AiError>\n readonly research: (request: Req) => Effect.Effect<Turn, AiError.AiError>\n readonly researchStream: (request: Req) => Stream.Stream<TurnEvent, AiError.AiError>\n}\n\nexport type DeepResearchService = DeepResearchServiceShape<ResearchRequest>\n\nexport class DeepResearch extends Context.Service<DeepResearch, DeepResearchService>()(\n \"@betalyra/effect-uai/DeepResearch\",\n) {}\n\n// ---------------------------------------------------------------------------\n// fromJob: build the whole service from the three job ops (+ an optional real\n// live stream). The derivations are identical for every provider.\n// ---------------------------------------------------------------------------\n\n/** The wire ops a provider supplies. `streamFrom` is optional: poll-only jobs\n * get a synthesized stream ({@link synthesizedStream}) in its place. */\nexport type ResearchJobOps<Req> = {\n readonly submit: (request: Req) => Effect.Effect<ResearchJobRef, AiError.AiError>\n readonly poll: (ref: ResearchJobRef) => Effect.Effect<ResearchState, AiError.AiError>\n readonly cancel: (ref: ResearchJobRef) => Effect.Effect<void, AiError.AiError>\n readonly streamFrom?: (ref: ResearchJobRef) => Stream.Stream<TurnEvent, AiError.AiError>\n}\n\n// A poll-only job has no event stream, so synthesize one: a leading \"searching\"\n// progress event, then the terminal `TurnComplete` off the poll loop. Honest\n// low-fidelity progress, not a fabricated per-search feed.\nconst synthesizedStream = <Req>(\n ops: ResearchJobOps<Req>,\n ref: ResearchJobRef,\n config?: Job.JobConfig,\n): Stream.Stream<TurnEvent, AiError.AiError> =>\n Stream.concat(\n Stream.make(TurnEvent.WebSearchCall({ status: \"searching\" })),\n Stream.map(Stream.fromEffect(Job.collect(ops.poll, ref, config)), (turn) =>\n TurnEvent.TurnComplete({ turn }),\n ),\n )\n\n/**\n * Assemble a {@link DeepResearchServiceShape} from the job ops. `research` is\n * `submit` then poll-to-settle (best-effort cancel on interrupt, via\n * {@link Job.run}); `collect` / `status` are the detached equivalents;\n * `researchStream` submits then attaches. Generic over the request type so a\n * provider-typed tag keeps its narrowed `submit`. `config` tunes the poll\n * cadence and overall timeout of every derived poll loop (see\n * {@link Job.JobConfig} for the defaults).\n */\nexport const fromJob = <Req extends ResearchRequest>(\n ops: ResearchJobOps<Req>,\n config?: Job.JobConfig,\n): DeepResearchServiceShape<Req> => {\n const streamFrom =\n ops.streamFrom ?? ((ref: ResearchJobRef) => synthesizedStream(ops, ref, config))\n return {\n submit: ops.submit,\n status: ops.poll,\n collect: (ref) => Job.collect(ops.poll, ref, config),\n cancel: ops.cancel,\n streamFrom,\n research: (request) =>\n Job.run({ submit: ops.submit(request), poll: ops.poll, cancel: ops.cancel }, config),\n researchStream: (request) => Stream.unwrap(Effect.map(ops.submit(request), streamFrom)),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Top-level accessors over the generic tag. Portable code uses these; they\n// require only `DeepResearch` in `R`.\n// ---------------------------------------------------------------------------\n\n/** Submit and poll to the terminal `Turn`. Cancels the job on interrupt. */\nexport const research = (\n request: ResearchRequest,\n): Effect.Effect<Turn, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.research(request))\n\n/** Submit and forward live progress, terminating in `TurnComplete`. */\nexport const researchStream = (\n request: ResearchRequest,\n): Stream.Stream<TurnEvent, AiError.AiError, DeepResearch> =>\n Stream.unwrap(Effect.map(DeepResearch, (s) => s.researchStream(request)))\n\n/** Submit a detached job and return its ref. */\nexport const submit = (\n request: ResearchRequest,\n): Effect.Effect<ResearchJobRef, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.submit(request))\n\n/** Current state of a job. */\nexport const status = (\n ref: ResearchJobRef,\n): Effect.Effect<ResearchState, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.status(ref))\n\n/** Poll a detached job to completion. */\nexport const collect = (ref: ResearchJobRef): Effect.Effect<Turn, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.collect(ref))\n\n/** Attach a live progress stream to a job (call again to re-attach). */\nexport const streamFrom = (\n ref: ResearchJobRef,\n): Stream.Stream<TurnEvent, AiError.AiError, DeepResearch> =>\n Stream.unwrap(Effect.map(DeepResearch, (s) => s.streamFrom(ref)))\n\n/** Cancel a running job. */\nexport const cancel = (ref: ResearchJobRef): Effect.Effect<void, AiError.AiError, DeepResearch> =>\n Effect.flatMap(DeepResearch, (s) => s.cancel(ref))\n"],"mappings":";;;;;;;;;;;;;;;;AAmCA,IAAa,eAAb,cAAkC,QAAQ,QAA2C,CAAC,CACpF,mCACF,CAAC,CAAC,CAAC;AAmBH,MAAM,qBACJ,KACA,KACA,WAEA,OAAO,OACL,OAAO,KAAK,UAAU,cAAc,EAAE,QAAQ,YAAY,CAAC,CAAC,GAC5D,OAAO,IAAI,OAAO,WAAWA,UAAY,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,SACjE,UAAU,aAAa,EAAE,KAAK,CAAC,CACjC,CACF;;;;;;;;;;AAWF,MAAa,WACX,KACA,WACkC;CAClC,MAAM,aACJ,IAAI,gBAAgB,QAAwB,kBAAkB,KAAK,KAAK,MAAM;CAChF,OAAO;EACL,QAAQ,IAAI;EACZ,QAAQ,IAAI;EACZ,UAAU,QAAQA,UAAY,IAAI,MAAM,KAAK,MAAM;EACnD,QAAQ,IAAI;EACZ;EACA,WAAW,YACTC,IAAQ;GAAE,QAAQ,IAAI,OAAO,OAAO;GAAG,MAAM,IAAI;GAAM,QAAQ,IAAI;EAAO,GAAG,MAAM;EACrF,iBAAiB,YAAY,OAAO,OAAO,OAAO,IAAI,IAAI,OAAO,OAAO,GAAG,UAAU,CAAC;CACxF;AACF;;AAQA,MAAa,YACX,YAEA,OAAO,QAAQ,eAAe,MAAM,EAAE,SAAS,OAAO,CAAC;;AAGzD,MAAa,kBACX,YAEA,OAAO,OAAO,OAAO,IAAI,eAAe,MAAM,EAAE,eAAe,OAAO,CAAC,CAAC;;AAG1E,MAAa,UACX,YAEA,OAAO,QAAQ,eAAe,MAAM,EAAE,OAAO,OAAO,CAAC;;AAGvD,MAAa,UACX,QAEA,OAAO,QAAQ,eAAe,MAAM,EAAE,OAAO,GAAG,CAAC;;AAGnD,MAAa,WAAW,QACtB,OAAO,QAAQ,eAAe,MAAM,EAAE,QAAQ,GAAG,CAAC;;AAGpD,MAAa,cACX,QAEA,OAAO,OAAO,OAAO,IAAI,eAAe,MAAM,EAAE,WAAW,GAAG,CAAC,CAAC;;AAGlE,MAAa,UAAU,QACrB,OAAO,QAAQ,eAAe,MAAM,EAAE,OAAO,GAAG,CAAC"}
@@ -1,13 +1,9 @@
1
- import { d as RateLimited, m as Unavailable, p as Timeout, t as AiError, u as InvalidRequest } from "../AiError-Bf1pq4BB.mjs";
1
+ import { d as RateLimited, m as Unavailable, p as Timeout, t as AiError, u as InvalidRequest } from "../AiError-eLV9t1lU.mjs";
2
2
  import { Effect, Schedule, Stream } from "effect";
3
- import * as _$effect_Cause0 from "effect/Cause";
4
- import * as _$effect_Types0 from "effect/Types";
5
-
6
- //#region src/retry/Retry.d.ts
7
3
  declare namespace Retry_d_exports {
8
4
  export { Retryable, effect, isRetryable, stream };
9
5
  }
10
- declare const Retryable_base: new <A extends Record<string, any> = {}>(args: _$effect_Types0.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => _$effect_Cause0.YieldableError & {
6
+ declare const Retryable_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
11
7
  readonly _tag: "RetryableAi";
12
8
  } & Readonly<A>;
13
9
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Retry.d.mts","names":[],"sources":["../../src/retry/Retry.ts"],"mappings":";;;;;;;;;cACoD,cAAA;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;cA6BvC,SAAA,SAAkB,cAAA;EAAA,SACpB,KAAA,EACL,WAAA,GACA,WAAA,GACA,OAAA,GACA,cAAA;AAAA;;cAsCO,WAAA,GACX,CAAA,EAAG,OAAA,KACF,CAAA,IAAK,WAAA,GAAsB,WAAA,GAAsB,OAAA,GAAkB,cAAA;;;;;;;cAmBzD,MAAA,QACL,QAAA,EAAU,QAAA,CAAS,QAAA,CAAS,GAAA,EAAK,SAAA,aAChC,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,OAAA,EAAiB,CAAA,MAAK,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,OAAA,EAAiB,CAAA;AAlErF;;;;;;;;;;AAAA,cA2Fa,MAAA,QACL,QAAA,EAAU,QAAA,CAAS,QAAA,CAAS,GAAA,EAAK,OAAA,aAChC,GAAA,EAAK,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,OAAA,EAAiB,CAAA,MAAK,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,OAAA,EAAiB,CAAA"}
1
+ {"version":3,"file":"Retry.d.mts","names":[],"sources":["../../src/retry/Retry.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA8Ba,kBAAkB;WACpB,OACL,cACA,cACA,UACA;;;cAsCO,cAAW,GACnB,YACF,KAAK,cAAsB,cAAsB,UAAkB;;;;;;;cAmBzD,SACV,KAAG,UAAY,SAAS,SAAS,KAAK,gBACtC,GAAG,GAAC,GAAK,OAAO,OAAO,GAAG,SAAiB,OAAK,OAAO,OAAO,GAAG,SAAiB;;;;;;;;;;;cAyBxE,SACV,KAAG,UAAY,SAAS,SAAS,KAAK,cACtC,GAAG,GAAC,KAAO,OAAO,OAAO,GAAG,SAAiB,OAAK,OAAO,OAAO,GAAG,SAAiB"}
@@ -1,4 +1,4 @@
1
- import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
1
+ import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
2
2
  import { Data, Effect, Stream } from "effect";
3
3
  //#region src/retry/Retry.ts
4
4
  var Retry_exports = /* @__PURE__ */ __exportAll({
@@ -1 +1 @@
1
- {"version":3,"file":"Retry.mjs","names":[],"sources":["../../src/retry/Retry.ts"],"sourcesContent":["import { Data, Effect, type Schedule, Stream } from \"effect\"\nimport type * as AiError from \"../domain/AiError.js\"\n\n/**\n * Subset-aware retry helpers for `AiError`.\n *\n * Effect's own `Effect.retry` / `Stream.retry` apply the schedule to\n * every failure. For AI calls that's the wrong policy — replaying a\n * `ContentFiltered` or `InvalidRequest` won't change the outcome and\n * just wastes quota. These helpers gate the schedule on the\n * {@link Retryable} subset (rate limits, transport hiccups, timeouts);\n * everything else propagates unchanged.\n *\n * Two carriers:\n * - {@link stream} — for `Stream<A, AiError, R>` (e.g. `streamTurn`,\n * `streamSynthesis`, `streamTranscriptionFrom`). Caveat: the entire\n * stream re-runs on retry, so deltas before the failure replay on\n * the next attempt.\n * - {@link effect} — for `Effect<A, AiError, R>` (e.g. `turn`, `embed`,\n * `embedMany`, `synthesize`, `transcribe`). At-most-once.\n *\n * Composes with `Stream.retry` / `Effect.retry` directly (no naming\n * collision since these live under the `Retry` namespace).\n */\n\n/**\n * Wrapper around the retryable subset of `AiError`. Internal to the\n * lift/retry/unlift dance — exported so callers can build their own\n * variants if needed (e.g. a custom schedule that observes `cause`).\n */\nexport class Retryable extends Data.TaggedError(\"RetryableAi\")<{\n readonly cause:\n | AiError.RateLimited\n | AiError.Unavailable\n | AiError.Timeout\n | AiError.InvalidRequest\n}> {}\n\n/**\n * `InvalidRequest` payloads that are a transient fault on the provider's side\n * rather than a defect in the request.\n *\n * The class exists because a provider can only answer within its own error\n * vocabulary: a constrained-decoding grammar that times out while compiling is\n * a cold-start timeout, but it arrives as `invalid_request_error` because that\n * is where the vendor files schema problems. Replaying it succeeds — the same\n * schema compiles on the next call.\n *\n * An allow-list rather than a general softening of `InvalidRequest`, and it\n * must stay one. The whole point of that tag being fatal is that a genuinely\n * malformed request retried on a schedule burns quota to arrive at the same\n * rejection, slowly. An entry earns its place by having been observed to\n * succeed on replay.\n */\nconst TRANSIENT_INVALID_REQUEST: ReadonlyArray<RegExp> = [/grammar compilation timed out/i]\n\n/** The payload as text, for matching. `raw` is whatever the provider handed\n * back — usually its response body as a string, sometimes a parsed object,\n * and occasionally something that will not serialise. */\nconst rawText = (raw: unknown): string => {\n if (typeof raw === \"string\") return raw\n try {\n return JSON.stringify(raw) ?? \"\"\n } catch {\n return String(raw)\n }\n}\n\nconst isTransientInvalidRequest = (e: AiError.AiError): boolean =>\n e._tag === \"InvalidRequest\" &&\n TRANSIENT_INVALID_REQUEST.some((pattern) => pattern.test(rawText(e.raw)))\n\n/** Type-narrowing predicate for the retryable subset. */\nexport const isRetryable = (\n e: AiError.AiError,\n): e is AiError.RateLimited | AiError.Unavailable | AiError.Timeout | AiError.InvalidRequest =>\n e._tag === \"RateLimited\" ||\n e._tag === \"Unavailable\" ||\n e._tag === \"Timeout\" ||\n isTransientInvalidRequest(e)\n\n// Lift events to Items, non-retryable failures to Terminal values\n// (escape retry), retryable failures to wrapped errors (only thing\n// retry sees).\ntype Lifted<A> =\n | { readonly _tag: \"Item\"; readonly value: A }\n | { readonly _tag: \"Terminal\"; readonly cause: AiError.AiError }\n\n/**\n * Retry a `Stream<A, AiError, R>` on the retryable subset. Other\n * failures bypass the schedule and propagate unchanged. The whole\n * stream replays on each attempt — deltas emitted before the failure\n * are re-emitted on the next try.\n */\nexport const stream =\n <Out>(schedule: Schedule.Schedule<Out, Retryable>) =>\n <A, R>(s: Stream.Stream<A, AiError.AiError, R>): Stream.Stream<A, AiError.AiError, R> =>\n s.pipe(\n Stream.map((value): Lifted<A> => ({ _tag: \"Item\", value })),\n Stream.catchIf(\n isRetryable,\n (cause) => Stream.fail(new Retryable({ cause })),\n (cause) => Stream.succeed<Lifted<A>>({ _tag: \"Terminal\", cause }),\n ),\n Stream.retry(schedule),\n Stream.catchTag(\"RetryableAi\", (e) => Stream.fail<AiError.AiError>(e.cause)),\n Stream.flatMap((item) =>\n item._tag === \"Item\" ? Stream.succeed(item.value) : Stream.fail(item.cause),\n ),\n )\n\n/**\n * Retry an `Effect<A, AiError, R>` on the retryable subset. Other\n * failures bypass the schedule and propagate unchanged. At-most-once\n * — the underlying call only re-runs if the previous attempt failed\n * with a retryable tag.\n *\n * Skips the lift/unlift dance the Stream variant needs: `Effect.retry`\n * exposes a `while:` predicate so the error channel stays a plain\n * `AiError` throughout.\n */\nexport const effect =\n <Out>(schedule: Schedule.Schedule<Out, AiError.AiError>) =>\n <A, R>(eff: Effect.Effect<A, AiError.AiError, R>): Effect.Effect<A, AiError.AiError, R> =>\n Effect.retry(eff, { schedule, while: isRetryable })\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,YAAb,cAA+B,KAAK,YAAY,cAAc,CAM3D;;;;;;;;;;;;;;;;;AAkBH,MAAM,4BAAmD,CAAC,iCAAiC;;;;AAK3F,MAAM,WAAW,QAAyB;AACxC,KAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,KAAI;AACF,SAAO,KAAK,UAAU,IAAI,IAAI;SACxB;AACN,SAAO,OAAO,IAAI;;;AAItB,MAAM,6BAA6B,MACjC,EAAE,SAAS,oBACX,0BAA0B,MAAM,YAAY,QAAQ,KAAK,QAAQ,EAAE,IAAI,CAAC,CAAC;;AAG3E,MAAa,eACX,MAEA,EAAE,SAAS,iBACX,EAAE,SAAS,iBACX,EAAE,SAAS,aACX,0BAA0B,EAAE;;;;;;;AAe9B,MAAa,UACL,cACC,MACL,EAAE,KACA,OAAO,KAAK,WAAsB;CAAE,MAAM;CAAQ;CAAO,EAAE,EAC3D,OAAO,QACL,cACC,UAAU,OAAO,KAAK,IAAI,UAAU,EAAE,OAAO,CAAC,CAAC,GAC/C,UAAU,OAAO,QAAmB;CAAE,MAAM;CAAY;CAAO,CAAC,CAClE,EACD,OAAO,MAAM,SAAS,EACtB,OAAO,SAAS,gBAAgB,MAAM,OAAO,KAAsB,EAAE,MAAM,CAAC,EAC5E,OAAO,SAAS,SACd,KAAK,SAAS,SAAS,OAAO,QAAQ,KAAK,MAAM,GAAG,OAAO,KAAK,KAAK,MAAM,CAC5E,CACF;;;;;;;;;;;AAYL,MAAa,UACL,cACC,QACL,OAAO,MAAM,KAAK;CAAE;CAAU,OAAO;CAAa,CAAC"}
1
+ {"version":3,"file":"Retry.mjs","names":[],"sources":["../../src/retry/Retry.ts"],"sourcesContent":["import { Data, Effect, type Schedule, Stream } from \"effect\"\nimport type * as AiError from \"../domain/AiError.js\"\n\n/**\n * Subset-aware retry helpers for `AiError`.\n *\n * Effect's own `Effect.retry` / `Stream.retry` apply the schedule to\n * every failure. For AI calls that's the wrong policy — replaying a\n * `ContentFiltered` or `InvalidRequest` won't change the outcome and\n * just wastes quota. These helpers gate the schedule on the\n * {@link Retryable} subset (rate limits, transport hiccups, timeouts);\n * everything else propagates unchanged.\n *\n * Two carriers:\n * - {@link stream} — for `Stream<A, AiError, R>` (e.g. `streamTurn`,\n * `streamSynthesis`, `streamTranscriptionFrom`). Caveat: the entire\n * stream re-runs on retry, so deltas before the failure replay on\n * the next attempt.\n * - {@link effect} — for `Effect<A, AiError, R>` (e.g. `turn`, `embed`,\n * `embedMany`, `synthesize`, `transcribe`). At-most-once.\n *\n * Composes with `Stream.retry` / `Effect.retry` directly (no naming\n * collision since these live under the `Retry` namespace).\n */\n\n/**\n * Wrapper around the retryable subset of `AiError`. Internal to the\n * lift/retry/unlift dance — exported so callers can build their own\n * variants if needed (e.g. a custom schedule that observes `cause`).\n */\nexport class Retryable extends Data.TaggedError(\"RetryableAi\")<{\n readonly cause:\n | AiError.RateLimited\n | AiError.Unavailable\n | AiError.Timeout\n | AiError.InvalidRequest\n}> {}\n\n/**\n * `InvalidRequest` payloads that are a transient fault on the provider's side\n * rather than a defect in the request.\n *\n * The class exists because a provider can only answer within its own error\n * vocabulary: a constrained-decoding grammar that times out while compiling is\n * a cold-start timeout, but it arrives as `invalid_request_error` because that\n * is where the vendor files schema problems. Replaying it succeeds — the same\n * schema compiles on the next call.\n *\n * An allow-list rather than a general softening of `InvalidRequest`, and it\n * must stay one. The whole point of that tag being fatal is that a genuinely\n * malformed request retried on a schedule burns quota to arrive at the same\n * rejection, slowly. An entry earns its place by having been observed to\n * succeed on replay.\n */\nconst TRANSIENT_INVALID_REQUEST: ReadonlyArray<RegExp> = [/grammar compilation timed out/i]\n\n/** The payload as text, for matching. `raw` is whatever the provider handed\n * back — usually its response body as a string, sometimes a parsed object,\n * and occasionally something that will not serialise. */\nconst rawText = (raw: unknown): string => {\n if (typeof raw === \"string\") return raw\n try {\n return JSON.stringify(raw) ?? \"\"\n } catch {\n return String(raw)\n }\n}\n\nconst isTransientInvalidRequest = (e: AiError.AiError): boolean =>\n e._tag === \"InvalidRequest\" &&\n TRANSIENT_INVALID_REQUEST.some((pattern) => pattern.test(rawText(e.raw)))\n\n/** Type-narrowing predicate for the retryable subset. */\nexport const isRetryable = (\n e: AiError.AiError,\n): e is AiError.RateLimited | AiError.Unavailable | AiError.Timeout | AiError.InvalidRequest =>\n e._tag === \"RateLimited\" ||\n e._tag === \"Unavailable\" ||\n e._tag === \"Timeout\" ||\n isTransientInvalidRequest(e)\n\n// Lift events to Items, non-retryable failures to Terminal values\n// (escape retry), retryable failures to wrapped errors (only thing\n// retry sees).\ntype Lifted<A> =\n | { readonly _tag: \"Item\"; readonly value: A }\n | { readonly _tag: \"Terminal\"; readonly cause: AiError.AiError }\n\n/**\n * Retry a `Stream<A, AiError, R>` on the retryable subset. Other\n * failures bypass the schedule and propagate unchanged. The whole\n * stream replays on each attempt — deltas emitted before the failure\n * are re-emitted on the next try.\n */\nexport const stream =\n <Out>(schedule: Schedule.Schedule<Out, Retryable>) =>\n <A, R>(s: Stream.Stream<A, AiError.AiError, R>): Stream.Stream<A, AiError.AiError, R> =>\n s.pipe(\n Stream.map((value): Lifted<A> => ({ _tag: \"Item\", value })),\n Stream.catchIf(\n isRetryable,\n (cause) => Stream.fail(new Retryable({ cause })),\n (cause) => Stream.succeed<Lifted<A>>({ _tag: \"Terminal\", cause }),\n ),\n Stream.retry(schedule),\n Stream.catchTag(\"RetryableAi\", (e) => Stream.fail<AiError.AiError>(e.cause)),\n Stream.flatMap((item) =>\n item._tag === \"Item\" ? Stream.succeed(item.value) : Stream.fail(item.cause),\n ),\n )\n\n/**\n * Retry an `Effect<A, AiError, R>` on the retryable subset. Other\n * failures bypass the schedule and propagate unchanged. At-most-once\n * — the underlying call only re-runs if the previous attempt failed\n * with a retryable tag.\n *\n * Skips the lift/unlift dance the Stream variant needs: `Effect.retry`\n * exposes a `while:` predicate so the error channel stays a plain\n * `AiError` throughout.\n */\nexport const effect =\n <Out>(schedule: Schedule.Schedule<Out, AiError.AiError>) =>\n <A, R>(eff: Effect.Effect<A, AiError.AiError, R>): Effect.Effect<A, AiError.AiError, R> =>\n Effect.retry(eff, { schedule, while: isRetryable })\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,YAAb,cAA+B,KAAK,YAAY,aAAa,CAAC,CAM3D,CAAC;;;;;;;;;;;;;;;;;AAkBJ,MAAM,4BAAmD,CAAC,gCAAgC;;;;AAK1F,MAAM,WAAW,QAAyB;CACxC,IAAI,OAAO,QAAQ,UAAU,OAAO;CACpC,IAAI;EACF,OAAO,KAAK,UAAU,GAAG,KAAK;CAChC,QAAQ;EACN,OAAO,OAAO,GAAG;CACnB;AACF;AAEA,MAAM,6BAA6B,MACjC,EAAE,SAAS,oBACX,0BAA0B,MAAM,YAAY,QAAQ,KAAK,QAAQ,EAAE,GAAG,CAAC,CAAC;;AAG1E,MAAa,eACX,MAEA,EAAE,SAAS,iBACX,EAAE,SAAS,iBACX,EAAE,SAAS,aACX,0BAA0B,CAAC;;;;;;;AAe7B,MAAa,UACL,cACC,MACL,EAAE,KACA,OAAO,KAAK,WAAsB;CAAE,MAAM;CAAQ;AAAM,EAAE,GAC1D,OAAO,QACL,cACC,UAAU,OAAO,KAAK,IAAI,UAAU,EAAE,MAAM,CAAC,CAAC,IAC9C,UAAU,OAAO,QAAmB;CAAE,MAAM;CAAY;AAAM,CAAC,CAClE,GACA,OAAO,MAAM,QAAQ,GACrB,OAAO,SAAS,gBAAgB,MAAM,OAAO,KAAsB,EAAE,KAAK,CAAC,GAC3E,OAAO,SAAS,SACd,KAAK,SAAS,SAAS,OAAO,QAAQ,KAAK,KAAK,IAAI,OAAO,KAAK,KAAK,KAAK,CAC5E,CACF;;;;;;;;;;;AAYJ,MAAa,UACL,cACC,QACL,OAAO,MAAM,KAAK;CAAE;CAAU,OAAO;AAAY,CAAC"}
@@ -1 +1 @@
1
- export { };
1
+ export {}
@@ -1,6 +1,7 @@
1
1
  import { ContentFiltered, RateLimited, Timeout, Unavailable } from "../domain/AiError.mjs";
2
2
  import { effect, stream } from "./Retry.mjs";
3
- import { c as it, n as globalExpect, o as describe } from "../dist-CcRV3-A5.mjs";
3
+ import { m as it, o as describe } from "../utils-CiH_DjFW.mjs";
4
+ import { n as globalExpect } from "../test.DNmyFkvJ-YPzDR0Co.mjs";
4
5
  import { Cause, Effect, Exit, Option, Ref, Schedule, Stream } from "effect";
5
6
  //#region src/retry/Retry.test.ts
6
7
  const planned = (attempts, plan) => Stream.unwrap(Ref.getAndUpdate(attempts, (n) => n + 1).pipe(Effect.map((n) => plan[Math.min(n, plan.length - 1)])));
@@ -55,14 +56,16 @@ describe("Retry.stream", () => {
55
56
  });
56
57
  it("preserves items emitted before a retryable failure (and replays on retry)", async () => {
57
58
  const program = Effect.gen(function* () {
58
- const s = planned(yield* Ref.make(0), [Stream.concat(Stream.succeed("partial"), Stream.fail(new Timeout({
59
+ const attempts = yield* Ref.make(0);
60
+ const s = planned(attempts, [Stream.concat(Stream.succeed("partial"), Stream.fail(new Timeout({
59
61
  provider: "mock",
60
62
  raw: null
61
63
  }))), Stream.fromIterable(["partial", "done"])]).pipe(stream(Schedule.recurs(1)));
62
64
  const out = yield* Stream.runCollect(s);
63
65
  return Array.from(out);
64
66
  });
65
- globalExpect(await Effect.runPromise(program)).toEqual([
67
+ const out = await Effect.runPromise(program);
68
+ globalExpect(out).toEqual([
66
69
  "partial",
67
70
  "partial",
68
71
  "done"
@@ -1 +1 @@
1
- {"version":3,"file":"Retry.test.mjs","names":["AiError.RateLimited","Retry.stream","AiError.Unavailable","AiError.ContentFiltered","AiError.Timeout","Retry.effect"],"sources":["../../src/retry/Retry.test.ts"],"sourcesContent":["import { Cause, Effect, Exit, Option, Ref, Schedule, Stream } from \"effect\"\nimport { describe, expect, it } from \"vitest\"\nimport * as AiError from \"../domain/AiError.js\"\nimport * as Retry from \"./Retry.js\"\n\n// Each call pulls the next plan entry; the last entry repeats forever\n// (so \"succeed on attempt N\" plans naturally re-yield success after).\nconst planned = <A, E>(\n attempts: Ref.Ref<number>,\n plan: ReadonlyArray<Stream.Stream<A, E>>,\n): Stream.Stream<A, E> =>\n Stream.unwrap(\n Ref.getAndUpdate(attempts, (n) => n + 1).pipe(\n Effect.map((n) => plan[Math.min(n, plan.length - 1)]!),\n ),\n )\n\nconst plannedEffect = <A, E>(\n attempts: Ref.Ref<number>,\n plan: ReadonlyArray<Effect.Effect<A, E>>,\n): Effect.Effect<A, E> =>\n Ref.getAndUpdate(attempts, (n) => n + 1).pipe(\n Effect.flatMap((n) => plan[Math.min(n, plan.length - 1)]!),\n )\n\ndescribe(\"Retry.stream\", () => {\n it(\"retries on RateLimited and yields success on the next attempt\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const s = planned(attempts, [\n Stream.fail<AiError.AiError>(new AiError.RateLimited({ provider: \"mock\", raw: null })),\n Stream.fromIterable([\"a\", \"b\"]),\n ]).pipe(Retry.stream(Schedule.recurs(3)))\n const out = yield* Stream.runCollect(s)\n const count = yield* Ref.get(attempts)\n return { out: Array.from(out), count }\n })\n\n const { out, count } = await Effect.runPromise(program)\n expect(count).toBe(2)\n expect(out).toEqual([\"a\", \"b\"])\n })\n\n it(\"surfaces the underlying retryable failure when retries are exhausted\", async () => {\n const cause = new AiError.Unavailable({ provider: \"mock\", raw: null })\n const s = Stream.fail<AiError.AiError>(cause).pipe(Retry.stream(Schedule.recurs(2)))\n\n const exit = await Effect.runPromise(Effect.exit(Stream.runCollect(s)))\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"bypasses retry for non-retryable AiError (ContentFiltered)\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const cause = new AiError.ContentFiltered({ provider: \"mock\", raw: null })\n const s = planned(attempts, [Stream.fail<AiError.AiError>(cause)]).pipe(\n Retry.stream(Schedule.recurs(5)),\n )\n const exit = yield* Effect.exit(Stream.runCollect(s))\n const count = yield* Ref.get(attempts)\n return { exit, count, cause }\n })\n\n const { exit, count, cause } = await Effect.runPromise(program)\n expect(count).toBe(1)\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"preserves items emitted before a retryable failure (and replays on retry)\", async () => {\n // Documents the 'replays on retry' caveat: the entire stream re-runs.\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const s = planned(attempts, [\n Stream.concat(\n Stream.succeed(\"partial\"),\n Stream.fail<AiError.AiError>(new AiError.Timeout({ provider: \"mock\", raw: null })),\n ),\n Stream.fromIterable([\"partial\", \"done\"]),\n ]).pipe(Retry.stream(Schedule.recurs(1)))\n const out = yield* Stream.runCollect(s)\n return Array.from(out)\n })\n\n const out = await Effect.runPromise(program)\n expect(out).toEqual([\"partial\", \"partial\", \"done\"])\n })\n})\n\ndescribe(\"Retry.effect\", () => {\n it(\"retries on RateLimited and yields success on the next attempt\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const value = yield* plannedEffect(attempts, [\n Effect.fail<AiError.AiError>(new AiError.RateLimited({ provider: \"mock\", raw: null })),\n Effect.succeed(\"ok\"),\n ]).pipe(Retry.effect(Schedule.recurs(3)))\n const count = yield* Ref.get(attempts)\n return { value, count }\n })\n\n const { value, count } = await Effect.runPromise(program)\n expect(count).toBe(2)\n expect(value).toBe(\"ok\")\n })\n\n it(\"surfaces the underlying retryable failure when retries are exhausted\", async () => {\n const cause = new AiError.Unavailable({ provider: \"mock\", raw: null })\n const eff = Effect.fail<AiError.AiError>(cause).pipe(Retry.effect(Schedule.recurs(2)))\n\n const exit = await Effect.runPromise(Effect.exit(eff))\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"bypasses retry for non-retryable AiError (ContentFiltered)\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const cause = new AiError.ContentFiltered({ provider: \"mock\", raw: null })\n const exit = yield* Effect.exit(\n plannedEffect(attempts, [Effect.fail<AiError.AiError>(cause)]).pipe(\n Retry.effect(Schedule.recurs(5)),\n ),\n )\n const count = yield* Ref.get(attempts)\n return { exit, count, cause }\n })\n\n const { exit, count, cause } = await Effect.runPromise(program)\n expect(count).toBe(1)\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"does NOT replay successful prior work — at-most-once semantics\", async () => {\n // Contrast with Retry.stream: an Effect.retry only re-invokes the\n // failing computation. No replay of work done before the failure\n // (there's nothing to replay — Effects are single-shot).\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const value = yield* plannedEffect(attempts, [\n Effect.fail<AiError.AiError>(new AiError.Timeout({ provider: \"mock\", raw: null })),\n Effect.fail<AiError.AiError>(new AiError.Timeout({ provider: \"mock\", raw: null })),\n Effect.succeed(\"done\"),\n ]).pipe(Retry.effect(Schedule.recurs(5)))\n const count = yield* Ref.get(attempts)\n return { value, count }\n })\n\n const { value, count } = await Effect.runPromise(program)\n expect(count).toBe(3)\n expect(value).toBe(\"done\")\n })\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"Retry.test.mjs","names":["AiError.RateLimited","Retry.stream","AiError.Unavailable","AiError.ContentFiltered","AiError.Timeout","Retry.effect"],"sources":["../../src/retry/Retry.test.ts"],"sourcesContent":["import { Cause, Effect, Exit, Option, Ref, Schedule, Stream } from \"effect\"\nimport { describe, expect, it } from \"vitest\"\nimport * as AiError from \"../domain/AiError.js\"\nimport * as Retry from \"./Retry.js\"\n\n// Each call pulls the next plan entry; the last entry repeats forever\n// (so \"succeed on attempt N\" plans naturally re-yield success after).\nconst planned = <A, E>(\n attempts: Ref.Ref<number>,\n plan: ReadonlyArray<Stream.Stream<A, E>>,\n): Stream.Stream<A, E> =>\n Stream.unwrap(\n Ref.getAndUpdate(attempts, (n) => n + 1).pipe(\n Effect.map((n) => plan[Math.min(n, plan.length - 1)]!),\n ),\n )\n\nconst plannedEffect = <A, E>(\n attempts: Ref.Ref<number>,\n plan: ReadonlyArray<Effect.Effect<A, E>>,\n): Effect.Effect<A, E> =>\n Ref.getAndUpdate(attempts, (n) => n + 1).pipe(\n Effect.flatMap((n) => plan[Math.min(n, plan.length - 1)]!),\n )\n\ndescribe(\"Retry.stream\", () => {\n it(\"retries on RateLimited and yields success on the next attempt\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const s = planned(attempts, [\n Stream.fail<AiError.AiError>(new AiError.RateLimited({ provider: \"mock\", raw: null })),\n Stream.fromIterable([\"a\", \"b\"]),\n ]).pipe(Retry.stream(Schedule.recurs(3)))\n const out = yield* Stream.runCollect(s)\n const count = yield* Ref.get(attempts)\n return { out: Array.from(out), count }\n })\n\n const { out, count } = await Effect.runPromise(program)\n expect(count).toBe(2)\n expect(out).toEqual([\"a\", \"b\"])\n })\n\n it(\"surfaces the underlying retryable failure when retries are exhausted\", async () => {\n const cause = new AiError.Unavailable({ provider: \"mock\", raw: null })\n const s = Stream.fail<AiError.AiError>(cause).pipe(Retry.stream(Schedule.recurs(2)))\n\n const exit = await Effect.runPromise(Effect.exit(Stream.runCollect(s)))\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"bypasses retry for non-retryable AiError (ContentFiltered)\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const cause = new AiError.ContentFiltered({ provider: \"mock\", raw: null })\n const s = planned(attempts, [Stream.fail<AiError.AiError>(cause)]).pipe(\n Retry.stream(Schedule.recurs(5)),\n )\n const exit = yield* Effect.exit(Stream.runCollect(s))\n const count = yield* Ref.get(attempts)\n return { exit, count, cause }\n })\n\n const { exit, count, cause } = await Effect.runPromise(program)\n expect(count).toBe(1)\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"preserves items emitted before a retryable failure (and replays on retry)\", async () => {\n // Documents the 'replays on retry' caveat: the entire stream re-runs.\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const s = planned(attempts, [\n Stream.concat(\n Stream.succeed(\"partial\"),\n Stream.fail<AiError.AiError>(new AiError.Timeout({ provider: \"mock\", raw: null })),\n ),\n Stream.fromIterable([\"partial\", \"done\"]),\n ]).pipe(Retry.stream(Schedule.recurs(1)))\n const out = yield* Stream.runCollect(s)\n return Array.from(out)\n })\n\n const out = await Effect.runPromise(program)\n expect(out).toEqual([\"partial\", \"partial\", \"done\"])\n })\n})\n\ndescribe(\"Retry.effect\", () => {\n it(\"retries on RateLimited and yields success on the next attempt\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const value = yield* plannedEffect(attempts, [\n Effect.fail<AiError.AiError>(new AiError.RateLimited({ provider: \"mock\", raw: null })),\n Effect.succeed(\"ok\"),\n ]).pipe(Retry.effect(Schedule.recurs(3)))\n const count = yield* Ref.get(attempts)\n return { value, count }\n })\n\n const { value, count } = await Effect.runPromise(program)\n expect(count).toBe(2)\n expect(value).toBe(\"ok\")\n })\n\n it(\"surfaces the underlying retryable failure when retries are exhausted\", async () => {\n const cause = new AiError.Unavailable({ provider: \"mock\", raw: null })\n const eff = Effect.fail<AiError.AiError>(cause).pipe(Retry.effect(Schedule.recurs(2)))\n\n const exit = await Effect.runPromise(Effect.exit(eff))\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"bypasses retry for non-retryable AiError (ContentFiltered)\", async () => {\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const cause = new AiError.ContentFiltered({ provider: \"mock\", raw: null })\n const exit = yield* Effect.exit(\n plannedEffect(attempts, [Effect.fail<AiError.AiError>(cause)]).pipe(\n Retry.effect(Schedule.recurs(5)),\n ),\n )\n const count = yield* Ref.get(attempts)\n return { exit, count, cause }\n })\n\n const { exit, count, cause } = await Effect.runPromise(program)\n expect(count).toBe(1)\n expect(Exit.isFailure(exit)).toBe(true)\n if (Exit.isFailure(exit)) {\n expect(Cause.findErrorOption(exit.cause)).toEqual(Option.some(cause))\n }\n })\n\n it(\"does NOT replay successful prior work — at-most-once semantics\", async () => {\n // Contrast with Retry.stream: an Effect.retry only re-invokes the\n // failing computation. No replay of work done before the failure\n // (there's nothing to replay — Effects are single-shot).\n const program = Effect.gen(function* () {\n const attempts = yield* Ref.make(0)\n const value = yield* plannedEffect(attempts, [\n Effect.fail<AiError.AiError>(new AiError.Timeout({ provider: \"mock\", raw: null })),\n Effect.fail<AiError.AiError>(new AiError.Timeout({ provider: \"mock\", raw: null })),\n Effect.succeed(\"done\"),\n ]).pipe(Retry.effect(Schedule.recurs(5)))\n const count = yield* Ref.get(attempts)\n return { value, count }\n })\n\n const { value, count } = await Effect.runPromise(program)\n expect(count).toBe(3)\n expect(value).toBe(\"done\")\n })\n})\n"],"mappings":"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"}
@@ -1,6 +1,4 @@
1
1
  import { Brand } from "effect";
2
-
3
- //#region src/sandbox/Memory.d.ts
4
2
  declare namespace Memory_d_exports {
5
3
  export { Input, Memory, bytes, fromInputUnsafe, gb, gib, kb, kib, mb, mib, toBytes };
6
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Memory.d.mts","names":[],"sources":["../../src/sandbox/Memory.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA;;;;;KAAY,MAAA,GAAS,KAAA,CAAM,OAAA;AAAA,KAuBf,KAAA,YAAiB,MAAA;;;;AAqC7B;cAAa,eAAA,GAAmB,KAAA,EAAO,KAAA,KAAQ,MAAA;;cAelC,OAAA,GAAW,CAAA,EAAG,MAAA,GAAS,KAAA;;cAUvB,KAAA,GAAS,CAAA,aAAY,MAAA;;cAGrB,GAAA,GAAO,CAAA,aAAY,MAAA;;cAGnB,GAAA,GAAO,CAAA,aAAY,MAAA;;cAGnB,GAAA,GAAO,CAAA,aAAY,MAAA;;cAGnB,EAAA,GAAM,CAAA,aAAY,MAAA;;cAGlB,EAAA,GAAM,CAAA,aAAY,MAAA;;cAGlB,EAAA,GAAM,CAAA,aAAY,MAAA"}
1
+ {"version":3,"file":"Memory.d.mts","names":[],"sources":["../../src/sandbox/Memory.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;KAwBY,SAAS,MAAM;KAuBf,iBAAiB;;;;;cAqChB,kBAAe,OAAW,UAAQ;;cAelC,UAAO,GAAO,SAAS;;cAUvB,QAAK,cAAgB;;cAGrB,MAAG,cAAgB;;cAGnB,MAAG,cAAgB;;cAGnB,MAAG,cAAgB;;cAGnB,KAAE,cAAgB;;cAGlB,KAAE,cAAgB;;cAGlB,KAAE,cAAgB"}
@@ -1,4 +1,4 @@
1
- import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
1
+ import { n as __exportAll } from "../rolldown-runtime-EAsCxrDo.mjs";
2
2
  import { Brand } from "effect";
3
3
  //#region src/sandbox/Memory.ts
4
4
  var Memory_exports = /* @__PURE__ */ __exportAll({
@@ -20,9 +20,9 @@ const UNIT_BYTES = {
20
20
  gb: 1e9,
21
21
  tb: 0xe8d4a51000,
22
22
  kib: 1024,
23
- mib: 1024 * 1024,
24
- gib: 1024 * 1024 * 1024,
25
- tib: 1024 * 1024 * 1024 * 1024
23
+ mib: 1048576,
24
+ gib: 1073741824,
25
+ tib: 1099511627776
26
26
  };
27
27
  const PARSE_RE = /^\s*(\d+(?:\.\d+)?)\s*([a-zA-Z]*)\s*$/;
28
28
  const parseString = (s) => {
@@ -1 +1 @@
1
- {"version":3,"file":"Memory.mjs","names":[],"sources":["../../src/sandbox/Memory.ts"],"sourcesContent":["import { Brand } from \"effect\"\n\n/**\n * A memory / data size, always represented internally as a number of\n * bytes. Mirrors the `Duration` shape from `effect` — a branded value\n * type with a wider `Input` union for ergonomic construction at call\n * sites.\n *\n * `effect` itself has no byte-count primitive (only `Duration`), so we\n * own this here rather than leak provider-specific shapes (Deno's\n * template-literal `Memory`, Vercel's `mb`, Modal's `gpuMemory`, …)\n * through the cross-provider `Sandbox` request types.\n *\n * @example\n * ```ts\n * import * as Memory from \"@effect-uai/core/Memory\"\n *\n * Memory.gib(2) // 2 GiB → 2_147_483_648 bytes\n * Memory.fromInputUnsafe(\"1.5 GiB\") // human-string parsing\n * Memory.fromInputUnsafe(1_280_000_000) // raw bytes\n * Memory.toBytes(m) // unwrap\n * ```\n */\n\nexport type Memory = Brand.Branded<number, \"Memory\">\n\nconst make = Brand.nominal<Memory>()\n\n// ---------------------------------------------------------------------------\n// Input — what the public APIs accept.\n//\n// Supported string forms (case-insensitive on the unit, whitespace\n// optional between number and unit):\n//\n// \"<n>\" bytes (no unit)\n// \"<n> B\" bytes\n// \"<n> kB\" 1_000 bytes (decimal)\n// \"<n> MB\" 1_000_000 (decimal)\n// \"<n> GB\" 1_000_000_000 (decimal)\n// \"<n> KiB\" 1_024 (binary)\n// \"<n> MiB\" 1_048_576 (binary)\n// \"<n> GiB\" 1_073_741_824 (binary)\n//\n// Decimal vs binary follows the SI / IEC convention (`MB` = 10^6,\n// `MiB` = 2^20). When in doubt, prefer the binary `*iB` units.\n// ---------------------------------------------------------------------------\n\nexport type Input = number | Memory | string\n\nconst UNIT_BYTES: Record<string, number> = {\n b: 1,\n kb: 1_000,\n mb: 1_000_000,\n gb: 1_000_000_000,\n tb: 1_000_000_000_000,\n kib: 1_024,\n mib: 1_024 * 1_024,\n gib: 1_024 * 1_024 * 1_024,\n tib: 1_024 * 1_024 * 1_024 * 1_024,\n}\n\nconst PARSE_RE = /^\\s*(\\d+(?:\\.\\d+)?)\\s*([a-zA-Z]*)\\s*$/\n\nconst parseString = (s: string): number => {\n const m = PARSE_RE.exec(s)\n if (m === null) {\n throw new Error(`Memory: cannot parse \"${s}\" — expected forms like \"1024\", \"10 MB\", \"1GiB\"`)\n }\n const value = Number(m[1])\n const unit = (m[2] ?? \"\").toLowerCase()\n if (unit === \"\") return value\n const factor = UNIT_BYTES[unit]\n if (factor === undefined) {\n throw new Error(\n `Memory: unknown unit \"${m[2]}\" in \"${s}\" — supported: ${Object.keys(UNIT_BYTES).join(\", \")}`,\n )\n }\n return value * factor\n}\n\n/**\n * Coerce a {@link Input} to a {@link Memory}. Throws on malformed\n * strings or non-finite numbers. Mirrors `Duration.fromInputUnsafe`.\n */\nexport const fromInputUnsafe = (input: Input): Memory => {\n if (typeof input === \"number\") {\n if (!Number.isFinite(input) || input < 0) {\n throw new Error(`Memory: bytes must be a non-negative finite number, got ${input}`)\n }\n return make(Math.floor(input))\n }\n return make(Math.floor(parseString(input)))\n}\n\n// ---------------------------------------------------------------------------\n// Unwrap\n// ---------------------------------------------------------------------------\n\n/** Return the underlying byte count. */\nexport const toBytes = (m: Memory | Input): number =>\n typeof m === \"number\" && (m as number) === Math.floor(m as number) && (m as number) >= 0\n ? (m as number)\n : (fromInputUnsafe(m) as unknown as number)\n\n// ---------------------------------------------------------------------------\n// Unit constructors — terse for use at call sites.\n// ---------------------------------------------------------------------------\n\n/** N bytes. */\nexport const bytes = (n: number): Memory => make(Math.floor(n))\n\n/** N KiB (binary kibibytes, `n * 1024`). */\nexport const kib = (n: number): Memory => make(Math.floor(n * 1_024))\n\n/** N MiB (binary mebibytes, `n * 1024^2`). */\nexport const mib = (n: number): Memory => make(Math.floor(n * 1_024 * 1_024))\n\n/** N GiB (binary gibibytes, `n * 1024^3`). */\nexport const gib = (n: number): Memory => make(Math.floor(n * 1_024 * 1_024 * 1_024))\n\n/** N kB (decimal kilobytes, `n * 1000`). */\nexport const kb = (n: number): Memory => make(Math.floor(n * 1_000))\n\n/** N MB (decimal megabytes, `n * 1_000_000`). */\nexport const mb = (n: number): Memory => make(Math.floor(n * 1_000_000))\n\n/** N GB (decimal gigabytes, `n * 1_000_000_000`). */\nexport const gb = (n: number): Memory => make(Math.floor(n * 1_000_000_000))\n"],"mappings":";;;;;;;;;;;;;;AA0BA,MAAM,OAAO,MAAM,SAAiB;AAuBpC,MAAM,aAAqC;CACzC,GAAG;CACH,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK,OAAQ;CACb,KAAK,OAAQ,OAAQ;CACrB,KAAK,OAAQ,OAAQ,OAAQ;CAC9B;AAED,MAAM,WAAW;AAEjB,MAAM,eAAe,MAAsB;CACzC,MAAM,IAAI,SAAS,KAAK,EAAE;AAC1B,KAAI,MAAM,KACR,OAAM,IAAI,MAAM,yBAAyB,EAAE,iDAAiD;CAE9F,MAAM,QAAQ,OAAO,EAAE,GAAG;CAC1B,MAAM,QAAQ,EAAE,MAAM,IAAI,aAAa;AACvC,KAAI,SAAS,GAAI,QAAO;CACxB,MAAM,SAAS,WAAW;AAC1B,KAAI,WAAW,KAAA,EACb,OAAM,IAAI,MACR,yBAAyB,EAAE,GAAG,QAAQ,EAAE,iBAAiB,OAAO,KAAK,WAAW,CAAC,KAAK,KAAK,GAC5F;AAEH,QAAO,QAAQ;;;;;;AAOjB,MAAa,mBAAmB,UAAyB;AACvD,KAAI,OAAO,UAAU,UAAU;AAC7B,MAAI,CAAC,OAAO,SAAS,MAAM,IAAI,QAAQ,EACrC,OAAM,IAAI,MAAM,2DAA2D,QAAQ;AAErF,SAAO,KAAK,KAAK,MAAM,MAAM,CAAC;;AAEhC,QAAO,KAAK,KAAK,MAAM,YAAY,MAAM,CAAC,CAAC;;;AAQ7C,MAAa,WAAW,MACtB,OAAO,MAAM,YAAa,MAAiB,KAAK,MAAM,EAAY,IAAK,KAAgB,IAClF,IACA,gBAAgB,EAAE;;AAOzB,MAAa,SAAS,MAAsB,KAAK,KAAK,MAAM,EAAE,CAAC;;AAG/D,MAAa,OAAO,MAAsB,KAAK,KAAK,MAAM,IAAI,KAAM,CAAC;;AAGrE,MAAa,OAAO,MAAsB,KAAK,KAAK,MAAM,IAAI,OAAQ,KAAM,CAAC;;AAG7E,MAAa,OAAO,MAAsB,KAAK,KAAK,MAAM,IAAI,OAAQ,OAAQ,KAAM,CAAC;;AAGrF,MAAa,MAAM,MAAsB,KAAK,KAAK,MAAM,IAAI,IAAM,CAAC;;AAGpE,MAAa,MAAM,MAAsB,KAAK,KAAK,MAAM,IAAI,IAAU,CAAC;;AAGxE,MAAa,MAAM,MAAsB,KAAK,KAAK,MAAM,IAAI,IAAc,CAAC"}
1
+ {"version":3,"file":"Memory.mjs","names":[],"sources":["../../src/sandbox/Memory.ts"],"sourcesContent":["import { Brand } from \"effect\"\n\n/**\n * A memory / data size, always represented internally as a number of\n * bytes. Mirrors the `Duration` shape from `effect` — a branded value\n * type with a wider `Input` union for ergonomic construction at call\n * sites.\n *\n * `effect` itself has no byte-count primitive (only `Duration`), so we\n * own this here rather than leak provider-specific shapes (Deno's\n * template-literal `Memory`, Vercel's `mb`, Modal's `gpuMemory`, …)\n * through the cross-provider `Sandbox` request types.\n *\n * @example\n * ```ts\n * import * as Memory from \"@effect-uai/core/Memory\"\n *\n * Memory.gib(2) // 2 GiB → 2_147_483_648 bytes\n * Memory.fromInputUnsafe(\"1.5 GiB\") // human-string parsing\n * Memory.fromInputUnsafe(1_280_000_000) // raw bytes\n * Memory.toBytes(m) // unwrap\n * ```\n */\n\nexport type Memory = Brand.Branded<number, \"Memory\">\n\nconst make = Brand.nominal<Memory>()\n\n// ---------------------------------------------------------------------------\n// Input — what the public APIs accept.\n//\n// Supported string forms (case-insensitive on the unit, whitespace\n// optional between number and unit):\n//\n// \"<n>\" bytes (no unit)\n// \"<n> B\" bytes\n// \"<n> kB\" 1_000 bytes (decimal)\n// \"<n> MB\" 1_000_000 (decimal)\n// \"<n> GB\" 1_000_000_000 (decimal)\n// \"<n> KiB\" 1_024 (binary)\n// \"<n> MiB\" 1_048_576 (binary)\n// \"<n> GiB\" 1_073_741_824 (binary)\n//\n// Decimal vs binary follows the SI / IEC convention (`MB` = 10^6,\n// `MiB` = 2^20). When in doubt, prefer the binary `*iB` units.\n// ---------------------------------------------------------------------------\n\nexport type Input = number | Memory | string\n\nconst UNIT_BYTES: Record<string, number> = {\n b: 1,\n kb: 1_000,\n mb: 1_000_000,\n gb: 1_000_000_000,\n tb: 1_000_000_000_000,\n kib: 1_024,\n mib: 1_024 * 1_024,\n gib: 1_024 * 1_024 * 1_024,\n tib: 1_024 * 1_024 * 1_024 * 1_024,\n}\n\nconst PARSE_RE = /^\\s*(\\d+(?:\\.\\d+)?)\\s*([a-zA-Z]*)\\s*$/\n\nconst parseString = (s: string): number => {\n const m = PARSE_RE.exec(s)\n if (m === null) {\n throw new Error(`Memory: cannot parse \"${s}\" — expected forms like \"1024\", \"10 MB\", \"1GiB\"`)\n }\n const value = Number(m[1])\n const unit = (m[2] ?? \"\").toLowerCase()\n if (unit === \"\") return value\n const factor = UNIT_BYTES[unit]\n if (factor === undefined) {\n throw new Error(\n `Memory: unknown unit \"${m[2]}\" in \"${s}\" — supported: ${Object.keys(UNIT_BYTES).join(\", \")}`,\n )\n }\n return value * factor\n}\n\n/**\n * Coerce a {@link Input} to a {@link Memory}. Throws on malformed\n * strings or non-finite numbers. Mirrors `Duration.fromInputUnsafe`.\n */\nexport const fromInputUnsafe = (input: Input): Memory => {\n if (typeof input === \"number\") {\n if (!Number.isFinite(input) || input < 0) {\n throw new Error(`Memory: bytes must be a non-negative finite number, got ${input}`)\n }\n return make(Math.floor(input))\n }\n return make(Math.floor(parseString(input)))\n}\n\n// ---------------------------------------------------------------------------\n// Unwrap\n// ---------------------------------------------------------------------------\n\n/** Return the underlying byte count. */\nexport const toBytes = (m: Memory | Input): number =>\n typeof m === \"number\" && (m as number) === Math.floor(m as number) && (m as number) >= 0\n ? (m as number)\n : (fromInputUnsafe(m) as unknown as number)\n\n// ---------------------------------------------------------------------------\n// Unit constructors — terse for use at call sites.\n// ---------------------------------------------------------------------------\n\n/** N bytes. */\nexport const bytes = (n: number): Memory => make(Math.floor(n))\n\n/** N KiB (binary kibibytes, `n * 1024`). */\nexport const kib = (n: number): Memory => make(Math.floor(n * 1_024))\n\n/** N MiB (binary mebibytes, `n * 1024^2`). */\nexport const mib = (n: number): Memory => make(Math.floor(n * 1_024 * 1_024))\n\n/** N GiB (binary gibibytes, `n * 1024^3`). */\nexport const gib = (n: number): Memory => make(Math.floor(n * 1_024 * 1_024 * 1_024))\n\n/** N kB (decimal kilobytes, `n * 1000`). */\nexport const kb = (n: number): Memory => make(Math.floor(n * 1_000))\n\n/** N MB (decimal megabytes, `n * 1_000_000`). */\nexport const mb = (n: number): Memory => make(Math.floor(n * 1_000_000))\n\n/** N GB (decimal gigabytes, `n * 1_000_000_000`). */\nexport const gb = (n: number): Memory => make(Math.floor(n * 1_000_000_000))\n"],"mappings":";;;;;;;;;;;;;;AA0BA,MAAM,OAAO,MAAM,QAAgB;AAuBnC,MAAM,aAAqC;CACzC,GAAG;CACH,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;AACP;AAEA,MAAM,WAAW;AAEjB,MAAM,eAAe,MAAsB;CACzC,MAAM,IAAI,SAAS,KAAK,CAAC;CACzB,IAAI,MAAM,MACR,MAAM,IAAI,MAAM,yBAAyB,EAAE,gDAAgD;CAE7F,MAAM,QAAQ,OAAO,EAAE,EAAE;CACzB,MAAM,QAAQ,EAAE,MAAM,GAAA,CAAI,YAAY;CACtC,IAAI,SAAS,IAAI,OAAO;CACxB,MAAM,SAAS,WAAW;CAC1B,IAAI,WAAW,KAAA,GACb,MAAM,IAAI,MACR,yBAAyB,EAAE,GAAG,QAAQ,EAAE,iBAAiB,OAAO,KAAK,UAAU,CAAC,CAAC,KAAK,IAAI,GAC5F;CAEF,OAAO,QAAQ;AACjB;;;;;AAMA,MAAa,mBAAmB,UAAyB;CACvD,IAAI,OAAO,UAAU,UAAU;EAC7B,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,GACrC,MAAM,IAAI,MAAM,2DAA2D,OAAO;EAEpF,OAAO,KAAK,KAAK,MAAM,KAAK,CAAC;CAC/B;CACA,OAAO,KAAK,KAAK,MAAM,YAAY,KAAK,CAAC,CAAC;AAC5C;;AAOA,MAAa,WAAW,MACtB,OAAO,MAAM,YAAa,MAAiB,KAAK,MAAM,CAAW,KAAM,KAAgB,IAClF,IACA,gBAAgB,CAAC;;AAOxB,MAAa,SAAS,MAAsB,KAAK,KAAK,MAAM,CAAC,CAAC;;AAG9D,MAAa,OAAO,MAAsB,KAAK,KAAK,MAAM,IAAI,IAAK,CAAC;;AAGpE,MAAa,OAAO,MAAsB,KAAK,KAAK,MAAM,IAAI,OAAQ,IAAK,CAAC;;AAG5E,MAAa,OAAO,MAAsB,KAAK,KAAK,MAAM,IAAI,OAAQ,OAAQ,IAAK,CAAC;;AAGpF,MAAa,MAAM,MAAsB,KAAK,KAAK,MAAM,IAAI,GAAK,CAAC;;AAGnE,MAAa,MAAM,MAAsB,KAAK,KAAK,MAAM,IAAI,GAAS,CAAC;;AAGvE,MAAa,MAAM,MAAsB,KAAK,KAAK,MAAM,IAAI,GAAa,CAAC"}