import { type Schema as JTDSchemaJson } from '../jtd/index.js'; import type { SignalDescriptorJson } from '../proto/index.js'; import { type ConvertFailure, type ConvertSuccess, type ConvertSuccessBinary, type ConvertSuccessJson, type ConvertSuccessSignals } from '../schema-utils.js'; /** * JSON Schema subset accepted by the Anthropic structured-output API. * * This is the provider-specific representation produced by * {@link AnthropicConversion}. It covers the keywords that Anthropic * inspects when constraining model output: `type`, `properties`, `required`, * `additionalProperties`, `enum`, `const`, `format`, `items`, `anyOf`, * `$defs`, `$ref`, and `description`. */ export interface AnthropicSchema { type?: string | string[]; description?: string; properties?: Record; required?: string[]; additionalProperties?: false; enum?: (string | number | boolean | null)[]; const?: string | number | boolean | null; format?: string; items?: AnthropicSchema; anyOf?: AnthropicSchema[]; $defs?: Record; $ref?: string; } export type { ConvertFailure, ConvertResult, ConvertSuccess, ConvertSuccessBinary, ConvertSuccessJson, ConvertSuccessSignals } from '../schema-utils.js'; /** * Converts JTD schemas or Adapt signal descriptors into Anthropic-compatible * JSON Schema, and converts raw LLM output back into validated data. * * ### JTD form mapping * - **type** -- mapped to the corresponding JSON Schema `type` (`string`, * `number`, `integer`, `boolean`). Integer sub-types (int8 .. uint32) * have their bounds described in `description` (Anthropic does not * support `minimum`/`maximum`). `timestamp` becomes `string` with * `format: "date-time"`. * - **enum** -- mapped to `type: "string"` with an `enum` array. * - **elements** -- mapped to `type: "array"` with `items`. * - **properties / optionalProperties** -- mapped to `type: "object"` with * `properties`, `required`, and `additionalProperties: false`. Unlike * OpenAI, **optional properties are kept genuinely optional** -- they are * not added to the `required` array. This avoids forced nullability. * - **values** -- mapped to an array of `{key, value}` objects because * Anthropic does not support `additionalProperties` with a schema value. * During {@link convert}, the array is coerced back into a plain `Record`. * - **discriminator** -- mapped to `anyOf` with one variant per mapping * entry. Each variant is a flat object containing the discriminator key * (with a `const` value) plus the variant's own properties. * * ### Unstructured schemas * Empty JTD schemas or schemas with only `additionalProperties: true` are * considered unstructured. They produce an empty `{}` JSON Schema with * `strict: false`, and during {@link convert} the raw string output is * parsed via `JSON.parse` back into an arbitrary value. * * ### MIME formats * MIME signal formats become `type: "string"` with a description requesting * base64-encoded content. On {@link convert}, the base64 string is decoded * into a {@link ConvertSuccessBinary} result. * * ### Circular references * Anthropic does not support recursive schemas. {@link fromJTD} will throw * if any circular reference is detected among the JTD definitions. * * ### Serialization * `JSON.stringify(conv)` produces a JSON-safe object via {@link toJSON}. * Use {@link fromJSON} to restore a fully functional instance from the * serialized form (string or parsed object). * * ```ts * const conv = AnthropicConversion.fromJTD(jtdSchema); * conv.schema; // Anthropic JSON Schema to pass to the LLM * conv.strict; // whether strict mode applies * conv.convert(output); // coerce + validate -> ConvertResult * * // Serialize & restore * const cached = JSON.stringify(conv); * const restored = AnthropicConversion.fromJSON(cached); * ``` */ export declare class AnthropicConversion { /** The Anthropic-specific JSON Schema to pass to the Anthropic API as the tool input schema. */ readonly schema: AnthropicSchema; /** * Whether the schema qualifies for Anthropic strict structured-output mode. * * This is `false` when the root JTD schema is empty or unstructured (e.g. * the empty schema `{}` or a properties form with no real properties and * `additionalProperties: true`). In that case `schema` is `{}` and the * model output is unconstrained. */ readonly strict: boolean; /** * The original JTD schema used to build this conversion. * Set when created via {@link fromJTD}; `undefined` when created via {@link fromSignal}. */ readonly jtdSchema?: JTDSchemaJson; /** * The original signal descriptor used to build this conversion. * Set when created via {@link fromSignal}; `undefined` when created via {@link fromJTD}. */ readonly descriptor?: SignalDescriptorJson; /** * The original signal descriptors used to build this conversion. * Set when created via {@link fromSignals}; `undefined` otherwise. */ readonly descriptors?: SignalDescriptorJson[]; /** * When true, MIME-format signals expect blob reference strings instead of * base64-encoded data objects. Mixed signals (JTD + MIME) use a discriminated * anyOf with `kind: "value" | "reference"`. */ readonly referenceMode: boolean; /** * Build a conversion from a JTD schema. * * Recursively converts every JTD form into the equivalent Anthropic JSON * Schema node. Definitions (`jtdSchema.definitions`) are emitted as `$defs` * at the root level, and references become `$ref` pointers. * * If the root schema is unstructured, the result has an empty `schema` and * `strict: false`. * * @param jtdSchema - A valid JTD schema (RFC 8927). * @returns A new {@link AnthropicConversion} with `jtdSchema` set. * @throws If the schema contains an unknown JTD type, an unresolved `ref`, * nesting exceeding 32 levels, or **any circular reference** among * definitions (Anthropic does not support recursive schemas). */ static fromJTD(input: unknown): AnthropicConversion; /** * Build a conversion from an Adapt signal descriptor. * * If the descriptor has a single format, its schema is used directly * (unwrapped). If it has multiple formats, a wrapper object schema is * produced with `format_0`, `format_1`, ... properties. Unlike OpenAI, * the format properties are genuinely optional (not listed in `required`), * so the LLM only needs to provide the one it chooses. * * @param descriptor - An Adapt signal descriptor with one or more formats. * @returns A new {@link AnthropicConversion} with `descriptor` set. * @throws If the descriptor has no formats, or a format has neither * `jtdSchema` nor `mimeType`. */ static fromSignal(descriptor: SignalDescriptorJson, sharedDefs?: Record, referenceMode?: boolean): AnthropicConversion; /** * Build a conversion from multiple signal descriptors. * * Produces an object schema with one property per signal, suitable for * use as structured output parameters. Each signal's schema is built via * {@link fromSignal} internally. * * For Anthropic, optional signals are genuinely optional -- they are NOT * added to `required` (no nullable wrapping needed). * * Receiver/transceiver compatible: * ```ts * const conv = AnthropicConversion.fromSignals( * receiver.signals!, * receiver.description, * receiver.name * ); * ``` * * @param signals - Array of signal descriptors. * @param description - Optional description for the compound schema. * @param label - Optional label (reserved for other providers). * @returns A new {@link AnthropicConversion} with `descriptors` set. * @throws If any signal has no formats or an invalid format. */ static fromSignals(signals: SignalDescriptorJson[], description?: string, label?: string, referenceMode?: boolean): AnthropicConversion; /** * Restore an {@link AnthropicConversion} from its serialized form. * * Accepts either the JSON string produced by `JSON.stringify(conv)` or the * already-parsed plain object. The original `jtdSchema` or `descriptor` is * re-processed through the corresponding factory, so the restored instance * is fully functional. * * @param data - A JSON string or parsed object previously produced by {@link toJSON}. * @returns A fully reconstructed {@link AnthropicConversion}. * @throws If the serialized data contains neither `jtdSchema` nor `descriptor`. */ static fromJSON(data: string | Record): AnthropicConversion; private constructor(); /** * Convert raw LLM output into a validated result. * * For JTD-based conversions, the value is coerced to conform to the original * JTD schema: * - Non-integer numbers are rounded for integer types. * - `{key, value}` arrays from the values form are reassembled into Records. * - Unstructured/empty schemas parse the raw JSON string via `JSON.parse`. * * Unlike OpenAI, no null-stripping is needed for optional properties because * Anthropic keeps them genuinely optional (not in `required`). * * The coerced value is then validated against the JTD schema. Returns * {@link ConvertSuccessJson} on success. * * For MIME-based conversions, the value is expected to be a base64 string * which is decoded into raw bytes. Returns {@link ConvertSuccessBinary}. * * For multi-format signals, the first non-null `format_N` property is * selected and converted individually. * * @param value - The value to convert. JSON for JTD, or `{ data, mimeType, filename }` for MIME. * @returns A {@link ConvertResult} indicating success or failure with errors. */ convert: (value: unknown) => T | ConvertFailure; /** * Produce a JSON-serializable representation of this conversion. * * The output includes the Anthropic `schema`, `strict` flag, and either the * original `jtdSchema` or `descriptor` (whichever was used to create this * instance), which is sufficient to fully restore the conversion via * {@link fromJSON}. * * Called automatically by `JSON.stringify(conv)`. */ toJSON(): Record; } /** * Convenience alias for {@link AnthropicConversion.fromJTD}. * * @param jtdSchema - A valid JTD schema (RFC 8927). * @returns A new {@link AnthropicConversion}. */ export declare function convertToAnthropicSchema(jtdSchema: unknown): AnthropicConversion; /** * Convenience alias for {@link AnthropicConversion.fromSignal}. * * @param descriptor - An Adapt signal descriptor. * @returns A new {@link AnthropicConversion}. */ export declare function convertSignalToAnthropicSchema(descriptor: SignalDescriptorJson): AnthropicConversion; //# sourceMappingURL=index.d.ts.map