// Shared type definitions for llama-infra (type-only; erased at runtime). import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; export type Currency = "usd" | "eur" | "gbp" | "cny"; /** * Energy-cost profile for one machine: power draw during inference (kW) and * electricity tariff (per kWh, in the configured currency). Cost of a request * = (ms / 3_600_000) × kW × ratePerKwh. `host`/`pattern` refine matching when * needed (they are optional; the serverId association is the primary key). */ export interface CostProfile { label?: string; /** Power draw during inference, in kilowatts. 0/absent = estimation off. */ kW: number; /** Electricity tariff per kWh (in the configured currency). */ ratePerKwh: number; host?: string; pattern?: string; } /** One machine that may serve llama.cpp-family models on one or more ports. */ export interface ServerConfig { id: string; host: string; label?: string; ports: number[]; enabled: boolean; probeDs4?: boolean; apiKey?: string; /** Energy-cost profile for this machine (kW + tariff). */ costProfile?: CostProfile; } /** Thinking budget (tokens) per pi thinking level, llama.cpp-style. */ export interface ThinkingBudgets { minimal?: number; low?: number; medium?: number; high?: number; } /** Per-model options keyed by the registered model id. */ export interface ModelOptions { thinkingBudgets?: ThinkingBudgets; /** Override the top-level request field that carries the thinking budget for * THIS model (e.g. `"thinking_token_budget"` on vLLM when the server kind is * not detected). Wins over the per-kind default; see core.thinkingBudgetField. * Set it to `false` to send **no** budget field at all: some engines (strict * Python workers, vLLM forks with a custom native worker) answer HTTP 400 * "not supported …": the field must then never be sent. llama-infra also * sets this to `false` on its own when a server rejects the field. */ thinkingBudgetField?: string | false; /** Manual override to force vision detection (vLLM does not publish modalities in /v1/models). */ vision?: boolean; /** Informative drafter/spec-decode label (vLLM does not publish it). */ drafter?: string; /** Per-model output cap; wins over the server-reported max_tokens and over settings.maxOutputTokens; clamped to the model contextWindow. */ maxTokens?: number; } export interface SettingsConfig { discoveryTimeoutMs: number; pollIntervalMs: number; pollMaxMs: number; startupGraceMs: number; maxOutputTokens: number; requestTimeoutMs: number; knownGoodFailLimit: number; detectVision: boolean; prefixModelIds: boolean; warmup: boolean; metricsEnabled: boolean; metricsPollMs: number; includeUnloadedRouterModels: boolean; showBadgesInNames: boolean; /** Display currency for energy costs (default: eur). */ currency: Currency; /** Whether the footer shows accumulated energy cost (default: true). */ costTracking: boolean; } export interface InfraConfig { servers: ServerConfig[]; settings: SettingsConfig; modelOptions: Record; } export interface LlamaCppMeta { n_ctx?: number; n_ctx_train?: number; } export interface LmStudioModelInfo { key?: string; id?: string; display_name?: string; type?: string; publisher?: string; architecture?: string | null; arch?: string | null; format?: string | null; compatibility_type?: string | null; quantization?: string | { name?: string | null; bits_per_weight?: number | null } | null; state?: string; max_context_length?: number; loaded_instances?: Array<{ id?: string; config?: { context_length?: number; parallel?: number } }>; capabilities?: { vision?: boolean; trained_for_tool_use?: boolean; reasoning?: boolean | { allowed_options?: string[]; default?: string }; }; selected_variant?: string; variants?: string[]; } export interface LmStudioModelsResponse { models?: LmStudioModelInfo[]; data?: LmStudioModelInfo[]; object?: string; } export interface LlamaCppModel { id: string; name?: string; object?: string; owned_by?: string; display_name?: string; path?: string; /** vLLM: absolute checkpoint path (equivalent to `path` for extracting the quant tag). */ root?: string; /** vLLM: maximum served context length. */ max_model_len?: number; status?: { value?: string; args?: string[]; preset?: string; failed?: boolean; exit_code?: number; }; architecture?: { input_modalities?: string[]; output_modalities?: string[]; }; lmStudio?: LmStudioModelInfo; meta?: LlamaCppMeta; context_window?: number; context_length?: number; max_tokens?: number; } export interface LlamaCppModelsResponse { models?: Array<{ name?: string; model?: string }>; data: LlamaCppModel[]; object?: string; } /** Tolerant view of GET /props across llama.cpp builds and forks. */ export interface ServerProps { model_path?: string | null; model_alias?: string | null; build_info?: string; server?: { name?: string; version?: string }; role?: string; max_instances?: number; total_slots?: number; is_sleeping?: boolean; modalities?: { vision?: boolean; audio?: boolean }; default_generation_settings?: { n_ctx?: number; speculative?: boolean; params?: Record; }; capabilities?: { reasoning_supported?: boolean; tools_supported?: boolean }; model?: { arch?: string | null; draft_path?: string | null }; draft_path?: string | null; cache_type_k?: string; cache_type_v?: string; } export type ServerKind = "llamacpp" | "zinc" | "lucebox" | "dwarfstar" | "lmstudio" | "vllm"; export type ServerMode = "single" | "router" | "unknown"; export interface ModelMetadata { quant?: string; vision?: boolean; drafter?: string; cacheK?: string; cacheV?: string; routerStatus?: string; } export interface EndpointResult { serverId: string; host: string; label: string; port: number; baseUrl: string; server: ServerKind | "auto" | "unknown"; mode: ServerMode; models: LlamaCppModel[]; meta: Map; ok: boolean; error?: string; loading?: boolean; latencyMs?: number; nameMap?: Map; props?: ServerProps; } export interface ScanResult { endpoints: EndpointResult[]; totalModels: number; serversUp: number; serversTotal: number; } export interface ParsedServerArgs { cacheK?: string; cacheV?: string; draft?: string; hasDraft?: boolean; hasMmproj?: boolean; mmprojPath?: string; /** OpenAI-compatible engines (vLLM & co): does the served model accept images? * false = --language-model-only or an image limit of 0; undefined = unknown. */ acceptsImages?: boolean; } export interface LocalServerInfo extends ParsedServerArgs { port: number; } export interface HttpResult { status: number; body: string; contentType?: string; } export interface PiModel { id: string; name: string; baseUrl: string; reasoning: boolean; input: ("text" | "image")[]; cost: { input: number; output: number; cacheRead: number; cacheWrite: number }; contextWindow: number; maxTokens: number; compat?: CompatProfile; headers?: Record; thinkingBudgets?: ThinkingBudgets; serverModelId: string; endpoint: { serverId: string; host: string; port: number; kind: ServerKind | "unknown" | "auto"; mode: ServerMode }; quant?: string; cacheK?: string; cacheV?: string; drafter?: string; routerStatus?: string; } export interface MetricsEndpointDiscovered { url: string; format: "prometheus" | "json"; } /** Server-side snapshot from the /metrics endpoint (see metrics.ts). */ export interface ServerMetricsState { /** In-flight requests reported by the server. */ processing: number; /** Prompt (prefill) rate in tokens/s over the last poll, if measurable. */ promptTps?: number; /** Generation rate in tokens/s over the last poll, if measurable. */ genTps?: number; /** Speculative-decoding acceptance ratio (vLLM `spec_decode_*`), 0..1. */ specAcceptRate?: number; /** Prefix-cache hit ratio (vLLM `prefix_cache_*`), 0..1. */ prefixCacheHitRate?: number; } export type ThemeFg = (color: any, text: string) => string; export interface CompatProfile { supportsDeveloperRole: boolean; supportsReasoningEffort: boolean; maxTokensField: "max_tokens"; supportsUsageInStreaming: boolean; supportsStrictMode: boolean; /** Top-level thinking-budget request field, or `false` when the server must * not receive one at all (pi treats a falsy value as "disabled"). */ thinkingTokenBudgetField?: string | false; /** Set to `false` alongside `thinkingTokenBudgetField: false` so pi's own * alias (`supportsThinkingTokenBudget` → vLLM field) cannot re-enable it. */ supportsThinkingTokenBudget?: boolean; /** pi's per-engine thinking control. `qwen-chat-template` makes pi send * `chat_template_kwargs:{enable_thinking,preserve_thinking}` — what halogen * (and llama.cpp Qwen templates) read to turn thinking off/on. */ thinkingFormat?: | "openai" | "openrouter" | "deepseek" | "together" | "baseten" | "zai" | "qwen" | "chat-template" | "qwen-chat-template" | "string-thinking" | "ant-ling"; } // Re-exports for convenience to keep call-sites stable. export type { ExtensionAPI, ExtensionContext };