/** * Connector Registry — central catalog for LLM provider connectors. * * Connectors are adapters for specific LLM API transport protocols. The registry * supports both direct connector registration and provider-config-based * resolution. * * @module */ import type { Api, Connector, ModelDescriptor, ResolvedAuth } from "../types.js"; /** * Central registry for LLM provider connectors. * * @example * ```ts * import { ConnectorRegistry } from "clawtools/connectors"; * * const registry = new ConnectorRegistry(); * * // Register a custom connector * registry.register({ * id: "my-llm", * label: "My LLM", * provider: "custom", * api: "openai-completions", * envVars: ["MY_LLM_API_KEY"], * async *stream(model, context, options) { * yield { type: "text_delta", delta: "Hello from my connector!" }; * yield { type: "done", stopReason: "stop" }; * }, * }); * * // Lookup by provider * const connector = registry.getByProvider("custom"); * ``` */ export declare class ConnectorRegistry { private connectors; private providerIndex; private apiIndex; /** * Register a connector. * * The connector's `id` is the primary key — registering a second connector * with the same `id` silently replaces the first. * * **Provider index (last-write-wins):** `connector.provider` is also indexed * for {@link getByProvider} lookups. If two connectors share the same * `provider` string (e.g., both declare `provider: "openai"`), the second * call to `register()` wins: `getByProvider("openai")` will return the * most-recently-registered connector. The earlier connector remains * accessible via its `id` through {@link get}. * * @param connector - The connector to register. */ register(connector: Connector): void; /** * Get a connector by its unique ID. */ get(id: string): Connector | undefined; /** * Get a connector by provider name (e.g., "anthropic", "openai"). */ getByProvider(provider: string): Connector | undefined; /** * Get all connectors for a given API transport. */ getByApi(api: Api): Connector[]; /** * List all registered connectors. */ list(): Connector[]; /** * Iterate over all registered connectors. * * Makes `ConnectorRegistry` iterable so you can write: * ```ts * const ct = await createClawtools(); * for (const connector of ct.connectors) { * console.log(connector.id); * } * // or spread into an array: * const all = [...ct.connectors]; * ``` */ [Symbol.iterator](): Iterator; /** * List all registered provider names. */ listProviders(): string[]; /** * Check whether a connector with the given ID is registered. */ has(id: string): boolean; /** * Remove a connector from the registry. */ unregister(id: string): boolean; /** * Remove all registered connectors. */ clear(): void; /** * The number of registered connectors. */ get size(): number; } /** Callback for resolving authentication for a provider. */ export type AuthResolver = (provider: string) => ResolvedAuth | undefined; /** * Resolves authentication credentials for connectors. * * Checks environment variables and explicit configuration to find * API keys for a given provider. * * @param provider - Provider name to resolve auth for. * @param envVars - Environment variable names to check. * @param explicitKey - An explicitly provided API key (highest priority). * @returns Resolved authentication, or undefined if no credentials found. */ export declare function resolveAuth(provider: string, envVars?: string[], explicitKey?: string): ResolvedAuth | undefined; /** * The snake_case serialized form of a {@link ModelDescriptor}. * * This is the canonical mapping used when storing or transmitting model * descriptors in SQL databases, REST APIs, or any other context that expects * snake_case field names. * * @see serializeModel */ export interface SerializedModel { id: string; name?: string; api: string; provider: string; base_url?: string; reasoning?: boolean; input?: ("text" | "image")[]; cost?: { input: number; output: number; cache_read: number; cache_write: number; }; context_window?: number; max_tokens?: number; headers?: Record; compat?: Record; } /** * Convert a {@link ModelDescriptor} (camelCase) to its snake_case serialized * form ({@link SerializedModel}). * * This is the canonical mapping for integrators who store models in SQL * databases or send them over REST APIs. Rather than each consumer writing * their own mapping, use this utility: * * ```ts * import { serializeModel } from "clawtools/connectors"; * * const row = serializeModel(descriptor); * // row.context_window, row.max_tokens, row.base_url, etc. * await db.run("INSERT INTO models VALUES (?)", [JSON.stringify(row)]); * ``` * * Fields not present on the descriptor are omitted from the result (not set * to null), so the returned object is safe to spread into a database row * without stomping existing columns. * * @param model - The ModelDescriptor to serialize. * @returns A plain object with snake_case field names. */ export declare function serializeModel(model: ModelDescriptor): SerializedModel; /** * Convert a {@link SerializedModel} (snake_case) back to a * {@link ModelDescriptor} (camelCase). * * The inverse of {@link serializeModel}. Use when reading model rows from a * database or REST API and passing them to clawtools: * * ```ts * import { deserializeModel } from "clawtools/connectors"; * * const row = await db.get("SELECT * FROM models WHERE id = ?", [modelId]); * const descriptor = deserializeModel(row); * const stream = connector.stream(descriptor, context, options); * ``` * * @param serialized - The snake_case model object to convert. * @returns A ModelDescriptor with camelCase field names. */ export declare function deserializeModel(serialized: SerializedModel): ModelDescriptor; //# sourceMappingURL=registry.d.ts.map