/** * Model-class classification for Databricks Model Serving endpoints. * * Chat capability bands are derived from the live workspace catalogue * rather than a hand-maintained table. Databricks publishes * per-endpoint `quality` / `speed` / `cost` scores (the AI Playground * bars) on the serving list; {@link classifyEndpoints} buckets scored * chat models into the chat {@link ModelClass} bands by the *relative* * distribution of those scores (quantiles, not fixed cut-offs) so a * brand-new model that lands outside today's score range still slots in * next to its peers. Embedding endpoints (`task === "llm/v1/embeddings"`) * are bucketed into {@link ModelClass.Embedding} by task, independent of * any score. * * Unscored-but-recognizable chat endpoints are still placed by a small * family heuristic ({@link classifyByFamily}) so a workspace whose * models predate Foundation Model API scoring keeps working. The * offline fallback floor - the hard-coded model list reached for when * the live catalogue can't be read at all - is a server concern and * lives in `@dbx-tools/model`, not here: a browser client never talks * to Databricks directly, so it has nothing to fall back to. * * Pure (no Node-only imports), so a client can classify a `/models` * response without server dependencies. * * @module */ import { ModelClass, type ServingEndpointSummary } from "./model.ts"; /** What an endpoint can be asked to do, as derived by {@link endpointCapabilities}. */ export interface EndpointCapabilities { /** OpenAI chat/completions + Responses: the surface a chat agent needs. */ chat: boolean; /** Embedding (vector) endpoint. */ embedding: boolean; /** Complete function-tool round-trip (call plus function_call_output replay). */ tools: boolean; } /** * Provider families verified against Databricks Responses/Open Responses with * both a forced function call and a stateless `function_call_output` replay. * * Databricks' endpoint list/OpenAPI currently exposes no tools capability bit. * Keep this conservative: an unknown chat family is not agent-safe until it is * verified. Gemini is excluded because it emits a call but Open Responses * cannot replay the required thought signature; GPT-OSS rejects Responses * passthrough entirely. */ export declare function supportsToolsByFamily(name: string): boolean; /** * Derive an endpoint's capabilities from its Databricks task hint and its * classified {@link ModelClass}, so consumers filter on capability instead of * re-deriving it from raw `task` / `class` strings. * * Either signal alone is enough: the task hint is authoritative when present, * and the class covers endpoints Databricks left untasked but the classifier * recognized. Embedding wins over chat when both point at it, since the two are * not interchangeable. */ export declare function endpointCapabilities(endpoint: ServingEndpointSummary): EndpointCapabilities; /** Family-heuristic classification of a single endpoint name. */ export interface FamilyClass { /** Chat capability band the family maps to (never embedding). */ class: ModelClass; /** Intra-family ordering hint (higher is newer / more capable). */ rank: number; } /** * Numeric `[major, minor, patch]` version parsed from an endpoint * name, used to order siblings within a family/tier. Starts at the * first digit in the name, then reads successive separator-delimited, * digit-prefixed chunks as the three components (missing ones default * to `0`): * * - `databricks-claude-opus-4-8` -> `[4, 8, 0]` * - `databricks-claude-opus-4-10` -> `[4, 10, 0]` (sorts above 4-8) * - `databricks-meta-llama-3-3-70b`-> `[3, 3, 70]` * - `databricks-bge-large-en` -> `[0, 0, 0]` (no digits) * * Component-wise comparison (not a decimal collapse) so `4.10` beats * `4.8` - the bug a `major + minor/10` score would hit. */ export declare function versionTuple(name: string): [number, number, number]; /** * Best-effort chat capability band for an endpoint we have no live * score for, keyed off provider family and the well-known variant words * in the name (`opus`/`sonnet`/`haiku`, `pro`/`mini`/`nano`, * `flash`/`flash-lite`, Llama parameter sizes, etc). Returns `null` for * names we don't recognize so unknown custom endpoints are never * auto-selected as a default. The accompanying `rank` orders siblings * within a class. Only ever returns a chat band - embedding endpoints * are classified by task, not name. */ export declare function classifyByFamily(name: string): FamilyClass | null; /** * Bucket live endpoints into {@link ModelClass}es, ranked best-first * within each chat band. * * Embedding endpoints (`task === "llm/v1/embeddings"`) go into * {@link ModelClass.Embedding} by task, in listing order (they carry no * capability score to rank on). * * Chat endpoints (`task === "llm/v1/chat"`) split into the three chat * bands. Scored endpoints (those carrying a `profile.quality`) drive * the banding: the observed quality distribution is split at its 1/3 * and 2/3 quantiles, so the top third is {@link ModelClass.ChatThinking}, * the bottom third {@link ModelClass.ChatFast}, and the middle * {@link ModelClass.ChatBalanced}. Because the thresholds come from the * data, the split adapts as Databricks adds or rescores models - * nothing is pinned to a fixed score band. * * Unscored chat endpoints are placed by {@link classifyByFamily} and * ranked after the scored ones in their band; unrecognized, unscored * endpoints (e.g. custom external models) are omitted entirely so they * are never picked as an automatic default. * * Within a chat band, scored models sort by `quality` desc, then `cost` * asc, then `speed` desc, then parsed name version desc; family-only * models sort by version rank then parsed version. The version * tie-break ({@link versionTuple}) is what separates point releases * that share a score profile (e.g. `opus-4-8` ahead of `opus-4-7`). */ export declare function classifyEndpoints(endpoints: readonly ServingEndpointSummary[]): Record;