@effect-uai/core 0.5.2 → 0.7.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 (175) hide show
  1. package/README.md +1 -1
  2. package/dist/{Audio-BfCTGnH3.d.mts → Audio-DPlTsNdz.d.mts} +3 -2
  3. package/dist/Audio-DPlTsNdz.d.mts.map +1 -0
  4. package/dist/{Items-BH8xUkoR.d.mts → Items-D8UaXQx_.d.mts} +15 -15
  5. package/dist/Items-D8UaXQx_.d.mts.map +1 -0
  6. package/dist/SandboxError-BvKypkJm.d.mts +158 -0
  7. package/dist/SandboxError-BvKypkJm.d.mts.map +1 -0
  8. package/dist/{Tool-87ViKCCO.d.mts → Tool-CiFXYjmR.d.mts} +11 -11
  9. package/dist/{Tool-87ViKCCO.d.mts.map → Tool-CiFXYjmR.d.mts.map} +1 -1
  10. package/dist/capabilities/Capabilities.d.mts +78 -0
  11. package/dist/capabilities/Capabilities.d.mts.map +1 -0
  12. package/dist/capabilities/Capabilities.mjs +65 -0
  13. package/dist/capabilities/Capabilities.mjs.map +1 -0
  14. package/dist/domain/Audio.d.mts +1 -1
  15. package/dist/domain/Audio.mjs.map +1 -1
  16. package/dist/domain/Items.d.mts +2 -2
  17. package/dist/domain/Items.mjs +15 -15
  18. package/dist/domain/Items.mjs.map +1 -1
  19. package/dist/domain/Music.d.mts +131 -72
  20. package/dist/domain/Music.d.mts.map +1 -1
  21. package/dist/domain/Music.mjs +36 -9
  22. package/dist/domain/Music.mjs.map +1 -1
  23. package/dist/domain/Transcript.d.mts +8 -2
  24. package/dist/domain/Transcript.d.mts.map +1 -1
  25. package/dist/domain/Transcript.mjs.map +1 -1
  26. package/dist/domain/Turn.d.mts +388 -2
  27. package/dist/domain/Turn.d.mts.map +1 -0
  28. package/dist/domain/Turn.mjs +13 -13
  29. package/dist/domain/Turn.mjs.map +1 -1
  30. package/dist/embedding-model/Embedding.d.mts +12 -2
  31. package/dist/embedding-model/Embedding.d.mts.map +1 -1
  32. package/dist/embedding-model/Embedding.mjs.map +1 -1
  33. package/dist/embedding-model/EmbeddingModel.d.mts +36 -23
  34. package/dist/embedding-model/EmbeddingModel.d.mts.map +1 -1
  35. package/dist/embedding-model/EmbeddingModel.mjs +20 -1
  36. package/dist/embedding-model/EmbeddingModel.mjs.map +1 -1
  37. package/dist/embedding-model/EmbeddingModel.test.mjs +15 -3
  38. package/dist/embedding-model/EmbeddingModel.test.mjs.map +1 -1
  39. package/dist/index.d.mts +13 -7
  40. package/dist/index.mjs +9 -3
  41. package/dist/language-model/LanguageModel.d.mts +5 -5
  42. package/dist/language-model/LanguageModel.d.mts.map +1 -1
  43. package/dist/language-model/LanguageModel.mjs.map +1 -1
  44. package/dist/loop/Loop.d.mts +37 -90
  45. package/dist/loop/Loop.d.mts.map +1 -1
  46. package/dist/loop/Loop.mjs +39 -93
  47. package/dist/loop/Loop.mjs.map +1 -1
  48. package/dist/loop/Loop.test.mjs +46 -54
  49. package/dist/loop/Loop.test.mjs.map +1 -1
  50. package/dist/music-generator/MusicGenerator.d.mts +48 -25
  51. package/dist/music-generator/MusicGenerator.d.mts.map +1 -1
  52. package/dist/music-generator/MusicGenerator.mjs +17 -9
  53. package/dist/music-generator/MusicGenerator.mjs.map +1 -1
  54. package/dist/music-generator/MusicGenerator.test.mjs +81 -56
  55. package/dist/music-generator/MusicGenerator.test.mjs.map +1 -1
  56. package/dist/sandbox/Memory.d.mts +53 -0
  57. package/dist/sandbox/Memory.d.mts.map +1 -0
  58. package/dist/sandbox/Memory.mjs +68 -0
  59. package/dist/sandbox/Memory.mjs.map +1 -0
  60. package/dist/sandbox/Sandbox.d.mts +717 -0
  61. package/dist/sandbox/Sandbox.d.mts.map +1 -0
  62. package/dist/sandbox/Sandbox.mjs +192 -0
  63. package/dist/sandbox/Sandbox.mjs.map +1 -0
  64. package/dist/sandbox/SandboxError.d.mts +2 -0
  65. package/dist/sandbox/SandboxError.mjs +89 -0
  66. package/dist/sandbox/SandboxError.mjs.map +1 -0
  67. package/dist/sandbox/SandboxImage.d.mts +28 -0
  68. package/dist/sandbox/SandboxImage.d.mts.map +1 -0
  69. package/dist/sandbox/SandboxImage.mjs +32 -0
  70. package/dist/sandbox/SandboxImage.mjs.map +1 -0
  71. package/dist/sandbox/SandboxNetwork.d.mts +34 -0
  72. package/dist/sandbox/SandboxNetwork.d.mts.map +1 -0
  73. package/dist/sandbox/SandboxNetwork.mjs +36 -0
  74. package/dist/sandbox/SandboxNetwork.mjs.map +1 -0
  75. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +84 -3
  76. package/dist/speech-synthesizer/SpeechSynthesizer.d.mts.map +1 -1
  77. package/dist/speech-synthesizer/SpeechSynthesizer.mjs +32 -2
  78. package/dist/speech-synthesizer/SpeechSynthesizer.mjs.map +1 -1
  79. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs +59 -5
  80. package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs.map +1 -1
  81. package/dist/testing/MockMusicGenerator.d.mts +12 -7
  82. package/dist/testing/MockMusicGenerator.d.mts.map +1 -1
  83. package/dist/testing/MockMusicGenerator.mjs +4 -3
  84. package/dist/testing/MockMusicGenerator.mjs.map +1 -1
  85. package/dist/testing/MockProvider.d.mts +3 -3
  86. package/dist/testing/MockProvider.d.mts.map +1 -1
  87. package/dist/testing/MockProvider.mjs.map +1 -1
  88. package/dist/testing/MockSandbox.d.mts +604 -0
  89. package/dist/testing/MockSandbox.d.mts.map +1 -0
  90. package/dist/testing/MockSandbox.mjs +160 -0
  91. package/dist/testing/MockSandbox.mjs.map +1 -0
  92. package/dist/testing/MockSpeechSynthesizer.d.mts +27 -12
  93. package/dist/testing/MockSpeechSynthesizer.d.mts.map +1 -1
  94. package/dist/testing/MockSpeechSynthesizer.mjs +75 -51
  95. package/dist/testing/MockSpeechSynthesizer.mjs.map +1 -1
  96. package/dist/tool/{Resolvers.d.mts → Approval.d.mts} +27 -27
  97. package/dist/tool/Approval.d.mts.map +1 -0
  98. package/dist/tool/{Resolvers.mjs → Approval.mjs} +18 -18
  99. package/dist/tool/Approval.mjs.map +1 -0
  100. package/dist/tool/{Resolvers.test.mjs → Approval.test.mjs} +40 -40
  101. package/dist/tool/Approval.test.mjs.map +1 -0
  102. package/dist/tool/HistoryCheck.d.mts +6 -6
  103. package/dist/tool/HistoryCheck.d.mts.map +1 -1
  104. package/dist/tool/HistoryCheck.mjs +5 -5
  105. package/dist/tool/HistoryCheck.mjs.map +1 -1
  106. package/dist/tool/Tool.d.mts +2 -2
  107. package/dist/tool/Tool.mjs +4 -4
  108. package/dist/tool/Tool.mjs.map +1 -1
  109. package/dist/tool/ToolEvent.d.mts +19 -19
  110. package/dist/tool/ToolEvent.d.mts.map +1 -1
  111. package/dist/tool/ToolEvent.mjs +8 -8
  112. package/dist/tool/ToolEvent.mjs.map +1 -1
  113. package/dist/tool/{Outcome.d.mts → ToolResult.d.mts} +29 -29
  114. package/dist/tool/ToolResult.d.mts.map +1 -0
  115. package/dist/tool/ToolResult.mjs +61 -0
  116. package/dist/tool/ToolResult.mjs.map +1 -0
  117. package/dist/tool/Toolkit.d.mts +58 -26
  118. package/dist/tool/Toolkit.d.mts.map +1 -1
  119. package/dist/tool/Toolkit.mjs +62 -34
  120. package/dist/tool/Toolkit.mjs.map +1 -1
  121. package/dist/tool/Toolkit.test.mjs +13 -13
  122. package/dist/tool/Toolkit.test.mjs.map +1 -1
  123. package/dist/transcriber/Transcriber.d.mts +11 -10
  124. package/dist/transcriber/Transcriber.d.mts.map +1 -1
  125. package/dist/transcriber/Transcriber.mjs.map +1 -1
  126. package/dist/transcriber/Transcriber.test.mjs +3 -3
  127. package/dist/transcriber/Transcriber.test.mjs.map +1 -1
  128. package/package.json +35 -7
  129. package/src/capabilities/Capabilities.ts +81 -0
  130. package/src/domain/Audio.ts +2 -1
  131. package/src/domain/Items.ts +9 -9
  132. package/src/domain/Music.ts +142 -68
  133. package/src/domain/Transcript.ts +7 -1
  134. package/src/domain/Turn.ts +16 -16
  135. package/src/embedding-model/Embedding.ts +11 -0
  136. package/src/embedding-model/EmbeddingModel.test.ts +15 -4
  137. package/src/embedding-model/EmbeddingModel.ts +48 -21
  138. package/src/index.ts +8 -2
  139. package/src/language-model/LanguageModel.ts +3 -3
  140. package/src/loop/Loop.test.ts +93 -91
  141. package/src/loop/Loop.ts +72 -170
  142. package/src/music-generator/MusicGenerator.test.ts +78 -53
  143. package/src/music-generator/MusicGenerator.ts +65 -24
  144. package/src/sandbox/Memory.ts +128 -0
  145. package/src/sandbox/Sandbox.ts +639 -0
  146. package/src/sandbox/SandboxError.ts +140 -0
  147. package/src/sandbox/SandboxImage.ts +26 -0
  148. package/src/sandbox/SandboxNetwork.ts +34 -0
  149. package/src/speech-synthesizer/SpeechSynthesizer.test.ts +92 -3
  150. package/src/speech-synthesizer/SpeechSynthesizer.ts +109 -0
  151. package/src/testing/MockMusicGenerator.ts +28 -18
  152. package/src/testing/MockProvider.ts +21 -20
  153. package/src/testing/MockSandbox.ts +342 -0
  154. package/src/testing/MockSpeechSynthesizer.ts +137 -77
  155. package/src/tool/{Resolvers.test.ts → Approval.test.ts} +45 -54
  156. package/src/tool/{Resolvers.ts → Approval.ts} +25 -25
  157. package/src/tool/HistoryCheck.ts +10 -13
  158. package/src/tool/Tool.ts +13 -15
  159. package/src/tool/ToolEvent.ts +7 -7
  160. package/src/tool/{Outcome.ts → ToolResult.ts} +20 -20
  161. package/src/tool/Toolkit.test.ts +13 -13
  162. package/src/tool/Toolkit.ts +97 -73
  163. package/src/transcriber/Transcriber.test.ts +3 -3
  164. package/src/transcriber/Transcriber.ts +10 -7
  165. package/dist/Audio-BfCTGnH3.d.mts.map +0 -1
  166. package/dist/Items-BH8xUkoR.d.mts.map +0 -1
  167. package/dist/Turn-0CwCAyVe.d.mts +0 -388
  168. package/dist/Turn-0CwCAyVe.d.mts.map +0 -1
  169. package/dist/tool/Outcome.d.mts.map +0 -1
  170. package/dist/tool/Outcome.mjs +0 -61
  171. package/dist/tool/Outcome.mjs.map +0 -1
  172. package/dist/tool/Resolvers.d.mts.map +0 -1
  173. package/dist/tool/Resolvers.mjs.map +0 -1
  174. package/dist/tool/Resolvers.test.mjs.map +0 -1
  175. /package/dist/tool/{Resolvers.test.d.mts → Approval.test.d.mts} +0 -0
