/** * Tools read from a service's own API description, an OpenAPI document: one tool per operation, its * name, description, and parameters the service's, the capabilities it declares read from its method, * and what it returns kept as a schema. Given where the API lives, each tool calls it; without, the * tools describe the API and run nowhere, as `emulatedTools()` wants them. */ import type { ToolContext, ToolDefinition } from '../types/messages.js'; /** An OpenAPI 3 document, as parsed JSON. Only what tools are read from is typed. */ export interface OpenApiDocument { /** The OpenAPI version, `3.0.x` or `3.1.x`. */ openapi: string; /** The API's title and version. */ info?: { title?: string; version?: string; description?: string; }; /** Where the API is served. */ servers?: Array<{ url: string; variables?: Record; }>; /** Its operations, by path and method. */ paths?: Record>; /** Schemas, parameters, request bodies, and responses its operations refer to. */ components?: Record; [key: string]: unknown; } /** One operation of the API, as a tool reads it. */ export interface OpenApiOperation { /** The tool's name: the operation's id, or its method and path. */ name: string; /** The HTTP method, in capitals. */ method: string; /** The path, with its `{parameters}`. */ path: string; /** The operation's id, when it has one. */ operationId?: string; /** Its summary, when it has one. */ summary?: string; /** Its tags. */ tags: string[]; /** What it does to the service, read from its method: `read` for GET, HEAD, OPTIONS, and TRACE, `destructive` for DELETE, and `write` for the rest. */ access: 'read' | 'write' | 'destructive'; /** * The security it asks for, as the document writes it: alternatives, any one of which will do, each * the schemes it needs at once with their scopes. Empty when it asks for none. */ security: Array>; } /** * A credential for one of the API's security schemes: the API key, bearer token, or access token as * text or `{ token }`; `{ username, password }` for HTTP basic; or `{ clientId, clientSecret }` for an * OAuth 2.0 client-credentials flow, whose token is fetched and kept until it expires. */ export type OpenApiCredential = string | { token: string; } | { username: string; password: string; } | { clientId: string; clientSecret: string; }; /** A request or callback the API sends to the application, which no tool calls: its name and the body it carries. */ export interface OpenApiWebhook { /** The webhook's name, or the operation and callback it belongs to. */ name: string; /** `webhook` for one of the document's webhooks, `callback` for an operation's callback. */ source: 'webhook' | 'callback'; /** The HTTP method it arrives with, in capitals. */ method: string; /** For a callback, the expression that names where it is sent, such as `{$request.body#/callbackUrl}`. */ expression?: string; /** The JSON Schema of the body it carries, when it carries JSON. */ body?: Record; } /** What a tool's headers are chosen from: the operation, and the call's context. */ export interface OpenApiHeadersRequest { /** The operation being called. */ operation: OpenApiOperation; /** The call's context: its tenant, principal, and thread. */ context?: ToolContext; } /** Options for `openApiTools()`. */ export interface OpenApiToolsOptions { /** The API's name, in each tool's capabilities. Defaults to its title, as a slug, or `api`. */ name?: string; /** * Where the API lives, its path prefix included, such as `https://shop.example.com/api`. Defaults * to the document's first server, resolved against `documentUrl` when relative. Without one, the * tools describe the API and run nowhere. */ baseUrl?: string; /** Where the document came from, to resolve a relative server URL against. */ documentUrl?: string; /** * Headers every call sends, such as authorization, or a function choosing them per operation and * call, such as by its tenant. They win over a header parameter the model sets. */ headers?: Readonly> | ((request: OpenApiHeadersRequest) => Record | Promise>); /** Which operations become tools. Defaults to every one. */ include?: (operation: OpenApiOperation) => boolean; /** Put before every tool's name, with an underscore, so two APIs' operations stay apart. */ prefix?: string; /** How long a call may take, in milliseconds. Defaults to 30 seconds. */ timeoutMs?: number; /** The largest answer a call reads, in bytes; a larger one fails the call. Defaults to 1 MB. */ maxResponseBytes?: number; /** Replaces the global `fetch`. */ fetch?: typeof globalThis.fetch; /** * Credentials for the API's own security schemes, by the name the document gives each, or a * function choosing one per call, such as by its tenant. Each call sends those its operation asks * for: the first of its alternatives every scheme of which has a credential, as an API key in its * header, query, or cookie, HTTP basic or bearer, or an OAuth 2.0 or OpenID Connect token. With * credentials given, a call whose operation asks for schemes none of which has one fails before it * is sent. They win over `headers`. */ credentials?: Readonly OpenApiCredential | Promise)>>; } /** An API's operations as tools, with what each returns. */ export interface OpenApiTools { /** The API's name, as its tools' capabilities carry it. */ name: string; /** Where the tools send their calls, when they run. */ baseUrl?: string; /** One tool per operation. */ tools: ToolDefinition[]; /** The operations, in the tools' order. */ operations: OpenApiOperation[]; /** The JSON Schema of what each tool returns, by name: its first success response's. Pass it to `emulatedTools()` as `results`. */ results: Record>; /** What the API sends the application, which no tool calls: its webhooks and its operations' callbacks. */ webhooks: OpenApiWebhook[]; } /** Why an API could not be read into tools, or a call to it failed. */ export declare class OpenApiError extends Error { /** * `OPENAPI_INVALID` for a malformed document or call, `OPENAPI_UNSUPPORTED` for one these tools * cannot read, such as Swagger 1.2 or a reference outside the document not bundled first, and * `OPENAPI_REQUEST` for a call the API refused or did not answer. */ readonly code: 'OPENAPI_INVALID' | 'OPENAPI_UNSUPPORTED' | 'OPENAPI_REQUEST'; /** The HTTP status the API answered with, when it did. */ readonly status?: number | undefined; constructor(message: string, /** * `OPENAPI_INVALID` for a malformed document or call, `OPENAPI_UNSUPPORTED` for one these tools * cannot read, such as Swagger 1.2 or a reference outside the document not bundled first, and * `OPENAPI_REQUEST` for a call the API refused or did not answer. */ code: 'OPENAPI_INVALID' | 'OPENAPI_UNSUPPORTED' | 'OPENAPI_REQUEST', /** The HTTP status the API answered with, when it did. */ status?: number | undefined); } /** * Reads an OpenAPI 3 document into tools, one per operation: named by its `operationId`, or its * method and path; described by its summary; its path, query, and header parameters, and the fields * of a JSON body, as the tool's parameters. Each declares `api.read`, `api.write`, or * `api.destructive` with the API's name and its own, as its method says, and `network` for the * API's host when it runs. References within the document are followed; one outside it is refused * here, and followed by `loadOpenApiTools()` or `bundleOpenApiDocument()`. A Swagger 2.0 document is * read as the OpenAPI 3 document it describes. Each call sends the credentials its operation's * security asks for, from `credentials`. * * ```ts * const shop = openApiTools(JSON.parse(await readFile('shop.openapi.json', 'utf8')), { * baseUrl: 'https://shop.example.com/api', * headers: { authorization: `Bearer ${process.env.SHOP_TOKEN}` }, * }); * const agent = createAgent({ client: ai, tools: shop.tools }); * ``` */ export declare function openApiTools(document: OpenApiDocument | string, options?: OpenApiToolsOptions): OpenApiTools; /** * Fetches an OpenAPI document, as JSON, and reads it into tools, resolving its servers against where * it came from, and following its references to other documents on the same origin, or as * `references` allows. */ export declare function loadOpenApiTools(url: string, options?: OpenApiToolsOptions & Pick): Promise; /** * A Swagger 2.0 document as the OpenAPI 3.0 document it describes: its host, base path, and schemes * as a server; its definitions, parameters, responses, and security definitions as components; a * body parameter, and form data, as a request body of what it consumes; and each response's schema as * content of what it produces. Every reference is moved with what it names. */ export declare function swaggerToOpenApi(swagger: Record): OpenApiDocument; /** Options for `bundleOpenApiDocument()`. */ export interface OpenApiBundleOptions { /** Where the document came from: references outside it are read relative to it. */ documentUrl: string; /** * Which documents a reference may name: `same-origin`, the default, only those on the document's * own origin; `any`, any HTTP or HTTPS URL; or a function deciding each. A document never makes the * tools fetch where it was not allowed to. */ references?: 'same-origin' | 'any' | ((url: string) => boolean); /** The most documents read, the first included. Defaults to 50. */ maxDocuments?: number; /** The largest document read, the first included, in bytes. Defaults to 5 MB. */ maxBytes?: number; /** Replaces the global `fetch`. */ fetch?: typeof globalThis.fetch; } /** * The document with every reference outside it read in its place: each other document fetched, as * JSON, relative to the one that names it, its own references followed the same way, and a reference * back to one still being read left as a description. `loadOpenApiTools()` does this before reading the * document into tools. */ export declare function bundleOpenApiDocument(document: OpenApiDocument, options: OpenApiBundleOptions): Promise;