/** * `codeModeTool` — Code Mode for AI agents. * * Instead of exposing N tools to the model and having it call them one * at a time (N round-trips per turn, N tool-call tokens, the model has * to track intermediate state in context), Code Mode exposes ONE tool: * `run_code`. The model sees the typed TypeScript signatures of all * underlying tools and emits a single function that chains them. * * Pattern was popularized by Cloudflare's Dynamic Workers (April 2026 * blog post: "100× faster than containers"). Anthropic's programmatic * tool calling is the same idea — execution pauses on a sub-tool call, * the API yields a tool_use, you return a result, execution resumes. * Both vendors report ~80% token reduction on multi-tool turns. * * ```ts * import { codeModeTool } from '@absolutejs/ai/tools'; * * const tools = { * run_code: codeModeTool({ * timeout: 5000, * tools: { * search_products: { * description: 'Full-text search the product catalogue.', * tsSignature: '(query: string) => Promise', * handler: async (q) => db.products.search(q as string), * }, * get_product: { * description: 'Fetch one product by id.', * tsSignature: '(id: string) => Promise', * handler: async (id) => db.products.findById(id as string), * }, * }, * types: ` * type Product = { id: string; name: string; price: number }; * `, * }), * }; * ``` * * The model emits a single function: * * ```js * const items = await search_products('hat'); * const cheapest = items.sort((a, b) => a.price - b.price)[0]; * const detail = await get_product(cheapest.id); * return { name: detail.name, price: detail.price }; * ``` * * One sandbox eval. Two host-fn calls. One returned value. The model's * context only ever sees the final return — intermediate tool results * don't enter the conversation window, so multi-step workflows are * dramatically cheaper. * * Each underlying tool's `handler` runs on the HOST side (not in the * sandbox). Async host fns work on both FFI (via the 0.4 pump) and * Worker backends since isolated-jsc 0.4+. Errors thrown by host * handlers propagate into the sandbox as JS Errors the model can * catch and recover from. */ import type { AIToolDefinition } from "../../../types/ai"; /** * One callable surfaced to the sandbox. The `tsSignature` shows up in * the model-visible description; `handler` runs on the host when the * sandbox calls it. */ export type CodeModeHostTool = { /** One-line human description of what this tool does. */ description: string; /** TypeScript signature shown to the model. Example: * `'(query: string, options?: { limit?: number }) => Promise'`. * The model writes JS against this signature; we don't enforce it at * runtime — type-check is the model's responsibility. */ tsSignature: string; /** Host implementation. Receives positional args as the model passed * them. Return value is structure-cloned back into the sandbox. */ handler: (...args: unknown[]) => unknown; }; /** Options for {@link codeModeTool}. */ export type CodeModeToolOptions = { /** Map of host-tool name → {@link CodeModeHostTool}. */ tools: Record; /** * Optional shared TypeScript declarations stitched into the prompt * (type aliases, interfaces, etc.) so signatures can reference them. * Use raw TS source; no parsing happens host-side. */ types?: string; /** * Per-isolate heap memory cap (MB). Default 64. As with the regular * code-execution tool, FFI's cold heap is much smaller than Worker's, * but per-call retention scales similarly. */ memoryLimit?: number; /** Wall-clock timeout per `run_code` call (ms). Default 5000. */ timeout?: number; /** * isolated-jsc backend. Defaults to `'auto'`. Since isolated-jsc 0.4 * both backends support async host fns, so the choice is purely * about cold spawn (FFI wins ~6×) vs Web APIs availability (Worker * has `URL` / `TextEncoder` / `WebSocket`; FFI does not). */ backend?: "auto" | "ffi" | "worker"; /** * Override the auto-generated description. By default we emit the * model-facing prompt: a short instruction header + the host fn * signatures + any shared `types`. */ description?: string; /** Pool size cap. Default 8. */ poolSize?: number; /** Recycle the isolate after N successful runs. Default 50. */ recycleAfter?: number; }; export declare const codeModeTool: (options: CodeModeToolOptions) => AIToolDefinition;