@@ -1,2 +1,388 @@
1
- import { c as assistantText, d as isTurnComplete, f as reasonings, i as TurnEvent, l as assistantTexts, m as toStructured, n as RefusalRejected, o as appendTurn, p as textDeltas, r as Turn, s as assistantMessages, t as InteractionEvent, u as functionCalls } from "../Turn-0CwCAyVe.mjs";
2
- export { InteractionEvent, RefusalRejected, Turn, TurnEvent, appendTurn, assistantMessages, assistantText, assistantTexts, functionCalls, isTurnComplete, reasonings, textDeltas, toStructured };
1
+ import { i as ImageSource } from "../Image-HNmMpMTh.mjs";
2
+ import { d as Message, m as Reasoning, o as HistoryItem, v as ToolCall, x as Usage, y as ToolCallOutput } from "../Items-D8UaXQx_.mjs";
3
+ import { i as StructuredFormat, n as JsonParseError, r as StructuredDecodeError } from "../StructuredFormat-BbN4dosH.mjs";
4
+ import { Data, Effect, Schema, Stream } from "effect";
5
+ import * as _$effect_Types0 from "effect/Types";
6
+ import * as _$effect_Cause0 from "effect/Cause";
7
+ import * as _$effect_Unify0 from "effect/Unify";
8
+
9
+ //#region src/domain/Turn.d.ts
10
+ declare namespace Turn_d_exports {
11
+ export { InteractionEvent, RefusalRejected, Turn, TurnEvent, appendToHistory, assistantMessages, assistantText, assistantTexts, decodeStructured, getToolCalls, isTurnComplete, reasonings, textDeltas };
12
+ }
13
+ /**
14
+ * The result of a single LLM generation. A turn produces zero or more items
15
+ * (typically one assistant message and zero or more function_call items)
16
+ * and reports usage + a stop reason.
17
+ */
18
+ declare const Turn: Schema.Struct<{
19
+ readonly items: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
20
+ readonly type: Schema.Literal<"message">;
21
+ readonly role: Schema.Literals<readonly ["user", "assistant", "system"]>;
22
+ readonly content: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
23
+ readonly type: Schema.Literal<"input_text">;
24
+ readonly text: Schema.String;
25
+ }>, Schema.Struct<{
26
+ readonly type: Schema.Literal<"input_image">;
27
+ readonly source: Schema.Schema<ImageSource>;
28
+ }>, Schema.Struct<{
29
+ readonly type: Schema.Literal<"output_text">;
30
+ readonly text: Schema.String;
31
+ readonly annotations: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
32
+ readonly type: Schema.Literal<"url_citation">;
33
+ readonly url: Schema.String;
34
+ readonly start_index: Schema.Number;
35
+ readonly end_index: Schema.Number;
36
+ readonly title: Schema.String;
37
+ }>, Schema.Struct<{
38
+ readonly type: Schema.Literal<"file_citation">;
39
+ readonly file_id: Schema.String;
40
+ readonly index: Schema.Number;
41
+ }>, Schema.Struct<{
42
+ readonly type: Schema.Literal<"container_file_citation">;
43
+ readonly container_id: Schema.String;
44
+ readonly file_id: Schema.String;
45
+ readonly start_index: Schema.Number;
46
+ readonly end_index: Schema.Number;
47
+ }>, Schema.Struct<{
48
+ readonly type: Schema.Literal<"file_path">;
49
+ readonly file_id: Schema.String;
50
+ readonly index: Schema.Number;
51
+ }>]>>>;
52
+ }>, Schema.Struct<{
53
+ readonly type: Schema.Literal<"refusal">;
54
+ readonly text: Schema.String;
55
+ }>]>>;
56
+ readonly providerData: Schema.optional<Schema.Unknown>;
57
+ }>, Schema.Struct<{
58
+ readonly type: Schema.Literal<"function_call">;
59
+ readonly call_id: Schema.String;
60
+ readonly name: Schema.String;
61
+ readonly arguments: Schema.String;
62
+ readonly providerData: Schema.optional<Schema.Unknown>;
63
+ }>, Schema.Struct<{
64
+ readonly type: Schema.Literal<"function_call_output">;
65
+ readonly call_id: Schema.String;
66
+ readonly output: Schema.String;
67
+ readonly providerData: Schema.optional<Schema.Unknown>;
68
+ }>, Schema.Struct<{
69
+ readonly type: Schema.Literal<"reasoning">;
70
+ readonly id: Schema.optional<Schema.String>;
71
+ readonly summary: Schema.optional<Schema.String>;
72
+ readonly signature: Schema.optional<Schema.String>;
73
+ readonly providerData: Schema.optional<Schema.Unknown>;
74
+ }>]>>;
75
+ readonly usage: Schema.Struct<{
76
+ readonly input_tokens: Schema.optional<Schema.Number>;
77
+ readonly output_tokens: Schema.optional<Schema.Number>;
78
+ readonly total_tokens: Schema.optional<Schema.Number>;
79
+ readonly input_tokens_details: Schema.optional<Schema.Struct<{
80
+ readonly cached_tokens: Schema.optional<Schema.Number>;
81
+ }>>;
82
+ readonly output_tokens_details: Schema.optional<Schema.Struct<{
83
+ readonly reasoning_tokens: Schema.optional<Schema.Number>;
84
+ }>>;
85
+ }>;
86
+ readonly stop_reason: Schema.Literals<readonly ["stop", "tool_calls", "max_tokens", "refusal", "content_filter", "max_tool_calls"]>;
87
+ }>;
88
+ type Turn = typeof Turn.Type;
89
+ /**
90
+ * Canonical events emitted while a single turn is being generated. Most
91
+ * variants are streaming deltas (text, reasoning, tool-call args); the
92
+ * terminal `TurnComplete` carries the assembled `Turn`. Lifecycle members
93
+ * aren't deltas, hence the union name.
94
+ *
95
+ * `ReasoningDelta.kind`: `trace` is the model's raw chain-of-thought;
96
+ * `summary` is a model-written summary intended for display. OpenAI
97
+ * Responses emits both; Anthropic and Gemini only emit `trace`.
98
+ *
99
+ * `RefusalDelta`: the model declined to answer. OpenAI Responses emits
100
+ * this as its own event; Anthropic surfaces refusals via `stop_reason`
101
+ * and Gemini collapses them into `finishReason: SAFETY` — both go
102
+ * without a `RefusalDelta`.
103
+ *
104
+ * `UsageUpdate`: mid-stream cumulative usage. Anthropic emits this on
105
+ * `message_start` and `message_delta`; other providers may only deliver
106
+ * usage via `TurnComplete.turn.usage`.
107
+ */
108
+ type TurnEvent = Data.TaggedEnum<{
109
+ TextDelta: {
110
+ readonly text: string;
111
+ };
112
+ ReasoningDelta: {
113
+ readonly text: string;
114
+ readonly kind: "trace" | "summary";
115
+ };
116
+ RefusalDelta: {
117
+ readonly text: string;
118
+ };
119
+ ToolCallStart: {
120
+ readonly call_id: string;
121
+ readonly name: string;
122
+ };
123
+ ToolCallArgsDelta: {
124
+ readonly call_id: string;
125
+ readonly delta: string;
126
+ };
127
+ UsageUpdate: {
128
+ readonly usage: Usage;
129
+ };
130
+ TurnComplete: {
131
+ readonly turn: Turn;
132
+ };
133
+ }>;
134
+ declare const TurnEvent: {
135
+ readonly TextDelta: Data.TaggedEnum.ConstructorFrom<{
136
+ readonly _tag: "TextDelta";
137
+ readonly text: string;
138
+ }, "_tag">;
139
+ readonly ReasoningDelta: Data.TaggedEnum.ConstructorFrom<{
140
+ readonly _tag: "ReasoningDelta";
141
+ readonly text: string;
142
+ readonly kind: "trace" | "summary";
143
+ }, "_tag">;
144
+ readonly RefusalDelta: Data.TaggedEnum.ConstructorFrom<{
145
+ readonly _tag: "RefusalDelta";
146
+ readonly text: string;
147
+ }, "_tag">;
148
+ readonly ToolCallStart: Data.TaggedEnum.ConstructorFrom<{
149
+ readonly _tag: "ToolCallStart";
150
+ readonly call_id: string;
151
+ readonly name: string;
152
+ }, "_tag">;
153
+ readonly ToolCallArgsDelta: Data.TaggedEnum.ConstructorFrom<{
154
+ readonly _tag: "ToolCallArgsDelta";
155
+ readonly call_id: string;
156
+ readonly delta: string;
157
+ }, "_tag">;
158
+ readonly UsageUpdate: Data.TaggedEnum.ConstructorFrom<{
159
+ readonly _tag: "UsageUpdate";
160
+ readonly usage: Usage;
161
+ }, "_tag">;
162
+ readonly TurnComplete: Data.TaggedEnum.ConstructorFrom<{
163
+ readonly _tag: "TurnComplete";
164
+ readonly turn: Turn;
165
+ }, "_tag">;
166
+ readonly $is: <Tag extends "TextDelta" | "ReasoningDelta" | "RefusalDelta" | "ToolCallStart" | "ToolCallArgsDelta" | "UsageUpdate" | "TurnComplete">(tag: Tag) => (u: unknown) => u is Extract<{
167
+ readonly _tag: "TextDelta";
168
+ readonly text: string;
169
+ }, {
170
+ readonly _tag: Tag;
171
+ }> | Extract<{
172
+ readonly _tag: "ReasoningDelta";
173
+ readonly text: string;
174
+ readonly kind: "trace" | "summary";
175
+ }, {
176
+ readonly _tag: Tag;
177
+ }> | Extract<{
178
+ readonly _tag: "RefusalDelta";
179
+ readonly text: string;
180
+ }, {
181
+ readonly _tag: Tag;
182
+ }> | Extract<{
183
+ readonly _tag: "ToolCallStart";
184
+ readonly call_id: string;
185
+ readonly name: string;
186
+ }, {
187
+ readonly _tag: Tag;
188
+ }> | Extract<{
189
+ readonly _tag: "ToolCallArgsDelta";
190
+ readonly call_id: string;
191
+ readonly delta: string;
192
+ }, {
193
+ readonly _tag: Tag;
194
+ }> | Extract<{
195
+ readonly _tag: "UsageUpdate";
196
+ readonly usage: Usage;
197
+ }, {
198
+ readonly _tag: Tag;
199
+ }> | Extract<{
200
+ readonly _tag: "TurnComplete";
201
+ readonly turn: Turn;
202
+ }, {
203
+ readonly _tag: Tag;
204
+ }>;
205
+ readonly $match: {
206
+ <Cases extends {
207
+ readonly TextDelta: (args: {
208
+ readonly _tag: "TextDelta";
209
+ readonly text: string;
210
+ }) => any;
211
+ readonly ReasoningDelta: (args: {
212
+ readonly _tag: "ReasoningDelta";
213
+ readonly text: string;
214
+ readonly kind: "trace" | "summary";
215
+ }) => any;
216
+ readonly RefusalDelta: (args: {
217
+ readonly _tag: "RefusalDelta";
218
+ readonly text: string;
219
+ }) => any;
220
+ readonly ToolCallStart: (args: {
221
+ readonly _tag: "ToolCallStart";
222
+ readonly call_id: string;
223
+ readonly name: string;
224
+ }) => any;
225
+ readonly ToolCallArgsDelta: (args: {
226
+ readonly _tag: "ToolCallArgsDelta";
227
+ readonly call_id: string;
228
+ readonly delta: string;
229
+ }) => any;
230
+ readonly UsageUpdate: (args: {
231
+ readonly _tag: "UsageUpdate";
232
+ readonly usage: Usage;
233
+ }) => any;
234
+ readonly TurnComplete: (args: {
235
+ readonly _tag: "TurnComplete";
236
+ readonly turn: Turn;
237
+ }) => any;
238
+ }>(cases: Cases): (value: {
239
+ readonly _tag: "TextDelta";
240
+ readonly text: string;
241
+ } | {
242
+ readonly _tag: "ReasoningDelta";
243
+ readonly text: string;
244
+ readonly kind: "trace" | "summary";
245
+ } | {
246
+ readonly _tag: "RefusalDelta";
247
+ readonly text: string;
248
+ } | {
249
+ readonly _tag: "ToolCallStart";
250
+ readonly call_id: string;
251
+ readonly name: string;
252
+ } | {
253
+ readonly _tag: "ToolCallArgsDelta";
254
+ readonly call_id: string;
255
+ readonly delta: string;
256
+ } | {
257
+ readonly _tag: "UsageUpdate";
258
+ readonly usage: Usage;
259
+ } | {
260
+ readonly _tag: "TurnComplete";
261
+ readonly turn: Turn;
262
+ }) => _$effect_Unify0.Unify<ReturnType<Cases["TextDelta" | "ReasoningDelta" | "RefusalDelta" | "ToolCallStart" | "ToolCallArgsDelta" | "UsageUpdate" | "TurnComplete"]>>;
263
+ <Cases extends {
264
+ readonly TextDelta: (args: {
265
+ readonly _tag: "TextDelta";
266
+ readonly text: string;
267
+ }) => any;
268
+ readonly ReasoningDelta: (args: {
269
+ readonly _tag: "ReasoningDelta";
270
+ readonly text: string;
271
+ readonly kind: "trace" | "summary";
272
+ }) => any;
273
+ readonly RefusalDelta: (args: {
274
+ readonly _tag: "RefusalDelta";
275
+ readonly text: string;
276
+ }) => any;
277
+ readonly ToolCallStart: (args: {
278
+ readonly _tag: "ToolCallStart";
279
+ readonly call_id: string;
280
+ readonly name: string;
281
+ }) => any;
282
+ readonly ToolCallArgsDelta: (args: {
283
+ readonly _tag: "ToolCallArgsDelta";
284
+ readonly call_id: string;
285
+ readonly delta: string;
286
+ }) => any;
287
+ readonly UsageUpdate: (args: {
288
+ readonly _tag: "UsageUpdate";
289
+ readonly usage: Usage;
290
+ }) => any;
291
+ readonly TurnComplete: (args: {
292
+ readonly _tag: "TurnComplete";
293
+ readonly turn: Turn;
294
+ }) => any;
295
+ }>(value: {
296
+ readonly _tag: "TextDelta";
297
+ readonly text: string;
298
+ } | {
299
+ readonly _tag: "ReasoningDelta";
300
+ readonly text: string;
301
+ readonly kind: "trace" | "summary";
302
+ } | {
303
+ readonly _tag: "RefusalDelta";
304
+ readonly text: string;
305
+ } | {
306
+ readonly _tag: "ToolCallStart";
307
+ readonly call_id: string;
308
+ readonly name: string;
309
+ } | {
310
+ readonly _tag: "ToolCallArgsDelta";
311
+ readonly call_id: string;
312
+ readonly delta: string;
313
+ } | {
314
+ readonly _tag: "UsageUpdate";
315
+ readonly usage: Usage;
316
+ } | {
317
+ readonly _tag: "TurnComplete";
318
+ readonly turn: Turn;
319
+ }, cases: Cases): _$effect_Unify0.Unify<ReturnType<Cases["TextDelta" | "ReasoningDelta" | "RefusalDelta" | "ToolCallStart" | "ToolCallArgsDelta" | "UsageUpdate" | "TurnComplete"]>>;
320
+ };
321
+ };
322
+ /**
323
+ * What flows out of an agent loop body to its consumer per turn: every
324
+ * `TurnEvent` the provider emits (including the terminal `TurnComplete`
325
+ * carrying the assembled `Turn`), plus the output of any tool the loop ran.
326
+ * Both variants carry a `_tag` discriminator.
327
+ */
328
+ type InteractionEvent = TurnEvent | ToolCallOutput;
329
+ declare const isTurnComplete: (u: unknown) => u is {
330
+ readonly _tag: "TurnComplete";
331
+ readonly turn: Turn;
332
+ };
333
+ declare const getToolCalls: (turn: Turn) => ReadonlyArray<ToolCall>;
334
+ declare const reasonings: (turn: Turn) => ReadonlyArray<Reasoning>;
335
+ declare const assistantMessages: (turn: Turn) => ReadonlyArray<Message>;
336
+ /**
337
+ * Every `output_text` payload across every assistant message in the turn,
338
+ * preserving order. Refusals and other content blocks are dropped — use
339
+ * `assistantMessages` if you need to inspect them. The primitive for
340
+ * "give me the assistant's text"; callers decide how to combine
341
+ * (typically `.join("")` for prose or `.join(" ")` for log strings).
342
+ */
343
+ declare const assistantTexts: (turn: Turn) => ReadonlyArray<string>;
344
+ /**
345
+ * Sugar over `assistantTexts(turn).join("")` — the common case for
346
+ * summarizers, classifiers, judge calls, and structured-output backstops
347
+ * that want one concatenated string.
348
+ */
349
+ declare const assistantText: (turn: Turn) => string;
350
+ /**
351
+ * Append a completed turn and optional follow-up items to a state record's
352
+ * history. Recipes use this at the point where structured tool results are
353
+ * converted to model-facing `ToolCallOutput`s.
354
+ */
355
+ declare const appendToHistory: <S extends {
356
+ readonly history: ReadonlyArray<HistoryItem>;
357
+ }>(state: S, turn: Turn, items?: ReadonlyArray<HistoryItem>) => S;
358
+ /**
359
+ * Project a `TurnEvent` stream onto its `TextDelta` payloads. Other
360
+ * variants are dropped. Composes with `Lines.lines` +
361
+ * `decodeJsonLines` for prompted-JSONL streaming.
362
+ */
363
+ declare const textDeltas: <E, R>(self: Stream.Stream<TurnEvent, E, R>) => Stream.Stream<string, E, R>;
364
+ declare const RefusalRejected_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 & {
365
+ readonly _tag: "RefusalRejected";
366
+ } & Readonly<A>;
367
+ /**
368
+ * The assistant message on the just-completed turn was a refusal block,
369
+ * not an `output_text` payload. Returned by `decodeStructured` to short-circuit
370
+ * decoding before `JSON.parse` / schema validation runs.
371
+ */
372
+ declare class RefusalRejected extends RefusalRejected_base<{
373
+ readonly turn: Turn;
374
+ }> {}
375
+ /**
376
+ * Validate a completed `Turn` against a `StructuredFormat`. Concatenates
377
+ * `output_text` blocks on the last assistant message, then runs
378
+ * `JSON.parse` + the format's schema validation.
379
+ *
380
+ * Three failure modes:
381
+ * - `RefusalRejected` — the assistant emitted a refusal block.
382
+ * - `JsonParseError` — the assembled text wasn't valid JSON.
383
+ * - `StructuredDecodeError` — the JSON didn't match the schema.
384
+ */
385
+ declare const decodeStructured: <A>(turn: Turn, format: StructuredFormat<A>) => Effect.Effect<A, RefusalRejected | JsonParseError | StructuredDecodeError>;
386
+ //#endregion
387
+ export { InteractionEvent, RefusalRejected, Turn, TurnEvent, appendToHistory, assistantMessages, assistantText, assistantTexts, decodeStructured, getToolCalls, isTurnComplete, reasonings, Turn_d_exports as t, textDeltas };
388
+ //# sourceMappingURL=Turn.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Turn.d.mts","names":[],"sources":["../../src/domain/Turn.ts"],"mappings":";;;;;;;;;;;;;;;;;cAqBa,IAAA,EAAI,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKL,IAAA,UAAc,IAAA,CAAK,IAAA;;;;;;;;;;;;;;;;;;;;KAqBnB,SAAA,GAAY,IAAA,CAAK,UAAA;EAC3B,SAAA;IAAA,SAAsB,IAAA;EAAA;EACtB,cAAA;IAAA,SAA2B,IAAA;IAAA,SAAuB,IAAA;EAAA;EAClD,YAAA;IAAA,SAAyB,IAAA;EAAA;EACzB,aAAA;IAAA,SAA0B,OAAA;IAAA,SAA0B,IAAA;EAAA;EACpD,iBAAA;IAAA,SAA8B,OAAA;IAAA,SAA0B,KAAA;EAAA;EACxD,WAAA;IAAA,SAAwB,KAAA,EAAO,KAAA;EAAA;EAC/B,YAAA;IAAA,SAAyB,IAAA,EAAM,IAAA;EAAA;AAAA;AAAA,cAGpB,SAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;oBAJoB,KAAA;EAAA;EAAA;;mBACA,IAAA;EAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBADA,KAAA;EAAA;IAAA;;;mBACA,IAAA;EAAA;IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBADA,KAAA;MAAA;MAAA;;uBACA,IAAA;MAAA;IAAA;;;;;;;;;;;;;;;;;;;;sBADA,KAAA;IAAA;MAAA;qBACA,IAAA;IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;wBADA,KAAA;MAAA;MAAA;;uBACA,IAAA;MAAA;IAAA;;;;;;;;;;;;;;;;;;;;sBADA,KAAA;IAAA;MAAA;qBACA,IAAA;IAAA;;;;;;;;;KAWrB,gBAAA,GAAmB,SAAA,GAAY,cAAA;AAAA,cAE9B,cAAA,GAAc,CAAA,cAAA,CAAA;EAAA;iBAbM,IAAA;AAAA;AAAA,cAepB,YAAA,GAAgB,IAAA,EAAM,IAAA,KAAO,aAAA,CAAc,QAAA;AAAA,cAE3C,UAAA,GAAc,IAAA,EAAM,IAAA,KAAO,aAAA,CAAc,SAAA;AAAA,cAEzC,iBAAA,GAAqB,IAAA,EAAM,IAAA,KAAO,aAAA,CAAc,OAAA;;;;;;;;cAUhD,cAAA,GAAkB,IAAA,EAAM,IAAA,KAAO,aAAA;;;;;;cAW/B,aAAA,GAAiB,IAAA,EAAM,IAAA;;;;;AA/CpC;cAsDa,eAAA;EAAA,SAAwC,OAAA,EAAS,aAAA,CAAc,WAAA;AAAA,GAC1E,KAAA,EAAO,CAAA,EACP,IAAA,EAAM,IAAA,EACN,KAAA,GAAO,aAAA,CAAc,WAAA,MACpB,CAAA;;;;;;cAcU,UAAA,SACX,IAAA,EAAM,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,CAAA,EAAG,CAAA,MACjC,MAAA,CAAO,MAAA,SAAe,CAAA,EAAG,CAAA;AAAA,cAGzB,oBAAA;;;;;;;;cAWU,eAAA,SAAwB,oBAAA;EAAA,SAC1B,IAAA,EAAM,IAAA;AAAA;;;;;;;;;;AA/EjB;cAwGa,gBAAA,MACX,IAAA,EAAM,IAAA,EACN,MAAA,EAAQ,gBAAA,CAAkC,CAAA,MACzC,MAAA,CAAO,MAAA,CACR,CAAA,EACA,eAAA,GAAkB,cAAA,GAAkC,qBAAA"}
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "../chunk-uyGKjUfl.mjs";
2
- import { Item, StopReason, Usage, isOutputText, isRefusal } from "./Items.mjs";
2
+ import { HistoryItem, StopReason, Usage, isOutputText, isReasoning, isRefusal, isToolCall } from "./Items.mjs";
3
3
  import { parseJson } from "../structured-format/StructuredFormat.mjs";
