@effect/ai 0.14.0 → 0.15.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 (134) hide show
  1. package/AiEmbeddingModel/package.json +6 -0
  2. package/AiLanguageModel/package.json +6 -0
  3. package/AiTool/package.json +6 -0
  4. package/dist/cjs/AiChat.js +65 -86
  5. package/dist/cjs/AiChat.js.map +1 -1
  6. package/dist/cjs/{Embeddings.js → AiEmbeddingModel.js} +12 -12
  7. package/dist/cjs/AiEmbeddingModel.js.map +1 -0
  8. package/dist/cjs/AiError.js +8 -1
  9. package/dist/cjs/AiError.js.map +1 -1
  10. package/dist/cjs/AiInput.js +335 -248
  11. package/dist/cjs/AiInput.js.map +1 -1
  12. package/dist/cjs/AiLanguageModel.js +311 -0
  13. package/dist/cjs/AiLanguageModel.js.map +1 -0
  14. package/dist/cjs/AiModel.js +11 -5
  15. package/dist/cjs/AiModel.js.map +1 -1
  16. package/dist/cjs/AiPlan.js +10 -3
  17. package/dist/cjs/AiPlan.js.map +1 -1
  18. package/dist/cjs/AiResponse.js +481 -165
  19. package/dist/cjs/AiResponse.js.map +1 -1
  20. package/dist/cjs/AiTelemetry.js +10 -3
  21. package/dist/cjs/AiTelemetry.js.map +1 -1
  22. package/dist/cjs/AiTool.js +93 -0
  23. package/dist/cjs/AiTool.js.map +1 -0
  24. package/dist/cjs/AiToolkit.js +121 -98
  25. package/dist/cjs/AiToolkit.js.map +1 -1
  26. package/dist/cjs/Tokenizer.js +14 -16
  27. package/dist/cjs/Tokenizer.js.map +1 -1
  28. package/dist/cjs/index.js +7 -9
  29. package/dist/cjs/internal/aiPlan.js +6 -9
  30. package/dist/cjs/internal/aiPlan.js.map +1 -1
  31. package/dist/cjs/internal/common.js +22 -0
  32. package/dist/cjs/internal/common.js.map +1 -0
  33. package/dist/dts/AiChat.d.ts +58 -44
  34. package/dist/dts/AiChat.d.ts.map +1 -1
  35. package/dist/dts/{Embeddings.d.ts → AiEmbeddingModel.d.ts} +13 -14
  36. package/dist/dts/AiEmbeddingModel.d.ts.map +1 -0
  37. package/dist/dts/AiError.d.ts +4 -3
  38. package/dist/dts/AiError.d.ts.map +1 -1
  39. package/dist/dts/AiInput.d.ts +441 -146
  40. package/dist/dts/AiInput.d.ts.map +1 -1
  41. package/dist/dts/AiLanguageModel.d.ts +263 -0
  42. package/dist/dts/AiLanguageModel.d.ts.map +1 -0
  43. package/dist/dts/AiModel.d.ts +21 -20
  44. package/dist/dts/AiModel.d.ts.map +1 -1
  45. package/dist/dts/AiPlan.d.ts +90 -26
  46. package/dist/dts/AiPlan.d.ts.map +1 -1
  47. package/dist/dts/AiResponse.d.ts +711 -100
  48. package/dist/dts/AiResponse.d.ts.map +1 -1
  49. package/dist/dts/AiTelemetry.d.ts +175 -157
  50. package/dist/dts/AiTelemetry.d.ts.map +1 -1
  51. package/dist/dts/AiTool.d.ts +288 -0
  52. package/dist/dts/AiTool.d.ts.map +1 -0
  53. package/dist/dts/AiToolkit.d.ts +50 -111
  54. package/dist/dts/AiToolkit.d.ts.map +1 -1
  55. package/dist/dts/Tokenizer.d.ts +8 -6
  56. package/dist/dts/Tokenizer.d.ts.map +1 -1
  57. package/dist/dts/index.d.ts +8 -12
  58. package/dist/dts/index.d.ts.map +1 -1
  59. package/dist/dts/internal/common.d.ts +2 -0
  60. package/dist/dts/internal/common.d.ts.map +1 -0
  61. package/dist/esm/AiChat.js +62 -83
  62. package/dist/esm/AiChat.js.map +1 -1
  63. package/dist/esm/{Embeddings.js → AiEmbeddingModel.js} +10 -10
  64. package/dist/esm/AiEmbeddingModel.js.map +1 -0
  65. package/dist/esm/AiError.js +8 -1
  66. package/dist/esm/AiError.js.map +1 -1
  67. package/dist/esm/AiInput.js +316 -238
  68. package/dist/esm/AiInput.js.map +1 -1
  69. package/dist/esm/AiLanguageModel.js +300 -0
  70. package/dist/esm/AiLanguageModel.js.map +1 -0
  71. package/dist/esm/AiModel.js +11 -5
  72. package/dist/esm/AiModel.js.map +1 -1
  73. package/dist/esm/AiPlan.js +8 -2
  74. package/dist/esm/AiPlan.js.map +1 -1
  75. package/dist/esm/AiResponse.js +467 -162
  76. package/dist/esm/AiResponse.js.map +1 -1
  77. package/dist/esm/AiTelemetry.js +8 -2
  78. package/dist/esm/AiTelemetry.js.map +1 -1
  79. package/dist/esm/AiTool.js +82 -0
  80. package/dist/esm/AiTool.js.map +1 -0
  81. package/dist/esm/AiToolkit.js +118 -96
  82. package/dist/esm/AiToolkit.js.map +1 -1
  83. package/dist/esm/Tokenizer.js +14 -16
  84. package/dist/esm/Tokenizer.js.map +1 -1
  85. package/dist/esm/index.js +8 -12
  86. package/dist/esm/index.js.map +1 -1
  87. package/dist/esm/internal/aiPlan.js +4 -7
  88. package/dist/esm/internal/aiPlan.js.map +1 -1
  89. package/dist/esm/internal/common.js +14 -0
  90. package/dist/esm/internal/common.js.map +1 -0
  91. package/package.json +28 -36
  92. package/src/AiChat.ts +182 -207
  93. package/src/{Embeddings.ts → AiEmbeddingModel.ts} +19 -18
  94. package/src/AiError.ts +8 -1
  95. package/src/AiInput.ts +434 -313
  96. package/src/AiLanguageModel.ts +569 -0
  97. package/src/AiModel.ts +47 -29
  98. package/src/AiPlan.ts +102 -30
  99. package/src/AiResponse.ts +743 -187
  100. package/src/AiTelemetry.ts +214 -197
  101. package/src/AiTool.ts +496 -0
  102. package/src/AiToolkit.ts +200 -240
  103. package/src/Tokenizer.ts +18 -22
  104. package/src/index.ts +9 -14
  105. package/src/internal/aiPlan.ts +12 -14
  106. package/src/internal/common.ts +12 -0
  107. package/AiModels/package.json +0 -6
  108. package/AiRole/package.json +0 -6
  109. package/Completions/package.json +0 -6
  110. package/Embeddings/package.json +0 -6
  111. package/dist/cjs/AiModels.js +0 -54
  112. package/dist/cjs/AiModels.js.map +0 -1
  113. package/dist/cjs/AiRole.js +0 -106
  114. package/dist/cjs/AiRole.js.map +0 -1
  115. package/dist/cjs/Completions.js +0 -256
  116. package/dist/cjs/Completions.js.map +0 -1
  117. package/dist/cjs/Embeddings.js.map +0 -1
  118. package/dist/dts/AiModels.d.ts +0 -34
  119. package/dist/dts/AiModels.d.ts.map +0 -1
  120. package/dist/dts/AiRole.d.ts +0 -111
  121. package/dist/dts/AiRole.d.ts.map +0 -1
  122. package/dist/dts/Completions.d.ts +0 -128
  123. package/dist/dts/Completions.d.ts.map +0 -1
  124. package/dist/dts/Embeddings.d.ts.map +0 -1
  125. package/dist/esm/AiModels.js +0 -44
  126. package/dist/esm/AiModels.js.map +0 -1
  127. package/dist/esm/AiRole.js +0 -93
  128. package/dist/esm/AiRole.js.map +0 -1
  129. package/dist/esm/Completions.js +0 -245
  130. package/dist/esm/Completions.js.map +0 -1
  131. package/dist/esm/Embeddings.js.map +0 -1
  132. package/src/AiModels.ts +0 -77
  133. package/src/AiRole.ts +0 -122
  134. package/src/Completions.ts +0 -434
