import { type AnyModel, type Api, type AssistantImages, type AssistantMessage, type AssistantMessageEventStream, type AuthCheck, type AuthInteraction, type AuthOperationOptions, type AuthResult, type AuthType, type ClassifierApi, type ClassifierContext, type ClassifierModel, type ClassifierResult, type Context, type Credential, type CredentialInfo, type DeferredHandle, type ImageApi, type ImageModel, type ImagesContext, type LoginOptions, type Model, type Models, type ModelsApiStreamOptions, type ModelsClassifierOptions, type ModelsDeferredCancelOptions, type ModelsDeferredFetchOptions, type ModelsImagesOptions, type ModelsRefreshOptions, type ModelsRefreshResult, type ModelType, type ModelTypeMap, type Provider } from "@bastani/pi-ai"; import { type FastModelVariantDiagnostic } from "./fast-model-variants.ts"; import { type AuthStatus, type CompatibilityRequestConfig, type ProviderConfigInput } from "./provider-composer.ts"; export type { CreateModelRuntimeOptions, ModelRuntimeAuthOverrides } from "./model-runtime-types.ts"; import { type ModelRuntimeSimpleStreamOptions } from "./model-runtime-streaming.ts"; import type { CreateModelRuntimeOptions, ModelRuntimeAuthOverrides } from "./model-runtime-types.ts"; export type CredentialSynchronizationOperation = "login" | "logout" | "saveCredential" | "setRuntimeApiKey" | "removeRuntimeApiKey"; /** Credentials changed successfully, but local model state could not be synchronized. */ export declare class CredentialSynchronizationError extends Error { readonly providerId: string; readonly operation: CredentialSynchronizationOperation; readonly credential: Credential | undefined; constructor(providerId: string, operation: CredentialSynchronizationOperation, credential: Credential | undefined, options: ErrorOptions); } export interface ExtensionProviderTransaction { registerNativeProvider(provider: Provider): void; registerProvider(providerId: string, config: ProviderConfigInput): void; unregisterProvider(providerId: string): void; hasConfiguredAuth(providerId: string): boolean; commit(): Promise; } export interface SaveCredentialOptions { /** Fetch the remote catalog before publishing the credential. Defaults to true. */ refreshCatalog?: boolean; } /** Configured pi-ai Models collection used by coding-agent and SDK consumers. */ export declare class ModelRuntime implements Models { private readonly models; private readonly credentials; private readonly streaming; private readonly defaultBuiltins; private readonly builtins; private readonly nativeExtensionProviders; private readonly extensionProviders; private readonly compositionErrors; private readonly fastModelVariantDiagnostics; private readonly modelsPath; private readonly modelNetworkEnabled; private config; private snapshot; private snapshotGeneration; private catalogInputsGeneration; private observedModelsFileToken; private readonly externalProviderAuthStatuses; private readonly externalStatusCredentials; private readonly availabilityCredentials; private availabilityRefreshSeq; private availabilityErrorSeq; private readonly providerAvailabilitySeq; private readonly credentialOperations; private availabilityError; private refreshSequence; private constructor(); static create(options?: CreateModelRuntimeOptions): Promise; private configureRadiusProviders; private providerIds; /** Privacy boundary: no request auth resolution, credential commands, or OAuth refresh. */ containsConfiguredCredential(serialized: string): Promise; /** * Overlay derived selectable `-fast` model variants. Applied last so exact `-fast` IDs owned by the * provider, models.json, or an extension are already present and win the collision. */ private withDerivedFastModels; /** * Publish a provider through the fast-variant overlay. Every catalog accessor — `getProvider`, * `getProviders`, `getModel`, `getModels`, `getAvailable` — then reports the same list. The overlay * is `{ ...provider, getModels }`, so `auth`, `login`, `stream`, and `streamSimple` stay the same * function references the caller registered. */ private publishProvider; private recomposeProvider; private composeProvider; private rebuildProviders; private updateModelSnapshot; private runAvailabilityRefresh; private queueAvailabilityRefresh; private refreshProviderAvailability; getProviders(): readonly Provider[]; getProvider(providerId: string): Provider | undefined; /** * Whether an authenticated provider may reconstruct an absent saved model ID. * * Pass `modelId` whenever it is known. GitHub Copilot advertises every model it offers per account, * so a `-fast` ID that appears in neither the picker list nor the fast-sibling list is definitively * not restorable. An ID advertised as a fast sibling also requires its corresponding base model in * the catalog; otherwise reconstruction would invent a route-less fast identity. An ID advertised * as an ordinary model stays ordinary whatever its name ends in. Every other provider keeps the * provider-scoped answer, so a provider-owned model whose upstream name merely ends in `-fast` * (several exist under `vercel-ai-gateway`) still restores. */ canRestoreUnknownModel(providerId: string, modelId?: string): boolean; private resolveModelMetadata; getModels(providerId?: string): readonly Model[]; getModel(providerId: string, modelId: string): Model | undefined; private resolveCatalogMetadata; getModelsOfType(type: TType, providerId?: string): readonly ModelTypeMap[TType][]; getModelOfType(type: TType, providerId: string, modelId: string): ModelTypeMap[TType] | undefined; getAllModels(providerId?: string): readonly AnyModel[]; getAvailableOfType(type: TType, providerId?: string, options?: AuthOperationOptions): Promise; getAllAvailable(providerId?: string, options?: AuthOperationOptions): Promise; checkAuth(providerId: string, options?: AuthOperationOptions): Promise; getAvailable(providerId?: string, options?: AuthOperationOptions): Promise[]>; getAvailableSnapshot(): readonly Model[]; getError(): string | undefined; /** * Derived fast model variants that were suppressed because a provider, models.json custom model, or * extension already owns the exact `-fast` model ID. Reported as warnings, not composition errors. */ getFastModelVariantDiagnostics(): readonly FastModelVariantDiagnostic[]; /** Non-fatal catalog warnings, joined for display. */ getWarning(): string | undefined; getRegisteredProviderConfig(providerId: string): ProviderConfigInput | undefined; /** * Whether an extension supplies the stream function for this model's api. Such a transport owns its * own serialization, so Atomic must not attach first-party provider routing to it. This mirrors the * `usesExtensionStream` check the agent session makes before dispatching. */ private ownsExtensionTransport; getRegisteredProviderIds(): readonly string[]; getRegisteredNativeProvider(providerId: string): Provider | undefined; getOAuthProviderMetadata(): import("./oauth-login.ts").OAuthProviderMetadata[]; /** Providers that offer API-key login in `/login`. */ getApiKeyLoginProviderMetadata(): Array<{ id: string; name: string; }>; /** @internal Compatibility fallback for ModelRegistry when provider auth is unconfigured. */ getCompatibilityRequestConfig(model: Model): CompatibilityRequestConfig; isUsingOAuth(providerId: string): boolean; hasConfiguredAuth(providerId: string): boolean; private syncStoredCredentialChanges; private availabilityCredentialChanged; private recordAvailabilityCredentials; private withCredentialAvailability; /** Return stored credential metadata synchronously without refreshing auth. */ getCredentialSnapshot(providerId: string): Credential | undefined; getAuth(providerId: string, overrides?: ModelRuntimeAuthOverrides): Promise; getAuth(model: AnyModel, overrides?: ModelRuntimeAuthOverrides): Promise; /** * Resolve request-owned auth/config headers without copying the model's static * catalog headers into the per-request override layer. The API provider reads * static headers from the model itself; duplicating them in auth would make * them override API-computed defaults that intentionally replace catalog values. */ getRequestAuth(model: Model, overrides?: ModelRuntimeAuthOverrides): Promise; /** * Monotonic count of changes to any input a catalog refresh reads. * * `refresh()` reloads models.json, recomposes every provider from it, the * extension registrations, and the builtin catalog, resolves credentials as * it runs, and publishes ONE snapshot at the end. So a pass belongs to the * inputs it started under, and joining a pass across a bump is unsound in * both directions: the joiner reads models and credentials the user has * already replaced, and the pass's late publish overwrites the newer state * with them. * * Every mutation source bumps this counter, which is why callers need only * this one number rather than a growing tuple of per-input keys: * * - credential writes — `login`, `logout`, `saveCredential`, * `setRuntimeApiKey`, `removeRuntimeApiKey`, an external * `reloadCredentials`, and an applied external auth status; * - provider registrations — `registerProvider`, `registerNativeProvider`, * and `unregisterProvider`, through the refresh they schedule; * - models.json content — provider `baseUrl`, `apiKey`, `api`, headers, * model definitions, and overrides, which every pass reloads. * * The first two are this runtime's own writes and bump where they happen. * The third is an external edit nothing here observes, so reading the * generation samples the file and bumps when its content moved since the * last sample. That read is synchronous so the answer belongs to the same * tick as the decision that depends on it, and it hashes content rather * than trusting an mtime: a same-size rewrite inside one filesystem * timestamp tick — an edited key, a renamed model — is exactly the change a * shared pass must not hide. */ getCatalogInputsGeneration(): number; /** * Record that an input a catalog refresh reads changed. Every pass started * before this call answers for inputs that no longer exist. */ private markCatalogInputsChanged; /** Bump the generation when models.json changed since the last observation. */ private observeModelsFile; private readModelsFileToken; /** Reload credentials changed by the authoritative isolated engine and update auth status snapshots. */ reloadCredentials(options?: { refreshAvailability?: boolean; }): Promise; private assertCredentialRefreshSucceeded; private enqueueCredentialOperation; private synchronizeCredentialState; private refreshRemainingAuthAfterLogout; /** * Persist a credential acquired elsewhere. * * `refreshCatalog` defaults to true so the saved credential is published against * a freshly fetched catalog. Callers that acquired the key through a login dialog * pass false: that transaction ends at persistence, and a remote catalog fetch * would make an offline save fail after the credential was already committed. */ saveCredential(providerId: string, credential: Credential, options?: SaveCredentialOptions): Promise; /** * Apply a process-scoped API key override. This publishes the provider against * the current snapshot and deliberately does not refresh the model catalog; * callers needing catalog freshness call refresh({ providers: [providerId], signal }) * separately. */ setRuntimeApiKey(providerId: string, apiKey: string, options: AuthOperationOptions): Promise; removeRuntimeApiKey(providerId: string, options?: AuthOperationOptions): Promise; listCredentials(): Promise; getStoredCredentialType(providerId: string): CredentialInfo["type"] | undefined; getProviderAuthStatus(providerId: string): AuthStatus; /** Apply authoritative auth state returned by an isolated engine mutation. */ applyExternalProviderAuthStatus(providerId: string, status: AuthStatus): void; stream(model: Model, context: Context, options?: ModelsApiStreamOptions): AssistantMessageEventStream; complete(model: Model, context: Context, options?: ModelsApiStreamOptions): Promise; streamSimple(model: Model, context: Context, options?: ModelRuntimeSimpleStreamOptions): AssistantMessageEventStream; completeSimple(model: Model, context: Context, options?: ModelRuntimeSimpleStreamOptions): Promise; fetchDeferred(model: Model, handle: DeferredHandle, options?: ModelsDeferredFetchOptions): Promise; cancelDeferred(model: Model, handle: DeferredHandle, options?: ModelsDeferredCancelOptions): Promise; private operationHeaders; generateImages(model: ImageModel, context: ImagesContext, options?: ModelsImagesOptions): Promise; classify(model: ClassifierModel, context: ClassifierContext, options?: ModelsClassifierOptions): Promise; login(providerId: string, type: AuthType, interaction: AuthInteraction, options?: LoginOptions): Promise; logout(providerId: string, options?: AuthOperationOptions): Promise; /** * The network policy a refresh with an omitted `allowNetwork` resolves to. * * Callers that share one in-flight refresh key on the effective policy, so * they need the same answer `runRefresh` computes rather than a second guess * at the offline setting this runtime was created under. */ isNetworkRefreshEnabled(): boolean; refresh(options?: ModelsRefreshOptions): Promise; /** * A registration's offline catalog pass must not publish after a newer refresh * that resolves configured credentials. * * The registration is also a catalog-input change: it adds, replaces, or drops * a provider every later pass composes from, so no pass that predates it can * answer for the provider set a caller now sees. */ private scheduleRegistrationRefresh; private runRefresh; private validateAliasRegistration; createExtensionProviderTransaction(replacedProviderIds?: Iterable): ExtensionProviderTransaction; registerNativeProvider(provider: Provider): void; registerProvider(providerId: string, config: ProviderConfigInput): void; private markProvisionallyConfigured; unregisterProvider(providerId: string): void; } //# sourceMappingURL=model-runtime.d.ts.map