| /** | |
| * Defines prompts sent to AI language models. | |
| * | |
| * A prompt is an ordered list of messages. Messages can use roles such as | |
| * system, user, assistant, and tool, and their content can be split into typed | |
| * parts such as text, files, reasoning, tool calls, tool results, and approval | |
| * messages. This module helps build prompts, combine them, and convert raw | |
| * input or response parts into the shared prompt shape. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| import * as Arr from "../../Array.ts" | |
| import * as Effect from "../../Effect.ts" | |
| import { dual } from "../../Function.ts" | |
| import * as Option from "../../Option.ts" | |
| import { type Pipeable, pipeArguments } from "../../Pipeable.ts" | |
| import * as Predicate from "../../Predicate.ts" | |
| import * as Schema from "../../Schema.ts" | |
| import * as SchemaIssue from "../../SchemaIssue.ts" | |
| import * as SchemaParser from "../../SchemaParser.ts" | |
| import * as SchemaTransformation from "../../SchemaTransformation.ts" | |
| import type * as Response from "./Response.ts" | |
| // ============================================================================= | |
| // Options | |
| // ============================================================================= | |
| /** | |
| * Schema for provider-specific options that can be attached to content parts | |
| * and messages. | |
| * | |
| * **Details** | |
| * | |
| * Provider-specific options are keyed by provider-specific names, and each | |
| * value is JSON or `null`. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export const ProviderOptions: Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > = Schema.Record(Schema.String, Schema.NullOr(Schema.Json)) | |
| /** | |
| * Type of provider-specific options that can be attached to prompt messages | |
| * and content parts. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export type ProviderOptions = typeof ProviderOptions.Type | |
| // ============================================================================= | |
| // Base Part | |
| // ============================================================================= | |
| const PartTypeId = "~effect/ai/Prompt/Part" as const | |
| /** | |
| * Type guard to check if a value is a Part. | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isPart = (u: unknown): u is Part => Predicate.hasProperty(u, PartTypeId) | |
| /** | |
| * Union type representing all possible content parts within messages. | |
| * | |
| * **Details** | |
| * | |
| * Parts are the building blocks of message content, supporting text, files, | |
| * reasoning, tool calls, tool results, tool approval responses, and tool | |
| * approval requests. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type Part = | |
| | TextPart | |
| | ReasoningPart | |
| | FilePart | |
| | ToolCallPart | |
| | ToolResultPart | |
| | ToolApprovalResponsePart | |
| | ToolApprovalRequestPart | |
| /** | |
| * Encoded representation of a Part. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type PartEncoded = | |
| | TextPartEncoded | |
| | ReasoningPartEncoded | |
| | FilePartEncoded | |
| | ToolCallPartEncoded | |
| | ToolResultPartEncoded | |
| | ToolApprovalResponsePartEncoded | |
| | ToolApprovalRequestPartEncoded | |
| /** | |
| * Base interface for all content parts. | |
| * | |
| * **Details** | |
| * | |
| * It provides the common structure shared by all content parts, including the | |
| * part type and provider options. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface BasePart<Type extends string, Options extends ProviderOptions> { | |
| readonly [PartTypeId]: typeof PartTypeId | |
| /** | |
| * The type of this content part. | |
| */ | |
| readonly type: Type | |
| /** | |
| * Provider-specific options for this part. | |
| */ | |
| readonly options: Options | |
| } | |
| /** | |
| * Base interface for encoded content parts. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface BasePartEncoded<Type extends string, Options extends ProviderOptions> { | |
| /** | |
| * The type of this content part. | |
| */ | |
| readonly type: Type | |
| /** | |
| * Provider-specific options for this part. | |
| */ | |
| readonly options?: Options | undefined | |
| } | |
| const BasePart = Schema.Struct({ | |
| [PartTypeId]: Schema.Literal(PartTypeId).pipe( | |
| Schema.withDecodingDefaultKey(Effect.succeed(PartTypeId), { encodingStrategy: "omit" }) | |
| ), | |
| options: ProviderOptions.pipe(Schema.withDecodingDefault(Effect.succeed({}))) | |
| }) | |
| /** | |
| * Creates a new content part of the specified type. | |
| * | |
| * **Example** (Creating content parts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const textPart = Prompt.makePart("text", { | |
| * text: "Hello, world!" | |
| * }) | |
| * | |
| * const filePart = Prompt.makePart("file", { | |
| * mediaType: "image/png", | |
| * fileName: "screenshot.png", | |
| * data: new Uint8Array([1, 2, 3]) | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const makePart = <const Type extends Part["type"]>( | |
| /** | |
| * The type of part to create. | |
| */ | |
| type: Type, | |
| /** | |
| * Parameters specific to the part type being created. | |
| */ | |
| params: Omit<Extract<Part, { type: Type }>, typeof PartTypeId | "type" | "options"> & { | |
| /** | |
| * Optional provider-specific options for this part. | |
| */ | |
| readonly options?: Extract<Part, { type: Type }>["options"] | undefined | |
| } | |
| ): Extract<Part, { type: Type }> => (({ | |
| ...params, | |
| [PartTypeId]: PartTypeId, | |
| type, | |
| options: params.options ?? {} | |
| }) as any) | |
| /** | |
| * A utility type for specifying the parameters required to construct a | |
| * specific part of a prompt. | |
| * | |
| * @category utility types | |
| * @since 4.0.0 | |
| */ | |
| export type PartConstructorParams<P extends Part> = Omit<P, typeof PartTypeId | "type" | "options"> & { | |
| /** | |
| * Optional provider-specific options for this part. | |
| */ | |
| readonly options?: Part["options"] | undefined | |
| } | |
| // ============================================================================= | |
| // Text Part | |
| // ============================================================================= | |
| /** | |
| * Content part representing plain text. | |
| * | |
| * **Details** | |
| * | |
| * Text parts are the basic content type used for textual information in | |
| * messages. | |
| * | |
| * **Example** (Creating text parts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const textPart: Prompt.TextPart = Prompt.makePart("text", { | |
| * text: "Hello, how can I help you today?" | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface TextPart extends BasePart<"text", TextPartOptions> { | |
| /** | |
| * The text content. | |
| */ | |
| readonly text: string | |
| } | |
| /** | |
| * Encoded representation of text parts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface TextPartEncoded extends BasePartEncoded<"text", TextPartOptions> { | |
| /** | |
| * The text content. | |
| */ | |
| readonly text: string | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `TextPart` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface TextPartOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of text parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const TextPart: Schema.Struct< | |
| { | |
| readonly type: Schema.Literal<"text"> | |
| readonly text: Schema.String | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| } | |
| > = Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("text"), | |
| text: Schema.String | |
| }).annotate({ identifier: "TextPart" }) | |
| /** | |
| * Constructs a new text part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const textPart = (params: PartConstructorParams<TextPart>): TextPart => makePart("text", params as any) | |
| // ============================================================================= | |
| // Reasoning Part | |
| // ============================================================================= | |
| /** | |
| * Content part carrying reasoning text in an assistant message, such as a | |
| * provider-supplied reasoning summary or explanation. | |
| * | |
| * **Example** (Creating reasoning parts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const reasoningPart: Prompt.ReasoningPart = Prompt.makePart("reasoning", { | |
| * text: | |
| * "Summary: the response compares the requested options by price and availability." | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ReasoningPart extends BasePart<"reasoning", ReasoningPartOptions> { | |
| /** | |
| * The reasoning or thought process text. | |
| */ | |
| readonly text: string | |
| } | |
| /** | |
| * Encoded representation of reasoning parts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ReasoningPartEncoded extends BasePartEncoded<"reasoning", ReasoningPartOptions> { | |
| /** | |
| * The reasoning or thought process text. | |
| */ | |
| readonly text: string | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `ReasoningPart` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface ReasoningPartOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of reasoning parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ReasoningPart: Schema.Struct<{ | |
| readonly type: Schema.Literal<"reasoning"> | |
| readonly text: Schema.String | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("reasoning"), | |
| text: Schema.String | |
| }).annotate({ identifier: "ReasoningPart" }) | |
| /** | |
| * Constructs a new reasoning part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const reasoningPart = (params: PartConstructorParams<ReasoningPart>): ReasoningPart => | |
| makePart("reasoning", params as any) | |
| // ============================================================================= | |
| // File Part | |
| // ============================================================================= | |
| /** | |
| * Content part representing a file attachment. | |
| * | |
| * **Details** | |
| * | |
| * Files can be provided as base64 data strings, byte arrays, or URLs, and can | |
| * represent images, documents, or other binary data. | |
| * | |
| * **Example** (Creating file parts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const imagePart: Prompt.FilePart = Prompt.makePart("file", { | |
| * mediaType: "image/jpeg", | |
| * fileName: "photo.jpg", | |
| * data: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..." | |
| * }) | |
| * | |
| * const documentPart: Prompt.FilePart = Prompt.makePart("file", { | |
| * mediaType: "application/pdf", | |
| * fileName: "report.pdf", | |
| * data: new Uint8Array([1, 2, 3]) | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface FilePart extends BasePart<"file", FilePartOptions> { | |
| /** | |
| * MIME type of the file (e.g., "image/jpeg", "application/pdf"). | |
| */ | |
| readonly mediaType: string | |
| /** | |
| * Optional filename for the file. | |
| */ | |
| readonly fileName?: string | undefined | |
| /** | |
| * File data as base64 string of data, a byte array, or a URL. | |
| */ | |
| readonly data: string | Uint8Array | URL | |
| } | |
| /** | |
| * Encoded representation of file parts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface FilePartEncoded extends BasePartEncoded<"file", FilePartOptions> { | |
| /** | |
| * MIME type of the file (e.g., "image/jpeg", "application/pdf"). | |
| */ | |
| readonly mediaType: string | |
| /** | |
| * Optional filename for the file. | |
| */ | |
| readonly fileName?: string | undefined | |
| /** | |
| * File data as base64 string of data, a byte array, or a URL. | |
| */ | |
| readonly data: string | Uint8Array | URL | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `FilePart` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface FilePartOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of file parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const FilePart: Schema.Struct<{ | |
| readonly type: Schema.Literal<"file"> | |
| readonly mediaType: Schema.String | |
| readonly fileName: Schema.optional<Schema.String> | |
| readonly data: Schema.Union<readonly [Schema.String, Schema.Uint8Array, Schema.URL]> | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("file"), | |
| mediaType: Schema.String, | |
| fileName: Schema.optional(Schema.String), | |
| data: Schema.Union([Schema.String, Schema.Uint8Array, Schema.URL]) | |
| }).annotate({ identifier: "FilePart" }) | |
| /** | |
| * Constructs a `FilePart` for prompt file attachments. | |
| * | |
| * **When to use** | |
| * | |
| * Use to create the file-attachment part of a prompt from typed file part | |
| * parameters. | |
| * | |
| * @see {@link makePart} for the generic part constructor | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const filePart = (params: PartConstructorParams<FilePart>): FilePart => makePart("file", params as any) | |
| // ============================================================================= | |
| // Tool Call Part | |
| // ============================================================================= | |
| /** | |
| * Content part representing a tool call request. | |
| * | |
| * **Example** (Creating tool call parts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const toolCallPart: Prompt.ToolCallPart = Prompt.makePart("tool-call", { | |
| * id: "call_123", | |
| * name: "get_weather", | |
| * params: { city: "San Francisco", units: "celsius" }, | |
| * providerExecuted: false | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolCallPart extends BasePart<"tool-call", ToolCallPartOptions> { | |
| /** | |
| * Unique identifier for this tool call. | |
| */ | |
| readonly id: string | |
| /** | |
| * Name of the tool to invoke. | |
| */ | |
| readonly name: string | |
| /** | |
| * Parameters to pass to the tool. | |
| */ | |
| readonly params: unknown | |
| /** | |
| * Whether the tool was executed by the provider (true) or framework (false). | |
| */ | |
| readonly providerExecuted: boolean | |
| } | |
| /** | |
| * Encoded representation of tool call parts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolCallPartEncoded extends BasePartEncoded<"tool-call", ToolCallPartOptions> { | |
| /** | |
| * Unique identifier for this tool call. | |
| */ | |
| readonly id: string | |
| /** | |
| * Name of the tool to invoke. | |
| */ | |
| readonly name: string | |
| /** | |
| * Parameters to pass to the tool. | |
| */ | |
| readonly params: unknown | |
| /** | |
| * Whether the tool was executed by the provider (true) or framework (false). | |
| */ | |
| readonly providerExecuted?: boolean | undefined | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `ToolCallPart` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolCallPartOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of tool call parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolCallPart: Schema.Struct<{ | |
| readonly type: Schema.Literal<"tool-call"> | |
| readonly id: Schema.String | |
| readonly name: Schema.String | |
| readonly params: Schema.Unknown | |
| readonly providerExecuted: Schema.withDecodingDefault<Schema.Boolean> | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-call"), | |
| id: Schema.String, | |
| name: Schema.String, | |
| params: Schema.Unknown, | |
| providerExecuted: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))) | |
| }).annotate({ identifier: "ToolCallPart" }) | |
| /** | |
| * Constructs a new tool call part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolCallPart = (params: PartConstructorParams<ToolCallPart>): ToolCallPart => | |
| makePart("tool-call", params as any) | |
| // ============================================================================= | |
| // Tool Result Part | |
| // ============================================================================= | |
| /** | |
| * Content part representing the result of a tool call. | |
| * | |
| * **Example** (Creating tool result parts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const toolResultPart: Prompt.ToolResultPart = Prompt.makePart("tool-result", { | |
| * id: "call_123", | |
| * name: "get_weather", | |
| * isFailure: false, | |
| * result: { | |
| * temperature: 22, | |
| * condition: "sunny", | |
| * humidity: 65 | |
| * } | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolResultPart extends BasePart<"tool-result", ToolResultPartOptions> { | |
| /** | |
| * Unique identifier matching the original tool call. | |
| */ | |
| readonly id: string | |
| /** | |
| * Name of the tool that was executed. | |
| */ | |
| readonly name: string | |
| /** | |
| * Whether or not the result of executing the tool call handler was an error. | |
| */ | |
| readonly isFailure: boolean | |
| /** | |
| * The result returned by the tool execution. | |
| */ | |
| readonly result: unknown | |
| } | |
| /** | |
| * Encoded representation of tool result parts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolResultPartEncoded extends BasePartEncoded<"tool-result", ToolResultPartOptions> { | |
| /** | |
| * Unique identifier matching the original tool call. | |
| */ | |
| readonly id: string | |
| /** | |
| * Name of the tool that was executed. | |
| */ | |
| readonly name: string | |
| /** | |
| * Whether or not the result of executing the tool call handler was an error. | |
| */ | |
| readonly isFailure: boolean | |
| /** | |
| * The result returned by the tool execution. | |
| */ | |
| readonly result: unknown | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `ToolResultPart` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolResultPartOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of tool result parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolResultPart: Schema.Struct<{ | |
| readonly type: Schema.Literal<"tool-result"> | |
| readonly id: Schema.String | |
| readonly name: Schema.String | |
| readonly isFailure: Schema.Boolean | |
| readonly result: Schema.Unknown | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-result"), | |
| id: Schema.String, | |
| name: Schema.String, | |
| isFailure: Schema.Boolean, | |
| result: Schema.Unknown | |
| }).annotate({ identifier: "ToolResultPart" }) | |
| /** | |
| * Constructs a new tool result part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolResultPart = (params: PartConstructorParams<ToolResultPart>): ToolResultPart => | |
| makePart("tool-result", params as any) | |
| // ============================================================================= | |
| // Tool Approval Response Part | |
| // ============================================================================= | |
| /** | |
| * Content part representing a user's response to a tool approval request. | |
| * | |
| * **When to use** | |
| * | |
| * Use when tool messages must approve or deny tool execution for tools with the | |
| * `needsApproval` property set. | |
| * | |
| * **Example** (Creating tool approval responses) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const approvalResponse: Prompt.ToolApprovalResponsePart = Prompt.makePart( | |
| * "tool-approval-response", | |
| * { | |
| * approvalId: "approval_123", | |
| * approved: true | |
| * } | |
| * ) | |
| * | |
| * const denialResponse: Prompt.ToolApprovalResponsePart = Prompt.makePart( | |
| * "tool-approval-response", | |
| * { | |
| * approvalId: "approval_456", | |
| * approved: false, | |
| * reason: "Operation not allowed" | |
| * } | |
| * ) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolApprovalResponsePart extends BasePart<"tool-approval-response", ToolApprovalResponsePartOptions> { | |
| /** | |
| * References the original approval request. | |
| */ | |
| readonly approvalId: string | |
| /** | |
| * User's decision to approve or deny the tool execution. | |
| */ | |
| readonly approved: boolean | |
| /** | |
| * Optional justification for the decision. | |
| */ | |
| readonly reason?: string | undefined | |
| } | |
| /** | |
| * Encoded representation of tool approval response parts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolApprovalResponsePartEncoded | |
| extends BasePartEncoded<"tool-approval-response", ToolApprovalResponsePartOptions> | |
| { | |
| /** | |
| * References the original approval request. | |
| */ | |
| readonly approvalId: string | |
| /** | |
| * User's decision to approve or deny the tool execution. | |
| */ | |
| readonly approved: boolean | |
| /** | |
| * Optional justification for the decision. | |
| */ | |
| readonly reason?: string | undefined | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `ToolApprovalResponsePart` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolApprovalResponsePartOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of tool approval response parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolApprovalResponsePart: Schema.Struct<{ | |
| readonly type: Schema.Literal<"tool-approval-response"> | |
| readonly approvalId: Schema.String | |
| readonly approved: Schema.Boolean | |
| readonly reason: Schema.optional<Schema.String> | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-approval-response"), | |
| approvalId: Schema.String, | |
| approved: Schema.Boolean, | |
| reason: Schema.optional(Schema.String) | |
| }).annotate({ identifier: "ToolApprovalResponsePart" }) | |
| /** | |
| * Constructs a new tool approval response part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolApprovalResponsePart = ( | |
| params: PartConstructorParams<ToolApprovalResponsePart> | |
| ): ToolApprovalResponsePart => makePart("tool-approval-response", params as any) | |
| // ============================================================================= | |
| // Tool Approval Request Part | |
| // ============================================================================= | |
| /** | |
| * Content part representing a tool approval request from the framework. | |
| * | |
| * **Details** | |
| * | |
| * Tool approval request parts are stored in assistant messages when a tool | |
| * requires user approval before execution. The user responds with a | |
| * `ToolApprovalResponsePart` in a tool message. | |
| * | |
| * **Example** (Creating tool approval requests) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const approvalRequest: Prompt.ToolApprovalRequestPart = Prompt.makePart( | |
| * "tool-approval-request", | |
| * { | |
| * approvalId: "approval_123", | |
| * toolCallId: "call_456" | |
| * } | |
| * ) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolApprovalRequestPart extends BasePart<"tool-approval-request", ToolApprovalRequestPartOptions> { | |
| /** | |
| * Unique identifier for this approval flow. | |
| */ | |
| readonly approvalId: string | |
| /** | |
| * The tool call ID requiring approval. | |
| */ | |
| readonly toolCallId: string | |
| } | |
| /** | |
| * Encoded representation of tool approval request parts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolApprovalRequestPartEncoded | |
| extends BasePartEncoded<"tool-approval-request", ToolApprovalRequestPartOptions> | |
| { | |
| /** | |
| * Unique identifier for this approval flow. | |
| */ | |
| readonly approvalId: string | |
| /** | |
| * The tool call ID requiring approval. | |
| */ | |
| readonly toolCallId: string | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `ToolApprovalRequestPart` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolApprovalRequestPartOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of tool approval request parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolApprovalRequestPart: Schema.Struct<{ | |
| readonly type: Schema.Literal<"tool-approval-request"> | |
| readonly approvalId: Schema.String | |
| readonly toolCallId: Schema.String | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BasePart.fields, | |
| type: Schema.Literal("tool-approval-request"), | |
| approvalId: Schema.String, | |
| toolCallId: Schema.String | |
| }).annotate({ identifier: "ToolApprovalRequestPart" }) | |
| /** | |
| * Constructs a new tool approval request part. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolApprovalRequestPart = ( | |
| params: PartConstructorParams<ToolApprovalRequestPart> | |
| ): ToolApprovalRequestPart => makePart("tool-approval-request", params as any) | |
| // ============================================================================= | |
| // Base Message | |
| // ============================================================================= | |
| const MessageTypeId = "~effect/ai/Prompt/Message" as const | |
| /** | |
| * Type guard to check if a value is a Message. | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isMessage = (u: unknown): u is Message => Predicate.hasProperty(u, MessageTypeId) | |
| /** | |
| * Base interface for all message types. | |
| * | |
| * **Details** | |
| * | |
| * It provides the common structure shared by all messages, including the role | |
| * and provider options. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface BaseMessage<Role extends string, Options extends ProviderOptions> { | |
| readonly [MessageTypeId]: typeof MessageTypeId | |
| /** | |
| * The role of the message participant. | |
| */ | |
| readonly role: Role | |
| /** | |
| * Provider-specific options for this message. | |
| */ | |
| readonly options: Options | |
| } | |
| /** | |
| * Base interface for encoded message types. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface BaseMessageEncoded<Role extends string, Options extends ProviderOptions> { | |
| /** | |
| * The role of the message participant. | |
| */ | |
| readonly role: Role | |
| /** | |
| * Provider-specific options for this message. | |
| */ | |
| readonly options?: Options | undefined | |
| } | |
| const BaseMessage = Schema.Struct({ | |
| [MessageTypeId]: Schema.Literal(MessageTypeId).pipe( | |
| Schema.withDecodingDefaultKey(Effect.succeed(MessageTypeId), { encodingStrategy: "omit" }) | |
| ), | |
| options: ProviderOptions.pipe(Schema.withDecodingDefault(Effect.succeed({}))) | |
| }) | |
| /** | |
| * Creates a new message with the specified role. | |
| * | |
| * **Example** (Creating messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const textPart = Prompt.makePart("text", { | |
| * text: "Hello, world!" | |
| * }) | |
| * | |
| * const userMessage = Prompt.makeMessage("user", { | |
| * content: [textPart] | |
| * }) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const makeMessage = <const Role extends Message["role"]>( | |
| role: Role, | |
| params: Omit<Extract<Message, { role: Role }>, typeof MessageTypeId | "role" | "options"> & { | |
| readonly options?: Extract<Message, { role: Role }>["options"] | undefined | |
| } | |
| ): Extract<Message, { role: Role }> => (({ | |
| ...params, | |
| [MessageTypeId]: MessageTypeId, | |
| role, | |
| options: params.options ?? {} | |
| }) as any) | |
| /** | |
| * A utility type for specifying the parameters required to construct a | |
| * specific message for a prompt. | |
| * | |
| * @category utility types | |
| * @since 4.0.0 | |
| */ | |
| export type MessageConstructorParams<M extends Message> = Omit<M, typeof MessageTypeId | "role" | "options"> & { | |
| /** | |
| * Optional provider-specific options for this message. | |
| */ | |
| readonly options?: Part["options"] | undefined | |
| } | |
| /** | |
| * Schema that decodes a string into content containing a single `TextPart` and, | |
| * when encoding, emits the `text` value of the first part. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ContentFromString: Schema.decodeTo< | |
| Schema.NonEmptyArray< | |
| Schema.toType< | |
| Schema.Struct<{ | |
| readonly type: Schema.Literal<"text"> | |
| readonly text: Schema.String | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> | |
| > | |
| >, | |
| Schema.String | |
| > = Schema.String.pipe( | |
| Schema.decodeTo( | |
| Schema.NonEmptyArray(Schema.toType(TextPart)), | |
| SchemaTransformation.transform({ | |
| decode: (text) => Arr.of(makePart("text", { text })) as Arr.NonEmptyReadonlyArray<TextPart>, | |
| encode: (content) => content[0].text | |
| }) | |
| ) | |
| ) | |
| // ============================================================================= | |
| // System Message | |
| // ============================================================================= | |
| /** | |
| * Message representing system instructions or context. | |
| * | |
| * **Example** (Creating system messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemMessage: Prompt.SystemMessage = Prompt.makeMessage("system", { | |
| * content: "You are a helpful assistant specialized in mathematics. " + | |
| * "Always show your work step by step." | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface SystemMessage extends BaseMessage<"system", SystemMessageOptions> { | |
| /** | |
| * The system instruction or context as plain text. | |
| */ | |
| readonly content: string | |
| } | |
| /** | |
| * Encoded representation of system messages for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface SystemMessageEncoded extends BaseMessageEncoded<"system", SystemMessageOptions> { | |
| /** | |
| * The system instruction or context as plain text. | |
| */ | |
| readonly content: string | |
| } | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `SystemMessage` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface SystemMessageOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of system messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const SystemMessage: Schema.Struct<{ | |
| readonly role: Schema.Literal<"system"> | |
| readonly content: Schema.String | |
| readonly "~effect/ai/Prompt/Message": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Message">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("system"), | |
| content: Schema.String | |
| }).annotate({ identifier: "SystemMessage" }) | |
| /** | |
| * Constructs a new system message. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const systemMessage = (params: MessageConstructorParams<SystemMessage>): SystemMessage => | |
| makeMessage("system", params) | |
| // ============================================================================= | |
| // User Message | |
| // ============================================================================= | |
| /** | |
| * Message representing user input or questions. | |
| * | |
| * **Example** (Creating user messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const textUserMessage: Prompt.UserMessage = Prompt.makeMessage("user", { | |
| * content: [ | |
| * Prompt.makePart("text", { | |
| * text: "Can you analyze this image for me?" | |
| * }) | |
| * ] | |
| * }) | |
| * | |
| * const multimodalUserMessage: Prompt.UserMessage = Prompt.makeMessage("user", { | |
| * content: [ | |
| * Prompt.makePart("text", { | |
| * text: "What do you see in this image?" | |
| * }), | |
| * Prompt.makePart("file", { | |
| * mediaType: "image/jpeg", | |
| * fileName: "vacation.jpg", | |
| * data: "data:image/jpeg;base64,..." | |
| * }) | |
| * ] | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface UserMessage extends BaseMessage<"user", UserMessageOptions> { | |
| /** | |
| * Array of content parts that make up the user's message. | |
| */ | |
| readonly content: ReadonlyArray<UserMessagePart> | |
| } | |
| /** | |
| * Union type of content parts allowed in user messages. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type UserMessagePart = TextPart | FilePart | |
| /** | |
| * Encoded representation of user messages for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface UserMessageEncoded extends BaseMessageEncoded<"user", UserMessageOptions> { | |
| /** | |
| * Array of content parts that make up the user's message. | |
| */ | |
| readonly content: string | ReadonlyArray<UserMessagePartEncoded> | |
| } | |
| /** | |
| * Union type of encoded content parts for user messages. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type UserMessagePartEncoded = TextPartEncoded | FilePartEncoded | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `UserMessage` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface UserMessageOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of user messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const UserMessage: Schema.Struct<{ | |
| readonly role: Schema.Literal<"user"> | |
| readonly content: Schema.Union< | |
| readonly [ | |
| Schema.decodeTo< | |
| Schema.NonEmptyArray< | |
| Schema.toType< | |
| Schema.Struct<{ | |
| readonly type: Schema.Literal<"text"> | |
| readonly text: Schema.String | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> | |
| > | |
| >, | |
| Schema.String, | |
| never, | |
| never | |
| >, | |
| Schema.$Array< | |
| Schema.Union< | |
| readonly [ | |
| Schema.Struct<{ | |
| readonly type: Schema.Literal<"text"> | |
| readonly text: Schema.String | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }>, | |
| Schema.Struct<{ | |
| readonly type: Schema.Literal<"file"> | |
| readonly mediaType: Schema.String | |
| readonly fileName: Schema.optional<Schema.String> | |
| readonly data: Schema.Union<readonly [Schema.String, Schema.Uint8Array, Schema.URL]> | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> | |
| ] | |
| > | |
| > | |
| ] | |
| > | |
| readonly "~effect/ai/Prompt/Message": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Message">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("user"), | |
| content: Schema.Union([ | |
| ContentFromString, | |
| Schema.Array(Schema.Union([TextPart, FilePart])) | |
| ]) | |
| }).annotate({ identifier: "UserMessage" }) | |
| /** | |
| * Constructs a new user message. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const userMessage = (params: MessageConstructorParams<UserMessage>): UserMessage => makeMessage("user", params) | |
| // ============================================================================= | |
| // Assistant Message | |
| // ============================================================================= | |
| /** | |
| * Message representing large language model assistant responses. | |
| * | |
| * **Example** (Creating assistant messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const assistantMessage: Prompt.AssistantMessage = Prompt.makeMessage( | |
| * "assistant", | |
| * { | |
| * content: [ | |
| * Prompt.makePart("text", { | |
| * text: | |
| * "I can check the current weather for San Francisco." | |
| * }), | |
| * Prompt.makePart("tool-call", { | |
| * id: "call_123", | |
| * name: "get_weather", | |
| * params: { city: "San Francisco" }, | |
| * providerExecuted: false | |
| * }), | |
| * Prompt.makePart("tool-result", { | |
| * id: "call_123", | |
| * name: "get_weather", | |
| * isFailure: false, | |
| * result: { | |
| * temperature: 72, | |
| * condition: "sunny" | |
| * } | |
| * }), | |
| * Prompt.makePart("text", { | |
| * text: "The weather in San Francisco is currently 72°F and sunny." | |
| * }) | |
| * ] | |
| * } | |
| * ) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface AssistantMessage extends BaseMessage<"assistant", AssistantMessageOptions> { | |
| /** | |
| * Array of content parts that make up the assistant's response. | |
| */ | |
| readonly content: ReadonlyArray<AssistantMessagePart> | |
| } | |
| /** | |
| * Union type of content parts allowed in assistant messages. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type AssistantMessagePart = | |
| | TextPart | |
| | FilePart | |
| | ReasoningPart | |
| | ToolCallPart | |
| | ToolResultPart | |
| | ToolApprovalRequestPart | |
| /** | |
| * Encoded representation of assistant messages for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface AssistantMessageEncoded extends BaseMessageEncoded<"assistant", AssistantMessageOptions> { | |
| readonly content: string | ReadonlyArray<AssistantMessagePartEncoded> | |
| } | |
| /** | |
| * Union type of encoded content parts for assistant messages. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type AssistantMessagePartEncoded = | |
| | TextPartEncoded | |
| | FilePartEncoded | |
| | ReasoningPartEncoded | |
| | ToolCallPartEncoded | |
| | ToolResultPartEncoded | |
| | ToolApprovalRequestPartEncoded | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `AssistantMessage` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface AssistantMessageOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of assistant messages. | |
| * | |
| * **Details** | |
| * | |
| * Assistant content can be a string decoded through `ContentFromString` or an | |
| * array of text, file, reasoning, tool-call, tool-result, and | |
| * tool-approval-request parts. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const AssistantMessage: Schema.Struct<{ | |
| readonly role: Schema.Literal<"assistant"> | |
| readonly content: Schema.Union< | |
| readonly [ | |
| Schema.decodeTo< | |
| Schema.NonEmptyArray< | |
| Schema.toType< | |
| Schema.Struct<{ | |
| readonly type: Schema.Literal<"text"> | |
| readonly text: Schema.String | |
| readonly "~effect/ai/Prompt/Part": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Part">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> | |
| > | |
| >, | |
| Schema.String, | |
| never, | |
| never | |
| >, | |
| Schema.$Array< | |
| Schema.Union< | |
| readonly [ | |
| typeof TextPart, | |
| typeof FilePart, | |
| typeof ReasoningPart, | |
| typeof ToolCallPart, | |
| typeof ToolResultPart, | |
| typeof ToolApprovalRequestPart | |
| ] | |
| > | |
| > | |
| ] | |
| > | |
| readonly "~effect/ai/Prompt/Message": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Message">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("assistant"), | |
| content: Schema.Union([ | |
| ContentFromString, | |
| Schema.Array(Schema.Union([ | |
| TextPart, | |
| FilePart, | |
| ReasoningPart, | |
| ToolCallPart, | |
| ToolResultPart, | |
| ToolApprovalRequestPart | |
| ])) | |
| ]) | |
| }).annotate({ identifier: "AssistantMessage" }) | |
| /** | |
| * Constructs a new assistant message. | |
| * | |
| * **When to use** | |
| * | |
| * Use to add assistant-role prompt history or model responses. | |
| * | |
| * **Details** | |
| * | |
| * This is the role-specific wrapper around `makeMessage("assistant", params)`. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const assistantMessage = (params: MessageConstructorParams<AssistantMessage>): AssistantMessage => | |
| makeMessage("assistant", params) | |
| // ============================================================================= | |
| // Tool Message | |
| // ============================================================================= | |
| /** | |
| * Message carrying tool-side content, including tool execution results and | |
| * responses to tool approval requests. | |
| * | |
| * **Example** (Creating tool messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const toolMessage: Prompt.ToolMessage = Prompt.makeMessage("tool", { | |
| * content: [ | |
| * Prompt.makePart("tool-result", { | |
| * id: "call_123", | |
| * name: "search_web", | |
| * isFailure: false, | |
| * result: { | |
| * query: "TypeScript best practices", | |
| * results: [ | |
| * { title: "TypeScript Handbook", url: "https://..." }, | |
| * { title: "Effective TypeScript", url: "https://..." } | |
| * ] | |
| * } | |
| * }) | |
| * ] | |
| * }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolMessage extends BaseMessage<"tool", ToolMessageOptions> { | |
| /** | |
| * Array of tool result parts. | |
| */ | |
| readonly content: ReadonlyArray<ToolMessagePart> | |
| } | |
| /** | |
| * Union type of content parts allowed in tool messages. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type ToolMessagePart = ToolResultPart | ToolApprovalResponsePart | |
| /** | |
| * Encoded representation of tool messages for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolMessageEncoded extends BaseMessageEncoded<"tool", ToolMessageOptions> { | |
| /** | |
| * Array of tool result parts. | |
| */ | |
| readonly content: ReadonlyArray<ToolMessagePartEncoded> | |
| } | |
| /** | |
| * Union type of encoded content parts for tool messages. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type ToolMessagePartEncoded = ToolResultPartEncoded | ToolApprovalResponsePartEncoded | |
| /** | |
| * Represents provider-specific options that can be associated with a | |
| * `ToolMessage` through module augmentation. | |
| * | |
| * @category options | |
| * @since 4.0.0 | |
| */ | |
| export interface ToolMessageOptions extends ProviderOptions {} | |
| /** | |
| * Schema for validation and encoding of tool messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const ToolMessage: Schema.Struct<{ | |
| readonly role: Schema.Literal<"tool"> | |
| readonly content: Schema.$Array< | |
| Schema.Union<readonly [typeof ToolResultPart, typeof ToolApprovalResponsePart]> | |
| > | |
| readonly "~effect/ai/Prompt/Message": Schema.withDecodingDefaultKey<Schema.Literal<"~effect/ai/Prompt/Message">> | |
| readonly options: Schema.withDecodingDefault< | |
| Schema.$Record< | |
| Schema.String, | |
| Schema.NullOr<Schema.Codec<Schema.Json>> | |
| > | |
| > | |
| }> = Schema.Struct({ | |
| ...BaseMessage.fields, | |
| role: Schema.Literal("tool"), | |
| content: Schema.Array(Schema.Union([ToolResultPart, ToolApprovalResponsePart])) | |
| }).annotate({ identifier: "ToolMessage" }) | |
| /** | |
| * Constructs a new tool message. | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const toolMessage = (params: MessageConstructorParams<ToolMessage>): ToolMessage => makeMessage("tool", params) | |
| // ============================================================================= | |
| // Message | |
| // ============================================================================= | |
| /** | |
| * A type representing all possible message types in a conversation. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type Message = | |
| | SystemMessage | |
| | UserMessage | |
| | AssistantMessage | |
| | ToolMessage | |
| /** | |
| * A type representing all possible encoded message types for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type MessageEncoded = | |
| | SystemMessageEncoded | |
| | UserMessageEncoded | |
| | AssistantMessageEncoded | |
| | ToolMessageEncoded | |
| /** | |
| * Schema for validation and encoding of messages. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const Message: Schema.Codec<Message, MessageEncoded> = Schema.Union([ | |
| SystemMessage, | |
| UserMessage, | |
| AssistantMessage, | |
| ToolMessage | |
| ]) | |
| // ============================================================================= | |
| // Prompt | |
| // ============================================================================= | |
| const TypeId = "~effect/unstable/ai/Prompt" as const | |
| /** | |
| * Type guard to check if a value is a Prompt. | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isPrompt = (u: unknown): u is Prompt => Predicate.hasProperty(u, TypeId) | |
| /** | |
| * A Prompt contains a sequence of messages that form the context of a | |
| * conversation with a large language model. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface Prompt extends Pipeable { | |
| readonly [TypeId]: typeof TypeId | |
| /** | |
| * Array of messages that make up the conversation. | |
| */ | |
| readonly content: ReadonlyArray<Message> | |
| } | |
| /** | |
| * Encoded representation of prompts for serialization. | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface PromptEncoded { | |
| /** | |
| * Array of messages that make up the conversation. | |
| */ | |
| readonly content: ReadonlyArray<MessageEncoded> | |
| } | |
| const $Prompt = Schema.declare((u) => isPrompt(u), { identifier: "Prompt" }) | |
| // TODO: is the type annotation necessary? | |
| // TODO: shoudn't the name be `PromptFrom...`? | |
| // TODO: is the explicit encoding necessary? maybe use the default JSON serializer? | |
| /** | |
| * Schema for AI prompt instances. | |
| * | |
| * @category schemas | |
| * @since 4.0.0 | |
| */ | |
| export const Prompt: Schema.Codec<Prompt, PromptEncoded> = Schema.Struct({ | |
| content: Schema.Array(Schema.toEncoded(Message)) | |
| }).pipe( | |
| Schema.decodeTo( | |
| $Prompt, | |
| SchemaTransformation.transformOrFail({ | |
| decode: (input) => | |
| Effect.mapBothEager( | |
| SchemaParser.decodeEffect(Schema.Array(Message))(input.content), | |
| { | |
| onSuccess: makePrompt, | |
| onFailure: () => | |
| new SchemaIssue.InvalidValue(Option.some(input.content), { message: "Invalid Prompt messages" }) | |
| } | |
| ), | |
| encode: (prompt) => | |
| Effect.mapBothEager( | |
| SchemaParser.encodeEffect(Schema.Array(Message))(prompt.content), | |
| { | |
| onSuccess: (messages) => ({ content: messages }), | |
| onFailure: () => | |
| new SchemaIssue.InvalidValue(Option.some(prompt.content), { message: "Invalid Prompt messages" }) | |
| } | |
| ) | |
| }) | |
| ) | |
| ) | |
| /** | |
| * Raw input accepted by `make`: a string, an iterable of encoded messages, or | |
| * an existing `Prompt`. | |
| * | |
| * **Example** (Accepting raw prompt input) | |
| * | |
| * ```ts | |
| * import type { Prompt } from "effect/unstable/ai" | |
| * | |
| * // String input - creates a user message | |
| * const stringInput: Prompt.RawInput = "Hello, world!" | |
| * | |
| * // Message array input | |
| * const messagesInput: Prompt.RawInput = [ | |
| * { role: "system", content: "You are helpful." }, | |
| * { role: "user", content: [{ type: "text", text: "Hi!" }] } | |
| * ] | |
| * | |
| * // Existing prompt | |
| * declare const existingPrompt: Prompt.Prompt | |
| * const promptInput: Prompt.RawInput = existingPrompt | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type RawInput = | |
| | string | |
| | Iterable<MessageEncoded> | |
| | Prompt | |
| const Proto = { | |
| [TypeId]: TypeId, | |
| pipe() { | |
| return pipeArguments(this, arguments) | |
| } | |
| } | |
| const makePrompt = (content: ReadonlyArray<Message>): Prompt => | |
| Object.assign(Object.create(Proto), { | |
| content | |
| }) | |
| const decodeMessagesSync = Schema.decodeSync(Schema.Array(Message)) | |
| /** | |
| * An empty prompt with no messages. | |
| * | |
| * **Example** (Creating an empty prompt) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const emptyPrompt = Prompt.empty | |
| * console.log(emptyPrompt.content) // [] | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const empty: Prompt = makePrompt([]) | |
| /** | |
| * Creates a `Prompt` from an input. | |
| * | |
| * **Details** | |
| * | |
| * This is the primary constructor for creating prompts, supporting multiple | |
| * input formats for convenience and flexibility. | |
| * | |
| * **Example** (Creating prompts from inputs) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * // From string - creates a user message | |
| * const textPrompt = Prompt.make("Hello, how are you?") | |
| * | |
| * // From messages array | |
| * const structuredPrompt = Prompt.make([ | |
| * { role: "system", content: "You are a helpful assistant." }, | |
| * { role: "user", content: [{ type: "text", text: "Hi!" }] } | |
| * ]) | |
| * | |
| * // From existing prompt | |
| * declare const existingPrompt: Prompt.Prompt | |
| * const copiedPrompt = Prompt.make(existingPrompt) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const make = (input: RawInput): Prompt => { | |
| if (typeof input === "string") { | |
| const part = makePart("text", { text: input }) | |
| const message = makeMessage("user", { content: [part] }) | |
| return makePrompt([message]) | |
| } | |
| if (Predicate.isIterable(input)) { | |
| return makePrompt(decodeMessagesSync(Arr.fromIterable(input), { | |
| errors: "all" | |
| })) | |
| } | |
| return input | |
| } | |
| /** | |
| * Creates a Prompt from an array of messages. | |
| * | |
| * **Example** (Creating prompts from messages) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const messages: ReadonlyArray<Prompt.Message> = [ | |
| * Prompt.makeMessage("system", { | |
| * content: "You are a coding assistant." | |
| * }), | |
| * Prompt.makeMessage("user", { | |
| * content: [Prompt.makePart("text", { text: "Help me with TypeScript" })] | |
| * }) | |
| * ] | |
| * | |
| * const prompt = Prompt.fromMessages(messages) | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromMessages = (messages: ReadonlyArray<Message>): Prompt => makePrompt(messages) | |
| /** | |
| * Creates a `Prompt` from response parts by folding completed text and | |
| * reasoning streams into assistant parts, placing tool calls and approval | |
| * requests in an assistant message, and placing non-preliminary tool results | |
| * in a tool message using their encoded results. | |
| * | |
| * **Example** (Creating prompts from response parts) | |
| * | |
| * ```ts | |
| * import { Prompt, Response } from "effect/unstable/ai" | |
| * | |
| * const responseParts: ReadonlyArray<Response.AnyPart> = [ | |
| * Response.makePart("text", { | |
| * text: "Hello there!" | |
| * }), | |
| * Response.makePart("tool-call", { | |
| * id: "call_1", | |
| * name: "get_time", | |
| * params: {}, | |
| * providerExecuted: false | |
| * }), | |
| * Response.makePart("tool-result", { | |
| * id: "call_1", | |
| * name: "get_time", | |
| * isFailure: false, | |
| * result: "10:30 AM", | |
| * encodedResult: "10:30 AM", | |
| * providerExecuted: false, | |
| * preliminary: false | |
| * }) | |
| * ] | |
| * | |
| * const prompt = Prompt.fromResponseParts(responseParts) | |
| * // Creates an assistant message with the response content | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromResponseParts = (parts: ReadonlyArray<Response.AnyPart>): Prompt => { | |
| if (parts.length === 0) { | |
| return empty | |
| } | |
| const assistantParts: Array<AssistantMessagePart> = [] | |
| const toolParts: Array<ToolMessagePart> = [] | |
| const activeTextDeltas = new Map<string, { text: string }>() | |
| const activeReasoningDeltas = new Map<string, { text: string }>() | |
| for (const part of parts) { | |
| switch (part.type) { | |
| // Text Parts | |
| case "text": { | |
| assistantParts.push(makePart("text", { text: part.text })) | |
| break | |
| } | |
| // Text Parts (streaming) | |
| case "text-start": { | |
| activeTextDeltas.set(part.id, { text: "" }) | |
| break | |
| } | |
| case "text-delta": { | |
| if (activeTextDeltas.has(part.id)) { | |
| activeTextDeltas.get(part.id)!.text += part.delta | |
| } | |
| break | |
| } | |
| case "text-end": { | |
| if (activeTextDeltas.has(part.id)) { | |
| assistantParts.push(makePart("text", activeTextDeltas.get(part.id)!)) | |
| } | |
| break | |
| } | |
| // Reasoning Parts | |
| case "reasoning": { | |
| assistantParts.push(makePart("reasoning", { text: part.text })) | |
| break | |
| } | |
| // Reasoning Parts (streaming) | |
| case "reasoning-start": { | |
| activeReasoningDeltas.set(part.id, { text: "" }) | |
| break | |
| } | |
| case "reasoning-delta": { | |
| if (activeReasoningDeltas.has(part.id)) { | |
| activeReasoningDeltas.get(part.id)!.text += part.delta | |
| } | |
| break | |
| } | |
| case "reasoning-end": { | |
| if (activeReasoningDeltas.has(part.id)) { | |
| assistantParts.push(makePart("reasoning", activeReasoningDeltas.get(part.id)!)) | |
| } | |
| break | |
| } | |
| // Tool Call Parts | |
| case "tool-call": { | |
| assistantParts.push(makePart("tool-call", { | |
| id: part.id, | |
| name: part.name, | |
| params: part.params, | |
| providerExecuted: part.providerExecuted ?? false | |
| })) | |
| break | |
| } | |
| // Tool Result Parts (skip preliminary results) | |
| case "tool-result": { | |
| if (part.preliminary !== true) { | |
| toolParts.push(makePart("tool-result", { | |
| id: part.id, | |
| name: part.name, | |
| isFailure: part.isFailure, | |
| result: part.encodedResult | |
| })) | |
| } | |
| break | |
| } | |
| // Tool Approval Request Parts | |
| case "tool-approval-request": { | |
| assistantParts.push(makePart("tool-approval-request", { | |
| approvalId: part.approvalId, | |
| toolCallId: part.toolCallId | |
| })) | |
| break | |
| } | |
| } | |
| } | |
| if (assistantParts.length === 0 && toolParts.length === 0) { | |
| return empty | |
| } | |
| const messages: Array<Message> = [] | |
| if (assistantParts.length > 0) { | |
| messages.push(makeMessage("assistant", { content: assistantParts })) | |
| } | |
| if (toolParts.length > 0) { | |
| messages.push(makeMessage("tool", { content: toolParts })) | |
| } | |
| return makePrompt(messages) | |
| } | |
| // ============================================================================= | |
| // Merging Prompts | |
| // ============================================================================= | |
| /** | |
| * Concatenates a prompt with additional raw input by concatenating messages. | |
| * | |
| * **Details** | |
| * | |
| * The returned prompt contains all messages from the original prompt followed | |
| * by the provided raw input, preserving message order. | |
| * | |
| * **Example** (Concatenating prompts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const merged = Prompt.concat(systemPrompt, "Hello, world!") | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const concat: { | |
| // ============================================================================= | |
| // Merging Prompts | |
| // ============================================================================= | |
| /** | |
| * Concatenates a prompt with additional raw input by concatenating messages. | |
| * | |
| * **Details** | |
| * | |
| * The returned prompt contains all messages from the original prompt followed | |
| * by the provided raw input, preserving message order. | |
| * | |
| * **Example** (Concatenating prompts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const merged = Prompt.concat(systemPrompt, "Hello, world!") | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (input: RawInput): (self: Prompt) => Prompt | |
| // ============================================================================= | |
| // Merging Prompts | |
| // ============================================================================= | |
| /** | |
| * Concatenates a prompt with additional raw input by concatenating messages. | |
| * | |
| * **Details** | |
| * | |
| * The returned prompt contains all messages from the original prompt followed | |
| * by the provided raw input, preserving message order. | |
| * | |
| * **Example** (Concatenating prompts) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const merged = Prompt.concat(systemPrompt, "Hello, world!") | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (self: Prompt, input: RawInput): Prompt | |
| } = dual(2, (self: Prompt, input: RawInput): Prompt => { | |
| const other = make(input) | |
| if (self.content.length === 0) { | |
| return other | |
| } | |
| if (other.content.length === 0) { | |
| return self | |
| } | |
| return fromMessages([...self.content, ...other.content]) | |
| }) | |
| // ============================================================================= | |
| // Manipulating Prompts | |
| // ============================================================================= | |
| /** | |
| * Creates a new prompt from the specified prompt with the system message set | |
| * to the specified text content. | |
| * | |
| * **Gotchas** | |
| * | |
| * This method removes and replaces any previous system message from the | |
| * prompt. | |
| * | |
| * **Example** (Replacing system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.setSystem( | |
| * prompt, | |
| * "You are an expert in programming" | |
| * ) | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const setSystem: { | |
| // ============================================================================= | |
| // Manipulating Prompts | |
| // ============================================================================= | |
| /** | |
| * Creates a new prompt from the specified prompt with the system message set | |
| * to the specified text content. | |
| * | |
| * **Gotchas** | |
| * | |
| * This method removes and replaces any previous system message from the | |
| * prompt. | |
| * | |
| * **Example** (Replacing system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.setSystem( | |
| * prompt, | |
| * "You are an expert in programming" | |
| * ) | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (content: string): (self: Prompt) => Prompt | |
| // ============================================================================= | |
| // Manipulating Prompts | |
| // ============================================================================= | |
| /** | |
| * Creates a new prompt from the specified prompt with the system message set | |
| * to the specified text content. | |
| * | |
| * **Gotchas** | |
| * | |
| * This method removes and replaces any previous system message from the | |
| * prompt. | |
| * | |
| * **Example** (Replacing system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are a helpful assistant." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.setSystem( | |
| * prompt, | |
| * "You are an expert in programming" | |
| * ) | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (self: Prompt, content: string): Prompt | |
| } = dual(2, (self: Prompt, content: string): Prompt => { | |
| const messages: Array<Message> = [makeMessage("system", { content })] | |
| for (const message of self.content) { | |
| if (message.role !== "system") { | |
| messages.push(message) | |
| } | |
| } | |
| return makePrompt(messages) | |
| }) | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content prepended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Prepending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.prependSystem( | |
| * prompt, | |
| * "You are a helpful assistant. " | |
| * ) | |
| * // result content: "You are a helpful assistant. You are an expert in programming." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const prependSystem: { | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content prepended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Prepending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.prependSystem( | |
| * prompt, | |
| * "You are a helpful assistant. " | |
| * ) | |
| * // result content: "You are a helpful assistant. You are an expert in programming." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (content: string): (self: Prompt) => Prompt | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content prepended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Prepending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.prependSystem( | |
| * prompt, | |
| * "You are a helpful assistant. " | |
| * ) | |
| * // result content: "You are a helpful assistant. You are an expert in programming." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (self: Prompt, content: string): Prompt | |
| } = dual(2, (self: Prompt, content: string): Prompt => { | |
| let system: SystemMessage | undefined = undefined | |
| for (const message of self.content) { | |
| if (message.role === "system") { | |
| system = makeMessage("system", { | |
| content: content + message.content | |
| }) | |
| break | |
| } | |
| } | |
| if (Predicate.isUndefined(system)) { | |
| system = makeMessage("system", { content }) | |
| } | |
| return makePrompt([system, ...self.content]) | |
| }) | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content appended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Appending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.appendSystem( | |
| * prompt, | |
| * " You are a helpful assistant." | |
| * ) | |
| * // result content: "You are an expert in programming. You are a helpful assistant." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| export const appendSystem: { | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content appended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Appending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.appendSystem( | |
| * prompt, | |
| * " You are a helpful assistant." | |
| * ) | |
| * // result content: "You are an expert in programming. You are a helpful assistant." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (content: string): (self: Prompt) => Prompt | |
| /** | |
| * Creates a new prompt with a leading system message. If the prompt already has | |
| * a system message, the new message uses the provided content appended to the | |
| * first existing system message's content; the original messages remain after | |
| * it. | |
| * | |
| * **Example** (Appending system instructions) | |
| * | |
| * ```ts | |
| * import { Prompt } from "effect/unstable/ai" | |
| * | |
| * const systemPrompt = Prompt.make([{ | |
| * role: "system", | |
| * content: "You are an expert in programming." | |
| * }]) | |
| * | |
| * const userPrompt = Prompt.make("Hello, world!") | |
| * | |
| * const prompt = Prompt.concat(systemPrompt, userPrompt) | |
| * | |
| * const replaced = Prompt.appendSystem( | |
| * prompt, | |
| * " You are a helpful assistant." | |
| * ) | |
| * // result content: "You are an expert in programming. You are a helpful assistant." | |
| * ``` | |
| * | |
| * @category combinators | |
| * @since 4.0.0 | |
| */ | |
| (self: Prompt, content: string): Prompt | |
| } = dual(2, (self: Prompt, content: string): Prompt => { | |
| let system: SystemMessage | undefined = undefined | |
| for (const message of self.content) { | |
| if (message.role === "system") { | |
| system = makeMessage("system", { | |
| content: message.content + content | |
| }) | |
| break | |
| } | |
| } | |
| if (Predicate.isUndefined(system)) { | |
| system = makeMessage("system", { content }) | |
| } | |
| return makePrompt([system, ...self.content]) | |
| }) | |
Xet Storage Details
- Size:
- 66.8 kB
- Xet hash:
- d287cd8c1f08d7b8145269fd341260e4496ce34e31d517435cfbc064a91456f9
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.