4
4
  import { Data, Effect, Result, Schema, Stream, pipe } from "effect";
5
5
  //#region src/domain/Turn.ts
@@ -7,15 +7,15 @@ var Turn_exports = /* @__PURE__ */ __exportAll({
7
7
  RefusalRejected: () => RefusalRejected,
8
8
  Turn: () => Turn,
9
9
  TurnEvent: () => TurnEvent,
10
- appendTurn: () => appendTurn,
10
+ appendToHistory: () => appendToHistory,
11
11
  assistantMessages: () => assistantMessages,
12
12
  assistantText: () => assistantText,
13
13
  assistantTexts: () => assistantTexts,
14
- functionCalls: () => functionCalls,
14
+ decodeStructured: () => decodeStructured,
15
+ getToolCalls: () => getToolCalls,
15
16
  isTurnComplete: () => isTurnComplete,
16
17
  reasonings: () => reasonings,
17
- textDeltas: () => textDeltas,
18
- toStructured: () => toStructured
18
+ textDeltas: () => textDeltas
19
19
  });
20
20
  /**
21
21
  * The result of a single LLM generation. A turn produces zero or more items
@@ -23,14 +23,14 @@ var Turn_exports = /* @__PURE__ */ __exportAll({
23
23
  * and reports usage + a stop reason.
24
24
  */
25
25
  const Turn = Schema.Struct({
26
- items: Schema.Array(Item),
26
+ items: Schema.Array(HistoryItem),
27
27
  usage: Usage,
28
28
  stop_reason: StopReason
29
29
  });
30
30
  const TurnEvent = Data.taggedEnum();
31
31
  const isTurnComplete = TurnEvent.$is("TurnComplete");
32
- const functionCalls = (turn) => turn.items.filter((i) => i.type === "function_call");
33
- const reasonings = (turn) => turn.items.filter((i) => i.type === "reasoning");
32
+ const getToolCalls = (turn) => turn.items.filter(isToolCall);
33
+ const reasonings = (turn) => turn.items.filter(isReasoning);
34
34
  const assistantMessages = (turn) => turn.items.filter((i) => i.type === "message" && i.role === "assistant");
35
35
  /**
36
36
  * Every `output_text` payload across every assistant message in the turn,
@@ -49,9 +49,9 @@ const assistantText = (turn) => assistantTexts(turn).join("");
49
49
  /**
50
50
  * Append a completed turn and optional follow-up items to a state record's
51
51
  * history. Recipes use this at the point where structured tool results are
52
- * converted to model-facing `FunctionCallOutput`s.
52
+ * converted to model-facing `ToolCallOutput`s.
53
53
  */
54
- const appendTurn = (state, turn, items = []) => ({
54
+ const appendToHistory = (state, turn, items = []) => ({
55
55
  ...state,
56
56
  history: [
57
57
  ...state.history,
@@ -67,7 +67,7 @@ const appendTurn = (state, turn, items = []) => ({
67
67
  const textDeltas = (self) => self.pipe(Stream.filterMap((ev) => ev._tag === "TextDelta" ? Result.succeed(ev.text) : Result.failVoid));
68
68
  /**
69
69
  * The assistant message on the just-completed turn was a refusal block,
70
- * not an `output_text` payload. Returned by `toStructured` to short-circuit
70
+ * not an `output_text` payload. Returned by `decodeStructured` to short-circuit
71
71
  * decoding before `JSON.parse` / schema validation runs.
72
72
  */
73
73
  var RefusalRejected = class extends Data.TaggedError("RefusalRejected") {};
@@ -97,8 +97,8 @@ const lastAssistantContent = (turn) => {
97
97
  * - `JsonParseError` — the assembled text wasn't valid JSON.
98
98
  * - `StructuredDecodeError` — the JSON didn't match the schema.
99
99
  */
100
- const toStructured = (turn, format) => pipe(lastAssistantContent(turn), ({ text, refused }) => refused ? Effect.fail(new RefusalRejected({ turn })) : parseJson(format)(text));
100
+ const decodeStructured = (turn, format) => pipe(lastAssistantContent(turn), ({ text, refused }) => refused ? Effect.fail(new RefusalRejected({ turn })) : parseJson(format)(text));
101
101
  //#endregion
102
- export { RefusalRejected, Turn, TurnEvent, appendTurn, assistantMessages, assistantText, assistantTexts, functionCalls, isTurnComplete, reasonings, Turn_exports as t, textDeltas, toStructured };
102
+ export { RefusalRejected, Turn, TurnEvent, appendToHistory, assistantMessages, assistantText, assistantTexts, decodeStructured, getToolCalls, isTurnComplete, reasonings, Turn_exports as t, textDeltas };
103
103
 
104
104
  //# sourceMappingURL=Turn.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Turn.mjs","names":["StructuredFormat.parseJson"],"sources":["../../src/domain/Turn.ts"],"sourcesContent":["import { Data, Effect, Result, Schema, Stream, pipe } from \"effect\"\nimport * as StructuredFormat from \"../structured-format/StructuredFormat.js\"\nimport {\n FunctionCall,\n FunctionCallOutput,\n Item,\n isOutputText,\n isRefusal,\n Message,\n Reasoning,\n StopReason,\n Usage,\n} from \"./Items.js\"\n\n/**\n * The result of a single LLM generation. A turn produces zero or more items\n * (typically one assistant message and zero or more function_call items)\n * and reports usage + a stop reason.\n */\nexport const Turn = Schema.Struct({\n items: Schema.Array(Item),\n usage: Usage,\n stop_reason: StopReason,\n})\nexport type Turn = typeof Turn.Type\n\n/**\n * Canonical events emitted while a single turn is being generated. Most\n * variants are streaming deltas (text, reasoning, tool-call args); the\n * terminal `TurnComplete` carries the assembled `Turn`. Lifecycle members\n * aren't deltas, hence the union name.\n *\n * `ReasoningDelta.kind`: `trace` is the model's raw chain-of-thought;\n * `summary` is a model-written summary intended for display. OpenAI\n * Responses emits both; Anthropic and Gemini only emit `trace`.\n *\n * `RefusalDelta`: the model declined to answer. OpenAI Responses emits\n * this as its own event; Anthropic surfaces refusals via `stop_reason`\n * and Gemini collapses them into `finishReason: SAFETY` — both go\n * without a `RefusalDelta`.\n *\n * `UsageUpdate`: mid-stream cumulative usage. Anthropic emits this on\n * `message_start` and `message_delta`; other providers may only deliver\n * usage via `TurnComplete.turn.usage`.\n */\nexport type TurnEvent = Data.TaggedEnum<{\n TextDelta: { readonly text: string }\n ReasoningDelta: { readonly text: string; readonly kind: \"trace\" | \"summary\" }\n RefusalDelta: { readonly text: string }\n ToolCallStart: { readonly call_id: string; readonly name: string }\n ToolCallArgsDelta: { readonly call_id: string; readonly delta: string }\n UsageUpdate: { readonly usage: Usage }\n TurnComplete: { readonly turn: Turn }\n}>\n\nexport const TurnEvent = Data.taggedEnum<TurnEvent>()\n\n/**\n * What flows out of an agent loop body to its consumer per turn: every\n * `TurnEvent` the provider emits (including the terminal `TurnComplete`\n * carrying the assembled `Turn`), plus the output of any tool the loop ran.\n * Both variants carry a `_tag` discriminator.\n */\nexport type InteractionEvent = TurnEvent | FunctionCallOutput\n\nexport const isTurnComplete = TurnEvent.$is(\"TurnComplete\")\n\nexport const functionCalls = (turn: Turn): ReadonlyArray<FunctionCall> =>\n turn.items.filter((i): i is FunctionCall => i.type === \"function_call\")\n\nexport const reasonings = (turn: Turn): ReadonlyArray<Reasoning> =>\n turn.items.filter((i): i is Reasoning => i.type === \"reasoning\")\n\nexport const assistantMessages = (turn: Turn): ReadonlyArray<Message> =>\n turn.items.filter((i): i is Message => i.type === \"message\" && i.role === \"assistant\")\n\n/**\n * Every `output_text` payload across every assistant message in the turn,\n * preserving order. Refusals and other content blocks are dropped — use\n * `assistantMessages` if you need to inspect them. The primitive for\n * \"give me the assistant's text\"; callers decide how to combine\n * (typically `.join(\"\")` for prose or `.join(\" \")` for log strings).\n */\nexport const assistantTexts = (turn: Turn): ReadonlyArray<string> =>\n assistantMessages(turn)\n .flatMap((m) => m.content)\n .filter(isOutputText)\n .map((b) => b.text)\n\n/**\n * Sugar over `assistantTexts(turn).join(\"\")` — the common case for\n * summarizers, classifiers, judge calls, and structured-output backstops\n * that want one concatenated string.\n */\nexport const assistantText = (turn: Turn): string => assistantTexts(turn).join(\"\")\n\n/**\n * Append a completed turn and optional follow-up items to a state record's\n * history. Recipes use this at the point where structured tool results are\n * converted to model-facing `FunctionCallOutput`s.\n */\nexport const appendTurn = <S extends { readonly history: ReadonlyArray<Item> }>(\n state: S,\n turn: Turn,\n items: ReadonlyArray<Item> = [],\n): S => ({\n ...state,\n history: [...state.history, ...turn.items, ...items],\n})\n\n// ---------------------------------------------------------------------------\n// Stream operators\n// ---------------------------------------------------------------------------\n\n/**\n * Project a `TurnEvent` stream onto its `TextDelta` payloads. Other\n * variants are dropped. Composes with `Lines.lines` +\n * `decodeJsonLines` for prompted-JSONL streaming.\n */\nexport const textDeltas = <E, R>(\n self: Stream.Stream<TurnEvent, E, R>,\n): Stream.Stream<string, E, R> =>\n self.pipe(\n Stream.filterMap((ev) => (ev._tag === \"TextDelta\" ? Result.succeed(ev.text) : Result.failVoid)),\n )\n\n// ---------------------------------------------------------------------------\n// Structured-output integration\n// ---------------------------------------------------------------------------\n\n/**\n * The assistant message on the just-completed turn was a refusal block,\n * not an `output_text` payload. Returned by `toStructured` to short-circuit\n * decoding before `JSON.parse` / schema validation runs.\n */\nexport class RefusalRejected extends Data.TaggedError(\"RefusalRejected\")<{\n readonly turn: Turn\n}> {}\n\nconst lastAssistantContent = (turn: Turn): { readonly text: string; readonly refused: boolean } => {\n const assistants = assistantMessages(turn)\n const last = assistants[assistants.length - 1]\n if (last === undefined) return { text: \"\", refused: false }\n if (last.content.some(isRefusal)) return { text: \"\", refused: true }\n const text = last.content\n .filter(isOutputText)\n .map((b) => b.text)\n .join(\"\")\n return { text, refused: false }\n}\n\n/**\n * Validate a completed `Turn` against a `StructuredFormat`. Concatenates\n * `output_text` blocks on the last assistant message, then runs\n * `JSON.parse` + the format's schema validation.\n *\n * Three failure modes:\n * - `RefusalRejected` — the assistant emitted a refusal block.\n * - `JsonParseError` — the assembled text wasn't valid JSON.\n * - `StructuredDecodeError` — the JSON didn't match the schema.\n */\nexport const toStructured = <A>(\n turn: Turn,\n format: StructuredFormat.StructuredFormat<A>,\n): Effect.Effect<\n A,\n RefusalRejected | StructuredFormat.JsonParseError | StructuredFormat.StructuredDecodeError\n> =>\n pipe(lastAssistantContent(turn), ({ text, refused }) =>\n refused ? Effect.fail(new RefusalRejected({ turn })) : StructuredFormat.parseJson(format)(text),\n )\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmBA,MAAa,OAAO,OAAO,OAAO;CAChC,OAAO,OAAO,MAAM,KAAK;CACzB,OAAO;CACP,aAAa;CACd,CAAC;AAgCF,MAAa,YAAY,KAAK,YAAuB;AAUrD,MAAa,iBAAiB,UAAU,IAAI,eAAe;AAE3D,MAAa,iBAAiB,SAC5B,KAAK,MAAM,QAAQ,MAAyB,EAAE,SAAS,gBAAgB;AAEzE,MAAa,cAAc,SACzB,KAAK,MAAM,QAAQ,MAAsB,EAAE,SAAS,YAAY;AAElE,MAAa,qBAAqB,SAChC,KAAK,MAAM,QAAQ,MAAoB,EAAE,SAAS,aAAa,EAAE,SAAS,YAAY;;;;;;;;AASxF,MAAa,kBAAkB,SAC7B,kBAAkB,KAAK,CACpB,SAAS,MAAM,EAAE,QAAQ,CACzB,OAAO,aAAa,CACpB,KAAK,MAAM,EAAE,KAAK;;;;;;AAOvB,MAAa,iBAAiB,SAAuB,eAAe,KAAK,CAAC,KAAK,GAAG;;;;;;AAOlF,MAAa,cACX,OACA,MACA,QAA6B,EAAE,MACxB;CACP,GAAG;CACH,SAAS;EAAC,GAAG,MAAM;EAAS,GAAG,KAAK;EAAO,GAAG;EAAM;CACrD;;;;;;AAWD,MAAa,cACX,SAEA,KAAK,KACH,OAAO,WAAW,OAAQ,GAAG,SAAS,cAAc,OAAO,QAAQ,GAAG,KAAK,GAAG,OAAO,SAAU,CAChG;;;;;;AAWH,IAAa,kBAAb,cAAqC,KAAK,YAAY,kBAAkB,CAErE;AAEH,MAAM,wBAAwB,SAAqE;CACjG,MAAM,aAAa,kBAAkB,KAAK;CAC1C,MAAM,OAAO,WAAW,WAAW,SAAS;AAC5C,KAAI,SAAS,KAAA,EAAW,QAAO;EAAE,MAAM;EAAI,SAAS;EAAO;AAC3D,KAAI,KAAK,QAAQ,KAAK,UAAU,CAAE,QAAO;EAAE,MAAM;EAAI,SAAS;EAAM;AAKpE,QAAO;EAAE,MAJI,KAAK,QACf,OAAO,aAAa,CACpB,KAAK,MAAM,EAAE,KAAK,CAClB,KAAK,GACK;EAAE,SAAS;EAAO;;;;;;;;;;;;AAajC,MAAa,gBACX,MACA,WAKA,KAAK,qBAAqB,KAAK,GAAG,EAAE,MAAM,cACxC,UAAU,OAAO,KAAK,IAAI,gBAAgB,EAAE,MAAM,CAAC,CAAC,GAAGA,UAA2B,OAAO,CAAC,KAAK,CAChG"}
1
+ {"version":3,"file":"Turn.mjs","names":["StructuredFormat.parseJson"],"sources":["../../src/domain/Turn.ts"],"sourcesContent":["import { Data, Effect, Result, Schema, Stream, pipe } from \"effect\"\nimport * as StructuredFormat from \"../structured-format/StructuredFormat.js\"\nimport {\n HistoryItem,\n Message,\n Reasoning,\n StopReason,\n ToolCall,\n ToolCallOutput,\n Usage,\n isOutputText,\n isReasoning,\n isRefusal,\n isToolCall,\n} from \"./Items.js\"\n\n/**\n * The result of a single LLM generation. A turn produces zero or more items\n * (typically one assistant message and zero or more function_call items)\n * and reports usage + a stop reason.\n */\nexport const Turn = Schema.Struct({\n items: Schema.Array(HistoryItem),\n usage: Usage,\n stop_reason: StopReason,\n})\nexport type Turn = typeof Turn.Type\n\n/**\n * Canonical events emitted while a single turn is being generated. Most\n * variants are streaming deltas (text, reasoning, tool-call args); the\n * terminal `TurnComplete` carries the assembled `Turn`. Lifecycle members\n * aren't deltas, hence the union name.\n *\n * `ReasoningDelta.kind`: `trace` is the model's raw chain-of-thought;\n * `summary` is a model-written summary intended for display. OpenAI\n * Responses emits both; Anthropic and Gemini only emit `trace`.\n *\n * `RefusalDelta`: the model declined to answer. OpenAI Responses emits\n * this as its own event; Anthropic surfaces refusals via `stop_reason`\n * and Gemini collapses them into `finishReason: SAFETY` — both go\n * without a `RefusalDelta`.\n *\n * `UsageUpdate`: mid-stream cumulative usage. Anthropic emits this on\n * `message_start` and `message_delta`; other providers may only deliver\n * usage via `TurnComplete.turn.usage`.\n */\nexport type TurnEvent = Data.TaggedEnum<{\n TextDelta: { readonly text: string }\n ReasoningDelta: { readonly text: string; readonly kind: \"trace\" | \"summary\" }\n RefusalDelta: { readonly text: string }\n ToolCallStart: { readonly call_id: string; readonly name: string }\n ToolCallArgsDelta: { readonly call_id: string; readonly delta: string }\n UsageUpdate: { readonly usage: Usage }\n TurnComplete: { readonly turn: Turn }\n}>\n\nexport const TurnEvent = Data.taggedEnum<TurnEvent>()\n\n/**\n * What flows out of an agent loop body to its consumer per turn: every\n * `TurnEvent` the provider emits (including the terminal `TurnComplete`\n * carrying the assembled `Turn`), plus the output of any tool the loop ran.\n * Both variants carry a `_tag` discriminator.\n */\nexport type InteractionEvent = TurnEvent | ToolCallOutput\n\nexport const isTurnComplete = TurnEvent.$is(\"TurnComplete\")\n\nexport const getToolCalls = (turn: Turn): ReadonlyArray<ToolCall> => turn.items.filter(isToolCall)\n\nexport const reasonings = (turn: Turn): ReadonlyArray<Reasoning> => turn.items.filter(isReasoning)\n\nexport const assistantMessages = (turn: Turn): ReadonlyArray<Message> =>\n turn.items.filter((i): i is Message => i.type === \"message\" && i.role === \"assistant\")\n\n/**\n * Every `output_text` payload across every assistant message in the turn,\n * preserving order. Refusals and other content blocks are dropped — use\n * `assistantMessages` if you need to inspect them. The primitive for\n * \"give me the assistant's text\"; callers decide how to combine\n * (typically `.join(\"\")` for prose or `.join(\" \")` for log strings).\n */\nexport const assistantTexts = (turn: Turn): ReadonlyArray<string> =>\n assistantMessages(turn)\n .flatMap((m) => m.content)\n .filter(isOutputText)\n .map((b) => b.text)\n\n/**\n * Sugar over `assistantTexts(turn).join(\"\")` — the common case for\n * summarizers, classifiers, judge calls, and structured-output backstops\n * that want one concatenated string.\n */\nexport const assistantText = (turn: Turn): string => assistantTexts(turn).join(\"\")\n\n/**\n * Append a completed turn and optional follow-up items to a state record's\n * history. Recipes use this at the point where structured tool results are\n * converted to model-facing `ToolCallOutput`s.\n */\nexport const appendToHistory = <S extends { readonly history: ReadonlyArray<HistoryItem> }>(\n state: S,\n turn: Turn,\n items: ReadonlyArray<HistoryItem> = [],\n): S => ({\n ...state,\n history: [...state.history, ...turn.items, ...items],\n})\n\n// ---------------------------------------------------------------------------\n// Stream operators\n// ---------------------------------------------------------------------------\n\n/**\n * Project a `TurnEvent` stream onto its `TextDelta` payloads. Other\n * variants are dropped. Composes with `Lines.lines` +\n * `decodeJsonLines` for prompted-JSONL streaming.\n */\nexport const textDeltas = <E, R>(\n self: Stream.Stream<TurnEvent, E, R>,\n): Stream.Stream<string, E, R> =>\n self.pipe(\n Stream.filterMap((ev) => (ev._tag === \"TextDelta\" ? Result.succeed(ev.text) : Result.failVoid)),\n )\n\n// ---------------------------------------------------------------------------\n// Structured-output integration\n// ---------------------------------------------------------------------------\n\n/**\n * The assistant message on the just-completed turn was a refusal block,\n * not an `output_text` payload. Returned by `decodeStructured` to short-circuit\n * decoding before `JSON.parse` / schema validation runs.\n */\nexport class RefusalRejected extends Data.TaggedError(\"RefusalRejected\")<{\n readonly turn: Turn\n}> {}\n\nconst lastAssistantContent = (turn: Turn): { readonly text: string; readonly refused: boolean } => {\n const assistants = assistantMessages(turn)\n const last = assistants[assistants.length - 1]\n if (last === undefined) return { text: \"\", refused: false }\n if (last.content.some(isRefusal)) return { text: \"\", refused: true }\n const text = last.content\n .filter(isOutputText)\n .map((b) => b.text)\n .join(\"\")\n return { text, refused: false }\n}\n\n/**\n * Validate a completed `Turn` against a `StructuredFormat`. Concatenates\n * `output_text` blocks on the last assistant message, then runs\n * `JSON.parse` + the format's schema validation.\n *\n * Three failure modes:\n * - `RefusalRejected` — the assistant emitted a refusal block.\n * - `JsonParseError` — the assembled text wasn't valid JSON.\n * - `StructuredDecodeError` — the JSON didn't match the schema.\n */\nexport const decodeStructured = <A>(\n turn: Turn,\n format: StructuredFormat.StructuredFormat<A>,\n): Effect.Effect<\n A,\n RefusalRejected | StructuredFormat.JsonParseError | StructuredFormat.StructuredDecodeError\n> =>\n pipe(lastAssistantContent(turn), ({ text, refused }) =>\n refused ? Effect.fail(new RefusalRejected({ turn })) : StructuredFormat.parseJson(format)(text),\n )\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,OAAO,OAAO,OAAO;CAChC,OAAO,OAAO,MAAM,YAAY;CAChC,OAAO;CACP,aAAa;CACd,CAAC;AAgCF,MAAa,YAAY,KAAK,YAAuB;AAUrD,MAAa,iBAAiB,UAAU,IAAI,eAAe;AAE3D,MAAa,gBAAgB,SAAwC,KAAK,MAAM,OAAO,WAAW;AAElG,MAAa,cAAc,SAAyC,KAAK,MAAM,OAAO,YAAY;AAElG,MAAa,qBAAqB,SAChC,KAAK,MAAM,QAAQ,MAAoB,EAAE,SAAS,aAAa,EAAE,SAAS,YAAY;;;;;;;;AASxF,MAAa,kBAAkB,SAC7B,kBAAkB,KAAK,CACpB,SAAS,MAAM,EAAE,QAAQ,CACzB,OAAO,aAAa,CACpB,KAAK,MAAM,EAAE,KAAK;;;;;;AAOvB,MAAa,iBAAiB,SAAuB,eAAe,KAAK,CAAC,KAAK,GAAG;;;;;;AAOlF,MAAa,mBACX,OACA,MACA,QAAoC,EAAE,MAC/B;CACP,GAAG;CACH,SAAS;EAAC,GAAG,MAAM;EAAS,GAAG,KAAK;EAAO,GAAG;EAAM;CACrD;;;;;;AAWD,MAAa,cACX,SAEA,KAAK,KACH,OAAO,WAAW,OAAQ,GAAG,SAAS,cAAc,OAAO,QAAQ,GAAG,KAAK,GAAG,OAAO,SAAU,CAChG;;;;;;AAWH,IAAa,kBAAb,cAAqC,KAAK,YAAY,kBAAkB,CAErE;AAEH,MAAM,wBAAwB,SAAqE;CACjG,MAAM,aAAa,kBAAkB,KAAK;CAC1C,MAAM,OAAO,WAAW,WAAW,SAAS;AAC5C,KAAI,SAAS,KAAA,EAAW,QAAO;EAAE,MAAM;EAAI,SAAS;EAAO;AAC3D,KAAI,KAAK,QAAQ,KAAK,UAAU,CAAE,QAAO;EAAE,MAAM;EAAI,SAAS;EAAM;AAKpE,QAAO;EAAE,MAJI,KAAK,QACf,OAAO,aAAa,CACpB,KAAK,MAAM,EAAE,KAAK,CAClB,KAAK,GACK;EAAE,SAAS;EAAO;;;;;;;;;;;;AAajC,MAAa,oBACX,MACA,WAKA,KAAK,qBAAqB,KAAK,GAAG,EAAE,MAAM,cACxC,UAAU,OAAO,KAAK,IAAI,gBAAgB,EAAE,MAAM,CAAC,CAAC,GAAGA,UAA2B,OAAO,CAAC,KAAK,CAChG"}
@@ -2,7 +2,7 @@ import { i as ImageSource } from "../Image-HNmMpMTh.mjs";
2
2
 
3
3
  //#region src/embedding-model/Embedding.d.ts
4
4
  declare namespace Embedding_d_exports {
5
- export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse };
5
+ export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, ResponseEncoding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse };
6
6
  }
7
7
  /**
8
8
  * One part of a mixed text+image input. Used inside `EmbedInput.content[]`
@@ -94,6 +94,16 @@ declare const isInt8: (e: Embedding) => e is Int8Embedding;
94
94
  declare const isBinary: (e: Embedding) => e is BinaryEmbedding;
95
95
  declare const isSparse: (e: Embedding) => e is SparseEmbedding;
96
96
  declare const isMultivector: (e: Embedding) => e is MultivectorEmbedding;
97
+ /**
98
+ * Domain of `EmbeddingFor` and the response type parameter on
99
+ * `EmbedResponse` / `EmbedManyResponse`: every encoding a provider can
100
+ * *return*, including Jina's widened `sparse` / `multivector`. Distinct
101
+ * from `EmbedEncoding` (the cross-provider *request* set, which is dense
102
+ * quantization only). Providers whose typed request widens beyond the
103
+ * dense set (Jina) parameterize their responses with their own encoding
104
+ * union, which is a subset of this.
105
+ */
106
+ type ResponseEncoding = "float32" | "int8" | "binary" | "sparse" | "multivector";
97
107
  /**
98
108
  * Maps an `encoding` request field to the corresponding response embedding
99
109
  * variant. `undefined` (no encoding requested) defaults to `Float32Embedding`,
@@ -115,5 +125,5 @@ type Usage = {
115
125
  readonly inputTokens?: number;
116
126
  };
117
127
  //#endregion
118
- export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse, Embedding_d_exports as t };
128
+ export { BinaryEmbedding, EmbedContentPart, EmbedInput, Embedding, EmbeddingFor, Float32Embedding, Int8Embedding, MultivectorEmbedding, ResponseEncoding, SparseEmbedding, Usage, isBinary, isFloat32, isInt8, isMultivector, isSparse, Embedding_d_exports as t };
119
129
  //# sourceMappingURL=Embedding.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Embedding.d.mts","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"mappings":";;;;;;;;;;;KAOY,gBAAA;EAAA,SAA8B,IAAA;AAAA;EAAA,SAA4B,KAAA,EAAO,WAAA;AAAA;;;;;;;;;;KAWjE,UAAA;EAAA,SAEG,IAAA;AAAA;EAAA,SACA,KAAA,EAAO,WAAA;AAAA;EAAA,SACP,OAAA,EAAS,aAAA,CAAc,gBAAA;AAAA;;KAY1B,gBAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,YAAA;AAAA;;;;;KAOP,aAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,SAAA;AAAA;;;;;;KAQP,eAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,UAAA;AAAA;;;;;;;AAZnB;;;;;;;;;AAUA;;;KAuBY,eAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA;AAAA;;;AAF7B;;;;;;;;KAeY,oBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,YAAA;AAAA;AAAA,KAGtB,SAAA,GACR,gBAAA,GACA,aAAA,GACA,eAAA,GACA,eAAA,GACA,oBAAA;AAAA,cAES,SAAA,GAAa,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,gBAAA;AAAA,cACjC,MAAA,GAAU,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,aAAA;AAAA,cAC9B,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,aAAA,GAAiB,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,oBAAA;;;AAXlD;;;;;;;;;KAwBY,YAAA,OAAmB,CAAA,oCAC3B,gBAAA,IACC,CAAA,qBACC,aAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,4BACC,oBAAA,GACA,SAAA;;;;;;KAOA,KAAA;EAAA,SACD,WAAA;AAAA"}
1
+ {"version":3,"file":"Embedding.d.mts","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"mappings":";;;;;;;;;;;KAOY,gBAAA;EAAA,SAA8B,IAAA;AAAA;EAAA,SAA4B,KAAA,EAAO,WAAA;AAAA;;;;;;;;;;KAWjE,UAAA;EAAA,SAEG,IAAA;AAAA;EAAA,SACA,KAAA,EAAO,WAAA;AAAA;EAAA,SACP,OAAA,EAAS,aAAA,CAAc,gBAAA;AAAA;;KAY1B,gBAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,YAAA;AAAA;;;;;KAOP,aAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,SAAA;AAAA;;;;;;KAQP,eAAA;EAAA,SACD,IAAA;EAAA,SACA,MAAA,EAAQ,UAAA;AAAA;;;;;;;;AAZnB;;;;;;;;;AAUA;;KAuBY,eAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,QAAA,CAAS,MAAA;AAAA;;;;AAF7B;;;;;;;KAeY,oBAAA;EAAA,SACD,IAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,YAAA;AAAA;AAAA,KAGtB,SAAA,GACR,gBAAA,GACA,aAAA,GACA,eAAA,GACA,eAAA,GACA,oBAAA;AAAA,cAES,SAAA,GAAa,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,gBAAA;AAAA,cACjC,MAAA,GAAU,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,aAAA;AAAA,cAC9B,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,QAAA,GAAY,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,eAAA;AAAA,cAChC,aAAA,GAAiB,CAAA,EAAG,SAAA,KAAY,CAAA,IAAK,oBAAA;;;;AAXlD;;;;;;KAsBY,gBAAA;;;;;;;;;;;AAfZ;KA4BY,YAAA,OAAmB,CAAA,oCAC3B,gBAAA,IACC,CAAA,qBACC,aAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,uBACC,eAAA,IACC,CAAA,4BACC,oBAAA,GACA,SAAA;;;;;;KAOA,KAAA;EAAA,SACD,WAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Embedding.mjs","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"sourcesContent":["import type { ImageSource } from \"../domain/Image.js\"\n\n/**\n * One part of a mixed text+image input. Used inside `EmbedInput.content[]`\n * for providers that accept interleaved modalities in a single embed call\n * (Cohere v4, Voyage multimodal, Jina v4, Google `gemini-embedding-2`).\n */\nexport type EmbedContentPart = { readonly text: string } | { readonly image: ImageSource }\n\n/**\n * What you embed. The `string` shorthand covers the common text-only case;\n * structured variants exist for image-only and mixed-modality inputs.\n *\n * Not every provider accepts every variant: text-only providers (OpenAI,\n * Mixedbread today) handle `string` and `{ text }`; multimodal providers\n * (Google, Jina v4, Voyage multimodal, Cohere v4) handle all four. A\n * provider layer rejects shapes it can't encode as `AiError.InvalidRequest`.\n */\nexport type EmbedInput =\n | string\n | { readonly text: string }\n | { readonly image: ImageSource }\n | { readonly content: ReadonlyArray<EmbedContentPart> }\n\n// ---------------------------------------------------------------------------\n// Embedding representations\n//\n// The `_tag` reflects the wire form the provider returned, *not* what the\n// consumer asked for - request `encoding: \"int8\"` and you get back an\n// `Int8Embedding`. Math primitives are typed against the named interfaces\n// (see `Vector.ts`) so e.g. `sparseCosine` only accepts `SparseEmbedding`.\n// ---------------------------------------------------------------------------\n\n/** Dense float32 vector. The default representation across all providers. */\nexport type Float32Embedding = {\n readonly _tag: \"float32\"\n readonly vector: Float32Array\n}\n\n/**\n * Dense int8-quantized vector. ~4x smaller than float32 with minimal\n * recall loss on most benchmarks.\n */\nexport type Int8Embedding = {\n readonly _tag: \"int8\"\n readonly vector: Int8Array\n}\n\n/**\n * Dense binary-quantized vector. One bit per dimension, packed into bytes.\n * ~32x smaller than float32; meaningful recall loss but useful for hot\n * indexes paired with a float32 reranker pass.\n */\nexport type BinaryEmbedding = {\n readonly _tag: \"binary\"\n readonly vector: Uint8Array\n}\n\n/**\n * Sparse vector. Token-keyed weights for hybrid search (dense + lexical-\n * style sparse). The single hosted producer today is Jina's `elser-v2`\n * model, which returns subword tokens (e.g. `\"bread\"`, `\"##ing\"`) with\n * their relevance weights.\n *\n * The shape is `Record<string, number>` rather than `(indices, values)`\n * because real hosted learned-sparse encoders (ELSER, SPLADE) emit token\n * strings with no shared vocabulary index. Converting to integer indices\n * would either need a vocabulary table the model doesn't expose, or\n * lose the cross-vector matching semantics. If a provider ever exposes\n * index-valued sparse vectors (Pinecone-style, where you bring your own\n * vocab), add an `IndexSparseEmbedding` sibling arm with `_tag:\n * \"sparse-indexed\"`.\n *\n * Score with `Vector.sparseCosine` — dot product over the intersection\n * of keys, normalized by the L2 norms of both maps.\n */\nexport type SparseEmbedding = {\n readonly _tag: \"sparse\"\n readonly weights: Readonly<Record<string, number>>\n}\n\n/**\n * Multivector / late-interaction output: one float32 vector per token.\n * Score documents with `Vector.maxSim` (ColBERT-style: per query vector,\n * max dot product across doc vectors, summed). Typically ~50-500 vectors\n * per document, each shorter than a single-vector embedding (~128 dim\n * vs ~1024).\n *\n * Quantized multivector forms aren't modeled for the same reason as\n * sparse - nothing on hosted APIs ships them yet.\n */\nexport type MultivectorEmbedding = {\n readonly _tag: \"multivector\"\n readonly vectors: ReadonlyArray<Float32Array>\n}\n\nexport type Embedding =\n | Float32Embedding\n | Int8Embedding\n | BinaryEmbedding\n | SparseEmbedding\n | MultivectorEmbedding\n\nexport const isFloat32 = (e: Embedding): e is Float32Embedding => e._tag === \"float32\"\nexport const isInt8 = (e: Embedding): e is Int8Embedding => e._tag === \"int8\"\nexport const isBinary = (e: Embedding): e is BinaryEmbedding => e._tag === \"binary\"\nexport const isSparse = (e: Embedding): e is SparseEmbedding => e._tag === \"sparse\"\nexport const isMultivector = (e: Embedding): e is MultivectorEmbedding => e._tag === \"multivector\"\n\n/**\n * Maps an `encoding` request field to the corresponding response embedding\n * variant. `undefined` (no encoding requested) defaults to `Float32Embedding`,\n * which is what every provider returns when the caller doesn't ask for\n * anything else. Widened `E` falls back to the full `Embedding` union — the\n * caller has to narrow at use site, which honestly reflects what they know\n * at compile time.\n *\n * Used by `EmbedResponse<E>` / `EmbedManyResponse<E>` to give callers a\n * precise embedding type without a runtime narrowing helper.\n */\nexport type EmbeddingFor<E> = [E] extends [undefined | \"float32\"]\n ? Float32Embedding\n : [E] extends [\"int8\"]\n ? Int8Embedding\n : [E] extends [\"binary\"]\n ? BinaryEmbedding\n : [E] extends [\"sparse\"]\n ? SparseEmbedding\n : [E] extends [\"multivector\"]\n ? MultivectorEmbedding\n : Embedding\n\n/**\n * Token usage for one embed / embedMany call. One value per HTTP request,\n * not per input vector. Most providers populate `inputTokens`; the field\n * is optional for those that don't (or for mock layers in tests).\n */\nexport type Usage = {\n readonly inputTokens?: number\n}\n"],"mappings":";;;;;;;;;AAuGA,MAAa,aAAa,MAAwC,EAAE,SAAS;AAC7E,MAAa,UAAU,MAAqC,EAAE,SAAS;AACvE,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,iBAAiB,MAA4C,EAAE,SAAS"}
1
+ {"version":3,"file":"Embedding.mjs","names":[],"sources":["../../src/embedding-model/Embedding.ts"],"sourcesContent":["import type { ImageSource } from \"../domain/Image.js\"\n\n/**\n * One part of a mixed text+image input. Used inside `EmbedInput.content[]`\n * for providers that accept interleaved modalities in a single embed call\n * (Cohere v4, Voyage multimodal, Jina v4, Google `gemini-embedding-2`).\n */\nexport type EmbedContentPart = { readonly text: string } | { readonly image: ImageSource }\n\n/**\n * What you embed. The `string` shorthand covers the common text-only case;\n * structured variants exist for image-only and mixed-modality inputs.\n *\n * Not every provider accepts every variant: text-only providers (OpenAI,\n * Mixedbread today) handle `string` and `{ text }`; multimodal providers\n * (Google, Jina v4, Voyage multimodal, Cohere v4) handle all four. A\n * provider layer rejects shapes it can't encode as `AiError.InvalidRequest`.\n */\nexport type EmbedInput =\n | string\n | { readonly text: string }\n | { readonly image: ImageSource }\n | { readonly content: ReadonlyArray<EmbedContentPart> }\n\n// ---------------------------------------------------------------------------\n// Embedding representations\n//\n// The `_tag` reflects the wire form the provider returned, *not* what the\n// consumer asked for - request `encoding: \"int8\"` and you get back an\n// `Int8Embedding`. Math primitives are typed against the named interfaces\n// (see `Vector.ts`) so e.g. `sparseCosine` only accepts `SparseEmbedding`.\n// ---------------------------------------------------------------------------\n\n/** Dense float32 vector. The default representation across all providers. */\nexport type Float32Embedding = {\n readonly _tag: \"float32\"\n readonly vector: Float32Array\n}\n\n/**\n * Dense int8-quantized vector. ~4x smaller than float32 with minimal\n * recall loss on most benchmarks.\n */\nexport type Int8Embedding = {\n readonly _tag: \"int8\"\n readonly vector: Int8Array\n}\n\n/**\n * Dense binary-quantized vector. One bit per dimension, packed into bytes.\n * ~32x smaller than float32; meaningful recall loss but useful for hot\n * indexes paired with a float32 reranker pass.\n */\nexport type BinaryEmbedding = {\n readonly _tag: \"binary\"\n readonly vector: Uint8Array\n}\n\n/**\n * Sparse vector. Token-keyed weights for hybrid search (dense + lexical-\n * style sparse). The single hosted producer today is Jina's `elser-v2`\n * model, which returns subword tokens (e.g. `\"bread\"`, `\"##ing\"`) with\n * their relevance weights.\n *\n * The shape is `Record<string, number>` rather than `(indices, values)`\n * because real hosted learned-sparse encoders (ELSER, SPLADE) emit token\n * strings with no shared vocabulary index. Converting to integer indices\n * would either need a vocabulary table the model doesn't expose, or\n * lose the cross-vector matching semantics. If a provider ever exposes\n * index-valued sparse vectors (Pinecone-style, where you bring your own\n * vocab), add an `IndexSparseEmbedding` sibling arm with `_tag:\n * \"sparse-indexed\"`.\n *\n * Score with `Vector.sparseCosine` — dot product over the intersection\n * of keys, normalized by the L2 norms of both maps.\n */\nexport type SparseEmbedding = {\n readonly _tag: \"sparse\"\n readonly weights: Readonly<Record<string, number>>\n}\n\n/**\n * Multivector / late-interaction output: one float32 vector per token.\n * Score documents with `Vector.maxSim` (ColBERT-style: per query vector,\n * max dot product across doc vectors, summed). Typically ~50-500 vectors\n * per document, each shorter than a single-vector embedding (~128 dim\n * vs ~1024).\n *\n * Quantized multivector forms aren't modeled for the same reason as\n * sparse - nothing on hosted APIs ships them yet.\n */\nexport type MultivectorEmbedding = {\n readonly _tag: \"multivector\"\n readonly vectors: ReadonlyArray<Float32Array>\n}\n\nexport type Embedding =\n | Float32Embedding\n | Int8Embedding\n | BinaryEmbedding\n | SparseEmbedding\n | MultivectorEmbedding\n\nexport const isFloat32 = (e: Embedding): e is Float32Embedding => e._tag === \"float32\"\nexport const isInt8 = (e: Embedding): e is Int8Embedding => e._tag === \"int8\"\nexport const isBinary = (e: Embedding): e is BinaryEmbedding => e._tag === \"binary\"\nexport const isSparse = (e: Embedding): e is SparseEmbedding => e._tag === \"sparse\"\nexport const isMultivector = (e: Embedding): e is MultivectorEmbedding => e._tag === \"multivector\"\n\n/**\n * Domain of `EmbeddingFor` and the response type parameter on\n * `EmbedResponse` / `EmbedManyResponse`: every encoding a provider can\n * *return*, including Jina's widened `sparse` / `multivector`. Distinct\n * from `EmbedEncoding` (the cross-provider *request* set, which is dense\n * quantization only). Providers whose typed request widens beyond the\n * dense set (Jina) parameterize their responses with their own encoding\n * union, which is a subset of this.\n */\nexport type ResponseEncoding = \"float32\" | \"int8\" | \"binary\" | \"sparse\" | \"multivector\"\n\n/**\n * Maps an `encoding` request field to the corresponding response embedding\n * variant. `undefined` (no encoding requested) defaults to `Float32Embedding`,\n * which is what every provider returns when the caller doesn't ask for\n * anything else. Widened `E` falls back to the full `Embedding` union — the\n * caller has to narrow at use site, which honestly reflects what they know\n * at compile time.\n *\n * Used by `EmbedResponse<E>` / `EmbedManyResponse<E>` to give callers a\n * precise embedding type without a runtime narrowing helper.\n */\nexport type EmbeddingFor<E> = [E] extends [undefined | \"float32\"]\n ? Float32Embedding\n : [E] extends [\"int8\"]\n ? Int8Embedding\n : [E] extends [\"binary\"]\n ? BinaryEmbedding\n : [E] extends [\"sparse\"]\n ? SparseEmbedding\n : [E] extends [\"multivector\"]\n ? MultivectorEmbedding\n : Embedding\n\n/**\n * Token usage for one embed / embedMany call. One value per HTTP request,\n * not per input vector. Most providers populate `inputTokens`; the field\n * is optional for those that don't (or for mock layers in tests).\n */\nexport type Usage = {\n readonly inputTokens?: number\n}\n"],"mappings":";;;;;;;;;AAuGA,MAAa,aAAa,MAAwC,EAAE,SAAS;AAC7E,MAAa,UAAU,MAAqC,EAAE,SAAS;AACvE,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,YAAY,MAAuC,EAAE,SAAS;AAC3E,MAAa,iBAAiB,MAA4C,EAAE,SAAS"}