///
import * as Effect from "effect/Effect";
import { makeLanguageModelLayer } from "../AI/LanguageModel.ts";
import { AI, WorkersAIError, type AIClient } from "./AI.ts";
import * as Binding from "./Binding.ts";
import { makeBindingLayer } from "./BindingLayer.ts";
/** The binding value produced by calling {@link AI} (declared on `env` or `yield*`-ed). */
export type AIBinding = Binding.Binding;
/**
* The layer that provides the Effect-native interface for the Cloudflare
* Workers AI binding.
*
* Provide it on the Worker effect (`Effect.provide(Cloudflare.Workers.AIBinding)`)
* so that yielding an {@link AI} binding attaches the native `ai` binding to
* the surrounding Worker at deploy time and, at runtime, resolves to the
* Effect-native {@link AIClient} (wrapping the raw `Ai` handle so `run` /
* `models` return Effects and `model(...)` yields a `LanguageModel` layer).
*/
export const AIBinding = makeBindingLayer(AI, (raw) => {
const self: AIClient = {
raw,
run: (model, inputs, options) =>
Effect.gen(function* () {
const ai = yield* raw;
return yield* tryPromise(() => ai.run(model, inputs, options));
}),
models: (params) =>
Effect.gen(function* () {
const ai = yield* raw;
return yield* tryPromise(() => ai.models(params));
}),
model: (options) =>
makeLanguageModelLayer({
...options,
client: self,
}),
};
return self;
});
const tryPromise = (
fn: () => Promise,
): Effect.Effect =>
Effect.tryPromise({
try: fn,
catch: (error) =>
new WorkersAIError({
message:
error instanceof Error
? error.message
: "Unknown Workers AI runtime error",
cause: error,
}),
});