@effect-uai/core 0.1.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 (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -0
  3. package/dist/AiError-CqmYjXyx.d.mts +110 -0
  4. package/dist/AiError-CqmYjXyx.d.mts.map +1 -0
  5. package/dist/Items-D1C2686t.d.mts +372 -0
  6. package/dist/Items-D1C2686t.d.mts.map +1 -0
  7. package/dist/Loop-CzSJo1h8.d.mts +87 -0
  8. package/dist/Loop-CzSJo1h8.d.mts.map +1 -0
  9. package/dist/Outcome-C2JYknCu.d.mts +40 -0
  10. package/dist/Outcome-C2JYknCu.d.mts.map +1 -0
  11. package/dist/StructuredFormat-B5ueioNr.d.mts +88 -0
  12. package/dist/StructuredFormat-B5ueioNr.d.mts.map +1 -0
  13. package/dist/Tool-5wxOCuOh.d.mts +86 -0
  14. package/dist/Tool-5wxOCuOh.d.mts.map +1 -0
  15. package/dist/ToolEvent-B2N10hr3.d.mts +29 -0
  16. package/dist/ToolEvent-B2N10hr3.d.mts.map +1 -0
  17. package/dist/Turn-rlTfuHaQ.d.mts +211 -0
  18. package/dist/Turn-rlTfuHaQ.d.mts.map +1 -0
  19. package/dist/chunk-CfYAbeIz.mjs +13 -0
  20. package/dist/domain/AiError.d.mts +2 -0
  21. package/dist/domain/AiError.mjs +40 -0
  22. package/dist/domain/AiError.mjs.map +1 -0
  23. package/dist/domain/Items.d.mts +2 -0
  24. package/dist/domain/Items.mjs +238 -0
  25. package/dist/domain/Items.mjs.map +1 -0
  26. package/dist/domain/Turn.d.mts +2 -0
  27. package/dist/domain/Turn.mjs +82 -0
  28. package/dist/domain/Turn.mjs.map +1 -0
  29. package/dist/index.d.mts +14 -0
  30. package/dist/index.mjs +14 -0
  31. package/dist/language-model/LanguageModel.d.mts +60 -0
  32. package/dist/language-model/LanguageModel.d.mts.map +1 -0
  33. package/dist/language-model/LanguageModel.mjs +33 -0
  34. package/dist/language-model/LanguageModel.mjs.map +1 -0
  35. package/dist/loop/Loop.d.mts +2 -0
  36. package/dist/loop/Loop.mjs +172 -0
  37. package/dist/loop/Loop.mjs.map +1 -0
  38. package/dist/match/Match.d.mts +16 -0
  39. package/dist/match/Match.d.mts.map +1 -0
  40. package/dist/match/Match.mjs +15 -0
  41. package/dist/match/Match.mjs.map +1 -0
  42. package/dist/observability/Metrics.d.mts +45 -0
  43. package/dist/observability/Metrics.d.mts.map +1 -0
  44. package/dist/observability/Metrics.mjs +52 -0
  45. package/dist/observability/Metrics.mjs.map +1 -0
  46. package/dist/streaming/JSONL.d.mts +34 -0
  47. package/dist/streaming/JSONL.d.mts.map +1 -0
  48. package/dist/streaming/JSONL.mjs +51 -0
  49. package/dist/streaming/JSONL.mjs.map +1 -0
  50. package/dist/streaming/Lines.d.mts +27 -0
  51. package/dist/streaming/Lines.d.mts.map +1 -0
  52. package/dist/streaming/Lines.mjs +32 -0
  53. package/dist/streaming/Lines.mjs.map +1 -0
  54. package/dist/streaming/SSE.d.mts +31 -0
  55. package/dist/streaming/SSE.d.mts.map +1 -0
  56. package/dist/streaming/SSE.mjs +58 -0
  57. package/dist/streaming/SSE.mjs.map +1 -0
  58. package/dist/structured-format/StructuredFormat.d.mts +2 -0
  59. package/dist/structured-format/StructuredFormat.mjs +68 -0
  60. package/dist/structured-format/StructuredFormat.mjs.map +1 -0
  61. package/dist/testing/MockProvider.d.mts +48 -0
  62. package/dist/testing/MockProvider.d.mts.map +1 -0
  63. package/dist/testing/MockProvider.mjs +95 -0
  64. package/dist/testing/MockProvider.mjs.map +1 -0
  65. package/dist/tool/HistoryCheck.d.mts +24 -0
  66. package/dist/tool/HistoryCheck.d.mts.map +1 -0
  67. package/dist/tool/HistoryCheck.mjs +39 -0
  68. package/dist/tool/HistoryCheck.mjs.map +1 -0
  69. package/dist/tool/Outcome.d.mts +2 -0
  70. package/dist/tool/Outcome.mjs +45 -0
  71. package/dist/tool/Outcome.mjs.map +1 -0
  72. package/dist/tool/Resolvers.d.mts +44 -0
  73. package/dist/tool/Resolvers.d.mts.map +1 -0
  74. package/dist/tool/Resolvers.mjs +67 -0
  75. package/dist/tool/Resolvers.mjs.map +1 -0
  76. package/dist/tool/Tool.d.mts +2 -0
  77. package/dist/tool/Tool.mjs +79 -0
  78. package/dist/tool/Tool.mjs.map +1 -0
  79. package/dist/tool/ToolEvent.d.mts +2 -0
  80. package/dist/tool/ToolEvent.mjs +8 -0
  81. package/dist/tool/ToolEvent.mjs.map +1 -0
  82. package/dist/tool/Toolkit.d.mts +34 -0
  83. package/dist/tool/Toolkit.d.mts.map +1 -0
  84. package/dist/tool/Toolkit.mjs +105 -0
  85. package/dist/tool/Toolkit.mjs.map +1 -0
  86. package/package.json +127 -0
  87. package/src/domain/AiError.ts +93 -0
  88. package/src/domain/Items.ts +260 -0
  89. package/src/domain/Turn.ts +174 -0
  90. package/src/index.ts +13 -0
  91. package/src/language-model/LanguageModel.ts +73 -0
  92. package/src/loop/Loop.test.ts +412 -0
  93. package/src/loop/Loop.ts +295 -0
  94. package/src/match/Match.ts +9 -0
  95. package/src/observability/Metrics.ts +87 -0
  96. package/src/streaming/JSONL.test.ts +85 -0
  97. package/src/streaming/JSONL.ts +96 -0
  98. package/src/streaming/Lines.ts +34 -0
  99. package/src/streaming/SSE.test.ts +72 -0
  100. package/src/streaming/SSE.ts +114 -0
  101. package/src/structured-format/StructuredFormat.ts +160 -0
  102. package/src/testing/MockProvider.ts +161 -0
  103. package/src/tool/HistoryCheck.ts +49 -0
  104. package/src/tool/Outcome.ts +101 -0
  105. package/src/tool/Resolvers.test.ts +426 -0
  106. package/src/tool/Resolvers.ts +166 -0
  107. package/src/tool/Tool.ts +150 -0
  108. package/src/tool/ToolEvent.ts +37 -0
  109. package/src/tool/Toolkit.test.ts +45 -0
  110. package/src/tool/Toolkit.ts +228 -0
@@ -0,0 +1,238 @@
1
+ import { t as __exportAll } from "../chunk-CfYAbeIz.mjs";
2
+ import { Schema } from "effect";
3
+ //#region src/domain/Items.ts
4
+ var Items_exports = /* @__PURE__ */ __exportAll({
5
+ Annotation: () => Annotation,
6
+ ContainerFileCitation: () => ContainerFileCitation,
7
+ ContentBlock: () => ContentBlock,
8
+ FileCitation: () => FileCitation,
9
+ FilePath: () => FilePath,
10
+ FunctionCall: () => FunctionCall,
11
+ FunctionCallOutput: () => FunctionCallOutput,
12
+ ImageBase64Source: () => ImageBase64Source,
13
+ ImageSource: () => ImageSource,
14
+ ImageUrlSource: () => ImageUrlSource,
15
+ InputImage: () => InputImage,
16
+ InputText: () => InputText,
17
+ InputTokensDetails: () => InputTokensDetails,
18
+ Item: () => Item,
19
+ Message: () => Message,
20
+ OutputText: () => OutputText,
21
+ OutputTokensDetails: () => OutputTokensDetails,
22
+ Reasoning: () => Reasoning,
23
+ Refusal: () => Refusal,
24
+ Role: () => Role,
25
+ StopReason: () => StopReason,
26
+ UrlCitation: () => UrlCitation,
27
+ Usage: () => Usage,
28
+ assistantText: () => assistantText,
29
+ functionCallOutput: () => functionCallOutput,
30
+ isContainerFileCitation: () => isContainerFileCitation,
31
+ isFileCitation: () => isFileCitation,
32
+ isFilePath: () => isFilePath,
33
+ isFunctionCall: () => isFunctionCall,
34
+ isFunctionCallOutput: () => isFunctionCallOutput,
35
+ isImageBase64Source: () => isImageBase64Source,
36
+ isImageUrlSource: () => isImageUrlSource,
37
+ isInputImage: () => isInputImage,
38
+ isInputText: () => isInputText,
39
+ isMessage: () => isMessage,
40
+ isOutputText: () => isOutputText,
41
+ isReasoning: () => isReasoning,
42
+ isRefusal: () => isRefusal,
43
+ isUrlCitation: () => isUrlCitation,
44
+ systemText: () => systemText,
45
+ userText: () => userText
46
+ });
47
+ const InputText = Schema.Struct({
48
+ type: Schema.Literal("input_text"),
49
+ text: Schema.String
50
+ });
51
+ /**
52
+ * Where an image lives. `url` covers HTTP(S) URLs (the model fetches
53
+ * them); `base64` covers inline bytes embedded in the request. Provider
54
+ * encoders dispatch on `_tag`. File-id / uploaded-asset references are
55
+ * provider-specific and stay out of this union for now.
56
+ */
57
+ const ImageUrlSource = Schema.Struct({
58
+ _tag: Schema.Literal("url"),
59
+ url: Schema.String
60
+ });
61
+ /**
62
+ * Inline image bytes. `data` is **already base64-encoded** (matches what
63
+ * the wire formats expect; no double-encoding needed downstream).
64
+ * `media_type` is the MIME type, e.g. `"image/png"`.
65
+ */
66
+ const ImageBase64Source = Schema.Struct({
67
+ _tag: Schema.Literal("base64"),
68
+ media_type: Schema.String,
69
+ data: Schema.String
70
+ });
71
+ const ImageSource = Schema.Union([ImageUrlSource, ImageBase64Source]);
72
+ const isImageUrlSource = (s) => s._tag === "url";
73
+ const isImageBase64Source = (s) => s._tag === "base64";
74
+ /**
75
+ * User-provided image content block. Pair with `InputText` inside a
76
+ * `Message.content` array to ask "what's in this image?" style questions.
77
+ */
78
+ const InputImage = Schema.Struct({
79
+ type: Schema.Literal("input_image"),
80
+ source: ImageSource
81
+ });
82
+ const UrlCitation = Schema.Struct({
83
+ type: Schema.Literal("url_citation"),
84
+ url: Schema.String,
85
+ start_index: Schema.Number,
86
+ end_index: Schema.Number,
87
+ title: Schema.String
88
+ });
89
+ const FileCitation = Schema.Struct({
90
+ type: Schema.Literal("file_citation"),
91
+ file_id: Schema.String,
92
+ index: Schema.Number
93
+ });
94
+ const ContainerFileCitation = Schema.Struct({
95
+ type: Schema.Literal("container_file_citation"),
96
+ container_id: Schema.String,
97
+ file_id: Schema.String,
98
+ start_index: Schema.Number,
99
+ end_index: Schema.Number
100
+ });
101
+ const FilePath = Schema.Struct({
102
+ type: Schema.Literal("file_path"),
103
+ file_id: Schema.String,
104
+ index: Schema.Number
105
+ });
106
+ const Annotation = Schema.Union([
107
+ UrlCitation,
108
+ FileCitation,
109
+ ContainerFileCitation,
110
+ FilePath
111
+ ]);
112
+ const isUrlCitation = (a) => a.type === "url_citation";
113
+ const isFileCitation = (a) => a.type === "file_citation";
114
+ const isContainerFileCitation = (a) => a.type === "container_file_citation";
115
+ const isFilePath = (a) => a.type === "file_path";
116
+ const OutputText = Schema.Struct({
117
+ type: Schema.Literal("output_text"),
118
+ text: Schema.String,
119
+ annotations: Schema.optional(Schema.Array(Annotation))
120
+ });
121
+ /**
122
+ * Model-emitted refusal. Distinct from `output_text`: the model declined
123
+ * to answer rather than producing normal output. Pair with
124
+ * `stop_reason: "refusal"` on the surrounding `Turn`. Streamed via the
125
+ * `refusal_delta` `TurnEvent`.
126
+ */
127
+ const Refusal = Schema.Struct({
128
+ type: Schema.Literal("refusal"),
129
+ text: Schema.String
130
+ });
131
+ const ContentBlock = Schema.Union([
132
+ InputText,
133
+ InputImage,
134
+ OutputText,
135
+ Refusal
136
+ ]);
137
+ const Role = Schema.Literals([
138
+ "user",
139
+ "assistant",
140
+ "system"
141
+ ]);
142
+ const ProviderData = Schema.optional(Schema.Unknown);
143
+ const Message = Schema.Struct({
144
+ type: Schema.Literal("message"),
145
+ role: Role,
146
+ content: Schema.Array(ContentBlock),
147
+ providerData: ProviderData
148
+ });
149
+ const FunctionCall = Schema.Struct({
150
+ type: Schema.Literal("function_call"),
151
+ call_id: Schema.String,
152
+ name: Schema.String,
153
+ arguments: Schema.String,
154
+ providerData: ProviderData
155
+ });
156
+ const FunctionCallOutput = Schema.Struct({
157
+ type: Schema.Literal("function_call_output"),
158
+ call_id: Schema.String,
159
+ output: Schema.String,
160
+ providerData: ProviderData
161
+ });
162
+ /**
163
+ * Reasoning item - top-level, mirrors OpenAI Responses API. Common shape
164
+ * across providers covers `summary` (human-readable text) and `signature`
165
+ * (opaque round-trip blob - Anthropic's signed thinking, OpenAI's
166
+ * encrypted_content, etc.). Provider-specific fields go in `providerData`.
167
+ */
168
+ const Reasoning = Schema.Struct({
169
+ type: Schema.Literal("reasoning"),
170
+ id: Schema.optional(Schema.String),
171
+ summary: Schema.optional(Schema.String),
172
+ signature: Schema.optional(Schema.String),
173
+ providerData: ProviderData
174
+ });
175
+ const Item = Schema.Union([
176
+ Message,
177
+ FunctionCall,
178
+ FunctionCallOutput,
179
+ Reasoning
180
+ ]);
181
+ const isInputText = (block) => block.type === "input_text";
182
+ const isInputImage = (block) => block.type === "input_image";
183
+ const isOutputText = (block) => block.type === "output_text";
184
+ const isRefusal = (block) => block.type === "refusal";
185
+ const isMessage = (item) => item.type === "message";
186
+ const isFunctionCall = (item) => item.type === "function_call";
187
+ const isFunctionCallOutput = (item) => item.type === "function_call_output";
188
+ const isReasoning = (item) => item.type === "reasoning";
189
+ const InputTokensDetails = Schema.Struct({ cached_tokens: Schema.optional(Schema.Number) });
190
+ const OutputTokensDetails = Schema.Struct({ reasoning_tokens: Schema.optional(Schema.Number) });
191
+ const Usage = Schema.Struct({
192
+ input_tokens: Schema.optional(Schema.Number),
193
+ output_tokens: Schema.optional(Schema.Number),
194
+ total_tokens: Schema.optional(Schema.Number),
195
+ input_tokens_details: Schema.optional(InputTokensDetails),
196
+ output_tokens_details: Schema.optional(OutputTokensDetails)
197
+ });
198
+ const StopReason = Schema.Literals([
199
+ "stop",
200
+ "tool_calls",
201
+ "max_tokens",
202
+ "refusal",
203
+ "content_filter",
204
+ "max_tool_calls"
205
+ ]);
206
+ const userText = (text) => ({
207
+ type: "message",
208
+ role: "user",
209
+ content: [{
210
+ type: "input_text",
211
+ text
212
+ }]
213
+ });
214
+ const systemText = (text) => ({
215
+ type: "message",
216
+ role: "system",
217
+ content: [{
218
+ type: "input_text",
219
+ text
220
+ }]
221
+ });
222
+ const assistantText = (text) => ({
223
+ type: "message",
224
+ role: "assistant",
225
+ content: [{
226
+ type: "output_text",
227
+ text
228
+ }]
229
+ });
230
+ const functionCallOutput = (call_id, output) => ({
231
+ type: "function_call_output",
232
+ call_id,
233
+ output
234
+ });
235
+ //#endregion
236
+ export { Annotation, ContainerFileCitation, ContentBlock, FileCitation, FilePath, FunctionCall, FunctionCallOutput, ImageBase64Source, ImageSource, ImageUrlSource, InputImage, InputText, InputTokensDetails, Item, Message, OutputText, OutputTokensDetails, Reasoning, Refusal, Role, StopReason, UrlCitation, Usage, assistantText, functionCallOutput, isContainerFileCitation, isFileCitation, isFilePath, isFunctionCall, isFunctionCallOutput, isImageBase64Source, isImageUrlSource, isInputImage, isInputText, isMessage, isOutputText, isReasoning, isRefusal, isUrlCitation, systemText, Items_exports as t, userText };
237
+
238
+ //# sourceMappingURL=Items.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Items.mjs","names":[],"sources":["../../src/domain/Items.ts"],"sourcesContent":["import { Schema } from \"effect\"\n\n// ---------------------------------------------------------------------------\n// Content blocks (inside Message.content)\n// ---------------------------------------------------------------------------\n\nexport const InputText = Schema.Struct({\n type: Schema.Literal(\"input_text\"),\n text: Schema.String,\n})\nexport type InputText = typeof InputText.Type\n\n/**\n * Where an image lives. `url` covers HTTP(S) URLs (the model fetches\n * them); `base64` covers inline bytes embedded in the request. Provider\n * encoders dispatch on `_tag`. File-id / uploaded-asset references are\n * provider-specific and stay out of this union for now.\n */\nexport const ImageUrlSource = Schema.Struct({\n _tag: Schema.Literal(\"url\"),\n url: Schema.String,\n})\nexport type ImageUrlSource = typeof ImageUrlSource.Type\n\n/**\n * Inline image bytes. `data` is **already base64-encoded** (matches what\n * the wire formats expect; no double-encoding needed downstream).\n * `media_type` is the MIME type, e.g. `\"image/png\"`.\n */\nexport const ImageBase64Source = Schema.Struct({\n _tag: Schema.Literal(\"base64\"),\n media_type: Schema.String,\n data: Schema.String,\n})\nexport type ImageBase64Source = typeof ImageBase64Source.Type\n\nexport const ImageSource = Schema.Union([ImageUrlSource, ImageBase64Source])\nexport type ImageSource = typeof ImageSource.Type\n\nexport const isImageUrlSource = (s: ImageSource): s is ImageUrlSource => s._tag === \"url\"\nexport const isImageBase64Source = (s: ImageSource): s is ImageBase64Source => s._tag === \"base64\"\n\n/**\n * User-provided image content block. Pair with `InputText` inside a\n * `Message.content` array to ask \"what's in this image?\" style questions.\n */\nexport const InputImage = Schema.Struct({\n type: Schema.Literal(\"input_image\"),\n source: ImageSource,\n})\nexport type InputImage = typeof InputImage.Type\n\n// ---------------------------------------------------------------------------\n// Annotations - source / citation pointers attached to `output_text` blocks.\n// Mirrors OpenAI Responses API; other providers can omit or map onto these\n// shapes.\n// ---------------------------------------------------------------------------\n\nexport const UrlCitation = Schema.Struct({\n type: Schema.Literal(\"url_citation\"),\n url: Schema.String,\n start_index: Schema.Number,\n end_index: Schema.Number,\n title: Schema.String,\n})\nexport type UrlCitation = typeof UrlCitation.Type\n\nexport const FileCitation = Schema.Struct({\n type: Schema.Literal(\"file_citation\"),\n file_id: Schema.String,\n index: Schema.Number,\n})\nexport type FileCitation = typeof FileCitation.Type\n\nexport const ContainerFileCitation = Schema.Struct({\n type: Schema.Literal(\"container_file_citation\"),\n container_id: Schema.String,\n file_id: Schema.String,\n start_index: Schema.Number,\n end_index: Schema.Number,\n})\nexport type ContainerFileCitation = typeof ContainerFileCitation.Type\n\nexport const FilePath = Schema.Struct({\n type: Schema.Literal(\"file_path\"),\n file_id: Schema.String,\n index: Schema.Number,\n})\nexport type FilePath = typeof FilePath.Type\n\nexport const Annotation = Schema.Union([UrlCitation, FileCitation, ContainerFileCitation, FilePath])\nexport type Annotation = typeof Annotation.Type\n\nexport const isUrlCitation = (a: Annotation): a is UrlCitation => a.type === \"url_citation\"\nexport const isFileCitation = (a: Annotation): a is FileCitation => a.type === \"file_citation\"\nexport const isContainerFileCitation = (a: Annotation): a is ContainerFileCitation =>\n a.type === \"container_file_citation\"\nexport const isFilePath = (a: Annotation): a is FilePath => a.type === \"file_path\"\n\nexport const OutputText = Schema.Struct({\n type: Schema.Literal(\"output_text\"),\n text: Schema.String,\n annotations: Schema.optional(Schema.Array(Annotation)),\n})\nexport type OutputText = typeof OutputText.Type\n\n/**\n * Model-emitted refusal. Distinct from `output_text`: the model declined\n * to answer rather than producing normal output. Pair with\n * `stop_reason: \"refusal\"` on the surrounding `Turn`. Streamed via the\n * `refusal_delta` `TurnEvent`.\n */\nexport const Refusal = Schema.Struct({\n type: Schema.Literal(\"refusal\"),\n text: Schema.String,\n})\nexport type Refusal = typeof Refusal.Type\n\nexport const ContentBlock = Schema.Union([InputText, InputImage, OutputText, Refusal])\nexport type ContentBlock = typeof ContentBlock.Type\n\nexport const Role = Schema.Literals([\"user\", \"assistant\", \"system\"])\nexport type Role = typeof Role.Type\n\n// ---------------------------------------------------------------------------\n// Provider passthrough - every Item type carries this opaque slot.\n// The framework never reads or interprets it; provider modules decode\n// their own data via their own typed readers (see e.g.\n// the `@effect-uai/responses` package).\n// ---------------------------------------------------------------------------\n\nconst ProviderData = Schema.optional(Schema.Unknown)\n\n// ---------------------------------------------------------------------------\n// Items\n// ---------------------------------------------------------------------------\n\nexport const Message = Schema.Struct({\n type: Schema.Literal(\"message\"),\n role: Role,\n content: Schema.Array(ContentBlock),\n providerData: ProviderData,\n})\nexport type Message = typeof Message.Type\n\nexport const FunctionCall = Schema.Struct({\n type: Schema.Literal(\"function_call\"),\n call_id: Schema.String,\n name: Schema.String,\n // JSON-encoded arguments string, mirroring OpenAI Responses API\n arguments: Schema.String,\n providerData: ProviderData,\n})\nexport type FunctionCall = typeof FunctionCall.Type\n\nexport const FunctionCallOutput = Schema.Struct({\n type: Schema.Literal(\"function_call_output\"),\n call_id: Schema.String,\n output: Schema.String,\n providerData: ProviderData,\n})\nexport type FunctionCallOutput = typeof FunctionCallOutput.Type\n\n/**\n * Reasoning item - top-level, mirrors OpenAI Responses API. Common shape\n * across providers covers `summary` (human-readable text) and `signature`\n * (opaque round-trip blob - Anthropic's signed thinking, OpenAI's\n * encrypted_content, etc.). Provider-specific fields go in `providerData`.\n */\nexport const Reasoning = Schema.Struct({\n type: Schema.Literal(\"reasoning\"),\n id: Schema.optional(Schema.String),\n summary: Schema.optional(Schema.String),\n signature: Schema.optional(Schema.String),\n providerData: ProviderData,\n})\nexport type Reasoning = typeof Reasoning.Type\n\nexport const Item = Schema.Union([Message, FunctionCall, FunctionCallOutput, Reasoning])\nexport type Item = typeof Item.Type\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\nexport const isInputText = (block: ContentBlock): block is InputText => block.type === \"input_text\"\nexport const isInputImage = (block: ContentBlock): block is InputImage =>\n block.type === \"input_image\"\nexport const isOutputText = (block: ContentBlock): block is OutputText =>\n block.type === \"output_text\"\nexport const isRefusal = (block: ContentBlock): block is Refusal => block.type === \"refusal\"\n\nexport const isMessage = (item: Item): item is Message => item.type === \"message\"\nexport const isFunctionCall = (item: Item): item is FunctionCall => item.type === \"function_call\"\nexport const isFunctionCallOutput = (item: Item): item is FunctionCallOutput =>\n item.type === \"function_call_output\"\nexport const isReasoning = (item: Item): item is Reasoning => item.type === \"reasoning\"\n\n// ---------------------------------------------------------------------------\n// Usage and stop reason\n// ---------------------------------------------------------------------------\n\nexport const InputTokensDetails = Schema.Struct({\n cached_tokens: Schema.optional(Schema.Number),\n})\nexport type InputTokensDetails = typeof InputTokensDetails.Type\n\nexport const OutputTokensDetails = Schema.Struct({\n reasoning_tokens: Schema.optional(Schema.Number),\n})\nexport type OutputTokensDetails = typeof OutputTokensDetails.Type\n\nexport const Usage = Schema.Struct({\n input_tokens: Schema.optional(Schema.Number),\n output_tokens: Schema.optional(Schema.Number),\n total_tokens: Schema.optional(Schema.Number),\n input_tokens_details: Schema.optional(InputTokensDetails),\n output_tokens_details: Schema.optional(OutputTokensDetails),\n})\nexport type Usage = typeof Usage.Type\n\nexport const StopReason = Schema.Literals([\n \"stop\",\n \"tool_calls\",\n \"max_tokens\",\n \"refusal\",\n /** Provider-side safety classifier flagged the output. */\n \"content_filter\",\n /** Server-enforced cap on tool calls per turn was hit. */\n \"max_tool_calls\",\n])\nexport type StopReason = typeof StopReason.Type\n\n// ---------------------------------------------------------------------------\n// Helper constructors\n// ---------------------------------------------------------------------------\n\nexport const userText = (text: string): Message => ({\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text }],\n})\n\nexport const systemText = (text: string): Message => ({\n type: \"message\",\n role: \"system\",\n content: [{ type: \"input_text\", text }],\n})\n\nexport const assistantText = (text: string): Message => ({\n type: \"message\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text }],\n})\n\nexport const functionCallOutput = (call_id: string, output: string): FunctionCallOutput => ({\n type: \"function_call_output\",\n call_id,\n output,\n})\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { a as TurnEvent, c as cursor, d as reasonings, f as textDeltas, i as Turn, l as functionCalls, n as InteractionEvent, p as toStructured, r as RefusalRejected, s as assistantMessages, t as Cursor, u as isTurnComplete } from "../Turn-rlTfuHaQ.mjs";
2
+ export { Cursor, InteractionEvent, RefusalRejected, Turn, TurnEvent, assistantMessages, cursor, functionCalls, isTurnComplete, reasonings, textDeltas, toStructured };
@@ -0,0 +1,82 @@
1
+ import { t as __exportAll } from "../chunk-CfYAbeIz.mjs";
2
+ import { Item, StopReason, Usage, isOutputText, isRefusal } from "./Items.mjs";
3
+ import { parseJson } from "../structured-format/StructuredFormat.mjs";
4
+ import { Data, Effect, Result, Schema, Stream, pipe } from "effect";
5
+ //#region src/domain/Turn.ts
6
+ var Turn_exports = /* @__PURE__ */ __exportAll({
7
+ RefusalRejected: () => RefusalRejected,
8
+ Turn: () => Turn,
9
+ assistantMessages: () => assistantMessages,
10
+ cursor: () => cursor,
11
+ functionCalls: () => functionCalls,
12
+ isTurnComplete: () => isTurnComplete,
13
+ reasonings: () => reasonings,
14
+ textDeltas: () => textDeltas,
15
+ toStructured: () => toStructured
16
+ });
17
+ /**
18
+ * The result of a single LLM generation. A turn produces zero or more items
19
+ * (typically one assistant message and zero or more function_call items)
20
+ * and reports usage + a stop reason.
21
+ */
22
+ const Turn = Schema.Struct({
23
+ items: Schema.Array(Item),
24
+ usage: Usage,
25
+ stop_reason: StopReason
26
+ });
27
+ const isTurnComplete = (d) => d.type === "turn_complete";
28
+ const functionCalls = (turn) => turn.items.filter((i) => i.type === "function_call");
29
+ const reasonings = (turn) => turn.items.filter((i) => i.type === "reasoning");
30
+ const assistantMessages = (turn) => turn.items.filter((i) => i.type === "message" && i.role === "assistant");
31
+ /**
32
+ * Build a `Cursor<S>` from a state record and the just-completed turn.
33
+ * Extends `state.history` with `turn.items` and stamps the turn.
34
+ */
35
+ const cursor = (state, turn) => ({
36
+ ...state,
37
+ history: [...state.history, ...turn.items],
38
+ turn
39
+ });
40
+ /**
41
+ * Project a `TurnEvent` stream onto its `text_delta` payloads. Other
42
+ * variants are dropped. Composes with `Lines.lines` +
43
+ * `decodeJsonLines` for prompted-JSONL streaming.
44
+ */
45
+ const textDeltas = (self) => self.pipe(Stream.filterMap((ev) => ev.type === "text_delta" ? Result.succeed(ev.text) : Result.failVoid));
46
+ /**
47
+ * The assistant message on the just-completed turn was a refusal block,
48
+ * not an `output_text` payload. Returned by `toStructured` to short-circuit
49
+ * decoding before `JSON.parse` / schema validation runs.
50
+ */
51
+ var RefusalRejected = class extends Data.TaggedError("RefusalRejected") {};
52
+ const lastAssistantContent = (turn) => {
53
+ const assistants = assistantMessages(turn);
54
+ const last = assistants[assistants.length - 1];
55
+ if (last === void 0) return {
56
+ text: "",
57
+ refused: false
58
+ };
59
+ if (last.content.some(isRefusal)) return {
60
+ text: "",
61
+ refused: true
62
+ };
63
+ return {
64
+ text: last.content.filter(isOutputText).map((b) => b.text).join(""),
65
+ refused: false
66
+ };
67
+ };
68
+ /**
69
+ * Validate a completed `Turn` against a `StructuredFormat`. Concatenates
70
+ * `output_text` blocks on the last assistant message, then runs
71
+ * `JSON.parse` + the format's schema validation.
72
+ *
73
+ * Three failure modes:
74
+ * - `RefusalRejected` — the assistant emitted a refusal block.
75
+ * - `JsonParseError` — the assembled text wasn't valid JSON.
76
+ * - `StructuredDecodeError` — the JSON didn't match the schema.
77
+ */
78
+ const toStructured = (turn, format) => pipe(lastAssistantContent(turn), ({ text, refused }) => refused ? Effect.fail(new RefusalRejected({ turn })) : parseJson(format)(text));
79
+ //#endregion
80
+ export { RefusalRejected, Turn, assistantMessages, cursor, functionCalls, isTurnComplete, reasonings, Turn_exports as t, textDeltas, toStructured };
81
+
82
+ //# sourceMappingURL=Turn.mjs.map
@@ -0,0 +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 `turn_complete` carries the assembled `Turn`. Lifecycle members\n * aren't deltas, hence the union name.\n */\nexport type TurnEvent =\n | { readonly type: \"text_delta\"; readonly text: string }\n | {\n readonly type: \"reasoning_delta\"\n readonly text: string\n /**\n * `trace` is the model's raw chain-of-thought; `summary` is a\n * model-written summary intended for display. OpenAI Responses emits\n * both as separate wire events; Anthropic and Gemini only emit\n * `trace`. Consumers who just want any reasoning text match once;\n * those who want only summaries filter `kind === \"summary\"`.\n */\n readonly kind: \"trace\" | \"summary\"\n }\n /**\n * The model declined to answer. `text` is the (streamed) explanation.\n * Distinct from the failure channel: a refusal is normal model output and\n * the stream still completes with `turn_complete`. OpenAI Responses emits\n * this; Anthropic surfaces refusals via `stop_reason`, and Gemini collapses\n * them into `finishReason: SAFETY` - both go without a `refusal_delta`.\n */\n | { readonly type: \"refusal_delta\"; readonly text: string }\n | { readonly type: \"tool_call_start\"; readonly call_id: string; readonly name: string }\n | { readonly type: \"tool_call_args_delta\"; readonly call_id: string; readonly delta: string }\n /**\n * Mid-stream cumulative usage. Carries the full `Usage` (including cache\n * token fields when the provider surfaces them) so consumers can drive\n * live budget / cost tracking without waiting for `turn_complete`.\n * Anthropic emits this on `message_start` and `message_delta`; other\n * providers may not emit any `usage_update` and only deliver usage via\n * `turn_complete.turn.usage`.\n */\n | { readonly type: \"usage_update\"; readonly usage: Usage }\n | { readonly type: \"turn_complete\"; readonly turn: Turn }\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 `turn_complete`\n * carrying the assembled `Turn`), plus the output of any tool the loop ran.\n * Both variants carry a `type` discriminator.\n */\nexport type InteractionEvent = TurnEvent | FunctionCallOutput\n\nexport const isTurnComplete = (d: TurnEvent): d is Extract<TurnEvent, { type: \"turn_complete\" }> =>\n d.type === \"turn_complete\"\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 * State stamped with the just-completed `Turn`. Recipes use this as the\n * intermediate value between \"turn lands\" and \"compute next state\": extend\n * `state.history` with the turn's items, and keep the assembled turn\n * around for stop-reason / usage / function-call inspection.\n *\n * Generic over the recipe's state shape - any record carrying a\n * `history: ReadonlyArray<Item>` field works.\n */\nexport type Cursor<S> = S & { readonly turn: Turn }\n\n/**\n * Build a `Cursor<S>` from a state record and the just-completed turn.\n * Extends `state.history` with `turn.items` and stamps the turn.\n */\nexport const cursor = <S extends { readonly history: ReadonlyArray<Item> }>(\n state: S,\n turn: Turn,\n): Cursor<S> => ({\n ...state,\n history: [...state.history, ...turn.items],\n turn,\n})\n\n// ---------------------------------------------------------------------------\n// Stream operators\n// ---------------------------------------------------------------------------\n\n/**\n * Project a `TurnEvent` stream onto its `text_delta` 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) =>\n ev.type === \"text_delta\" ? Result.succeed(ev.text) : Result.failVoid,\n ),\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;AAoDF,MAAa,kBAAkB,MAC7B,EAAE,SAAS;AAEb,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;;;;;AAiBxF,MAAa,UACX,OACA,UACe;CACf,GAAG;CACH,SAAS,CAAC,GAAG,MAAM,SAAS,GAAG,KAAK,MAAM;CAC1C;CACD;;;;;;AAWD,MAAa,cACX,SAEA,KAAK,KACH,OAAO,WAAW,OAChB,GAAG,SAAS,eAAe,OAAO,QAAQ,GAAG,KAAK,GAAG,OAAO,SAC7D,CACF;;;;;;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"}
@@ -0,0 +1,14 @@
1
+ import { n as AiError_d_exports } from "./AiError-CqmYjXyx.mjs";
2
+ import { h as Items_d_exports } from "./Items-D1C2686t.mjs";
3
+ import { a as StructuredFormat_d_exports } from "./StructuredFormat-B5ueioNr.mjs";
4
+ import { o as Turn_d_exports } from "./Turn-rlTfuHaQ.mjs";
5
+ import { l as Tool_d_exports } from "./Tool-5wxOCuOh.mjs";
6
+ import { t as LanguageModel_d_exports } from "./language-model/LanguageModel.mjs";
7
+ import { n as Loop_d_exports } from "./Loop-CzSJo1h8.mjs";
8
+ import { t as Match_d_exports } from "./match/Match.mjs";
9
+ import { t as Toolkit_d_exports } from "./tool/Toolkit.mjs";
10
+ import { t as JSONL_d_exports } from "./streaming/JSONL.mjs";
11
+ import { t as Lines_d_exports } from "./streaming/Lines.mjs";
12
+ import { t as SSE_d_exports } from "./streaming/SSE.mjs";
13
+ import { t as Metrics_d_exports } from "./observability/Metrics.mjs";
14
+ export { AiError_d_exports as AiError, Items_d_exports as Items, JSONL_d_exports as JSONL, LanguageModel_d_exports as LanguageModel, Lines_d_exports as Lines, Loop_d_exports as Loop, Match_d_exports as Match, Metrics_d_exports as Metrics, SSE_d_exports as SSE, StructuredFormat_d_exports as StructuredFormat, Tool_d_exports as Tool, Toolkit_d_exports as Toolkit, Turn_d_exports as Turn };
package/dist/index.mjs ADDED
@@ -0,0 +1,14 @@
1
+ import { t as AiError_exports } from "./domain/AiError.mjs";
2
+ import { t as Items_exports } from "./domain/Items.mjs";
3
+ import { t as StructuredFormat_exports } from "./structured-format/StructuredFormat.mjs";
4
+ import { t as Turn_exports } from "./domain/Turn.mjs";
5
+ import { t as LanguageModel_exports } from "./language-model/LanguageModel.mjs";
6
+ import { t as Loop_exports } from "./loop/Loop.mjs";
7
+ import { t as Match_exports } from "./match/Match.mjs";
8
+ import { t as Tool_exports } from "./tool/Tool.mjs";
9
+ import { t as Toolkit_exports } from "./tool/Toolkit.mjs";
10
+ import { t as JSONL_exports } from "./streaming/JSONL.mjs";
11
+ import { t as Lines_exports } from "./streaming/Lines.mjs";
12
+ import { t as SSE_exports } from "./streaming/SSE.mjs";
13
+ import { t as Metrics_exports } from "./observability/Metrics.mjs";
14
+ export { AiError_exports as AiError, Items_exports as Items, JSONL_exports as JSONL, LanguageModel_exports as LanguageModel, Lines_exports as Lines, Loop_exports as Loop, Match_exports as Match, Metrics_exports as Metrics, SSE_exports as SSE, StructuredFormat_exports as StructuredFormat, Tool_exports as Tool, Toolkit_exports as Toolkit, Turn_exports as Turn };
@@ -0,0 +1,60 @@
1
+ import { t as AiError } from "../AiError-CqmYjXyx.mjs";
2
+ import { m as Item } from "../Items-D1C2686t.mjs";
3
+ import { i as StructuredFormat } from "../StructuredFormat-B5ueioNr.mjs";
4
+ import { a as TurnEvent, i as Turn } from "../Turn-rlTfuHaQ.mjs";
5
+ import { o as ToolDescriptor } from "../Tool-5wxOCuOh.mjs";
6
+ import { Context, Effect, Stream } from "effect";
7
+
8
+ //#region src/language-model/LanguageModel.d.ts
9
+ declare namespace LanguageModel_d_exports {
10
+ export { CommonRequest, LanguageModel, LanguageModelService, streamTurn, turn };
11
+ }
12
+ /**
13
+ * Cross-provider request shape. Every call carries its own `history` and
14
+ * `model` - models are not bound at layer construction. Anything specific
15
+ * to a single provider (reasoning effort, prompt caching, store flags,
16
+ * ...) lives in that provider's own request interface, which extends this.
17
+ */
18
+ interface CommonRequest {
19
+ readonly history: ReadonlyArray<Item>;
20
+ /**
21
+ * Model identifier. Each provider narrows this to its typed literal union,
22
+ * so code that yields a typed provider tag gets autocompletion.
23
+ */
24
+ readonly model: string;
25
+ readonly tools?: ReadonlyArray<ToolDescriptor>;
26
+ readonly toolChoice?: "auto" | "required" | "none" | {
27
+ readonly type: "function";
28
+ readonly name: string;
29
+ };
30
+ readonly temperature?: number;
31
+ readonly topP?: number;
32
+ readonly maxOutputTokens?: number;
33
+ /**
34
+ * Schema-bound JSON output. The provider constrains the wire to match the
35
+ * schema; pair with `Turn.toStructured` for runtime validation. Supported
36
+ * across all current providers (OpenAI Responses json_schema, Anthropic
37
+ * `output_config`, Gemini `responseJsonSchema`).
38
+ */
39
+ readonly structured?: StructuredFormat<unknown>;
40
+ }
41
+ interface LanguageModelService {
42
+ readonly streamTurn: (request: CommonRequest) => Stream.Stream<TurnEvent, AiError>;
43
+ }
44
+ declare const LanguageModel_base: Context.ServiceClass<LanguageModel, "@betalyra/effect-uai/LanguageModel", LanguageModelService>;
45
+ declare class LanguageModel extends LanguageModel_base {}
46
+ /**
47
+ * Stream the deltas of a single turn.
48
+ */
49
+ declare const streamTurn: (request: CommonRequest) => Stream.Stream<TurnEvent, AiError, LanguageModel>;
50
+ /**
51
+ * Run a single turn to completion and return the assembled `Turn`.
52
+ *
53
+ * Implementation: drain the delta stream and pluck the terminal
54
+ * `turn_complete` event. The provider is contractually required to emit
55
+ * exactly one such event as the last delta.
56
+ */
57
+ declare const turn: (request: CommonRequest) => Effect.Effect<Turn, AiError, LanguageModel>;
58
+ //#endregion
59
+ export { CommonRequest, LanguageModel, LanguageModelService, streamTurn, LanguageModel_d_exports as t, turn };
60
+ //# sourceMappingURL=LanguageModel.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LanguageModel.d.mts","names":[],"sources":["../../src/language-model/LanguageModel.ts"],"mappings":";;;;;;;;;;;;;;;;;UAaiB,aAAA;EAAA,SACN,OAAA,EAAS,aAAA,CAAc,IAAA;;;AADlC;;WAMW,KAAA;EAAA,SACA,KAAA,GAAQ,aAAA,CAAc,cAAA;EAAA,SACtB,UAAA;IAAA,SAIM,IAAA;IAAA,SAA2B,IAAA;EAAA;EAAA,SACjC,WAAA;EAAA,SACA,IAAA;EAAA,SACA,eAAA;EAdS;;;;;;EAAA,SAqBT,UAAA,GAAa,gBAAA;AAAA;AAAA,UAGP,oBAAA;EAAA,SACN,UAAA,GAAa,OAAA,EAAS,aAAA,KAAkB,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA;AAAA;AAAA,cAC3E,kBAAA;cAEY,aAAA,SAAsB,kBAAA;;;;cAOtB,UAAA,GACX,OAAA,EAAS,aAAA,KACR,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA,EAAiB,aAAA;;;;;;;;cAUhC,IAAA,GAAQ,OAAA,EAAS,aAAA,KAAgB,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,OAAA,EAAiB,aAAA"}
@@ -0,0 +1,33 @@
1
+ import { t as __exportAll } from "../chunk-CfYAbeIz.mjs";
2
+ import { Unavailable } from "../domain/AiError.mjs";
3
+ import { isTurnComplete } from "../domain/Turn.mjs";
4
+ import { Context, Effect, Stream } from "effect";
5
+ //#region src/language-model/LanguageModel.ts
6
+ var LanguageModel_exports = /* @__PURE__ */ __exportAll({
7
+ LanguageModel: () => LanguageModel,
8
+ streamTurn: () => streamTurn,
9
+ turn: () => turn
10
+ });
11
+ var LanguageModel = class extends Context.Service()("@betalyra/effect-uai/LanguageModel") {};
12
+ /**
13
+ * Stream the deltas of a single turn.
14
+ */
15
+ const streamTurn = (request) => Stream.unwrap(Effect.map(LanguageModel.asEffect(), (m) => m.streamTurn(request)));
16
+ /**
17
+ * Run a single turn to completion and return the assembled `Turn`.
18
+ *
19
+ * Implementation: drain the delta stream and pluck the terminal
20
+ * `turn_complete` event. The provider is contractually required to emit
21
+ * exactly one such event as the last delta.
22
+ */
23
+ const turn = (request) => Effect.flatMap(Stream.runCollect(streamTurn(request)), (deltas) => {
24
+ const last = deltas[deltas.length - 1];
25
+ return last !== void 0 && isTurnComplete(last) ? Effect.succeed(last.turn) : Effect.fail(new Unavailable({
26
+ provider: "unknown",
27
+ raw: "Provider stream ended without a turn_complete event"
28
+ }));
29
+ });
30
+ //#endregion
31
+ export { LanguageModel, streamTurn, LanguageModel_exports as t, turn };
32
+
33
+ //# sourceMappingURL=LanguageModel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LanguageModel.mjs","names":["AiError.Unavailable"],"sources":["../../src/language-model/LanguageModel.ts"],"sourcesContent":["import { Context, Effect, Stream } from \"effect\"\nimport * as AiError from \"../domain/AiError.js\"\nimport type { Item } from \"../domain/Items.js\"\nimport type * as StructuredFormat from \"../structured-format/StructuredFormat.js\"\nimport type { ToolDescriptor } from \"../tool/Tool.js\"\nimport { isTurnComplete, type Turn, type TurnEvent } from \"../domain/Turn.js\"\n\n/**\n * Cross-provider request shape. Every call carries its own `history` and\n * `model` - models are not bound at layer construction. Anything specific\n * to a single provider (reasoning effort, prompt caching, store flags,\n * ...) lives in that provider's own request interface, which extends this.\n */\nexport interface CommonRequest {\n readonly history: ReadonlyArray<Item>\n /**\n * Model identifier. Each provider narrows this to its typed literal union,\n * so code that yields a typed provider tag gets autocompletion.\n */\n readonly model: string\n readonly tools?: ReadonlyArray<ToolDescriptor>\n readonly toolChoice?:\n | \"auto\"\n | \"required\"\n | \"none\"\n | { readonly type: \"function\"; readonly name: string }\n readonly temperature?: number\n readonly topP?: number\n readonly maxOutputTokens?: number\n /**\n * Schema-bound JSON output. The provider constrains the wire to match the\n * schema; pair with `Turn.toStructured` for runtime validation. Supported\n * across all current providers (OpenAI Responses json_schema, Anthropic\n * `output_config`, Gemini `responseJsonSchema`).\n */\n readonly structured?: StructuredFormat.StructuredFormat<unknown>\n}\n\nexport interface LanguageModelService {\n readonly streamTurn: (request: CommonRequest) => Stream.Stream<TurnEvent, AiError.AiError>\n}\n\nexport class LanguageModel extends Context.Service<LanguageModel, LanguageModelService>()(\n \"@betalyra/effect-uai/LanguageModel\",\n) {}\n\n/**\n * Stream the deltas of a single turn.\n */\nexport const streamTurn = (\n request: CommonRequest,\n): Stream.Stream<TurnEvent, AiError.AiError, LanguageModel> =>\n Stream.unwrap(Effect.map(LanguageModel.asEffect(), (m) => m.streamTurn(request)))\n\n/**\n * Run a single turn to completion and return the assembled `Turn`.\n *\n * Implementation: drain the delta stream and pluck the terminal\n * `turn_complete` event. The provider is contractually required to emit\n * exactly one such event as the last delta.\n */\nexport const turn = (request: CommonRequest): Effect.Effect<Turn, AiError.AiError, LanguageModel> =>\n Effect.flatMap(Stream.runCollect(streamTurn(request)), (deltas) => {\n const last = deltas[deltas.length - 1]\n return last !== undefined && isTurnComplete(last)\n ? Effect.succeed(last.turn)\n : Effect.fail(\n new AiError.Unavailable({\n provider: \"unknown\",\n raw: \"Provider stream ended without a turn_complete event\",\n }),\n )\n })\n"],"mappings":";;;;;;;;;;AA0CA,IAAa,gBAAb,cAAmC,QAAQ,SAA8C,CACvF,qCACD,CAAC;;;;AAKF,MAAa,cACX,YAEA,OAAO,OAAO,OAAO,IAAI,cAAc,UAAU,GAAG,MAAM,EAAE,WAAW,QAAQ,CAAC,CAAC;;;;;;;;AASnF,MAAa,QAAQ,YACnB,OAAO,QAAQ,OAAO,WAAW,WAAW,QAAQ,CAAC,GAAG,WAAW;CACjE,MAAM,OAAO,OAAO,OAAO,SAAS;AACpC,QAAO,SAAS,KAAA,KAAa,eAAe,KAAK,GAC7C,OAAO,QAAQ,KAAK,KAAK,GACzB,OAAO,KACL,IAAIA,YAAoB;EACtB,UAAU;EACV,KAAK;EACN,CAAC,CACH;EACL"}
@@ -0,0 +1,2 @@
1
+ import { a as nextAfter, c as stopAfter, d as value, i as next, l as stopEvent, o as nextAfterFold, r as loop, s as stop, t as Event, u as streamUntilComplete } from "../Loop-CzSJo1h8.mjs";
2
+ export { Event, loop, next, nextAfter, nextAfterFold, stop, stopAfter, stopEvent, streamUntilComplete, value };