1/**
2 * Defines a shared data model for AI model output.
3 *
4 * Responses are represented as typed parts so different providers can expose
5 * text, reasoning, tool calls, files, sources, metadata, finish information, and
6 * errors through one shape. The same model is used for complete responses and
7 * streaming responses, where start, delta, and end parts describe content as it
8 * arrives. This module also carries provider metadata and schemas used by tools
9 * that need to validate response parts.
10 *
11 * @stability unstable
12 * @since 4.0.0
13 */
14import type * as DateTime from "../DateTime.ts"
15import * as Effect from "../Effect.ts"
16import { identity } from "../Function.ts"
17import * as Predicate from "../Predicate.ts"
18import * as Schema from "../Schema.ts"
19import * as SchemaTransformation from "../SchemaTransformation.ts"
20import * as AiError from "./AiError.ts"
21import * as Tool from "./Tool.ts"
22import type * as Toolkit from "./Toolkit.ts"
23
24const PartTypeId = "~effect/ai/Response/Part" as const
25
26// =============================================================================
27// All Parts
28// =============================================================================
29
30/**
31 * Type guard to check if a value is a Response Part.
32 *
33 * @stability unstable
34 * @category guards
35 * @since 4.0.0
36 */
37export const isPart = (u: unknown): u is AnyPart => Predicate.hasProperty(u, PartTypeId)
38
39/**
40 * Union type representing all possible response content parts.
41 *
42 * @stability unstable
43 * @category models
44 * @since 4.0.0
45 */
46export type AnyPart =
47 | TextPart
48 | TextStartPart
49 | TextDeltaPart
50 | TextEndPart
51 | ReasoningPart
52 | ReasoningStartPart
53 | ReasoningDeltaPart
54 | ReasoningEndPart
55 | ToolParamsStartPart
56 | ToolParamsDeltaPart
57 | ToolParamsEndPart
58 | ToolCallPart<any, any>
59 | ToolResultPart<any, any, any>
60 | ToolApprovalRequestPart
61 | FilePart
62 | DocumentSourcePart
63 | UrlSourcePart
64 | ResponseMetadataPart
65 | FinishPart
66 | ErrorPart
67
68/**
69 * Encoded representation of all possible response content parts for serialization.
70 *
71 * @stability unstable
72 * @category models
73 * @since 4.0.0
74 */
75export type AnyPartEncoded =
76 | TextPartEncoded
77 | TextStartPartEncoded
78 | TextDeltaPartEncoded
79 | TextEndPartEncoded
80 | ReasoningPartEncoded
81 | ReasoningStartPartEncoded
82 | ReasoningDeltaPartEncoded
83 | ReasoningEndPartEncoded
84 | ToolParamsStartPartEncoded
85 | ToolParamsDeltaPartEncoded
86 | ToolParamsEndPartEncoded
87 | ToolCallPartEncoded
88 | ToolResultPartEncoded
89 | ToolApprovalRequestPartEncoded
90 | FilePartEncoded
91 | DocumentSourcePartEncoded
92 | UrlSourcePartEncoded
93 | ResponseMetadataPartEncoded
94 | FinishPartEncoded
95 | ErrorPartEncoded
96
97/**
98 * Union type for all response parts with tool-specific typing.
99 *
100 * @stability unstable
101 * @category models
102 * @since 4.0.0
103 */
104export type AllParts<Tools extends Record<string, Tool.Any>> =
105 | TextPart
106 | TextStartPart
107 | TextDeltaPart
108 | TextEndPart
109 | ReasoningPart
110 | ReasoningStartPart
111 | ReasoningDeltaPart
112 | ReasoningEndPart
113 | ToolParamsStartPart
114 | ToolParamsDeltaPart
115 | ToolParamsEndPart
116 | ToolCallParts<Tools>
117 | ToolResultParts<Tools>
118 | ToolApprovalRequestPart
119 | FilePart
120 | DocumentSourcePart
121 | UrlSourcePart
122 | ResponseMetadataPart
123 | FinishPart
124 | ErrorPart
125
126/**
127 * Encoded representation of all response parts for serialization.
128 *
129 * @stability unstable
130 * @category models
131 * @since 4.0.0
132 */
133export type AllPartsEncoded =
134 | TextPartEncoded
135 | TextStartPartEncoded
136 | TextDeltaPartEncoded
137 | TextEndPartEncoded
138 | ReasoningPartEncoded
139 | ReasoningStartPartEncoded
140 | ReasoningDeltaPartEncoded
141 | ReasoningEndPartEncoded
142 | ToolParamsStartPartEncoded
143 | ToolParamsDeltaPartEncoded
144 | ToolParamsEndPartEncoded
145 | ToolCallPartEncoded
146 | ToolResultPartEncoded
147 | ToolApprovalRequestPartEncoded
148 | FilePartEncoded
149 | DocumentSourcePartEncoded
150 | UrlSourcePartEncoded
151 | ResponseMetadataPartEncoded
152 | FinishPartEncoded
153 | ErrorPartEncoded
154
155// Tools are immutable, so response schemas can share their per-tool parts.
156const toolPartSchemaCache = new WeakMap<Tool.Any, {
157 readonly toolCall: Schema.Top
158 readonly toolResult: Schema.Top
159}>()
160
161const toolPartSchemas = (tool: Tool.Any) => {
162 let parts = toolPartSchemaCache.get(tool)
163 if (parts === undefined) {
164 parts = {
165 toolCall: ToolCallPart(tool.name, tool.parametersSchema),
166 toolResult: ToolResultPart(tool.name, tool.successSchema, Tool.failureResultSchema(tool))
167 }
168 toolPartSchemaCache.set(tool, parts)
169 }
170 return parts
171}
172
173/**
174 * Creates a Schema for all response parts based on a toolkit.
175 *
176 * **Details**
177 *
178 * Generates a schema that includes all possible response parts, with tool call
179 * and tool result parts dynamically created based on the provided toolkit.
180 *
181 * **Example** (Building a response parts schema)
182 *
183 * ```ts import.meta.vitest
184 * import { Schema } from "effect"
185 * import { Response, Tool, Toolkit } from "effect/ai"
186 *
187 * const myToolkit = Toolkit.make(
188 * Tool.make("GetWeather", {
189 * parameters: Schema.Struct({ city: Schema.String }),
190 * success: Schema.Struct({ temperature: Schema.Number })
191 * })
192 * )
193 *
194 * const allPartsSchema = Response.AllParts(myToolkit)
195 * Schema.isSchema(allPartsSchema) // => true
196 * ```
197 *
198 * @stability unstable
199 * @category schemas
200 * @since 4.0.0
201 */
202export const AllParts = <T extends Toolkit.Any | Toolkit.WithHandler<any>>(
203 toolkit: T
204): Schema.Codec<
205 AllParts<T extends Toolkit.Any ? Toolkit.Tools<T> : Toolkit.WithHandlerTools<T>>,
206 AllPartsEncoded,
207 Tool.ResultDecodingServices<Toolkit.Tools<T>[keyof Toolkit.Tools<T>]>,
208 Tool.ResultEncodingServices<Toolkit.Tools<T>[keyof Toolkit.Tools<T>]>
209> => {
210 const toolCalls: Array<Schema.Top> = []
211 const toolResults: Array<Schema.Top> = []
212 for (const tool of Object.values(toolkit.tools as Record<string, Tool.Any>)) {
213 const parts = toolPartSchemas(tool)
214 toolCalls.push(parts.toolCall)
215 toolResults.push(parts.toolResult)
216 }
217 return Schema.Union([
218 TextPart,
219 TextStartPart,
220 TextDeltaPart,
221 TextEndPart,
222 ReasoningPart,
223 ReasoningStartPart,
224 ReasoningDeltaPart,
225 ReasoningEndPart,
226 ToolParamsStartPart,
227 ToolParamsDeltaPart,
228 ToolParamsEndPart,
229 ToolApprovalRequestPart,
230 FilePart,
231 DocumentSourcePart,
232 UrlSourcePart,
233 ResponseMetadataPart,
234 FinishPart,
235 ErrorPart,
236 ...toolCalls,
237 ...toolResults
238 ]) as any
239}
240
241// =============================================================================
242// Parts
243// =============================================================================
244
245/**
246 * A type for representing non-streaming response parts with tool-specific
247 * typing.
248 *
249 * @stability unstable
250 * @category models
251 * @since 4.0.0
252 */
253export type Part<
254 Tools extends Record<string, Tool.Any>,
255 ParametersMode extends ToolParametersMode = "decoded"
256> =
257 | TextPart
258 | ReasoningPart
259 | ToolCallParts<Tools, ParametersMode>
260 | ToolResultParts<Tools>
261 | ToolApprovalRequestPart
262 | FilePart
263 | DocumentSourcePart
264 | UrlSourcePart
265 | ResponseMetadataPart
266 | FinishPart
267
268/**
269 * Encoded representation of non-streaming response parts for serialization.
270 *
271 * @stability unstable
272 * @category models
273 * @since 4.0.0
274 */
275export type PartEncoded =
276 | TextPartEncoded
277 | ReasoningPartEncoded
278 | ReasoningDeltaPartEncoded
279 | ReasoningEndPartEncoded
280 | ToolCallPartEncoded
281 | ToolResultPartEncoded
282 | ToolApprovalRequestPartEncoded
283 | FilePartEncoded
284 | DocumentSourcePartEncoded
285 | UrlSourcePartEncoded
286 | ResponseMetadataPartEncoded
287 | FinishPartEncoded
288
289/**
290 * Creates a Schema for non-streaming response parts based on a toolkit.
291 *
292 * @stability unstable
293 * @category schemas
294 * @since 4.0.0
295 */
296export const Part = <T extends Toolkit.Any | Toolkit.WithHandler<any>>(
297 toolkit: T
298): Schema.Codec<
299 Part<T extends Toolkit.Any ? Toolkit.Tools<T> : Toolkit.WithHandlerTools<T>>,
300 PartEncoded,
301 Tool.ResultDecodingServices<Toolkit.Tools<T>[keyof Toolkit.Tools<T>]>,
302 Tool.ResultEncodingServices<Toolkit.Tools<T>[keyof Toolkit.Tools<T>]>
303> => {
304 const toolCalls: Array<Schema.Top> = []
305 const toolResults: Array<Schema.Top> = []
306 for (const tool of Object.values(toolkit.tools as Record<string, Tool.Any>)) {
307 const parts = toolPartSchemas(tool)
308 toolCalls.push(parts.toolCall)
309 toolResults.push(parts.toolResult)
310 }
311 return Schema.Union([
312 TextPart,
313 ReasoningPart,
314 ToolApprovalRequestPart,
315 FilePart,
316 DocumentSourcePart,
317 UrlSourcePart,
318 ResponseMetadataPart,
319 FinishPart,
320 ...toolCalls,
321 ...toolResults
322 ]) as any
323}
324
325// =============================================================================
326// Stream Parts
327// =============================================================================
328
329/**
330 * A type for representing streaming response parts with tool-specific typing.
331 *
332 * @stability unstable
333 * @category models
334 * @since 4.0.0
335 */
336export type StreamPart<
337 Tools extends Record<string, Tool.Any>,
338 ParametersMode extends ToolParametersMode = "decoded"
339> =
340 | TextStartPart
341 | TextDeltaPart
342 | TextEndPart
343 | ReasoningStartPart
344 | ReasoningDeltaPart
345 | ReasoningEndPart
346 | ToolParamsStartPart
347 | ToolParamsDeltaPart
348 | ToolParamsEndPart
349 | ToolCallParts<Tools, ParametersMode>
350 | ToolResultParts<Tools>
351 | ToolApprovalRequestPart
352 | FilePart
353 | DocumentSourcePart
354 | UrlSourcePart
355 | ResponseMetadataPart
356 | FinishPart
357 | ErrorPart
358
359/**
360 * Encoded representation of streaming response parts for serialization.
361 *
362 * @stability unstable
363 * @category models
364 * @since 4.0.0
365 */
366export type StreamPartEncoded =
367 | TextStartPartEncoded
368 | TextDeltaPartEncoded
369 | TextEndPartEncoded
370 | ReasoningStartPartEncoded
371 | ReasoningDeltaPartEncoded
372 | ReasoningEndPartEncoded
373 | ToolParamsStartPartEncoded
374 | ToolParamsDeltaPartEncoded
375 | ToolParamsEndPartEncoded
376 | ToolCallPartEncoded
377 | ToolResultPartEncoded
378 | ToolApprovalRequestPartEncoded
379 | FilePartEncoded
380 | DocumentSourcePartEncoded
381 | UrlSourcePartEncoded
382 | ResponseMetadataPartEncoded
383 | FinishPartEncoded
384 | ErrorPartEncoded
385
386/**
387 * Creates a Schema for streaming response parts based on a toolkit.
388 *
389 * @stability unstable
390 * @category schemas
391 * @since 4.0.0
392 */
393export const StreamPart = <T extends Toolkit.Any | Toolkit.WithHandler<any>>(
394 toolkit: T
395): Schema.Codec<
396 StreamPart<T extends Toolkit.Any ? Toolkit.Tools<T> : Toolkit.WithHandlerTools<T>>,
397 StreamPartEncoded,
398 Tool.ResultDecodingServices<Toolkit.Tools<T>[keyof Toolkit.Tools<T>]>,
399 Tool.ResultEncodingServices<Toolkit.Tools<T>[keyof Toolkit.Tools<T>]>
400> => {
401 const toolCalls: Array<Schema.Top> = []
402 const toolResults: Array<Schema.Top> = []
403 for (const tool of Object.values(toolkit.tools as Record<string, Tool.Any>)) {
404 const parts = toolPartSchemas(tool)
405 toolCalls.push(parts.toolCall)
406 toolResults.push(parts.toolResult)
407 }
408 return Schema.Union([
409 TextStartPart,
410 TextDeltaPart,
411 TextEndPart,
412 ReasoningStartPart,
413 ReasoningDeltaPart,
414 ReasoningEndPart,
415 ToolParamsStartPart,
416 ToolParamsDeltaPart,
417 ToolParamsEndPart,
418 ToolApprovalRequestPart,
419 FilePart,
420 DocumentSourcePart,
421 UrlSourcePart,
422 ResponseMetadataPart,
423 FinishPart,
424 ErrorPart,
425 ...toolCalls,
426 ...toolResults
427 ]) as any
428}
429
430// =============================================================================
431// utility types
432// =============================================================================
433
434/**
435 * Utility type that extracts tool call parts from a set of tools.
436 *
437 * @stability unstable
438 * @category utility types
439 * @since 4.0.0
440 */
441export type ToolCallParts<
442 Tools extends Record<string, Tool.Any>,
443 ParametersMode extends ToolParametersMode = "decoded"
444> = ToolCallPartForName<Tools, ParametersMode, keyof Tools>
445
446/**
447 * Controls whether tool parameters are decoded, encoded, or opaque.
448 *
449 * @stability unstable
450 * @category utility types
451 * @since 4.0.0
452 */
453export type ToolParametersMode = "decoded" | "encoded" | "opaque"
454
455type ToolCallPartForName<
456 Tools extends Record<string, Tool.Any>,
457 ParametersMode extends ToolParametersMode,
458 Name extends keyof Tools
459> = Name extends string ? ToolCallPart<
460 Name,
461 ParametersMode extends "encoded" ? Tool.ParametersEncoded<Tools[Name]>
462 : ParametersMode extends "opaque" ? unknown
463 : Tool.Parameters<Tools[Name]>
464 >
465 : never
466
467/**
468 * Utility type that extracts tool result parts from a set of tools.
469 *
470 * @stability unstable
471 * @category utility types
472 * @since 4.0.0
473 */
474export type ToolResultParts<Tools extends Record<string, Tool.Any>> = ToolResultPartForName<Tools, keyof Tools>
475
476type ToolResultPartForName<
477 Tools extends Record<string, Tool.Any>,
478 Name extends keyof Tools
479> = Name extends string ? ToolResultPart<Name, Tool.Success<Tools[Name]>, Tool.FailureResult<Tools[Name]>> : never
480
481// =============================================================================
482// Base Part
483// =============================================================================
484
485/**
486 * Schema for provider-specific metadata attached to response parts,
487 * represented as a record from provider-specific keys to JSON values or `null`.
488 *
489 * @stability unstable
490 * @category schemas
491 * @since 4.0.0
492 */
493export const ProviderMetadata: Schema.$Record<
494 Schema.String,
495 Schema.NullOr<Schema.Codec<Schema.Json>>
496> = Schema.Record(Schema.String, Schema.NullOr(Schema.Json))
497
498/**
499 * Type of provider-specific metadata attached to response parts, keyed by
500 * provider-specific names with JSON or `null` values.
501 *
502 * @stability unstable
503 * @category models
504 * @since 4.0.0
505 */
506export type ProviderMetadata = typeof ProviderMetadata.Type
507
508/**
509 * Base interface for all response content parts, including the type identifier
510 * and optional metadata.
511 *
512 * @stability unstable
513 * @category models
514 * @since 4.0.0
515 */
516export interface BasePart<Type extends string, Metadata extends ProviderMetadata> {
517 readonly [PartTypeId]: typeof PartTypeId
518 /**
519 * The type of this response part.
520 */
521 readonly type: Type
522 /**
523 * Optional provider-specific metadata for this part.
524 */
525 readonly metadata: Metadata
526}
527
528/**
529 * Base interface for encoded response content parts.
530 *
531 * @stability unstable
532 * @category models
533 * @since 4.0.0
534 */
535export interface BasePartEncoded<Type extends string, Metadata extends ProviderMetadata> {
536 /**
537 * The type of this response part.
538 */
539 readonly type: Type
540 /**
541 * Optional provider-specific metadata for this part.
542 */
543 readonly metadata?: Metadata | undefined
544}
545
546const BasePart = Schema.Struct({
547 [PartTypeId]: Schema.tag(PartTypeId).pipe(
548 Schema.withDecodingDefaultKey(Effect.succeed(PartTypeId), { encodingStrategy: "omit" })
549 ),
550 metadata: ProviderMetadata.pipe(
551 Schema.withDecodingDefault(Effect.succeed({}))
552 )
553})
554
555/**
556 * Creates a new response content part of the specified type.
557 *
558 * **Example** (Creating response content parts)
559 *
560 * ```ts import.meta.vitest
561 * import { Response } from "effect/ai"
562 *
563 * const textPart = Response.makePart("text", {
564 * text: "Hello, world!"
565 * })
566 *
567 * const toolCallPart = Response.makePart("tool-call", {
568 * id: "call_123",
569 * name: "get_weather",
570 * params: { city: "San Francisco" },
571 * providerExecuted: false
572 * })
573 *
574 * const result = [textPart.type, toolCallPart.name] // => ["text", "get_weather"]
575 * ```
576 *
577 * @stability unstable
578 * @category constructors
579 * @since 4.0.0
580 */
581export const makePart = <const Type extends AnyPart["type"]>(
582 /**
583 * The type of part to create.
584 */
585 type: Type,
586 /**
587 * Parameters specific to the part type being created.
588 */
589 params: Omit<Extract<AnyPart, { type: Type }>, typeof PartTypeId | "type" | "metadata"> & {
590 /**
591 * Optional provider-specific metadata for this part.
592 */
593 readonly metadata?: Extract<AnyPart, { type: Type }>["metadata"] | undefined
594 }
595): Extract<AnyPart, { type: Type }> => (({
596 ...params,
597 [PartTypeId]: PartTypeId,
598 type,
599 metadata: params.metadata ?? {}
600}) as any)
601
602/**
603 * A utility type for specifying the parameters required to construct a
604 * specific response part.
605 *
606 * @stability unstable
607 * @category utility types
608 * @since 4.0.0
609 */
610export type ConstructorParams<Part extends AnyPart> =
611 & Omit<Part, typeof PartTypeId | "type" | "sourceType" | "metadata">
612 & {
613 /**
614 * Optional provider-specific metadata for this part.
615 */
616 readonly metadata?: Part["metadata"] | undefined
617 }
618
619// =============================================================================
620// Text Part
621// =============================================================================
622
623/**
624 * Response part representing plain text content.
625 *
626 * **Example** (Creating a text part)
627 *
628 * ```ts import.meta.vitest
629 * import { Response } from "effect/ai"
630 *
631 * const textPart: Response.TextPart = Response.makePart("text", {
632 * text: "The answer to your question is 42."
633 * })
634 * textPart.text // => "The answer to your question is 42."
635 * ```
636 *
637 * @stability unstable
638 * @category models
639 * @since 4.0.0
640 */
641export interface TextPart extends BasePart<"text", TextPartMetadata> {
642 /**
643 * The text content.
644 */
645 readonly text: string
646}
647
648/**
649 * Encoded representation of text parts for serialization.
650 *
651 * @stability unstable
652 * @category models
653 * @since 4.0.0
654 */
655export interface TextPartEncoded extends BasePartEncoded<"text", TextPartMetadata> {
656 /**
657 * The text content.
658 */
659 readonly text: string
660}
661
662/**
663 * Represents provider-specific metadata that can be associated with a
664 * `TextPart` through module augmentation.
665 *
666 * @stability unstable
667 * @category configuration
668 * @since 4.0.0
669 */
670export interface TextPartMetadata extends ProviderMetadata {}
671
672/**
673 * Schema for validation and encoding of text parts.
674 *
675 * @stability unstable
676 * @category schemas
677 * @since 4.0.0
678 */
679export const TextPart: Schema.Struct<{
680 readonly type: Schema.tag<"text">
681 readonly text: Schema.String
682 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
683 readonly metadata: Schema.withDecodingDefault<
684 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
685 >
686}> = Schema.Struct({
687 ...BasePart.fields,
688 type: Schema.tag("text"),
689 text: Schema.String
690}).annotate({ identifier: "TextPart" }) satisfies Schema.Codec<TextPart, TextPartEncoded>
691
692// =============================================================================
693// Text Start Part
694// =============================================================================
695
696/**
697 * Response part indicating the start of streaming text content with a unique
698 * text chunk identifier.
699 *
700 * @stability unstable
701 * @category models
702 * @since 4.0.0
703 */
704export interface TextStartPart extends BasePart<"text-start", TextStartPartMetadata> {
705 /**
706 * Unique identifier for this text chunk.
707 */
708 readonly id: string
709}
710
711/**
712 * Encoded representation of text start parts for serialization.
713 *
714 * @stability unstable
715 * @category models
716 * @since 4.0.0
717 */
718export interface TextStartPartEncoded extends BasePartEncoded<"text-start", TextStartPartMetadata> {
719 /**
720 * Unique identifier for this text chunk.
721 */
722 readonly id: string
723}
724
725/**
726 * Represents provider-specific metadata that can be associated with a
727 * `TextStartPart` through module augmentation.
728 *
729 * @stability unstable
730 * @category configuration
731 * @since 4.0.0
732 */
733export interface TextStartPartMetadata extends ProviderMetadata {}
734
735/**
736 * Schema for validation and encoding of text start parts.
737 *
738 * @stability unstable
739 * @category schemas
740 * @since 4.0.0
741 */
742export const TextStartPart: Schema.Struct<{
743 readonly type: Schema.tag<"text-start">
744 readonly id: Schema.String
745 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
746 readonly metadata: Schema.withDecodingDefault<
747 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
748 >
749}> = Schema.Struct({
750 ...BasePart.fields,
751 type: Schema.tag("text-start"),
752 id: Schema.String
753}).annotate({ identifier: "TextStartPart" }) satisfies Schema.Codec<TextStartPart, TextStartPartEncoded>
754
755// =============================================================================
756// Text Delta Part
757// =============================================================================
758
759/**
760 * Response part containing incremental text content to be added to the existing
761 * text chunk with the same unique identifier.
762 *
763 * @stability unstable
764 * @category models
765 * @since 4.0.0
766 */
767export interface TextDeltaPart extends BasePart<"text-delta", TextDeltaPartMetadata> {
768 /**
769 * Unique identifier matching the corresponding text chunk.
770 */
771 readonly id: string
772 /**
773 * The incremental text content to add.
774 */
775 readonly delta: string
776}
777
778/**
779 * Encoded representation of text delta parts for serialization.
780 *
781 * @stability unstable
782 * @category models
783 * @since 4.0.0
784 */
785export interface TextDeltaPartEncoded extends BasePartEncoded<"text-delta", TextDeltaPartMetadata> {
786 /**
787 * Unique identifier matching the corresponding text chunk.
788 */
789 readonly id: string
790 /**
791 * The incremental text content to add.
792 */
793 readonly delta: string
794}
795
796/**
797 * Represents provider-specific metadata that can be associated with a
798 * `TextDeltaPart` through module augmentation.
799 *
800 * @stability unstable
801 * @category configuration
802 * @since 4.0.0
803 */
804export interface TextDeltaPartMetadata extends ProviderMetadata {}
805
806/**
807 * Schema for validation and encoding of text delta parts.
808 *
809 * @stability unstable
810 * @category schemas
811 * @since 4.0.0
812 */
813export const TextDeltaPart: Schema.Struct<{
814 readonly type: Schema.tag<"text-delta">
815 readonly id: Schema.String
816 readonly delta: Schema.String
817 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
818 readonly metadata: Schema.withDecodingDefault<
819 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
820 >
821}> = Schema.Struct({
822 ...BasePart.fields,
823 type: Schema.tag("text-delta"),
824 id: Schema.String,
825 delta: Schema.String
826}).annotate({ identifier: "TextDeltaPart" }) satisfies Schema.Codec<TextDeltaPart, TextDeltaPartEncoded>
827
828// =============================================================================
829// Text End Part
830// =============================================================================
831
832/**
833 * Response part indicating the completion of a streaming text chunk.
834 *
835 * @stability unstable
836 * @category models
837 * @since 4.0.0
838 */
839export interface TextEndPart extends BasePart<"text-end", TextEndPartMetadata> {
840 /**
841 * Unique identifier matching the corresponding text chunk.
842 */
843 readonly id: string
844}
845
846/**
847 * Encoded representation of text end parts for serialization.
848 *
849 * @stability unstable
850 * @category models
851 * @since 4.0.0
852 */
853export interface TextEndPartEncoded extends BasePartEncoded<"text-end", TextEndPartMetadata> {
854 /**
855 * Unique identifier matching the corresponding text chunk.
856 */
857 readonly id: string
858}
859
860/**
861 * Represents provider-specific metadata that can be associated with a
862 * `TextEndPart` through module augmentation.
863 *
864 * @stability unstable
865 * @category configuration
866 * @since 4.0.0
867 */
868export interface TextEndPartMetadata extends ProviderMetadata {}
869
870/**
871 * Schema for validation and encoding of text end parts.
872 *
873 * @stability unstable
874 * @category schemas
875 * @since 4.0.0
876 */
877export const TextEndPart: Schema.Struct<{
878 readonly type: Schema.tag<"text-end">
879 readonly id: Schema.String
880 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
881 readonly metadata: Schema.withDecodingDefault<
882 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
883 >
884}> = Schema.Struct({
885 ...BasePart.fields,
886 type: Schema.tag("text-end"),
887 id: Schema.String
888}).annotate({ identifier: "TextEndPart" }) satisfies Schema.Codec<TextEndPart, TextEndPartEncoded>
889
890// =============================================================================
891// Reasoning Part
892// =============================================================================
893
894/**
895 * Response part carrying provider-supplied reasoning text, such as an exposed
896 * reasoning summary or explanation. Do not assume it contains hidden
897 * chain-of-thought.
898 *
899 * **Example** (Creating a reasoning part)
900 *
901 * ```ts import.meta.vitest
902 * import { Response } from "effect/ai"
903 *
904 * const reasoningPart: Response.ReasoningPart = Response.makePart("reasoning", {
905 * text:
906 * "Let me think step by step: First I need to analyze the user's question..."
907 * })
908 * reasoningPart.type // => "reasoning"
909 * ```
910 *
911 * @stability unstable
912 * @category models
913 * @since 4.0.0
914 */
915export interface ReasoningPart extends BasePart<"reasoning", ReasoningPartMetadata> {
916 /**
917 * The reasoning or thought process text.
918 */
919 readonly text: string
920}
921
922/**
923 * Encoded representation of reasoning parts for serialization.
924 *
925 * @stability unstable
926 * @category models
927 * @since 4.0.0
928 */
929export interface ReasoningPartEncoded extends BasePartEncoded<"reasoning", ReasoningPartMetadata> {
930 /**
931 * The reasoning or thought process text.
932 */
933 readonly text: string
934}
935
936/**
937 * Represents provider-specific metadata that can be associated with a
938 * `ReasoningPart` through module augmentation.
939 *
940 * @stability unstable
941 * @category configuration
942 * @since 4.0.0
943 */
944export interface ReasoningPartMetadata extends ProviderMetadata {}
945
946/**
947 * Schema for validation and encoding of reasoning parts.
948 *
949 * @stability unstable
950 * @category schemas
951 * @since 4.0.0
952 */
953export const ReasoningPart: Schema.Struct<{
954 readonly type: Schema.tag<"reasoning">
955 readonly text: Schema.String
956 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
957 readonly metadata: Schema.withDecodingDefault<
958 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
959 >
960}> = Schema.Struct({
961 ...BasePart.fields,
962 type: Schema.tag("reasoning"),
963 text: Schema.String
964}).annotate({ identifier: "ReasoningPart" }) satisfies Schema.Codec<ReasoningPart, ReasoningPartEncoded>
965
966// =============================================================================
967// Reasoning Start Part
968// =============================================================================
969
970/**
971 * Response part indicating the start of streaming reasoning content with a
972 * unique reasoning chunk identifier.
973 *
974 * @stability unstable
975 * @category models
976 * @since 4.0.0
977 */
978export interface ReasoningStartPart extends BasePart<"reasoning-start", ReasoningStartPartMetadata> {
979 /**
980 * Unique identifier for this reasoning chunk.
981 */
982 readonly id: string
983}
984
985/**
986 * Encoded representation of reasoning start parts for serialization.
987 *
988 * @stability unstable
989 * @category models
990 * @since 4.0.0
991 */
992export interface ReasoningStartPartEncoded extends BasePartEncoded<"reasoning-start", ReasoningStartPartMetadata> {
993 /**
994 * Unique identifier for this reasoning stream.
995 */
996 readonly id: string
997}
998
999/**
1000 * Represents provider-specific metadata that can be associated with a
1001 * `ReasoningStartPart` through module augmentation.
1002 *
1003 * @stability unstable
1004 * @category configuration
1005 * @since 4.0.0
1006 */
1007export interface ReasoningStartPartMetadata extends ProviderMetadata {}
1008
1009/**
1010 * Schema for validation and encoding of reasoning start parts.
1011 *
1012 * @stability unstable
1013 * @category schemas
1014 * @since 4.0.0
1015 */
1016export const ReasoningStartPart: Schema.Struct<{
1017 readonly type: Schema.tag<"reasoning-start">
1018 readonly id: Schema.String
1019 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1020 readonly metadata: Schema.withDecodingDefault<
1021 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1022 >
1023}> = Schema.Struct({
1024 ...BasePart.fields,
1025 type: Schema.tag("reasoning-start"),
1026 id: Schema.String
1027}).annotate({ identifier: "ReasoningStartPart" }) satisfies Schema.Codec<ReasoningStartPart, ReasoningStartPartEncoded>
1028
1029// =============================================================================
1030// Reasoning Delta Part
1031// =============================================================================
1032
1033/**
1034 * Response part containing incremental reasoning content to be added to the
1035 * existing chunk of reasoning text with the same unique identifier.
1036 *
1037 * @stability unstable
1038 * @category models
1039 * @since 4.0.0
1040 */
1041export interface ReasoningDeltaPart extends BasePart<"reasoning-delta", ReasoningDeltaPartMetadata> {
1042 /**
1043 * Unique identifier matching the corresponding reasoning chunk.
1044 */
1045 readonly id: string
1046 /**
1047 * The incremental reasoning content to add.
1048 */
1049 readonly delta: string
1050}
1051
1052/**
1053 * Encoded representation of reasoning delta parts for serialization.
1054 *
1055 * @stability unstable
1056 * @category models
1057 * @since 4.0.0
1058 */
1059export interface ReasoningDeltaPartEncoded extends BasePartEncoded<"reasoning-delta", ReasoningDeltaPartMetadata> {
1060 /**
1061 * Unique identifier matching the corresponding reasoning chunk.
1062 */
1063 readonly id: string
1064 /**
1065 * The incremental reasoning content to add.
1066 */
1067 readonly delta: string
1068}
1069
1070/**
1071 * Represents provider-specific metadata that can be associated with a
1072 * `ReasoningDeltaPart` through module augmentation.
1073 *
1074 * @stability unstable
1075 * @category configuration
1076 * @since 4.0.0
1077 */
1078export interface ReasoningDeltaPartMetadata extends ProviderMetadata {}
1079
1080/**
1081 * Schema for validation and encoding of reasoning delta parts.
1082 *
1083 * @stability unstable
1084 * @category schemas
1085 * @since 4.0.0
1086 */
1087export const ReasoningDeltaPart: Schema.Struct<{
1088 readonly type: Schema.tag<"reasoning-delta">
1089 readonly id: Schema.String
1090 readonly delta: Schema.String
1091 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1092 readonly metadata: Schema.withDecodingDefault<
1093 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1094 >
1095}> = Schema.Struct({
1096 ...BasePart.fields,
1097 type: Schema.tag("reasoning-delta"),
1098 id: Schema.String,
1099 delta: Schema.String
1100}).annotate({ identifier: "ReasoningDeltaPart" }) satisfies Schema.Codec<ReasoningDeltaPart, ReasoningDeltaPartEncoded>
1101
1102// =============================================================================
1103// Reasoning End Part
1104// =============================================================================
1105
1106/**
1107 * Response part indicating the completion of a streaming reasoning chunk.
1108 *
1109 * @stability unstable
1110 * @category models
1111 * @since 4.0.0
1112 */
1113export interface ReasoningEndPart extends BasePart<"reasoning-end", ReasoningEndPartMetadata> {
1114 /**
1115 * Unique identifier matching the corresponding reasoning chunk.
1116 */
1117 readonly id: string
1118}
1119
1120/**
1121 * Encoded representation of reasoning end parts for serialization.
1122 *
1123 * @stability unstable
1124 * @category models
1125 * @since 4.0.0
1126 */
1127export interface ReasoningEndPartEncoded extends BasePartEncoded<"reasoning-end", ReasoningEndPartMetadata> {
1128 /**
1129 * Unique identifier matching the corresponding reasoning chunk.
1130 */
1131 readonly id: string
1132}
1133
1134/**
1135 * Represents provider-specific metadata that can be associated with a
1136 * `ReasoningEndPart` through module augmentation.
1137 *
1138 * @stability unstable
1139 * @category configuration
1140 * @since 4.0.0
1141 */
1142export interface ReasoningEndPartMetadata extends ProviderMetadata {}
1143
1144/**
1145 * Schema for validation and encoding of reasoning end parts.
1146 *
1147 * @stability unstable
1148 * @category schemas
1149 * @since 4.0.0
1150 */
1151export const ReasoningEndPart: Schema.Struct<{
1152 readonly type: Schema.tag<"reasoning-end">
1153 readonly id: Schema.String
1154 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1155 readonly metadata: Schema.withDecodingDefault<
1156 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1157 >
1158}> = Schema.Struct({
1159 ...BasePart.fields,
1160 type: Schema.tag("reasoning-end"),
1161 id: Schema.String
1162}).annotate({ identifier: "ReasoningEndPart" }) satisfies Schema.Codec<ReasoningEndPart, ReasoningEndPartEncoded>
1163
1164// =============================================================================
1165// Tool Params Start Part
1166// =============================================================================
1167
1168/**
1169 * Response part indicating the start of streaming tool parameters.
1170 *
1171 * **Details**
1172 *
1173 * Marks the beginning of tool parameter streaming with metadata about the tool
1174 * call.
1175 *
1176 * @stability unstable
1177 * @category models
1178 * @since 4.0.0
1179 */
1180export interface ToolParamsStartPart extends BasePart<"tool-params-start", ToolParamsStartPartMetadata> {
1181 /**
1182 * Unique identifier for this tool parameter chunk.
1183 */
1184 readonly id: string
1185 /**
1186 * Name of the tool being called, which corresponds to the name of the tool
1187 * in the `Toolkit` included with the request.
1188 */
1189 readonly name: string
1190 /**
1191 * Whether the tool was executed by the provider (true) or framework (false).
1192 */
1193 readonly providerExecuted: boolean
1194}
1195
1196/**
1197 * Encoded representation of tool params start parts for serialization.
1198 *
1199 * @stability unstable
1200 * @category models
1201 * @since 4.0.0
1202 */
1203export interface ToolParamsStartPartEncoded extends BasePartEncoded<"tool-params-start", ToolParamsStartPartMetadata> {
1204 /**
1205 * Unique identifier for this tool parameter chunk.
1206 */
1207 readonly id: string
1208 /**
1209 * Name of the tool being called, which corresponds to the name of the tool
1210 * in the `Toolkit` included with the request.
1211 */
1212 readonly name: string
1213 /**
1214 * Whether the tool was executed by the provider (true) or framework (false).
1215 */
1216 readonly providerExecuted?: boolean
1217}
1218
1219/**
1220 * Represents provider-specific metadata that can be associated with a
1221 * `ToolParamsStartPart` through module augmentation.
1222 *
1223 * @stability unstable
1224 * @category configuration
1225 * @since 4.0.0
1226 */
1227export interface ToolParamsStartPartMetadata extends ProviderMetadata {}
1228
1229/**
1230 * Schema for validation and encoding of tool params start parts.
1231 *
1232 * @stability unstable
1233 * @category schemas
1234 * @since 4.0.0
1235 */
1236export const ToolParamsStartPart: Schema.Struct<{
1237 readonly type: Schema.tag<"tool-params-start">
1238 readonly id: Schema.String
1239 readonly name: Schema.String
1240 readonly providerExecuted: Schema.withDecodingDefaultKey<Schema.Boolean>
1241 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1242 readonly metadata: Schema.withDecodingDefault<
1243 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1244 >
1245}> = Schema.Struct({
1246 ...BasePart.fields,
1247 type: Schema.tag("tool-params-start"),
1248 id: Schema.String,
1249 name: Schema.String,
1250 providerExecuted: Schema.Boolean.pipe(Schema.withDecodingDefaultKey(Effect.succeed(false)))
1251}).annotate({ identifier: "ToolParamsStartPart" }) satisfies Schema.Codec<
1252 ToolParamsStartPart,
1253 ToolParamsStartPartEncoded
1254>
1255
1256// =============================================================================
1257// Tool Params Delta Part
1258// =============================================================================
1259
1260/**
1261 * Response part containing incremental tool parameter content.
1262 *
1263 * **Details**
1264 *
1265 * Represents a chunk of tool parameters being streamed, containing the
1266 * incremental JSON content that forms the tool parameters.
1267 *
1268 * @stability unstable
1269 * @category models
1270 * @since 4.0.0
1271 */
1272export interface ToolParamsDeltaPart extends BasePart<"tool-params-delta", ToolParamsDeltaPartMetadata> {
1273 /**
1274 * Unique identifier matching the corresponding tool parameter chunk.
1275 */
1276 readonly id: string
1277 /**
1278 * The incremental parameter content (typically JSON fragment) to add.
1279 */
1280 readonly delta: string
1281}
1282
1283/**
1284 * Encoded representation of tool params delta parts for serialization.
1285 *
1286 * @stability unstable
1287 * @category models
1288 * @since 4.0.0
1289 */
1290export interface ToolParamsDeltaPartEncoded extends BasePartEncoded<"tool-params-delta", ToolParamsDeltaPartMetadata> {
1291 /**
1292 * Unique identifier matching the corresponding tool parameter chunk.
1293 */
1294 readonly id: string
1295 /**
1296 * The incremental parameter content (typically JSON fragment) to add.
1297 */
1298 readonly delta: string
1299}
1300
1301/**
1302 * Represents provider-specific metadata that can be associated with a
1303 * `ToolParamsDeltaPart` through module augmentation.
1304 *
1305 * @stability unstable
1306 * @category configuration
1307 * @since 4.0.0
1308 */
1309export interface ToolParamsDeltaPartMetadata extends ProviderMetadata {}
1310
1311/**
1312 * Schema for validation and encoding of tool params delta parts.
1313 *
1314 * @stability unstable
1315 * @category schemas
1316 * @since 4.0.0
1317 */
1318export const ToolParamsDeltaPart: Schema.Struct<{
1319 readonly type: Schema.tag<"tool-params-delta">
1320 readonly id: Schema.String
1321 readonly delta: Schema.String
1322 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1323 readonly metadata: Schema.withDecodingDefault<
1324 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1325 >
1326}> = Schema.Struct({
1327 ...BasePart.fields,
1328 type: Schema.tag("tool-params-delta"),
1329 id: Schema.String,
1330 delta: Schema.String
1331}).annotate({ identifier: "ToolParamsDeltaPart" }) satisfies Schema.Codec<
1332 ToolParamsDeltaPart,
1333 ToolParamsDeltaPartEncoded
1334>
1335
1336// =============================================================================
1337// Tool Params End Part
1338// =============================================================================
1339
1340/**
1341 * Response part indicating the end of streaming tool parameters.
1342 *
1343 * **Details**
1344 *
1345 * Marks the completion of a tool parameter stream, indicating that all
1346 * parameter data has been sent and the tool call is ready to be executed.
1347 *
1348 * @stability unstable
1349 * @category models
1350 * @since 4.0.0
1351 */
1352export interface ToolParamsEndPart extends BasePart<"tool-params-end", ToolParamsEndPartMetadata> {
1353 /**
1354 * Unique identifier matching the corresponding tool parameter chunk.
1355 */
1356 readonly id: string
1357}
1358
1359/**
1360 * Encoded representation of tool params end parts for serialization.
1361 *
1362 * @stability unstable
1363 * @category models
1364 * @since 4.0.0
1365 */
1366export interface ToolParamsEndPartEncoded extends BasePartEncoded<"tool-params-end", ToolParamsEndPartMetadata> {
1367 /**
1368 * Unique identifier matching the corresponding tool parameter stream.
1369 */
1370 readonly id: string
1371}
1372
1373/**
1374 * Represents provider-specific metadata that can be associated with a
1375 * `ToolParamsEndPart` through module augmentation.
1376 *
1377 * @stability unstable
1378 * @category configuration
1379 * @since 4.0.0
1380 */
1381export interface ToolParamsEndPartMetadata extends ProviderMetadata {}
1382
1383/**
1384 * Schema for validation and encoding of tool params end parts.
1385 *
1386 * @stability unstable
1387 * @category schemas
1388 * @since 4.0.0
1389 */
1390export const ToolParamsEndPart: Schema.Struct<{
1391 readonly type: Schema.tag<"tool-params-end">
1392 readonly id: Schema.String
1393 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1394 readonly metadata: Schema.withDecodingDefault<
1395 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1396 >
1397}> = Schema.Struct({
1398 ...BasePart.fields,
1399 type: Schema.tag("tool-params-end"),
1400 id: Schema.String
1401}).annotate({ identifier: "ToolParamsEndPart" }) satisfies Schema.Codec<ToolParamsEndPart, ToolParamsEndPartEncoded>
1402
1403// =============================================================================
1404// Tool Call Part
1405// =============================================================================
1406
1407/**
1408 * Response part representing a tool call request.
1409 *
1410 * **Example** (Creating a tool call part)
1411 *
1412 * ```ts import.meta.vitest
1413 * import { Schema } from "effect"
1414 * import { Response } from "effect/ai"
1415 *
1416 * const weatherParams = Schema.Struct({
1417 * city: Schema.String,
1418 * units: Schema.optional(Schema.Literals(["celsius", "fahrenheit"]))
1419 * })
1420 *
1421 * const toolCallPart: Response.ToolCallPart<
1422 * "get_weather",
1423 * {
1424 * readonly city: string
1425 * readonly units?: "celsius" | "fahrenheit"
1426 * }
1427 * > = Response.makePart("tool-call", {
1428 * id: "call_123",
1429 * name: "get_weather",
1430 * params: { city: "San Francisco", units: "celsius" },
1431 * providerExecuted: false
1432 * })
1433 * const result = [toolCallPart.name, toolCallPart.params.city] // => ["get_weather", "San Francisco"]
1434 * ```
1435 *
1436 * @stability unstable
1437 * @category models
1438 * @since 4.0.0
1439 */
1440export interface ToolCallPart<Name extends string, Params> extends BasePart<"tool-call", ToolCallPartMetadata> {
1441 /**
1442 * Unique identifier for this tool call.
1443 */
1444 readonly id: string
1445 /**
1446 * Name of the tool being called, which corresponds to the name of the tool
1447 * in the `Toolkit` included with the request.
1448 */
1449 readonly name: Name
1450 /**
1451 * Parameters to pass to the tool.
1452 */
1453 readonly params: Params
1454 /**
1455 * Whether the tool was executed by the provider (true) or framework (false).
1456 */
1457 readonly providerExecuted: boolean
1458}
1459
1460/**
1461 * Encoded representation of tool call parts for serialization.
1462 *
1463 * @stability unstable
1464 * @category models
1465 * @since 4.0.0
1466 */
1467export interface ToolCallPartEncoded extends BasePartEncoded<"tool-call", ToolCallPartMetadata> {
1468 /**
1469 * Unique identifier for this tool call.
1470 */
1471 readonly id: string
1472 /**
1473 * Name of the tool being called, which corresponds to the name of the tool
1474 * in the `Toolkit` included with the request.
1475 */
1476 readonly name: string
1477 /**
1478 * Parameters to pass to the tool.
1479 */
1480 readonly params: unknown
1481 /**
1482 * Whether the tool was executed by the provider (true) or framework (false).
1483 */
1484 readonly providerExecuted?: boolean | undefined
1485}
1486
1487/**
1488 * Represents provider-specific metadata that can be associated with a
1489 * `ToolCallPart` through module augmentation.
1490 *
1491 * @stability unstable
1492 * @category configuration
1493 * @since 4.0.0
1494 */
1495export interface ToolCallPartMetadata extends ProviderMetadata {}
1496
1497/**
1498 * Creates a Schema for tool call parts with specific tool name and parameters.
1499 *
1500 * @stability unstable
1501 * @category schemas
1502 * @since 4.0.0
1503 */
1504export const ToolCallPart: <const Name extends string, Params extends Schema.Constraint>(
1505 name: Name,
1506 params: Params
1507) => Schema.Struct<
1508 {
1509 readonly type: Schema.Literal<"tool-call">
1510 readonly id: Schema.String
1511 readonly name: Schema.Literal<Name>
1512 readonly params: Params
1513 readonly providerExecuted: Schema.withDecodingDefaultKey<Schema.Boolean>
1514 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1515 readonly metadata: Schema.withDecodingDefault<
1516 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1517 >
1518 }
1519> = <const Name extends string, Params extends Schema.Constraint>(
1520 name: Name,
1521 params: Params
1522) =>
1523 Schema.Struct({
1524 ...BasePart.fields,
1525 type: Schema.Literal("tool-call"),
1526 id: Schema.String,
1527 name: Schema.Literal(name),
1528 params,
1529 providerExecuted: Schema.Boolean.pipe(Schema.withDecodingDefaultKey(Effect.succeed(false)))
1530 }).annotate({ identifier: "ToolCallPart" }) as any
1531
1532/**
1533 * Constructs a new tool call part.
1534 *
1535 * @stability unstable
1536 * @category constructors
1537 * @since 4.0.0
1538 */
1539export const toolCallPart = <const Name extends string, Params>(
1540 params: ConstructorParams<ToolCallPart<Name, Params>>
1541): ToolCallPart<Name, Params> => makePart("tool-call", params)
1542
1543// =============================================================================
1544// Tool Call Result Part
1545// =============================================================================
1546
1547/**
1548 * The base fields of a tool result part.
1549 *
1550 * @stability unstable
1551 * @category models
1552 * @since 4.0.0
1553 */
1554export interface BaseToolResult<Name extends string> extends BasePart<"tool-result", ToolResultPartMetadata> {
1555 /**
1556 * Unique identifier matching the original tool call.
1557 */
1558 readonly id: string
1559 /**
1560 * Name of the tool being called, which corresponds to the name of the tool
1561 * in the `Toolkit` included with the request.
1562 */
1563 readonly name: Name
1564 /**
1565 * The encoded result for serialization purposes.
1566 */
1567 readonly encodedResult: unknown
1568 /**
1569 * Whether the tool was executed by the provider (true) or framework (false).
1570 */
1571 readonly providerExecuted: boolean
1572 /**
1573 * Whether this is a preliminary (intermediate) result.
1574 *
1575 * **Details**
1576 *
1577 * Preliminary results represent progress updates during streaming tool
1578 * execution. Only the final result (where `preliminary` is `false` or
1579 * `undefined`) should be used as the authoritative output.
1580 *
1581 * **Gotchas**
1582 *
1583 * Only applicable for framework-executed tools during streaming.
1584 */
1585 readonly preliminary: boolean
1586}
1587
1588/**
1589 * Represents a successful tool call result.
1590 *
1591 * @stability unstable
1592 * @category models
1593 * @since 4.0.0
1594 */
1595export interface ToolResultSuccess<Name extends string, Success> extends BaseToolResult<Name> {
1596 /**
1597 * The decoded success returned by the tool execution.
1598 */
1599 readonly result: Success
1600 /**
1601 * Whether or not the result of executing the tool call handler was an error.
1602 */
1603 readonly isFailure: false
1604}
1605
1606/**
1607 * Represents a failed tool call result.
1608 *
1609 * @stability unstable
1610 * @category models
1611 * @since 4.0.0
1612 */
1613export interface ToolResultFailure<Name extends string, Failure> extends BaseToolResult<Name> {
1614 /**
1615 * The decoded failure returned by the tool execution.
1616 */
1617 readonly result: Failure
1618 /**
1619 * Whether or not the result of executing the tool call handler was an error.
1620 */
1621 readonly isFailure: true
1622}
1623
1624/**
1625 * Response part representing the result of a tool call.
1626 *
1627 * **Example** (Creating a tool result part)
1628 *
1629 * ```ts import.meta.vitest
1630 * import { Response } from "effect/ai"
1631 *
1632 * interface WeatherData {
1633 * temperature: number
1634 * condition: string
1635 * humidity: number
1636 * }
1637 *
1638 * const toolResultPart: Response.ToolResultPart<
1639 * "get_weather",
1640 * WeatherData,
1641 * never
1642 * > = Response.toolResultPart({
1643 * id: "call_123",
1644 * name: "get_weather",
1645 * isFailure: false,
1646 * result: {
1647 * temperature: 22,
1648 * condition: "sunny",
1649 * humidity: 65
1650 * },
1651 * encodedResult: {
1652 * temperature: 22,
1653 * condition: "sunny",
1654 * humidity: 65
1655 * },
1656 * providerExecuted: false,
1657 * preliminary: false
1658 * })
1659 * const result = [toolResultPart.name, toolResultPart.result.temperature] // => ["get_weather", 22]
1660 * ```
1661 *
1662 * @stability unstable
1663 * @category models
1664 * @since 4.0.0
1665 */
1666export type ToolResultPart<Name extends string, Success, Failure> =
1667 | ToolResultSuccess<Name, Success>
1668 | ToolResultFailure<Name, Failure>
1669
1670/**
1671 * Encoded representation of tool result parts for serialization.
1672 *
1673 * @stability unstable
1674 * @category models
1675 * @since 4.0.0
1676 */
1677export interface ToolResultPartEncoded extends BasePartEncoded<"tool-result", ToolResultPartMetadata> {
1678 /**
1679 * Unique identifier matching the original tool call.
1680 */
1681 readonly id: string
1682 /**
1683 * Name of the tool being called, which corresponds to the name of the tool
1684 * in the `Toolkit` included with the request.
1685 */
1686 readonly name: string
1687 /**
1688 * The result returned by the tool execution.
1689 */
1690 readonly result: unknown
1691 /**
1692 * Whether or not the result of executing the tool call handler was an error.
1693 */
1694 readonly isFailure: boolean
1695 /**
1696 * Whether the tool was executed by the provider (true) or framework (false).
1697 */
1698 readonly providerExecuted?: boolean | undefined
1699 /**
1700 * Whether this is a preliminary (intermediate) result.
1701 *
1702 * **Gotchas**
1703 *
1704 * Only applicable for framework-executed tools during streaming.
1705 */
1706 readonly preliminary?: boolean | undefined
1707}
1708
1709/**
1710 * Represents provider-specific metadata that can be associated with a
1711 * `ToolResultPart` through module augmentation.
1712 *
1713 * @stability unstable
1714 * @category configuration
1715 * @since 4.0.0
1716 */
1717export interface ToolResultPartMetadata extends ProviderMetadata {}
1718
1719/**
1720 * Creates a Schema for tool result parts with specific tool name and result type.
1721 *
1722 * @stability unstable
1723 * @category schemas
1724 * @since 4.0.0
1725 */
1726export const ToolResultPart = <
1727 const Name extends string,
1728 Success extends Schema.Constraint,
1729 Failure extends Schema.Constraint
1730>(
1731 name: Name,
1732 success: Success,
1733 failure: Failure
1734): Schema.Codec<
1735 ToolResultPart<Name, Success["Type"], Failure["Type"]>,
1736 ToolResultPartEncoded,
1737 Success["DecodingServices"] | Failure["DecodingServices"],
1738 Success["EncodingServices"] | Failure["EncodingServices"]
1739> => {
1740 const makeSchema = (result: Schema.Constraint, isFailure: boolean) => {
1741 const encodedResult = Schema.toEncoded(result)
1742 const Common = {
1743 id: Schema.String,
1744 type: Schema.Literal("tool-result"),
1745 isFailure: Schema.Literal(isFailure),
1746 name: Schema.Literal(name)
1747 }
1748 const Decoded = Schema.Struct({
1749 ...Common,
1750 [PartTypeId]: Schema.Literal(PartTypeId),
1751 result,
1752 providerExecuted: Schema.Boolean,
1753 metadata: ProviderMetadata,
1754 encodedResult,
1755 preliminary: Schema.Boolean
1756 })
1757 const Encoded = Schema.Struct({
1758 ...Common,
1759 result: encodedResult,
1760 providerExecuted: Schema.optional(Schema.Boolean),
1761 metadata: Schema.optional(ProviderMetadata),
1762 preliminary: Schema.optional(Schema.Boolean)
1763 })
1764 return Decoded.pipe(Schema.encodeTo(
1765 Encoded,
1766 SchemaTransformation.transform({
1767 decode: (encoded) => ({
1768 ...encoded,
1769 [PartTypeId]: PartTypeId,
1770 providerExecuted: encoded.providerExecuted ?? false,
1771 metadata: encoded.metadata ?? {},
1772 encodedResult: encoded.result,
1773 preliminary: encoded.preliminary ?? false
1774 }),
1775 encode: identity
1776 })
1777 ))
1778 }
1779 return Schema.Union([makeSchema(success, false), makeSchema(failure, true)]).annotate({
1780 identifier: `ToolResultPart(${name})`
1781 })
1782}
1783
1784/**
1785 * Constructs a new tool result part.
1786 *
1787 * @stability unstable
1788 * @category constructors
1789 * @since 4.0.0
1790 */
1791export const toolResultPart = <const Params extends ConstructorParams<ToolResultPart<string, unknown, unknown>>>(
1792 params: Params
1793): Params extends {
1794 readonly name: infer Name extends string
1795 readonly isFailure: false
1796 readonly result: infer Success
1797} ? ToolResultPart<Name, Success, never>
1798 : Params extends {
1799 readonly name: infer Name extends string
1800 readonly isFailure: true
1801 readonly result: infer Failure
1802 } ? ToolResultPart<Name, never, Failure>
1803 : never => makePart("tool-result", params) as any
1804
1805// =============================================================================
1806// Tool Approval Request Part
1807// =============================================================================
1808
1809/**
1810 * Response part representing a tool approval request.
1811 *
1812 * **Details**
1813 *
1814 * Emitted when a tool requires user approval before execution. The framework
1815 * checks the tool's `needsApproval` property and emits this part instead of
1816 * executing the tool when approval is required.
1817 *
1818 * **Example** (Creating an approval request part)
1819 *
1820 * ```ts import.meta.vitest
1821 * import { Response } from "effect/ai"
1822 *
1823 * const approvalRequest: Response.ToolApprovalRequestPart = Response.makePart(
1824 * "tool-approval-request",
1825 * {
1826 * approvalId: "approval_123",
1827 * toolCallId: "call_456"
1828 * }
1829 * )
1830 * const result = [approvalRequest.approvalId, approvalRequest.toolCallId] // => ["approval_123", "call_456"]
1831 * ```
1832 *
1833 * @stability unstable
1834 * @category models
1835 * @since 4.0.0
1836 */
1837export interface ToolApprovalRequestPart extends BasePart<"tool-approval-request", ToolApprovalRequestPartMetadata> {
1838 /**
1839 * Unique identifier for this approval flow.
1840 */
1841 readonly approvalId: string
1842 /**
1843 * The tool call ID requiring approval.
1844 */
1845 readonly toolCallId: string
1846}
1847
1848/**
1849 * Encoded representation of tool approval request parts for serialization.
1850 *
1851 * @stability unstable
1852 * @category models
1853 * @since 4.0.0
1854 */
1855export interface ToolApprovalRequestPartEncoded
1856 extends BasePartEncoded<"tool-approval-request", ToolApprovalRequestPartMetadata>
1857{
1858 /**
1859 * Unique identifier for this approval flow.
1860 */
1861 readonly approvalId: string
1862 /**
1863 * The tool call ID requiring approval.
1864 */
1865 readonly toolCallId: string
1866}
1867
1868/**
1869 * Represents provider-specific metadata that can be associated with a
1870 * `ToolApprovalRequestPart` through module augmentation.
1871 *
1872 * @stability unstable
1873 * @category configuration
1874 * @since 4.0.0
1875 */
1876export interface ToolApprovalRequestPartMetadata extends ProviderMetadata {}
1877
1878/**
1879 * Schema for validation and encoding of tool approval request parts.
1880 *
1881 * @stability unstable
1882 * @category schemas
1883 * @since 4.0.0
1884 */
1885export const ToolApprovalRequestPart: Schema.Struct<{
1886 readonly type: Schema.tag<"tool-approval-request">
1887 readonly approvalId: Schema.String
1888 readonly toolCallId: Schema.String
1889 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1890 readonly metadata: Schema.withDecodingDefault<
1891 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1892 >
1893}> = Schema.Struct({
1894 ...BasePart.fields,
1895 type: Schema.tag("tool-approval-request"),
1896 approvalId: Schema.String,
1897 toolCallId: Schema.String
1898}).annotate({ identifier: "ToolApprovalRequestPart" }) satisfies Schema.Codec<
1899 ToolApprovalRequestPart,
1900 ToolApprovalRequestPartEncoded
1901>
1902
1903/**
1904 * Constructs a new tool approval request part.
1905 *
1906 * @stability unstable
1907 * @category constructors
1908 * @since 4.0.0
1909 */
1910export const toolApprovalRequestPart = (
1911 params: ConstructorParams<ToolApprovalRequestPart>
1912): ToolApprovalRequestPart => makePart("tool-approval-request", params as any)
1913
1914// =============================================================================
1915// File Part
1916// =============================================================================
1917
1918/**
1919 * Response part representing a file attachment.
1920 *
1921 * **Details**
1922 *
1923 * Supports various file types including images, documents, and binary data.
1924 *
1925 * **Example** (Creating a file part)
1926 *
1927 * ```ts import.meta.vitest
1928 * import { Response } from "effect/ai"
1929 *
1930 * const imagePart: Response.FilePart = Response.makePart("file", {
1931 * mediaType: "image/jpeg",
1932 * data: new Uint8Array([1, 2, 3])
1933 * })
1934 * const result = [imagePart.mediaType, imagePart.data] // => ["image/jpeg", new Uint8Array([1, 2, 3])]
1935 * ```
1936 *
1937 * @stability unstable
1938 * @category models
1939 * @since 4.0.0
1940 */
1941export interface FilePart extends BasePart<"file", FilePartMetadata> {
1942 /**
1943 * MIME type of the file (e.g., "image/jpeg", "application/pdf").
1944 */
1945 readonly mediaType: string
1946 /**
1947 * File data as a byte array.
1948 */
1949 readonly data: Uint8Array
1950}
1951
1952/**
1953 * Encoded representation of file parts for serialization.
1954 *
1955 * @stability unstable
1956 * @category models
1957 * @since 4.0.0
1958 */
1959export interface FilePartEncoded extends BasePartEncoded<"file", FilePartMetadata> {
1960 /**
1961 * MIME type of the file (e.g., "image/jpeg", "application/pdf").
1962 */
1963 readonly mediaType: string
1964 /**
1965 * File data as a base64 string.
1966 */
1967 readonly data: string
1968}
1969
1970/**
1971 * Represents provider-specific metadata that can be associated with a
1972 * `FilePart` through module augmentation.
1973 *
1974 * @stability unstable
1975 * @category configuration
1976 * @since 4.0.0
1977 */
1978export interface FilePartMetadata extends ProviderMetadata {}
1979
1980/**
1981 * Schema for validation and encoding of file parts.
1982 *
1983 * **Details**
1984 *
1985 * Decoded `data` is a `Uint8Array`; encoded `data` is a base64 string through
1986 * `Schema.Uint8ArrayFromBase64`.
1987 *
1988 * @stability unstable
1989 * @category schemas
1990 * @since 4.0.0
1991 */
1992export const FilePart: Schema.Struct<{
1993 readonly type: Schema.tag<"file">
1994 readonly mediaType: Schema.String
1995 readonly data: Schema.Uint8ArrayFromBase64
1996 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
1997 readonly metadata: Schema.withDecodingDefault<
1998 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
1999 >
2000}> = Schema.Struct({
2001 ...BasePart.fields,
2002 type: Schema.tag("file"),
2003 mediaType: Schema.String,
2004 data: Schema.Uint8ArrayFromBase64
2005}).annotate({ identifier: "FilePart" }) satisfies Schema.Codec<FilePart, FilePartEncoded>
2006
2007// =============================================================================
2008// Document Source Part
2009// =============================================================================
2010
2011/**
2012 * Response part representing a document source reference used in generating the
2013 * response.
2014 *
2015 * @stability unstable
2016 * @category models
2017 * @since 4.0.0
2018 */
2019export interface DocumentSourcePart extends BasePart<"source", DocumentSourcePartMetadata> {
2020 /**
2021 * Type discriminator for document sources.
2022 */
2023 readonly sourceType: "document"
2024 /**
2025 * Unique identifier for the document.
2026 */
2027 readonly id: string
2028 /**
2029 * MIME type of the document.
2030 */
2031 readonly mediaType: string
2032 /**
2033 * Display title of the document.
2034 */
2035 readonly title: string
2036 /**
2037 * Optional filename of the document.
2038 */
2039 readonly fileName?: string
2040}
2041
2042/**
2043 * Encoded representation of document source parts for serialization.
2044 *
2045 * @stability unstable
2046 * @category models
2047 * @since 4.0.0
2048 */
2049export interface DocumentSourcePartEncoded extends BasePartEncoded<"source", DocumentSourcePartMetadata> {
2050 /**
2051 * Type discriminator for document sources.
2052 */
2053 readonly sourceType: "document"
2054 /**
2055 * Unique identifier for the document.
2056 */
2057 readonly id: string
2058 /**
2059 * MIME type of the document.
2060 */
2061 readonly mediaType: string
2062 /**
2063 * Display title of the document.
2064 */
2065 readonly title: string
2066 /**
2067 * Optional filename of the document.
2068 */
2069 readonly fileName?: string
2070}
2071
2072/**
2073 * Represents provider-specific metadata that can be associated with a
2074 * `DocumentSourcePart` through module augmentation.
2075 *
2076 * @stability unstable
2077 * @category configuration
2078 * @since 4.0.0
2079 */
2080export interface DocumentSourcePartMetadata extends ProviderMetadata {}
2081
2082/**
2083 * Schema for validation and encoding of document source parts.
2084 *
2085 * **When to use**
2086 *
2087 * Use to validate or encode document source references returned as response
2088 * content parts.
2089 *
2090 * **Details**
2091 *
2092 * Validates `type: "source"`, `sourceType: "document"`, required `id`,
2093 * `mediaType`, and `title`, optional `fileName`, and the metadata fields
2094 * inherited from response parts.
2095 *
2096 * @see {@link UrlSourcePart} for URL source references
2097 * @see {@link DocumentSourcePartEncoded} for the encoded document source representation
2098 *
2099 * @stability unstable
2100 * @category schemas
2101 * @since 4.0.0
2102 */
2103export const DocumentSourcePart: Schema.Struct<{
2104 readonly type: Schema.tag<"source">
2105 readonly sourceType: Schema.tag<"document">
2106 readonly id: Schema.String
2107 readonly mediaType: Schema.String
2108 readonly title: Schema.String
2109 readonly fileName: Schema.optionalKey<Schema.String>
2110 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
2111 readonly metadata: Schema.withDecodingDefault<
2112 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
2113 >
2114}> = Schema.Struct({
2115 ...BasePart.fields,
2116 type: Schema.tag("source"),
2117 sourceType: Schema.tag("document"),
2118 id: Schema.String,
2119 mediaType: Schema.String,
2120 title: Schema.String,
2121 fileName: Schema.optionalKey(Schema.String)
2122}).annotate({ identifier: "DocumentSourcePart" }) satisfies Schema.Codec<DocumentSourcePart, DocumentSourcePartEncoded>
2123
2124// =============================================================================
2125// Url Source Part
2126// =============================================================================
2127
2128/**
2129 * Response part representing a URL source reference used in generating the
2130 * response.
2131 *
2132 * @stability unstable
2133 * @category models
2134 * @since 4.0.0
2135 */
2136export interface UrlSourcePart extends BasePart<"source", UrlSourcePartMetadata> {
2137 /**
2138 * Type discriminator for URL sources.
2139 */
2140 readonly sourceType: "url"
2141 /**
2142 * Unique identifier for the URL.
2143 */
2144 readonly id: string
2145 /**
2146 * The URL that was referenced.
2147 */
2148 readonly url: URL
2149 /**
2150 * Display title of the URL content.
2151 */
2152 readonly title: string
2153}
2154
2155/**
2156 * Encoded representation of URL source parts for serialization.
2157 *
2158 * @stability unstable
2159 * @category models
2160 * @since 4.0.0
2161 */
2162export interface UrlSourcePartEncoded extends BasePartEncoded<"source", UrlSourcePartMetadata> {
2163 /**
2164 * Type discriminator for URL sources.
2165 */
2166 readonly sourceType: "url"
2167 /**
2168 * Unique identifier for the URL.
2169 */
2170 readonly id: string
2171 /**
2172 * The URL that was referenced as a string.
2173 */
2174 readonly url: string
2175 /**
2176 * Display title of the URL content.
2177 */
2178 readonly title: string
2179}
2180
2181/**
2182 * Represents provider-specific metadata that can be associated with a
2183 * `UrlSourcePart` through module augmentation.
2184 *
2185 * @stability unstable
2186 * @category configuration
2187 * @since 4.0.0
2188 */
2189export interface UrlSourcePartMetadata extends ProviderMetadata {}
2190
2191/**
2192 * Schema for validation and encoding of url source parts.
2193 *
2194 * @stability unstable
2195 * @category schemas
2196 * @since 4.0.0
2197 */
2198export const UrlSourcePart: Schema.Struct<{
2199 readonly type: Schema.tag<"source">
2200 readonly sourceType: Schema.tag<"url">
2201 readonly id: Schema.String
2202 readonly url: Schema.URLFromString
2203 readonly title: Schema.String
2204 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
2205 readonly metadata: Schema.withDecodingDefault<
2206 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
2207 >
2208}> = Schema.Struct({
2209 ...BasePart.fields,
2210 type: Schema.tag("source"),
2211 sourceType: Schema.tag("url"),
2212 id: Schema.String,
2213 url: Schema.URLFromString,
2214 title: Schema.String
2215}).annotate({ identifier: "UrlSourcePart" }) satisfies Schema.Codec<UrlSourcePart, UrlSourcePartEncoded>
2216
2217// =============================================================================
2218// HTTP Details
2219// =============================================================================
2220
2221/**
2222 * Alias of {@link AiError.HttpRequestDetails}.
2223 *
2224 * @stability unstable
2225 * @category schemas
2226 * @since 4.0.0
2227 */
2228export const HttpRequestDetails = AiError.HttpRequestDetails
2229
2230/**
2231 * Alias of {@link AiError.HttpResponseDetails}.
2232 *
2233 * @stability unstable
2234 * @category schemas
2235 * @since 4.0.0
2236 */
2237export const HttpResponseDetails = AiError.HttpResponseDetails
2238
2239// =============================================================================
2240// Response Metadata Part
2241// =============================================================================
2242
2243/**
2244 * Response part containing metadata about the large language model response.
2245 *
2246 * **Example** (Creating a metadata part)
2247 *
2248 * ```ts import.meta.vitest
2249 * import { DateTime } from "effect"
2250 * import { Response } from "effect/ai"
2251 *
2252 * const metadataPart: Response.ResponseMetadataPart = Response.makePart(
2253 * "response-metadata",
2254 * {
2255 * id: "resp_123",
2256 * modelId: "gpt-4",
2257 * timestamp: DateTime.makeUnsafe("2024-01-01T00:00:00Z"),
2258 * request: undefined
2259 * }
2260 * )
2261 * const result = [metadataPart.id, metadataPart.modelId] // => ["resp_123", "gpt-4"]
2262 * ```
2263 *
2264 * @stability unstable
2265 * @category models
2266 * @since 4.0.0
2267 */
2268export interface ResponseMetadataPart extends BasePart<"response-metadata", ResponseMetadataPartMetadata> {
2269 /**
2270 * Optional unique identifier for this specific response.
2271 */
2272 readonly id?: string | undefined
2273 /**
2274 * Optional identifier of the AI model that generated the response.
2275 */
2276 readonly modelId?: string | undefined
2277 /**
2278 * Optional timestamp when the response was generated.
2279 */
2280 readonly timestamp?: DateTime.Utc | undefined
2281 /**
2282 * Optional HTTP request details for the request made to the AI provider.
2283 */
2284 readonly request?: typeof HttpRequestDetails.Type | undefined
2285}
2286
2287/**
2288 * Encoded representation of response metadata parts for serialization.
2289 *
2290 * @stability unstable
2291 * @category models
2292 * @since 4.0.0
2293 */
2294export interface ResponseMetadataPartEncoded
2295 extends BasePartEncoded<"response-metadata", ResponseMetadataPartMetadata>
2296{
2297 /**
2298 * Optional unique identifier for this specific response.
2299 */
2300 readonly id?: string | undefined
2301 /**
2302 * Optional identifier of the AI model that generated the response.
2303 */
2304 readonly modelId?: string | undefined
2305 /**
2306 * Optional timestamp when the response was generated.
2307 */
2308 readonly timestamp?: string | undefined
2309 /**
2310 * Optional HTTP request details for the request made to the AI provider.
2311 */
2312 readonly request?: typeof HttpRequestDetails.Encoded | undefined
2313}
2314
2315/**
2316 * Represents provider-specific metadata that can be associated with a
2317 * `ResponseMetadataPart` through module augmentation.
2318 *
2319 * @stability unstable
2320 * @category configuration
2321 * @since 4.0.0
2322 */
2323export interface ResponseMetadataPartMetadata extends ProviderMetadata {}
2324
2325/**
2326 * Schema for validation and encoding of response metadata parts.
2327 *
2328 * @stability unstable
2329 * @category schemas
2330 * @since 4.0.0
2331 */
2332export const ResponseMetadataPart: Schema.Struct<{
2333 readonly type: Schema.tag<"response-metadata">
2334 readonly id: Schema.optional<Schema.String>
2335 readonly modelId: Schema.optional<Schema.String>
2336 readonly timestamp: Schema.optional<Schema.DateTimeUtcFromString>
2337 readonly request: Schema.optional<typeof HttpRequestDetails>
2338 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
2339 readonly metadata: Schema.withDecodingDefault<
2340 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
2341 >
2342}> = Schema.Struct({
2343 ...BasePart.fields,
2344 type: Schema.tag("response-metadata"),
2345 id: Schema.optional(Schema.String),
2346 modelId: Schema.optional(Schema.String),
2347 timestamp: Schema.optional(Schema.DateTimeUtcFromString),
2348 request: Schema.optional(HttpRequestDetails)
2349}).annotate({ identifier: "ResponseMetadataPart" }) satisfies Schema.Codec<
2350 ResponseMetadataPart,
2351 ResponseMetadataPartEncoded
2352>
2353
2354// =============================================================================
2355// Finish Part
2356// =============================================================================
2357
2358/**
2359 * Represents the reason why a model finished generation of a response.
2360 *
2361 * **Details**
2362 *
2363 * Possible finish reasons:
2364 * - `"stop"`: The model generated a stop sequence.
2365 * - `"length"`: The model exceeded its token budget.
2366 * - `"content-filter"`: The model generated content which violated a content filter.
2367 * - `"tool-calls"`: The model triggered a tool call.
2368 * - `"error"`: The model encountered an error.
2369 * - `"pause"`: The model requested to pause execution.
2370 * - `"other"`: The model stopped for a reason not supported by this protocol.
2371 * - `"unknown"`: The model did not specify a finish reason.
2372 *
2373 * @stability unstable
2374 * @category models
2375 * @since 4.0.0
2376 */
2377export const FinishReason: Schema.Literals<[
2378 "stop",
2379 "length",
2380 "content-filter",
2381 "tool-calls",
2382 "error",
2383 "pause",
2384 "other",
2385 "unknown"
2386]> = Schema.Literals([
2387 "stop",
2388 "length",
2389 "content-filter",
2390 "tool-calls",
2391 "error",
2392 "pause",
2393 "other",
2394 "unknown"
2395])
2396
2397/**
2398 * Type of the reason why a model stopped generating a response.
2399 *
2400 * **Details**
2401 *
2402 * Values include normal stops, token-limit stops, content filtering,
2403 * tool-call pauses, provider errors, and unknown provider-specific finish
2404 * reasons.
2405 *
2406 * @stability unstable
2407 * @category models
2408 * @since 4.0.0
2409 */
2410export type FinishReason = typeof FinishReason.Type
2411
2412/**
2413 * Represents usage information for a request to a large language model provider.
2414 *
2415 * **Details**
2416 *
2417 * If the model provider returns additional usage information than what is
2418 * specified here, you can generally find that information under the provider
2419 * metadata of the finish part of the response.
2420 *
2421 * @stability unstable
2422 * @category models
2423 * @since 4.0.0
2424 */
2425export class Usage extends Schema.Class<Usage>("effect/ai/AiResponse/Usage")({
2426 /**
2427 * Information about input (i.e. prompt) token utilization.
2428 */
2429 inputTokens: Schema.Struct({
2430 /**
2431 * The number of non-cached input (i.e. prompt) tokens used.
2432 */
2433 uncached: Schema.optional(Schema.Int),
2434 /**
2435 * The total of number of input (i.e. prompt) tokens used.
2436 */
2437 total: Schema.optional(Schema.Int),
2438 /**
2439 * The number of cached input (i.e. prompt) tokens read.
2440 */
2441 cacheRead: Schema.optional(Schema.Int),
2442 /**
2443 * The number of cached input (i.e. prompt) tokens written.
2444 */
2445 cacheWrite: Schema.optional(Schema.Int)
2446 }),
2447 /**
2448 * Information about the output (i.e. response) tokens used.
2449 */
2450 outputTokens: Schema.Struct({
2451 /**
2452 * The total of number of output (i.e. response) tokens used.
2453 */
2454 total: Schema.optional(Schema.Int),
2455 /**
2456 * The number of text tokens used.
2457 */
2458 text: Schema.optional(Schema.Int),
2459 /**
2460 * The number of reasoning tokens used.
2461 */
2462 reasoning: Schema.optional(Schema.Int)
2463 })
2464}) {}
2465
2466/**
2467 * Response part indicating the completion of a response generation.
2468 *
2469 * **Example** (Creating a finish part)
2470 *
2471 * ```ts import.meta.vitest
2472 * import { Response } from "effect/ai"
2473 *
2474 * const finishPart: Response.FinishPart = Response.makePart("finish", {
2475 * reason: "stop",
2476 * usage: new Response.Usage({
2477 * inputTokens: {
2478 * uncached: undefined,
2479 * total: 50,
2480 * cacheRead: undefined,
2481 * cacheWrite: undefined
2482 * },
2483 * outputTokens: {
2484 * total: 25,
2485 * text: undefined,
2486 * reasoning: undefined
2487 * }
2488 * }),
2489 * response: undefined
2490 * })
2491 * const result = [finishPart.reason, finishPart.usage.inputTokens.total] // => ["stop", 50]
2492 * ```
2493 *
2494 * @stability unstable
2495 * @category models
2496 * @since 4.0.0
2497 */
2498export interface FinishPart extends BasePart<"finish", FinishPartMetadata> {
2499 /**
2500 * The reason why the model finished generating the response.
2501 */
2502 readonly reason: FinishReason
2503 /**
2504 * Token usage statistics for the request.
2505 */
2506 readonly usage: Usage
2507 /**
2508 * Optional HTTP response details from the AI provider.
2509 */
2510 readonly response?: typeof HttpResponseDetails.Type | undefined
2511}
2512
2513/**
2514 * Encoded representation of finish parts for serialization.
2515 *
2516 * @stability unstable
2517 * @category models
2518 * @since 4.0.0
2519 */
2520export interface FinishPartEncoded extends BasePartEncoded<"finish", FinishPartMetadata> {
2521 /**
2522 * The reason why the model finished generating the response.
2523 */
2524 readonly reason: typeof FinishReason.Encoded
2525 /**
2526 * Token usage statistics for the request.
2527 */
2528 readonly usage: typeof Usage.Encoded
2529 /**
2530 * Optional HTTP response details from the AI provider.
2531 */
2532 readonly response?: typeof HttpResponseDetails.Encoded | undefined
2533}
2534
2535/**
2536 * Represents provider-specific metadata that can be associated with a
2537 * `FinishPart` through module augmentation.
2538 *
2539 * @stability unstable
2540 * @category configuration
2541 * @since 4.0.0
2542 */
2543export interface FinishPartMetadata extends ProviderMetadata {}
2544
2545/**
2546 * Schema for finish response parts.
2547 *
2548 * **Details**
2549 *
2550 * Validates `type: "finish"`, `reason` through `FinishReason`, `usage`
2551 * through `Usage`, and optional provider HTTP response details.
2552 *
2553 * @stability unstable
2554 * @category schemas
2555 * @since 4.0.0
2556 */
2557export const FinishPart: Schema.Struct<{
2558 readonly type: Schema.tag<"finish">
2559 readonly reason: Schema.Literals<[
2560 "stop",
2561 "length",
2562 "content-filter",
2563 "tool-calls",
2564 "error",
2565 "pause",
2566 "other",
2567 "unknown"
2568 ]>
2569 readonly usage: typeof Usage
2570 readonly response: Schema.optional<typeof HttpResponseDetails>
2571 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
2572 readonly metadata: Schema.withDecodingDefault<
2573 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
2574 >
2575}> = Schema.Struct({
2576 ...BasePart.fields,
2577 type: Schema.tag("finish"),
2578 reason: FinishReason,
2579 usage: Usage,
2580 response: Schema.optional(HttpResponseDetails)
2581}).annotate({ identifier: "FinishPart" }) satisfies Schema.Codec<FinishPart, FinishPartEncoded>
2582
2583// =============================================================================
2584// Error Part
2585// =============================================================================
2586
2587/**
2588 * Response part indicating that an error occurred generating the response.
2589 *
2590 * **Example** (Creating an error part)
2591 *
2592 * ```ts import.meta.vitest
2593 * import { Response } from "effect/ai"
2594 *
2595 * const errorPart: Response.ErrorPart = Response.makePart("error", {
2596 * error: new Error("boom")
2597 * })
2598 * const result = [errorPart.type, errorPart.error instanceof Error] // => ["error", true]
2599 * ```
2600 *
2601 * @stability unstable
2602 * @category models
2603 * @since 4.0.0
2604 */
2605export interface ErrorPart extends BasePart<"error", ErrorPartMetadata> {
2606 readonly error: unknown
2607}
2608
2609/**
2610 * Encoded representation of error parts for serialization.
2611 *
2612 * @stability unstable
2613 * @category models
2614 * @since 4.0.0
2615 */
2616export interface ErrorPartEncoded extends BasePartEncoded<"error", ErrorPartMetadata> {
2617 readonly error: unknown
2618}
2619
2620/**
2621 * Represents provider-specific metadata that can be associated with a
2622 * `ErrorPart` through module augmentation.
2623 *
2624 * @stability unstable
2625 * @category configuration
2626 * @since 4.0.0
2627 */
2628export interface ErrorPartMetadata extends ProviderMetadata {}
2629
2630/**
2631 * Schema for validation and encoding of error parts.
2632 *
2633 * **Details**
2634 *
2635 * Validates and encodes error parts with `type: "error"` and an `error` payload
2636 * kept as `unknown`.
2637 *
2638 * **Gotchas**
2639 *
2640 * The decoded `error` value is not guaranteed to be an `Error`; narrow it before
2641 * reading `Error`-specific fields.
2642 *
2643 * @stability unstable
2644 * @category schemas
2645 * @since 4.0.0
2646 */
2647export const ErrorPart: Schema.Struct<{
2648 readonly type: Schema.tag<"error">
2649 readonly error: Schema.Unknown
2650 readonly "~effect/ai/Response/Part": Schema.withDecodingDefaultKey<Schema.tag<"~effect/ai/Response/Part">>
2651 readonly metadata: Schema.withDecodingDefault<
2652 Schema.$Record<Schema.String, Schema.Codec<Schema.Json>>
2653 >
2654}> = Schema.Struct({
2655 ...BasePart.fields,
2656 type: Schema.tag("error"),
2657 error: Schema.Unknown
2658}).annotate({ identifier: "ErrorPart" }) satisfies Schema.Codec<ErrorPart, ErrorPartEncoded>