import type { ThinkingLevel } from "@earendil-works/pi-ai"; import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; export declare const ANTHROPIC_PROVIDER_ID = "anthropic"; export declare const OPENAI_CODEX_PROVIDER_ID = "openai-codex"; export declare const INVALID_REFRESH_TOKEN_BACKOFF_MS: number; export type ManagedProviderId = typeof ANTHROPIC_PROVIDER_ID | typeof OPENAI_CODEX_PROVIDER_ID; export type LadderProviderId = "anthropic" | "openai"; export type ModelStrength = "ultra" | "strong" | "medium" | "light"; export type SubscriptionCredential = { label: string; refresh: string; access: string; expires: number; rateLimitedUntil: number; lastAttemptAt: number; lastRateLimitedAt: number; authFailure?: "invalid_grant"; accountId?: string; }; export type ModelRef = { providerId: ManagedProviderId; modelId: string; }; export type RotationConfig = { defaultFallbackStrength?: ModelStrength; revertWhenAvailable?: boolean; preferredModel?: ModelRef; }; type RotationConfigUpdate = { defaultFallbackStrength?: ModelStrength; revertWhenAvailable?: boolean; preferredModel?: ModelRef | null; }; export type FallbackTarget = { providerId: ManagedProviderId; modelId: string; label: string; strength: ModelStrength; thinkingLevel?: ThinkingLevel; }; /** A concrete provider/model considered for either broker launch or turn-time rotation. */ export type ProviderCandidate = { providerId: string; modelId: string; thinkingLevel?: string; registered: boolean; authenticated: boolean; /** A provider is unavailable until this instant when every credential is cooling. */ coolingUntil?: number; /** False when this candidate may only be selected by an explicit request, never as fallback. */ automaticFallback?: boolean; }; export type ProviderCandidateRejection = "unregistered" | "non-managed-fallback" | "unauthenticated" | "cooling"; /** * Select the first viable model from an explicitly ordered set. Callers own ordering * (requested model first, then their configured fallback order) and side effects; * this policy owns the shared viability rules so launch and rotation cannot diverge. * * `pinnedToFirst` marks the FIRST candidate as an explicit provider pin: the caller * demanded that exact provider, so an unregistered or unauthenticated first candidate * forbids cross-provider fallback (selection stops, reporting only that one rejection). * A merely COOLING pin is transient, so fallback to a viable alternative is still * allowed. When false, every candidate is considered in order. */ export declare function resolveProviderCandidates(candidates: readonly ProviderCandidate[], now?: number, options?: { pinnedToFirst?: boolean; }): { candidates: ProviderCandidate[]; rejected: Array<{ candidate: ProviderCandidate; reason: ProviderCandidateRejection; }>; }; export declare function isManagedProvider(providerId: string | undefined): providerId is ManagedProviderId; /** The `modelLadders` CONFIG key for a runtime provider id -- `openai-codex` * (the runtime/auth id) maps to the `openai` ladder key used in * ~/.crouter/config.json. Callers building a repair command that a user can * paste into `crtr sys config set modelLadders....` must use THIS key, * not the runtime provider id. */ export declare function getLadderProviderId(providerId: ManagedProviderId): LadderProviderId; export declare function getProviderLabel(providerId: ManagedProviderId): string; export declare function mutateSubscriptionPool(providerId: ManagedProviderId, fn: (pool: SubscriptionCredential[], assertLockHeld: () => void) => SubscriptionCredential[] | undefined | Promise): Promise; export declare function refreshSubscriptionCredential(providerId: ManagedProviderId, label: string, exchange: (refreshToken: string) => Promise<{ refresh: string; access: string; expires: number; }>): Promise; export declare function isInvalidRefreshTokenError(error: unknown): boolean; export declare function modifyElectedSubscription(providerId: ManagedProviderId, elect: (pool: SubscriptionCredential[]) => SubscriptionCredential | undefined, apply: (current: SubscriptionCredential) => Promise<{ refresh: string; access: string; expires: number; } | undefined>): Promise; export declare function readSubscriptionPool(providerId: ManagedProviderId): SubscriptionCredential[]; export declare function writeSubscriptionPool(providerId: ManagedProviderId, next: SubscriptionCredential[]): Promise; export declare function upsertSubscription(providerId: ManagedProviderId, next: SubscriptionCredential): Promise; export declare class DuplicateSubscriptionError extends Error { constructor(message: string); } export declare function addSubscription(providerId: ManagedProviderId, entry: SubscriptionCredential): Promise; export declare function upsertSubscriptionWithUniqueAccount(providerId: ManagedProviderId, next: SubscriptionCredential): Promise; export declare function renameSubscription(providerId: ManagedProviderId, ref: string, nextLabel: string): Promise; export declare function removeManagedAccount(providerId: ManagedProviderId, ref: string): Promise; export type ManagedLoginIdentity = { accountId?: string; email?: string; }; /** Fetch Anthropic's stable OAuth account identity without making login depend on it. */ export declare function enrichManagedLoginIdentity(providerId: ManagedProviderId, credential: { access: string; accountId?: string; }): Promise; export declare function commitManagedLogin(providerId: ManagedProviderId, label: string | undefined, credential: { refresh: string; access: string; expires: number; accountId?: string; lastRateLimitedAt: number; autoLabel?: boolean; }): Promise; export declare function removeManagedProvider(providerId: ManagedProviderId, label?: string): Promise; export declare function removeSubscription(providerId: ManagedProviderId, ref: string): Promise; export declare function promoteSubscription(providerId: ManagedProviderId, ref: string): Promise; export declare function markSubscriptionAttempt(providerId: ManagedProviderId, ref: string, attemptAt?: number): Promise; export declare function markSubscriptionAuthenticationFailed(providerId: ManagedProviderId, ref: string, retryAfterMs: number, attemptAt?: number): Promise; export declare function markSubscriptionRateLimited(providerId: ManagedProviderId, ref: string, retryAfterMs: number, attemptAt?: number, rateLimitedAt?: number): Promise; export declare function markSubscriptionSuccess(providerId: ManagedProviderId, ref: string, attemptAt?: number): Promise; export declare function parseRetryAfterHeader(value: string | undefined, now?: number): number | undefined; export declare function readRotationConfig(): RotationConfig; export declare function writeRotationConfig(next: RotationConfigUpdate): RotationConfig; export declare function clearPreferredModel(): RotationConfig; export declare function rememberPreferredModel(model: ModelRef): RotationConfig; export declare function resolveFallbackTarget(currentProviderId: ManagedProviderId, currentModelId?: string, config?: RotationConfig, currentThinkingLevel?: string): FallbackTarget | undefined; export declare function shouldRestorePreferredModel(config?: RotationConfig, now?: number): boolean; export declare function restorePreferredModelIfPossible(piApi: ExtensionAPI, ctx: Pick): Promise; export declare function switchToFallbackIfPossible(piApi: ExtensionAPI, ctx: Pick, preferredModel?: ModelRef | undefined): Promise; export declare function formatStatusLine(providerId: ManagedProviderId, now?: number): string; export {};