@@ -1,60 +1,340 @@
1
- /**
2
- * @since 1.0.0
3
- */
4
- import * as Chunk from "effect/Chunk";
5
- import * as Data from "effect/Data";
6
1
  import * as Effect from "effect/Effect";
7
- import * as Iterable from "effect/Iterable";
2
+ import { dual } from "effect/Function";
8
3
  import * as Option from "effect/Option";
9
4
  import * as Predicate from "effect/Predicate";
10
5
  import * as Schema from "effect/Schema";
11
6
  import { AiError } from "./AiError.js";
12
- import * as AiRole from "./AiRole.js";
7
+ import * as InternalCommon from "./internal/common.js";
8
+ const constDisableValidation = {
9
+ disableValidation: true
10
+ };
13
11
  /**
14
12
  * @since 1.0.0
15
- * @category type ids
13
+ * @category Type Ids
16
14
  */
17
- export const TypeId = /*#__PURE__*/Symbol("@effect/ai/AiResponse");
15
+ export const TypeId = /*#__PURE__*/Symbol.for("@effect/ai/AiResponse");
18
16
  /**
17
+ * Represents a response received from a large language model.
18
+ *
19
19
  * @since 1.0.0
20
- * @category parts
20
+ * @category Models
21
21
  */
22
- export const PartTypeId = /*#__PURE__*/Symbol("@effect/ai/AiResponse/Part");
23
- const constDisableValidation = {
24
- disableValidation: true
25
- };
22
+ export class AiResponse extends /*#__PURE__*/Schema.Class("@effect/ai/AiResponse")({
23
+ /**
24
+ * The parts of the response.
25
+ */
26
+ parts: /*#__PURE__*/Schema.Array( /*#__PURE__*/Schema.suspend(() => Part))
27
+ }) {
28
+ /**
29
+ * @since 1.0.0
30
+ */
31
+ [TypeId] = TypeId;
32
+ /**
33
+ * Returns the generated text content of the response.
34
+ */
35
+ get text() {
36
+ let text = "";
37
+ let found = false;
38
+ for (const part of this.parts) {
39
+ if (part._tag === "TextPart") {
40
+ text += found ? "\n\n" + part.text : part.text;
41
+ found = true;
42
+ }
43
+ }
44
+ return text;
45
+ }
46
+ /**
47
+ * Returns the finish reason for the response, or `"unknown"` if the finish
48
+ * reason is not known.
49
+ */
50
+ get finishReason() {
51
+ const finishPart = this.parts.find(part => part._tag === "FinishPart");
52
+ return finishPart?.reason ?? "unknown";
53
+ }
54
+ /**
55
+ * Attempts to retrieve provider-specific response metadata.
56
+ */
57
+ getProviderMetadata(tag) {
58
+ const finishPart = this.parts.find(part => part._tag === "FinishPart");
59
+ return Option.fromNullable(finishPart?.providerMetadata[tag.key]);
60
+ }
61
+ }
62
+ /**
63
+ * @since 1.0.0
64
+ * @category Models
65
+ */
66
+ export const FromJson = /*#__PURE__*/Schema.parseJson(AiResponse);
67
+ /**
68
+ * @since 1.0.0
69
+ * @category Type Ids
70
+ */
71
+ export const StructuredResponseTypeId = /*#__PURE__*/Symbol.for("@effect/ai/AiResponse/StructuredResponse");
72
+ /**
73
+ * Represents a response generated by a large language model that includes
74
+ * structured output.
75
+ *
76
+ * @since 1.0.0
77
+ * @category Models
78
+ */
79
+ export class WithStructuredOutput extends AiResponse {
80
+ /**
81
+ * @since 1.0.0
82
+ */
83
+ [StructuredResponseTypeId] = StructuredResponseTypeId;
84
+ /**
85
+ * The identifier of the tool which generated the structured output.
86
+ */
87
+ id;
88
+ /**
89
+ * The name of the tool which generated the structured output.
90
+ */
91
+ name;
92
+ /**
93
+ * The structured output generated by the model.
94
+ */
95
+ value;
96
+ constructor(props, options) {
97
+ super({
98
+ parts: props.parts
99
+ }, options);
100
+ this.id = props.id;
101
+ this.name = props.name;
102
+ this.value = props.value;
103
+ }
104
+ }
105
+ /**
106
+ * @since 1.0.0
107
+ * @category Type Ids
108
+ */
109
+ export const WithToolCallResultsTypeId = /*#__PURE__*/Symbol.for("@effect/ai/AiResponse/WithToolCallResults");
110
+ /**
111
+ * Represents a response generated by a large language model that includes
112
+ * tool call results.
113
+ *
114
+ * @since 1.0.0
115
+ * @category Models
116
+ */
117
+ export class WithToolCallResults extends AiResponse {
118
+ /**
119
+ * @since 1.0.0
120
+ */
121
+ [WithToolCallResultsTypeId] = WithToolCallResultsTypeId;
122
+ /**
123
+ * The tool call results, represented as a mapping between the tool call
124
+ * identifier and the result of the tool call handler.
125
+ */
126
+ results;
127
+ /**
128
+ * The encoded tool call results, suitable for incorporation into subsequent
129
+ * requests to the large language model.
130
+ */
131
+ encodedResults;
132
+ constructor(props, options) {
133
+ super({
134
+ parts: props.parts
135
+ }, options);
136
+ this.results = props.results;
137
+ this.encodedResults = props.encodedResults;
138
+ }
139
+ }
140
+ // =============================================================================
141
+ // Part
142
+ // =============================================================================
143
+ /**
144
+ * @since 1.0.0
145
+ * @category Type Ids
146
+ */
147
+ export const PartTypeId = /*#__PURE__*/Symbol.for("@effect/ai/AiResponse/Part");
26
148
  /**
149
+ * Represents a content source that was used to generate a model response.
150
+ *
27
151
  * @since 1.0.0
28
- * @category parts
152
+ * @category Models
29
153
  */
