import type * as Context from "effect/Context"; import * as Effect from "effect/Effect"; import type { RuntimeContext } from "../RuntimeContext.ts"; import type { Parameter } from "./Parameter.ts"; export type ToolParameters = { [toolName in Extract["~alchemy/Name"]]: Extract< Refs, Parameter >["schema"]["Type"]; }; export interface Tool< Name extends string = string, Refs extends any[] = any[], > { "~alchemy/Kind": "Tool"; "~alchemy/Name": Name; refs: Refs; template: TemplateStringsArray; params: { [p in keyof ToolParameters]: ToolParameters[p]; }; impl: (props: this["params"]) => Effect.Effect; new (): Tool; ( impl: Effect.Effect< (props: this["params"]) => Effect.Effect, Err, Req >, ): ToolImpl; ( impl: (props: this["params"]) => Effect.Effect, ): ToolImpl; } export interface ToolImpl< T extends Tool = any, Err = any, Req = any, > { "~alchemy/Kind": "ToolImpl"; tool: T; impl: (props: T["params"]) => Effect.Effect; new (): {}; } export const Tool: { ( name: Name, ): { ( template: TemplateStringsArray, ...refs: Refs ): Tool; }; (): { ( name: Name, ): { ( template: TemplateStringsArray, ...refs: Refs ): Tool & Context.Service< Self, | (( input: ToolParameters, ) => Effect.Effect) | Effect.Effect< ( input: ToolParameters, ) => Effect.Effect, never, RuntimeContext > >; }; }; } = ((name?: string) => name ? (template: TemplateStringsArray, ...refs: any[]) => makeTool(name, template, refs) : (name: string) => (template: TemplateStringsArray, ...refs: any[]) => makeTool(name, template, refs)) as any; const makeTool = (name: string, template: TemplateStringsArray, refs: any[]) => Object.assign( function (impl: (props: any) => Effect.Effect) {}, { "~alchemy/Kind": "Tool", "~alchemy/Name": name, refs, template, }, ) as any;