/** * llm domain contract: host-scoped provider topology for configuration * surfaces. `llm.providers` merges the configurable-provider directory * (which providers CAN be configured, and where their settings live) with the * live route registry; `llm.models` is the session-independent model catalog * (the same groups as `session.models`, without the per-session current * target). Both invalidate on the `host/models-changed` frame. */ import type { RpcRequest, RpcResponse } from './rpc.ts' import type { ModelCatalogFailure, ModelProviderGroup } from './sessions.ts' /** Wire view of one configurable provider. */ export interface ConfigurableProviderView { /** Provider route key (`deepseek-official`, `openai`, …). */ provider: string /** Human-readable name for configuration surfaces. */ displayName: string /** Settings namespace whose section configures this provider. */ settingsNs: string /** Path from that section's root to the provider's profile object (empty = whole section). */ settingsPath: string[] /** Whether the route is currently registered (its models are requestable). */ active: boolean } /** Llm-domain unary methods (the map keys llm.* of RpcMethodMap). */ export interface LlmApi { /** * List every configurable provider with its live/dormant state, in * directory declaration order. Routes registered outside the directory * (an adapter that never declared configurability) are appended with their * registration identity and no settings address. */ providers(request: RpcRequest<{}>): Promise> /** * Host-scoped model catalog over every registered provider route: the * settings surface's models view, needing no session. Per-provider listing * failures ride `failures` without failing the sound groups. */ models(request: RpcRequest<{}>): Promise> /** * Interrogate a provider endpoint the configuration surface is still * drafting, and return the models it advertises for the user to adopt. * * The payload is the draft, not a stored route: `settingsNs` selects the * adapter family that knows how to read the listing, and the endpoint, * protocol, and key come from the form. Nothing is written — the reply is * candidates, and only a later `settings.mutate` decides what a route * serves. `apiKey` is therefore accepted here but never stored, logged, or * echoed back; a provider whose key is already stored omits it and the * endpoint answers unauthenticated or refuses. */ discoverModels( request: RpcRequest<{ settingsNs: string baseURL: string api?: string apiKey?: string }>, signal?: AbortSignal, ): Promise> } /** Wire view of one model an interrogated endpoint advertises. */ export interface DiscoveredModelView { /** Model id the endpoint accepts. */ id: string /** Human-readable name when the endpoint supplies one. */ name?: string /** Maximum combined request and response context, when disclosed. */ contextWindow?: number /** Maximum output tokens, when disclosed. */ maxTokens?: number }