import { type Api, type AssistantMessageEventStream, type Context, type Model, type ModelRefreshStrategy, type SimpleStreamOptions, type ThinkingConfig } from "@oh-my-pi/pi-ai"; import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/utils/oauth/types"; import { type ThemeColor } from "../modes/theme/theme"; import type { AuthStorage } from "../session/auth-storage"; import { type ConfigError, ConfigFile } from "./config-file"; import { type CanonicalModelIndex, type CanonicalModelRecord, type CanonicalModelVariant, type ModelEquivalenceConfig } from "./model-equivalence"; import { type Settings } from "./settings"; export type { CanonicalModelIndex, CanonicalModelRecord, CanonicalModelVariant, ModelEquivalenceConfig }; export declare const kNoAuth = "N/A"; export declare function isAuthenticated(apiKey: string | undefined | null): apiKey is string; export type ModelRole = "default" | "smol" | "slow" | "vision" | "plan" | "designer" | "commit" | "task"; export interface ModelRoleInfo { tag?: string; name: string; color?: ThemeColor; } export declare const MODEL_ROLES: Record; export declare const MODEL_ROLE_IDS: ModelRole[]; /** Alias for ModelRoleInfo - used for both built-in and custom roles */ export type RoleInfo = ModelRoleInfo; /** * Return the canonical set of known roles for selector/carousel UI. * * Built-ins always come first. Configured cycle order, model assignments, and * tag metadata can introduce additional custom roles without requiring duplicate * entries across settings. */ export declare function getKnownRoleIds(settings: Settings): string[]; /** * Get role info for a role name (built-in or custom). * Configured metadata overrides built-in defaults when present. */ export declare function getRoleInfo(role: string, settings: Settings): RoleInfo; export declare const ModelsConfigFile: ConfigFile<{ providers?: Record | undefined; compat?: { supportsStore?: boolean | undefined; supportsDeveloperRole?: boolean | undefined; supportsMultipleSystemMessages?: boolean | undefined; supportsReasoningEffort?: boolean | undefined; reasoningEffortMap?: { minimal?: string | undefined; low?: string | undefined; medium?: string | undefined; high?: string | undefined; xhigh?: string | undefined; } | undefined; maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined; supportsUsageInStreaming?: boolean | undefined; requiresToolResultName?: boolean | undefined; requiresMistralToolIds?: boolean | undefined; requiresAssistantAfterToolResult?: boolean | undefined; requiresThinkingAsText?: boolean | undefined; reasoningContentField?: "reasoning" | "reasoning_content" | "reasoning_text" | undefined; requiresReasoningContentForToolCalls?: boolean | undefined; allowsSyntheticReasoningContentForToolCalls?: boolean | undefined; requiresAssistantContentForToolCalls?: boolean | undefined; supportsToolChoice?: boolean | undefined; disableReasoningOnForcedToolChoice?: boolean | undefined; disableReasoningOnToolChoice?: boolean | undefined; thinkingFormat?: "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined; openRouterRouting?: { only?: string[] | undefined; order?: string[] | undefined; } | undefined; vercelGatewayRouting?: { only?: string[] | undefined; order?: string[] | undefined; } | undefined; extraBody?: Record | undefined; supportsStrictMode?: boolean | undefined; toolStrictMode?: "all_strict" | "none" | undefined; } | undefined; authHeader?: boolean | undefined; auth?: "apiKey" | "none" | "oauth" | undefined; discovery?: { type: "llama.cpp" | "lm-studio" | "ollama" | "openai-models-list"; } | undefined; models?: { id: string; name?: string | undefined; api?: "anthropic-messages" | "azure-openai-responses" | "google-generative-ai" | "google-vertex" | "openai-codex-responses" | "openai-completions" | "openai-responses" | undefined; baseUrl?: string | undefined; reasoning?: boolean | undefined; thinking?: { minLevel: "high" | "low" | "medium" | "minimal" | "xhigh"; maxLevel: "high" | "low" | "medium" | "minimal" | "xhigh"; mode: "anthropic-adaptive" | "anthropic-budget-effort" | "budget" | "effort" | "google-level"; defaultLevel?: "high" | "low" | "medium" | "minimal" | "xhigh" | undefined; levels?: ("high" | "low" | "medium" | "minimal" | "xhigh")[] | undefined; } | undefined; input?: ("image" | "text")[] | undefined; cost?: { input: number; output: number; cacheRead: number; cacheWrite: number; } | undefined; premiumMultiplier?: number | undefined; contextWindow?: number | undefined; maxTokens?: number | undefined; headers?: Record | undefined; compat?: { supportsStore?: boolean | undefined; supportsDeveloperRole?: boolean | undefined; supportsMultipleSystemMessages?: boolean | undefined; supportsReasoningEffort?: boolean | undefined; reasoningEffortMap?: { minimal?: string | undefined; low?: string | undefined; medium?: string | undefined; high?: string | undefined; xhigh?: string | undefined; } | undefined; maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined; supportsUsageInStreaming?: boolean | undefined; requiresToolResultName?: boolean | undefined; requiresMistralToolIds?: boolean | undefined; requiresAssistantAfterToolResult?: boolean | undefined; requiresThinkingAsText?: boolean | undefined; reasoningContentField?: "reasoning" | "reasoning_content" | "reasoning_text" | undefined; requiresReasoningContentForToolCalls?: boolean | undefined; allowsSyntheticReasoningContentForToolCalls?: boolean | undefined; requiresAssistantContentForToolCalls?: boolean | undefined; supportsToolChoice?: boolean | undefined; disableReasoningOnForcedToolChoice?: boolean | undefined; disableReasoningOnToolChoice?: boolean | undefined; thinkingFormat?: "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined; openRouterRouting?: { only?: string[] | undefined; order?: string[] | undefined; } | undefined; vercelGatewayRouting?: { only?: string[] | undefined; order?: string[] | undefined; } | undefined; extraBody?: Record | undefined; supportsStrictMode?: boolean | undefined; toolStrictMode?: "all_strict" | "none" | undefined; } | undefined; contextPromotionTarget?: string | undefined; }[] | undefined; modelOverrides?: Record | undefined; compat?: { supportsStore?: boolean | undefined; supportsDeveloperRole?: boolean | undefined; supportsMultipleSystemMessages?: boolean | undefined; supportsReasoningEffort?: boolean | undefined; reasoningEffortMap?: { minimal?: string | undefined; low?: string | undefined; medium?: string | undefined; high?: string | undefined; xhigh?: string | undefined; } | undefined; maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined; supportsUsageInStreaming?: boolean | undefined; requiresToolResultName?: boolean | undefined; requiresMistralToolIds?: boolean | undefined; requiresAssistantAfterToolResult?: boolean | undefined; requiresThinkingAsText?: boolean | undefined; reasoningContentField?: "reasoning" | "reasoning_content" | "reasoning_text" | undefined; requiresReasoningContentForToolCalls?: boolean | undefined; allowsSyntheticReasoningContentForToolCalls?: boolean | undefined; requiresAssistantContentForToolCalls?: boolean | undefined; supportsToolChoice?: boolean | undefined; disableReasoningOnForcedToolChoice?: boolean | undefined; disableReasoningOnToolChoice?: boolean | undefined; thinkingFormat?: "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined; openRouterRouting?: { only?: string[] | undefined; order?: string[] | undefined; } | undefined; vercelGatewayRouting?: { only?: string[] | undefined; order?: string[] | undefined; } | undefined; extraBody?: Record | undefined; supportsStrictMode?: boolean | undefined; toolStrictMode?: "all_strict" | "none" | undefined; } | undefined; contextPromotionTarget?: string | undefined; }> | undefined; disableStrictTools?: boolean | undefined; transport?: "pi-native" | undefined; }> | undefined; equivalence?: { overrides?: Record | undefined; exclude?: string[] | undefined; } | undefined; }>; export type ProviderDiscoveryStatus = "idle" | "ok" | "empty" | "cached" | "unavailable" | "unauthenticated"; export interface ProviderDiscoveryState { provider: string; status: ProviderDiscoveryStatus; optional: boolean; stale: boolean; fetchedAt?: number; models: string[]; error?: string; } export interface CanonicalModelQueryOptions { availableOnly?: boolean; candidates?: readonly Model[]; } /** * Model registry - loads and manages models, resolves API keys via AuthStorage. */ export declare class ModelRegistry { #private; readonly authStorage: AuthStorage; /** * @param authStorage - Auth storage for API key resolution */ constructor(authStorage: AuthStorage, modelsPath?: string); /** * Reload models from disk (built-in + custom from models.json). */ refresh(strategy?: ModelRefreshStrategy): Promise; refreshInBackground(strategy?: ModelRefreshStrategy): void; refreshProvider(providerId: string, strategy?: ModelRefreshStrategy): Promise; /** * Get any error from loading models.json (undefined if no error). */ getError(): ConfigError | undefined; /** * Get all models (built-in + custom). * If models.json had errors, returns only built-in models. */ getAll(): Model[]; getCanonicalModels(options?: CanonicalModelQueryOptions): CanonicalModelRecord[]; getCanonicalVariants(canonicalId: string, options?: CanonicalModelQueryOptions): CanonicalModelVariant[]; resolveCanonicalModel(canonicalId: string, options?: CanonicalModelQueryOptions): Model | undefined; getCanonicalId(model: Model): string | undefined; /** * Get only models that have auth configured. * This is a fast check that doesn't refresh OAuth tokens. */ getAvailable(): Model[]; /** * Check whether auth is configured for a model's provider. * * Mirrors the upstream `@mariozechner/pi-coding-agent` API surface so that * external plugins/extensions and downstream wrappers (e.g. subagent launch * paths that pre-flight auth before model resolution) can probe a model * without resolving an API key. Returns true for keyless providers as well * as providers with stored credentials. See issue #993. */ hasConfiguredAuth(model: Model): boolean; getDiscoverableProviders(): string[]; getProviderDiscoveryState(provider: string): ProviderDiscoveryState | undefined; /** * Find a model by provider and ID. */ find(provider: string, modelId: string): Model | undefined; /** * Get the base URL associated with a provider, if any model defines one. */ getProviderBaseUrl(provider: string): string | undefined; /** * Get API key for a model. */ getApiKey(model: Model, sessionId?: string): Promise; /** * Get API key for a provider (e.g., "openai"). */ getApiKeyForProvider(provider: string, sessionId?: string, baseUrl?: string): Promise; /** * Check if a model is using OAuth credentials (subscription). */ isUsingOAuth(model: Model): boolean; /** * Remove custom API/OAuth registrations for a specific extension source. */ clearSourceRegistrations(sourceId: string): void; /** * Remove registrations for extension sources that are no longer active. */ syncExtensionSources(activeSourceIds: string[]): void; /** * Register a provider dynamically (from extensions). * * If provider has models: replaces all existing models for this provider. * If provider has only baseUrl/headers: overrides existing models' URLs. * If provider has streamSimple: registers a custom API streaming function. * If provider has oauth: registers OAuth provider for /login support. */ registerProvider(providerName: string, config: ProviderConfigInput, sourceId?: string): void; /** * Suppress a specific model selector (e.g., "provider/id") until a specific timestamp. */ suppressSelector(selector: string, untilMs: number): void; /** * Check if a model selector is currently suppressed due to rate limits. */ isSelectorSuppressed(selector: string): boolean; } /** * Input type for registerProvider API (from extensions). */ export interface ProviderConfigInput { baseUrl?: string; apiKey?: string; api?: Api; streamSimple?: (model: Model, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream; headers?: Record; compat?: Model["compat"]; authHeader?: boolean; /** Streaming transport override — see {@link Model.transport}. */ transport?: Model["transport"]; oauth?: { name: string; login(callbacks: OAuthLoginCallbacks): Promise; refreshToken?(credentials: OAuthCredentials): Promise; getApiKey?(credentials: OAuthCredentials): string; modifyModels?(models: Model[], credentials: OAuthCredentials): Model[]; }; models?: Array<{ id: string; name: string; api?: Api; baseUrl?: string; reasoning: boolean; thinking?: ThinkingConfig; input: ("text" | "image")[]; cost: { input: number; output: number; cacheRead: number; cacheWrite: number; }; contextWindow: number; maxTokens: number; headers?: Record; compat?: Model["compat"]; contextPromotionTarget?: string; premiumMultiplier?: number; }>; }