import * as Context from "../Context.ts"; import * as Effect from "../Effect.ts"; import * as Layer from "../Layer.ts"; import type * as SchemaAST from "../SchemaAST.ts"; import type * as Scope from "../Scope.ts"; import * as Stream from "../Stream.ts"; import * as AiError from "./AiError.ts"; import * as Tool from "./Tool.ts"; declare const TypeId: "~effect/ai/Toolkit"; /** * Represents a collection of tools which can be used to enhance the * capabilities of a large language model. * * **Example** (Defining AI toolkits) * * ```ts import.meta.vitest * import { Effect, Schema } from "effect" * import { Tool, Toolkit } from "effect/ai" * * const SearchDocs = Tool.make("SearchDocs", { * description: "Search project documentation", * parameters: Schema.Struct({ query: Schema.String }), * success: Schema.Array(Schema.String) * }) * * const SummarizeText = Tool.make("SummarizeText", { * description: "Summarize text", * parameters: Schema.Struct({ text: Schema.String }), * success: Schema.String * }) * * const AiToolkit = Toolkit.make(SearchDocs, SummarizeText) * * const ready = AiToolkit.pipe(Effect.provide(AiToolkit.toLayer({ * SearchDocs: ({ query }) => Effect.succeed([query]), * SummarizeText: ({ text }) => Effect.succeed(text) * }))) * * Object.keys((await Effect.runPromise(ready)).tools) // => ["SearchDocs", "SummarizeText"] * ``` * * @stability unstable * @category models * @since 4.0.0 */ export interface Toolkit> extends Effect.Effect, never, Tool.HandlersFor> { new (_: never): {}; readonly [TypeId]: typeof TypeId; /** * A record containing all tools in this toolkit. */ readonly tools: Tools; /** * A helper method which can be used for type-safe handler declarations. */ of>(handlers: Handlers): Handlers; /** * Converts a toolkit into a `Context` containing handlers for each tool * in the toolkit. */ toHandlers, EX = never, RX = never>(build: Handlers | Effect.Effect): Effect.Effect>, EX, RX>; /** * Converts a toolkit into a `Layer` containing handlers for each tool in the * toolkit. */ toLayer, EX = never, RX = never>( /** * Handler functions or Effect that produces handlers. */ build: Handlers | Effect.Effect): Layer.Layer, EX, Exclude>; } /** * Context provided to tool handlers during execution. * * @stability unstable * @category models * @since 4.0.0 */ export interface HandlerContext { /** * The unique identifier of the tool call, when available. */ readonly toolCallId?: string | undefined; /** * Emit a preliminary result during long-running tool calls. * * **Details** * * Preliminary results are streamed to the caller before the handler completes, * enabling real-time progress updates for lengthy operations. Results are * buffered without limit unless the caller provides `PreliminaryBuffer`. */ readonly preliminary: (result: Tool.Success) => Effect.Effect; } /** * Represents any `Toolkit` instance, used for generic constraints. * * @stability unstable * @category utility types * @since 4.0.0 */ export interface Any { readonly [TypeId]: typeof TypeId; readonly tools: Record; } /** * A utility type which can be used to extract the tool definitions from a * toolkit. * * @stability unstable * @category utility types * @since 4.0.0 */ export type Tools = T extends Toolkit ? Tools : never; /** * A utility type which transforms either a record or an array of tools into * a record where keys are tool names and values are the tool instances. * * @stability unstable * @category utility types * @since 4.0.0 */ export type ToolsByName = Tools extends Record ? { readonly [Name in keyof Tools]: Tools[Name]; } : Tools extends ReadonlyArray ? { readonly [Tool in Tools[number] as Tool["name"]]: Tool; } : never; /** * A utility type that maps tool names to their required handler functions. * * **Details** * * Handlers can return either the tool's custom failure type, an `AiErrorReason` * (which will be wrapped in `AiError`), or a full `AiError`. * * @stability unstable * @category utility types * @since 4.0.0 */ export type HandlersFrom> = { readonly [Name in keyof Tools as Tool.RequiresHandler extends true ? Name : never]: (params: Tool.Parameters, context: HandlerContext) => Effect.Effect, Tool.Failure | AiError.AiError | AiError.AiErrorReason, Tool.HandlerServices>; }; /** * A toolkit instance with registered handlers ready for tool execution. * * @stability unstable * @category models * @since 4.0.0 */ export interface WithHandler> { /** * The tools available in this toolkit instance. */ readonly tools: Tools; /** * Executes a tool call by name. * * **Details** * * Validates the input parameters, executes the corresponding handler, and * streams back both the typed result and encoded result. Streaming allows * handlers to emit preliminary results before completion. */ readonly handle: ( /** * The name of the tool to execute. */ name: Name, /** * Encoded parameters to decode and pass to the tool handler. */ params: Tool.ParametersEncoded, /** * The unique identifier of the tool call. */ toolCallId?: string, /** * Schema parse options for tool parameters. */ options?: SchemaAST.ParseOptions) => Effect.Effect, Tool.HandlerError | AiError.AiError, Tool.HandlerServices>, AiError.AiError, Tool.HandlerServices>; } /** * A utility type which can be used to extract the tools from a toolkit with * handlers. * * @stability unstable * @category utility types * @since 4.0.0 */ export type WithHandlerTools = T extends WithHandler ? Tools : never; /** * Cause annotation identifying the phase of a typed `Toolkit.handle` failure. * * **Details** * * Typed failures raised by `Toolkit.handle` carry one of these origins: * * - `"parameters"`: the tool call arguments failed to decode * - `"handler"`: the tool handler itself failed * - `"result"`: the handler's output failed to validate or encode * * Unannotated causes default to `"result"`, allowing consumers to treat them * as internal failures. * * Returned failures expose the same origin in `Tool.HandlerResult.failureOrigin`. * * **Example** (Reading a handler failure's origin) * * ```ts import.meta.vitest * import { Cause, Context, Effect, Schema, Stream } from "effect" * import { Tool, Toolkit } from "effect/ai" * * const toolkit = Toolkit.make(Tool.make("Lookup", { * failure: Schema.String, * failureMode: "error" * })) * * const program = Effect.gen(function*() { * const handlers = yield* toolkit * yield* handlers.handle("Lookup", {}).pipe(Effect.flatMap(Stream.runDrain)) * }).pipe( * Effect.catchCause((cause) => * Effect.succeed(Context.get(Cause.annotations(cause), Toolkit.FailureOrigin)) * ), * Effect.provide(toolkit.toLayer({ Lookup: () => Effect.fail("Not found") })) * ) * * await Effect.runPromise(program) // => "handler" * ``` * * @stability unstable * @category services * @since 4.0.0 */ export declare const FailureOrigin: Context.Reference; /** * Limits how many preliminary results `Toolkit.handle` buffers per tool call. * * **Details** * * Defaults to `"unbounded"`. Provide it as a positive integer around `handle`, * or around a program that calls it, and `HandlerContext.preliminary` suspends * once that many results are unconsumed. Any other value is a defect. * * The bound only applies to the stream returned by `handle`. Consume that * stream while the handler runs; waiting for the handler before reading it * deadlocks once the buffer fills. `LanguageModel` moves results into its own * buffers, so the bound does not limit memory end to end there. * * **Example** (Bounding preliminary results) * * ```ts import.meta.vitest * import { Effect, Schema, Stream } from "effect" * import { Tool, Toolkit } from "effect/ai" * * const toolkit = Toolkit.make(Tool.make("Progress", { success: Schema.Number })) * * const program = Effect.gen(function*() { * const handlers = yield* toolkit * const stream = yield* handlers.handle("Progress", {}).pipe( * Effect.provideService(Toolkit.PreliminaryBuffer, 16) * ) * const results = yield* Stream.runCollect(stream) * return results.length * }).pipe( * Effect.provide(toolkit.toLayer({ * Progress: Effect.fnUntraced(function*(_, ctx) { * for (let i = 0; i < 64; i++) yield* ctx.preliminary(i) * return 64 * }) * })) * ) * * await Effect.runPromise(program) // => 65 * ``` * * @stability unstable * @category services * @since 4.1.0 */ export declare const PreliminaryBuffer: Context.Reference; /** * An empty toolkit with no tools. * * **When to use** * * Use when you need an empty starting point for building toolkits or a default * toolkit value that can be extended with `merge`. * * @stability unstable * @category constructors * @since 4.0.0 */ export declare const empty: Toolkit<{}>; /** * Creates a new toolkit from the specified tools. * * **Details** * * This is the primary constructor for creating toolkits. It accepts multiple * tools and organizes them into a toolkit that can be provided to AI language * models. * * **Example** (Creating a toolkit) * * ```ts import.meta.vitest * import { Effect, Schema } from "effect" * import { Tool, Toolkit } from "effect/ai" * * const GetCurrentTime = Tool.make("GetCurrentTime", { * description: "Get the current timestamp", * success: Schema.Number * }) * * const GetWeather = Tool.make("get_weather", { * description: "Get weather information", * parameters: Schema.Struct({ location: Schema.String }), * success: Schema.Struct({ * temperature: Schema.Number, * condition: Schema.String * }) * }) * * const toolkit = Toolkit.make(GetCurrentTime, GetWeather) * const ready = toolkit.pipe(Effect.provide(toolkit.toLayer({ * GetCurrentTime: () => Effect.succeed(0), * get_weather: () => Effect.succeed({ temperature: 20, condition: "clear" }) * }))) * * Object.keys((await Effect.runPromise(ready)).tools) // => ["GetCurrentTime", "get_weather"] * ``` * * @stability unstable * @category constructors * @since 4.0.0 */ export declare const make: >(...tools: Tools) => Toolkit>; /** * A utility type which flattens a record type for improved IDE display. * * @stability unstable * @category utility types * @since 4.0.0 */ export type SimplifyRecord = { [K in keyof T]: T[K]; } & {}; /** * A utility type which merges a union of tool records into a single record. * * @stability unstable * @category utility types * @since 4.0.0 */ export type MergeRecords = { readonly [K in Extract]: Extract ? V : never, Tool.Any>; }; /** * A utility type which merges the tools from multiple toolkits into a single * record. * * @stability unstable * @category utility types * @since 4.0.0 */ export type MergedTools> = SimplifyRecord>>; /** * Merges multiple toolkits into a single toolkit. * * **Details** * * Combines all tools from the provided toolkits into one unified toolkit. * If there are naming conflicts, tools from later toolkits will override * tools from earlier ones. * * **Example** (Merging toolkits) * * ```ts import.meta.vitest * import { Effect, Schema } from "effect" * import { Tool, Toolkit } from "effect/ai" * * const mathToolkit = Toolkit.make( * Tool.make("add", { success: Schema.Number }), * Tool.make("subtract", { success: Schema.Number }) * ) * * const utilityToolkit = Toolkit.make( * Tool.make("get_time", { success: Schema.Number }), * Tool.make("get_weather", { success: Schema.String }) * ) * * const combined = Toolkit.merge(mathToolkit, utilityToolkit) * const ready = combined.pipe(Effect.provide(combined.toLayer({ * add: () => Effect.succeed(1), * subtract: () => Effect.succeed(0), * get_time: () => Effect.succeed(0), * get_weather: () => Effect.succeed("clear") * }))) * * Object.keys((await Effect.runPromise(ready)).tools) // => ["add", "subtract", "get_time", "get_weather"] * ``` * * @stability unstable * @category constructors * @since 4.0.0 */ export declare const merge: >( /** * The toolkits to merge together. */ ...toolkits: Toolkits) => Toolkit>; export {}; //# sourceMappingURL=Toolkit.d.ts.map