/** * Provider configurations for different AI services */ export interface ProviderConfig { name: string; description: string; protocols: { openai?: { baseUrl: string; authHeader: 'Bearer' | 'x-api-key'; supportsNativeTools?: boolean; }; anthropic?: { baseUrl: string; authHeader: 'Bearer' | 'x-api-key'; supportsNativeTools?: boolean; }; }; models: { id: string; name: string; description: string; }[]; defaultModel: string; defaultProtocol: 'openai' | 'anthropic'; maxOutputTokens?: number; useMaxCompletionTokens?: boolean; requiresDefaultTemperature?: boolean; /** Provider's OpenAI-compatible endpoint rejects `tools` together with * `stream: true` (Alibaba/Qwen DashScope). When true, agent turns that send * tools are issued non-streamed (we buffer the full response). */ noStreamWithTools?: boolean; envKey?: string; subscribeUrl?: string; noApiKey?: boolean; dynamicModels?: boolean; /** Billed as a flat subscription (or free) — token counts are real, per-token * cost is not. Cost surfaces must say "included in plan" instead of pricing * these tokens at the provider's pay-per-use rates. */ flatFee?: boolean; groupLabel?: string; hint?: string; mcpEndpoints?: { webSearch?: string; webReader?: string; zread?: string; }; } export declare const PROVIDERS: Record; export type ProviderId = keyof typeof PROVIDERS; export declare function getProvider(id: string): ProviderConfig | null; export declare function replacementModelFor(providerId: string, modelId: string): string | undefined; export declare function getProviderList(): { id: string; name: string; description: string; subscribeUrl?: string; noApiKey?: boolean; }[]; export declare function getProviderModels(providerId: string): { id: string; name: string; description: string; }[]; export declare function isNoApiKeyProvider(providerId: string): boolean; export declare function isDynamicModelsProvider(providerId: string): boolean; /** * Returns true if the provider bills a flat subscription (or is free), so any * per-token dollar figure we compute for it is invented — see `flatFee`. */ export declare function isFlatFeeProvider(providerId: string): boolean; export declare function getProviderBaseUrl(providerId: string, protocol: 'openai' | 'anthropic'): string | null; export declare function getProviderAuthHeader(providerId: string, protocol: 'openai' | 'anthropic'): 'Bearer' | 'x-api-key'; export declare function getProviderMcpEndpoints(providerId: string): ProviderConfig['mcpEndpoints'] | null; export declare function supportsNativeTools(providerId: string, protocol: 'openai' | 'anthropic'): boolean; /** * Returns true if the provider uses max_completion_tokens instead of max_tokens. */ export declare function usesMaxCompletionTokens(providerId: string): boolean; /** * Returns true if the provider rejects custom temperature values * (e.g. OpenAI GPT-5+ only accepts the default of 1). */ export declare function requiresDefaultTemperature(providerId: string): boolean; /** * Returns true if the provider's OpenAI-compatible endpoint rejects `tools` * together with `stream: true` (Alibaba/Qwen) — callers must issue tool-bearing * agent turns non-streamed. */ export declare function providerNoStreamWithTools(providerId: string): boolean; export declare function modelRejectsSamplingParams(model: string): boolean; /** * Returns the effective max output tokens for a provider, capped by the provider's limit. * Falls back to the requested value if no provider limit is set. */ export declare function getEffectiveMaxTokens(providerId: string, requested: number): number; /** * Unified, user-facing thinking-effort tiers (the `/thinking` setting). * * 'auto' — omit the param entirely → each provider's own default. * low / medium / high / max — four explicit depth tiers. * * The four tiers are CONCEPTUAL. `reasoningParamsFor()` clamps each one to the * nearest level the active provider+model actually accepts, so we never send a * value that would 400 (e.g. Gemini rejects "medium"; OpenAI has no "max"). * The control is a pure DEPTH knob on models that already think — it never * toggles thinking on/off, which keeps us clear of the reasoning_content-replay * contract that DeepSeek/GLM impose when thinking mode is flipped. */ export type ReasoningTier = 'auto' | 'low' | 'medium' | 'high' | 'max'; export declare const REASONING_TIERS: ReasoningTier[]; /** * Canonicalize a model id for capability matching: lowercase, drop any * `vendor/` namespace (OpenRouter sends `anthropic/claude-opus-4.8`), and * normalize `.` version separators to `-` (`glm-5.2` → `glm-5-2`, * `claude-opus-4.8` → `claude-opus-4-8`). Mirrors macOS `ModelTuning.canonicalModelID`. */ export declare function canonicalModelId(model: string): string; /** * Does this provider+model expose a GRADED thinking-effort control we can drive? * Used to gate the `/thinking` UI — hidden entirely for models without one. * Keep in lockstep with macOS `ModelTuning.reasoningEffortSupported`. */ export declare function modelSupportsReasoningEffort(providerId: string, model: string): boolean; /** * Build the request-body fields that carry the chosen effort tier for the * active provider+model+protocol. Returns `{}` for 'auto', unsupported * models, or providers without a graded knob — so callers can spread it * unconditionally. Keep in lockstep with macOS `ModelTuning.reasoningParams`. */ export declare function reasoningParamsFor(providerId: string, model: string, tier: ReasoningTier): Record; /** * The DISTINCT tiers a given provider+model actually exposes — used to build a * per-model picker that only offers levels the model can tell apart (e.g. * GLM-5.2/DeepSeek grade only high|max; Gemini via the OpenAI-compat layer only * low|high). Always leads with 'auto'. `[]` for models with no graded knob. * * Kept in lockstep with `reasoningParamsFor` (the providers-test asserts every * listed tier yields a DISTINCT param, so this can't silently drift). Mirrors * macOS `ModelTuning.availableReasoningTiers`. */ export declare function availableReasoningTiers(providerId: string, model: string): ReasoningTier[]; /** * Map a (possibly out-of-range) tier to the tier this model actually distinguishes, * for display — the chip + the checked menu row. The effort setting is global, so * a tier picked on Opus ('medium') may not exist on Kimi K3; we show the level * Kimi will really run (its 'medium' clamps to 'high'). Picks the tier whose * effective param equals the requested one. 'auto' (or unsupported) → 'auto'. */ export declare function resolveReasoningTier(providerId: string, model: string, tier: ReasoningTier): ReasoningTier;