import type { Yieldable } from "effect/Effect"; import * as Effect from "effect/Effect"; import * as S from "effect/Schema"; import { Function } from "../../Schema.ts"; import { defineAspect, type Aspect } from "../Aspect.ts"; import { Parameter, type Parameters } from "./parameter.ts"; import { Result } from "./result.ts"; export const isTool = (artifact: any): artifact is Tool => artifact?.type === "tool"; export class ToolProps extends S.Class("ToolProps")({ alias: S.optional(Function<(model: string) => string | undefined>()), }) {} export type ToolHandler = ( params: Parameters.Of, ) => Effect.Effect, Err, Req>; export type Tool< ID extends string = string, References extends any[] = any[], Props extends ToolProps = ToolProps, Handler extends ToolHandler = any, > = Aspect & {}; export declare namespace Tool { export type Success = Result.Of; export type Error = Effect.Error>; export type Context = Effect.Services< ReturnType >; } export const Tool = defineAspect< ( id: ID, props?: Props, ) => ( template: TemplateStringsArray, ...references: References ) => (>( handler: Handler, ) => Aspect) & (>( handler: ( input: Parameters.Of, ) => Generator>, never>, ) => Aspect< Tool, "tool", ID, References, Props, ( input: Parameters.Of, ) => Effect.Effect< NoInfer>, [Eff] extends [never] ? never : [Eff] extends [Yieldable] ? E : never, [Eff] extends [never] ? never : [Eff] extends [Yieldable] ? R : never > >) >("tool", ToolProps).with({ input: Parameter, output: Result, });