import type { InceptronModel } from "./types.js"; /** * Standard thinking-level map for Inceptron reasoning models. Inceptron speaks * the OpenAI Completions API, so reasoning is driven via `reasoning_effort`. * pi's low/medium/high levels map onto the provider's effort buckets; minimal * disables thinking. Applied only to models that actually accept the * `reasoning_effort` parameter (see discovery.ts). */ export const REASONING_EFFORT_MAP: InceptronModel["thinkingLevelMap"] = { minimal: null, low: "low", medium: "medium", high: "high", xhigh: "high", }; /** * Curated fallback catalog used only when dynamic discovery (`GET /v1/models`) * is unavailable (no key, network error, or empty response). When discovery * succeeds, every field below is instead derived live from the API. * * Values verified against `GET https://api.inceptron.io/v1/models` on * 2026-06-18. Cost is USD per million tokens. */ export const INCEPTRON_FALLBACK_MODELS: InceptronModel[] = [ { id: "MiniMaxAI/MiniMax-M2.5", name: "MiniMax M2.5 (FP8)", reasoning: true, thinkingLevelMap: REASONING_EFFORT_MAP, input: ["text"], cost: { input: 0.15, output: 0.9, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 196_608, maxTokens: 196_608, }, { id: "zai-org/GLM-5.1-FP8", name: "GLM 5.1 (FP8)", reasoning: true, thinkingLevelMap: REASONING_EFFORT_MAP, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 202_752, maxTokens: 202_752, }, { id: "moonshotai/Kimi-K2.6", name: "Kimi K2.6 (INT4)", reasoning: true, // Kimi advertises `reasoning` but not the `reasoning_effort` parameter, so // no thinkingLevelMap — pi must not send an unsupported field. input: ["text", "image"], cost: { input: 0.73, output: 3.5, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 262_144, maxTokens: 262_144, }, ]; /** Curated catalog indexed by model id for O(1) enrichment of discovered ids. */ const FALLBACK_BY_ID = new Map( INCEPTRON_FALLBACK_MODELS.map((m) => [m.id, m]), ); /** Look up the curated entry for a model id, if one exists. */ export function findCuratedModel(id: string): InceptronModel | undefined { return FALLBACK_BY_ID.get(id); } /** * Produce a safe, text-only, tool-capable default config for any model id we * have no live metadata for (e.g. a discovery entry missing fields). Conservative * limits; no reasoning, no image input. */ export function defaultModelConfig(id: string): InceptronModel { return { id, // Derive a readable label from the id's last path segment. name: id.split("/").pop() ?? id, reasoning: false, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128_000, maxTokens: 8_192, }; }