30
- export class TextPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/TextPart")("Text", {
31
- content: Schema.String
154
+ export class ContentSourceAnnotation extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/Annotation/ContentSourceAnnotation")("ContentSourceAnnotation", {
155
+ /**
156
+ * The identifier for the content source.
157
+ */
158
+ id: Schema.String,
159
+ /**
160
+ * The index of the content source in the list of sources provided in the
161
+ * model request parameters.
162
+ */
163
+ index: Schema.Int,
164
+ /**
165
+ * The provider-specific type of the file annotation.
166
+ *
167
+ * For example, when using Anthropic the type may be `char_location`,
168
+ * `page_location`, or `content_block_location`.
169
+ */
170
+ type: Schema.String,
171
+ /**
172
+ * The content used from the content source in the message generated by the
173
+ * model.
174
+ */
175
+ referencedContent: Schema.String,
176
+ /**
177
+ * The index of the first character of the content referenced by the content
178
+ * source in the message generated by the model.
179
+ */
180
+ startIndex: Schema.Int,
181
+ /**
182
+ * The index of the last character of the content referenced by the content
183
+ * source in the message generated by the model.
184
+ */
185
+ endIndex: Schema.Int
186
+ }) {}
187
+ /**
188
+ * Represents a file that was used to generate a model response.
189
+ *
190
+ * @since 1.0.0
191
+ * @category Models
192
+ */
193
+ export class FileAnnotation extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/Annotation/FileAnnotation")("FileAnnotation", {
194
+ /**
195
+ * The identifier for the file.
196
+ */
197
+ id: Schema.String,
198
+ /**
199
+ * The provider-specific type of the file annotation.
200
+ *
201
+ * For example, when using OpenAi the type may be `file_citation` or
202
+ * `file_path`.
203
+ */
204
+ type: Schema.String,
205
+ /**
206
+ * The index of the file in the list of files provided in the model request
207
+ * parameters.
208
+ */
209
+ index: Schema.Int
210
+ }) {}
211
+ /**
212
+ * Represents a web resource that was used to generate a model response.
213
+ *
214
+ * @since 1.0.0
215
+ * @category Models
216
+ */
217
+ export class UrlAnnotation extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/Annotation/UrlAnnotation")("UrlAnnotation", {
218
+ /**
219
+ * The URL of the web resource.
220
+ */
221
+ url: Schema.String,
222
+ /**
223
+ * The title of the web resource.
224
+ */
225
+ title: Schema.String,
226
+ /**
227
+ * The index of the first character of the content referenced by the web
228
+ * resource in the message generated by the model.
229
+ */
230
+ startIndex: Schema.Int,
231
+ /**
232
+ * The index of the last character of the content referenced by the web
233
+ * resource in the message generated by the model.
234
+ */
235
+ endIndex: Schema.Int
236
+ }) {}
237
+ /**
238
+ * Represents annotations that were used to support the message generated by
239
+ * a model.
240
+ *
241
+ * @since 1.0.0
242
+ * @category Models
243
+ */
244
+ export const Annotation = /*#__PURE__*/Schema.Union(ContentSourceAnnotation, FileAnnotation, UrlAnnotation);
245
+ /**
246
+ * Represents part of the text generated by the model.
247
+ *
248
+ * @since 1.0.0
249
+ * @category Models
250
+ */
251
+ export class TextPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/TextPart")("TextPart", {
252
+ /**
253
+ * The text content generated by the model.
254
+ */
255
+ text: Schema.String,
256
+ /**
257
+ * The annotations used to support the text generated by the model.
258
+ */
259
+ annotations: /*#__PURE__*/Schema.optionalWith( /*#__PURE__*/Schema.Array(Annotation), {
260
+ default: () => []
261
+ })
32
262
  }) {
33
263
  /**
34
264
  * @since 1.0.0
35
265
  */
36
266
  [PartTypeId] = PartTypeId;
267
+ }
268
+ /**
269
+ * Represents part of the reasoning carried out by the model to generate a
270
+ * response.
271
+ *
272
+ * @since 1.0.0
273
+ * @category Models
274
+ */
275
+ export class ReasoningPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/ReasoningPart")("ReasoningPart", {
276
+ /**
277
+ * The reasoning content that the model used to return the output.
278
+ */
279
+ reasoningText: Schema.String,
280
+ /**
281
+ * An optional signature which verifies that the reasoning text was generated
282
+ * by the model.
283
+ */
284
+ signature: /*#__PURE__*/Schema.optional(Schema.String)
285
+ }) {
37
286
  /**
38
287
  * @since 1.0.0
39
288
  */
40
- static fromContent(content) {
41
- return new TextPart({
42
- content
43
- }, constDisableValidation);
44
- }
289
+ [PartTypeId] = PartTypeId;
290
+ }
291
+ /**
292
+ * Represents part of the reasoning carried out by the model to generate a
293
+ * response which needed to be encrypted by the model provider for safety
294
+ * reasons.
295
+ *
296
+ * @since 1.0.0
297
+ * @category Models
298
+ */
299
+ export class RedactedReasoningPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/RedactedReasoningPart")("RedactedReasoningPart", {
300
+ /**
301
+ * The content in the reasoning that was encrypted by the model provider for
302
+ * safety reasons.
303
+ */
304
+ redactedText: Schema.String
305
+ }) {
306
+ /**
307
+ * @since 1.0.0
308
+ */
309
+ [PartTypeId] = PartTypeId;
45
310
  }
