import { Effect, Schema } from "effect" import type { Namespace } from "./namespace.js" import type { Tools } from "./tools.js" /** * JSON Schema subset for model-visible signatures. CodeMode does not validate values against * these schemas. */ export type JsonSchema = { readonly type?: string | ReadonlyArray readonly enum?: ReadonlyArray readonly const?: unknown readonly anyOf?: ReadonlyArray readonly oneOf?: ReadonlyArray readonly allOf?: ReadonlyArray readonly properties?: Readonly> readonly required?: ReadonlyArray readonly items?: JsonSchema readonly additionalProperties?: boolean | JsonSchema readonly description?: string readonly default?: unknown readonly format?: string readonly deprecated?: boolean readonly minimum?: number readonly maximum?: number readonly exclusiveMinimum?: number readonly exclusiveMaximum?: number readonly multipleOf?: number readonly minLength?: number readonly maxLength?: number readonly pattern?: string readonly minItems?: number readonly maxItems?: number readonly uniqueItems?: boolean readonly $ref?: string readonly $defs?: Readonly> readonly definitions?: Readonly> } /** Either a validating Effect Schema or a render-only JSON Schema document. */ export type SchemaType = Schema.Decoder | JsonSchema /** Executable tool exposed through CodeMode's `tools` object. */ export type Tool = { readonly _tag: "CodeModeTool" readonly description: string readonly input: SchemaType readonly output: SchemaType | undefined readonly execute: (input: unknown) => Effect.Effect } type InputType = S extends Schema.Decoder ? S["Type"] : unknown type ResultType = S extends undefined ? void : S extends Schema.Decoder ? S["Encoded"] : unknown /** Options for declaring one CodeMode tool. */ export type Options = { readonly description: string readonly input: I readonly output?: O readonly execute: (input: InputType) => Effect.Effect, unknown, R> } export const isTool = (value: Tool | Namespace | Tools | undefined): value is Tool => value !== undefined && Object.hasOwn(value, "_tag") && value._tag === "CodeModeTool" /** * Declares one schema-described tool available to a CodeMode program through `tools.*`. * * Effect Schemas validate values; JSON Schemas only shape the model-visible signature. * Without `output`, results are exposed as `void`. Hosts remain responsible for authorization * and durable side effects. */ export const make = ( options: Options, ): Tool => ({ _tag: "CodeModeTool", description: options.description, input: options.input, output: options.output, execute: (input) => options.execute(input as InputType), })