@effect/ai 0.26.1 → 0.27.1

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 (188) hide show
  1. package/Chat/package.json +6 -0
  2. package/EmbeddingModel/package.json +6 -0
  3. package/IdGenerator/package.json +6 -0
  4. package/LanguageModel/package.json +6 -0
  5. package/Model/package.json +6 -0
  6. package/Prompt/package.json +6 -0
  7. package/Response/package.json +6 -0
  8. package/Telemetry/package.json +6 -0
  9. package/Tool/package.json +6 -0
  10. package/Toolkit/package.json +6 -0
  11. package/dist/cjs/AiError.js +575 -11
  12. package/dist/cjs/AiError.js.map +1 -1
  13. package/dist/cjs/Chat.js +302 -0
  14. package/dist/cjs/Chat.js.map +1 -0
  15. package/dist/cjs/EmbeddingModel.js +184 -0
  16. package/dist/cjs/EmbeddingModel.js.map +1 -0
  17. package/dist/cjs/IdGenerator.js +255 -0
  18. package/dist/cjs/IdGenerator.js.map +1 -0
  19. package/dist/cjs/LanguageModel.js +584 -0
  20. package/dist/cjs/LanguageModel.js.map +1 -0
  21. package/dist/cjs/McpServer.js +2 -2
  22. package/dist/cjs/McpServer.js.map +1 -1
  23. package/dist/cjs/Model.js +118 -0
  24. package/dist/cjs/Model.js.map +1 -0
  25. package/dist/cjs/Prompt.js +649 -0
  26. package/dist/cjs/Prompt.js.map +1 -0
  27. package/dist/cjs/Response.js +635 -0
  28. package/dist/cjs/Response.js.map +1 -0
  29. package/dist/cjs/Telemetry.js +176 -0
  30. package/dist/cjs/Telemetry.js.map +1 -0
  31. package/dist/cjs/Tokenizer.js +87 -8
  32. package/dist/cjs/Tokenizer.js.map +1 -1
  33. package/dist/cjs/Tool.js +635 -0
  34. package/dist/cjs/Tool.js.map +1 -0
  35. package/dist/cjs/Toolkit.js +279 -0
  36. package/dist/cjs/Toolkit.js.map +1 -0
  37. package/dist/cjs/index.js +21 -19
  38. package/dist/dts/AiError.d.ts +577 -9
  39. package/dist/dts/AiError.d.ts.map +1 -1
  40. package/dist/dts/Chat.d.ts +356 -0
  41. package/dist/dts/Chat.d.ts.map +1 -0
  42. package/dist/dts/EmbeddingModel.d.ts +153 -0
  43. package/dist/dts/EmbeddingModel.d.ts.map +1 -0
  44. package/dist/dts/IdGenerator.d.ts +272 -0
  45. package/dist/dts/IdGenerator.d.ts.map +1 -0
  46. package/dist/dts/LanguageModel.d.ts +458 -0
  47. package/dist/dts/LanguageModel.d.ts.map +1 -0
  48. package/dist/dts/McpSchema.d.ts +25 -25
  49. package/dist/dts/McpServer.d.ts +4 -4
  50. package/dist/dts/McpServer.d.ts.map +1 -1
  51. package/dist/dts/Model.d.ts +124 -0
  52. package/dist/dts/Model.d.ts.map +1 -0
  53. package/dist/dts/Prompt.d.ts +1119 -0
  54. package/dist/dts/Prompt.d.ts.map +1 -0
  55. package/dist/dts/Response.d.ts +1519 -0
  56. package/dist/dts/Response.d.ts.map +1 -0
  57. package/dist/dts/Telemetry.d.ts +520 -0
  58. package/dist/dts/Telemetry.d.ts.map +1 -0
  59. package/dist/dts/Tokenizer.d.ts +131 -13
  60. package/dist/dts/Tokenizer.d.ts.map +1 -1
  61. package/dist/dts/Tool.d.ts +884 -0
  62. package/dist/dts/Tool.d.ts.map +1 -0
  63. package/dist/dts/Toolkit.d.ts +310 -0
  64. package/dist/dts/Toolkit.d.ts.map +1 -0
  65. package/dist/dts/index.d.ts +498 -13
  66. package/dist/dts/index.d.ts.map +1 -1
  67. package/dist/esm/AiError.js +570 -10
  68. package/dist/esm/AiError.js.map +1 -1
  69. package/dist/esm/Chat.js +291 -0
  70. package/dist/esm/Chat.js.map +1 -0
  71. package/dist/esm/EmbeddingModel.js +173 -0
  72. package/dist/esm/EmbeddingModel.js.map +1 -0
  73. package/dist/esm/IdGenerator.js +245 -0
  74. package/dist/esm/IdGenerator.js.map +1 -0
  75. package/dist/esm/LanguageModel.js +572 -0
  76. package/dist/esm/LanguageModel.js.map +1 -0
  77. package/dist/esm/McpServer.js +2 -2
  78. package/dist/esm/McpServer.js.map +1 -1
  79. package/dist/esm/Model.js +108 -0
  80. package/dist/esm/Model.js.map +1 -0
  81. package/dist/esm/Prompt.js +633 -0
  82. package/dist/esm/Prompt.js.map +1 -0
  83. package/dist/esm/Response.js +619 -0
  84. package/dist/esm/Response.js.map +1 -0
  85. package/dist/esm/Telemetry.js +166 -0
  86. package/dist/esm/Telemetry.js.map +1 -0
  87. package/dist/esm/Tokenizer.js +87 -8
  88. package/dist/esm/Tokenizer.js.map +1 -1
  89. package/dist/esm/Tool.js +612 -0
  90. package/dist/esm/Tool.js.map +1 -0
  91. package/dist/esm/Toolkit.js +269 -0
  92. package/dist/esm/Toolkit.js.map +1 -0
  93. package/dist/esm/index.js +498 -13
  94. package/dist/esm/index.js.map +1 -1
  95. package/package.json +76 -68
  96. package/src/AiError.ts +739 -9
  97. package/src/Chat.ts +546 -0
  98. package/src/EmbeddingModel.ts +311 -0
  99. package/src/IdGenerator.ts +320 -0
  100. package/src/LanguageModel.ts +1074 -0
  101. package/src/McpServer.ts +328 -192
  102. package/src/Model.ts +155 -0
  103. package/src/Prompt.ts +1621 -0
  104. package/src/Response.ts +2131 -0
  105. package/src/Telemetry.ts +655 -0
  106. package/src/Tokenizer.ts +145 -24
  107. package/src/Tool.ts +1361 -0
  108. package/src/Toolkit.ts +516 -0
  109. package/src/index.ts +499 -13
  110. package/AiChat/package.json +0 -6
  111. package/AiEmbeddingModel/package.json +0 -6
  112. package/AiInput/package.json +0 -6
  113. package/AiLanguageModel/package.json +0 -6
  114. package/AiModel/package.json +0 -6
  115. package/AiResponse/package.json +0 -6
  116. package/AiTelemetry/package.json +0 -6
  117. package/AiTool/package.json +0 -6
  118. package/AiToolkit/package.json +0 -6
  119. package/dist/cjs/AiChat.js +0 -122
  120. package/dist/cjs/AiChat.js.map +0 -1
  121. package/dist/cjs/AiEmbeddingModel.js +0 -109
  122. package/dist/cjs/AiEmbeddingModel.js.map +0 -1
  123. package/dist/cjs/AiInput.js +0 -458
  124. package/dist/cjs/AiInput.js.map +0 -1
  125. package/dist/cjs/AiLanguageModel.js +0 -351
  126. package/dist/cjs/AiLanguageModel.js.map +0 -1
  127. package/dist/cjs/AiModel.js +0 -37
  128. package/dist/cjs/AiModel.js.map +0 -1
  129. package/dist/cjs/AiResponse.js +0 -681
  130. package/dist/cjs/AiResponse.js.map +0 -1
  131. package/dist/cjs/AiTelemetry.js +0 -58
  132. package/dist/cjs/AiTelemetry.js.map +0 -1
  133. package/dist/cjs/AiTool.js +0 -150
  134. package/dist/cjs/AiTool.js.map +0 -1
  135. package/dist/cjs/AiToolkit.js +0 -157
  136. package/dist/cjs/AiToolkit.js.map +0 -1
  137. package/dist/cjs/internal/common.js +0 -21
  138. package/dist/cjs/internal/common.js.map +0 -1
  139. package/dist/dts/AiChat.d.ts +0 -101
  140. package/dist/dts/AiChat.d.ts.map +0 -1
  141. package/dist/dts/AiEmbeddingModel.d.ts +0 -65
  142. package/dist/dts/AiEmbeddingModel.d.ts.map +0 -1
  143. package/dist/dts/AiInput.d.ts +0 -590
  144. package/dist/dts/AiInput.d.ts.map +0 -1
  145. package/dist/dts/AiLanguageModel.d.ts +0 -302
  146. package/dist/dts/AiLanguageModel.d.ts.map +0 -1
  147. package/dist/dts/AiModel.d.ts +0 -25
  148. package/dist/dts/AiModel.d.ts.map +0 -1
  149. package/dist/dts/AiResponse.d.ts +0 -863
  150. package/dist/dts/AiResponse.d.ts.map +0 -1
  151. package/dist/dts/AiTelemetry.d.ts +0 -242
  152. package/dist/dts/AiTelemetry.d.ts.map +0 -1
  153. package/dist/dts/AiTool.d.ts +0 -334
  154. package/dist/dts/AiTool.d.ts.map +0 -1
  155. package/dist/dts/AiToolkit.d.ts +0 -96
  156. package/dist/dts/AiToolkit.d.ts.map +0 -1
  157. package/dist/dts/internal/common.d.ts +0 -2
  158. package/dist/dts/internal/common.d.ts.map +0 -1
  159. package/dist/esm/AiChat.js +0 -111
  160. package/dist/esm/AiChat.js.map +0 -1
  161. package/dist/esm/AiEmbeddingModel.js +0 -98
  162. package/dist/esm/AiEmbeddingModel.js.map +0 -1
  163. package/dist/esm/AiInput.js +0 -433
  164. package/dist/esm/AiInput.js.map +0 -1
  165. package/dist/esm/AiLanguageModel.js +0 -340
  166. package/dist/esm/AiLanguageModel.js.map +0 -1
  167. package/dist/esm/AiModel.js +0 -29
  168. package/dist/esm/AiModel.js.map +0 -1
  169. package/dist/esm/AiResponse.js +0 -657
  170. package/dist/esm/AiResponse.js.map +0 -1
  171. package/dist/esm/AiTelemetry.js +0 -48
  172. package/dist/esm/AiTelemetry.js.map +0 -1
  173. package/dist/esm/AiTool.js +0 -134
  174. package/dist/esm/AiTool.js.map +0 -1
  175. package/dist/esm/AiToolkit.js +0 -147
  176. package/dist/esm/AiToolkit.js.map +0 -1
  177. package/dist/esm/internal/common.js +0 -14
  178. package/dist/esm/internal/common.js.map +0 -1
  179. package/src/AiChat.ts +0 -251
  180. package/src/AiEmbeddingModel.ts +0 -169
  181. package/src/AiInput.ts +0 -602
  182. package/src/AiLanguageModel.ts +0 -685
  183. package/src/AiModel.ts +0 -53
  184. package/src/AiResponse.ts +0 -986
  185. package/src/AiTelemetry.ts +0 -333
  186. package/src/AiTool.ts +0 -579
  187. package/src/AiToolkit.ts +0 -265
  188. package/src/internal/common.ts +0 -12