46
311
  /**
312
+ * Represents the identifier generated by a model when a tool call is requested.
313
+ *
47
314
  * @since 1.0.0
48
- * @category parts
315
+ * @category Models
49
316
  */
50
- export const ToolCallId = /*#__PURE__*/Schema.String.pipe( /*#__PURE__*/Schema.brand("ToolCallId"));
317
+ export const ToolCallId = InternalCommon.ToolCallId;
51
318
  /**
319
+ * Represents a request by a model to call a specific tool that it has been
320
+ * provided with.
321
+ *
52
322
  * @since 1.0.0
53
- * @category parts
323
+ * @category Models
54
324
  */
55
- export class ToolCallPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/ToolCallPart")("ToolCall", {
325
+ export class ToolCallPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/ToolCallPart")("ToolCallPart", {
326
+ /**
327
+ * The identifier generated by a model when requesting a tool call.
328
+ */
56
329
  id: ToolCallId,
330
+ /**
331
+ * The name of the tool to call.
332
+ */
57
333
  name: Schema.String,
334
+ /**
335
+ * The arguments to call the tool with as a JSON-serializable object that
336
+ * matches the tool call input schema.
337
+ */
58
338
  params: Schema.Unknown
59
339
  }) {
60
340
  /**
@@ -62,6 +342,10 @@ export class ToolCallPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/Ai
62
342
  */
63
343
  [PartTypeId] = PartTypeId;
64
344
  /**
345
+ * Converts a raw tool call into a `ToolCallPart` by parsing tool call
346
+ * parameters as a JSON string. If your tool call parameters are already
347
+ * parsed, use `ToolCallPart.fromUnknown`.
348
+ *
65
349
  * @since 1.0.0
66
350
  */
67
351
  static fromJson({
@@ -72,7 +356,7 @@ export class ToolCallPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/Ai
72
356
  return Effect.try({
73
357
  try() {
74
358
  return new ToolCallPart({
75
- id: ToolCallId.make(id),
359
+ id: ToolCallId.make(id, constDisableValidation),
76
360
  name,
77
361
  params: JSON.parse(params)
78
362
  }, constDisableValidation);
@@ -80,12 +364,16 @@ export class ToolCallPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/Ai
80
364
  catch: cause => new AiError({
81
365
  module: "AiResponse",
82
366
  method: "ToolCall.fromJson",
83
- description: "Failed to parse parameters",
367
+ description: `Failed to parse parameters from JSON:\n${params}`,
84
368
  cause
85
369
  })
86
370
  });
87
371
  }
88
372
  /**
373
+ * Converts a raw tool call into a `ToolCallPart` assuming that the tool call
374
+ * parameters have already been parsed. If your tool call parameters have not
375
+ * already been parsed, use `ToolCallPart.fromJson`.
376
+ *
89
377
  * @since 1.0.0
90
378
  */
91
379
  static fromUnknown({
@@ -94,18 +382,33 @@ export class ToolCallPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/Ai
94
382
  params
95
383
  }) {
96
384
  return new ToolCallPart({
97
- id: ToolCallId.make(id),
385
+ id: ToolCallId.make(id, constDisableValidation),
98
386
  name,
99
387
  params
100
388
  }, constDisableValidation);
101
389
  }
102
390
  }
103
391
  /**
392
+ * Represents the initial response metadata generated by a model when responding
393
+ * to a request.
394
+ *
104
395
  * @since 1.0.0
105
- * @category parts
396
+ * @categor Models
106
397
  */
107
- export class ImageUrlPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/ImageUrlPart")("ImageUrl", {
108
- url: Schema.String
398
+ export class MetadataPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/MetadataPart")("MetadataPart", {
399
+ /**
400
+ * The unique identifier for the response. Each chunk of the response should
401
+ * have the same identifier.
402
+ */
403
+ id: /*#__PURE__*/Schema.optional(Schema.String),
404
+ /**
405
+ * The model that was used to generate the response.
406
+ */
407
+ model: Schema.String,
408
+ /**
409
+ * The Unix timestamp of when the model began generated the response.
410
+ */
411
+ timestamp: /*#__PURE__*/Schema.optional(Schema.DateFromNumber)
109
412
  }) {
110
413
  /**
111
414
  * @since 1.0.0
@@ -113,169 +416,171 @@ export class ImageUrlPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/Ai
113
416
  [PartTypeId] = PartTypeId;
114
417
  }
115
418
  /**
419
+ * Represents the reason why a model finished generation of a response.
420
+ *
421
+ * Possible finish reasons:
422
+ * - `"stop"`: The model generated a stop sequence.
423
+ * - `"length"`: The model exceeded its token budget.
424
+ * - `"content-filter"`: The model generated content which violated a content filter.
425
+ * - `"tool-calls"`: The model triggered a tool call.
426
+ * - `"error"`: The model encountered an error.
427
+ * - `"other"`: The model stopped for a reason not supported by this protocol.
428
+ * - `"unknown"`: The model did not specify a finish reason.
429
+ *
116
430
  * @since 1.0.0
117
- * @category parts
431
+ * @category Models
118
432
  */
119
- export const Part = /*#__PURE__*/Schema.Union(TextPart, ToolCallPart, ImageUrlPart);
433
+ export const FinishReason = /*#__PURE__*/Schema.Literal("stop", "length", "content-filter", "tool-calls", "error", "other", "unknown");
120
434
  /**
435
+ * Represents information about the number of tokens used by the model to
436
+ * generate a response.
437
+ *
121
438
  * @since 1.0.0
122
- * @category models
439
+ * @category Models
123
440
  */
124
- export class AiResponse extends /*#__PURE__*/Schema.Class("@effect/ai/AiResponse")({
125
- role: AiRole.AiRole,
126
- parts: /*#__PURE__*/Schema.Chunk(Part)
127
- }) {
441
+ export class Usage extends /*#__PURE__*/Schema.Class("@effect/ai/AiResponse/Usage")({
128
442
  /**
129
- * @since 1.0.0
443
+ * The number of tokens sent in the request to the model.
130
444
  */
131
- [TypeId] = TypeId;
445
+ inputTokens: Schema.Number,
132
446
  /**
133
- * @since 1.0.0
447
+ * The number of tokens that the model generated for the request.
134
448
  */
135
- static is(u) {
136
- return Predicate.hasProperty(u, TypeId);
137
- }
449
+ outputTokens: Schema.Number,
138
450
  /**
139
- * @since 1.0.0
451
+ * The total of number of input tokens and output tokens generated by the
452
+ * model.
140
453
  */
141
- static empty = /*#__PURE__*/new AiResponse({
142
- role: AiRole.model,
143
- parts: /*#__PURE__*/Chunk.empty()
144
- });
454
+ totalTokens: Schema.Number,
145
455
  /**
146
- * @since 1.0.0
456
+ * The number of reasoning tokens that the model used to generate the output
457
+ * for the request.
147
458
  */
148
- static fromText(options) {
149
- return new AiResponse({
150
- role: options.role,
151
- parts: Chunk.of(TextPart.fromContent(options.content))
152
- }, constDisableValidation);
153
- }
459
+ reasoningTokens: Schema.Number,
154
460
  /**
155
- * @since 1.0.0
461
+ * The number of input tokens read from the prompt cache for the request.
156
462
  */
157
- get text() {
158
- let text = "";
159
- let found = false;
160
- for (const part of this.parts) {
161
- if (part._tag === "Text") {
162
- text += found ? "\n\n" + part.content : part.content;
163
- found = true;
164
- }
165
- }
166
- return text;
167
- }
463
+ cacheReadInputTokens: Schema.Number,
168
464
  /**
169
- * @since 1.0.0
465
+ * The number of input tokens written to the prompt cache for the request.
170
466
  */
171
- get imageUrl() {
172
- for (const part of this.parts) {
173
- if (part._tag === "ImageUrl") {
174
- return Option.some(part.url);
175
- }
176
- }
177
- return Option.none();
178
- }
467
+ cacheWriteInputTokens: Schema.Number
468
+ }) {}
469
+ /**
470
+ * Represents the final part of a response generated by a large language model.
471
+ *
472
+ * Contains useful information such as tokens used as part of the interaction
473
+ * with the model.
474
+ *
475
+ * @since 1.0.0
476
+ * @category Models
477
+ */
478
+ export class FinishPart extends /*#__PURE__*/Schema.TaggedClass("@effect/ai/AiResponse/FinishPart")("FinishPart", {
179
479
  /**
180
- * @since 1.0.0
480
+ * The usage information for the response.
181
481
  */
182
- withToolCallsJson(calls) {
183
- return Effect.forEach(calls, call => ToolCallPart.fromJson(call)).pipe(Effect.map(parts => new AiResponse({
184
- role: this.role,
185
- parts: Chunk.appendAll(this.parts, Chunk.unsafeFromArray(parts))
186
- }, constDisableValidation)));
187
- }
482
+ usage: Usage,
188
483
  /**
189
- * @since 1.0.0
484
+ * The reason the model finished generating a response.
190
485
  */
191
- withToolCallsUnknown(calls) {
192
- return new AiResponse({
193
- role: this.role,
194
- parts: Chunk.fromIterable(calls).pipe(Chunk.map(part => ToolCallPart.fromUnknown(part)))
195
- }, constDisableValidation);
196
- }
486
+ reason: FinishReason,
487
+ /**
488
+ * Provider-specific metadata associated with the response.
489
+ */
490
+ providerMetadata: /*#__PURE__*/Schema.optionalWith( /*#__PURE__*/Schema.Record({
491
+ key: Schema.String,
492
+ value: /*#__PURE__*/Schema.Record({
493
+ key: Schema.String,
494
+ value: Schema.Unknown
495
+ })
496
+ }), {
497
+ default: () => ({})
498
+ })
499
+ }) {
197
500
  /**
198
501
  * @since 1.0.0
199
502
  */
200
- concat(that) {
201
- if (Chunk.isEmpty(that.parts)) {
202
- return this;
203
- }
204
- const lastPart = Chunk.last(this.parts);
205
- if (Option.isNone(lastPart)) {
206
- return that;
207
- }
208
- const newParts = [];
209
- let content = lastPart.value._tag === "Text" ? lastPart.value.content : "";
210
- for (const part of that.parts) {
211
- if (part._tag === "Text") {
212
- content += part.content;
213
- }
214
- }
215
- if (content.length > 0) {
216
- newParts.push(TextPart.fromContent(content));
217
- }
218
- return newParts.length === 0 ? this : new AiResponse({
219
- role: that.role,
220
- parts: Chunk.appendAll(Chunk.dropRight(this.parts, 1), Chunk.unsafeFromArray(newParts))
221
- }, constDisableValidation);
222
- }
503
+ [PartTypeId] = PartTypeId;
223
504
  }
224
505
  /**
506
+ * Represents an single part of a response received from a large language model.
507
+ *
225
508
  * @since 1.0.0
226
- * @category tools
509
+ * @category Models
227
510
  */
228
- export const WithResolvedTypeId = /*#__PURE__*/Symbol("@effect/ai/AiResponse/WithResolved");
511
+ export const Part = /*#__PURE__*/Schema.Union(TextPart, ReasoningPart, RedactedReasoningPart, ToolCallPart, MetadataPart, FinishPart);
229
512
  /**
230
513
  * @since 1.0.0
231
- * @category tools
514
+ * @category Guards
232
515
  */
233
- export class WithResolved extends Data.Class {
234
- /**
235
- * @since 1.0.0
236
- */
237
- [WithResolvedTypeId] = WithResolvedTypeId;
238
- /**
239
- * @since 1.0.0
240
- */
241
- static is(u) {
242
- return Predicate.hasProperty(u, WithResolvedTypeId);
243
- }
244
- /**
245
- * @since 1.0.0
246
- */
247
- static empty = /*#__PURE__*/new WithResolved({
248
- response: AiResponse.empty,
249
- resolved: /*#__PURE__*/new Map(),
250
- encoded: /*#__PURE__*/new Map()
251
- });
252
- /**
253
- * @since 1.0.0
254
- */
255
- get values() {
256
- return Array.from(this.resolved.values());
516
+ export const is = u => Predicate.hasProperty(u, TypeId);
517
+ /**
518
+ * @since 1.0.0
519
+ * @category Guards
520
+ */
521
+ export const isPart = u => Predicate.hasProperty(u, PartTypeId);
522
+ /**
523
+ * @since 1.0.0
524
+ * @category Guards
525
+ */
526
+ export const isStructured = u => Predicate.hasProperty(u, StructuredResponseTypeId);
527
+ /**
528
+ * @since 1.0.0
529
+ * @category Guards
530
+ */
531
+ export const hasToolCallResults = u => Predicate.hasProperty(u, WithToolCallResultsTypeId);
532
+ /**
533
+ * @since 1.0.0
534
+ * @category Constructors
535
+ */
536
+ export const empty = /*#__PURE__*/new AiResponse({
537
+ parts: []
538
+ }, constDisableValidation);
539
+ /**
540
+ * Combines two responses into a single response.
541
+ *
542
+ * @since 1.0.0
543
+ * @category Combination
544
+ */
545
+ export const merge = /*#__PURE__*/dual(2, (self, other) => {
546
+ if (other.parts.length === 0) {
547
+ return new AiResponse({
548
+ parts: self.parts
549
+ }, constDisableValidation);
257
550
  }
258
- /**
259
- * @since 1.0.0
260
- */
261
- get value() {
262
- return Iterable.head(this.resolved.values());
551
+ if (self.parts.length === 0) {
552
+ return new AiResponse({
553
+ parts: other.parts
554
+ }, constDisableValidation);
263
555
  }
264
- /**
265
- * @since 1.0.0
266
- */
267
- get unsafeValue() {
268
- return Iterable.unsafeHead(this.resolved.values());
556
+ const lastPart = self.parts[self.parts.length - 1];
557
+ const newParts = [];
558
+ let text = lastPart._tag === "TextPart" ? lastPart.text : "";
559
+ for (const part of other.parts) {
560
+ if (part._tag === "TextPart") {
561
+ text += part.text;
562
+ }
269
563
  }
270
- /**
271
- * @since 1.0.0
272
- */
273
- concat(that) {
274
- return new WithResolved({
275
- response: this.response.concat(that.response),
276
- resolved: that.resolved.size === 0 ? this.resolved : new Map([...this.resolved, ...that.resolved]),
277
- encoded: that.encoded.size === 0 ? this.encoded : new Map([...this.encoded, ...that.encoded])
278
- });
564
+ if (text.length > 0) {
565
+ newParts.push(new TextPart({
566
+ text
567
+ }, constDisableValidation));
279
568
  }
280
- }
569
+ return newParts.length === 0 ? self : new AiResponse({
570
+ parts: [...self.parts.slice(0, self.parts.length - 1), ...newParts]
571
+ }, constDisableValidation);
572
+ });
573
+ /**
574
+ * Adds the specified tool calls to the provided `AiResponse`.
575
+ *
576
+ * **NOTE**: With this method, the tool call parameters will be parsed as a
577
+ * JSON string. If your tool call parameters are already parsed, use
578
+ * `AiResponse.withToolCallsUnknown`.
579
+ *
580
+ * @since 1.0.0
581
+ * @category Combination
582
+ */
583
+ export const withToolCallsJson = /*#__PURE__*/dual(2, (self, toolCalls) => Effect.forEach(toolCalls, toolCall => ToolCallPart.fromJson(toolCall)).pipe(Effect.map(parts => new AiResponse({
584
+ parts: [...self.parts, ...parts]
585
+ }, constDisableValidation))));
281
586
  //# sourceMappingURL=AiResponse.js.map