Download shared/types.ts from automindy/fokemal: direct link, hf CLI and curl.
- Browser
- Download file 24.6 kB
-
https://huggingface.co/spaces/automindy/fokemal/resolve/main/shared/types.ts
- Command line
-
hf download hf://spaces/automindy/fokemal/shared/types.ts
-
curl -L -o types.ts https://huggingface.co/spaces/automindy/fokemal/resolve/main/shared/types.ts
24.6 kB
| // ---- Platform & Model Types ---- | |
| /** How the global outbound proxy URL is interpreted. Per-key proxies always | |
| * use the traditional forward-proxy transport. */ | |
| export type ProxyMode = 'forward' | 'fetch-relay'; | |
| /** A model declared beside a custom endpoint in an import file (#382). A | |
| * capability flag is present only when the paste declared it via a trailing | |
| * -TOOLS / -VISION suffix. */ | |
| export interface ImportModelEntry { | |
| id: string; | |
| supportsTools?: boolean; | |
| supportsVision?: boolean; | |
| } | |
| export interface PreviewKey { | |
| keyName: string; | |
| keyValue: string; | |
| detectedPlatform: string | null; | |
| prefix: string; | |
| /** Custom endpoints only: the upstream URL the export file carried (#687). */ | |
| baseUrl?: string; | |
| /** Custom endpoints only: models to register alongside the key (#382). */ | |
| models?: ImportModelEntry[]; | |
| isDuplicate?: boolean; | |
| } | |
| export interface ImportKey { | |
| keyName: string; | |
| keyValue: string; | |
| platform: string; | |
| baseUrl?: string; | |
| models?: ImportModelEntry[]; | |
| } | |
| export interface PreviewResponse { | |
| keys: PreviewKey[]; | |
| total: number; | |
| skipped: string[]; | |
| duplicates: number; | |
| } | |
| export interface ImportSelectedRequest { | |
| keys: ImportKey[]; | |
| } | |
| export interface ImportSelectedResponse { | |
| imported: number; | |
| skipped: string[]; | |
| errors: Array<{ key: string; error: string }>; | |
| total: number; | |
| /** Models registered for imported custom endpoints (#382). */ | |
| modelsRegistered: number; | |
| } | |
| // Active platforms — must match server/src/providers/index.ts and | |
| // server/src/routes/keys.ts PLATFORMS allowlist. | |
| // Moonshot and MiniMax direct integrations were dropped in migrateModelsV4 | |
| // (see server/src/db/index.ts). HuggingFace was dropped in V4 and re-added | |
| // in V13 via the router.huggingface.co Inference Providers meta-router. | |
| // SambaNova was dropped in V23 (free tier permanently retired — 402 | |
| // "payment method required" once the one-time $5 trial credit lapses). | |
| export type Platform = | |
| | 'google' | |
| | 'groq' | |
| | 'cerebras' | |
| // Sail Research — native Responses API provider. $5 in free credits refreshes | |
| // monthly when a payment method is attached; usage beyond the grant is | |
| // pay-as-you-go. Background polling is required for its flex-only models. | |
| | 'sail' | |
| // Responses-only gateway; a shared monthly free allowance, not per model. | |
| | 'aclide' | |
| // OpenAI-compatible chat and embeddings; one shared $1 monthly allowance. | |
| | 'speka' | |
| // Ongoing free research API for chat and speech recognition; catalog only. | |
| | 'typhoon' | |
| // Permanent free chat aliases, shared fair-use quota; signed catalog only. | |
| | 'plugsky' | |
| // Catalog-only free chat gateways; shared monthly/daily account allowances. | |
| | 'inferbase' | |
| | 'simplellm' | |
| // Selected zero-priced routes have daily/rolling quotas without a top-up; | |
| // signed catalog only. The public roster also includes paid/promotional IDs. | |
| | 'llmtr' | |
| // Catalog-managed free routes: monthly request quota / ongoing $0 models. | |
| | 'gizmo' | |
| | 'blockrun' | |
| // Hosted vision API: $5/workspace in recurring monthly credits, shared | |
| // across models. Signed catalog only; no bundled model seeds. | |
| | 'moondream' | |
| // Hosted gateways; model rows are delivered by the signed catalog only. | |
| // ElectronHub renews weekly credits; Experiential renews monthly credits. | |
| | 'electronhub' | |
| | 'experiential' | |
| // Catalog-managed gateways: monthly shared credits vs daily free-model quota. | |
| | 'router9' | |
| | 'septor' | |
| | 'clod' | |
| | 'speechify' | |
| | 'blaze' | |
| // Lucidity Composite, Api.Airforce and DreamPrompting expose daily free | |
| // allowances; Waterfall and Logfare publish community / fair-use tiers. | |
| | 'lucidity' | |
| | 'airforce' | |
| | 'dreamprompting' | |
| | 'waterfall' | |
| | 'logfare' | |
| // B.AI — OpenAI-compatible gateway. Its catalog row is a live-tested, | |
| // limited-time 0-credit promotion, not a recurring free allowance. | |
| | 'bai' | |
| // AnyAPI — OpenAI-compatible gateway. Free tier is $0/no card/recurring but | |
| // capped at 100K tokens/day over "free and basic" models only; no RPM/RPD is | |
| // published. Catalog rows live in the hosted catalog (premium now, free after | |
| // 30 days). | |
| | 'anyapi' | |
| // AMD Radeon Cloud TokenFactory — OpenAI-compatible shared inference. Its | |
| // rotating public-model roster is free without consuming instance credits, | |
| // with recurring account-level allowance and request/concurrency controls. | |
| | 'radeon' | |
| | 'nvidia' | |
| | 'mistral' | |
| | 'sambanova' | |
| | 'openrouter' | |
| | 'github' | |
| | 'cohere' | |
| | 'cloudflare' | |
| | 'zhipu' | |
| | 'ollama' | |
| | 'kilo' | |
| | 'pollinations' | |
| | 'llm7' | |
| | 'huggingface' | |
| // OpenCode Zen — OpenAI-compatible gateway. Free promotional models require a | |
| // free (no-card) account key from opencode.ai/auth; see migrateModelsV18. | |
| | 'opencode' | |
| // OVHcloud AI Endpoints — OpenAI-compatible, keyless anonymous tier | |
| // (2 req/min per IP per model); see migrateModelsV26. | |
| | 'ovh' | |
| // Agnes AI (Sapiens AI) — OpenAI-compatible (LiteLLM + vLLM backend). Serves | |
| // its own proprietary Agnes models; the free key comes from | |
| // platform.agnes-ai.com (no card). | |
| | 'agnes' | |
| // Reka — OpenAI-compatible. Native multimodal models (reka-edge takes | |
| // image/video). New accounts need prepaid credits (#1202); key from | |
| // platform.reka.ai. | |
| | 'reka' | |
| // SiliconFlow — OpenAI-compatible. Registered for its FREE generative-media | |
| // models (FLUX.1-schnell image, CosyVoice2 TTS) routed via services/media.ts; | |
| // chat is supported too. Key from siliconflow.com (no card). | |
| | 'siliconflow' | |
| // Routeway — OpenAI-compatible aggregator. Free ':free' models ($0) on a | |
| // rate-limited pool (~5 rpm observed); requires a browser User-Agent (CF | |
| // blocks others). Key from routeway.ai (no card). | |
| | 'routeway' | |
| // BazaarLink — OpenAI-compatible aggregator. Free 'auto:free' route picks an | |
| // available zero-cost model. Key from bazaarlink.ai (no card). | |
| | 'bazaarlink' | |
| // AINative Studio — OpenAI-compatible aggregator. Advertises a recurring | |
| // ~10M tokens/month free allocation (no card); quota unverified. Key from | |
| // ainative.studio. | |
| | 'ainative' | |
| // Aion Labs — OpenAI-compatible aggregator with a no-card free API key. | |
| // Catalog rows live in the Oracle catalog (premium now, free after 30 days). | |
| | 'aion' | |
| // Requesty — OpenAI-compatible router with no-card free models/credits. | |
| // Catalog rows live in the Oracle catalog (premium now, free after 30 days). | |
| | 'requesty' | |
| // NavyAI — OpenAI-compatible unified API. Free plan is 150K tokens/day and | |
| // 20 RPM; catalog rows live in the Oracle catalog (premium now, free after 30 days). | |
| | 'navy' | |
| // NaraRouter — OpenAI-compatible aggregator. Free account key from | |
| // router.bynara.id after Telegram channel/link verification; free-plan routes | |
| // reset daily and are catalog-managed (premium now, free after 30 days). | |
| | 'nara' | |
| // SEA-LION (AI Singapore) — OpenAI-compatible first-party API. Free key | |
| // (Google sign-in, no card, no region wall) at 10 RPM; catalog rows live in | |
| // the Oracle catalog (premium now, free after 30 days). | |
| | 'sealion' | |
| // OrcaRouter — OpenAI-compatible aggregator (api.orcarouter.ai/v1). Free key | |
| // from orcarouter.ai (no card); recurring rate-limited free aliases at $0 | |
| // (never fall back to paid). Catalog rows live in the Oracle catalog | |
| // (premium now, free after the 30-day model-age gate). | |
| | 'orcarouter' | |
| // UnoRouter (unorouter.com) — OpenAI-compatible aggregator. The web app is a | |
| // Next.js site at unorouter.com; the API lives at api.unorouter.com/v1. Free | |
| // key from unorouter.com (no card); free models carry a `:free` suffix and a | |
| // per-minute rate limit (429 on cap, e.g. "1 request(s) every 1 min"). | |
| // Live-probed 2026-08-23: /v1/models is public without a key but 401s on a | |
| // wrong key, and /v1/chat/completions 401s without a key, so default key | |
| // validation works. Catalog rows live in the hosted catalog (premium now, | |
| // free after the 30-day model-age gate). | |
| | 'unorouter' | |
| // xKiro (xkiro.com) — OpenAI-compatible gateway at api.xkiro.com/v1. Free key | |
| // from xkiro.com (no card); free plan is 5M tokens/day on its free models, | |
| // paid models 403 on a free key. | |
| // /v1/models is public (200 with no key), so key validation must probe | |
| // /v1/usage, which 401s on a missing/invalid ClientApiKey. Catalog rows live | |
| // in the hosted catalog (premium now, free after the 30-day model-age gate). | |
| | 'xkiro' | |
| // ModelScope (魔搭社区, Alibaba) — OpenAI-compatible inference API | |
| // (api-inference.modelscope.cn/v1). Free tier is 2000 requests/day | |
| // account-wide, but calls only work after the ModelScope account is bound to | |
| // an Alibaba Cloud CHINA-site (cn) account with Chinese real-name | |
| // verification — tokens mint without binding, then every call 401s. Catalog | |
| // rows land after community testing confirms per-model behavior (#581). | |
| | 'modelscope' | |
| // ── Chinese domestic providers (#922/#923/#924) ──────────────────────────── | |
| // All four need Chinese real-name verification (实名认证) on the cloud account | |
| // before a key will serve traffic, the same wall ModelScope hits above. | |
| // LongCat is the exception worth knowing: its platform accepts an email | |
| // signup from outside mainland China. | |
| // | |
| // Baidu Qianfan (百度千帆) — OpenAI-compatible (https://qianfan.baidubce.com/v2). | |
| // The ERNIE-Speed / ERNIE-Lite / ERNIE-Tiny series are free indefinitely via | |
| // pay-as-you-go billing rather than a token pool, so the ceiling is rate | |
| // limits, not a balance. Baidu calls the arrangement "long-term". Real-name | |
| // auth (individual or enterprise) required. | |
| | 'qianfan' | |
| // Volcengine Ark (火山方舟, ByteDance) — OpenAI-compatible | |
| // (https://ark.cn-beijing.volces.com/api/v3). Individual developers get a | |
| // RECURRING daily per-model free reward quota (raised from 500K to 2M | |
| // tokens/day/model), on top of a one-time 500K new-user grant. The strongest | |
| // recurring free tier of the four. | |
| | 'volcengine' | |
| // LongCat (Meituan / 美团) — OpenAI-compatible | |
| // (https://api.longcat.chat/openai/v1); also exposes an Anthropic-compatible | |
| // surface at /anthropic. Free tier is daily; the figure quoted at platform | |
| // launch was 100K tokens/day. Meituan has ANNOUNCED a 50M tokens/day | |
| // Flash-Lite free tier but it was described as a future plan, so it is not | |
| // treated as live here. | |
| | 'longcat' | |
| // iFlytek Spark (讯飞星火) — OpenAI-compatible | |
| // (https://spark-api-open.xf-yun.com/v1), Bearer auth using the console's | |
| // APIPassword (not the APIKey/APISecret pair the older WebSocket API used). | |
| // The Lite model (model id `lite`) is documented as free to call; iFlytek | |
| // does not publish a token ceiling or a QPS figure for it, so neither is | |
| // claimed here. | |
| | 'xfyun' | |
| // AI Horde — free, community-powered inference (volunteer workers) via an | |
| // OpenAI-compatible proxy (https://oai.aihorde.net/v1). Queue-based, so calls | |
| // can take tens of seconds; no tool support; usage is reported as kudos, not | |
| // tokens. Anonymous key `0000000000` works (lowest priority); a registered | |
| // aihorde.net key raises queue priority. Has a dedicated AIHordeProvider that | |
| // normalizes the proxy's OpenAI divergences. See issue #345. | |
| | 'aihorde' | |
| // User-configured OpenAI-compatible endpoint (llama.cpp, LM Studio, vLLM, | |
| // Ollama, any base_url). The endpoint URL lives on the api_keys row; see #117. | |
| | 'custom'; | |
| export interface Model { | |
| id: number; | |
| platform: Platform; | |
| modelId: string; | |
| displayName: string; | |
| intelligenceRank: number; | |
| speedRank: number; | |
| sizeLabel: string; | |
| rpmLimit: number | null; | |
| rpdLimit: number | null; | |
| tpmLimit: number | null; | |
| tpdLimit: number | null; | |
| monthlyTokenBudget: string; | |
| contextWindow: number | null; | |
| enabled: boolean; | |
| supportsVision: boolean; | |
| supportsTools: boolean; | |
| /** 'discovered': fetched from a built-in provider's own /models because the | |
| * catalog carries no models for it (#1348). */ | |
| source?: 'catalog' | 'custom' | 'discovered'; | |
| keyId?: number | null; | |
| endpointScope?: string | null; | |
| } | |
| // ---- Quirks ---- | |
| // Structured, reusable notes about catalog models. One quirk is applied to many | |
| // models via selector parameters (see quirk_targets / services/quirks.ts). | |
| export type QuirkSeverity = 'info' | 'warning' | 'blocker'; | |
| export interface Quirk { | |
| slug: string; | |
| title: string; | |
| body: string; | |
| severity: QuirkSeverity; | |
| } | |
| export interface QuirkTarget { | |
| platform: Platform | null; | |
| modelGlob: string | null; | |
| } | |
| export interface ModelListRow { | |
| platform: string; | |
| model_id: string; | |
| display_name: string; | |
| context_window: number | null; | |
| // 1 when the catalog row is enabled. 1 when an enabled key can serve it | |
| // (enabled AND a matching enabled api_key exists). SQLite returns 0/1. | |
| enabled: number; | |
| available: number; | |
| } | |
| export type KeyStatus = 'healthy' | 'rate_limited' | 'invalid' | 'error' | 'unknown'; | |
| export interface ApiKeyModel { | |
| id: number; | |
| kind: 'chat' | 'embedding' | 'image' | 'audio' | 'transcription'; | |
| modelId: string; | |
| displayName: string; | |
| family?: string | null; | |
| } | |
| /** An active rate-limit cooldown on one model for a key. A key can be healthy | |
| * and enabled yet still skipped by the router because of these. */ | |
| export interface ApiKeyCooldown { | |
| modelId: string; | |
| expiresAtMs: number; | |
| remainingMs: number; | |
| } | |
| export interface ApiKey { | |
| id: number; | |
| platform: Platform; | |
| label: string; | |
| maskedKey: string; | |
| baseUrl: string | null; | |
| /** Optional custom-endpoint group label (#1176); null = legacy single | |
| * "Custom" group. Only set on platform='custom' rows. */ | |
| groupLabel?: string | null; | |
| status: KeyStatus; | |
| enabled: boolean; | |
| /** This row is the anonymous sentinel of a key-optional platform: there is | |
| * no credential to copy, scope or reveal. */ | |
| keyless: boolean; | |
| /** The platform works with or without a key (Kilo, OVH, AI Horde), so a key | |
| * can be added to or left off this row (#1331). */ | |
| keyOptional?: boolean; | |
| /** Whether an export file would actually contain this row. The server decides | |
| * it so the dialog's "will export N keys" cannot drift from the export. */ | |
| exportable: boolean; | |
| createdAt: string; | |
| lastCheckedAt: string | null; | |
| lastHealthError: string | null; | |
| /** Model ids this key is limited to; null = serves every model of its | |
| * platform (#657). */ | |
| modelScope?: string[] | null; | |
| /** Per-key monthly request cap (0 = unlimited, #1158). */ | |
| monthlyRequestCap?: number; | |
| /** Per-key monthly token cap (0 = unlimited, #1158). */ | |
| monthlyTokenCap?: number; | |
| /** Current UTC month's successful usage against the caps above, with the | |
| * ISO time of the next monthly reset. */ | |
| monthlyUsage?: { requests: number; tokens: number; resetsAt: string }; | |
| /** The per-key proxy override with its password masked (#590); '' = none. */ | |
| maskedProxyUrl?: string; | |
| models?: ApiKeyModel[]; | |
| cooldowns?: ApiKeyCooldown[]; | |
| /** True for a built-in provider key whose platform the catalog carries no | |
| * models for, so the dashboard offers Fetch models on it (#1348). */ | |
| modelDiscovery?: boolean; | |
| } | |
| export interface ApiKeyCreate { | |
| platform: Platform; | |
| key: string; | |
| label?: string; | |
| } | |
| // ---- Fallback Config ---- | |
| export interface FallbackEntry { | |
| modelId: number; | |
| platform: Platform; | |
| displayName: string; | |
| intelligenceRank: number; | |
| speedRank: number; | |
| priority: number; | |
| enabled: boolean; | |
| // Present when model unification is enabled — identifies the logical model | |
| // this provider row belongs to so the dashboard can render grouped rows. | |
| groupKey?: string; | |
| canonicalId?: string; | |
| groupLabel?: string; | |
| } | |
| // ---- Model Grouping (unify the same model across providers) ---- | |
| // One logical model can be served by several providers (rows in the `models` | |
| // table). When unification is enabled, those rows collapse into a single group | |
| // keyed by a normalized display name; see server/src/services/model-groups.ts. | |
| export interface ModelGroupInfo { | |
| groupKey: string; // normalized display name — the grouping identity | |
| canonicalId: string; // stable slug advertised on /v1/models | |
| groupLabel: string; // human label (suffix-stripped display name) | |
| } | |
| export interface UnifyOverrides { | |
| // Coalesce several normalized display-names (or exact "platform:model_id" | |
| // members) into one group keyed by `into`. | |
| merges: { into: string; keys: string[] }[]; | |
| // Force a specific "platform:model_id" row out of its computed group. | |
| splits: { member: string; groupKey?: string }[]; | |
| } | |
| export interface UnifySettings { | |
| enabled: boolean; | |
| overrides: UnifyOverrides; | |
| } | |
| // ---- OpenAI-Compatible Types ---- | |
| export interface ChatToolCallFunction { | |
| name: string; | |
| arguments: string; | |
| } | |
| export interface ChatToolCall { | |
| id: string; | |
| type: 'function'; | |
| function: ChatToolCallFunction; | |
| thought_signature?: string; | |
| } | |
| export interface ChatToolFunctionDefinition { | |
| name: string; | |
| description?: string; | |
| parameters?: Record<string, unknown>; | |
| strict?: boolean; | |
| } | |
| export interface ChatToolDefinition { | |
| type: 'function'; | |
| function: ChatToolFunctionDefinition; | |
| } | |
| export type ChatToolChoice = | |
| | 'none' | |
| | 'auto' | |
| | 'required' | |
| | { | |
| type: 'function'; | |
| function: { | |
| name: string; | |
| }; | |
| }; | |
| // OpenAI's multimodal envelope: clients like opencode / continue.dev send | |
| // content as an array of typed blocks even for text-only messages, and | |
| // Gemini-lineage agents (Qwen Code, AionUI) send part-style `{ text }` blocks | |
| // with no `type` — plus bare strings inside arrays. We accept all of it on | |
| // the wire and flatten to string for providers that don't support arrays | |
| // (Cohere, Cloudflare). See server/src/lib/content.ts. (#200) | |
| export type ChatContentBlock = string | { type?: string; text?: string; [key: string]: unknown }; | |
| export type ChatContent = string | null | ChatContentBlock[]; | |
| export interface ChatMessage { | |
| role: 'system' | 'user' | 'assistant' | 'tool'; | |
| content: ChatContent; | |
| name?: string; | |
| tool_call_id?: string; | |
| tool_calls?: ChatToolCall[]; | |
| // The model's thinking trace on an assistant turn. Some thinking models | |
| // (DeepSeek on OpenCode Zen) require it to be replayed verbatim on the next | |
| // turn or they 400; the proxy preserves and forwards it. See issue #255. | |
| reasoning_content?: string; | |
| // Moonshot's "partial" prefill flag on an assistant turn: when true, the | |
| // model continues the given text instead of starting a fresh turn. Only | |
| // forwarded to models that understand it (Moonshot/Kimi); stripped for all | |
| // other providers. See issue #1038. | |
| partial?: boolean; | |
| } | |
| export interface ChatCompletionRequest { | |
| model?: string; | |
| messages: ChatMessage[]; | |
| temperature?: number; | |
| max_tokens?: number; | |
| stream?: boolean; | |
| stream_options?: { | |
| include_usage?: boolean; | |
| }; | |
| top_p?: number; | |
| stop?: string | string[]; | |
| tools?: ChatToolDefinition[]; | |
| tool_choice?: ChatToolChoice; | |
| parallel_tool_calls?: boolean; | |
| } | |
| export interface ChatCompletionChoice { | |
| index: number; | |
| message: ChatMessage; | |
| finish_reason: string | null; | |
| // Present when the client requested logprobs and the provider returned | |
| // them; passed through verbatim (provider shapes vary slightly). | |
| logprobs?: unknown; | |
| } | |
| export interface TokenUsage { | |
| prompt_tokens: number; | |
| completion_tokens: number; | |
| total_tokens: number; | |
| // OpenAI-standard breakdown some providers advertise alongside the totals. | |
| // Optional because many free-tier endpoints omit it; the proxy falls back | |
| // to its chars/4 estimate when absent. (#764) | |
| completion_tokens_details?: { reasoning_tokens?: number }; | |
| prompt_tokens_details?: { cached_tokens?: number }; | |
| // Gateway-synthesized block (upstream never sent usage): flagged so a | |
| // cost-accounting client can tell it apart from the upstream's real | |
| // counts. (#1084) | |
| estimated?: boolean; | |
| } | |
| export interface ChatCompletionResponse { | |
| id: string; | |
| object: 'chat.completion'; | |
| created: number; | |
| model: string; | |
| choices: ChatCompletionChoice[]; | |
| usage: TokenUsage; | |
| _routed_via?: { | |
| platform: Platform; | |
| model: string; | |
| }; | |
| } | |
| export interface ChatCompletionChunk { | |
| id: string; | |
| object: 'chat.completion.chunk'; | |
| created: number; | |
| model: string; | |
| choices: { | |
| index: number; | |
| delta: { | |
| role?: 'assistant'; | |
| content?: string; | |
| reasoning_content?: string; | |
| tool_calls?: ChatToolCall[]; | |
| }; | |
| finish_reason: string | null; | |
| }[]; | |
| usage?: TokenUsage; | |
| } | |
| // ---- Analytics Types ---- | |
| export interface AnalyticsSummary { | |
| totalRequests: number; | |
| successRate: number; | |
| totalInputTokens: number; | |
| totalOutputTokens: number; | |
| avgLatencyMs: number; | |
| estimatedCostSavings: number; | |
| } | |
| export interface PlatformStats { | |
| platform: Platform; | |
| requests: number; | |
| successRate: number; | |
| avgLatencyMs: number; | |
| totalInputTokens: number; | |
| totalOutputTokens: number; | |
| } | |
| export interface TimelinePoint { | |
| timestamp: string; | |
| requests: number; | |
| successCount: number; | |
| failureCount: number; | |
| } | |
| export interface RequestLog { | |
| id: number; | |
| platform: Platform; | |
| modelId: string; | |
| status: 'success' | 'error'; | |
| inputTokens: number; | |
| outputTokens: number; | |
| latencyMs: number; | |
| error: string | null; | |
| createdAt: string; | |
| } | |
| // ---- Rate Limit Types ---- | |
| export interface RateLimitStatus { | |
| platform: Platform; | |
| modelId: string; | |
| rpm: { used: number; limit: number | null }; | |
| rpd: { used: number; limit: number | null }; | |
| tpm: { used: number; limit: number | null }; | |
| available: boolean; | |
| nextResetAt: string | null; | |
| } | |
| // ---- Provider Quota Observability ---- | |
| export type QuotaMetric = 'requests' | 'tokens' | 'credits' | 'neurons'; | |
| export type QuotaResetStrategy = 'fixed_calendar' | 'rolling_window' | 'token_bucket' | 'provider_reported' | 'unknown'; | |
| export type QuotaObservationSource = 'header' | 'quota_api' | 'error_body' | 'local_usage' | 'documentation' | 'probe'; | |
| export interface ProviderQuotaState { | |
| platform: Platform; | |
| keyId: number; | |
| /** The key's operator-facing label, when the row still names a live key. */ | |
| keyLabel?: string | null; | |
| quotaPoolKey: string; | |
| metric: QuotaMetric; | |
| limit: number | null; | |
| remaining: number | null; | |
| resetAt: string | null; | |
| resetStrategy: QuotaResetStrategy; | |
| source: QuotaObservationSource; | |
| confidence: number; | |
| notes: string | null; | |
| observedAt: string; | |
| updatedAt: string; | |
| } | |
| export interface ProviderQuotaObservation extends ProviderQuotaState { | |
| id: string; | |
| statusCode: number | null; | |
| retryAfterMs: number | null; | |
| providerAccountId: string | null; | |
| modelId: string | null; | |
| endpoint: string | null; | |
| rawJson: string | null; | |
| createdAt: string; | |
| } | |
| export interface QuotaOutlookPool { | |
| platform: Platform; | |
| pool: string; | |
| limit: number | null; | |
| remaining: number | null; | |
| remainingPct: number | null; | |
| observedAt: string | null; | |
| resetAt: string | null; | |
| /** Successful requests through this instance during the observation window. */ | |
| recentRequestCount: number; | |
| ratePerMin: number; | |
| unavailableReason: 'quota_not_reported' | 'stale_observation' | 'reset_not_reported' | 'low_confidence' | null; | |
| estimatedExhaustionAt: string | null; | |
| status: 'unknown' | 'stale' | 'unavailable' | 'insufficient_data' | 'resets_first' | 'forecast' | 'exhausted'; | |
| warning: 'low_balance' | 'exhausting_soon' | null; | |
| } | |
| export interface QuotaOutlookResponse { | |
| generatedAt: string; | |
| observationWindowMinutes: number; | |
| minimumRequests: number; | |
| pools: QuotaOutlookPool[]; | |
| } | |
| // ---- Provider Dashboard Types ---- | |
| export type ProviderHealthStatus = 'healthy' | 'issues' | 'rate_limited' | 'unknown' | 'unconfigured'; | |
| export interface ProviderSummary { | |
| platform: Platform; | |
| name: string; | |
| totalKeys: number; | |
| enabledKeys: number; | |
| healthyKeys: number; | |
| totalModels: number; | |
| activeModels: number; | |
| status: ProviderHealthStatus; | |
| isConfigured: boolean; | |
| } | |
| export interface GroupedProvider { | |
| id: string; | |
| platform: Platform; | |
| name: string; | |
| url?: string; | |
| baseUrl?: string | null; | |
| endpointScope?: string | null; | |
| keyless?: boolean; | |
| keys: ApiKey[]; | |
| models: Model[]; | |
| summary: ProviderSummary; | |
| } | |
| export interface CustomModelCreate { | |
| platform: Platform; | |
| modelId: string; | |
| displayName?: string; | |
| contextWindow?: number | null; | |
| rpmLimit?: number | null; | |
| rpdLimit?: number | null; | |
| tpmLimit?: number | null; | |
| tpdLimit?: number | null; | |
| supportsVision?: boolean; | |
| supportsTools?: boolean; | |
| } | |
| export interface ModelTestResult { | |
| success: boolean; | |
| modelId: string; | |
| latencyMs: number; | |
| error?: string; | |
| } | |