package/src/Prompt.ts ADDED
@@ -0,0 +1,1621 @@
1
+ /**
2
+ * The `Prompt` module provides several data structures to simplify creating and
3
+ * combining prompts.
4
+ *
5
+ * This module defines the complete structure of a conversation with a large
6
+ * language model, including messages, content parts, and provider-specific
7
+ * options. It supports rich content types like text, files, tool calls, and
8
+ * reasoning.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { Prompt } from "@effect/ai"
13
+ *
14
+ * // Create a structured conversation
15
+ * const conversation = Prompt.make([
16
+ * {
17
+ * role: "system",
18
+ * content: "You are a helpful assistant specialized in mathematics."
19
+ * },
20
+ * {
21
+ * role: "user",
22
+ * content: [{
23
+ * type: "text",
24
+ * text: "What is the derivative of x²?"
25
+ * }]
26
+ * },
27
+ * {
28
+ * role: "assistant",
29
+ * content: [{
30
+ * type: "text",
31
+ * text: "The derivative of x² is 2x."
32
+ * }]
33
+ * }
34
+ * ])
35
+ * ```
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { Prompt } from "@effect/ai"
40
+ *
41
+ * // Merge multiple prompts
42
+ * const systemPrompt = Prompt.make([{
43
+ * role: "system",
44
+ * content: "You are a coding assistant."
45
+ * }])
46
+ *
47
+ * const userPrompt = Prompt.make("Help me write a function")
48
+ *
49
+ * const combined = Prompt.merge(systemPrompt, userPrompt)
50
+ * ```
51
+ *
52
+ * @since 1.0.0
53
+ */
54
+ import { constFalse, dual } from "effect/Function"
55
+ import * as Predicate from "effect/Predicate"
56
+ import * as Schema from "effect/Schema"
57
+ import type * as Response from "./Response.js"
58
+
59
+ const constEmptyObject = () => ({})
60
+
61
+ // =============================================================================
62
+ // Options
63
+ // =============================================================================
64
+
65
+ /**
66
+ * Schema for provider-specific options which can be attached to both content
67
+ * parts and messages, enabling provider-specific behavior.
68
+ *
69
+ * Provider-specific options are namespaced by provider and have the structure:
70
+ *
71
+ * ```
72
+ * {
73
+ * "<provider-specific-key>": {
74
+ * // Provider-specific options
75
+ * }
76
+ * }
77
+ * ```
78
+ *
79
+ * @since 1.0.0
80
+ * @category Models
81
+ */
82
+ export const ProviderOptions = Schema.Record({
83
+ key: Schema.String,
84
+ value: Schema.UndefinedOr(
85
+ Schema.Record({
86
+ key: Schema.String,
87
+ value: Schema.Unknown
88
+ })
89
+ )
90
+ })
91
+
92
+ /**
93
+ * @since 1.0.0
94
+ * @category Models
95
+ */
96
+ export type ProviderOptions = typeof ProviderOptions.Type
97
+
98
+ // =============================================================================
99
+ // Base Part
100
+ // =============================================================================
101
+
102
+ /**
103
+ * Unique identifier for Part instances.
104
+ *
105
+ * @since 1.0.0
106
+ * @category Type Ids
107
+ */
108
+ export const PartTypeId = "~effect/ai/Prompt/Part"
109
+
110
+ /**
111
+ * Type-level representation of the Part identifier.
112
+ *
113
+ * @since 1.0.0
114
+ * @category Type Ids
115
+ */
116
+ export type PartTypeId = typeof PartTypeId
117
+
118
+ /**
119
+ * Type guard to check if a value is a Part.
120
+ *
121
+ * @since 1.0.0
122
+ * @category Guards
123
+ */
124
+ export const isPart = (u: unknown): u is Part => Predicate.hasProperty(u, PartTypeId)
125
+
126
+ /**
127
+ * Union type representing all possible content parts within messages.
128
+ *
129
+ * Parts are the building blocks of message content, supporting text, files,
130
+ * reasoning, tool calls, and tool results.
131
+ *
132
+ * @since 1.0.0
133
+ * @category Models
134
+ */
135
+ export type Part = TextPart | ReasoningPart | FilePart | ToolCallPart | ToolResultPart
136
+
137
+ /**
138
+ * Encoded representation of a Part.
139
+ *
140
+ * @since 1.0.0
141
+ * @category Models
142
+ */
143
+ export type PartEncoded =
144
+ | TextPartEncoded
145
+ | ReasoningPartEncoded
146
+ | FilePartEncoded
147
+ | ToolCallPartEncoded
148
+ | ToolResultPartEncoded
149
+
150
+ /**
151
+ * Base interface for all content parts.
152
+ *
153
+ * Provides common structure including type and provider options.
154
+ *
155
+ * @since 1.0.0
156
+ * @category Models
157
+ */
158
+ export interface BasePart<Type extends string, Options extends ProviderOptions> {
159
+ readonly [PartTypeId]: PartTypeId
160
+ /**
161
+ * The type of this content part.
162
+ */
163
+ readonly type: Type
164
+ /**
165
+ * Provider-specific options for this part.
166
+ */
167
+ readonly options: Options
168
+ }
169
+
170
+ /**
171
+ * Base interface for encoded content parts.
172
+ *
173
+ * @since 1.0.0
174
+ * @category Models
175
+ */
176
+ export interface BasePartEncoded<Type extends string, Options extends ProviderOptions> {
177
+ /**
178
+ * The type of this content part.
179
+ */
180
+ readonly type: Type
181
+ /**
182
+ * Provider-specific options for this part.
183
+ */
184
+ readonly options?: Options | undefined
185
+ }
186
+
187
+ /**
188
+ * Creates a new content part of the specified type.
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * import { Prompt } from "@effect/ai"
193
+ *
194
+ * const textPart = Prompt.makePart("text", {
195
+ * text: "Hello, world!"
196
+ * })
197
+ *
198
+ * const filePart = Prompt.makePart("file", {
199
+ * mediaType: "image/png",
200
+ * fileName: "screenshot.png",
201
+ * data: new Uint8Array([1, 2, 3])
202
+ * })
203
+ * ```
204
+ *
205
+ * @since 1.0.0
206
+ * @category Constructors
207
+ */
208
+ export const makePart = <const Type extends Part["type"]>(
209
+ /**
210
+ * The type of part to create.
211
+ */
212
+ type: Type,
213
+ /**
214
+ * Parameters specific to the part type being created.
215
+ */
216
+ params: Omit<Extract<Part, { type: Type }>, PartTypeId | "type" | "options"> & {
217
+ /**
218
+ * Optional provider-specific options for this part.
219
+ */
220
+ readonly options?: Extract<Part, { type: Type }>["options"] | undefined
221
+ }
222
+ ): Extract<Part, { type: Type }> =>
223
+ (({
224
+ ...params,
225
+ [PartTypeId]: PartTypeId,
226
+ type,
227
+ options: params.options ?? {}
228
+ }) as any)
229
+
230
+ // =============================================================================
231
+ // Text Part
232
+ // =============================================================================
233
+
234
+ /**
235
+ * Content part representing plain text.
236
+ *
237
+ * The most basic content type used for textual information in messages.
238
+ *
239
+ * @example
240
+ * ```ts
241
+ * import { Prompt } from "@effect/ai"
242
+ *
243
+ * const textPart: Prompt.TextPart = Prompt.makePart("text", {
244
+ * text: "Hello, how can I help you today?",
245
+ * })
246
+ * ```
247
+ *
248
+ * @since 1.0.0
249
+ * @category Models
250
+ */
251
+ export interface TextPart extends BasePart<"text", TextPartOptions> {
252
+ /**
253
+ * The text content.
254
+ */
255
+ readonly text: string
256
+ }
257
+
258
+ /**
259
+ * Encoded representation of text parts for serialization.
260
+ *
261
+ * @since 1.0.0
262
+ * @category Models
263
+ */
264
+ export interface TextPartEncoded extends BasePartEncoded<"text", TextPartOptions> {
265
+ /**
266
+ * The text content.
267
+ */
268
+ readonly text: string
269
+ }
270
+
271
+ /**
272
+ * Represents provider-specific options that can be associated with a
273
+ * `TextPart` through module augmentation.
274
+ *
275
+ * @since 1.0.0
276
+ * @category ProviderOptions
277
+ */
278
+ export interface TextPartOptions extends ProviderOptions {}
279
+
280
+ /**
281
+ * Schema for validation and encoding of text parts.
282
+ *
283
+ * @since 1.0.0
284
+ * @category Schemas
285
+ */
286
+ export const TextPart: Schema.Schema<TextPart, TextPartEncoded> = Schema.Struct({
287
+ type: Schema.Literal("text"),
288
+ text: Schema.String,
289
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
290
+ }).pipe(
291
+ Schema.attachPropertySignature(PartTypeId, PartTypeId),
292
+ Schema.annotations({ identifier: "TextPart" })
293
+ )
294
+
295
+ // =============================================================================
296
+ // Reasoning Part
297
+ // =============================================================================
298
+
299
+ /**
300
+ * Content part representing reasoning or chain-of-thought.
301
+ *
302
+ * @example
303
+ * ```ts
304
+ * import { Prompt } from "@effect/ai"
305
+ *
306
+ * const reasoningPart: Prompt.ReasoningPart = Prompt.makePart("reasoning", {
307
+ * text: "Let me think step by step: First I need to understand the user's question...",
308
+ * })
309
+ * ```
310
+ *
311
+ * @since 1.0.0
312
+ * @category Models
313
+ */
314
+ export interface ReasoningPart extends BasePart<"reasoning", ReasoningPartOptions> {
315
+ /**
316
+ * The reasoning or thought process text.
317
+ */
318
+ readonly text: string
319
+ }
320
+
321
+ /**
322
+ * Encoded representation of reasoning parts for serialization.
323
+ *
324
+ * @since 1.0.0
325
+ * @category Models
326
+ */
327
+ export interface ReasoningPartEncoded extends BasePartEncoded<"reasoning", ReasoningPartOptions> {
328
+ /**
329
+ * The reasoning or thought process text.
330
+ */
331
+ readonly text: string
332
+ }
333
+
334
+ /**
335
+ * Represents provider-specific options that can be associated with a
336
+ * `ReasoningPart` through module augmentation.
337
+ *
338
+ * @since 1.0.0
339
+ * @category ProviderOptions
340
+ */
341
+ export interface ReasoningPartOptions extends ProviderOptions {}
342
+
343
+ /**
344
+ * Schema for validation and encoding of reasoning parts.
345
+ *
346
+ * @since 1.0.0
347
+ * @category Schemas
348
+ */
349
+ export const ReasoningPart: Schema.Schema<ReasoningPart, ReasoningPartEncoded> = Schema.Struct({
350
+ type: Schema.Literal("reasoning"),
351
+ text: Schema.String,
352
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
353
+ }).pipe(
354
+ Schema.attachPropertySignature(PartTypeId, PartTypeId),
355
+ Schema.annotations({ identifier: "ReasoningPart" })
356
+ )
357
+
358
+ // =============================================================================
359
+ // File Part
360
+ // =============================================================================
361
+
362
+ /**
363
+ * Content part representing a file attachment. Files can be provided as base64
364
+ * strings of data, byte arrays, or URLs.
365
+ *
366
+ * Supports various file types including images, documents, and binary data.
367
+ *
368
+ * @example
369
+ * ```ts
370
+ * import { Prompt } from "@effect/ai"
371
+ *
372
+ * const imagePart: Prompt.FilePart = Prompt.makePart("file", {
373
+ * mediaType: "image/jpeg",
374
+ * fileName: "photo.jpg",
375
+ * data: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
376
+ * })
377
+ *
378
+ * const documentPart: Prompt.FilePart = Prompt.makePart("file", {
379
+ * mediaType: "application/pdf",
380
+ * fileName: "report.pdf",
381
+ * data: new Uint8Array([1, 2, 3])
382
+ * })
383
+ * ```
384
+ *
385
+ * @since 1.0.0
386
+ * @category Models
387
+ */
388
+ export interface FilePart extends BasePart<"file", FilePartOptions> {
389
+ /**
390
+ * MIME type of the file (e.g., "image/jpeg", "application/pdf").
391
+ */
392
+ readonly mediaType: string
393
+ /**
394
+ * Optional filename for the file.
395
+ */
396
+ readonly fileName?: string | undefined
397
+ /**
398
+ * File data as base64 string of data, a byte array, or a URL.
399
+ */
400
+ readonly data: string | Uint8Array | URL
401
+ }
402
+
403
+ /**
404
+ * Encoded representation of file parts for serialization.
405
+ *
406
+ * @since 1.0.0
407
+ * @category Models
408
+ */
409
+ export interface FilePartEncoded extends BasePartEncoded<"file", FilePartOptions> {
410
+ /**
411
+ * MIME type of the file (e.g., "image/jpeg", "application/pdf").
412
+ */
413
+ readonly mediaType: string
414
+ /**
415
+ * Optional filename for the file.
416
+ */
417
+ readonly fileName?: string | undefined
418
+ /**
419
+ * File data as base64 string of data, a byte array, or a URL.
420
+ */
421
+ readonly data: string | Uint8Array | URL
422
+ }
423
+
424
+ /**
425
+ * Represents provider-specific options that can be associated with a
426
+ * `FilePart` through module augmentation.
427
+ *
428
+ * @since 1.0.0
429
+ * @category ProviderOptions
430
+ */
431
+ export interface FilePartOptions extends ProviderOptions {}
432
+
433
+ /**
434
+ * Schema for validation and encoding of file parts.
435
+ *
436
+ * @since 1.0.0
437
+ * @category Schemas
438
+ */
439
+ export const FilePart: Schema.Schema<FilePart, FilePartEncoded> = Schema.Struct({
440
+ type: Schema.Literal("file"),
441
+ mediaType: Schema.String,
442
+ fileName: Schema.optional(Schema.String),
443
+ data: Schema.Union(Schema.String, Schema.Uint8ArrayFromSelf, Schema.URLFromSelf),
444
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
445
+ }).pipe(
446
+ Schema.attachPropertySignature(PartTypeId, PartTypeId),
447
+ Schema.annotations({ identifier: "FilePart" })
448
+ )
449
+
450
+ // =============================================================================
451
+ // Tool Call Part
452
+ // =============================================================================
453
+
454
+ /**
455
+ * Content part representing a tool call request.
456
+ *
457
+ * @example
458
+ * ```ts
459
+ * import { Prompt } from "@effect/ai"
460
+ *
461
+ * const toolCallPart: Prompt.ToolCallPart = Prompt.makePart("tool-call", {
462
+ * id: "call_123",
463
+ * name: "get_weather",
464
+ * params: { city: "San Francisco", units: "celsius" },
465
+ * providerExecuted: false,
466
+ * })
467
+ * ```
468
+ *
469
+ * @since 1.0.0
470
+ * @category Models
471
+ */
472
+ export interface ToolCallPart extends BasePart<"tool-call", ToolCallPartOptions> {
473
+ /**
474
+ * Unique identifier for this tool call.
475
+ */
476
+ readonly id: string
477
+ /**
478
+ * Name of the tool to invoke.
479
+ */
480
+ readonly name: string
481
+ /**
482
+ * Parameters to pass to the tool.
483
+ */
484
+ readonly params: unknown
485
+ /**
486
+ * Whether the tool was executed by the provider (true) or framework (false).
487
+ */
488
+ readonly providerExecuted: boolean
489
+ }
490
+
491
+ /**
492
+ * Encoded representation of tool call parts for serialization.
493
+ *
494
+ * @since 1.0.0
495
+ * @category Models
496
+ */
497
+ export interface ToolCallPartEncoded extends BasePartEncoded<"tool-call", ToolCallPartOptions> {
498
+ /**
499
+ * Unique identifier for this tool call.
500
+ */
501
+ readonly id: string
502
+ /**
503
+ * Name of the tool to invoke.
504
+ */
505
+ readonly name: string
506
+ /**
507
+ * Parameters to pass to the tool.
508
+ */
509
+ readonly params: unknown
510
+ /**
511
+ * Whether the tool was executed by the provider (true) or framework (false).
512
+ */
513
+ readonly providerExecuted?: boolean | undefined
514
+ }
515
+
516
+ /**
517
+ * Represents provider-specific options that can be associated with a
518
+ * `ToolCallPart` through module augmentation.
519
+ *
520
+ * @since 1.0.0
521
+ * @category ProviderOptions
522
+ */
523
+ export interface ToolCallPartOptions extends ProviderOptions {}
524
+
525
+ /**
526
+ * Schema for validation and encoding of tool call parts.
527
+ *
528
+ * @since 1.0.0
529
+ * @category Schemas
530
+ */
531
+ export const ToolCallPart: Schema.Schema<ToolCallPart, ToolCallPartEncoded> = Schema.Struct({
532
+ type: Schema.Literal("tool-call"),
533
+ id: Schema.String,
534
+ name: Schema.String,
535
+ params: Schema.Unknown,
536
+ providerExecuted: Schema.optionalWith(Schema.Boolean, { default: constFalse }),
537
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
538
+ }).pipe(
539
+ Schema.attachPropertySignature(PartTypeId, PartTypeId),
540
+ Schema.annotations({ identifier: "ToolCallPart" })
541
+ )
542
+
543
+ // =============================================================================
544
+ // Tool Result Part
545
+ // =============================================================================
546
+
547
+ /**
548
+ * Content part representing the result of a tool call.
549
+ *
550
+ * @example
551
+ * ```ts
552
+ * import { Prompt } from "@effect/ai"
553
+ *
554
+ * const toolResultPart: Prompt.ToolResultPart = Prompt.makePart("tool-result", {
555
+ * id: "call_123",
556
+ * name: "get_weather",
557
+ * result: {
558
+ * temperature: 22,
559
+ * condition: "sunny",
560
+ * humidity: 65
561
+ * }
562
+ * })
563
+ * ```
564
+ *
565
+ * @since 1.0.0
566
+ * @category Models
567
+ */
568
+ export interface ToolResultPart extends BasePart<"tool-result", ToolResultPartOptions> {
569
+ /**
570
+ * Unique identifier matching the original tool call.
571
+ */
572
+ readonly id: string
573
+ /**
574
+ * Name of the tool that was executed.
575
+ */
576
+ readonly name: string
577
+ /**
578
+ * The result returned by the tool execution.
579
+ */
580
+ readonly result: unknown
581
+ }
582
+
583
+ /**
584
+ * Encoded representation of tool result parts for serialization.
585
+ *
586
+ * @since 1.0.0
587
+ * @category Models
588
+ */
589
+ export interface ToolResultPartEncoded extends BasePartEncoded<"tool-result", ToolResultPartOptions> {
590
+ /**
591
+ * Unique identifier matching the original tool call.
592
+ */
593
+ readonly id: string
594
+ /**
595
+ * Name of the tool that was executed.
596
+ */
597
+ readonly name: string
598
+ /**
599
+ * The result returned by the tool execution.
600
+ */
601
+ readonly result: unknown
602
+ }
603
+
604
+ /**
605
+ * Represents provider-specific options that can be associated with a
606
+ * `ToolResultPart` through module augmentation.
607
+ *
608
+ * @since 1.0.0
609
+ * @category ProviderOptions
610
+ */
611
+ export interface ToolResultPartOptions extends ProviderOptions {}
612
+
613
+ /**
614
+ * Schema for validation and encoding of tool result parts.
615
+ *
616
+ * @since 1.0.0
617
+ * @category Schemas
618
+ */
619
+ export const ToolResultPart: Schema.Schema<ToolResultPart, ToolResultPartEncoded> = Schema.Struct({
620
+ type: Schema.Literal("tool-result"),
621
+ id: Schema.String,
622
+ name: Schema.String,
623
+ result: Schema.Unknown,
624
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
625
+ }).pipe(
626
+ Schema.attachPropertySignature(PartTypeId, PartTypeId),
627
+ Schema.annotations({ identifier: "ToolResultPart" })
628
+ )
629
+
630
+ // =============================================================================
631
+ // Base Message
632
+ // =============================================================================
633
+
634
+ /**
635
+ * Unique identifier for Message instances.
636
+ *
637
+ * @since 1.0.0
638
+ * @category Type Ids
639
+ */
640
+ export const MessageTypeId = "~effect/ai/Prompt/Message"
641
+
642
+ /**
643
+ * Type-level representation of the Message identifier.
644
+ *
645
+ * @since 1.0.0
646
+ * @category Type Ids
647
+ */
648
+ export type MessageTypeId = typeof MessageTypeId
649
+
650
+ /**
651
+ * Type guard to check if a value is a Message.
652
+ *
653
+ * @since 1.0.0
654
+ * @category Guards
655
+ */
656
+ export const isMessage = (u: unknown): u is Message => Predicate.hasProperty(u, MessageTypeId)
657
+
658
+ /**
659
+ * Base interface for all message types.
660
+ *
661
+ * Provides common structure including role and provider options.
662
+ *
663
+ * @since 1.0.0
664
+ * @category Models
665
+ */
666
+ export interface BaseMessage<Role extends string, Options extends ProviderOptions> {
667
+ readonly [MessageTypeId]: MessageTypeId
668
+ /**
669
+ * The role of the message participant.
670
+ */
671
+ readonly role: Role
672
+ /**
673
+ * Provider-specific options for this message.
674
+ */
675
+ readonly options: Options
676
+ }
677
+
678
+ /**
679
+ * Base interface for encoded message types.
680
+ *
681
+ * @template Role - String literal type for the message role
682
+ *
683
+ * @since 1.0.0
684
+ * @category Models
685
+ */
686
+ export interface BaseMessageEncoded<Role extends string, Options extends ProviderOptions> {
687
+ /**
688
+ * The role of the message participant.
689
+ */
690
+ readonly role: Role
691
+ /**
692
+ * Provider-specific options for this message.
693
+ */
694
+ readonly options?: Options | undefined
695
+ }
696
+
697
+ /**
698
+ * Creates a new message with the specified role.
699
+ *
700
+ * @example
701
+ * ```ts
702
+ * import { Prompt } from "@effect/ai"
703
+ *
704
+ * const textPart = Prompt.makePart("text", {
705
+ * text: "Hello, world!"
706
+ * })
707
+ *
708
+ * const filePart = Prompt.makeMessage("user", {
709
+ * content: [textPart]
710
+ * })
711
+ * ```
712
+ *
713
+ * @since 1.0.0
714
+ * @category Constructors
715
+ */
716
+ export const makeMessage = <const Role extends Message["role"]>(
717
+ role: Role,
718
+ params: Omit<Extract<Message, { role: Role }>, MessageTypeId | "role" | "options"> & {
719
+ readonly options?: Extract<Message, { role: Role }>["options"]
720
+ }
721
+ ): Extract<Message, { role: Role }> =>
722
+ (({
723
+ ...params,
724
+ [MessageTypeId]: MessageTypeId,
725
+ role,
726
+ options: params.options ?? {}
727
+ }) as any)
728
+
729
+ // =============================================================================
730
+ // System Message
731
+ // =============================================================================
732
+
733
+ /**
734
+ * Message representing system instructions or context.
735
+ *
736
+ * @example
737
+ * ```ts
738
+ * import { Prompt } from "@effect/ai"
739
+ *
740
+ * const systemMessage: Prompt.SystemMessage = Prompt.makeMessage("system", {
741
+ * content: "You are a helpful assistant specialized in mathematics. " +
742
+ * "Always show your work step by step."
743
+ * })
744
+ * ```
745
+ *
746
+ * @since 1.0.0
747
+ * @category Models
748
+ */
749
+ export interface SystemMessage extends BaseMessage<"system", SystemMessageOptions> {
750
+ /**
751
+ * The system instruction or context as plain text.
752
+ */
753
+ readonly content: string
754
+ }
755
+
756
+ /**
757
+ * Encoded representation of system messages for serialization.
758
+ *
759
+ * @since 1.0.0
760
+ * @category Models
761
+ */
762
+ export interface SystemMessageEncoded extends BaseMessageEncoded<"system", SystemMessageOptions> {
763
+ /**
764
+ * The system instruction or context as plain text.
765
+ */
766
+ readonly content: string
767
+ }
768
+
769
+ /**
770
+ * Represents provider-specific options that can be associated with a
771
+ * `SystemMessage` through module augmentation.
772
+ *
773
+ * @since 1.0.0
774
+ * @category ProviderOptions
775
+ */
776
+ export interface SystemMessageOptions extends ProviderOptions {}
777
+
778
+ /**
779
+ * Schema for validation and encoding of system messages.
780
+ *
781
+ * @since 1.0.0
782
+ * @category Schemas
783
+ */
784
+ export const SystemMessage: Schema.Schema<SystemMessage, SystemMessageEncoded> = Schema.Struct({
785
+ role: Schema.Literal("system"),
786
+ content: Schema.String,
787
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
788
+ }).pipe(
789
+ Schema.attachPropertySignature(MessageTypeId, MessageTypeId),
790
+ Schema.annotations({ identifier: "SystemMessage" })
791
+ )
792
+
793
+ // =============================================================================
794
+ // User Message
795
+ // =============================================================================
796
+
797
+ /**
798
+ * Message representing user input or questions.
799
+ *
800
+ * @example
801
+ * ```ts
802
+ * import { Prompt } from "@effect/ai"
803
+ *
804
+ * const textUserMessage: Prompt.UserMessage = Prompt.makeMessage("user", {
805
+ * content: [
806
+ * Prompt.makePart("text", {
807
+ * text: "Can you analyze this image for me?"
808
+ * })
809
+ * ]
810
+ * })
811
+ *
812
+ * const multimodalUserMessage: Prompt.UserMessage = Prompt.makeMessage("user", {
813
+ * content: [
814
+ * Prompt.makePart("text", {
815
+ * text: "What do you see in this image?"
816
+ * }),
817
+ * Prompt.makePart("file", {
818
+ * mediaType: "image/jpeg",
819
+ * fileName: "vacation.jpg",
820
+ * data: "data:image/jpeg;base64,..."
821
+ * })
822
+ * ]
823
+ * })
824
+ * ```
825
+ *
826
+ * @since 1.0.0
827
+ * @category Models
828
+ */
829
+ export interface UserMessage extends BaseMessage<"user", UserMessageOptions> {
830
+ /**
831
+ * Array of content parts that make up the user's message.
832
+ */
833
+ readonly content: ReadonlyArray<UserMessagePart>
834
+ }
835
+
836
+ /**
837
+ * Union type of content parts allowed in user messages.
838
+ *
839
+ * @since 1.0.0
840
+ * @category Models
841
+ */
842
+ export type UserMessagePart = TextPart | FilePart
843
+
844
+ /**
845
+ * Encoded representation of user messages for serialization.
846
+ *
847
+ * @since 1.0.0
848
+ * @category Models
849
+ */
850
+ export interface UserMessageEncoded extends BaseMessageEncoded<"user", UserMessageOptions> {
851
+ /**
852
+ * Array of content parts that make up the user's message.
853
+ */
854
+ readonly content: ReadonlyArray<UserMessagePartEncoded>
855
+ }
856
+
857
+ /**
858
+ * Union type of encoded content parts for user messages.
859
+ *
860
+ * @since 1.0.0
861
+ * @category Models
862
+ */
863
+ export type UserMessagePartEncoded = TextPartEncoded | FilePartEncoded
864
+
865
+ /**
866
+ * Represents provider-specific options that can be associated with a
867
+ * `UserMessage` through module augmentation.
868
+ *
869
+ * @since 1.0.0
870
+ * @category ProviderOptions
871
+ */
872
+ export interface UserMessageOptions extends ProviderOptions {}
873
+
874
+ /**
875
+ * Schema for validation and encoding of user messages.
876
+ *
877
+ * @since 1.0.0
878
+ * @category Schemas
879
+ */
880
+ export const UserMessage: Schema.Schema<UserMessage, UserMessageEncoded> = Schema.Struct({
881
+ role: Schema.Literal("user"),
882
+ content: Schema.Array(Schema.Union(TextPart, FilePart)),
883
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
884
+ }).pipe(
885
+ Schema.attachPropertySignature(MessageTypeId, MessageTypeId),
886
+ Schema.annotations({ identifier: "UserMessage" })
887
+ )
888
+
889
+ // =============================================================================
890
+ // Assistant Message
891
+ // =============================================================================
892
+
893
+ /**
894
+ * Message representing large language model assistant responses.
895
+ *
896
+ * @example
897
+ * ```ts
898
+ * import { Prompt } from "@effect/ai"
899
+ *
900
+ * const assistantMessage: Prompt.AssistantMessage = Prompt.makeMessage("assistant", {
901
+ * content: [
902
+ * Prompt.makePart("text", {
903
+ * text: "The user is asking about the weather. I should use the weather tool."
904
+ * }),
905
+ * Prompt.makePart("tool-call", {
906
+ * id: "call_123",
907
+ * name: "get_weather",
908
+ * params: { city: "San Francisco" },
909
+ * providerExecuted: false
910
+ * }),
911
+ * Prompt.makePart("tool-result", {
912
+ * id: "call_123",
913
+ * name: "get_weather",
914
+ * result: { temperature: 72, condition: "sunny" }
915
+ * }),
916
+ * Prompt.makePart("text", {
917
+ * text: "The weather in San Francisco is currently 72°F and sunny."
918
+ * })
919
+ * ]
920
+ * })
921
+ * ```
922
+ *
923
+ * @since 1.0.0
924
+ * @category Models
925
+ */
926
+ export interface AssistantMessage extends BaseMessage<"assistant", AssistantMessageOptions> {
927
+ /**
928
+ * Array of content parts that make up the assistant's response.
929
+ */
930
+ readonly content: ReadonlyArray<AssistantMessagePart>
931
+ }
932
+
933
+ /**
934
+ * Union type of content parts allowed in assistant messages.
935
+ *
936
+ * @since 1.0.0
937
+ * @category Models
938
+ */
939
+ export type AssistantMessagePart =
940
+ | TextPart
941
+ | FilePart
942
+ | ReasoningPart
943
+ | ToolCallPart
944
+ | ToolResultPart
945
+
946
+ /**
947
+ * Encoded representation of assistant messages for serialization.
948
+ *
949
+ * @since 1.0.0
950
+ * @category Models
951
+ */
952
+ export interface AssistantMessageEncoded extends BaseMessageEncoded<"assistant", AssistantMessageOptions> {
953
+ readonly content: ReadonlyArray<AssistantMessagePartEncoded>
954
+ }
955
+
956
+ /**
957
+ * Union type of encoded content parts for assistant messages.
958
+ *
959
+ * @since 1.0.0
960
+ * @category Models
961
+ */
962
+ export type AssistantMessagePartEncoded =
963
+ | TextPartEncoded
964
+ | FilePartEncoded
965
+ | ReasoningPartEncoded
966
+ | ToolCallPartEncoded
967
+ | ToolResultPartEncoded
968
+
969
+ /**
970
+ * Represents provider-specific options that can be associated with a
971
+ * `AssistantMessage` through module augmentation.
972
+ *
973
+ * @since 1.0.0
974
+ * @category ProviderOptions
975
+ */
976
+ export interface AssistantMessageOptions extends ProviderOptions {}
977
+
978
+ /**
979
+ * Schema for validation and encoding of assistant messages.
980
+ *
981
+ * @since 1.0.0
982
+ * @category Schemas
983
+ */
984
+ export const AssistantMessage: Schema.Schema<AssistantMessage, AssistantMessageEncoded> = Schema.Struct({
985
+ role: Schema.Literal("assistant"),
986
+ content: Schema.Array(Schema.Union(TextPart, FilePart, ReasoningPart, ToolCallPart, ToolResultPart)),
987
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
988
+ }).pipe(
989
+ Schema.attachPropertySignature(MessageTypeId, MessageTypeId),
990
+ Schema.annotations({ identifier: "AssistantMessage" })
991
+ )
992
+
993
+ // =============================================================================
994
+ // Tool Message
995
+ // =============================================================================
996
+
997
+ /**
998
+ * Message representing tool execution results.
999
+ *
1000
+ * @example
1001
+ * ```ts
1002
+ * import { Prompt } from "@effect/ai"
1003
+ *
1004
+ * const toolMessage: Prompt.ToolMessage = Prompt.makeMessage("tool", {
1005
+ * content: [
1006
+ * Prompt.makePart("tool-result", {
1007
+ * id: "call_123",
1008
+ * name: "search_web",
1009
+ * result: {
1010
+ * query: "TypeScript best practices",
1011
+ * results: [
1012
+ * { title: "TypeScript Handbook", url: "https://..." },
1013
+ * { title: "Effective TypeScript", url: "https://..." }
1014
+ * ]
1015
+ * }
1016
+ * })
1017
+ * ]
1018
+ * })
1019
+ * ```
1020
+ *
1021
+ * @since 1.0.0
1022
+ * @category Models
1023
+ */
1024
+ export interface ToolMessage extends BaseMessage<"tool", ToolMessageOptions> {
1025
+ /**
1026
+ * Array of tool result parts.
1027
+ */
1028
+ readonly content: ReadonlyArray<ToolMessagePart>
1029
+ }
1030
+
1031
+ /**
1032
+ * Union type of content parts allowed in tool messages.
1033
+ *
1034
+ * @since 1.0.0
1035
+ * @category Models
1036
+ */
1037
+ export type ToolMessagePart = ToolResultPart
1038
+
1039
+ /**
1040
+ * Encoded representation of tool messages for serialization.
1041
+ *
1042
+ * @since 1.0.0
1043
+ * @category Models
1044
+ */
1045
+ export interface ToolMessageEncoded extends BaseMessageEncoded<"tool", ToolMessageOptions> {
1046
+ /**
1047
+ * Array of tool result parts.
1048
+ */
1049
+ readonly content: ReadonlyArray<ToolMessagePartEncoded>
1050
+ }
1051
+
1052
+ /**
1053
+ * Union type of encoded content parts for tool messages.
1054
+ *
1055
+ * @since 1.0.0
1056
+ * @category Models
1057
+ */
1058
+ export type ToolMessagePartEncoded = ToolResultPartEncoded
1059
+
1060
+ /**
1061
+ * Represents provider-specific options that can be associated with a
1062
+ * `ToolMessage` through module augmentation.
1063
+ *
1064
+ * @since 1.0.0
1065
+ * @category ProviderOptions
1066
+ */
1067
+ export interface ToolMessageOptions extends ProviderOptions {}
1068
+
1069
+ /**
1070
+ * Schema for validation and encoding of tool messages.
1071
+ *
1072
+ * @since 1.0.0
1073
+ * @category Schemas
1074
+ */
1075
+ export const ToolMessage: Schema.Schema<ToolMessage, ToolMessageEncoded> = Schema.Struct({
1076
+ role: Schema.Literal("tool"),
1077
+ content: Schema.Array(ToolResultPart),
1078
+ options: Schema.optionalWith(ProviderOptions, { default: constEmptyObject })
1079
+ }).pipe(
1080
+ Schema.attachPropertySignature(MessageTypeId, MessageTypeId),
1081
+ Schema.annotations({ identifier: "ToolMessage" })
1082
+ )
1083
+
1084
+ // =============================================================================
1085
+ // Message
1086
+ // =============================================================================
1087
+
1088
+ /**
1089
+ * A type representing all possible message types in a conversation.
1090
+ *
1091
+ * @since 1.0.0
1092
+ * @category Models
1093
+ */
1094
+ export type Message =
1095
+ | SystemMessage
1096
+ | UserMessage
1097
+ | AssistantMessage
1098
+ | ToolMessage
1099
+
1100
+ /**
1101
+ * A type representing all possible encoded message types for serialization.
1102
+ *
1103
+ * @since 1.0.0
1104
+ * @category Models
1105
+ */
1106
+ export type MessageEncoded =
1107
+ | SystemMessageEncoded
1108
+ | UserMessageEncoded
1109
+ | AssistantMessageEncoded
1110
+ | ToolMessageEncoded
1111
+
1112
+ /**
1113
+ * Schema for validation and encoding of messages.
1114
+ *
1115
+ * @since 1.0.0
1116
+ * @category Schemas
1117
+ */
1118
+ export const Message: Schema.Schema<Message, MessageEncoded> = Schema.Union(
1119
+ SystemMessage,
1120
+ UserMessage,
1121
+ AssistantMessage,
1122
+ ToolMessage
1123
+ )
1124
+
1125
+ // =============================================================================
1126
+ // Prompt
1127
+ // =============================================================================
1128
+
1129
+ /**
1130
+ * Unique identifier for Prompt instances.
1131
+ *
1132
+ * @since 1.0.0
1133
+ * @category Type Ids
1134
+ */
1135
+ export const TypeId = "~@effect/ai/Prompt"
1136
+
1137
+ /**
1138
+ * Type-level representation of the Prompt identifier.
1139
+ *
1140
+ * @since 1.0.0
1141
+ * @category Type Ids
1142
+ */
1143
+ export type TypeId = typeof TypeId
1144
+
1145
+ /**
1146
+ * Type guard to check if a value is a Prompt.
1147
+ *
1148
+ * @since 1.0.0
1149
+ * @category Guards
1150
+ */
1151
+ export const isPrompt = (u: unknown): u is Prompt => Predicate.hasProperty(u, TypeId)
1152
+
1153
+ /**
1154
+ * A Prompt contains a sequence of messages that form the context of a
1155
+ * conversation with a large language model.
1156
+ *
1157
+ * @since 1.0.0
1158
+ * @category Models
1159
+ */
1160
+ export interface Prompt {
1161
+ readonly [TypeId]: TypeId
1162
+ /**
1163
+ * Array of messages that make up the conversation.
1164
+ */
1165
+ readonly content: ReadonlyArray<Message>
1166
+ }
1167
+
1168
+ /**
1169
+ * Encoded representation of prompts for serialization.
1170
+ *
1171
+ * @since 1.0.0
1172
+ * @category Models
1173
+ */
1174
+ export interface PromptEncoded {
1175
+ /**
1176
+ * Array of messages that make up the conversation.
1177
+ */
1178
+ readonly content: ReadonlyArray<MessageEncoded>
1179
+ }
1180
+
1181
+ /**
1182
+ * Schema for validation and encoding of prompts.
1183
+ *
1184
+ * @since 1.0.0
1185
+ * @category Schemas
1186
+ */
1187
+ export const Prompt: Schema.Schema<Prompt, PromptEncoded> = Schema.Struct({
1188
+ content: Schema.Array(Message)
1189
+ }).pipe(
1190
+ Schema.attachPropertySignature(TypeId, TypeId),
1191
+ Schema.annotations({ identifier: "Prompt" })
1192
+ )
1193
+
1194
+ /**
1195
+ * Schema for parsing a Prompt from JSON strings.
1196
+ *
1197
+ * @since 1.0.0
1198
+ * @category Schemas
1199
+ */
1200
+ export const FromJson = Schema.parseJson(Prompt)
1201
+
1202
+ /**
1203
+ * Raw input types that can be converted into a Prompt.
1204
+ *
1205
+ * Supports various input formats for convenience, including simple strings,
1206
+ * message arrays, response parts, and existing prompts.
1207
+ *
1208
+ * @example
1209
+ * ```ts
1210
+ * import { Prompt } from "@effect/ai"
1211
+ *
1212
+ * // String input - creates a user message
1213
+ * const stringInput: Prompt.RawInput = "Hello, world!"
1214
+ *
1215
+ * // Message array input
1216
+ * const messagesInput: Prompt.RawInput = [
1217
+ * { role: "system", content: "You are helpful." },
1218
+ * { role: "user", content: [{ type: "text", text: "Hi!" }] }
1219
+ * ]
1220
+ *
1221
+ * // Existing prompt
1222
+ * declare const existingPrompt: Prompt.Prompt
1223
+ * const promptInput: Prompt.RawInput = existingPrompt
1224
+ * ```
1225
+ *
1226
+ * @since 1.0.0
1227
+ * @category Models
1228
+ */
1229
+ export type RawInput =
1230
+ | string
1231
+ | Iterable<MessageEncoded>
1232
+ | Prompt
1233
+
1234
+ const makePrompt = (content: ReadonlyArray<Message>): Prompt => ({
1235
+ [TypeId]: TypeId,
1236
+ content
1237
+ })
1238
+
1239
+ const decodeMessagesSync = Schema.decodeSync(Schema.Array(Message))
1240
+
1241
+ /**
1242
+ * An empty prompt with no messages.
1243
+ *
1244
+ * @example
1245
+ * ```ts
1246
+ * import { Prompt } from "@effect/ai"
1247
+ *
1248
+ * const emptyPrompt = Prompt.empty
1249
+ * console.log(emptyPrompt.content) // []
1250
+ * ```
1251
+ *
1252
+ * @since 1.0.0
1253
+ * @category Constructors
1254
+ */
1255
+ export const empty: Prompt = makePrompt([])
1256
+
1257
+ /**
1258
+ * Creates a Prompt from an input.
1259
+ *
1260
+ * This is the primary constructor for creating prompts, supporting multiple
1261
+ * input formats for convenience and flexibility.
1262
+ *
1263
+ * @example
1264
+ * ```ts
1265
+ * import { Prompt } from "@effect/ai"
1266
+ *
1267
+ * // From string - creates a user message
1268
+ * const textPrompt = Prompt.make("Hello, how are you?")
1269
+ *
1270
+ * // From messages array
1271
+ * const structuredPrompt = Prompt.make([
1272
+ * { role: "system", content: "You are a helpful assistant." },
1273
+ * { role: "user", content: [{ type: "text", text: "Hi!" }] }
1274
+ * ])
1275
+ *
1276
+ * // From existing prompt
1277
+ * declare const existingPrompt: Prompt.Prompt
1278
+ * const copiedPrompt = Prompt.make(existingPrompt)
1279
+ * ```
1280
+ *
1281
+ * @since 1.0.0
1282
+ * @category Constructors
1283
+ */
1284
+ export const make = (input: RawInput): Prompt => {
1285
+ if (Predicate.isString(input)) {
1286
+ const part = makePart("text", { text: input })
1287
+ const message = makeMessage("user", { content: [part] })
1288
+ return makePrompt([message])
1289
+ }
1290
+
1291
+ if (Predicate.isIterable(input)) {
1292
+ return makePrompt(decodeMessagesSync(Array.from(input), {
1293
+ errors: "all"
1294
+ }))
1295
+ }
1296
+
1297
+ return input
1298
+ }
1299
+
1300
+ /**
1301
+ * Creates a Prompt from an array of messages.
1302
+ *
1303
+ * @example
1304
+ * ```ts
1305
+ * import { Prompt } from "@effect/ai"
1306
+ *
1307
+ * const messages: ReadonlyArray<Prompt.Message> = [
1308
+ * Prompt.makeMessage("system", {
1309
+ * content: "You are a coding assistant."
1310
+ * }),
1311
+ * Prompt.makeMessage("user", {
1312
+ * content: [Prompt.makePart("text", { text: "Help me with TypeScript" })]
1313
+ * })
1314
+ * ]
1315
+ *
1316
+ * const prompt = Prompt.fromMessages(messages)
1317
+ * ```
1318
+ *
1319
+ * @since 1.0.0
1320
+ * @category Constructors
1321
+ */
1322
+ export const fromMessages = (messages: ReadonlyArray<Message>): Prompt => makePrompt(messages)
1323
+
1324
+ const VALID_RESPONSE_PART_MAP = {
1325
+ "response-metadata": false,
1326
+ "text": true,
1327
+ "text-start": false,
1328
+ "text-delta": true,
1329
+ "text-end": false,
1330
+ "reasoning": true,
1331
+ "reasoning-start": false,
1332
+ "reasoning-delta": true,
1333
+ "reasoning-end": false,
1334
+ "file": false,
1335
+ "source": false,
1336
+ "tool-params-start": false,
1337
+ "tool-params-delta": false,
1338
+ "tool-params-end": false,
1339
+ "tool-call": true,
1340
+ "tool-result": true,
1341
+ "finish": false,
1342
+ "error": false
1343
+ } as const satisfies Record<Response.AnyPart["type"], boolean>
1344
+
1345
+ type ValidResponseParts = typeof VALID_RESPONSE_PART_MAP
1346
+
1347
+ type ValidResponsePart = {
1348
+ [Type in keyof ValidResponseParts]: ValidResponseParts[Type] extends true ? Extract<Response.AnyPart, { type: Type }>
1349
+ : never
1350
+ }[keyof typeof VALID_RESPONSE_PART_MAP]
1351
+
1352
+ const isValidPart = (part: Response.AnyPart): part is ValidResponsePart => {
1353
+ return VALID_RESPONSE_PART_MAP[part.type]
1354
+ }
1355
+
1356
+ /**
1357
+ * Creates a Prompt from the response parts of a previous interaction with a
1358
+ * large language model.
1359
+ *
1360
+ * Converts streaming or non-streaming AI response parts into a structured
1361
+ * prompt, typically for use in conversation history or further processing.
1362
+ *
1363
+ * @example
1364
+ * ```ts
1365
+ * import { Prompt, Response } from "@effect/ai"
1366
+ *
1367
+ * const responseParts: ReadonlyArray<Response.AnyPart> = [
1368
+ * Response.makePart("text", {
1369
+ * text: "Hello there!"
1370
+ * }),
1371
+ * Response.makePart("tool-call", {
1372
+ * id: "call_1",
1373
+ * name: "get_time",
1374
+ * params: {},
1375
+ * providerExecuted: false
1376
+ * }),
1377
+ * Response.makePart("tool-result", {
1378
+ * id: "call_1",
1379
+ * name: "get_time",
1380
+ * result: "10:30 AM",
1381
+ * encodedResult: "10:30 AM",
1382
+ * providerExecuted: false
1383
+ * })
1384
+ * ]
1385
+ *
1386
+ * const prompt = Prompt.fromResponseParts(responseParts)
1387
+ * // Creates an assistant message with the response content
1388
+ * ```
1389
+ *
1390
+ * @since 1.0.0
1391
+ * @category Constructors
1392
+ */
1393
+ export const fromResponseParts = (parts: ReadonlyArray<Response.AnyPart>): Prompt => {
1394
+ if (parts.length === 0) {
1395
+ return empty
1396
+ }
1397
+
1398
+ const content: Array<AssistantMessagePart> = []
1399
+
1400
+ const textDeltas: Array<string> = []
1401
+ function flushTextDeltas() {
1402
+ if (textDeltas.length > 0) {
1403
+ const text = textDeltas.join("")
1404
+ if (text.length > 0) {
1405
+ content.push(makePart("text", { text }))
1406
+ }
1407
+ textDeltas.length = 0
1408
+ }
1409
+ }
1410
+
1411
+ const reasoningDeltas: Array<string> = []
1412
+ function flushReasoningDeltas() {
1413
+ if (reasoningDeltas.length > 0) {
1414
+ const text = reasoningDeltas.join("")
1415
+ if (text.length > 0) {
1416
+ content.push(makePart("reasoning", { text }))
1417
+ }
1418
+ reasoningDeltas.length = 0
1419
+ }
1420
+ }
1421
+
1422
+ function flushDeltas() {
1423
+ flushTextDeltas()
1424
+ flushReasoningDeltas()
1425
+ }
1426
+
1427
+ for (const part of parts) {
1428
+ if (isValidPart(part)) {
1429
+ switch (part.type) {
1430
+ case "text": {
1431
+ flushDeltas()
1432
+ content.push(makePart("text", { text: part.text }))
1433
+ break
1434
+ }
1435
+ case "text-delta": {
1436
+ flushReasoningDeltas()
1437
+ textDeltas.push(part.delta)
1438
+ break
1439
+ }
1440
+ case "reasoning": {
1441
+ flushDeltas()
1442
+ content.push(makePart("reasoning", { text: part.text }))
1443
+ break
1444
+ }
1445
+ case "reasoning-delta": {
1446
+ flushTextDeltas()
1447
+ reasoningDeltas.push(part.delta)
1448
+ break
1449
+ }
1450
+ case "tool-call": {
1451
+ flushDeltas()
1452
+ content.push(makePart("tool-call", {
1453
+ id: part.id,
1454
+ name: part.providerName ?? part.name,
1455
+ params: part.params,
1456
+ providerExecuted: part.providerExecuted ?? false
1457
+ }))
1458
+ break
1459
+ }
1460
+ case "tool-result": {
1461
+ flushDeltas()
1462
+ content.push(makePart("tool-result", {
1463
+ id: part.id,
1464
+ name: part.providerName ?? part.name,
1465
+ result: part.encodedResult
1466
+ }))
1467
+ break
1468
+ }
1469
+ }
1470
+ }
1471
+ }
1472
+
1473
+ flushDeltas()
1474
+
1475
+ const message = makeMessage("assistant", { content })
1476
+
1477
+ return makePrompt([message])
1478
+ }
1479
+
1480
+ // =============================================================================
1481
+ // Merging Prompts
1482
+ // =============================================================================
1483
+
1484
+ /**
1485
+ * Merges two prompts by concatenating their messages.
1486
+ *
1487
+ * Creates a new prompt containing all messages from both prompts, maintaining
1488
+ * the order of messages within each prompt.
1489
+ *
1490
+ * @example
1491
+ * ```ts
1492
+ * import { Prompt } from "@effect/ai"
1493
+ *
1494
+ * const systemPrompt = Prompt.make([{
1495
+ * role: "system",
1496
+ * content: "You are a helpful assistant."
1497
+ * }])
1498
+ *
1499
+ * const userPrompt = Prompt.make("Hello, world!")
1500
+ *
1501
+ * const merged = Prompt.merge(systemPrompt, userPrompt)
1502
+ * ```
1503
+ *
1504
+ * @since 1.0.0
1505
+ * @category Combinators
1506
+ */
1507
+ export const merge: {
1508
+ // =============================================================================
1509
+ // Merging Prompts
1510
+ // =============================================================================
1511
+
1512
+ /**
1513
+ * Merges two prompts by concatenating their messages.
1514
+ *
1515
+ * Creates a new prompt containing all messages from both prompts, maintaining
1516
+ * the order of messages within each prompt.
1517
+ *
1518
+ * @example
1519
+ * ```ts
1520
+ * import { Prompt } from "@effect/ai"
1521
+ *
1522
+ * const systemPrompt = Prompt.make([{
1523
+ * role: "system",
1524
+ * content: "You are a helpful assistant."
1525
+ * }])
1526
+ *
1527
+ * const userPrompt = Prompt.make("Hello, world!")
1528
+ *
1529
+ * const merged = Prompt.merge(systemPrompt, userPrompt)
1530
+ * ```
1531
+ *
1532
+ * @since 1.0.0
1533
+ * @category Combinators
1534
+ */
1535
+ (other: Prompt): (self: Prompt) => Prompt
1536
+ // =============================================================================
1537
+ // Merging Prompts
1538
+ // =============================================================================
1539
+
1540
+ /**
1541
+ * Merges two prompts by concatenating their messages.
1542
+ *
1543
+ * Creates a new prompt containing all messages from both prompts, maintaining
1544
+ * the order of messages within each prompt.
1545
+ *
1546
+ * @example
1547
+ * ```ts
1548
+ * import { Prompt } from "@effect/ai"
1549
+ *
1550
+ * const systemPrompt = Prompt.make([{
1551
+ * role: "system",
1552
+ * content: "You are a helpful assistant."
1553
+ * }])
1554
+ *
1555
+ * const userPrompt = Prompt.make("Hello, world!")
1556
+ *
1557
+ * const merged = Prompt.merge(systemPrompt, userPrompt)
1558
+ * ```
1559
+ *
1560
+ * @since 1.0.0
1561
+ * @category Combinators
1562
+ */
1563
+ (self: Prompt, other: Prompt): Prompt
1564
+ } = dual<
1565
+ // =============================================================================
1566
+ // Merging Prompts
1567
+ // =============================================================================
1568
+
1569
+ /**
1570
+ * Merges two prompts by concatenating their messages.
1571
+ *
1572
+ * Creates a new prompt containing all messages from both prompts, maintaining
1573
+ * the order of messages within each prompt.
1574
+ *
1575
+ * @example
1576
+ * ```ts
1577
+ * import { Prompt } from "@effect/ai"
1578
+ *
1579
+ * const systemPrompt = Prompt.make([{
1580
+ * role: "system",
1581
+ * content: "You are a helpful assistant."
1582
+ * }])
1583
+ *
1584
+ * const userPrompt = Prompt.make("Hello, world!")
1585
+ *
1586
+ * const merged = Prompt.merge(systemPrompt, userPrompt)
1587
+ * ```
1588
+ *
1589
+ * @since 1.0.0
1590
+ * @category Combinators
1591
+ */
1592
+ (other: Prompt) => (self: Prompt) => Prompt,
1593
+ // =============================================================================
1594
+ // Merging Prompts
1595
+ // =============================================================================
1596
+
1597
+ /**
1598
+ * Merges two prompts by concatenating their messages.
1599
+ *
1600
+ * Creates a new prompt containing all messages from both prompts, maintaining
1601
+ * the order of messages within each prompt.
1602
+ *
1603
+ * @example
1604
+ * ```ts
1605
+ * import { Prompt } from "@effect/ai"
1606
+ *
1607
+ * const systemPrompt = Prompt.make([{
1608
+ * role: "system",
1609
+ * content: "You are a helpful assistant."
1610
+ * }])
1611
+ *
1612
+ * const userPrompt = Prompt.make("Hello, world!")
1613
+ *
1614
+ * const merged = Prompt.merge(systemPrompt, userPrompt)
1615
+ * ```
1616
+ *
1617
+ * @since 1.0.0
1618
+ * @category Combinators
1619
+ */
1620
+ (self: Prompt, other: Prompt) => Prompt
1621
+ >(2, (self, other) => fromMessages([...self.content, ...other.content]))