///
import * as Data from "effect/Data";
import type * as Effect from "effect/Effect";
import type * as Layer from "effect/Layer";
import type { LanguageModel } from "effect/unstable/ai/LanguageModel";
import type { RuntimeContext } from "../../RuntimeContext.ts";
import type { LanguageModelOptions } from "../AI/LanguageModel.ts";
import type { AIBinding } from "./AIBinding.ts";
import * as Binding from "./Binding.ts";
const TypeId = "Cloudflare.Workers.AI" as const;
type TypeId = typeof TypeId;
/**
* Error raised by Workers AI runtime operations (`ai.run`, `ai.models`, …).
*/
export class WorkersAIError extends Data.TaggedError("WorkersAIError")<{
/**
* Human-readable runtime error message.
*/
message: string;
/**
* Original error thrown by the Cloudflare runtime binding.
*/
cause: unknown;
}> {}
/**
* The native Cloudflare Workers AI binding — run inference on Workers AI
* models directly from a Worker, with no AI Gateway (or any other cloud
* resource) required. This is the plain `{ type: "ai" }` Worker binding: the
* runtime value is the same `env.AI` handle you would declare in
* `wrangler.json`.
*
* `AI` is a single value that is at once the `Binding.Service` tag, the
* callable that produces an {@link AIBinding}, and the type. Declare it on a
* Worker's `env` (it flows through `InferEnv` → the runtime `Ai` handle) or
* `yield*` it inside an Effect-native Worker to attach the binding and obtain
* the {@link AIClient}.
*
* Use `Cloudflare.AI.Gateway` + `QueryGateway` instead when you want requests
* routed through an AI Gateway (caching, rate limiting, logs); use `AI` when
* you just want to call Workers AI models.
*
*
* ### Effect-style Worker (recommended)
* **Example:** Run a Workers AI model
* ```typescript
* Cloudflare.Worker("AiWorker", { main: import.meta.url },
* Effect.gen(function* () {
* const ai = yield* Cloudflare.Workers.AI();
* return {
* fetch: Effect.gen(function* () {
* const result = yield* ai.run("@cf/meta/llama-3.3-70b-instruct-fp8-fast", {
* prompt: "What is the origin of the phrase Hello, World?",
* }).pipe(Effect.orDie);
* return yield* HttpServerResponse.json(result);
* }),
* };
* }).pipe(Effect.provide(Cloudflare.Workers.AIBinding)),
* );
* ```
*
* ### Effect AI LanguageModel
* **Example:** `ai.model(...)` -> Effect AI `LanguageModel`
* `model(options)` produces a `Layer`
* that translates `LanguageModel.generateText` / `streamText` calls
* (including tool calls) into `ai.run(...)` against the bound Workers AI
* model — the same adapter AI Gateway's `QueryGateway` uses, minus the
* gateway routing.
* ```typescript
* const ai = yield* Cloudflare.Workers.AI();
*
* const languageModel = ai.model({
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
* parameters: { temperature: 0.7, maxTokens: 1024 },
* });
*
* const response = yield* LanguageModel.generateText({ prompt }).pipe(
* Effect.provide(languageModel),
* );
* ```
*
* ### Binding to an Async Worker
* **Example:** Example
* ```typescript
* export const Worker = Cloudflare.Worker("Worker", {
* main: "./src/worker.ts",
* env: { AI: Cloudflare.Workers.AI() },
* });
*
* export type WorkerEnv = Cloudflare.InferEnv;
* // { AI: Ai }
* ```
*
* @see https://developers.cloudflare.com/workers-ai/
*
* @binding
* @product Workers AI
* @category AI
*/
export interface AI extends Binding.Service {
/**
* @param name Binding name (logical id) — the `env` key it resolves to.
* @default "AI"
*/
(name?: string): AIBinding;
}
export const AI = Binding.Service({
id: TypeId,
defaultName: "AI",
toWorkerBinding: (binding) => ({ type: "ai", name: binding.name }),
});
export const isAI = (value: unknown): value is AIBinding =>
Binding.isBinding(value) && value.kind === TypeId;
/**
* Effect-native client for a Cloudflare Workers AI binding. Wraps the runtime
* `Ai` handle so each operation returns an Effect tagged with
* {@link WorkersAIError}, and provides a `model(options)` factory that
* produces an `effect/unstable/ai` `LanguageModel` `Layer`.
*/
export interface AIClient {
/**
* Effect resolving to the raw Workers AI runtime binding.
*/
raw: Effect.Effect;
/**
* Run inference on a Workers AI model. Typed by the model catalog from
* `@cloudflare/workers-types` — pass `options` (e.g. `returnRawResponse`,
* `gateway`) through to the runtime binding.
*/
run(
model: Name,
inputs: AiModels[Name]["inputs"],
options?: AiOptions,
): Effect.Effect<
AiModels[Name]["postProcessedOutputs"],
WorkersAIError,
RuntimeContext
>;
/**
* List Workers AI models from the catalog, optionally filtered.
*/
models(
params?: AiModelsSearchParams,
): Effect.Effect;
/**
* Provide an `effect/unstable/ai` `LanguageModel` layer backed by this
* binding and the given Workers AI model.
*/
model(
options: Omit,
): Layer.Layer;
}