From e38958bba9af0aaa788c5baafbdaff539638b7c9 Mon Sep 17 00:00:00 2001 From: 1bcMax Date: Tue, 29 Sep 2026 20:44:31 +0800 Subject: [PATCH] fix: retarget eco SIMPLE's second free rung off the delisted nemotron-3-nano-30b MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit blockrun delisted nvidia/nemotron-3-nano-30b on 2026-09-08: NVIDIA deprovisioned it for the account (a structured per-account 404), nine days after it was listed as the fastest free model. It was still ecoTiers.SIMPLE.fallback[0]. Nothing looked broken because the gateway redirects the id — which is the shape that silently defeats a host's /exclude. ecoTiers.SIMPLE.fallback[0] nemotron-3-nano-30b -> nemotron-3-nano-omni-30b-a3b-reasoning nano-omni is the gateway's own redirect target for nano-30b (both redirect tables, the retired entries' fallbackModel, and the eco.SIMPLE row of the savings mix), so the router and the gateway keep naming the same model — and the model actually served on this rung does not change. model-capabilities.ts: drops nano-30b (no longer in the catalog) and carries a supportsVision:false override for nano-omni. The catalog tags it vision, but ClawRouter's 2026-08-31 64x64 probe got it right 1 of 4 on Base and had the image silently dropped on Solana. Without the override this swap would have started routing eco SIMPLE image turns to it (the regenerated snapshot showed two vision prompts moving off glm-5.3-flash). With it, the decision snapshot moves by exactly one candidate id. Hand-applied rather than regenerated: a full sync against today's catalog rewrites ~80 unrelated lines. The two entries match the generator's output byte for byte. Co-Authored-By: Claude Opus 5.5 (1M context) --- config.ts | 7 ++++++- decisions.snapshot.json | 2 +- dist/index.js | 19 +++++++++---------- dist/index.js.map | 2 +- model-capabilities.ts | 10 ++-------- scripts/capability-overrides.json | 4 ++++ 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/config.ts b/config.ts index b34f9f9..db2f096 100644 --- a/config.ts +++ b/config.ts @@ -1159,7 +1159,12 @@ export const DEFAULT_ROUTING_CONFIG: RoutingConfig = { SIMPLE: { primary: "nvidia/nemotron-3.5-lightning", // FREE — NVIDIA free tier flagship, 1M ctx fallback: [ - "nvidia/nemotron-3-nano-30b", // FREE — fastest free model (~121 tok/s) + // Was nvidia/nemotron-3-nano-30b until blockrun delisted it on 2026-09-08 + // (NVIDIA deprovisioned it for the account — a structured per-account + // 404). nano-omni is blockrun's own redirect target for that id, so this + // follows the same rule as the head: the router and the gateway name the + // same model. + "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning", // FREE — nano-30b's successor, 256K ctx // The free head keeps rotting with NVIDIA's hosting (deepseek-v4-flash // 410 2026-08-12, seed-oss-36b 410 2026-08-03, gpt-oss-120b/20b 400 // 2026-08-21, and on 2026-08-30 FOUR of the five visible free models at diff --git a/decisions.snapshot.json b/decisions.snapshot.json index 61fb442..04f259a 100644 --- a/decisions.snapshot.json +++ b/decisions.snapshot.json @@ -969,7 +969,7 @@ "agenticScore": 0, "candidates": [ "nvidia/nemotron-3.5-lightning", - "nvidia/nemotron-3-nano-30b", + "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning", "google/gemini-2.5-flash-lite", "zai/glm-5.3-flash", "openai/gpt-5.6-luna", diff --git a/dist/index.js b/dist/index.js index 40c058f..e57dbaa 100644 --- a/dist/index.js +++ b/dist/index.js @@ -660,18 +660,12 @@ var DEFAULT_MODEL_CAPABILITIES = Object.freeze({ supportsTools: false, supportsVision: true }, - "nvidia/nemotron-3-nano-30b": { - // supportsTools: not probed — fails closed - contextWindow: 131072, - maxOutputTokens: 16384, - supportsTools: false, - supportsVision: false - }, "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning": { + // override: The catalog tags this model "vision", but a correctly sized probe does not hold up (ClawRouter, 2026-08-31): a 64x64 solid-red PNG was named correctly 1 of 4 times on Base, and on Solana the image was silently dropped and a text model answered "white". An HTTP 200 with a confident wrong answer gives the caller nothing to branch on, so image turns must not be routed here. It is ecoTiers.SIMPLE.fallback[0] since nemotron-3-nano-30b was delisted (2026-09-08); remove once a probe of this size comes back right on both chains. contextWindow: 256e3, maxOutputTokens: 16384, supportsTools: false, - supportsVision: true + supportsVision: false }, "nvidia/nemotron-3-ultra-550b": { // supportsTools: not probed — fails closed @@ -3498,8 +3492,13 @@ var DEFAULT_ROUTING_CONFIG = { primary: "nvidia/nemotron-3.5-lightning", // FREE — NVIDIA free tier flagship, 1M ctx fallback: [ - "nvidia/nemotron-3-nano-30b", - // FREE — fastest free model (~121 tok/s) + // Was nvidia/nemotron-3-nano-30b until blockrun delisted it on 2026-09-08 + // (NVIDIA deprovisioned it for the account — a structured per-account + // 404). nano-omni is blockrun's own redirect target for that id, so this + // follows the same rule as the head: the router and the gateway name the + // same model. + "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning", + // FREE — nano-30b's successor, 256K ctx // The free head keeps rotting with NVIDIA's hosting (deepseek-v4-flash // 410 2026-08-12, seed-oss-36b 410 2026-08-03, gpt-oss-120b/20b 400 // 2026-08-21, and on 2026-08-30 FOUR of the five visible free models at diff --git a/dist/index.js.map b/dist/index.js.map index 330db93..7f2d971 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../rules.ts","../selector.ts","../strategy.ts","../model-capabilities.ts","../model-profiles.generated.json","../model-profiles.ts","../tool-intent.ts","../portfolio.ts","../config.ts","../index.ts"],"sourcesContent":["/**\n * Rule-Based Classifier (v2 — Weighted Scoring)\n *\n * Scores a request across 15 weighted dimensions and maps the aggregate\n * score to a tier using configurable boundaries. Confidence is calibrated\n * via sigmoid — low confidence triggers the fallback classifier.\n *\n * Handles 70-80% of requests in < 1ms with zero cost.\n */\n\nimport type { Tier, ScoringResult, ScoringConfig } from \"./types.js\";\n\ntype DimensionScore = { name: string; score: number; signal: string | null };\n\n// ─── Dimension Scorers ───\n// Each returns a score in [-1, 1] and an optional signal string.\n\nfunction scoreTokenCount(\n estimatedTokens: number,\n thresholds: { simple: number; complex: number },\n): DimensionScore {\n if (estimatedTokens < thresholds.simple) {\n return { name: \"tokenCount\", score: -1.0, signal: `short (${estimatedTokens} tokens)` };\n }\n if (estimatedTokens > thresholds.complex) {\n return { name: \"tokenCount\", score: 1.0, signal: `long (${estimatedTokens} tokens)` };\n }\n return { name: \"tokenCount\", score: 0, signal: null };\n}\n\nfunction scoreKeywordMatch(\n text: string,\n keywords: string[],\n name: string,\n signalLabel: string,\n thresholds: { low: number; high: number },\n scores: { none: number; low: number; high: number },\n): DimensionScore {\n const matches = keywords.filter((kw) => text.includes(kw.toLowerCase()));\n if (matches.length >= thresholds.high) {\n return {\n name,\n score: scores.high,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n if (matches.length >= thresholds.low) {\n return {\n name,\n score: scores.low,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n return { name, score: scores.none, signal: null };\n}\n\nfunction scoreMultiStep(text: string): DimensionScore {\n const patterns = [/first.*then/i, /step \\d/i, /\\d\\.\\s/];\n const hits = patterns.filter((p) => p.test(text));\n if (hits.length > 0) {\n return { name: \"multiStepPatterns\", score: 0.5, signal: \"multi-step\" };\n }\n return { name: \"multiStepPatterns\", score: 0, signal: null };\n}\n\nfunction scoreQuestionComplexity(prompt: string): DimensionScore {\n const count = (prompt.match(/\\?/g) || []).length;\n if (count > 3) {\n return { name: \"questionComplexity\", score: 0.5, signal: `${count} questions` };\n }\n return { name: \"questionComplexity\", score: 0, signal: null };\n}\n\n/**\n * Score agentic task indicators.\n * Returns agenticScore (0-1) based on keyword matches:\n * - 4+ matches = 1.0 (high agentic)\n * - 3 matches = 0.6 (moderate agentic, triggers auto-agentic mode)\n * - 1-2 matches = 0.2 (low agentic)\n *\n * Thresholds raised because common keywords were pruned from the list.\n */\nfunction scoreAgenticTask(\n text: string,\n keywords: string[],\n): { dimensionScore: DimensionScore; agenticScore: number } {\n let matchCount = 0;\n const signals: string[] = [];\n\n for (const keyword of keywords) {\n if (text.includes(keyword.toLowerCase())) {\n matchCount++;\n if (signals.length < 3) {\n signals.push(keyword);\n }\n }\n }\n\n // Threshold-based scoring (raised thresholds after keyword pruning)\n if (matchCount >= 4) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 1.0,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 1.0,\n };\n } else if (matchCount >= 3) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.6,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 0.6,\n };\n } else if (matchCount >= 1) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.2,\n signal: `agentic-light (${signals.join(\", \")})`,\n },\n agenticScore: 0.2,\n };\n }\n\n return {\n dimensionScore: { name: \"agenticTask\", score: 0, signal: null },\n agenticScore: 0,\n };\n}\n\n// ─── Main Classifier ───\n\nexport function classifyByRules(\n prompt: string,\n systemPrompt: string | undefined,\n estimatedTokens: number,\n config: ScoringConfig,\n): ScoringResult {\n // Score against user prompt only — system prompts contain boilerplate keywords\n // (tool definitions, skill descriptions, behavioral rules) that dominate scoring\n // and make every request score identically. See GitHub issue #50.\n const userText = prompt.toLowerCase();\n\n // Score the base dimensions against user text only; the agentic dimension is\n // appended below, so the scored total is one more than this list.\n const dimensions: DimensionScore[] = [\n // Token count uses total estimated tokens (system + user) — context size matters for model selection\n scoreTokenCount(estimatedTokens, config.tokenCountThresholds),\n scoreKeywordMatch(\n userText,\n config.codeKeywords,\n \"codePresence\",\n \"code\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.reasoningKeywords,\n \"reasoningMarkers\",\n \"reasoning\",\n { low: 1, high: 2 },\n { none: 0, low: 0.7, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.technicalKeywords,\n \"technicalTerms\",\n \"technical\",\n { low: 2, high: 4 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.creativeKeywords,\n \"creativeMarkers\",\n \"creative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.simpleKeywords,\n \"simpleIndicators\",\n \"simple\",\n { low: 1, high: 2 },\n { none: 0, low: -1.0, high: -1.0 },\n ),\n scoreMultiStep(userText),\n scoreQuestionComplexity(prompt),\n\n // 6 new dimensions\n scoreKeywordMatch(\n userText,\n config.imperativeVerbs,\n \"imperativeVerbs\",\n \"imperative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.constraintIndicators,\n \"constraintCount\",\n \"constraints\",\n { low: 1, high: 3 },\n { none: 0, low: 0.3, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.outputFormatKeywords,\n \"outputFormat\",\n \"format\",\n { low: 1, high: 2 },\n { none: 0, low: 0.4, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.referenceKeywords,\n \"referenceComplexity\",\n \"references\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.negationKeywords,\n \"negationComplexity\",\n \"negation\",\n { low: 2, high: 3 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.domainSpecificKeywords,\n \"domainSpecificity\",\n \"domain-specific\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.8 },\n ),\n ];\n\n // Score agentic task indicators — user prompt only\n // System prompt describes assistant behavior, not user's intent.\n // e.g. a coding assistant system prompt with \"edit files\" / \"fix bugs\" should NOT\n // force every request into agentic mode.\n const agenticResult = scoreAgenticTask(userText, config.agenticTaskKeywords);\n dimensions.push(agenticResult.dimensionScore);\n const agenticScore = agenticResult.agenticScore;\n\n // Collect signals\n const signals = dimensions.filter((d) => d.signal !== null).map((d) => d.signal!);\n\n // Compute weighted score\n const weights = config.dimensionWeights;\n let weightedScore = 0;\n for (const d of dimensions) {\n const w = weights[d.name] ?? 0;\n weightedScore += d.score * w;\n }\n\n // Count reasoning markers for override — only check USER prompt, not system prompt\n // This prevents system prompts with \"step by step\" from triggering REASONING for simple queries\n const reasoningMatches = config.reasoningKeywords.filter((kw) =>\n userText.includes(kw.toLowerCase()),\n );\n\n // Direct reasoning override: 2+ reasoning markers = high confidence REASONING\n if (reasoningMatches.length >= 2) {\n const confidence = calibrateConfidence(\n Math.max(weightedScore, 0.3), // ensure positive for confidence calc\n config.confidenceSteepness,\n );\n return {\n score: weightedScore,\n tier: \"REASONING\",\n confidence: Math.max(confidence, 0.85),\n signals,\n agenticScore,\n dimensions,\n };\n }\n\n // Map weighted score to tier using boundaries\n const { simpleMedium, mediumComplex, complexReasoning } = config.tierBoundaries;\n let tier: Tier;\n let distanceFromBoundary: number;\n\n if (weightedScore < simpleMedium) {\n tier = \"SIMPLE\";\n distanceFromBoundary = simpleMedium - weightedScore;\n } else if (weightedScore < mediumComplex) {\n tier = \"MEDIUM\";\n distanceFromBoundary = Math.min(weightedScore - simpleMedium, mediumComplex - weightedScore);\n } else if (weightedScore < complexReasoning) {\n tier = \"COMPLEX\";\n distanceFromBoundary = Math.min(\n weightedScore - mediumComplex,\n complexReasoning - weightedScore,\n );\n } else {\n tier = \"REASONING\";\n distanceFromBoundary = weightedScore - complexReasoning;\n }\n\n // Calibrate confidence via sigmoid of distance from nearest boundary\n const confidence = calibrateConfidence(distanceFromBoundary, config.confidenceSteepness);\n\n // If confidence is below threshold → ambiguous\n if (confidence < config.confidenceThreshold) {\n return { score: weightedScore, tier: null, confidence, signals, agenticScore, dimensions };\n }\n\n return { score: weightedScore, tier, confidence, signals, agenticScore, dimensions };\n}\n\n/**\n * Sigmoid confidence calibration.\n * Maps distance from tier boundary to [0.5, 1.0] confidence range.\n */\nfunction calibrateConfidence(distance: number, steepness: number): number {\n return 1 / (1 + Math.exp(-steepness * distance));\n}\n","/**\n * Tier → Model Selection\n *\n * Maps a classification tier to the cheapest capable model.\n * Builds RoutingDecision metadata with cost estimates and savings.\n */\n\nimport type { Tier, TierConfig, RoutingDecision } from \"./types.js\";\n\nexport type ModelPricing = {\n inputPrice: number; // per 1M tokens\n outputPrice: number; // per 1M tokens\n /** Active promo flat price per request (overrides token-based pricing when set) */\n flatPrice?: number;\n};\n\n// The savings baseline is a price anchor, not \"the current flagship\" — it is\n// deliberately NOT bumped every time a new Opus ships. Opus 4.7, 4.8 and 5 all\n// bill $5/$25, so moving it would change no reported number while breaking\n// comparability with historical journal entries. Only move it if the Opus tier\n// itself is repriced.\nconst BASELINE_MODEL_ID = \"anthropic/claude-opus-4.7\";\n\n// Hardcoded fallback: Claude Opus 4.7 pricing (per 1M tokens)\n// Used when baseline model not found in dynamic pricing map\nconst BASELINE_INPUT_PRICE = 5.0;\nconst BASELINE_OUTPUT_PRICE = 25.0;\n\n/**\n * Select the primary model for a tier and build the RoutingDecision.\n *\n * Cost contract: the estimates here are raw token economics — no server\n * margin, no minimum-payment floor. `calculateModelCost` below applies both\n * to match the actual x402 charge, and hosts that display money (ClawRouter's\n * proxy does) recompute through it rather than reading these fields. Folding\n * the margin in here would double-apply it in every such host.\n */\nexport function selectModel(\n tier: Tier,\n confidence: number,\n method: \"rules\" | \"llm\" | \"portfolio\",\n reasoning: string,\n tierConfigs: Record,\n modelPricing: Map,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n agenticScore?: number,\n): RoutingDecision {\n const tierConfig = tierConfigs[tier];\n const model = tierConfig.primary;\n const pricing = modelPricing.get(model);\n\n let costEstimate: number;\n if (pricing?.flatPrice !== undefined) {\n costEstimate = pricing.flatPrice;\n } else {\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n costEstimate =\n (estimatedInputTokens / 1_000_000) * inputPrice + (maxOutputTokens / 1_000_000) * outputPrice;\n }\n\n // Baseline: what the anchor Opus tier would cost (see BASELINE_MODEL_ID)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return {\n model,\n tier,\n confidence,\n method,\n reasoning,\n costEstimate,\n baselineCost,\n savings,\n ...(agenticScore !== undefined && { agenticScore }),\n };\n}\n\n/**\n * Get the ordered fallback chain for a tier: [primary, ...fallbacks].\n */\nexport function getFallbackChain(tier: Tier, tierConfigs: Record): string[] {\n const config = tierConfigs[tier];\n return [config.primary, ...config.fallback];\n}\n\n/**\n * Calculate charge-accurate cost fields for a specific model (server margin\n * and minimum-payment floor included — see the cost contract on selectModel).\n * Hosts call this to display money and to recost a decision after a fallback.\n */\n// Server-side margin applied to all x402 payments (must match blockrun server's MARGIN_PERCENT)\nconst SERVER_MARGIN_PERCENT = 5;\n// Minimum payment enforced by CDP Facilitator (must match blockrun server's MIN_PAYMENT_USD)\nconst MIN_PAYMENT_USD = 0.001;\n\nexport function calculateModelCost(\n model: string,\n modelPricing: Map,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n): { costEstimate: number; baselineCost: number; savings: number } {\n const pricing = modelPricing.get(model);\n\n let costEstimate: number;\n if (pricing?.flatPrice !== undefined) {\n // Active promo: fixed cost per request\n costEstimate = Math.max(pricing.flatPrice * (1 + SERVER_MARGIN_PERCENT / 100), MIN_PAYMENT_USD);\n } else {\n // Defensive: guard against undefined price fields (not just undefined pricing)\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n const inputCost = (estimatedInputTokens / 1_000_000) * inputPrice;\n const outputCost = (maxOutputTokens / 1_000_000) * outputPrice;\n // Include server margin + minimum payment to match actual x402 charge\n costEstimate = Math.max(\n (inputCost + outputCost) * (1 + SERVER_MARGIN_PERCENT / 100),\n MIN_PAYMENT_USD,\n );\n }\n\n // Baseline: what the anchor Opus tier would cost (see BASELINE_MODEL_ID)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return { costEstimate, baselineCost, savings };\n}\n\n/**\n * Filter a model list to only those that support tool calling.\n * When hasTools is false, returns the list unchanged.\n * When all models lack tool calling support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByToolCalling(\n models: string[],\n hasTools: boolean,\n supportsToolCalling: (modelId: string) => boolean,\n): string[] {\n if (!hasTools) return models;\n const filtered = models.filter(supportsToolCalling);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Filter a model list to only those that support vision (image inputs).\n * When hasVision is false, returns the list unchanged.\n * When all models lack vision support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByVision(\n models: string[],\n hasVision: boolean,\n supportsVision: (modelId: string) => boolean,\n): string[] {\n if (!hasVision) return models;\n const filtered = models.filter(supportsVision);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Filter a model list to remove user-excluded models.\n * When all models are excluded, returns the full list as a fallback\n * (same safety pattern as filterByToolCalling/filterByVision).\n */\nexport function filterByExcludeList(models: string[], excludeList: Set): string[] {\n if (excludeList.size === 0) return models;\n const filtered = models.filter((m) => !excludeList.has(m));\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Get the fallback chain filtered by context length.\n * Only returns models that can handle the estimated total context.\n *\n * @param tier - The tier to get fallback chain for\n * @param tierConfigs - Tier configurations\n * @param estimatedTotalTokens - Estimated total context (input + output)\n * @param getContextWindow - Function to get context window for a model ID\n * @returns Filtered list of models that can handle the context\n */\nexport function getFallbackChainFiltered(\n tier: Tier,\n tierConfigs: Record,\n estimatedTotalTokens: number,\n getContextWindow: (modelId: string) => number | undefined,\n): string[] {\n const fullChain = getFallbackChain(tier, tierConfigs);\n\n // Filter to models that can handle the context\n const filtered = fullChain.filter((modelId) => {\n const contextWindow = getContextWindow(modelId);\n if (contextWindow === undefined) {\n // Unknown model - include it (let API reject if needed)\n return true;\n }\n // Add 10% buffer for safety\n return contextWindow >= estimatedTotalTokens * 1.1;\n });\n\n // If all models filtered out, return the original chain\n // (let the API error out - better than no options)\n if (filtered.length === 0) {\n return fullChain;\n }\n\n return filtered;\n}\n\n/**\n * Filter an already-ranked candidate list by total context and requested output.\n * Unlike the legacy tier helper, this supports the V3 portfolio order.\n */\nexport function filterCandidatesByCapacity(\n models: string[],\n estimatedInputTokens: number,\n requestedOutputTokens: number,\n getCapabilities: (modelId: string) => { contextWindow: number; maxOutput: number } | undefined,\n): string[] {\n const filtered = models.filter((modelId) => {\n const capabilities = getCapabilities(modelId);\n if (!capabilities) return true;\n return (\n capabilities.contextWindow >= (estimatedInputTokens + requestedOutputTokens) * 1.1 &&\n capabilities.maxOutput >= requestedOutputTokens\n );\n });\n return filtered;\n}\n","/**\n * Router Strategy Registry\n *\n * Pluggable strategy system for request routing.\n * Default: RulesStrategy — identical to the original inline route() logic, <1ms.\n */\n\nimport type {\n Tier,\n TierConfig,\n Promotion,\n RoutingDecision,\n RouterStrategy,\n RouterOptions,\n} from \"./types.js\";\nimport { classifyByRules } from \"./rules.js\";\nimport { selectModel } from \"./selector.js\";\n\n/**\n * Apply active time-windowed promotions to tier configs.\n * Returns a new tierConfigs object with promotion overrides merged in.\n * Expired or not-yet-active promotions are ignored.\n */\nfunction applyPromotions(\n tierConfigs: Record,\n promotions: Promotion[] | undefined,\n profile: \"auto\" | \"eco\" | \"premium\" | \"agentic\",\n now: Date = new Date(),\n): Record {\n if (!promotions || promotions.length === 0) return tierConfigs;\n\n let result = tierConfigs;\n for (const promo of promotions) {\n // Check time window\n const start = new Date(promo.startDate);\n const end = new Date(promo.endDate);\n if (now < start || now >= end) continue;\n\n // Check profile filter\n if (promo.profiles && !promo.profiles.includes(profile)) continue;\n\n // Shallow-clone on first mutation\n if (result === tierConfigs) {\n result = { ...tierConfigs };\n for (const t of Object.keys(result) as Tier[]) {\n result[t] = { ...result[t] };\n }\n }\n\n // Merge overrides\n for (const [tier, override] of Object.entries(promo.tierOverrides) as [\n Tier,\n Partial,\n ][]) {\n if (!result[tier]) continue;\n if (override.primary) result[tier].primary = override.primary;\n if (override.fallback) result[tier].fallback = override.fallback;\n }\n }\n\n return result;\n}\n\n/**\n * Remove host-declared-dead models from every tier chain, promoting the first\n * surviving rung to primary. A tier whose chain is entirely dead keeps its\n * original config — the router has nothing live to offer there, and inventing\n * a model would hide the outage from the host that reported it.\n */\nexport function applyUnavailableModels(\n tierConfigs: Record,\n unavailableModels: readonly string[] | undefined,\n): Record {\n if (!unavailableModels || unavailableModels.length === 0) return tierConfigs;\n const dead = new Set(unavailableModels);\n let result = tierConfigs;\n for (const tier of Object.keys(tierConfigs) as Tier[]) {\n const config = tierConfigs[tier];\n const alive = [config.primary, ...config.fallback].filter((model) => !dead.has(model));\n if (alive.length === 0 || (alive[0] === config.primary && alive.length === config.fallback.length + 1)) {\n continue;\n }\n if (result === tierConfigs) result = { ...tierConfigs };\n result[tier] = { primary: alive[0], fallback: alive.slice(1) };\n }\n return result;\n}\n\n/**\n * Rules-based routing strategy.\n * Extracted from the original route() in index.ts — logic is identical.\n * Attaches tierConfigs and profile to the decision for downstream use.\n */\nexport class RulesStrategy implements RouterStrategy {\n readonly name = \"rules\";\n\n route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n ): RoutingDecision {\n const { config, modelPricing } = options;\n\n // Estimate input tokens (~4 chars per token)\n const fullText = `${systemPrompt ?? \"\"} ${prompt}`;\n const estimatedTokens = Math.ceil(fullText.length / 4);\n const scanLimit = Math.max(1, Math.min(8_000, config.classifier.promptTruncationChars));\n const sample = (value: string): string => {\n if (value.length <= scanLimit) return value;\n const prefixLength = Math.ceil(scanLimit / 2);\n return `${value.slice(0, prefixLength)}\\n${value.slice(-(scanLimit - prefixLength))}`;\n };\n const scannedPrompt = sample(prompt);\n const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : undefined;\n\n // --- Rule-based classification (runs first to get agenticScore) ---\n const ruleResult = classifyByRules(\n scannedPrompt,\n scannedSystemPrompt,\n estimatedTokens,\n config.scoring,\n );\n\n // --- Select tier configs based on routing profile ---\n const { routingProfile } = options;\n let tierConfigs: Record;\n let profileSuffix: string;\n let profile: RoutingDecision[\"profile\"];\n\n if (routingProfile === \"eco\") {\n // `ecoTiers: null` explicitly disables the special eco tier set while\n // keeping eco routing semantics. Fall back to regular tiers instead of\n // dropping into auto routing (which could select agentic tiers).\n tierConfigs = config.ecoTiers ?? config.tiers;\n profileSuffix = config.ecoTiers ? \" | eco\" : \" | eco (default tiers)\";\n profile = \"eco\";\n } else if (routingProfile === \"premium\") {\n // `premiumTiers: null` disables the premium-specific tier set but the\n // request is still a premium-profile request, so use regular tiers while\n // preserving premium metadata/cost semantics.\n tierConfigs = config.premiumTiers ?? config.tiers;\n profileSuffix = config.premiumTiers ? \" | premium\" : \" | premium (default tiers)\";\n profile = \"premium\";\n } else {\n // Auto profile (or undefined): intelligent routing with agentic detection.\n //\n // `agenticMode` semantics:\n // - `true` → force agentic tiers (ignore heuristics)\n // - `false` → disable agentic tiers entirely (even if tools are present)\n // - `undefined` → auto-detect via heuristics (tools present OR high agenticScore)\n const agenticScore = ruleResult.agenticScore ?? 0;\n const isAutoAgentic = agenticScore >= 0.5;\n const agenticModeSetting = config.overrides.agenticMode;\n const hasToolsInRequest = options.requiresTools ?? options.hasTools ?? false;\n let useAgenticTiers: boolean;\n if (agenticModeSetting === false) {\n // Explicitly disabled — never use agentic tiers\n useAgenticTiers = false;\n } else if (agenticModeSetting === true) {\n // Explicitly enabled — use agentic tiers if available\n useAgenticTiers = config.agenticTiers != null;\n } else {\n // Auto-detect\n useAgenticTiers = (hasToolsInRequest || isAutoAgentic) && config.agenticTiers != null;\n }\n tierConfigs = useAgenticTiers ? config.agenticTiers! : config.tiers;\n profileSuffix = useAgenticTiers ? ` | agentic${hasToolsInRequest ? \" (tools)\" : \"\"}` : \"\";\n profile = useAgenticTiers ? \"agentic\" : \"auto\";\n }\n\n // Apply time-windowed promotions\n tierConfigs = applyPromotions(tierConfigs, config.promotions, profile!, options.now);\n\n // Hard-remove models the host has observed dead at the gateway. After\n // promotions, so a promo cannot resurrect a rung the host just killed.\n tierConfigs = applyUnavailableModels(tierConfigs, options.unavailableModels);\n\n const agenticScoreValue = ruleResult.agenticScore;\n\n // --- Override: large context → force COMPLEX ---\n if (estimatedTokens > config.overrides.maxTokensForceComplex) {\n const decision = selectModel(\n \"COMPLEX\",\n 0.95,\n \"rules\",\n `Input exceeds ${config.overrides.maxTokensForceComplex} tokens${profileSuffix}`,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n return { ...decision, tierConfigs, profile };\n }\n\n // Structured output detection\n const hasStructuredOutput =\n options.requiresStructuredOutput === true ||\n (scannedSystemPrompt ? /json|structured|schema/i.test(scannedSystemPrompt) : false);\n\n let tier: Tier;\n let confidence: number;\n const method: \"rules\" | \"llm\" = \"rules\";\n let reasoning = `score=${ruleResult.score.toFixed(2)} | ${ruleResult.signals.join(\", \")}`;\n\n if (ruleResult.tier !== null) {\n tier = ruleResult.tier;\n confidence = ruleResult.confidence;\n } else {\n // Ambiguous — default to configurable tier (no external API call)\n tier = config.overrides.ambiguousDefaultTier;\n confidence = 0.5;\n reasoning += ` | ambiguous -> default: ${tier}`;\n }\n\n // Apply structured output minimum tier\n if (hasStructuredOutput) {\n const tierRank: Record = { SIMPLE: 0, MEDIUM: 1, COMPLEX: 2, REASONING: 3 };\n const minTier = config.overrides.structuredOutputMinTier;\n if (tierRank[tier] < tierRank[minTier]) {\n reasoning += ` | upgraded to ${minTier} (structured output)`;\n tier = minTier;\n }\n }\n\n // Add routing profile suffix to reasoning\n reasoning += profileSuffix;\n\n const decision = selectModel(\n tier,\n confidence,\n method,\n reasoning,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n return { ...decision, tierConfigs, profile };\n }\n}\n\n// --- Strategy Registry ---\n\nconst registry = new Map();\nregistry.set(\"rules\", new RulesStrategy());\n\nexport function getStrategy(name: string): RouterStrategy {\n const strategy = registry.get(name);\n if (!strategy) {\n throw new Error(`Unknown routing strategy: ${name}`);\n }\n return strategy;\n}\n\nexport function registerStrategy(strategy: RouterStrategy): void {\n registry.set(strategy.name, strategy);\n}\n","/**\n * Model capabilities used for hard routing constraints.\n *\n * Hosts may inject fresher values through RouterOptions.modelCapabilities.\n * Keeping a small built-in snapshot makes the core safe and useful when a\n * product catalog is temporarily unavailable, without importing product code.\n *\n * GENERATED by scripts/sync-model-capabilities.mjs from the public catalog\n * (GET https://blockrun.ai/api/v1/models) on 2026-08-31; supportsTools comes\n * from a live function-calling probe (scripts/probe-tools.json). Regenerate\n * rather than editing by hand — a hand edit is overwritten on the next sync.\n */\nexport type ModelCapabilities = {\n contextWindow: number;\n maxOutputTokens: number;\n supportsTools: boolean;\n supportsVision: boolean;\n};\n\nexport const DEFAULT_MODEL_CAPABILITIES: Readonly> =\n Object.freeze({\n \"anthropic/claude-fable-5\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-haiku-4.5\": { // override: The public catalog's `categories` omit \"vision\" for this Anthropic model even though the gateway accepts image input for it (the prior hand-maintained snapshot had it, and Anthropic's model card lists it). Without this the vision filter would silently drop it — reported against the catalog; remove once the categories carry vision.\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-4.5\": {\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-4.7\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-4.8\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-5\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-sonnet-4.5\": {\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-sonnet-4.6\": { // override: The public catalog's `categories` omit \"vision\" for this Anthropic model even though the gateway accepts image input for it (the prior hand-maintained snapshot had it, and Anthropic's model card lists it). Without this the vision filter would silently drop it — reported against the catalog; remove once the categories carry vision.\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-sonnet-5\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"cohere/north-mini-code\": { // supportsTools: not probed — fails closed\n contextWindow: 256_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"deepseek/deepseek-chat\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"deepseek/deepseek-reasoner\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"deepseek/deepseek-v4-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-2.5-flash\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-2.5-flash-lite\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-2.5-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3-flash-preview\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3.1-flash-lite\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-3.1-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3.5-flash\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3.5-flash-lite\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-3.6-flash\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"minimax/minimax-m2.7\": {\n contextWindow: 204_800,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: false,\n },\n \"minimax/minimax-m3\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"moonshot/kimi-k3\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"nvidia/llama-3.2-11b-vision\": { // supportsTools: not probed — fails closed\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: true,\n },\n \"nvidia/nemotron-3-nano-30b\": { // supportsTools: not probed — fails closed\n contextWindow: 131_072,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning\": {\n contextWindow: 256_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: true,\n },\n \"nvidia/nemotron-3-ultra-550b\": { // supportsTools: not probed — fails closed\n contextWindow: 1_000_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"nvidia/nemotron-3.5-lightning\": { // supportsTools: not probed — fails closed\n contextWindow: 1_000_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"openai/chat-latest\": {\n contextWindow: 128_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-4.1\": {\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-4.1-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-4.1-nano\": {\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-4o\": {\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-4o-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5-mini\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5.2\": {\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.2-pro\": { // supportsTools: not probed — fails closed\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.3-codex\": { // supportsTools: gateway unavailable at probe time — fails closed; override: 2026-08-29 probe: every request (6 plain + 3 tool attempts) returned a gateway 500, so the probe measured an incident, not the model. Codex's function calling is established by the 2026-07 Terminal-Bench / tau2 calibration trajectories in portfolio.ts. Hosts observing the 500s should drop it with RouterOptions.unavailableModels rather than this snapshot claiming the model cannot call tools.\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5.4\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.4-mini\": {\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.4-nano\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5.4-pro\": { // supportsTools: not probed — fails closed\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.5\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.5-pro\": { // supportsTools: not probed — fails closed\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.6-luna\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-luna-pro\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.6-sol\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-sol-pro\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-terra\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-terra-pro\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/o1\": {\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/o3\": {\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/o3-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/o4-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"poolside/laguna-xs-2.1\": { // supportsTools: not probed — fails closed\n contextWindow: 131_072,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"qwen/qwen3.7-flash\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"qwen/qwen3.7-max\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"qwen/qwen3.7-plus\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"tencent/hy3\": {\n contextWindow: 262_144,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"xai/grok-4.3\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: true,\n },\n \"xai/grok-4.5\": {\n contextWindow: 500_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: true,\n },\n \"xai/grok-build-0.1\": {\n contextWindow: 256_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: false,\n },\n \"xiaomi/mimo-v2.5-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5-turbo\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.1\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.2\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.3\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.3-flash\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: true,\n },\n });\n","{\n \"anthropic/claude-fable-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9298.5,\n \"p95LatencyMs\": 9873.4,\n \"outputTokensPerSecond\": 55.17,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-haiku-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3157.4,\n \"p95LatencyMs\": 3170.7,\n \"outputTokensPerSecond\": 162.16,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6497.7,\n \"p95LatencyMs\": 6953.7,\n \"outputTokensPerSecond\": 78.99,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-4.7\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5316.5,\n \"p95LatencyMs\": 6121.5,\n \"outputTokensPerSecond\": 97.34,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-4.8\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6216.1,\n \"p95LatencyMs\": 6847.7,\n \"outputTokensPerSecond\": 82.81,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7309,\n \"p95LatencyMs\": 7745.2,\n \"outputTokensPerSecond\": 70.17,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-sonnet-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6330.4,\n \"p95LatencyMs\": 6631.6,\n \"outputTokensPerSecond\": 81.03,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-sonnet-4.6\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6508,\n \"p95LatencyMs\": 6698.3,\n \"outputTokensPerSecond\": 78.6,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-sonnet-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6165.4,\n \"p95LatencyMs\": 6582.9,\n \"outputTokensPerSecond\": 83.62,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"deepseek/deepseek-chat\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4351.4,\n \"p95LatencyMs\": 4543.7,\n \"outputTokensPerSecond\": 117.78,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"deepseek/deepseek-reasoner\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5201.2,\n \"p95LatencyMs\": 6079.6,\n \"outputTokensPerSecond\": 99.77,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"deepseek/deepseek-v4-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 8781.2,\n \"p95LatencyMs\": 9881.1,\n \"outputTokensPerSecond\": 58.98,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-2.5-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5416.4,\n \"p95LatencyMs\": 6442.8,\n \"outputTokensPerSecond\": 213.07,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-2.5-flash-lite\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5002.6,\n \"p95LatencyMs\": 5780.3,\n \"outputTokensPerSecond\": 408.43,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-2.5-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 28169.5,\n \"p95LatencyMs\": 29491.4,\n \"outputTokensPerSecond\": 147.3,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3-flash-preview\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4717.1,\n \"p95LatencyMs\": 5037.1,\n \"outputTokensPerSecond\": 198.71,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.1-flash-lite\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 2855.8,\n \"p95LatencyMs\": 3172.7,\n \"outputTokensPerSecond\": 286.91,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.1-pro\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 24194.1,\n \"p95LatencyMs\": 27269.6,\n \"outputTokensPerSecond\": 109.47,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.5-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5320.6,\n \"p95LatencyMs\": 5429.8,\n \"outputTokensPerSecond\": 226.21,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.5-flash-lite\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3515.8,\n \"p95LatencyMs\": 4363.4,\n \"outputTokensPerSecond\": 248.9,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.6-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 13020,\n \"p95LatencyMs\": 15383.1,\n \"outputTokensPerSecond\": 187.87,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"minimax/minimax-m2.7\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 8761.1,\n \"p95LatencyMs\": 10199.3,\n \"outputTokensPerSecond\": 59.18,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"minimax/minimax-m3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 11101.9,\n \"p95LatencyMs\": 26087.1,\n \"outputTokensPerSecond\": 101.12,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"moonshot/kimi-k3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 24498.9,\n \"p95LatencyMs\": 40365.3,\n \"outputTokensPerSecond\": 25.11,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"nvidia/mistral-nemotron\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7349.6,\n \"p95LatencyMs\": 9932.3,\n \"outputTokensPerSecond\": 79.48,\n \"errorRate\": 0.3333,\n \"samples\": 3\n },\n \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 9324.6,\n \"p95LatencyMs\": 12992,\n \"outputTokensPerSecond\": 64.96,\n \"errorRate\": 0.3333,\n \"samples\": 3\n },\n \"nvidia/nemotron-nano-12b-v2-vl\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5846.9,\n \"p95LatencyMs\": 5846.9,\n \"outputTokensPerSecond\": 87.57,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"nvidia/nemotron-nano-9b-v2\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5282.5,\n \"p95LatencyMs\": 5282.5,\n \"outputTokensPerSecond\": 96.92,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"nvidia/step-3.7-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4617.4,\n \"p95LatencyMs\": 5237.4,\n \"outputTokensPerSecond\": 112.92,\n \"errorRate\": 0.3333,\n \"samples\": 3\n },\n \"openai/chat-latest\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3690.9,\n \"p95LatencyMs\": 4344,\n \"outputTokensPerSecond\": 111.85,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4.1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3527.9,\n \"p95LatencyMs\": 3831.7,\n \"outputTokensPerSecond\": 141.27,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4.1-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4268.2,\n \"p95LatencyMs\": 5101.5,\n \"outputTokensPerSecond\": 103.42,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4.1-nano\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3088.3,\n \"p95LatencyMs\": 3369.2,\n \"outputTokensPerSecond\": 150.31,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4o\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 2995.2,\n \"p95LatencyMs\": 3174.2,\n \"outputTokensPerSecond\": 171.32,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4o-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4751.5,\n \"p95LatencyMs\": 4930.4,\n \"outputTokensPerSecond\": 107.84,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4558.1,\n \"p95LatencyMs\": 5081.9,\n \"outputTokensPerSecond\": 113.25,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.2\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5436.6,\n \"p95LatencyMs\": 5928.8,\n \"outputTokensPerSecond\": 95.47,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.3-codex\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 15290.4,\n \"p95LatencyMs\": 15290.4,\n \"outputTokensPerSecond\": 33.49,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"openai/gpt-5.4\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5596,\n \"p95LatencyMs\": 5919.4,\n \"outputTokensPerSecond\": 91.67,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.4-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3377.8,\n \"p95LatencyMs\": 3646.8,\n \"outputTokensPerSecond\": 138.08,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.4-nano\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4040.4,\n \"p95LatencyMs\": 4205.9,\n \"outputTokensPerSecond\": 118.52,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6367.8,\n \"p95LatencyMs\": 7330.7,\n \"outputTokensPerSecond\": 81.29,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-luna\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6064.5,\n \"p95LatencyMs\": 7347.3,\n \"outputTokensPerSecond\": 87.93,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-luna-pro\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 13914.9,\n \"p95LatencyMs\": 13914.9,\n \"outputTokensPerSecond\": 36.79,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"openai/gpt-5.6-sol\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7720.2,\n \"p95LatencyMs\": 9108.2,\n \"outputTokensPerSecond\": 67.47,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-sol-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 11442.7,\n \"p95LatencyMs\": 13363.1,\n \"outputTokensPerSecond\": 148.75,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-terra\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4941,\n \"p95LatencyMs\": 5095.3,\n \"outputTokensPerSecond\": 103.69,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-terra-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3574.1,\n \"p95LatencyMs\": 4126.3,\n \"outputTokensPerSecond\": 133.59,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4324.9,\n \"p95LatencyMs\": 5838.1,\n \"outputTokensPerSecond\": 125.86,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5463.4,\n \"p95LatencyMs\": 5613.1,\n \"outputTokensPerSecond\": 93.8,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o3-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 2912.7,\n \"p95LatencyMs\": 3092.1,\n \"outputTokensPerSecond\": 176.49,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o4-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4958.7,\n \"p95LatencyMs\": 5313,\n \"outputTokensPerSecond\": 103.81,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"qwen/qwen3.7-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3385.5,\n \"p95LatencyMs\": 4042.7,\n \"outputTokensPerSecond\": 153.94,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"qwen/qwen3.7-max\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9387.1,\n \"p95LatencyMs\": 10490.2,\n \"outputTokensPerSecond\": 54.92,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"qwen/qwen3.7-plus\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9766.6,\n \"p95LatencyMs\": 9798.2,\n \"outputTokensPerSecond\": 52.42,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"tencent/hy3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6062.3,\n \"p95LatencyMs\": 7070.2,\n \"outputTokensPerSecond\": 87.3,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xai/grok-4.3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9467.7,\n \"p95LatencyMs\": 10087.9,\n \"outputTokensPerSecond\": 48.36,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xai/grok-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 13564.8,\n \"p95LatencyMs\": 17351.9,\n \"outputTokensPerSecond\": 60.71,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xai/grok-build-0.1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 16394.8,\n \"p95LatencyMs\": 18035.4,\n \"outputTokensPerSecond\": 96.86,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xiaomi/mimo-v2.5-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 12070.7,\n \"p95LatencyMs\": 12386.8,\n \"outputTokensPerSecond\": 42.44,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6839.7,\n \"p95LatencyMs\": 7261.4,\n \"outputTokensPerSecond\": 75.16,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5-turbo\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 55348.5,\n \"p95LatencyMs\": 114086.6,\n \"outputTokensPerSecond\": 14.64,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 15658.4,\n \"p95LatencyMs\": 17307.1,\n \"outputTokensPerSecond\": 32.9,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.2\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 10308.5,\n \"p95LatencyMs\": 15127.6,\n \"outputTokensPerSecond\": 54.87,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7272.4,\n \"p95LatencyMs\": 7998.1,\n \"outputTokensPerSecond\": 71.09,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.3-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 10545.3,\n \"p95LatencyMs\": 11672.4,\n \"outputTokensPerSecond\": 49.01,\n \"errorRate\": 0,\n \"samples\": 3\n }\n}\n","/**\n * Model-performance priors consumed by the portfolio router.\n *\n * The entries below are a small, auditable seed extracted from the 2026-03-16\n * BlockRun performance run. They are deliberately weak priors: live data\n * injected by the host should replace them through configuration before a\n * release. Historical numbers must never be presented as a current\n * provider SLA or as task-quality measurements.\n */\n\nimport liveProfiles from \"./model-profiles.generated.json\";\n\nexport type ModelPerformanceProfile = {\n measuredAt: string;\n /** Gateway end-to-end latency for the benchmark workload. */\n latencyMs: number;\n /** Tail latency is more relevant than mean latency for urgent requests. */\n p95LatencyMs?: number;\n outputTokensPerSecond: number;\n /** External intelligence index when one was available; not task success. */\n intelligenceIndex?: number;\n /** Failure fraction observed in the same benchmark run. */\n errorRate?: number;\n /** Number of sampled calls behind the observation. */\n samples?: number;\n};\n\n// Generated from benchmark files that satisfy the uncached-inference\n// invariant. These are weak performance priors (speed/reliability), never\n// task-quality labels.\nexport const LIVE_MODEL_PROFILES: Readonly> = Object.freeze(\n liveProfiles as Record,\n);\n\nexport const HISTORICAL_MODEL_PROFILES: Readonly> =\n Object.freeze({\n \"anthropic/claude-haiku-4.5\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 2305,\n outputTokensPerSecond: 140.6,\n },\n \"anthropic/claude-sonnet-4.6\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 2110,\n outputTokensPerSecond: 121.3,\n },\n \"deepseek/deepseek-chat\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1431,\n outputTokensPerSecond: 179.2,\n intelligenceIndex: 32,\n },\n \"google/gemini-2.5-flash\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1238,\n outputTokensPerSecond: 207.6,\n intelligenceIndex: 20,\n },\n \"google/gemini-2.5-flash-lite\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1353,\n outputTokensPerSecond: 192.5,\n intelligenceIndex: 20,\n },\n \"google/gemini-2.5-pro\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1294,\n outputTokensPerSecond: 197.8,\n },\n \"google/gemini-3.1-pro\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1609,\n outputTokensPerSecond: 167.2,\n },\n \"openai/gpt-4o-mini\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 2764,\n outputTokensPerSecond: 92.8,\n },\n \"openai/gpt-5.3-codex\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 7935,\n outputTokensPerSecond: 32.3,\n },\n });\n","/**\n * Whether the request actually requires an external action/tool, as distinct\n * from merely being sent by a host that exposes tools on every turn.\n *\n * The detector intentionally looks for action+target pairs. A generic factual\n * or multiple-choice question must stay false even when the host attaches a\n * large tool schema; otherwise every tool-enabled host turn is over-routed as\n * an agent task and models may browse or mutate state unnecessarily.\n */\nexport function inferToolRequirement(\n prompt: string,\n _systemPrompt?: string,\n toolChoice?: unknown,\n): boolean {\n // OpenAI-compatible clients can state this requirement directly. Treat that\n // protocol signal as authoritative instead of trying to infer it from prose.\n if (toolChoice === \"none\") return false;\n if (toolChoice === \"required\") return true;\n if (\n typeof toolChoice === \"object\" &&\n toolChoice !== null &&\n (toolChoice as { type?: unknown }).type === \"function\"\n ) {\n return true;\n }\n\n // System prompts commonly describe every tool a host exposes. They are not\n // evidence that the user asked to perform an action on this turn. Explicit\n // host requirements should use tool_choice/requiresTools instead.\n const text = prompt;\n const explicitTool =\n /\\b(?:use|call|invoke)\\s+(?:the\\s+)?[\\w.-]+\\s+(?:tool|function|api)\\b|\\btool[_ -]?call\\b|使用.{0,20}(?:工具|函数|接口)|调用.{0,20}(?:工具|函数|接口)/i;\n const codeEnvironment =\n /\\b(?:run|execute)\\s+(?:the\\s+)?(?:tests?|command|script|build|linter)|\\b(?:edit|modify|patch|create|write|save|delete|rename|move|inspect|read)\\b.{0,60}\\b(?:file|repository|repo|codebase|directory|folder)\\b|\\b(?:terminal|shell|bash|zsh|pytest|npm test|pnpm test|git\\s+(?:status|diff|commit)|docker)\\b|(?:运行|执行).{0,20}(?:测试|命令|脚本|构建)|(?:修改|编辑|修复|创建|读取|检查|保存).{0,30}(?:文件|仓库|代码库|目录)/i;\n const webAction =\n /\\b(?:browse|search|look up|fetch|open)\\b.{0,80}\\b(?:web|website|url|online|documentation|docs|news|weather|price)\\b|(?:浏览|搜索|查询|打开).{0,30}(?:网页|网站|链接|文档|新闻|天气|价格)/i;\n const statefulAction =\n /\\b(?:refund|cancel|book|reserve|purchase|buy|return|exchange|transfer|update|change)\\b.{0,80}\\b(?:order|booking|reservation|account|address|payment|subscription|ticket|flight|item)\\b|(?:退款|取消|预订|购买|退货|换货|转账|更新|修改).{0,30}(?:订单|预订|账户|地址|付款|订阅|票|航班|商品)/i;\n return (\n explicitTool.test(text) ||\n codeEnvironment.test(text) ||\n webAction.test(text) ||\n statefulAction.test(text)\n );\n}\n","/**\n * V3 portfolio router.\n *\n * This is deliberately local and deterministic: feature extraction, eligibility\n * checks and scoring read only request data plus the in-process model registry.\n * It is therefore safe for the hot path and provides a stable baseline for the\n * RouterBench evaluation before health telemetry / an optional judge are added.\n */\n\nimport { DEFAULT_MODEL_CAPABILITIES } from \"./model-capabilities.js\";\nimport { getFallbackChain, selectModel } from \"./selector.js\";\nimport { RulesStrategy } from \"./strategy.js\";\nimport {\n HISTORICAL_MODEL_PROFILES,\n LIVE_MODEL_PROFILES,\n type ModelPerformanceProfile,\n} from \"./model-profiles.js\";\nimport type { RouterOptions, RouterStrategy, TaskType, Tier, TierConfig } from \"./types.js\";\nimport { inferToolRequirement } from \"./tool-intent.js\";\n\ntype TaskFeatures = {\n taskType: TaskType;\n estimatedInputTokens: number;\n hasCode: boolean;\n needsTools: boolean;\n toolsAvailable: boolean;\n needsVision: boolean;\n needsStructuredOutput: boolean;\n latencySensitive: boolean;\n highStakes: boolean;\n language: \"zh\" | \"other\";\n likelyParallelToolCalls: boolean;\n complexMultiToolPlan: boolean;\n agentDomain: \"airline\" | \"retail\" | \"web_research\" | \"other\";\n deepWebResearch: boolean;\n agentRisk: \"standard\" | \"high\" | \"complex_high\" | \"policy_exception_simple\" | \"policy_exception\";\n terminalToolSignal: boolean;\n terminalSafetySensitive: boolean;\n implicitTerminalCode: boolean;\n};\n\nconst DEFAULT_PORTFOLIO_WEIGHTS = {\n auto: {\n quality: 0.47,\n capability: 0.2,\n cost: 0.18,\n speed: 0.07,\n reliability: 0.03,\n legacy: 0.05,\n },\n eco: { quality: 0.36, capability: 0.2, cost: 0.28, speed: 0.1, reliability: 0.04, legacy: 0.02 },\n premium: {\n quality: 0.58,\n capability: 0.2,\n cost: 0.08,\n speed: 0.06,\n reliability: 0.06,\n legacy: 0.02,\n },\n highStakesBoost: { quality: 0.08, reliability: 0.05 },\n latencySensitiveSpeedBoost: 0.08,\n affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 },\n} as const;\n\n/**\n * Detect turns that probably need several tool calls. This is a\n * deliberately conservative request-side feature: it uses only the prompt\n * and visible tool count, never benchmark categories or expected answers.\n */\nfunction likelyNeedsParallelToolCalls(\n prompt: string,\n needsTools: boolean,\n toolCount: number | undefined,\n toolNames: readonly string[] | undefined,\n): boolean {\n if (!needsTools || toolCount === undefined || toolCount < 1) return false;\n const text = prompt.trim();\n const explicitRepeat =\n /\\b(?:in parallel|simultaneously|concurrently|for each|each of|every one|both|(?:two|three|multiple|several)\\s+(?:cities|locations|items|tasks|orders|users|files))\\b|并行|同时|分别|每个|各自|(?:两个|三个|多个)(?:城市|地点|项目|任务|订单|用户|文件)|cada uno|para cada|simult[aá]neamente/i.test(\n text,\n );\n if (explicitRepeat) return true;\n\n const sentenceClauses = text\n .split(/[.!?。!?]+/)\n .map((part) => part.trim())\n .filter((part) => part.length >= 8);\n if (\n (/\\b(?:also|additionally|furthermore)\\b|另外|此外|그리고/i.test(text) &&\n sentenceClauses.length >= 2) ||\n /\\band\\s+(?:also|for the)\\b/i.test(text)\n )\n return true;\n\n const pairedQuantity =\n /\\b\\d+(?:\\.\\d+)?\\s+(?:and|or)\\s+\\d+(?:\\.\\d+)?\\s*(?:gb|mb|tb|kg|g|ml|oz|cups?|cores?|cpus?)\\b/i.test(\n text,\n );\n if (pairedQuantity) return true;\n\n // Distinctive tokens from two visible tool names are a strong local signal\n // for a multi-operation turn (for example add_task + delete_task).\n const operationTokens = new Set([\n \"add\",\n \"delete\",\n \"remove\",\n \"cancel\",\n \"return\",\n \"exchange\",\n \"modify\",\n \"book\",\n \"transfer\",\n \"send\",\n \"upload\",\n \"download\",\n \"create\",\n \"close\",\n ]);\n const lowered = text.toLowerCase();\n const matchedOperationTokens = new Set(\n (toolNames ?? [])\n .flatMap((name) => name.toLowerCase().split(/[^a-z0-9\\u3400-\\u9fff]+/))\n .filter((token) => operationTokens.has(token) && lowered.includes(token)),\n );\n // A single workflow naturally mentions domain nouns like order/item plus\n // one action. Upgrade only when two different visible operation verbs are\n // requested (for example cancel + book or add + delete).\n if (matchedOperationTokens.size >= 2) return true;\n\n // Repeated food/logging entries are commonly expressed as several lines,\n // each with its own quantity rather than an explicit \"for each\" phrase.\n const nonEmptyLines = text\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n const quantityMentions =\n text.match(\n /\\b(?:\\d+(?:\\.\\d+)?|one|two|three|four|five|six|seven|eight|nine|ten)\\s*(?:oz|ounce|ounces|g|gram|grams|kg|ml|cups?|pieces?|tablespoons?)\\b/gi,\n ) ?? [];\n if (nonEmptyLines.length >= 2 && quantityMentions.length >= 2) return true;\n\n // Weather prompts provide a useful language-independent high-confidence\n // pattern: a single lookup tool plus multiple locations joined in one turn.\n const repeatedLookup =\n /\\b(?:weather|climate|clima|tiempo|temperature|snow|news|report)\\b|天气|气象|温度|降雪|新闻|报告/i.test(\n text,\n );\n const multiLocationConnector = /\\b(?:and also|both|y|e)\\b|还有|以及|和|、/i.test(text);\n const commaSeparatedLocations = (text.match(/[,,]/g) ?? []).length >= 2;\n if (repeatedLookup && (multiLocationConnector || commaSeparatedLocations)) return true;\n\n const distinctOrderParts =\n /\\b(?:food|meal)\\b[\\s\\S]*\\bdrink\\b|\\bdrink\\b[\\s\\S]*\\b(?:food|meal)\\b/i.test(text);\n const koreanParallelClauses = (text.match(/,/g) ?? []).length >= 3 && /하고|그리고/.test(text);\n return distinctOrderParts || koreanParallelClauses;\n}\n\nfunction classifyTask(\n prompt: string,\n systemPrompt: string | undefined,\n options: RouterOptions,\n): TaskFeatures {\n const fullText = `${systemPrompt ?? \"\"} ${prompt}`;\n const estimatedInputTokens = Math.ceil(fullText.length / 4);\n // Feature regexes need request shape and intent, not the entire document.\n // Sample both ends so a long pasted artifact keeps the task instruction at\n // either boundary, while the full length still drives capacity decisions.\n const scanLimit = Math.max(1, Math.min(8_000, options.config.classifier.promptTruncationChars));\n const sample = (value: string): string => {\n if (value.length <= scanLimit) return value;\n const prefixLength = Math.ceil(scanLimit / 2);\n return `${value.slice(0, prefixLength)}\\n${value.slice(-(scanLimit - prefixLength))}`;\n };\n const scannedPrompt = sample(prompt);\n const scannedSystemPrompt = sample(systemPrompt ?? \"\");\n const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;\n const text = scannedPrompt.toLowerCase();\n const explicitCodeSignal =\n /```|\\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\\b|\\.(?:ts|tsx|js|py|go|rs)\\b/i.test(\n scannedPrompt,\n );\n // `class` is common in non-code Agent domains (for example airline cabin\n // class). Treat code constructs as code only when the prompt also contains\n // an implementation/editing cue, instead of letting a single ambiguous\n // noun redirect an entire tool session to the code-agent portfolio.\n const codeConstructSignal =\n /\\b(?:implement|refactor|debug|write|edit|modify|create|define|review|fix)\\b[\\s\\S]{0,48}\\b(?:api|function|class|method)\\b|\\b(?:api|function|class|method)\\b[\\s\\S]{0,48}\\b(?:code|implementation|typescript|javascript|python|rust|java)\\b/i.test(\n scannedPrompt,\n );\n const nativeCodeSignal =\n /\\b(?:programmed|written|implemented?|code)\\s+(?:in|using)\\s+(?:c\\+\\+|c|rust|go)\\b/i.test(\n scannedPrompt,\n );\n const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal;\n const toolsAvailable = options.hasTools ?? false;\n const needsTools =\n options.requiresTools ??\n (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));\n const likelyParallelToolCalls = likelyNeedsParallelToolCalls(\n scannedPrompt,\n needsTools,\n options.toolCount,\n options.toolNames,\n );\n const normalizedToolNames = (options.toolNames ?? []).map((name) => name.toLowerCase());\n const airlineToolSignal = normalizedToolNames.some((name) =>\n /(?:flight|reservation|airport|baggage|passenger)/.test(name),\n );\n const retailToolSignal = normalizedToolNames.some((name) =>\n /(?:order|product|item|return|exchange|address)/.test(name),\n );\n const webResearchToolSignal = normalizedToolNames.some((name) =>\n /^(?:web_?search|web_?fetch)$/.test(name),\n );\n const agentDomain =\n airlineToolSignal && !retailToolSignal\n ? \"airline\"\n : retailToolSignal && !airlineToolSignal\n ? \"retail\"\n : webResearchToolSignal\n ? \"web_research\"\n : \"other\";\n // Distinguish a cheap lookup from a BrowseComp-like investigation. These\n // prompts require joining several clues, resolving an entity, and ending in\n // one exact answer; complete agent trajectories show that treating them as\n // ordinary search causes long, costly loops. This is request/tool-surface\n // evidence only and does not depend on a benchmark id or hidden answer.\n const clueConnectors =\n scannedFullText.match(\n /\\b(?:after|before|while|where|whose|which|in \\d{4}|as of|over \\d+|another|also|furthermore)\\b|(?:之后|之前|其中|截至|超过|另一个|此外)/gi,\n ) ?? [];\n const entityResolutionSignal =\n /\\b(?:identify|who (?:is|was)|what (?:is|was) the name|which (?:person|player|company|country|city)|find the (?:person|player|name|entity))\\b|(?:找出|识别|是谁|哪位|名称是什么)/i.test(\n scannedFullText,\n );\n const exactAnswerSignal =\n /\\b(?:exact answer|single best-supported answer|following clues|multiple public sources)\\b|(?:精确答案|根据.*线索|多个公开来源)/i.test(\n scannedFullText,\n );\n const deepWebResearch =\n agentDomain === \"web_research\" &&\n (exactAnswerSignal ||\n (entityResolutionSignal && (clueConnectors.length >= 3 || prompt.length >= 320)));\n const globalOptimizationSignal =\n /\\b(?:cheapest|lowest[- ]price|least expensive|most expensive|highest(?:[- ]priced)?|largest|smallest|maximum|minimum|best available|closest|not (?:cost|exceed))\\b|最便宜|最低价|最贵|最高价|最大|最小/i.test(\n scannedPrompt,\n );\n const globalScopeSignal =\n /\\b(?:everything|all (?:(?:my|your|their|the) )?(?:future |upcoming )?(?:items|orders|passengers|flights|reservations|bookings)|every (?:item|order|passenger|flight|reservation|booking))\\b|全部|所有|每个/i.test(\n scannedPrompt,\n );\n const globalChoiceSignal = globalOptimizationSignal || globalScopeSignal;\n const crossRecordSignal =\n /\\b(?:another|other|different|previous)\\s+(?:order|reservation|booking|account|address)\\b|另一(?:个)?(?:订单|预订|账户|地址)|其他(?:订单|预订|账户|地址)/i.test(\n scannedPrompt,\n );\n const reservationIds = scannedPrompt.match(/\\b[A-Z0-9]{6}\\b/g) ?? [];\n const crossReservationBatchSignal =\n agentDomain === \"airline\" &&\n (/\\b(?:two|three|multiple|several)(?:\\s+of\\s+(?:my|our|the))?\\s+(?:upcoming\\s+)?(?:reservations?|bookings?)\\b|\\b(?:a\\s+)?(?:second|third)\\s+(?:reservation|booking)\\b/i.test(\n scannedPrompt,\n ) ||\n new Set(reservationIds).size >= 2);\n const conditionalGlobalWorkflowSignal =\n agentDomain === \"airline\" &&\n globalScopeSignal &&\n /\\b(?:if|that (?:contain|have)|longer than|shorter than|under|over|at (?:most|least)|wherever possible)\\b|如果|超过|少于|不超过|尽可能/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:cancel|change|upgrade|move|book)\\b[\\s\\S]*\\b(?:cancel|change|upgrade|move|book)\\b|取消[\\s\\S]*(?:升级|更改)|升级[\\s\\S]*(?:取消|更改)/i.test(\n scannedPrompt,\n );\n // A refund explicitly targeted at a named/non-original card can conflict\n // with account state and require escalation rather than a substitute action.\n // This narrow feature is visible on the first turn and avoids sending every\n // ordinary return workflow to the expensive policy specialist.\n const policyExceptionSignal =\n agentDomain === \"retail\" &&\n /\\b(?:return|refund|send back|get (?:my |the )?money back)\\b|退货|退款|退回/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:amex|american express|visa|mastercard|credit card|debit card|different card|another card|other card)\\b|信用卡|借记卡|其他卡|另一张卡/i.test(\n scannedPrompt,\n );\n // A comparative selector can mention two products while requesting only\n // one write (for example \"send back the pricier one\"). Three-repeat tau2\n // calibration found no quality gain from the policy specialist on these\n // single-write cases, so keep them in a distinct, lower-cost risk band.\n const singleSelectedPolicyException =\n policyExceptionSignal &&\n /\\b(?:return|refund|send back)\\b[^.!?。!?]{0,96}\\b(?:the )?(?:pricier|cheaper|more expensive|less expensive|costlier|one)\\b/i.test(\n scannedPrompt,\n );\n // Returns and exchanges often pivot after confirmation (return -> rethink\n // -> exchange -> choose a variant). That future state is not visible to a\n // task-start router, so treat the observable workflow verb as the risk cue.\n // Simpler cancellation and one-field order edits stay on the standard path.\n const negotiatedWorkflowSignal =\n agentDomain === \"retail\" && /\\b(?:return|exchange)\\b|退货|退回|换货|交换/i.test(scannedPrompt);\n const numberedSteps = (scannedPrompt.match(/(?:^|\\s)\\d+(?:\\.\\d+)*[.)]\\s+/g) ?? []).length;\n const complexMultiToolPlan =\n likelyParallelToolCalls &&\n ((options.toolCount ?? 0) >= 6 || numberedSteps >= 3 || prompt.length > 1_200);\n let agentRisk: TaskFeatures[\"agentRisk\"] =\n needsTools && singleSelectedPolicyException\n ? \"policy_exception_simple\"\n : needsTools && policyExceptionSignal\n ? \"policy_exception\"\n : // Airline prompts that require a global optimum (for example the\n // cheapest itinerary across several candidates) are materially harder\n // than applying one change to every passenger in a known reservation.\n // Full-session evidence supports Sonnet for the former, while upgrading\n // the latter merely because it says \"all passengers\" caused a large cost\n // increase without a quality gain.\n needsTools &&\n agentDomain === \"airline\" &&\n (globalOptimizationSignal || conditionalGlobalWorkflowSignal)\n ? \"complex_high\"\n : needsTools &&\n (likelyParallelToolCalls ||\n globalChoiceSignal ||\n crossRecordSignal ||\n crossReservationBatchSignal ||\n negotiatedWorkflowSignal)\n ? \"high\"\n : \"standard\";\n const needsVision = options.hasVision ?? false;\n const needsStructuredOutput = options.requiresStructuredOutput ?? false;\n const latencySensitive =\n /\\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\\b|尽快|马上|快速|低延迟/i.test(\n scannedFullText,\n );\n const highStakes =\n /\\b(?:production|security|payment|legal|medical|financial|audit)\\b|生产|安全|支付|法律|医疗|财务|审计/i.test(\n scannedFullText,\n );\n // Terminal tasks often describe the desired artifact rather than naming a\n // programming language. Treat only small, deterministic local build/file\n // work as implicit code. Operational deployment, credentials, destructive\n // work, evaluation, vision, and broad search stay on the stronger generic\n // tool-agent path. This is a request-side feature, not a benchmark ID list.\n const terminalToolSignal = normalizedToolNames.some((name) =>\n /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name),\n );\n const simpleTerminalArtifact =\n /\\b(?:create|write|convert|generate|build|implement|run|fix|repair|debug|make)\\b[\\s\\S]{0,120}\\b(?:file|script|csv|parquet|json|txt|server|endpoint)\\b/i.test(\n scannedPrompt,\n );\n // Multi-file repair is qualitatively different from fixing one known local\n // script. The agent must preserve state across inspections, infer ordering\n // and dependencies, edit several artifacts, and close the loop with tests.\n // A frozen Terminal-Bench trajectory showed the economy model spending 27\n // turns repeatedly rereading files without making an edit, while Opus solved\n // the same task in eight turns. Promote this request-visible pattern before\n // model scoring; no benchmark ID or expected answer is consulted.\n const terminalComplexRepair =\n terminalToolSignal &&\n /\\b(?:multiple|several)\\s+(?:scripts?|files?|components?)\\b|\\b(?:pipeline|dependencies)\\b[\\s\\S]{0,100}\\b(?:fail|issue|fix|repair|run|execute)\\b|\\b(?:identify|find|fix|repair)\\s+(?:and\\s+)?(?:fix\\s+)?all\\s+(?:the\\s+)?issues\\b/i.test(\n scannedPrompt,\n );\n // One artifact that must be accepted by multiple compilers/runtimes is not\n // a routine file-writing task. It requires reasoning across incompatible\n // grammars and validating every execution path; cheap code models can\n // produce plausible-looking source that satisfies neither toolchain.\n const mentionedTerminalRuntimes = new Set(\n (scannedPrompt.match(/\\b(?:gcc|clang|rustc|javac|go\\s+build|node|python)\\b/gi) ?? []).map(\n (name) => name.toLowerCase().replace(/\\s+/g, \" \"),\n ),\n );\n const terminalCrossRuntimeArtifact =\n terminalToolSignal &&\n (/\\bpolyglot\\b/i.test(scannedPrompt) ||\n /\\b(?:both|each)\\b[\\s\\S]{0,120}\\b(?:compilers?|runtimes?|toolchains?)\\b/i.test(\n scannedPrompt,\n ) ||\n (mentionedTerminalRuntimes.size >= 2 &&\n /\\b(?:compile|build|run|execute)\\b/i.test(scannedPrompt)));\n // Framework-to-native ports combine binary checkpoint inspection, weight\n // export, tensor-layout reasoning, image/data decoding, and a separately\n // compiled runtime. A task-start router can see this boundary directly in\n // the request (for example PyTorch state_dict -> a pure C CLI); treating it\n // like routine single-file C work caused a 30-turn read/retry loop in a\n // frozen official Terminal-Bench trajectory.\n const terminalFrameworkToNativeArtifact =\n terminalToolSignal &&\n /\\b(?:pytorch|tensorflow|jax|onnx|state[_ -]?dict|checkpoint|safetensors?)\\b|\\.(?:pth|pt|onnx)\\b/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:pure|native|programmed|written|implemented?)\\s+(?:in|using)\\s+(?:c\\+\\+|c|rust|go)\\b|\\b(?:c\\+\\+|c|rust|go)\\s+(?:program|binary|executable|cli|tool|implementation)\\b/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:inference|model|weights?|tensor|export|convert|load)\\b/i.test(scannedPrompt);\n if (\n needsTools &&\n (terminalComplexRepair || terminalCrossRuntimeArtifact || terminalFrameworkToNativeArtifact) &&\n (agentRisk === \"standard\" || agentRisk === \"high\")\n )\n agentRisk = \"complex_high\";\n const complexTerminalOperation =\n /\\b(?:git|ssh|nginx|https|certificate|authentication|credential|deploy|production|encrypt|gpg|shred|securely delete|decommission|benchmark|evaluate|embedding|chess|image|search the web|schema|statistical|statistics|aggregate|join|multiple inputs?)\\b/i.test(\n scannedPrompt,\n );\n // A bare \"token\" is not a credential signal: blockchain, tokenizer, and\n // LLM tasks use that word routinely (for example \"token transfers\"). Only\n // treat it as sensitive when the prompt gives it an authentication/secret\n // qualifier. API keys remain an unambiguous high-risk signal on their own.\n const terminalCredentialSignal =\n /\\b(?:ssh|nginx|certificate|authentication|credentials?|passwords?|api keys?|deploy|production|encrypt|gpg|shred|securely delete|decommission)\\b/i.test(\n scannedPrompt,\n ) ||\n /\\b(?:access|auth|authentication|bearer|secret|api)\\s+tokens?\\b|\\btokens?\\s+(?:secret|credential|authentication)\\b/i.test(\n scannedPrompt,\n );\n const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);\n const implicitTerminalCode =\n needsTools &&\n terminalToolSignal &&\n agentRisk === \"standard\" &&\n !highStakes &&\n !complexTerminalOperation &&\n numberedSteps < 3 &&\n prompt.length <= 1_000 &&\n simpleTerminalArtifact;\n const language = /[\\u3400-\\u9fff]/.test(scannedFullText) ? \"zh\" : \"other\";\n const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\\n)\\s*[A-D][.)]\\s+/gim) ?? []).length;\n const numericSignals = (scannedPrompt.match(/-?\\d+(?:[.,]\\d+)?/g) ?? []).length;\n const compactMathProblem =\n !hasCode &&\n prompt.length < 2_500 &&\n numericSignals >= 2 &&\n (/[+×÷=%$€£¥]|\\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\\b/i.test(\n scannedPrompt,\n ) ||\n /[??]\\s*$/.test(scannedPrompt.trim()) ||\n numericSignals >= 3);\n\n let taskType: TaskType = \"chat\";\n if (needsVision) taskType = \"vision\";\n else if (estimatedInputTokens > 80_000) taskType = \"long_context\";\n else if (needsTools && (hasCode || implicitTerminalCode)) taskType = \"code_agent\";\n else if (needsTools && likelyParallelToolCalls && !complexMultiToolPlan)\n taskType = \"tool_agent_parallel\";\n else if (needsTools) taskType = \"tool_agent\";\n else if (multipleChoiceSignals >= 3) taskType = \"reasoning_mcq\";\n else if (compactMathProblem) taskType = \"reasoning_math\";\n else if (\n /\\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\\b/i.test(text)\n )\n taskType = \"debug\";\n else if (hasCode || /\\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\\b/i.test(text))\n taskType = \"code_edit\";\n else if (needsStructuredOutput || /\\b(?:extract|json|schema|csv|字段|提取)\\b/i.test(text))\n taskType = \"extraction\";\n else if (\n /\\b(?:prove|derive|theorem|formal|mathematical|reasoning|证明|推导|定理|数学)\\b/i.test(text)\n )\n taskType = \"reasoning\";\n\n return {\n taskType,\n estimatedInputTokens,\n hasCode,\n needsTools,\n toolsAvailable,\n needsVision,\n needsStructuredOutput,\n latencySensitive,\n highStakes,\n language,\n likelyParallelToolCalls,\n complexMultiToolPlan,\n agentDomain,\n deepWebResearch,\n agentRisk,\n terminalToolSignal,\n terminalSafetySensitive,\n implicitTerminalCode,\n };\n}\n\nfunction affinity(\n modelId: string,\n task: TaskType,\n language: TaskFeatures[\"language\"] = \"other\",\n agentDomain: TaskFeatures[\"agentDomain\"] = \"other\",\n deepWebResearch = false,\n agentRisk: TaskFeatures[\"agentRisk\"] = \"standard\",\n terminalToolSignal = false,\n terminalSafetySensitive = false,\n): number {\n const id = modelId.toLowerCase();\n // Model family names are intentionally similar (for example\n // `gemini-2.5-flash` vs `gemini-2.5-flash-lite`). A substring match lets a\n // smaller sibling inherit a capability claim that was measured only for the\n // flagship. Keep these assignments model-exact; a sibling can be added only\n // with its own evidence.\n const modelName = id.slice(id.indexOf(\"/\") + 1);\n const match = (values: string[], score: number) =>\n values.some((value) => modelName === value) ? score : 0;\n const base = 0.68;\n\n switch (task) {\n case \"code_agent\":\n if (terminalToolSignal && agentRisk === \"complex_high\") {\n // Strong native tool loop until the Responses function-output fix is\n // deployed on both gateways; keep Codex available below the floor.\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5.3-codex\"], 0.87),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n );\n }\n // Seven valid full agent + official Terminal-Bench trajectories\n // (2026-07-28) gave GPT-5 Mini 4/7 resolved tasks versus 1/7 for the\n // prior dynamic code-agent choice. Its token-normalized total cost was\n // higher in this small calibration, so keep Codex and Sonnet's quality\n // priors above it; admitting Mini to the scoring band lets the normal\n // quality/cost profile choose it without erasing stronger fallbacks.\n // DeepSeek V4 Pro is kept below the primary band after two consecutive\n // mid-trajectory provider timeouts contaminated its calibration runs.\n return Math.max(\n base,\n match([\"gpt-5.3-codex\"], 1),\n match([\"claude-sonnet-5\"], 0.98),\n match([\"gpt-5-mini\"], 0.96),\n match([\"gemini-3.5-flash\"], 0.92),\n match([\"kimi-k3\"], 0.9),\n match([\"deepseek-v4-pro\", \"glm-5.2\"], 0.88),\n );\n case \"tool_agent\":\n if (terminalToolSignal && agentRisk === \"complex_high\") {\n // Keep the Responses-API Codex path outside auto's affinity floor\n // until the gateway fix that preserves function_call_output is live\n // on both chains. Sonnet has a verified native multi-turn tool loop\n // and is the safe strong default for this band today.\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5.3-codex\"], 0.87),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n );\n }\n if (terminalToolSignal && !terminalSafetySensitive) {\n // Seven official Terminal-Bench calibration trajectories favoured\n // GPT-5 Mini over the prior dynamic choice. Admit Codex/Sonnet as\n // close fallbacks, but let actual request cost break the tie.\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-5.3-codex\"], 0.98),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"gemini-3.5-flash\"], 0.89),\n );\n }\n if (terminalToolSignal && terminalSafetySensitive) {\n // Two complete agent observations on the public\n // Terminal-Bench new-encrypt-command task ended in Codex repeating\n // the same TerminalExec input until the loop guard fired. Keep Codex\n // as an availability fallback, but below the safety-band affinity\n // floor until its Responses function-output path is verified on both\n // gateways. This does not change explicit code-agent routing.\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"claude-opus-4.8\"], 0.9),\n match([\"gpt-5.3-codex\"], 0.84),\n );\n }\n if (agentDomain === \"web_research\") {\n // Complete-session BrowseComp calibration supersedes the earlier\n // single-case Opus promotion: strict deduplicated evidence has Sonnet\n // 5 at 2/9 versus Opus 5 at 0/3, while Opus also costs more and has a\n // much longer tail. Keep Opus as an availability fallback until a\n // larger stable-provider sample supports promotion.\n return deepWebResearch\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.84),\n match([\"claude-opus-5\"], 0.8),\n match([\"claude-opus-4.8\"], 0.78),\n )\n : Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.86),\n match([\"claude-opus-5\"], 0.84),\n match([\"claude-opus-4.8\"], 0.82),\n );\n }\n // Full-trajectory tau2 calibration (2026-07-28, official gpt-4.1\n // simulator): Sonnet 5 completed both an airline policy task and a\n // retail multi-write task with reward 1.0. Gemini 3.5 Flash emitted\n // function calls as plain text after the first structured calls and\n // looped to the 100-step ceiling on the airline task. Keep only the\n // trajectory-validated primary inside the scoring band; the remaining\n // eligible models are retained below as availability fallbacks.\n if (agentDomain === \"retail\") {\n // Full-session calibration: GPT-5 Mini completed two local/single\n // retail workflows at a fraction of Sonnet's token cost. It remains\n // ineligible for promotion when the prompt asks for multiple actions,\n // cross-record discovery, or a global optimum; those trajectories\n // exposed unstable write arguments in prior calibration. DeepSeek V4\n // Pro completed all three high-risk retail calibration trajectories\n // that included global-choice, cross-record, and multi-write behavior;\n // Sonnet completed one of the same three.\n if (agentRisk === \"standard\") {\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.82),\n match([\"gpt-5.3-codex\"], 0.81),\n match([\"kimi-k3\"], 0.78),\n match([\"deepseek-v4-pro\"], 0.76),\n );\n }\n if (agentRisk === \"policy_exception\") {\n return Math.max(\n base,\n match([\"gpt-4.1\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-5-mini\"], 0.8),\n match([\"gpt-4o-mini\"], 0.76),\n );\n }\n if (agentRisk === \"policy_exception_simple\") {\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-4.1\"], 0.86),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-4o-mini\"], 0.8),\n );\n }\n return Math.max(\n base,\n match([\"deepseek-v4-pro\"], 1),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.82),\n match([\"gpt-5.3-codex\"], 0.81),\n match([\"kimi-k3\"], 0.78),\n match([\"gpt-5-mini\"], 0.76),\n );\n }\n // Standard airline workflows stay on GPT-5 Mini: six full-session\n // development trajectories gave it the same 5/6 success as Sonnet at\n // roughly one order of magnitude lower normalized token cost. A held-out\n // high-risk cabin/date negotiation then produced a persistent empty\n // assistant turn on Mini even after a semantic retry, while Sonnet 5\n // completed the identical official tau2 trajectory with reward 1.0.\n // Promote only global optimization / conditional-global work. A known\n // batch of reservations is operationally high-risk but still a\n // structured tool workflow: current Tau evidence has Mini and Sonnet at\n // equal task reward there, while Sonnet costs roughly two orders of\n // magnitude more on the long-tail case.\n if (agentDomain === \"airline\") {\n if (agentRisk === \"complex_high\") {\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n match([\"deepseek-v4-pro\"], 0.74),\n );\n }\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"gemini-3.5-flash\"], 0.8),\n match([\"deepseek-v4-pro\"], 0.76),\n );\n }\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gemini-3.5-flash\"], 0.88),\n match([\"gpt-5.3-codex\"], 0.87),\n match([\"gpt-5-mini\"], 0.84),\n match([\"kimi-k3\"], 0.85),\n match([\"deepseek-v4-pro\"], 0.82),\n );\n case \"tool_agent_parallel\":\n if (terminalToolSignal) {\n // Multi-file Terminal work is not equivalent to a one-turn parallel\n // function-call benchmark. Sonnet is the strongest trajectory-tested\n // cost-controlled default; Opus remains a close safety fallback.\n return terminalSafetySensitive\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"claude-opus-4.8\"], 0.9),\n match([\"gpt-5.3-codex\"], 0.86),\n )\n : Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-5.3-codex\"], 0.98),\n match([\"claude-sonnet-5\"], 0.92),\n match([\"gemini-3.5-flash\"], 0.88),\n );\n }\n if (agentDomain === \"web_research\") {\n return deepWebResearch\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.84),\n match([\"claude-opus-5\"], 0.8),\n match([\"claude-opus-4.8\"], 0.78),\n )\n : Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.86),\n match([\"claude-opus-5\"], 0.84),\n match([\"claude-opus-4.8\"], 0.82),\n );\n }\n if (agentDomain === \"retail\") {\n if (agentRisk === \"policy_exception\") {\n return Math.max(\n base,\n match([\"gpt-4.1\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-5-mini\"], 0.8),\n match([\"gpt-4o-mini\"], 0.76),\n );\n }\n if (agentRisk === \"policy_exception_simple\") {\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-4.1\"], 0.86),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-4o-mini\"], 0.8),\n );\n }\n return Math.max(\n base,\n match([\"deepseek-v4-pro\"], 1),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"claude-opus-4.8\"], 0.84),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n );\n }\n if (agentDomain === \"airline\") {\n return agentRisk === \"complex_high\"\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.78),\n match([\"claude-opus-4.8\"], 0.76),\n match([\"gemini-3.5-flash\"], 0.74),\n )\n : Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"gemini-3.5-flash\"], 0.8),\n );\n }\n // RouterBench calibration, 2026-07-26: Opus 4.8 produced complete\n // multi-call payloads on 2/3 multilingual BFCL parallel cases. Gemini\n // 3.5 Flash, Sonnet 5, DeepSeek V4 Pro, and Grok 4.5 were 0/3. This\n // narrow prior only applies after the conservative prompt feature above.\n return Math.max(\n base,\n match([\"claude-opus-4.8\"], 1),\n match([\"claude-sonnet-5\"], 0.84),\n match([\"grok-4.5\"], 0.82),\n match([\"gemini-3.5-flash\"], 0.8),\n match([\"deepseek-v4-pro\"], 0.78),\n );\n case \"code_edit\":\n case \"debug\":\n return Math.max(\n base,\n match([\"gpt-5.3-codex\"], 1),\n match([\"claude-sonnet-4.6\"], 0.94),\n match([\"glm-5.2\"], 0.9),\n match([\"deepseek-v4-pro\"], 0.86),\n );\n case \"reasoning\":\n return Math.max(\n base,\n match([\"claude-sonnet-5\", \"claude-sonnet-4.6\"], 0.98),\n match([\"deepseek-v4-pro\"], 0.95),\n match([\"grok-4.5\"], 0.94),\n match([\"gemini-3.1-pro\", \"gemini-3.5-flash\"], 0.92),\n );\n case \"reasoning_mcq\":\n // RouterBench calibration (2026-07-28, six stratified GPQA Diamond\n // tasks, identical agent adapter and 512-token budget): Gemini 3\n // Flash Preview scored 5/6, Gemini 3.5 Flash 4/6, and Gemini 3.1 Pro\n // 3/6 while costing ~170x more than Flash. Keep the measured winner as\n // the narrow default; version recency alone is not a quality signal.\n // Unused host tools must not change this reasoning-only model choice.\n return Math.max(\n base,\n match([\"gemini-3-flash-preview\"], 1),\n match([\"gemini-3.5-flash\"], 0.91),\n match([\"grok-4.5\"], 0.9),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"deepseek-v4-pro\"], 0.84),\n );\n case \"reasoning_math\":\n // Same calibration, five multilingual MGSM tasks: Gemini 3.5 Flash was\n // 5/5 with the lowest cost and latency; four current flagships were 4/5\n // and Kimi K2.7 was 3/5.\n return Math.max(\n base,\n match([\"gemini-3.5-flash\"], 1),\n match([\"grok-4.5\"], 0.93),\n match([\"claude-sonnet-5\", \"deepseek-v4-pro\", \"kimi-k3\"], 0.9),\n );\n case \"vision\":\n return Math.max(\n base,\n match([\"gemini-3.1-pro\"], 0.96),\n match([\"qwen3.7-max\", \"claude-sonnet-4.6\", \"kimi-k3\", \"grok-4.3\"], 0.9),\n );\n case \"long_context\":\n // Long-context eligibility is necessary but not sufficient: a provider\n // can advertise a 1M window yet return an empty completion near that\n // boundary. Keep the proven long-context flagship in the lead and put\n // less-established alternatives in a separate affinity band so price\n // alone cannot displace it.\n return Math.max(\n base,\n match([\"gemini-3.1-pro\"], 1),\n match([\"qwen3.7-max\", \"glm-5.2\"], 0.89),\n match([\"gemini-3.5-flash\"], 0.88),\n match([\"deepseek-v4-pro\"], 0.85),\n );\n case \"extraction\": {\n // A structured extraction must preserve both the output contract and the\n // source-language fields. For Mandarin input, keep the language-native\n // Kimi candidate in a distinct affinity band. This is deliberately a\n // candidate-pool decision (rather than a brittle post-hoc override): it\n // still falls back normally if that model is unavailable or ineligible.\n // Kimi K3 costs ~5x its retired sibling K2.7, so the band must be wider\n // than the auto affinityFloorGap (0.10) or price alone re-selects a\n // non-native model for Mandarin input; 0.12 keeps K3 alone in the\n // primary band for zh and leaves every other language untouched.\n const kimiExtractionAffinity = language === \"zh\" ? 1 : 0.9;\n const otherExtractionAffinity = language === \"zh\" ? 0.88 : 0.9;\n return Math.max(\n base,\n match([\"gemini-3.5-flash\", \"gemini-2.5-flash\", \"gpt-4o-mini\"], otherExtractionAffinity),\n match([\"claude-sonnet-5\", \"claude-sonnet-4.6\"], otherExtractionAffinity),\n match([\"kimi-k3\"], kimiExtractionAffinity),\n );\n }\n default:\n return Math.max(\n base,\n match([\"gemini-3.5-flash\", \"gemini-2.5-flash\", \"kimi-k3\"], 0.86),\n );\n }\n}\n\nfunction evidenceCandidates(task: TaskType): string[] {\n if (task === \"code_agent\") {\n return [\n \"openai/gpt-5.3-codex\",\n \"anthropic/claude-sonnet-5\",\n \"openai/gpt-5-mini\",\n \"google/gemini-3.5-flash\",\n \"moonshot/kimi-k3\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"tool_agent\") {\n return [\n \"anthropic/claude-sonnet-5\",\n \"anthropic/claude-opus-5\",\n \"openai/gpt-5-mini\",\n \"openai/gpt-4.1\",\n \"openai/gpt-4o-mini\",\n \"google/gemini-3.5-flash\",\n \"openai/gpt-5.3-codex\",\n \"moonshot/kimi-k3\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"tool_agent_parallel\") {\n return [\n \"anthropic/claude-opus-5\",\n \"anthropic/claude-opus-4.8\",\n \"anthropic/claude-sonnet-5\",\n \"openai/gpt-5-mini\",\n \"openai/gpt-4.1\",\n \"openai/gpt-4o-mini\",\n \"xai/grok-4.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"long_context\") {\n return [\n \"google/gemini-3.1-pro\",\n \"deepseek/deepseek-v4-pro\",\n \"qwen/qwen3.7-max\",\n \"zai/glm-5.2\",\n \"google/gemini-3.5-flash\",\n ];\n }\n if (task === \"reasoning_mcq\") {\n return [\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3.5-flash\",\n \"xai/grok-4.5\",\n \"anthropic/claude-sonnet-5\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"extraction\") {\n // Kimi K3 is no longer on the auto MEDIUM chain (K2.7 was); the\n // language-native extraction band in affinity() needs it in the pool.\n return [\"moonshot/kimi-k3\", \"google/gemini-3.5-flash\", \"anthropic/claude-sonnet-5\"];\n }\n if (task === \"reasoning_math\") {\n return [\n \"google/gemini-3.5-flash\",\n \"xai/grok-4.5\",\n \"anthropic/claude-sonnet-5\",\n \"deepseek/deepseek-v4-pro\",\n \"moonshot/kimi-k3\",\n ];\n }\n return [];\n}\n\nfunction isEligible(\n modelId: string,\n features: TaskFeatures,\n maxOutputTokens: number,\n options: RouterOptions,\n): boolean {\n const model = options.modelCapabilities?.[modelId] ?? DEFAULT_MODEL_CAPABILITIES[modelId];\n // Preserve compatibility for temporarily catalog-less fallback IDs. They are\n // kept behind known-model candidates but are not silently dropped.\n if (!model) return true;\n if (features.needsTools && !model.supportsTools) return false;\n if (features.needsVision && !model.supportsVision) return false;\n if (features.needsStructuredOutput && !model.supportsTools) return false;\n if (model.maxOutputTokens < maxOutputTokens) return false;\n return model.contextWindow >= (features.estimatedInputTokens + maxOutputTokens) * 1.1;\n}\n\nfunction estimatedCost(\n modelId: string,\n options: RouterOptions,\n inputTokens: number,\n outputTokens: number,\n): number {\n const price = options.modelPricing.get(modelId);\n if (!price) return Number.POSITIVE_INFINITY;\n if (price.flatPrice !== undefined) return price.flatPrice;\n return (inputTokens * price.inputPrice + outputTokens * price.outputPrice) / 1_000_000;\n}\n\nfunction profileScore(\n modelId: string,\n options: RouterOptions,\n now: Date,\n):\n | { quality?: number; speed: number; tailSpeed: number; reliability: number; freshness: number }\n | undefined {\n const profile: ModelPerformanceProfile | undefined =\n options.modelPerformance?.[modelId] ??\n LIVE_MODEL_PROFILES[modelId] ??\n HISTORICAL_MODEL_PROFILES[modelId];\n if (!profile) return undefined;\n const measuredAt = Date.parse(profile.measuredAt);\n if (!Number.isFinite(measuredAt)) return undefined;\n const ageDays = Math.max(0, (now.getTime() - measuredAt) / 86_400_000);\n // A 30-day half-life makes old data a tie-breaker only. Small probe runs are\n // also weak evidence: three quick samples should not overturn a curated\n // tier ordering merely because of a transient provider tail. Callers that\n // inject an observation without a sample count retain the legacy full\n // confidence behaviour for compatibility.\n const sampleConfidence =\n profile.samples === undefined ? 1 : Math.min(1, Math.max(0, profile.samples) / 10);\n const freshness = Math.pow(0.5, ageDays / 30) * sampleConfidence;\n const quality =\n profile.intelligenceIndex === undefined\n ? undefined\n : Math.min(1, profile.intelligenceIndex / 50);\n const speed = Math.min(\n 1,\n (2_000 / Math.max(500, profile.latencyMs) + profile.outputTokensPerSecond / 250) / 2,\n );\n const tailSpeed = Math.min(1, 3_000 / Math.max(750, profile.p95LatencyMs ?? profile.latencyMs));\n const reliability = Math.max(0, 1 - (profile.errorRate ?? 0));\n return { quality, speed, tailSpeed, reliability, freshness };\n}\n\n/** Candidate router used for Auto. Rules still set the capability tier; V3 ranks within it. */\nexport class PortfolioStrategy implements RouterStrategy {\n readonly name = \"portfolio\";\n\n route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n ) {\n const features = classifyTask(prompt, systemPrompt, options);\n const base = new RulesStrategy().route(prompt, systemPrompt, maxOutputTokens, {\n ...options,\n requiresTools: features.needsTools,\n });\n const tierConfigs = base.tierConfigs;\n if (!tierConfigs) return base;\n const targetTier: Tier =\n (features.taskType === \"reasoning_mcq\" || features.taskType === \"reasoning_math\") &&\n (base.tier === \"SIMPLE\" || base.tier === \"MEDIUM\")\n ? \"REASONING\"\n : base.tier;\n const tierConfig = tierConfigs[targetTier];\n const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];\n // Evidence candidates join the configured chain, but the host's\n // unavailable set applies to both: the configured side arrives filtered\n // through RulesStrategy, and a dead evidence model must not re-enter here.\n const unavailable = new Set(options.unavailableModels ?? []);\n const chain = [\n ...new Set([...configuredCandidates, ...evidenceCandidates(features.taskType)]),\n ].filter(\n (model): model is string =>\n typeof model === \"string\" && model.length > 0 && !unavailable.has(model),\n );\n const eligible = chain.filter((model) =>\n isEligible(model, features, maxOutputTokens, options),\n );\n const eligibleCandidates = eligible.length > 0 ? eligible : chain;\n if (eligibleCandidates.length === 0) return base;\n const profileName =\n options.routingProfile === \"eco\"\n ? \"eco\"\n : options.routingProfile === \"premium\"\n ? \"premium\"\n : \"auto\";\n const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;\n const getAffinity = (model: string) =>\n affinity(\n model,\n features.taskType,\n features.language,\n features.agentDomain,\n features.deepWebResearch,\n features.agentRisk,\n features.terminalToolSignal,\n features.terminalSafetySensitive,\n );\n const bestAffinity = Math.max(...eligibleCandidates.map(getAffinity));\n const specificAffinity = eligibleCandidates.filter((model) => getAffinity(model) > 0.68);\n // A tier's fallback list is primarily an availability/recovery chain, not a\n // set of equally validated substitutes. Re-ranking every fallback lets a\n // cheap generic model displace the curated primary merely because it has a\n // favourable short performance probe. Only promote models with explicit\n // task affinity; otherwise retain the first capability-eligible tier model.\n const affinityPool = specificAffinity.length > 0 ? specificAffinity : [eligibleCandidates[0]];\n // Generic Terminal work has much wider trajectory variance than a BFCL-like\n // one-turn parallel call. Keep the strong-model safety band, but admit the\n // next capable tier so Auto's cost/reliability score can reject an Opus\n // primary that is materially more expensive without measured benefit.\n const affinityFloorGap = features.terminalToolSignal\n ? Math.max(\n portfolio.affinityFloorGap[profileName],\n features.terminalSafetySensitive ? 0.15 : 0.12,\n )\n : portfolio.affinityFloorGap[profileName];\n const candidates = affinityPool.filter(\n (model) => getAffinity(model) >= bestAffinity - affinityFloorGap,\n );\n const costs = candidates.map((model) =>\n estimatedCost(model, options, features.estimatedInputTokens, maxOutputTokens),\n );\n const finiteCosts = costs.filter(Number.isFinite);\n const minCost = finiteCosts.length > 0 ? Math.min(...finiteCosts) : 0;\n const maxCost = finiteCosts.length > 0 ? Math.max(...finiteCosts) : 1;\n\n const now = options.now ?? new Date();\n const profileWeights = portfolio[profileName];\n const rankedEntries = candidates\n .map((model, index) => {\n const cost = estimatedCost(model, options, features.estimatedInputTokens, maxOutputTokens);\n const costScore =\n Number.isFinite(cost) && maxCost > minCost\n ? 1 - (cost - minCost) / (maxCost - minCost)\n : 0.5;\n const capabilityScore = isEligible(model, features, maxOutputTokens, options) ? 1 : 0;\n const profile = profileScore(model, options, now);\n // Fresh observations can refine affinity. Historical observations fade\n // quickly and never replace task-level RouterBench evidence.\n const observedQuality =\n profile?.quality === undefined\n ? getAffinity(model)\n : getAffinity(model) * (1 - profile.freshness) + profile.quality * profile.freshness;\n const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;\n const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;\n const observedReliability = profile\n ? profile.reliability * profile.freshness + (1 - profile.freshness)\n : 1;\n // Preserve a small amount of the hand-curated fallback order while V3's\n // task affinity and real request constraints do the primary work.\n const legacyScore = 1 - index / Math.max(1, candidates.length - 1);\n const qualityWeight =\n profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);\n const speedScore = features.latencySensitive ? observedTailSpeed : observedSpeed;\n const speedWeight =\n profileWeights.speed +\n (features.latencySensitive ? portfolio.latencySensitiveSpeedBoost : 0);\n const reliabilityWeight =\n profileWeights.reliability +\n (features.highStakes ? portfolio.highStakesBoost.reliability : 0);\n const score =\n observedQuality * qualityWeight +\n capabilityScore * profileWeights.capability +\n costScore * profileWeights.cost +\n speedScore * speedWeight +\n observedReliability * reliabilityWeight +\n legacyScore * profileWeights.legacy;\n return {\n model,\n score,\n quality: observedQuality,\n cost: costScore,\n speed: speedScore,\n reliability: observedReliability,\n };\n })\n .sort((a, b) => b.score - a.score);\n const scoredModels = rankedEntries.map((item) => item.model);\n // The affinity floor controls which models may compete for the primary;\n // it must not erase availability fallbacks. Append all remaining eligible\n // models in their curated chain order after the scored primary pool.\n const webResearchFallbackOrder = [\n \"anthropic/claude-sonnet-5\",\n \"openai/gpt-5-mini\",\n \"google/gemini-3.5-flash\",\n \"anthropic/claude-opus-5\",\n \"anthropic/claude-opus-4.8\",\n \"openai/gpt-5.3-codex\",\n ];\n const ranked =\n features.agentDomain === \"web_research\"\n ? [\n ...scoredModels,\n ...webResearchFallbackOrder.filter(\n (model) => eligibleCandidates.includes(model) && !scoredModels.includes(model),\n ),\n ...eligibleCandidates.filter(\n (model) => !scoredModels.includes(model) && !webResearchFallbackOrder.includes(model),\n ),\n ]\n : [...scoredModels, ...eligibleCandidates.filter((model) => !scoredModels.includes(model))];\n\n const model = ranked[0] ?? base.model;\n const selectedTierConfigs: Record = {\n ...tierConfigs,\n [targetTier]: { primary: model, fallback: ranked.slice(1) },\n };\n // selectModel only reads the selected tier; retain the complete tier map for host fallback.\n const decision = selectModel(\n targetTier,\n base.confidence,\n \"portfolio\",\n `${base.reasoning} | v3 task=${features.taskType} agentRisk=${features.agentRisk} deepWebResearch=${features.deepWebResearch} terminalCode=${features.implicitTerminalCode} terminalSafety=${features.terminalSafetySensitive} candidates=${ranked.length}`,\n selectedTierConfigs,\n options.modelPricing,\n features.estimatedInputTokens,\n maxOutputTokens,\n options.routingProfile,\n base.agenticScore,\n );\n return {\n ...decision,\n tierConfigs: selectedTierConfigs,\n profile: base.profile,\n candidates: ranked,\n candidateScores: rankedEntries.map(({ model, score, quality, cost, speed, reliability }) => ({\n model,\n score,\n quality,\n cost,\n speed,\n reliability,\n })),\n taskType: features.taskType,\n routerVersion: \"v3-portfolio\" as const,\n };\n }\n}\n","/**\n * Default Routing Config\n *\n * All routing parameters as a TypeScript constant.\n * Operators override via openclaw.yaml plugin config.\n *\n * Scoring uses 15 weighted dimensions with sigmoid confidence calibration.\n */\n\nimport type { RoutingConfig } from \"./types.js\";\n\nexport const DEFAULT_ROUTING_CONFIG: RoutingConfig = {\n version: \"3.5\",\n strategy: \"portfolio\",\n portfolio: {\n auto: {\n quality: 0.47,\n capability: 0.2,\n cost: 0.18,\n speed: 0.07,\n reliability: 0.03,\n legacy: 0.05,\n },\n eco: {\n quality: 0.36,\n capability: 0.2,\n cost: 0.28,\n speed: 0.1,\n reliability: 0.04,\n legacy: 0.02,\n },\n premium: {\n quality: 0.58,\n capability: 0.2,\n cost: 0.08,\n speed: 0.06,\n reliability: 0.06,\n legacy: 0.02,\n },\n highStakesBoost: { quality: 0.08, reliability: 0.05 },\n latencySensitiveSpeedBoost: 0.08,\n affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 },\n },\n\n classifier: {\n llmModel: \"google/gemini-2.5-flash\",\n llmMaxTokens: 10,\n llmTemperature: 0,\n promptTruncationChars: 500,\n cacheTtlMs: 3_600_000, // 1 hour\n },\n\n scoring: {\n tokenCountThresholds: { simple: 50, complex: 500 },\n\n // Multilingual keywords: EN + ZH + JA + RU + DE + ES + PT + KO + AR\n codeKeywords: [\n // English\n \"function\",\n \"class\",\n \"import\",\n \"def\",\n \"SELECT\",\n \"async\",\n \"await\",\n \"const\",\n \"let\",\n \"var\",\n \"return\",\n \"```\",\n // Chinese\n \"函数\",\n \"类\",\n \"导入\",\n \"定义\",\n \"查询\",\n \"异步\",\n \"等待\",\n \"常量\",\n \"变量\",\n \"返回\",\n // Japanese\n \"関数\",\n \"クラス\",\n \"インポート\",\n \"非同期\",\n \"定数\",\n \"変数\",\n // Russian\n \"функция\",\n \"класс\",\n \"импорт\",\n \"определ\",\n \"запрос\",\n \"асинхронный\",\n \"ожидать\",\n \"константа\",\n \"переменная\",\n \"вернуть\",\n // German\n \"funktion\",\n \"klasse\",\n \"importieren\",\n \"definieren\",\n \"abfrage\",\n \"asynchron\",\n \"erwarten\",\n \"konstante\",\n \"variable\",\n \"zurückgeben\",\n // Spanish\n \"función\",\n \"clase\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"asíncrono\",\n \"esperar\",\n \"constante\",\n \"variable\",\n \"retornar\",\n // Portuguese\n \"função\",\n \"classe\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"assíncrono\",\n \"aguardar\",\n \"constante\",\n \"variável\",\n \"retornar\",\n // Korean\n \"함수\",\n \"클래스\",\n \"가져오기\",\n \"정의\",\n \"쿼리\",\n \"비동기\",\n \"대기\",\n \"상수\",\n \"변수\",\n \"반환\",\n // Arabic\n \"دالة\",\n \"فئة\",\n \"استيراد\",\n \"تعريف\",\n \"استعلام\",\n \"غير متزامن\",\n \"انتظار\",\n \"ثابت\",\n \"متغير\",\n \"إرجاع\",\n ],\n reasoningKeywords: [\n // English\n \"prove\",\n \"theorem\",\n \"derive\",\n \"step by step\",\n \"chain of thought\",\n \"formally\",\n \"mathematical\",\n \"proof\",\n \"logically\",\n // Chinese\n \"证明\",\n \"定理\",\n \"推导\",\n \"逐步\",\n \"思维链\",\n \"形式化\",\n \"数学\",\n \"逻辑\",\n // Japanese\n \"証明\",\n \"定理\",\n \"導出\",\n \"ステップバイステップ\",\n \"論理的\",\n // Russian\n \"доказать\",\n \"докажи\",\n \"доказательств\",\n \"теорема\",\n \"вывести\",\n \"шаг за шагом\",\n \"пошагово\",\n \"поэтапно\",\n \"цепочка рассуждений\",\n \"рассуждени\",\n \"формально\",\n \"математически\",\n \"логически\",\n // German\n \"beweisen\",\n \"beweis\",\n \"theorem\",\n \"ableiten\",\n \"schritt für schritt\",\n \"gedankenkette\",\n \"formal\",\n \"mathematisch\",\n \"logisch\",\n // Spanish\n \"demostrar\",\n \"teorema\",\n \"derivar\",\n \"paso a paso\",\n \"cadena de pensamiento\",\n \"formalmente\",\n \"matemático\",\n \"prueba\",\n \"lógicamente\",\n // Portuguese\n \"provar\",\n \"teorema\",\n \"derivar\",\n \"passo a passo\",\n \"cadeia de pensamento\",\n \"formalmente\",\n \"matemático\",\n \"prova\",\n \"logicamente\",\n // Korean\n \"증명\",\n \"정리\",\n \"도출\",\n \"단계별\",\n \"사고의 연쇄\",\n \"형식적\",\n \"수학적\",\n \"논리적\",\n // Arabic\n \"إثبات\",\n \"نظرية\",\n \"اشتقاق\",\n \"خطوة بخطوة\",\n \"سلسلة التفكير\",\n \"رسمياً\",\n \"رياضي\",\n \"برهان\",\n \"منطقياً\",\n ],\n simpleKeywords: [\n // English\n \"what is\",\n \"define\",\n \"translate\",\n \"hello\",\n \"yes or no\",\n \"capital of\",\n \"how old\",\n \"who is\",\n \"when was\",\n // Chinese\n \"什么是\",\n \"定义\",\n \"翻译\",\n \"你好\",\n \"是否\",\n \"首都\",\n \"多大\",\n \"谁是\",\n \"何时\",\n // Japanese\n \"とは\",\n \"定義\",\n \"翻訳\",\n \"こんにちは\",\n \"はいかいいえ\",\n \"首都\",\n \"誰\",\n // Russian\n \"что такое\",\n \"определение\",\n \"перевести\",\n \"переведи\",\n \"привет\",\n \"да или нет\",\n \"столица\",\n \"сколько лет\",\n \"кто такой\",\n \"когда\",\n \"объясни\",\n // German\n \"was ist\",\n \"definiere\",\n \"übersetze\",\n \"hallo\",\n \"ja oder nein\",\n \"hauptstadt\",\n \"wie alt\",\n \"wer ist\",\n \"wann\",\n \"erkläre\",\n // Spanish\n \"qué es\",\n \"definir\",\n \"traducir\",\n \"hola\",\n \"sí o no\",\n \"capital de\",\n \"cuántos años\",\n \"quién es\",\n \"cuándo\",\n // Portuguese\n \"o que é\",\n \"definir\",\n \"traduzir\",\n \"olá\",\n \"sim ou não\",\n \"capital de\",\n \"quantos anos\",\n \"quem é\",\n \"quando\",\n // Korean\n \"무엇\",\n \"정의\",\n \"번역\",\n \"안녕하세요\",\n \"예 또는 아니오\",\n \"수도\",\n \"누구\",\n \"언제\",\n // Arabic\n \"ما هو\",\n \"تعريف\",\n \"ترجم\",\n \"مرحبا\",\n \"نعم أو لا\",\n \"عاصمة\",\n \"من هو\",\n \"متى\",\n ],\n technicalKeywords: [\n // English\n \"algorithm\",\n \"optimize\",\n \"architecture\",\n \"distributed\",\n \"kubernetes\",\n \"microservice\",\n \"database\",\n \"infrastructure\",\n // Chinese\n \"算法\",\n \"优化\",\n \"架构\",\n \"分布式\",\n \"微服务\",\n \"数据库\",\n \"基础设施\",\n // Japanese\n \"アルゴリズム\",\n \"最適化\",\n \"アーキテクチャ\",\n \"分散\",\n \"マイクロサービス\",\n \"データベース\",\n // Russian\n \"алгоритм\",\n \"оптимизировать\",\n \"оптимизаци\",\n \"оптимизируй\",\n \"архитектура\",\n \"распределённый\",\n \"микросервис\",\n \"база данных\",\n \"инфраструктура\",\n // German\n \"algorithmus\",\n \"optimieren\",\n \"architektur\",\n \"verteilt\",\n \"kubernetes\",\n \"mikroservice\",\n \"datenbank\",\n \"infrastruktur\",\n // Spanish\n \"algoritmo\",\n \"optimizar\",\n \"arquitectura\",\n \"distribuido\",\n \"microservicio\",\n \"base de datos\",\n \"infraestructura\",\n // Portuguese\n \"algoritmo\",\n \"otimizar\",\n \"arquitetura\",\n \"distribuído\",\n \"microsserviço\",\n \"banco de dados\",\n \"infraestrutura\",\n // Korean\n \"알고리즘\",\n \"최적화\",\n \"아키텍처\",\n \"분산\",\n \"마이크로서비스\",\n \"데이터베이스\",\n \"인프라\",\n // Arabic\n \"خوارزمية\",\n \"تحسين\",\n \"بنية\",\n \"موزع\",\n \"خدمة مصغرة\",\n \"قاعدة بيانات\",\n \"بنية تحتية\",\n ],\n creativeKeywords: [\n // English\n \"story\",\n \"poem\",\n \"compose\",\n \"brainstorm\",\n \"creative\",\n \"imagine\",\n \"write a\",\n // Chinese\n \"故事\",\n \"诗\",\n \"创作\",\n \"头脑风暴\",\n \"创意\",\n \"想象\",\n \"写一个\",\n // Japanese\n \"物語\",\n \"詩\",\n \"作曲\",\n \"ブレインストーム\",\n \"創造的\",\n \"想像\",\n // Russian\n \"история\",\n \"рассказ\",\n \"стихотворение\",\n \"сочинить\",\n \"сочини\",\n \"мозговой штурм\",\n \"творческий\",\n \"представить\",\n \"придумай\",\n \"напиши\",\n // German\n \"geschichte\",\n \"gedicht\",\n \"komponieren\",\n \"brainstorming\",\n \"kreativ\",\n \"vorstellen\",\n \"schreibe\",\n \"erzählung\",\n // Spanish\n \"historia\",\n \"poema\",\n \"componer\",\n \"lluvia de ideas\",\n \"creativo\",\n \"imaginar\",\n \"escribe\",\n // Portuguese\n \"história\",\n \"poema\",\n \"compor\",\n \"criativo\",\n \"imaginar\",\n \"escreva\",\n // Korean\n \"이야기\",\n \"시\",\n \"작곡\",\n \"브레인스토밍\",\n \"창의적\",\n \"상상\",\n \"작성\",\n // Arabic\n \"قصة\",\n \"قصيدة\",\n \"تأليف\",\n \"عصف ذهني\",\n \"إبداعي\",\n \"تخيل\",\n \"اكتب\",\n ],\n\n // New dimension keyword lists (multilingual)\n imperativeVerbs: [\n // English\n \"build\",\n \"create\",\n \"implement\",\n \"design\",\n \"develop\",\n \"construct\",\n \"generate\",\n \"deploy\",\n \"configure\",\n \"set up\",\n // Chinese\n \"构建\",\n \"创建\",\n \"实现\",\n \"设计\",\n \"开发\",\n \"生成\",\n \"部署\",\n \"配置\",\n \"设置\",\n // Japanese\n \"構築\",\n \"作成\",\n \"実装\",\n \"設計\",\n \"開発\",\n \"生成\",\n \"デプロイ\",\n \"設定\",\n // Russian\n \"построить\",\n \"построй\",\n \"создать\",\n \"создай\",\n \"реализовать\",\n \"реализуй\",\n \"спроектировать\",\n \"разработать\",\n \"разработай\",\n \"сконструировать\",\n \"сгенерировать\",\n \"сгенерируй\",\n \"развернуть\",\n \"разверни\",\n \"настроить\",\n \"настрой\",\n // German\n \"erstellen\",\n \"bauen\",\n \"implementieren\",\n \"entwerfen\",\n \"entwickeln\",\n \"konstruieren\",\n \"generieren\",\n \"bereitstellen\",\n \"konfigurieren\",\n \"einrichten\",\n // Spanish\n \"construir\",\n \"crear\",\n \"implementar\",\n \"diseñar\",\n \"desarrollar\",\n \"generar\",\n \"desplegar\",\n \"configurar\",\n // Portuguese\n \"construir\",\n \"criar\",\n \"implementar\",\n \"projetar\",\n \"desenvolver\",\n \"gerar\",\n \"implantar\",\n \"configurar\",\n // Korean\n \"구축\",\n \"생성\",\n \"구현\",\n \"설계\",\n \"개발\",\n \"배포\",\n \"설정\",\n // Arabic\n \"بناء\",\n \"إنشاء\",\n \"تنفيذ\",\n \"تصميم\",\n \"تطوير\",\n \"توليد\",\n \"نشر\",\n \"إعداد\",\n ],\n constraintIndicators: [\n // English\n \"under\",\n \"at most\",\n \"at least\",\n \"within\",\n \"no more than\",\n \"o(\",\n \"maximum\",\n \"minimum\",\n \"limit\",\n \"budget\",\n // Chinese\n \"不超过\",\n \"至少\",\n \"最多\",\n \"在内\",\n \"最大\",\n \"最小\",\n \"限制\",\n \"预算\",\n // Japanese\n \"以下\",\n \"最大\",\n \"最小\",\n \"制限\",\n \"予算\",\n // Russian\n \"не более\",\n \"не менее\",\n \"как минимум\",\n \"в пределах\",\n \"максимум\",\n \"минимум\",\n \"ограничение\",\n \"бюджет\",\n // German\n \"höchstens\",\n \"mindestens\",\n \"innerhalb\",\n \"nicht mehr als\",\n \"maximal\",\n \"minimal\",\n \"grenze\",\n \"budget\",\n // Spanish\n \"como máximo\",\n \"al menos\",\n \"dentro de\",\n \"no más de\",\n \"máximo\",\n \"mínimo\",\n \"límite\",\n \"presupuesto\",\n // Portuguese\n \"no máximo\",\n \"pelo menos\",\n \"dentro de\",\n \"não mais que\",\n \"máximo\",\n \"mínimo\",\n \"limite\",\n \"orçamento\",\n // Korean\n \"이하\",\n \"이상\",\n \"최대\",\n \"최소\",\n \"제한\",\n \"예산\",\n // Arabic\n \"على الأكثر\",\n \"على الأقل\",\n \"ضمن\",\n \"لا يزيد عن\",\n \"أقصى\",\n \"أدنى\",\n \"حد\",\n \"ميزانية\",\n ],\n outputFormatKeywords: [\n // English\n \"json\",\n \"yaml\",\n \"xml\",\n \"table\",\n \"csv\",\n \"markdown\",\n \"schema\",\n \"format as\",\n \"structured\",\n // Chinese\n \"表格\",\n \"格式化为\",\n \"结构化\",\n // Japanese\n \"テーブル\",\n \"フォーマット\",\n \"構造化\",\n // Russian\n \"таблица\",\n \"форматировать как\",\n \"структурированный\",\n // German\n \"tabelle\",\n \"formatieren als\",\n \"strukturiert\",\n // Spanish\n \"tabla\",\n \"formatear como\",\n \"estructurado\",\n // Portuguese\n \"tabela\",\n \"formatar como\",\n \"estruturado\",\n // Korean\n \"테이블\",\n \"형식\",\n \"구조화\",\n // Arabic\n \"جدول\",\n \"تنسيق\",\n \"منظم\",\n ],\n referenceKeywords: [\n // English\n \"above\",\n \"below\",\n \"previous\",\n \"following\",\n \"the docs\",\n \"the api\",\n \"the code\",\n \"earlier\",\n \"attached\",\n // Chinese\n \"上面\",\n \"下面\",\n \"之前\",\n \"接下来\",\n \"文档\",\n \"代码\",\n \"附件\",\n // Japanese\n \"上記\",\n \"下記\",\n \"前の\",\n \"次の\",\n \"ドキュメント\",\n \"コード\",\n // Russian\n \"выше\",\n \"ниже\",\n \"предыдущий\",\n \"следующий\",\n \"документация\",\n \"код\",\n \"ранее\",\n \"вложение\",\n // German\n \"oben\",\n \"unten\",\n \"vorherige\",\n \"folgende\",\n \"dokumentation\",\n \"der code\",\n \"früher\",\n \"anhang\",\n // Spanish\n \"arriba\",\n \"abajo\",\n \"anterior\",\n \"siguiente\",\n \"documentación\",\n \"el código\",\n \"adjunto\",\n // Portuguese\n \"acima\",\n \"abaixo\",\n \"anterior\",\n \"seguinte\",\n \"documentação\",\n \"o código\",\n \"anexo\",\n // Korean\n \"위\",\n \"아래\",\n \"이전\",\n \"다음\",\n \"문서\",\n \"코드\",\n \"첨부\",\n // Arabic\n \"أعلاه\",\n \"أدناه\",\n \"السابق\",\n \"التالي\",\n \"الوثائق\",\n \"الكود\",\n \"مرفق\",\n ],\n negationKeywords: [\n // English\n \"don't\",\n \"do not\",\n \"avoid\",\n \"never\",\n \"without\",\n \"except\",\n \"exclude\",\n \"no longer\",\n // Chinese\n \"不要\",\n \"避免\",\n \"从不\",\n \"没有\",\n \"除了\",\n \"排除\",\n // Japanese\n \"しないで\",\n \"避ける\",\n \"決して\",\n \"なしで\",\n \"除く\",\n // Russian\n \"не делай\",\n \"не надо\",\n \"нельзя\",\n \"избегать\",\n \"никогда\",\n \"без\",\n \"кроме\",\n \"исключить\",\n \"больше не\",\n // German\n \"nicht\",\n \"vermeide\",\n \"niemals\",\n \"ohne\",\n \"außer\",\n \"ausschließen\",\n \"nicht mehr\",\n // Spanish\n \"no hagas\",\n \"evitar\",\n \"nunca\",\n \"sin\",\n \"excepto\",\n \"excluir\",\n // Portuguese\n \"não faça\",\n \"evitar\",\n \"nunca\",\n \"sem\",\n \"exceto\",\n \"excluir\",\n // Korean\n \"하지 마\",\n \"피하다\",\n \"절대\",\n \"없이\",\n \"제외\",\n // Arabic\n \"لا تفعل\",\n \"تجنب\",\n \"أبداً\",\n \"بدون\",\n \"باستثناء\",\n \"استبعاد\",\n ],\n domainSpecificKeywords: [\n // English\n \"quantum\",\n \"fpga\",\n \"vlsi\",\n \"risc-v\",\n \"asic\",\n \"photonics\",\n \"genomics\",\n \"proteomics\",\n \"topological\",\n \"homomorphic\",\n \"zero-knowledge\",\n \"lattice-based\",\n // Chinese\n \"量子\",\n \"光子学\",\n \"基因组学\",\n \"蛋白质组学\",\n \"拓扑\",\n \"同态\",\n \"零知识\",\n \"格密码\",\n // Japanese\n \"量子\",\n \"フォトニクス\",\n \"ゲノミクス\",\n \"トポロジカル\",\n // Russian\n \"квантовый\",\n \"фотоника\",\n \"геномика\",\n \"протеомика\",\n \"топологический\",\n \"гомоморфный\",\n \"с нулевым разглашением\",\n \"на основе решёток\",\n // German\n \"quanten\",\n \"photonik\",\n \"genomik\",\n \"proteomik\",\n \"topologisch\",\n \"homomorph\",\n \"zero-knowledge\",\n \"gitterbasiert\",\n // Spanish\n \"cuántico\",\n \"fotónica\",\n \"genómica\",\n \"proteómica\",\n \"topológico\",\n \"homomórfico\",\n // Portuguese\n \"quântico\",\n \"fotônica\",\n \"genômica\",\n \"proteômica\",\n \"topológico\",\n \"homomórfico\",\n // Korean\n \"양자\",\n \"포토닉스\",\n \"유전체학\",\n \"위상\",\n \"동형\",\n // Arabic\n \"كمي\",\n \"ضوئيات\",\n \"جينوميات\",\n \"طوبولوجي\",\n \"تماثلي\",\n ],\n\n // Agentic task keywords - file ops, execution, multi-step, iterative work\n // Pruned: removed overly common words like \"then\", \"first\", \"run\", \"test\", \"build\"\n agenticTaskKeywords: [\n // English - File operations (clearly agentic)\n \"read file\",\n \"read the file\",\n \"look at\",\n \"check the\",\n \"open the\",\n \"edit\",\n \"modify\",\n \"update the\",\n \"change the\",\n \"write to\",\n \"create file\",\n // English - Execution (specific commands only)\n \"execute\",\n \"deploy\",\n \"install\",\n \"npm\",\n \"pip\",\n \"compile\",\n // English - Multi-step patterns (specific only)\n \"after that\",\n \"and also\",\n \"once done\",\n \"step 1\",\n \"step 2\",\n // English - Iterative work\n \"fix\",\n \"debug\",\n \"until it works\",\n \"keep trying\",\n \"iterate\",\n \"make sure\",\n \"verify\",\n \"confirm\",\n // Chinese (keep specific ones)\n \"读取文件\",\n \"查看\",\n \"打开\",\n \"编辑\",\n \"修改\",\n \"更新\",\n \"创建\",\n \"执行\",\n \"部署\",\n \"安装\",\n \"第一步\",\n \"第二步\",\n \"修复\",\n \"调试\",\n \"直到\",\n \"确认\",\n \"验证\",\n // Spanish\n \"leer archivo\",\n \"editar\",\n \"modificar\",\n \"actualizar\",\n \"ejecutar\",\n \"desplegar\",\n \"instalar\",\n \"paso 1\",\n \"paso 2\",\n \"arreglar\",\n \"depurar\",\n \"verificar\",\n // Portuguese\n \"ler arquivo\",\n \"editar\",\n \"modificar\",\n \"atualizar\",\n \"executar\",\n \"implantar\",\n \"instalar\",\n \"passo 1\",\n \"passo 2\",\n \"corrigir\",\n \"depurar\",\n \"verificar\",\n // Korean\n \"파일 읽기\",\n \"편집\",\n \"수정\",\n \"업데이트\",\n \"실행\",\n \"배포\",\n \"설치\",\n \"단계 1\",\n \"단계 2\",\n \"디버그\",\n \"확인\",\n // Arabic\n \"قراءة ملف\",\n \"تحرير\",\n \"تعديل\",\n \"تحديث\",\n \"تنفيذ\",\n \"نشر\",\n \"تثبيت\",\n \"الخطوة 1\",\n \"الخطوة 2\",\n \"إصلاح\",\n \"تصحيح\",\n \"تحقق\",\n ],\n\n // Dimension weights (sum to 1.0)\n dimensionWeights: {\n tokenCount: 0.08,\n codePresence: 0.15,\n reasoningMarkers: 0.18,\n technicalTerms: 0.1,\n creativeMarkers: 0.05,\n simpleIndicators: 0.02, // Reduced from 0.12 to make room for agenticTask\n multiStepPatterns: 0.12,\n questionComplexity: 0.05,\n imperativeVerbs: 0.03,\n constraintCount: 0.04,\n outputFormat: 0.03,\n referenceComplexity: 0.02,\n negationComplexity: 0.01,\n domainSpecificity: 0.02,\n agenticTask: 0.04, // Reduced - agentic signals influence tier selection, not dominate it\n },\n\n // Tier boundaries on weighted score axis\n tierBoundaries: {\n simpleMedium: 0.0,\n mediumComplex: 0.3, // Raised from 0.18 - prevent simple tasks from reaching expensive COMPLEX tier\n complexReasoning: 0.5, // Raised from 0.4 - reserve for true reasoning tasks\n },\n\n // Sigmoid steepness for confidence calibration\n confidenceSteepness: 12,\n // Below this confidence → ambiguous (null tier)\n confidenceThreshold: 0.7,\n },\n\n // ─── Tier chains ───\n //\n // Catalog refresh 2026-08-29 (V3.5). Every chain below names only models\n // the public catalog lists (GET https://blockrun.ai/api/v1/models). Ids the\n // gateway withholds (`hidden: true`) — kimi-k2.5/k2.6/k2.7, the grok-4-fast\n // and grok-4-1-fast pairs, grok-4-0709, claude-opus-4.6, gemini-3-pro-preview,\n // the whole `free/*` namespace — were removed everywhere, including fallback\n // rungs, so a routed model is always one a user can find on blockrun.ai/models.\n //\n // Primaries moved only where portfolio.ts already carries calibration\n // evidence for the successor (Sonnet 5 over Sonnet 4.6, GPT-5 Mini for\n // agentic MEDIUM, Gemini 3.5 Flash where Kimi K2.7 was). Newcomers with no\n // trajectory evidence yet (gemini-3.6-flash, glm-5.3, glm-5.3-flash,\n // gpt-5.6-luna, grok-4.3, minimax-m3, qwen3.7-plus) enter as fallback rungs;\n // promotion waits for a calibration run, because version recency is not a\n // quality signal.\n //\n // Latency figures in comments are the 2026-08-29 gateway probe\n // (model-profiles.generated.json); prices are the catalog list.\n\n // Auto (balanced) tier configs - current default smart routing\n tiers: {\n SIMPLE: {\n primary: \"google/gemini-2.5-flash\", // $0.30/$2.50 — 60% retention (best) in the 2026-03 run; still the fastest quality answer\n fallback: [\n \"google/gemini-3-flash-preview\", // $0.50/$3 — GPQA 5/6 in the 2026-07 calibration\n \"google/gemini-3.5-flash-lite\", // $0.30/$2.50, 1M ctx, thinking mode — same price as 2.5 Flash, newer generation\n \"deepseek/deepseek-chat\", // $0.14/$0.28, 1M ctx\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50, 1M ctx\n \"openai/gpt-5.6-luna\", // $0.20/$1.20, 1M ctx — GPT-5.6 cost tier (cut 2026-07-30)\n \"openai/gpt-5.4-nano\", // $0.20/$1.25, 1M ctx\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40\n \"nvidia/nemotron-3.5-lightning\", // FREE backstop — NVIDIA free tier (probed 2026-08-30)\n ],\n },\n MEDIUM: {\n // Was moonshot/kimi-k2.7 (hidden 2026-08). Gemini 3.5 Flash is the\n // calibrated successor: MGSM 5/5, GPQA 4/6, extraction band (portfolio.ts).\n primary: \"google/gemini-3.5-flash\", // $1.50/$9, 1M ctx, vision + tools\n fallback: [\n \"google/gemini-3.6-flash\", // $1.50/$7.50 — newest Flash, output 17% cheaper than 3.5; awaiting calibration\n \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx, vision + tools verified live 2026-08-27\n \"openai/gpt-5.6-terra\", // $2/$12, 1M ctx — GPT-5.6 balanced tier\n \"google/gemini-3-flash-preview\", // $0.50/$3\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n \"minimax/minimax-m3\", // $0.30/$1.20, 1M ctx\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n \"openai/gpt-5.6-luna\", // $0.20/$1.20\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40\n ],\n },\n COMPLEX: {\n primary: \"google/gemini-3.1-pro\", // $2/$12 — proven long-context flagship (portfolio.ts long_context lead)\n fallback: [\n \"google/gemini-3.6-flash\", // $1.50/$7.50 — Pro-level quality at Flash price (Google's claim; uncalibrated here)\n \"google/gemini-3.5-flash\", // $1.50/$9 — calibrated\n \"anthropic/claude-sonnet-5\", // $3/$15 — near-Opus quality, tau2 + Terminal-Bench calibrated\n \"xai/grok-4.5\", // $2.50/$9 — 503-resistant, independent infra (was grok-4-0709, now hidden)\n \"google/gemini-2.5-pro\", // $1.25/$10\n \"anthropic/claude-sonnet-4.6\", // $3/$15\n \"openai/gpt-5.6-terra\", // $2/$12 — GPT-5.6 balanced tier (Sol excluded: #202)\n \"openai/gpt-5.5\", // $5/$30 — prior OpenAI flagship\n \"openai/gpt-5.4\", // $2.50/$15 — previous flagship, benchmarked\n \"zai/glm-5.3\", // $1.40/$4.40, 1M ctx, always-on thinking — verified live 2026-08-19\n \"moonshot/kimi-k3\", // $3/$15, 1M ctx — Moonshot flagship (K2.7 successor)\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87 — strongest open-weight reasoner\n \"deepseek/deepseek-chat\", // $0.14/$0.28 — cheap last resort\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n REASONING: {\n // Was xai/grok-4-1-fast-reasoning ($0.20/$0.50, hidden 2026-08). DeepSeek\n // Reasoner is the cheapest listed reasoner at the same 1M context.\n primary: \"deepseek/deepseek-reasoner\", // $0.14/$0.28, 1M ctx\n fallback: [\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87 — calibrated reasoning band 0.95\n \"xai/grok-4.3\", // $1.50/$4, 1M ctx — xAI reasoning model, vision\n \"qwen/qwen3.7-plus\", // $0.32/$1.28, 1M ctx — reasoning; needs a generous max_tokens (thinking is billed)\n \"google/gemini-3.5-flash\", // $1.50/$9 — MGSM 5/5\n \"openai/o4-mini\", // $1.10/$4.40\n \"openai/o3\", // $2/$8\n ],\n },\n },\n\n // Eco tier configs - absolute cheapest (blockrun/eco)\n ecoTiers: {\n SIMPLE: {\n primary: \"nvidia/nemotron-3.5-lightning\", // FREE — NVIDIA free tier flagship, 1M ctx\n fallback: [\n \"nvidia/nemotron-3-nano-30b\", // FREE — fastest free model (~121 tok/s)\n // The free head keeps rotting with NVIDIA's hosting (deepseek-v4-flash\n // 410 2026-08-12, seed-oss-36b 410 2026-08-03, gpt-oss-120b/20b 400\n // 2026-08-21, and on 2026-08-30 FOUR of the five visible free models at\n // once — step-3.7-flash, nemotron-nano-9b-v2 and nemotron-nano-12b-v2-vl\n // all 410, mistral-nemotron hung). Each retirement retargets the two\n // free rungs to the current free tier; the paid rungs below never move.\n // The head follows blockrun's own redirect of the model it replaces, so\n // the router and the gateway never name different models.\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40 — cheapest paid rung\n \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx, vision + tools\n \"openai/gpt-5.6-luna\", // $0.20/$1.20, 1M ctx\n \"openai/gpt-5.4-nano\", // $0.20/$1.25\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n ],\n },\n MEDIUM: {\n primary: \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx, vision + tools verified live — cheapest full-capability model\n fallback: [\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n \"openai/gpt-5.6-luna\", // $0.20/$1.20\n \"openai/gpt-5.4-nano\", // $0.20/$1.25\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n COMPLEX: {\n primary: \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx\n fallback: [\n \"deepseek/deepseek-chat\", // $0.14/$0.28, 1M ctx\n \"minimax/minimax-m3\", // $0.30/$1.20, 1M ctx\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n REASONING: {\n primary: \"deepseek/deepseek-reasoner\", // $0.14/$0.28, 1M ctx — cheapest listed reasoner\n fallback: [\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87\n \"qwen/qwen3.7-plus\", // $0.32/$1.28 — reasoning\n \"minimax/minimax-m3\", // $0.30/$1.20 — reasoning + coding\n \"zai/glm-5.3-flash\", // $0.15/$0.50 — reasoning tokens alongside content\n ],\n },\n },\n\n // Premium tier configs - best quality (blockrun/premium)\n // codex=complex coding, flash=simple coding, sonnet=reasoning/instructions, fable/opus=architecture/PM/audits\n premiumTiers: {\n SIMPLE: {\n // Was moonshot/kimi-k2.7 (hidden 2026-08).\n primary: \"google/gemini-3.5-flash\", // $1.50/$9, 1M ctx, vision + tools — calibrated\n fallback: [\n \"google/gemini-3.6-flash\", // $1.50/$7.50 — newest Flash\n \"anthropic/claude-haiku-4.5\", // $1/$5\n \"zai/glm-5.3\", // $1.40/$4.40, 1M ctx\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n \"google/gemini-3.5-flash-lite\", // $0.30/$2.50\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n ],\n },\n MEDIUM: {\n primary: \"openai/gpt-5.3-codex\", // $1.75/$14 - 400K context, 128K output — code_edit/debug lead (portfolio.ts)\n fallback: [\n \"anthropic/claude-sonnet-5\", // $3/$15 — code_agent band 0.98\n \"moonshot/kimi-k3\", // $3/$15, 1M ctx — Moonshot flagship\n \"zai/glm-5.3\", // $1.40/$4.40 — long-horizon coding\n \"google/gemini-3.6-flash\", // $1.50/$7.50\n \"google/gemini-3.5-flash\", // $1.50/$9\n \"google/gemini-2.5-pro\", // $1.25/$10\n \"xai/grok-4.5\", // $2.50/$9\n \"anthropic/claude-sonnet-4.6\", // $3/$15\n \"openai/gpt-5.6-terra\", // $2/$12\n ],\n },\n COMPLEX: {\n // fable-5 was promoted here 2026-06-11, force-reverted 2026-06-13 when Anthropic\n // withdrew the offer, and restored 2026-07-14 now that BlockRun has relisted it.\n primary: \"anthropic/claude-fable-5\", // Best quality for complex tasks — Mythos-class flagship above Opus ($10/$50, 1M ctx, always-on thinking)\n // Fallback chain de-Gemini'd 2026-04-22: when Anthropic 503s, Gemini is\n // also prone to \"high demand\" 503s (correlated failure — everyone falls\n // back to Google at the same time). Prefer in-family → xAI → Moonshot →\n // OpenAI flagship → Z.AI → DeepSeek → NVIDIA free instead.\n fallback: [\n \"anthropic/claude-opus-5\", // in-family hot swap first (half the price, 1M ctx + adaptive thinking)\n \"anthropic/claude-opus-4.8\", // in-family hot swap (identical cost to 5)\n \"anthropic/claude-opus-4.7\", // in-family hot swap (identical cost to 4.8)\n \"anthropic/claude-sonnet-5\", // Sonnet-tier drop-down, near-Opus quality\n \"anthropic/claude-sonnet-4.6\",\n \"xai/grok-4.5\", // xAI flagship — 503-resistant, direct-xAI SKU\n \"moonshot/kimi-k3\", // Moonshot flagship, independent infra\n \"openai/gpt-5.6-terra\", // GPT-5.6 balanced tier — stable (Sol excluded: #202)\n \"openai/gpt-5.5\", // Prior OpenAI flagship — 1M+ ctx, native agent + computer use\n \"openai/gpt-5.4\", // Previous flagship (slow but stable, benchmarked at 6,213ms)\n \"openai/gpt-5.3-codex\",\n \"zai/glm-5.3\", // Z.AI flagship, 1M ctx\n \"deepseek/deepseek-v4-pro\", // strongest open-weight reasoner\n \"deepseek/deepseek-chat\", // Cheap, reliable\n \"nvidia/nemotron-3.5-lightning\", // NVIDIA free ultimate backstop\n ],\n },\n REASONING: {\n // Sonnet 5 promoted over Sonnet 4.6 (same price; reasoning band 0.98 for both,\n // plus Sonnet 5's tau2/BrowseComp trajectory evidence).\n primary: \"anthropic/claude-sonnet-5\", // $3/$15, 1M ctx, adaptive thinking\n fallback: [\n \"anthropic/claude-sonnet-4.6\", // in-family hot swap — same cost\n \"anthropic/claude-opus-5\", // Newest flagship Opus w/ adaptive thinking\n \"anthropic/claude-opus-4.8\", // Prior flagship Opus — identical cost to 5\n \"anthropic/claude-opus-4.7\", // Flagship Opus w/ adaptive thinking\n \"xai/grok-4.5\", // reasoning band 0.94\n \"deepseek/deepseek-v4-pro\", // reasoning band 0.95\n \"xai/grok-4.3\", // $1.50/$4 — xAI reasoning model\n \"openai/o4-mini\", // $1.10/$4.40\n \"openai/o3\", // $2/$8\n ],\n },\n },\n\n // Agentic tier configs - models that excel at multi-step autonomous tasks\n agenticTiers: {\n SIMPLE: {\n primary: \"openai/gpt-4o-mini\", // $0.15/$0.60 - best tool compliance at lowest cost\n fallback: [\n \"openai/gpt-5.6-luna\", // $0.20/$1.20 — lightweight agentic tier of GPT-5.6\n \"zai/glm-5.3-flash\", // $0.15/$0.50 — tool calls verified live 2026-08-27\n \"anthropic/claude-haiku-4.5\", // $1/$5\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n MEDIUM: {\n // Was moonshot/kimi-k2.7 (hidden 2026-08). GPT-5 Mini carries the\n // Terminal-Bench and tau2 trajectory evidence in portfolio.ts.\n primary: \"openai/gpt-5-mini\", // $0.25/$2 — 4/7 Terminal-Bench, 5/6 tau2 airline\n fallback: [\n \"google/gemini-3.5-flash\", // $1.50/$9 — tool_agent band 0.88\n \"zai/glm-5.3-flash\", // $0.15/$0.50 — tools verified\n \"openai/gpt-5.6-terra\", // $2/$12\n \"openai/gpt-4o-mini\", // $0.15/$0.60 — reliable tool calling\n \"anthropic/claude-haiku-4.5\", // $1/$5\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n \"moonshot/kimi-k3\", // $3/$15 — tool_agent band 0.85\n ],\n },\n COMPLEX: {\n // Sonnet 5 promoted over Sonnet 4.6: tau2 airline + retail reward 1.0,\n // Terminal-Bench safety band lead (portfolio.ts).\n primary: \"anthropic/claude-sonnet-5\", // $3/$15 — best agentic quality per trajectory evidence\n // Fallback chain de-Gemini'd 2026-04-22: Gemini's \"high demand\" 503s\n // correlate with Anthropic outages (everyone falls back together).\n // Prefer 503-resistant providers first.\n fallback: [\n \"anthropic/claude-sonnet-4.6\", // in-family hot swap — same cost\n \"anthropic/claude-opus-5\", // Newest flagship Opus — in-family hot swap\n \"anthropic/claude-opus-4.8\", // Prior flagship Opus — identical cost to 5\n \"anthropic/claude-opus-4.7\", // Flagship Opus — in-family hot swap\n \"xai/grok-4.5\", // xAI flagship — strong tool use, independent infra\n \"moonshot/kimi-k3\", // Moonshot flagship — independent infra\n \"openai/gpt-5.6-terra\", // GPT-5.6 balanced tier — stable (Sol excluded: #202)\n \"openai/gpt-5.5\", // Prior flagship — native agent + computer use (exactly the agentic-tier use case)\n \"openai/gpt-5.4\", // Previous flagship — reliable\n \"openai/gpt-5.3-codex\", // code_agent lead\n \"zai/glm-5.3\", // long-horizon coding\n \"deepseek/deepseek-v4-pro\", // retail high-risk 3/3\n \"deepseek/deepseek-chat\", // cheap, reliable\n \"nvidia/nemotron-3.5-lightning\", // NVIDIA free ultimate backstop\n ],\n },\n REASONING: {\n primary: \"anthropic/claude-sonnet-5\", // $3/$15 — strong tool use + adaptive thinking\n fallback: [\n \"anthropic/claude-sonnet-4.6\", // in-family hot swap — same cost\n \"anthropic/claude-opus-5\", // Newest flagship Opus w/ adaptive thinking\n \"anthropic/claude-opus-4.8\", // Prior flagship Opus — identical cost to 5\n \"anthropic/claude-opus-4.7\", // Flagship Opus w/ adaptive thinking\n \"xai/grok-4.5\", // reasoning band 0.94\n \"deepseek/deepseek-v4-pro\", // reasoning band 0.95\n \"deepseek/deepseek-reasoner\", // $0.14/$0.28\n ],\n },\n },\n\n // Time-windowed promotions — auto-applied when active, ignored when expired.\n // The GLM-5.1 launch promo (2026-04-01 → 2026-05-01) was the last entry and\n // has expired; the list is kept empty so the mechanism stays wired.\n promotions: [],\n\n overrides: {\n maxTokensForceComplex: 100_000,\n structuredOutputMinTier: \"MEDIUM\",\n ambiguousDefaultTier: \"MEDIUM\",\n // agenticMode left undefined → auto-detect via tools/agenticScore.\n // Set to `true` to force agentic tiers; `false` to disable them entirely.\n },\n};\n","/**\n * Smart Router Entry Point\n *\n * Classifies requests and routes to the cheapest capable model.\n * Delegates to pluggable RouterStrategy (default: RulesStrategy, <1ms).\n */\n\nimport type { RoutingDecision, RouterOptions } from \"./types.js\";\nimport { getStrategy, registerStrategy } from \"./strategy.js\";\nimport { PortfolioStrategy } from \"./portfolio.js\";\n\n// Register here instead of strategy.ts so PortfolioStrategy can reuse the\n// stable RulesStrategy without introducing a module cycle.\nregisterStrategy(new PortfolioStrategy());\n\n/**\n * Route a request to the cheapest capable model.\n * Delegates to the configured strategy (PortfolioStrategy by default).\n */\nexport function route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n): RoutingDecision {\n const strategy = getStrategy(options.config.strategy ?? \"portfolio\");\n return strategy.route(prompt, systemPrompt, maxOutputTokens, options);\n}\n\nexport { getStrategy, registerStrategy, applyUnavailableModels } from \"./strategy.js\";\nexport { RulesStrategy } from \"./strategy.js\";\nexport { PortfolioStrategy } from \"./portfolio.js\";\nexport { classifyByRules } from \"./rules.js\";\nexport { inferToolRequirement } from \"./tool-intent.js\";\nexport {\n getFallbackChain,\n getFallbackChainFiltered,\n filterByToolCalling,\n filterByVision,\n filterByExcludeList,\n filterCandidatesByCapacity,\n calculateModelCost,\n} from \"./selector.js\";\nexport { DEFAULT_ROUTING_CONFIG } from \"./config.js\";\nexport { DEFAULT_MODEL_CAPABILITIES } from \"./model-capabilities.js\";\nexport { LIVE_MODEL_PROFILES, HISTORICAL_MODEL_PROFILES } from \"./model-profiles.js\";\nexport type {\n RoutingDecision,\n Tier,\n TaskType,\n RoutingConfig,\n RouterOptions,\n RouterStrategy,\n} from \"./types.js\";\nexport type { ModelPricing } from \"./selector.js\";\nexport type { ModelCapabilities } from \"./model-capabilities.js\";\nexport type { ModelPerformanceProfile } from \"./model-profiles.js\";\n"],"mappings":"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AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA;AAAA,MAEd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,IAGA,iBAAiB;AAAA;AAAA,MAEf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,wBAAwB;AAAA;AAAA,MAEtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;AAAA,IAIA,qBAAqB;AAAA;AAAA,MAEnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA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","names":["confidence","decision","model"]} \ No newline at end of file +{"version":3,"sources":["../rules.ts","../selector.ts","../strategy.ts","../model-capabilities.ts","../model-profiles.generated.json","../model-profiles.ts","../tool-intent.ts","../portfolio.ts","../config.ts","../index.ts"],"sourcesContent":["/**\n * Rule-Based Classifier (v2 — Weighted Scoring)\n *\n * Scores a request across 15 weighted dimensions and maps the aggregate\n * score to a tier using configurable boundaries. Confidence is calibrated\n * via sigmoid — low confidence triggers the fallback classifier.\n *\n * Handles 70-80% of requests in < 1ms with zero cost.\n */\n\nimport type { Tier, ScoringResult, ScoringConfig } from \"./types.js\";\n\ntype DimensionScore = { name: string; score: number; signal: string | null };\n\n// ─── Dimension Scorers ───\n// Each returns a score in [-1, 1] and an optional signal string.\n\nfunction scoreTokenCount(\n estimatedTokens: number,\n thresholds: { simple: number; complex: number },\n): DimensionScore {\n if (estimatedTokens < thresholds.simple) {\n return { name: \"tokenCount\", score: -1.0, signal: `short (${estimatedTokens} tokens)` };\n }\n if (estimatedTokens > thresholds.complex) {\n return { name: \"tokenCount\", score: 1.0, signal: `long (${estimatedTokens} tokens)` };\n }\n return { name: \"tokenCount\", score: 0, signal: null };\n}\n\nfunction scoreKeywordMatch(\n text: string,\n keywords: string[],\n name: string,\n signalLabel: string,\n thresholds: { low: number; high: number },\n scores: { none: number; low: number; high: number },\n): DimensionScore {\n const matches = keywords.filter((kw) => text.includes(kw.toLowerCase()));\n if (matches.length >= thresholds.high) {\n return {\n name,\n score: scores.high,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n if (matches.length >= thresholds.low) {\n return {\n name,\n score: scores.low,\n signal: `${signalLabel} (${matches.slice(0, 3).join(\", \")})`,\n };\n }\n return { name, score: scores.none, signal: null };\n}\n\nfunction scoreMultiStep(text: string): DimensionScore {\n const patterns = [/first.*then/i, /step \\d/i, /\\d\\.\\s/];\n const hits = patterns.filter((p) => p.test(text));\n if (hits.length > 0) {\n return { name: \"multiStepPatterns\", score: 0.5, signal: \"multi-step\" };\n }\n return { name: \"multiStepPatterns\", score: 0, signal: null };\n}\n\nfunction scoreQuestionComplexity(prompt: string): DimensionScore {\n const count = (prompt.match(/\\?/g) || []).length;\n if (count > 3) {\n return { name: \"questionComplexity\", score: 0.5, signal: `${count} questions` };\n }\n return { name: \"questionComplexity\", score: 0, signal: null };\n}\n\n/**\n * Score agentic task indicators.\n * Returns agenticScore (0-1) based on keyword matches:\n * - 4+ matches = 1.0 (high agentic)\n * - 3 matches = 0.6 (moderate agentic, triggers auto-agentic mode)\n * - 1-2 matches = 0.2 (low agentic)\n *\n * Thresholds raised because common keywords were pruned from the list.\n */\nfunction scoreAgenticTask(\n text: string,\n keywords: string[],\n): { dimensionScore: DimensionScore; agenticScore: number } {\n let matchCount = 0;\n const signals: string[] = [];\n\n for (const keyword of keywords) {\n if (text.includes(keyword.toLowerCase())) {\n matchCount++;\n if (signals.length < 3) {\n signals.push(keyword);\n }\n }\n }\n\n // Threshold-based scoring (raised thresholds after keyword pruning)\n if (matchCount >= 4) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 1.0,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 1.0,\n };\n } else if (matchCount >= 3) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.6,\n signal: `agentic (${signals.join(\", \")})`,\n },\n agenticScore: 0.6,\n };\n } else if (matchCount >= 1) {\n return {\n dimensionScore: {\n name: \"agenticTask\",\n score: 0.2,\n signal: `agentic-light (${signals.join(\", \")})`,\n },\n agenticScore: 0.2,\n };\n }\n\n return {\n dimensionScore: { name: \"agenticTask\", score: 0, signal: null },\n agenticScore: 0,\n };\n}\n\n// ─── Main Classifier ───\n\nexport function classifyByRules(\n prompt: string,\n systemPrompt: string | undefined,\n estimatedTokens: number,\n config: ScoringConfig,\n): ScoringResult {\n // Score against user prompt only — system prompts contain boilerplate keywords\n // (tool definitions, skill descriptions, behavioral rules) that dominate scoring\n // and make every request score identically. See GitHub issue #50.\n const userText = prompt.toLowerCase();\n\n // Score the base dimensions against user text only; the agentic dimension is\n // appended below, so the scored total is one more than this list.\n const dimensions: DimensionScore[] = [\n // Token count uses total estimated tokens (system + user) — context size matters for model selection\n scoreTokenCount(estimatedTokens, config.tokenCountThresholds),\n scoreKeywordMatch(\n userText,\n config.codeKeywords,\n \"codePresence\",\n \"code\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.reasoningKeywords,\n \"reasoningMarkers\",\n \"reasoning\",\n { low: 1, high: 2 },\n { none: 0, low: 0.7, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.technicalKeywords,\n \"technicalTerms\",\n \"technical\",\n { low: 2, high: 4 },\n { none: 0, low: 0.5, high: 1.0 },\n ),\n scoreKeywordMatch(\n userText,\n config.creativeKeywords,\n \"creativeMarkers\",\n \"creative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.simpleKeywords,\n \"simpleIndicators\",\n \"simple\",\n { low: 1, high: 2 },\n { none: 0, low: -1.0, high: -1.0 },\n ),\n scoreMultiStep(userText),\n scoreQuestionComplexity(prompt),\n\n // 6 new dimensions\n scoreKeywordMatch(\n userText,\n config.imperativeVerbs,\n \"imperativeVerbs\",\n \"imperative\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.constraintIndicators,\n \"constraintCount\",\n \"constraints\",\n { low: 1, high: 3 },\n { none: 0, low: 0.3, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.outputFormatKeywords,\n \"outputFormat\",\n \"format\",\n { low: 1, high: 2 },\n { none: 0, low: 0.4, high: 0.7 },\n ),\n scoreKeywordMatch(\n userText,\n config.referenceKeywords,\n \"referenceComplexity\",\n \"references\",\n { low: 1, high: 2 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.negationKeywords,\n \"negationComplexity\",\n \"negation\",\n { low: 2, high: 3 },\n { none: 0, low: 0.3, high: 0.5 },\n ),\n scoreKeywordMatch(\n userText,\n config.domainSpecificKeywords,\n \"domainSpecificity\",\n \"domain-specific\",\n { low: 1, high: 2 },\n { none: 0, low: 0.5, high: 0.8 },\n ),\n ];\n\n // Score agentic task indicators — user prompt only\n // System prompt describes assistant behavior, not user's intent.\n // e.g. a coding assistant system prompt with \"edit files\" / \"fix bugs\" should NOT\n // force every request into agentic mode.\n const agenticResult = scoreAgenticTask(userText, config.agenticTaskKeywords);\n dimensions.push(agenticResult.dimensionScore);\n const agenticScore = agenticResult.agenticScore;\n\n // Collect signals\n const signals = dimensions.filter((d) => d.signal !== null).map((d) => d.signal!);\n\n // Compute weighted score\n const weights = config.dimensionWeights;\n let weightedScore = 0;\n for (const d of dimensions) {\n const w = weights[d.name] ?? 0;\n weightedScore += d.score * w;\n }\n\n // Count reasoning markers for override — only check USER prompt, not system prompt\n // This prevents system prompts with \"step by step\" from triggering REASONING for simple queries\n const reasoningMatches = config.reasoningKeywords.filter((kw) =>\n userText.includes(kw.toLowerCase()),\n );\n\n // Direct reasoning override: 2+ reasoning markers = high confidence REASONING\n if (reasoningMatches.length >= 2) {\n const confidence = calibrateConfidence(\n Math.max(weightedScore, 0.3), // ensure positive for confidence calc\n config.confidenceSteepness,\n );\n return {\n score: weightedScore,\n tier: \"REASONING\",\n confidence: Math.max(confidence, 0.85),\n signals,\n agenticScore,\n dimensions,\n };\n }\n\n // Map weighted score to tier using boundaries\n const { simpleMedium, mediumComplex, complexReasoning } = config.tierBoundaries;\n let tier: Tier;\n let distanceFromBoundary: number;\n\n if (weightedScore < simpleMedium) {\n tier = \"SIMPLE\";\n distanceFromBoundary = simpleMedium - weightedScore;\n } else if (weightedScore < mediumComplex) {\n tier = \"MEDIUM\";\n distanceFromBoundary = Math.min(weightedScore - simpleMedium, mediumComplex - weightedScore);\n } else if (weightedScore < complexReasoning) {\n tier = \"COMPLEX\";\n distanceFromBoundary = Math.min(\n weightedScore - mediumComplex,\n complexReasoning - weightedScore,\n );\n } else {\n tier = \"REASONING\";\n distanceFromBoundary = weightedScore - complexReasoning;\n }\n\n // Calibrate confidence via sigmoid of distance from nearest boundary\n const confidence = calibrateConfidence(distanceFromBoundary, config.confidenceSteepness);\n\n // If confidence is below threshold → ambiguous\n if (confidence < config.confidenceThreshold) {\n return { score: weightedScore, tier: null, confidence, signals, agenticScore, dimensions };\n }\n\n return { score: weightedScore, tier, confidence, signals, agenticScore, dimensions };\n}\n\n/**\n * Sigmoid confidence calibration.\n * Maps distance from tier boundary to [0.5, 1.0] confidence range.\n */\nfunction calibrateConfidence(distance: number, steepness: number): number {\n return 1 / (1 + Math.exp(-steepness * distance));\n}\n","/**\n * Tier → Model Selection\n *\n * Maps a classification tier to the cheapest capable model.\n * Builds RoutingDecision metadata with cost estimates and savings.\n */\n\nimport type { Tier, TierConfig, RoutingDecision } from \"./types.js\";\n\nexport type ModelPricing = {\n inputPrice: number; // per 1M tokens\n outputPrice: number; // per 1M tokens\n /** Active promo flat price per request (overrides token-based pricing when set) */\n flatPrice?: number;\n};\n\n// The savings baseline is a price anchor, not \"the current flagship\" — it is\n// deliberately NOT bumped every time a new Opus ships. Opus 4.7, 4.8 and 5 all\n// bill $5/$25, so moving it would change no reported number while breaking\n// comparability with historical journal entries. Only move it if the Opus tier\n// itself is repriced.\nconst BASELINE_MODEL_ID = \"anthropic/claude-opus-4.7\";\n\n// Hardcoded fallback: Claude Opus 4.7 pricing (per 1M tokens)\n// Used when baseline model not found in dynamic pricing map\nconst BASELINE_INPUT_PRICE = 5.0;\nconst BASELINE_OUTPUT_PRICE = 25.0;\n\n/**\n * Select the primary model for a tier and build the RoutingDecision.\n *\n * Cost contract: the estimates here are raw token economics — no server\n * margin, no minimum-payment floor. `calculateModelCost` below applies both\n * to match the actual x402 charge, and hosts that display money (ClawRouter's\n * proxy does) recompute through it rather than reading these fields. Folding\n * the margin in here would double-apply it in every such host.\n */\nexport function selectModel(\n tier: Tier,\n confidence: number,\n method: \"rules\" | \"llm\" | \"portfolio\",\n reasoning: string,\n tierConfigs: Record,\n modelPricing: Map,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n agenticScore?: number,\n): RoutingDecision {\n const tierConfig = tierConfigs[tier];\n const model = tierConfig.primary;\n const pricing = modelPricing.get(model);\n\n let costEstimate: number;\n if (pricing?.flatPrice !== undefined) {\n costEstimate = pricing.flatPrice;\n } else {\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n costEstimate =\n (estimatedInputTokens / 1_000_000) * inputPrice + (maxOutputTokens / 1_000_000) * outputPrice;\n }\n\n // Baseline: what the anchor Opus tier would cost (see BASELINE_MODEL_ID)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return {\n model,\n tier,\n confidence,\n method,\n reasoning,\n costEstimate,\n baselineCost,\n savings,\n ...(agenticScore !== undefined && { agenticScore }),\n };\n}\n\n/**\n * Get the ordered fallback chain for a tier: [primary, ...fallbacks].\n */\nexport function getFallbackChain(tier: Tier, tierConfigs: Record): string[] {\n const config = tierConfigs[tier];\n return [config.primary, ...config.fallback];\n}\n\n/**\n * Calculate charge-accurate cost fields for a specific model (server margin\n * and minimum-payment floor included — see the cost contract on selectModel).\n * Hosts call this to display money and to recost a decision after a fallback.\n */\n// Server-side margin applied to all x402 payments (must match blockrun server's MARGIN_PERCENT)\nconst SERVER_MARGIN_PERCENT = 5;\n// Minimum payment enforced by CDP Facilitator (must match blockrun server's MIN_PAYMENT_USD)\nconst MIN_PAYMENT_USD = 0.001;\n\nexport function calculateModelCost(\n model: string,\n modelPricing: Map,\n estimatedInputTokens: number,\n maxOutputTokens: number,\n routingProfile?: \"free\" | \"eco\" | \"auto\" | \"premium\",\n): { costEstimate: number; baselineCost: number; savings: number } {\n const pricing = modelPricing.get(model);\n\n let costEstimate: number;\n if (pricing?.flatPrice !== undefined) {\n // Active promo: fixed cost per request\n costEstimate = Math.max(pricing.flatPrice * (1 + SERVER_MARGIN_PERCENT / 100), MIN_PAYMENT_USD);\n } else {\n // Defensive: guard against undefined price fields (not just undefined pricing)\n const inputPrice = pricing?.inputPrice ?? 0;\n const outputPrice = pricing?.outputPrice ?? 0;\n const inputCost = (estimatedInputTokens / 1_000_000) * inputPrice;\n const outputCost = (maxOutputTokens / 1_000_000) * outputPrice;\n // Include server margin + minimum payment to match actual x402 charge\n costEstimate = Math.max(\n (inputCost + outputCost) * (1 + SERVER_MARGIN_PERCENT / 100),\n MIN_PAYMENT_USD,\n );\n }\n\n // Baseline: what the anchor Opus tier would cost (see BASELINE_MODEL_ID)\n const opusPricing = modelPricing.get(BASELINE_MODEL_ID);\n const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;\n const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;\n const baselineInput = (estimatedInputTokens / 1_000_000) * opusInputPrice;\n const baselineOutput = (maxOutputTokens / 1_000_000) * opusOutputPrice;\n const baselineCost = baselineInput + baselineOutput;\n\n // Premium profile doesn't calculate savings (it's about quality, not cost)\n const savings =\n routingProfile === \"premium\"\n ? 0\n : baselineCost > 0\n ? Math.max(0, (baselineCost - costEstimate) / baselineCost)\n : 0;\n\n return { costEstimate, baselineCost, savings };\n}\n\n/**\n * Filter a model list to only those that support tool calling.\n * When hasTools is false, returns the list unchanged.\n * When all models lack tool calling support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByToolCalling(\n models: string[],\n hasTools: boolean,\n supportsToolCalling: (modelId: string) => boolean,\n): string[] {\n if (!hasTools) return models;\n const filtered = models.filter(supportsToolCalling);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Filter a model list to only those that support vision (image inputs).\n * When hasVision is false, returns the list unchanged.\n * When all models lack vision support, returns the full list as a fallback\n * (better to let the API error than produce an empty chain).\n */\nexport function filterByVision(\n models: string[],\n hasVision: boolean,\n supportsVision: (modelId: string) => boolean,\n): string[] {\n if (!hasVision) return models;\n const filtered = models.filter(supportsVision);\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Filter a model list to remove user-excluded models.\n * When all models are excluded, returns the full list as a fallback\n * (same safety pattern as filterByToolCalling/filterByVision).\n */\nexport function filterByExcludeList(models: string[], excludeList: Set): string[] {\n if (excludeList.size === 0) return models;\n const filtered = models.filter((m) => !excludeList.has(m));\n return filtered.length > 0 ? filtered : models;\n}\n\n/**\n * Get the fallback chain filtered by context length.\n * Only returns models that can handle the estimated total context.\n *\n * @param tier - The tier to get fallback chain for\n * @param tierConfigs - Tier configurations\n * @param estimatedTotalTokens - Estimated total context (input + output)\n * @param getContextWindow - Function to get context window for a model ID\n * @returns Filtered list of models that can handle the context\n */\nexport function getFallbackChainFiltered(\n tier: Tier,\n tierConfigs: Record,\n estimatedTotalTokens: number,\n getContextWindow: (modelId: string) => number | undefined,\n): string[] {\n const fullChain = getFallbackChain(tier, tierConfigs);\n\n // Filter to models that can handle the context\n const filtered = fullChain.filter((modelId) => {\n const contextWindow = getContextWindow(modelId);\n if (contextWindow === undefined) {\n // Unknown model - include it (let API reject if needed)\n return true;\n }\n // Add 10% buffer for safety\n return contextWindow >= estimatedTotalTokens * 1.1;\n });\n\n // If all models filtered out, return the original chain\n // (let the API error out - better than no options)\n if (filtered.length === 0) {\n return fullChain;\n }\n\n return filtered;\n}\n\n/**\n * Filter an already-ranked candidate list by total context and requested output.\n * Unlike the legacy tier helper, this supports the V3 portfolio order.\n */\nexport function filterCandidatesByCapacity(\n models: string[],\n estimatedInputTokens: number,\n requestedOutputTokens: number,\n getCapabilities: (modelId: string) => { contextWindow: number; maxOutput: number } | undefined,\n): string[] {\n const filtered = models.filter((modelId) => {\n const capabilities = getCapabilities(modelId);\n if (!capabilities) return true;\n return (\n capabilities.contextWindow >= (estimatedInputTokens + requestedOutputTokens) * 1.1 &&\n capabilities.maxOutput >= requestedOutputTokens\n );\n });\n return filtered;\n}\n","/**\n * Router Strategy Registry\n *\n * Pluggable strategy system for request routing.\n * Default: RulesStrategy — identical to the original inline route() logic, <1ms.\n */\n\nimport type {\n Tier,\n TierConfig,\n Promotion,\n RoutingDecision,\n RouterStrategy,\n RouterOptions,\n} from \"./types.js\";\nimport { classifyByRules } from \"./rules.js\";\nimport { selectModel } from \"./selector.js\";\n\n/**\n * Apply active time-windowed promotions to tier configs.\n * Returns a new tierConfigs object with promotion overrides merged in.\n * Expired or not-yet-active promotions are ignored.\n */\nfunction applyPromotions(\n tierConfigs: Record,\n promotions: Promotion[] | undefined,\n profile: \"auto\" | \"eco\" | \"premium\" | \"agentic\",\n now: Date = new Date(),\n): Record {\n if (!promotions || promotions.length === 0) return tierConfigs;\n\n let result = tierConfigs;\n for (const promo of promotions) {\n // Check time window\n const start = new Date(promo.startDate);\n const end = new Date(promo.endDate);\n if (now < start || now >= end) continue;\n\n // Check profile filter\n if (promo.profiles && !promo.profiles.includes(profile)) continue;\n\n // Shallow-clone on first mutation\n if (result === tierConfigs) {\n result = { ...tierConfigs };\n for (const t of Object.keys(result) as Tier[]) {\n result[t] = { ...result[t] };\n }\n }\n\n // Merge overrides\n for (const [tier, override] of Object.entries(promo.tierOverrides) as [\n Tier,\n Partial,\n ][]) {\n if (!result[tier]) continue;\n if (override.primary) result[tier].primary = override.primary;\n if (override.fallback) result[tier].fallback = override.fallback;\n }\n }\n\n return result;\n}\n\n/**\n * Remove host-declared-dead models from every tier chain, promoting the first\n * surviving rung to primary. A tier whose chain is entirely dead keeps its\n * original config — the router has nothing live to offer there, and inventing\n * a model would hide the outage from the host that reported it.\n */\nexport function applyUnavailableModels(\n tierConfigs: Record,\n unavailableModels: readonly string[] | undefined,\n): Record {\n if (!unavailableModels || unavailableModels.length === 0) return tierConfigs;\n const dead = new Set(unavailableModels);\n let result = tierConfigs;\n for (const tier of Object.keys(tierConfigs) as Tier[]) {\n const config = tierConfigs[tier];\n const alive = [config.primary, ...config.fallback].filter((model) => !dead.has(model));\n if (alive.length === 0 || (alive[0] === config.primary && alive.length === config.fallback.length + 1)) {\n continue;\n }\n if (result === tierConfigs) result = { ...tierConfigs };\n result[tier] = { primary: alive[0], fallback: alive.slice(1) };\n }\n return result;\n}\n\n/**\n * Rules-based routing strategy.\n * Extracted from the original route() in index.ts — logic is identical.\n * Attaches tierConfigs and profile to the decision for downstream use.\n */\nexport class RulesStrategy implements RouterStrategy {\n readonly name = \"rules\";\n\n route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n ): RoutingDecision {\n const { config, modelPricing } = options;\n\n // Estimate input tokens (~4 chars per token)\n const fullText = `${systemPrompt ?? \"\"} ${prompt}`;\n const estimatedTokens = Math.ceil(fullText.length / 4);\n const scanLimit = Math.max(1, Math.min(8_000, config.classifier.promptTruncationChars));\n const sample = (value: string): string => {\n if (value.length <= scanLimit) return value;\n const prefixLength = Math.ceil(scanLimit / 2);\n return `${value.slice(0, prefixLength)}\\n${value.slice(-(scanLimit - prefixLength))}`;\n };\n const scannedPrompt = sample(prompt);\n const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : undefined;\n\n // --- Rule-based classification (runs first to get agenticScore) ---\n const ruleResult = classifyByRules(\n scannedPrompt,\n scannedSystemPrompt,\n estimatedTokens,\n config.scoring,\n );\n\n // --- Select tier configs based on routing profile ---\n const { routingProfile } = options;\n let tierConfigs: Record;\n let profileSuffix: string;\n let profile: RoutingDecision[\"profile\"];\n\n if (routingProfile === \"eco\") {\n // `ecoTiers: null` explicitly disables the special eco tier set while\n // keeping eco routing semantics. Fall back to regular tiers instead of\n // dropping into auto routing (which could select agentic tiers).\n tierConfigs = config.ecoTiers ?? config.tiers;\n profileSuffix = config.ecoTiers ? \" | eco\" : \" | eco (default tiers)\";\n profile = \"eco\";\n } else if (routingProfile === \"premium\") {\n // `premiumTiers: null` disables the premium-specific tier set but the\n // request is still a premium-profile request, so use regular tiers while\n // preserving premium metadata/cost semantics.\n tierConfigs = config.premiumTiers ?? config.tiers;\n profileSuffix = config.premiumTiers ? \" | premium\" : \" | premium (default tiers)\";\n profile = \"premium\";\n } else {\n // Auto profile (or undefined): intelligent routing with agentic detection.\n //\n // `agenticMode` semantics:\n // - `true` → force agentic tiers (ignore heuristics)\n // - `false` → disable agentic tiers entirely (even if tools are present)\n // - `undefined` → auto-detect via heuristics (tools present OR high agenticScore)\n const agenticScore = ruleResult.agenticScore ?? 0;\n const isAutoAgentic = agenticScore >= 0.5;\n const agenticModeSetting = config.overrides.agenticMode;\n const hasToolsInRequest = options.requiresTools ?? options.hasTools ?? false;\n let useAgenticTiers: boolean;\n if (agenticModeSetting === false) {\n // Explicitly disabled — never use agentic tiers\n useAgenticTiers = false;\n } else if (agenticModeSetting === true) {\n // Explicitly enabled — use agentic tiers if available\n useAgenticTiers = config.agenticTiers != null;\n } else {\n // Auto-detect\n useAgenticTiers = (hasToolsInRequest || isAutoAgentic) && config.agenticTiers != null;\n }\n tierConfigs = useAgenticTiers ? config.agenticTiers! : config.tiers;\n profileSuffix = useAgenticTiers ? ` | agentic${hasToolsInRequest ? \" (tools)\" : \"\"}` : \"\";\n profile = useAgenticTiers ? \"agentic\" : \"auto\";\n }\n\n // Apply time-windowed promotions\n tierConfigs = applyPromotions(tierConfigs, config.promotions, profile!, options.now);\n\n // Hard-remove models the host has observed dead at the gateway. After\n // promotions, so a promo cannot resurrect a rung the host just killed.\n tierConfigs = applyUnavailableModels(tierConfigs, options.unavailableModels);\n\n const agenticScoreValue = ruleResult.agenticScore;\n\n // --- Override: large context → force COMPLEX ---\n if (estimatedTokens > config.overrides.maxTokensForceComplex) {\n const decision = selectModel(\n \"COMPLEX\",\n 0.95,\n \"rules\",\n `Input exceeds ${config.overrides.maxTokensForceComplex} tokens${profileSuffix}`,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n return { ...decision, tierConfigs, profile };\n }\n\n // Structured output detection\n const hasStructuredOutput =\n options.requiresStructuredOutput === true ||\n (scannedSystemPrompt ? /json|structured|schema/i.test(scannedSystemPrompt) : false);\n\n let tier: Tier;\n let confidence: number;\n const method: \"rules\" | \"llm\" = \"rules\";\n let reasoning = `score=${ruleResult.score.toFixed(2)} | ${ruleResult.signals.join(\", \")}`;\n\n if (ruleResult.tier !== null) {\n tier = ruleResult.tier;\n confidence = ruleResult.confidence;\n } else {\n // Ambiguous — default to configurable tier (no external API call)\n tier = config.overrides.ambiguousDefaultTier;\n confidence = 0.5;\n reasoning += ` | ambiguous -> default: ${tier}`;\n }\n\n // Apply structured output minimum tier\n if (hasStructuredOutput) {\n const tierRank: Record = { SIMPLE: 0, MEDIUM: 1, COMPLEX: 2, REASONING: 3 };\n const minTier = config.overrides.structuredOutputMinTier;\n if (tierRank[tier] < tierRank[minTier]) {\n reasoning += ` | upgraded to ${minTier} (structured output)`;\n tier = minTier;\n }\n }\n\n // Add routing profile suffix to reasoning\n reasoning += profileSuffix;\n\n const decision = selectModel(\n tier,\n confidence,\n method,\n reasoning,\n tierConfigs,\n modelPricing,\n estimatedTokens,\n maxOutputTokens,\n routingProfile,\n agenticScoreValue,\n );\n return { ...decision, tierConfigs, profile };\n }\n}\n\n// --- Strategy Registry ---\n\nconst registry = new Map();\nregistry.set(\"rules\", new RulesStrategy());\n\nexport function getStrategy(name: string): RouterStrategy {\n const strategy = registry.get(name);\n if (!strategy) {\n throw new Error(`Unknown routing strategy: ${name}`);\n }\n return strategy;\n}\n\nexport function registerStrategy(strategy: RouterStrategy): void {\n registry.set(strategy.name, strategy);\n}\n","/**\n * Model capabilities used for hard routing constraints.\n *\n * Hosts may inject fresher values through RouterOptions.modelCapabilities.\n * Keeping a small built-in snapshot makes the core safe and useful when a\n * product catalog is temporarily unavailable, without importing product code.\n *\n * GENERATED by scripts/sync-model-capabilities.mjs from the public catalog\n * (GET https://blockrun.ai/api/v1/models) on 2026-08-31; supportsTools comes\n * from a live function-calling probe (scripts/probe-tools.json). Regenerate\n * rather than editing by hand — a hand edit is overwritten on the next sync.\n */\nexport type ModelCapabilities = {\n contextWindow: number;\n maxOutputTokens: number;\n supportsTools: boolean;\n supportsVision: boolean;\n};\n\nexport const DEFAULT_MODEL_CAPABILITIES: Readonly> =\n Object.freeze({\n \"anthropic/claude-fable-5\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-haiku-4.5\": { // override: The public catalog's `categories` omit \"vision\" for this Anthropic model even though the gateway accepts image input for it (the prior hand-maintained snapshot had it, and Anthropic's model card lists it). Without this the vision filter would silently drop it — reported against the catalog; remove once the categories carry vision.\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-4.5\": {\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-4.7\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-4.8\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-opus-5\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-sonnet-4.5\": {\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-sonnet-4.6\": { // override: The public catalog's `categories` omit \"vision\" for this Anthropic model even though the gateway accepts image input for it (the prior hand-maintained snapshot had it, and Anthropic's model card lists it). Without this the vision filter would silently drop it — reported against the catalog; remove once the categories carry vision.\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"anthropic/claude-sonnet-5\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"cohere/north-mini-code\": { // supportsTools: not probed — fails closed\n contextWindow: 256_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"deepseek/deepseek-chat\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"deepseek/deepseek-reasoner\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"deepseek/deepseek-v4-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-2.5-flash\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-2.5-flash-lite\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-2.5-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3-flash-preview\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3.1-flash-lite\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-3.1-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3.5-flash\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"google/gemini-3.5-flash-lite\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"google/gemini-3.6-flash\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"minimax/minimax-m2.7\": {\n contextWindow: 204_800,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: false,\n },\n \"minimax/minimax-m3\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"moonshot/kimi-k3\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: true,\n },\n \"nvidia/llama-3.2-11b-vision\": { // supportsTools: not probed — fails closed\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: true,\n },\n \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning\": { // override: The catalog tags this model \"vision\", but a correctly sized probe does not hold up (ClawRouter, 2026-08-31): a 64x64 solid-red PNG was named correctly 1 of 4 times on Base, and on Solana the image was silently dropped and a text model answered \"white\". An HTTP 200 with a confident wrong answer gives the caller nothing to branch on, so image turns must not be routed here. It is ecoTiers.SIMPLE.fallback[0] since nemotron-3-nano-30b was delisted (2026-09-08); remove once a probe of this size comes back right on both chains.\n contextWindow: 256_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"nvidia/nemotron-3-ultra-550b\": { // supportsTools: not probed — fails closed\n contextWindow: 1_000_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"nvidia/nemotron-3.5-lightning\": { // supportsTools: not probed — fails closed\n contextWindow: 1_000_000,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"openai/chat-latest\": {\n contextWindow: 128_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-4.1\": {\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-4.1-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-4.1-nano\": {\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-4o\": {\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-4o-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5-mini\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5.2\": {\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.2-pro\": { // supportsTools: not probed — fails closed\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.3-codex\": { // supportsTools: gateway unavailable at probe time — fails closed; override: 2026-08-29 probe: every request (6 plain + 3 tool attempts) returned a gateway 500, so the probe measured an incident, not the model. Codex's function calling is established by the 2026-07 Terminal-Bench / tau2 calibration trajectories in portfolio.ts. Hosts observing the 500s should drop it with RouterOptions.unavailableModels rather than this snapshot claiming the model cannot call tools.\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5.4\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.4-mini\": {\n contextWindow: 400_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.4-nano\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/gpt-5.4-pro\": { // supportsTools: not probed — fails closed\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.5\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.5-pro\": { // supportsTools: not probed — fails closed\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.6-luna\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-luna-pro\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: false,\n supportsVision: true,\n },\n \"openai/gpt-5.6-sol\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-sol-pro\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-terra\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/gpt-5.6-terra-pro\": {\n contextWindow: 1_050_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: true,\n },\n \"openai/o1\": {\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/o3\": {\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/o3-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"openai/o4-mini\": {\n contextWindow: 128_000,\n maxOutputTokens: 100_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"poolside/laguna-xs-2.1\": { // supportsTools: not probed — fails closed\n contextWindow: 131_072,\n maxOutputTokens: 16_384,\n supportsTools: false,\n supportsVision: false,\n },\n \"qwen/qwen3.7-flash\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"qwen/qwen3.7-max\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 65_536,\n supportsTools: true,\n supportsVision: false,\n },\n \"qwen/qwen3.7-plus\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"tencent/hy3\": {\n contextWindow: 262_144,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"xai/grok-4.3\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: true,\n },\n \"xai/grok-4.5\": {\n contextWindow: 500_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: true,\n },\n \"xai/grok-build-0.1\": {\n contextWindow: 256_000,\n maxOutputTokens: 16_384,\n supportsTools: true,\n supportsVision: false,\n },\n \"xiaomi/mimo-v2.5-pro\": {\n contextWindow: 1_048_576,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5-turbo\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.1\": {\n contextWindow: 200_000,\n maxOutputTokens: 128_000,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.2\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.3\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: false,\n },\n \"zai/glm-5.3-flash\": {\n contextWindow: 1_000_000,\n maxOutputTokens: 131_072,\n supportsTools: true,\n supportsVision: true,\n },\n });\n","{\n \"anthropic/claude-fable-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9298.5,\n \"p95LatencyMs\": 9873.4,\n \"outputTokensPerSecond\": 55.17,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-haiku-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3157.4,\n \"p95LatencyMs\": 3170.7,\n \"outputTokensPerSecond\": 162.16,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6497.7,\n \"p95LatencyMs\": 6953.7,\n \"outputTokensPerSecond\": 78.99,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-4.7\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5316.5,\n \"p95LatencyMs\": 6121.5,\n \"outputTokensPerSecond\": 97.34,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-4.8\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6216.1,\n \"p95LatencyMs\": 6847.7,\n \"outputTokensPerSecond\": 82.81,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-opus-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7309,\n \"p95LatencyMs\": 7745.2,\n \"outputTokensPerSecond\": 70.17,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-sonnet-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6330.4,\n \"p95LatencyMs\": 6631.6,\n \"outputTokensPerSecond\": 81.03,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-sonnet-4.6\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6508,\n \"p95LatencyMs\": 6698.3,\n \"outputTokensPerSecond\": 78.6,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"anthropic/claude-sonnet-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6165.4,\n \"p95LatencyMs\": 6582.9,\n \"outputTokensPerSecond\": 83.62,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"deepseek/deepseek-chat\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4351.4,\n \"p95LatencyMs\": 4543.7,\n \"outputTokensPerSecond\": 117.78,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"deepseek/deepseek-reasoner\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5201.2,\n \"p95LatencyMs\": 6079.6,\n \"outputTokensPerSecond\": 99.77,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"deepseek/deepseek-v4-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 8781.2,\n \"p95LatencyMs\": 9881.1,\n \"outputTokensPerSecond\": 58.98,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-2.5-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5416.4,\n \"p95LatencyMs\": 6442.8,\n \"outputTokensPerSecond\": 213.07,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-2.5-flash-lite\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5002.6,\n \"p95LatencyMs\": 5780.3,\n \"outputTokensPerSecond\": 408.43,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-2.5-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 28169.5,\n \"p95LatencyMs\": 29491.4,\n \"outputTokensPerSecond\": 147.3,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3-flash-preview\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4717.1,\n \"p95LatencyMs\": 5037.1,\n \"outputTokensPerSecond\": 198.71,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.1-flash-lite\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 2855.8,\n \"p95LatencyMs\": 3172.7,\n \"outputTokensPerSecond\": 286.91,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.1-pro\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 24194.1,\n \"p95LatencyMs\": 27269.6,\n \"outputTokensPerSecond\": 109.47,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.5-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5320.6,\n \"p95LatencyMs\": 5429.8,\n \"outputTokensPerSecond\": 226.21,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.5-flash-lite\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3515.8,\n \"p95LatencyMs\": 4363.4,\n \"outputTokensPerSecond\": 248.9,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"google/gemini-3.6-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 13020,\n \"p95LatencyMs\": 15383.1,\n \"outputTokensPerSecond\": 187.87,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"minimax/minimax-m2.7\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 8761.1,\n \"p95LatencyMs\": 10199.3,\n \"outputTokensPerSecond\": 59.18,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"minimax/minimax-m3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 11101.9,\n \"p95LatencyMs\": 26087.1,\n \"outputTokensPerSecond\": 101.12,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"moonshot/kimi-k3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 24498.9,\n \"p95LatencyMs\": 40365.3,\n \"outputTokensPerSecond\": 25.11,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"nvidia/mistral-nemotron\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7349.6,\n \"p95LatencyMs\": 9932.3,\n \"outputTokensPerSecond\": 79.48,\n \"errorRate\": 0.3333,\n \"samples\": 3\n },\n \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 9324.6,\n \"p95LatencyMs\": 12992,\n \"outputTokensPerSecond\": 64.96,\n \"errorRate\": 0.3333,\n \"samples\": 3\n },\n \"nvidia/nemotron-nano-12b-v2-vl\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5846.9,\n \"p95LatencyMs\": 5846.9,\n \"outputTokensPerSecond\": 87.57,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"nvidia/nemotron-nano-9b-v2\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5282.5,\n \"p95LatencyMs\": 5282.5,\n \"outputTokensPerSecond\": 96.92,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"nvidia/step-3.7-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4617.4,\n \"p95LatencyMs\": 5237.4,\n \"outputTokensPerSecond\": 112.92,\n \"errorRate\": 0.3333,\n \"samples\": 3\n },\n \"openai/chat-latest\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3690.9,\n \"p95LatencyMs\": 4344,\n \"outputTokensPerSecond\": 111.85,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4.1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3527.9,\n \"p95LatencyMs\": 3831.7,\n \"outputTokensPerSecond\": 141.27,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4.1-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4268.2,\n \"p95LatencyMs\": 5101.5,\n \"outputTokensPerSecond\": 103.42,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4.1-nano\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3088.3,\n \"p95LatencyMs\": 3369.2,\n \"outputTokensPerSecond\": 150.31,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4o\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 2995.2,\n \"p95LatencyMs\": 3174.2,\n \"outputTokensPerSecond\": 171.32,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-4o-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4751.5,\n \"p95LatencyMs\": 4930.4,\n \"outputTokensPerSecond\": 107.84,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4558.1,\n \"p95LatencyMs\": 5081.9,\n \"outputTokensPerSecond\": 113.25,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.2\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5436.6,\n \"p95LatencyMs\": 5928.8,\n \"outputTokensPerSecond\": 95.47,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.3-codex\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 15290.4,\n \"p95LatencyMs\": 15290.4,\n \"outputTokensPerSecond\": 33.49,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"openai/gpt-5.4\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5596,\n \"p95LatencyMs\": 5919.4,\n \"outputTokensPerSecond\": 91.67,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.4-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3377.8,\n \"p95LatencyMs\": 3646.8,\n \"outputTokensPerSecond\": 138.08,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.4-nano\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4040.4,\n \"p95LatencyMs\": 4205.9,\n \"outputTokensPerSecond\": 118.52,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6367.8,\n \"p95LatencyMs\": 7330.7,\n \"outputTokensPerSecond\": 81.29,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-luna\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6064.5,\n \"p95LatencyMs\": 7347.3,\n \"outputTokensPerSecond\": 87.93,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-luna-pro\": {\n \"measuredAt\": \"2026-08-29T16:59:54Z\",\n \"latencyMs\": 13914.9,\n \"p95LatencyMs\": 13914.9,\n \"outputTokensPerSecond\": 36.79,\n \"errorRate\": 0.6667,\n \"samples\": 3\n },\n \"openai/gpt-5.6-sol\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7720.2,\n \"p95LatencyMs\": 9108.2,\n \"outputTokensPerSecond\": 67.47,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-sol-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 11442.7,\n \"p95LatencyMs\": 13363.1,\n \"outputTokensPerSecond\": 148.75,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-terra\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4941,\n \"p95LatencyMs\": 5095.3,\n \"outputTokensPerSecond\": 103.69,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/gpt-5.6-terra-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3574.1,\n \"p95LatencyMs\": 4126.3,\n \"outputTokensPerSecond\": 133.59,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4324.9,\n \"p95LatencyMs\": 5838.1,\n \"outputTokensPerSecond\": 125.86,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 5463.4,\n \"p95LatencyMs\": 5613.1,\n \"outputTokensPerSecond\": 93.8,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o3-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 2912.7,\n \"p95LatencyMs\": 3092.1,\n \"outputTokensPerSecond\": 176.49,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"openai/o4-mini\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 4958.7,\n \"p95LatencyMs\": 5313,\n \"outputTokensPerSecond\": 103.81,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"qwen/qwen3.7-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 3385.5,\n \"p95LatencyMs\": 4042.7,\n \"outputTokensPerSecond\": 153.94,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"qwen/qwen3.7-max\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9387.1,\n \"p95LatencyMs\": 10490.2,\n \"outputTokensPerSecond\": 54.92,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"qwen/qwen3.7-plus\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9766.6,\n \"p95LatencyMs\": 9798.2,\n \"outputTokensPerSecond\": 52.42,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"tencent/hy3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6062.3,\n \"p95LatencyMs\": 7070.2,\n \"outputTokensPerSecond\": 87.3,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xai/grok-4.3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 9467.7,\n \"p95LatencyMs\": 10087.9,\n \"outputTokensPerSecond\": 48.36,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xai/grok-4.5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 13564.8,\n \"p95LatencyMs\": 17351.9,\n \"outputTokensPerSecond\": 60.71,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xai/grok-build-0.1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 16394.8,\n \"p95LatencyMs\": 18035.4,\n \"outputTokensPerSecond\": 96.86,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"xiaomi/mimo-v2.5-pro\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 12070.7,\n \"p95LatencyMs\": 12386.8,\n \"outputTokensPerSecond\": 42.44,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 6839.7,\n \"p95LatencyMs\": 7261.4,\n \"outputTokensPerSecond\": 75.16,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5-turbo\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 55348.5,\n \"p95LatencyMs\": 114086.6,\n \"outputTokensPerSecond\": 14.64,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.1\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 15658.4,\n \"p95LatencyMs\": 17307.1,\n \"outputTokensPerSecond\": 32.9,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.2\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 10308.5,\n \"p95LatencyMs\": 15127.6,\n \"outputTokensPerSecond\": 54.87,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.3\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 7272.4,\n \"p95LatencyMs\": 7998.1,\n \"outputTokensPerSecond\": 71.09,\n \"errorRate\": 0,\n \"samples\": 3\n },\n \"zai/glm-5.3-flash\": {\n \"measuredAt\": \"2026-08-29T16:51:33Z\",\n \"latencyMs\": 10545.3,\n \"p95LatencyMs\": 11672.4,\n \"outputTokensPerSecond\": 49.01,\n \"errorRate\": 0,\n \"samples\": 3\n }\n}\n","/**\n * Model-performance priors consumed by the portfolio router.\n *\n * The entries below are a small, auditable seed extracted from the 2026-03-16\n * BlockRun performance run. They are deliberately weak priors: live data\n * injected by the host should replace them through configuration before a\n * release. Historical numbers must never be presented as a current\n * provider SLA or as task-quality measurements.\n */\n\nimport liveProfiles from \"./model-profiles.generated.json\";\n\nexport type ModelPerformanceProfile = {\n measuredAt: string;\n /** Gateway end-to-end latency for the benchmark workload. */\n latencyMs: number;\n /** Tail latency is more relevant than mean latency for urgent requests. */\n p95LatencyMs?: number;\n outputTokensPerSecond: number;\n /** External intelligence index when one was available; not task success. */\n intelligenceIndex?: number;\n /** Failure fraction observed in the same benchmark run. */\n errorRate?: number;\n /** Number of sampled calls behind the observation. */\n samples?: number;\n};\n\n// Generated from benchmark files that satisfy the uncached-inference\n// invariant. These are weak performance priors (speed/reliability), never\n// task-quality labels.\nexport const LIVE_MODEL_PROFILES: Readonly> = Object.freeze(\n liveProfiles as Record,\n);\n\nexport const HISTORICAL_MODEL_PROFILES: Readonly> =\n Object.freeze({\n \"anthropic/claude-haiku-4.5\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 2305,\n outputTokensPerSecond: 140.6,\n },\n \"anthropic/claude-sonnet-4.6\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 2110,\n outputTokensPerSecond: 121.3,\n },\n \"deepseek/deepseek-chat\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1431,\n outputTokensPerSecond: 179.2,\n intelligenceIndex: 32,\n },\n \"google/gemini-2.5-flash\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1238,\n outputTokensPerSecond: 207.6,\n intelligenceIndex: 20,\n },\n \"google/gemini-2.5-flash-lite\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1353,\n outputTokensPerSecond: 192.5,\n intelligenceIndex: 20,\n },\n \"google/gemini-2.5-pro\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1294,\n outputTokensPerSecond: 197.8,\n },\n \"google/gemini-3.1-pro\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 1609,\n outputTokensPerSecond: 167.2,\n },\n \"openai/gpt-4o-mini\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 2764,\n outputTokensPerSecond: 92.8,\n },\n \"openai/gpt-5.3-codex\": {\n measuredAt: \"2026-03-16T13:50:48Z\",\n latencyMs: 7935,\n outputTokensPerSecond: 32.3,\n },\n });\n","/**\n * Whether the request actually requires an external action/tool, as distinct\n * from merely being sent by a host that exposes tools on every turn.\n *\n * The detector intentionally looks for action+target pairs. A generic factual\n * or multiple-choice question must stay false even when the host attaches a\n * large tool schema; otherwise every tool-enabled host turn is over-routed as\n * an agent task and models may browse or mutate state unnecessarily.\n */\nexport function inferToolRequirement(\n prompt: string,\n _systemPrompt?: string,\n toolChoice?: unknown,\n): boolean {\n // OpenAI-compatible clients can state this requirement directly. Treat that\n // protocol signal as authoritative instead of trying to infer it from prose.\n if (toolChoice === \"none\") return false;\n if (toolChoice === \"required\") return true;\n if (\n typeof toolChoice === \"object\" &&\n toolChoice !== null &&\n (toolChoice as { type?: unknown }).type === \"function\"\n ) {\n return true;\n }\n\n // System prompts commonly describe every tool a host exposes. They are not\n // evidence that the user asked to perform an action on this turn. Explicit\n // host requirements should use tool_choice/requiresTools instead.\n const text = prompt;\n const explicitTool =\n /\\b(?:use|call|invoke)\\s+(?:the\\s+)?[\\w.-]+\\s+(?:tool|function|api)\\b|\\btool[_ -]?call\\b|使用.{0,20}(?:工具|函数|接口)|调用.{0,20}(?:工具|函数|接口)/i;\n const codeEnvironment =\n /\\b(?:run|execute)\\s+(?:the\\s+)?(?:tests?|command|script|build|linter)|\\b(?:edit|modify|patch|create|write|save|delete|rename|move|inspect|read)\\b.{0,60}\\b(?:file|repository|repo|codebase|directory|folder)\\b|\\b(?:terminal|shell|bash|zsh|pytest|npm test|pnpm test|git\\s+(?:status|diff|commit)|docker)\\b|(?:运行|执行).{0,20}(?:测试|命令|脚本|构建)|(?:修改|编辑|修复|创建|读取|检查|保存).{0,30}(?:文件|仓库|代码库|目录)/i;\n const webAction =\n /\\b(?:browse|search|look up|fetch|open)\\b.{0,80}\\b(?:web|website|url|online|documentation|docs|news|weather|price)\\b|(?:浏览|搜索|查询|打开).{0,30}(?:网页|网站|链接|文档|新闻|天气|价格)/i;\n const statefulAction =\n /\\b(?:refund|cancel|book|reserve|purchase|buy|return|exchange|transfer|update|change)\\b.{0,80}\\b(?:order|booking|reservation|account|address|payment|subscription|ticket|flight|item)\\b|(?:退款|取消|预订|购买|退货|换货|转账|更新|修改).{0,30}(?:订单|预订|账户|地址|付款|订阅|票|航班|商品)/i;\n return (\n explicitTool.test(text) ||\n codeEnvironment.test(text) ||\n webAction.test(text) ||\n statefulAction.test(text)\n );\n}\n","/**\n * V3 portfolio router.\n *\n * This is deliberately local and deterministic: feature extraction, eligibility\n * checks and scoring read only request data plus the in-process model registry.\n * It is therefore safe for the hot path and provides a stable baseline for the\n * RouterBench evaluation before health telemetry / an optional judge are added.\n */\n\nimport { DEFAULT_MODEL_CAPABILITIES } from \"./model-capabilities.js\";\nimport { getFallbackChain, selectModel } from \"./selector.js\";\nimport { RulesStrategy } from \"./strategy.js\";\nimport {\n HISTORICAL_MODEL_PROFILES,\n LIVE_MODEL_PROFILES,\n type ModelPerformanceProfile,\n} from \"./model-profiles.js\";\nimport type { RouterOptions, RouterStrategy, TaskType, Tier, TierConfig } from \"./types.js\";\nimport { inferToolRequirement } from \"./tool-intent.js\";\n\ntype TaskFeatures = {\n taskType: TaskType;\n estimatedInputTokens: number;\n hasCode: boolean;\n needsTools: boolean;\n toolsAvailable: boolean;\n needsVision: boolean;\n needsStructuredOutput: boolean;\n latencySensitive: boolean;\n highStakes: boolean;\n language: \"zh\" | \"other\";\n likelyParallelToolCalls: boolean;\n complexMultiToolPlan: boolean;\n agentDomain: \"airline\" | \"retail\" | \"web_research\" | \"other\";\n deepWebResearch: boolean;\n agentRisk: \"standard\" | \"high\" | \"complex_high\" | \"policy_exception_simple\" | \"policy_exception\";\n terminalToolSignal: boolean;\n terminalSafetySensitive: boolean;\n implicitTerminalCode: boolean;\n};\n\nconst DEFAULT_PORTFOLIO_WEIGHTS = {\n auto: {\n quality: 0.47,\n capability: 0.2,\n cost: 0.18,\n speed: 0.07,\n reliability: 0.03,\n legacy: 0.05,\n },\n eco: { quality: 0.36, capability: 0.2, cost: 0.28, speed: 0.1, reliability: 0.04, legacy: 0.02 },\n premium: {\n quality: 0.58,\n capability: 0.2,\n cost: 0.08,\n speed: 0.06,\n reliability: 0.06,\n legacy: 0.02,\n },\n highStakesBoost: { quality: 0.08, reliability: 0.05 },\n latencySensitiveSpeedBoost: 0.08,\n affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 },\n} as const;\n\n/**\n * Detect turns that probably need several tool calls. This is a\n * deliberately conservative request-side feature: it uses only the prompt\n * and visible tool count, never benchmark categories or expected answers.\n */\nfunction likelyNeedsParallelToolCalls(\n prompt: string,\n needsTools: boolean,\n toolCount: number | undefined,\n toolNames: readonly string[] | undefined,\n): boolean {\n if (!needsTools || toolCount === undefined || toolCount < 1) return false;\n const text = prompt.trim();\n const explicitRepeat =\n /\\b(?:in parallel|simultaneously|concurrently|for each|each of|every one|both|(?:two|three|multiple|several)\\s+(?:cities|locations|items|tasks|orders|users|files))\\b|并行|同时|分别|每个|各自|(?:两个|三个|多个)(?:城市|地点|项目|任务|订单|用户|文件)|cada uno|para cada|simult[aá]neamente/i.test(\n text,\n );\n if (explicitRepeat) return true;\n\n const sentenceClauses = text\n .split(/[.!?。!?]+/)\n .map((part) => part.trim())\n .filter((part) => part.length >= 8);\n if (\n (/\\b(?:also|additionally|furthermore)\\b|另外|此外|그리고/i.test(text) &&\n sentenceClauses.length >= 2) ||\n /\\band\\s+(?:also|for the)\\b/i.test(text)\n )\n return true;\n\n const pairedQuantity =\n /\\b\\d+(?:\\.\\d+)?\\s+(?:and|or)\\s+\\d+(?:\\.\\d+)?\\s*(?:gb|mb|tb|kg|g|ml|oz|cups?|cores?|cpus?)\\b/i.test(\n text,\n );\n if (pairedQuantity) return true;\n\n // Distinctive tokens from two visible tool names are a strong local signal\n // for a multi-operation turn (for example add_task + delete_task).\n const operationTokens = new Set([\n \"add\",\n \"delete\",\n \"remove\",\n \"cancel\",\n \"return\",\n \"exchange\",\n \"modify\",\n \"book\",\n \"transfer\",\n \"send\",\n \"upload\",\n \"download\",\n \"create\",\n \"close\",\n ]);\n const lowered = text.toLowerCase();\n const matchedOperationTokens = new Set(\n (toolNames ?? [])\n .flatMap((name) => name.toLowerCase().split(/[^a-z0-9\\u3400-\\u9fff]+/))\n .filter((token) => operationTokens.has(token) && lowered.includes(token)),\n );\n // A single workflow naturally mentions domain nouns like order/item plus\n // one action. Upgrade only when two different visible operation verbs are\n // requested (for example cancel + book or add + delete).\n if (matchedOperationTokens.size >= 2) return true;\n\n // Repeated food/logging entries are commonly expressed as several lines,\n // each with its own quantity rather than an explicit \"for each\" phrase.\n const nonEmptyLines = text\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean);\n const quantityMentions =\n text.match(\n /\\b(?:\\d+(?:\\.\\d+)?|one|two|three|four|five|six|seven|eight|nine|ten)\\s*(?:oz|ounce|ounces|g|gram|grams|kg|ml|cups?|pieces?|tablespoons?)\\b/gi,\n ) ?? [];\n if (nonEmptyLines.length >= 2 && quantityMentions.length >= 2) return true;\n\n // Weather prompts provide a useful language-independent high-confidence\n // pattern: a single lookup tool plus multiple locations joined in one turn.\n const repeatedLookup =\n /\\b(?:weather|climate|clima|tiempo|temperature|snow|news|report)\\b|天气|气象|温度|降雪|新闻|报告/i.test(\n text,\n );\n const multiLocationConnector = /\\b(?:and also|both|y|e)\\b|还有|以及|和|、/i.test(text);\n const commaSeparatedLocations = (text.match(/[,,]/g) ?? []).length >= 2;\n if (repeatedLookup && (multiLocationConnector || commaSeparatedLocations)) return true;\n\n const distinctOrderParts =\n /\\b(?:food|meal)\\b[\\s\\S]*\\bdrink\\b|\\bdrink\\b[\\s\\S]*\\b(?:food|meal)\\b/i.test(text);\n const koreanParallelClauses = (text.match(/,/g) ?? []).length >= 3 && /하고|그리고/.test(text);\n return distinctOrderParts || koreanParallelClauses;\n}\n\nfunction classifyTask(\n prompt: string,\n systemPrompt: string | undefined,\n options: RouterOptions,\n): TaskFeatures {\n const fullText = `${systemPrompt ?? \"\"} ${prompt}`;\n const estimatedInputTokens = Math.ceil(fullText.length / 4);\n // Feature regexes need request shape and intent, not the entire document.\n // Sample both ends so a long pasted artifact keeps the task instruction at\n // either boundary, while the full length still drives capacity decisions.\n const scanLimit = Math.max(1, Math.min(8_000, options.config.classifier.promptTruncationChars));\n const sample = (value: string): string => {\n if (value.length <= scanLimit) return value;\n const prefixLength = Math.ceil(scanLimit / 2);\n return `${value.slice(0, prefixLength)}\\n${value.slice(-(scanLimit - prefixLength))}`;\n };\n const scannedPrompt = sample(prompt);\n const scannedSystemPrompt = sample(systemPrompt ?? \"\");\n const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;\n const text = scannedPrompt.toLowerCase();\n const explicitCodeSignal =\n /```|\\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\\b|\\.(?:ts|tsx|js|py|go|rs)\\b/i.test(\n scannedPrompt,\n );\n // `class` is common in non-code Agent domains (for example airline cabin\n // class). Treat code constructs as code only when the prompt also contains\n // an implementation/editing cue, instead of letting a single ambiguous\n // noun redirect an entire tool session to the code-agent portfolio.\n const codeConstructSignal =\n /\\b(?:implement|refactor|debug|write|edit|modify|create|define|review|fix)\\b[\\s\\S]{0,48}\\b(?:api|function|class|method)\\b|\\b(?:api|function|class|method)\\b[\\s\\S]{0,48}\\b(?:code|implementation|typescript|javascript|python|rust|java)\\b/i.test(\n scannedPrompt,\n );\n const nativeCodeSignal =\n /\\b(?:programmed|written|implemented?|code)\\s+(?:in|using)\\s+(?:c\\+\\+|c|rust|go)\\b/i.test(\n scannedPrompt,\n );\n const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal;\n const toolsAvailable = options.hasTools ?? false;\n const needsTools =\n options.requiresTools ??\n (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));\n const likelyParallelToolCalls = likelyNeedsParallelToolCalls(\n scannedPrompt,\n needsTools,\n options.toolCount,\n options.toolNames,\n );\n const normalizedToolNames = (options.toolNames ?? []).map((name) => name.toLowerCase());\n const airlineToolSignal = normalizedToolNames.some((name) =>\n /(?:flight|reservation|airport|baggage|passenger)/.test(name),\n );\n const retailToolSignal = normalizedToolNames.some((name) =>\n /(?:order|product|item|return|exchange|address)/.test(name),\n );\n const webResearchToolSignal = normalizedToolNames.some((name) =>\n /^(?:web_?search|web_?fetch)$/.test(name),\n );\n const agentDomain =\n airlineToolSignal && !retailToolSignal\n ? \"airline\"\n : retailToolSignal && !airlineToolSignal\n ? \"retail\"\n : webResearchToolSignal\n ? \"web_research\"\n : \"other\";\n // Distinguish a cheap lookup from a BrowseComp-like investigation. These\n // prompts require joining several clues, resolving an entity, and ending in\n // one exact answer; complete agent trajectories show that treating them as\n // ordinary search causes long, costly loops. This is request/tool-surface\n // evidence only and does not depend on a benchmark id or hidden answer.\n const clueConnectors =\n scannedFullText.match(\n /\\b(?:after|before|while|where|whose|which|in \\d{4}|as of|over \\d+|another|also|furthermore)\\b|(?:之后|之前|其中|截至|超过|另一个|此外)/gi,\n ) ?? [];\n const entityResolutionSignal =\n /\\b(?:identify|who (?:is|was)|what (?:is|was) the name|which (?:person|player|company|country|city)|find the (?:person|player|name|entity))\\b|(?:找出|识别|是谁|哪位|名称是什么)/i.test(\n scannedFullText,\n );\n const exactAnswerSignal =\n /\\b(?:exact answer|single best-supported answer|following clues|multiple public sources)\\b|(?:精确答案|根据.*线索|多个公开来源)/i.test(\n scannedFullText,\n );\n const deepWebResearch =\n agentDomain === \"web_research\" &&\n (exactAnswerSignal ||\n (entityResolutionSignal && (clueConnectors.length >= 3 || prompt.length >= 320)));\n const globalOptimizationSignal =\n /\\b(?:cheapest|lowest[- ]price|least expensive|most expensive|highest(?:[- ]priced)?|largest|smallest|maximum|minimum|best available|closest|not (?:cost|exceed))\\b|最便宜|最低价|最贵|最高价|最大|最小/i.test(\n scannedPrompt,\n );\n const globalScopeSignal =\n /\\b(?:everything|all (?:(?:my|your|their|the) )?(?:future |upcoming )?(?:items|orders|passengers|flights|reservations|bookings)|every (?:item|order|passenger|flight|reservation|booking))\\b|全部|所有|每个/i.test(\n scannedPrompt,\n );\n const globalChoiceSignal = globalOptimizationSignal || globalScopeSignal;\n const crossRecordSignal =\n /\\b(?:another|other|different|previous)\\s+(?:order|reservation|booking|account|address)\\b|另一(?:个)?(?:订单|预订|账户|地址)|其他(?:订单|预订|账户|地址)/i.test(\n scannedPrompt,\n );\n const reservationIds = scannedPrompt.match(/\\b[A-Z0-9]{6}\\b/g) ?? [];\n const crossReservationBatchSignal =\n agentDomain === \"airline\" &&\n (/\\b(?:two|three|multiple|several)(?:\\s+of\\s+(?:my|our|the))?\\s+(?:upcoming\\s+)?(?:reservations?|bookings?)\\b|\\b(?:a\\s+)?(?:second|third)\\s+(?:reservation|booking)\\b/i.test(\n scannedPrompt,\n ) ||\n new Set(reservationIds).size >= 2);\n const conditionalGlobalWorkflowSignal =\n agentDomain === \"airline\" &&\n globalScopeSignal &&\n /\\b(?:if|that (?:contain|have)|longer than|shorter than|under|over|at (?:most|least)|wherever possible)\\b|如果|超过|少于|不超过|尽可能/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:cancel|change|upgrade|move|book)\\b[\\s\\S]*\\b(?:cancel|change|upgrade|move|book)\\b|取消[\\s\\S]*(?:升级|更改)|升级[\\s\\S]*(?:取消|更改)/i.test(\n scannedPrompt,\n );\n // A refund explicitly targeted at a named/non-original card can conflict\n // with account state and require escalation rather than a substitute action.\n // This narrow feature is visible on the first turn and avoids sending every\n // ordinary return workflow to the expensive policy specialist.\n const policyExceptionSignal =\n agentDomain === \"retail\" &&\n /\\b(?:return|refund|send back|get (?:my |the )?money back)\\b|退货|退款|退回/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:amex|american express|visa|mastercard|credit card|debit card|different card|another card|other card)\\b|信用卡|借记卡|其他卡|另一张卡/i.test(\n scannedPrompt,\n );\n // A comparative selector can mention two products while requesting only\n // one write (for example \"send back the pricier one\"). Three-repeat tau2\n // calibration found no quality gain from the policy specialist on these\n // single-write cases, so keep them in a distinct, lower-cost risk band.\n const singleSelectedPolicyException =\n policyExceptionSignal &&\n /\\b(?:return|refund|send back)\\b[^.!?。!?]{0,96}\\b(?:the )?(?:pricier|cheaper|more expensive|less expensive|costlier|one)\\b/i.test(\n scannedPrompt,\n );\n // Returns and exchanges often pivot after confirmation (return -> rethink\n // -> exchange -> choose a variant). That future state is not visible to a\n // task-start router, so treat the observable workflow verb as the risk cue.\n // Simpler cancellation and one-field order edits stay on the standard path.\n const negotiatedWorkflowSignal =\n agentDomain === \"retail\" && /\\b(?:return|exchange)\\b|退货|退回|换货|交换/i.test(scannedPrompt);\n const numberedSteps = (scannedPrompt.match(/(?:^|\\s)\\d+(?:\\.\\d+)*[.)]\\s+/g) ?? []).length;\n const complexMultiToolPlan =\n likelyParallelToolCalls &&\n ((options.toolCount ?? 0) >= 6 || numberedSteps >= 3 || prompt.length > 1_200);\n let agentRisk: TaskFeatures[\"agentRisk\"] =\n needsTools && singleSelectedPolicyException\n ? \"policy_exception_simple\"\n : needsTools && policyExceptionSignal\n ? \"policy_exception\"\n : // Airline prompts that require a global optimum (for example the\n // cheapest itinerary across several candidates) are materially harder\n // than applying one change to every passenger in a known reservation.\n // Full-session evidence supports Sonnet for the former, while upgrading\n // the latter merely because it says \"all passengers\" caused a large cost\n // increase without a quality gain.\n needsTools &&\n agentDomain === \"airline\" &&\n (globalOptimizationSignal || conditionalGlobalWorkflowSignal)\n ? \"complex_high\"\n : needsTools &&\n (likelyParallelToolCalls ||\n globalChoiceSignal ||\n crossRecordSignal ||\n crossReservationBatchSignal ||\n negotiatedWorkflowSignal)\n ? \"high\"\n : \"standard\";\n const needsVision = options.hasVision ?? false;\n const needsStructuredOutput = options.requiresStructuredOutput ?? false;\n const latencySensitive =\n /\\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\\b|尽快|马上|快速|低延迟/i.test(\n scannedFullText,\n );\n const highStakes =\n /\\b(?:production|security|payment|legal|medical|financial|audit)\\b|生产|安全|支付|法律|医疗|财务|审计/i.test(\n scannedFullText,\n );\n // Terminal tasks often describe the desired artifact rather than naming a\n // programming language. Treat only small, deterministic local build/file\n // work as implicit code. Operational deployment, credentials, destructive\n // work, evaluation, vision, and broad search stay on the stronger generic\n // tool-agent path. This is a request-side feature, not a benchmark ID list.\n const terminalToolSignal = normalizedToolNames.some((name) =>\n /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name),\n );\n const simpleTerminalArtifact =\n /\\b(?:create|write|convert|generate|build|implement|run|fix|repair|debug|make)\\b[\\s\\S]{0,120}\\b(?:file|script|csv|parquet|json|txt|server|endpoint)\\b/i.test(\n scannedPrompt,\n );\n // Multi-file repair is qualitatively different from fixing one known local\n // script. The agent must preserve state across inspections, infer ordering\n // and dependencies, edit several artifacts, and close the loop with tests.\n // A frozen Terminal-Bench trajectory showed the economy model spending 27\n // turns repeatedly rereading files without making an edit, while Opus solved\n // the same task in eight turns. Promote this request-visible pattern before\n // model scoring; no benchmark ID or expected answer is consulted.\n const terminalComplexRepair =\n terminalToolSignal &&\n /\\b(?:multiple|several)\\s+(?:scripts?|files?|components?)\\b|\\b(?:pipeline|dependencies)\\b[\\s\\S]{0,100}\\b(?:fail|issue|fix|repair|run|execute)\\b|\\b(?:identify|find|fix|repair)\\s+(?:and\\s+)?(?:fix\\s+)?all\\s+(?:the\\s+)?issues\\b/i.test(\n scannedPrompt,\n );\n // One artifact that must be accepted by multiple compilers/runtimes is not\n // a routine file-writing task. It requires reasoning across incompatible\n // grammars and validating every execution path; cheap code models can\n // produce plausible-looking source that satisfies neither toolchain.\n const mentionedTerminalRuntimes = new Set(\n (scannedPrompt.match(/\\b(?:gcc|clang|rustc|javac|go\\s+build|node|python)\\b/gi) ?? []).map(\n (name) => name.toLowerCase().replace(/\\s+/g, \" \"),\n ),\n );\n const terminalCrossRuntimeArtifact =\n terminalToolSignal &&\n (/\\bpolyglot\\b/i.test(scannedPrompt) ||\n /\\b(?:both|each)\\b[\\s\\S]{0,120}\\b(?:compilers?|runtimes?|toolchains?)\\b/i.test(\n scannedPrompt,\n ) ||\n (mentionedTerminalRuntimes.size >= 2 &&\n /\\b(?:compile|build|run|execute)\\b/i.test(scannedPrompt)));\n // Framework-to-native ports combine binary checkpoint inspection, weight\n // export, tensor-layout reasoning, image/data decoding, and a separately\n // compiled runtime. A task-start router can see this boundary directly in\n // the request (for example PyTorch state_dict -> a pure C CLI); treating it\n // like routine single-file C work caused a 30-turn read/retry loop in a\n // frozen official Terminal-Bench trajectory.\n const terminalFrameworkToNativeArtifact =\n terminalToolSignal &&\n /\\b(?:pytorch|tensorflow|jax|onnx|state[_ -]?dict|checkpoint|safetensors?)\\b|\\.(?:pth|pt|onnx)\\b/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:pure|native|programmed|written|implemented?)\\s+(?:in|using)\\s+(?:c\\+\\+|c|rust|go)\\b|\\b(?:c\\+\\+|c|rust|go)\\s+(?:program|binary|executable|cli|tool|implementation)\\b/i.test(\n scannedPrompt,\n ) &&\n /\\b(?:inference|model|weights?|tensor|export|convert|load)\\b/i.test(scannedPrompt);\n if (\n needsTools &&\n (terminalComplexRepair || terminalCrossRuntimeArtifact || terminalFrameworkToNativeArtifact) &&\n (agentRisk === \"standard\" || agentRisk === \"high\")\n )\n agentRisk = \"complex_high\";\n const complexTerminalOperation =\n /\\b(?:git|ssh|nginx|https|certificate|authentication|credential|deploy|production|encrypt|gpg|shred|securely delete|decommission|benchmark|evaluate|embedding|chess|image|search the web|schema|statistical|statistics|aggregate|join|multiple inputs?)\\b/i.test(\n scannedPrompt,\n );\n // A bare \"token\" is not a credential signal: blockchain, tokenizer, and\n // LLM tasks use that word routinely (for example \"token transfers\"). Only\n // treat it as sensitive when the prompt gives it an authentication/secret\n // qualifier. API keys remain an unambiguous high-risk signal on their own.\n const terminalCredentialSignal =\n /\\b(?:ssh|nginx|certificate|authentication|credentials?|passwords?|api keys?|deploy|production|encrypt|gpg|shred|securely delete|decommission)\\b/i.test(\n scannedPrompt,\n ) ||\n /\\b(?:access|auth|authentication|bearer|secret|api)\\s+tokens?\\b|\\btokens?\\s+(?:secret|credential|authentication)\\b/i.test(\n scannedPrompt,\n );\n const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);\n const implicitTerminalCode =\n needsTools &&\n terminalToolSignal &&\n agentRisk === \"standard\" &&\n !highStakes &&\n !complexTerminalOperation &&\n numberedSteps < 3 &&\n prompt.length <= 1_000 &&\n simpleTerminalArtifact;\n const language = /[\\u3400-\\u9fff]/.test(scannedFullText) ? \"zh\" : \"other\";\n const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\\n)\\s*[A-D][.)]\\s+/gim) ?? []).length;\n const numericSignals = (scannedPrompt.match(/-?\\d+(?:[.,]\\d+)?/g) ?? []).length;\n const compactMathProblem =\n !hasCode &&\n prompt.length < 2_500 &&\n numericSignals >= 2 &&\n (/[+×÷=%$€£¥]|\\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\\b/i.test(\n scannedPrompt,\n ) ||\n /[??]\\s*$/.test(scannedPrompt.trim()) ||\n numericSignals >= 3);\n\n let taskType: TaskType = \"chat\";\n if (needsVision) taskType = \"vision\";\n else if (estimatedInputTokens > 80_000) taskType = \"long_context\";\n else if (needsTools && (hasCode || implicitTerminalCode)) taskType = \"code_agent\";\n else if (needsTools && likelyParallelToolCalls && !complexMultiToolPlan)\n taskType = \"tool_agent_parallel\";\n else if (needsTools) taskType = \"tool_agent\";\n else if (multipleChoiceSignals >= 3) taskType = \"reasoning_mcq\";\n else if (compactMathProblem) taskType = \"reasoning_math\";\n else if (\n /\\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\\b/i.test(text)\n )\n taskType = \"debug\";\n else if (hasCode || /\\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\\b/i.test(text))\n taskType = \"code_edit\";\n else if (needsStructuredOutput || /\\b(?:extract|json|schema|csv|字段|提取)\\b/i.test(text))\n taskType = \"extraction\";\n else if (\n /\\b(?:prove|derive|theorem|formal|mathematical|reasoning|证明|推导|定理|数学)\\b/i.test(text)\n )\n taskType = \"reasoning\";\n\n return {\n taskType,\n estimatedInputTokens,\n hasCode,\n needsTools,\n toolsAvailable,\n needsVision,\n needsStructuredOutput,\n latencySensitive,\n highStakes,\n language,\n likelyParallelToolCalls,\n complexMultiToolPlan,\n agentDomain,\n deepWebResearch,\n agentRisk,\n terminalToolSignal,\n terminalSafetySensitive,\n implicitTerminalCode,\n };\n}\n\nfunction affinity(\n modelId: string,\n task: TaskType,\n language: TaskFeatures[\"language\"] = \"other\",\n agentDomain: TaskFeatures[\"agentDomain\"] = \"other\",\n deepWebResearch = false,\n agentRisk: TaskFeatures[\"agentRisk\"] = \"standard\",\n terminalToolSignal = false,\n terminalSafetySensitive = false,\n): number {\n const id = modelId.toLowerCase();\n // Model family names are intentionally similar (for example\n // `gemini-2.5-flash` vs `gemini-2.5-flash-lite`). A substring match lets a\n // smaller sibling inherit a capability claim that was measured only for the\n // flagship. Keep these assignments model-exact; a sibling can be added only\n // with its own evidence.\n const modelName = id.slice(id.indexOf(\"/\") + 1);\n const match = (values: string[], score: number) =>\n values.some((value) => modelName === value) ? score : 0;\n const base = 0.68;\n\n switch (task) {\n case \"code_agent\":\n if (terminalToolSignal && agentRisk === \"complex_high\") {\n // Strong native tool loop until the Responses function-output fix is\n // deployed on both gateways; keep Codex available below the floor.\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5.3-codex\"], 0.87),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n );\n }\n // Seven valid full agent + official Terminal-Bench trajectories\n // (2026-07-28) gave GPT-5 Mini 4/7 resolved tasks versus 1/7 for the\n // prior dynamic code-agent choice. Its token-normalized total cost was\n // higher in this small calibration, so keep Codex and Sonnet's quality\n // priors above it; admitting Mini to the scoring band lets the normal\n // quality/cost profile choose it without erasing stronger fallbacks.\n // DeepSeek V4 Pro is kept below the primary band after two consecutive\n // mid-trajectory provider timeouts contaminated its calibration runs.\n return Math.max(\n base,\n match([\"gpt-5.3-codex\"], 1),\n match([\"claude-sonnet-5\"], 0.98),\n match([\"gpt-5-mini\"], 0.96),\n match([\"gemini-3.5-flash\"], 0.92),\n match([\"kimi-k3\"], 0.9),\n match([\"deepseek-v4-pro\", \"glm-5.2\"], 0.88),\n );\n case \"tool_agent\":\n if (terminalToolSignal && agentRisk === \"complex_high\") {\n // Keep the Responses-API Codex path outside auto's affinity floor\n // until the gateway fix that preserves function_call_output is live\n // on both chains. Sonnet has a verified native multi-turn tool loop\n // and is the safe strong default for this band today.\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5.3-codex\"], 0.87),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n );\n }\n if (terminalToolSignal && !terminalSafetySensitive) {\n // Seven official Terminal-Bench calibration trajectories favoured\n // GPT-5 Mini over the prior dynamic choice. Admit Codex/Sonnet as\n // close fallbacks, but let actual request cost break the tie.\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-5.3-codex\"], 0.98),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"gemini-3.5-flash\"], 0.89),\n );\n }\n if (terminalToolSignal && terminalSafetySensitive) {\n // Two complete agent observations on the public\n // Terminal-Bench new-encrypt-command task ended in Codex repeating\n // the same TerminalExec input until the loop guard fired. Keep Codex\n // as an availability fallback, but below the safety-band affinity\n // floor until its Responses function-output path is verified on both\n // gateways. This does not change explicit code-agent routing.\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"claude-opus-4.8\"], 0.9),\n match([\"gpt-5.3-codex\"], 0.84),\n );\n }\n if (agentDomain === \"web_research\") {\n // Complete-session BrowseComp calibration supersedes the earlier\n // single-case Opus promotion: strict deduplicated evidence has Sonnet\n // 5 at 2/9 versus Opus 5 at 0/3, while Opus also costs more and has a\n // much longer tail. Keep Opus as an availability fallback until a\n // larger stable-provider sample supports promotion.\n return deepWebResearch\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.84),\n match([\"claude-opus-5\"], 0.8),\n match([\"claude-opus-4.8\"], 0.78),\n )\n : Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.86),\n match([\"claude-opus-5\"], 0.84),\n match([\"claude-opus-4.8\"], 0.82),\n );\n }\n // Full-trajectory tau2 calibration (2026-07-28, official gpt-4.1\n // simulator): Sonnet 5 completed both an airline policy task and a\n // retail multi-write task with reward 1.0. Gemini 3.5 Flash emitted\n // function calls as plain text after the first structured calls and\n // looped to the 100-step ceiling on the airline task. Keep only the\n // trajectory-validated primary inside the scoring band; the remaining\n // eligible models are retained below as availability fallbacks.\n if (agentDomain === \"retail\") {\n // Full-session calibration: GPT-5 Mini completed two local/single\n // retail workflows at a fraction of Sonnet's token cost. It remains\n // ineligible for promotion when the prompt asks for multiple actions,\n // cross-record discovery, or a global optimum; those trajectories\n // exposed unstable write arguments in prior calibration. DeepSeek V4\n // Pro completed all three high-risk retail calibration trajectories\n // that included global-choice, cross-record, and multi-write behavior;\n // Sonnet completed one of the same three.\n if (agentRisk === \"standard\") {\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.82),\n match([\"gpt-5.3-codex\"], 0.81),\n match([\"kimi-k3\"], 0.78),\n match([\"deepseek-v4-pro\"], 0.76),\n );\n }\n if (agentRisk === \"policy_exception\") {\n return Math.max(\n base,\n match([\"gpt-4.1\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-5-mini\"], 0.8),\n match([\"gpt-4o-mini\"], 0.76),\n );\n }\n if (agentRisk === \"policy_exception_simple\") {\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-4.1\"], 0.86),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-4o-mini\"], 0.8),\n );\n }\n return Math.max(\n base,\n match([\"deepseek-v4-pro\"], 1),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.82),\n match([\"gpt-5.3-codex\"], 0.81),\n match([\"kimi-k3\"], 0.78),\n match([\"gpt-5-mini\"], 0.76),\n );\n }\n // Standard airline workflows stay on GPT-5 Mini: six full-session\n // development trajectories gave it the same 5/6 success as Sonnet at\n // roughly one order of magnitude lower normalized token cost. A held-out\n // high-risk cabin/date negotiation then produced a persistent empty\n // assistant turn on Mini even after a semantic retry, while Sonnet 5\n // completed the identical official tau2 trajectory with reward 1.0.\n // Promote only global optimization / conditional-global work. A known\n // batch of reservations is operationally high-risk but still a\n // structured tool workflow: current Tau evidence has Mini and Sonnet at\n // equal task reward there, while Sonnet costs roughly two orders of\n // magnitude more on the long-tail case.\n if (agentDomain === \"airline\") {\n if (agentRisk === \"complex_high\") {\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n match([\"deepseek-v4-pro\"], 0.74),\n );\n }\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"gemini-3.5-flash\"], 0.8),\n match([\"deepseek-v4-pro\"], 0.76),\n );\n }\n return Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gemini-3.5-flash\"], 0.88),\n match([\"gpt-5.3-codex\"], 0.87),\n match([\"gpt-5-mini\"], 0.84),\n match([\"kimi-k3\"], 0.85),\n match([\"deepseek-v4-pro\"], 0.82),\n );\n case \"tool_agent_parallel\":\n if (terminalToolSignal) {\n // Multi-file Terminal work is not equivalent to a one-turn parallel\n // function-call benchmark. Sonnet is the strongest trajectory-tested\n // cost-controlled default; Opus remains a close safety fallback.\n return terminalSafetySensitive\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"claude-opus-4.8\"], 0.9),\n match([\"gpt-5.3-codex\"], 0.86),\n )\n : Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-5.3-codex\"], 0.98),\n match([\"claude-sonnet-5\"], 0.92),\n match([\"gemini-3.5-flash\"], 0.88),\n );\n }\n if (agentDomain === \"web_research\") {\n return deepWebResearch\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.84),\n match([\"claude-opus-5\"], 0.8),\n match([\"claude-opus-4.8\"], 0.78),\n )\n : Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.88),\n match([\"gemini-3.5-flash\"], 0.86),\n match([\"claude-opus-5\"], 0.84),\n match([\"claude-opus-4.8\"], 0.82),\n );\n }\n if (agentDomain === \"retail\") {\n if (agentRisk === \"policy_exception\") {\n return Math.max(\n base,\n match([\"gpt-4.1\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-5-mini\"], 0.8),\n match([\"gpt-4o-mini\"], 0.76),\n );\n }\n if (agentRisk === \"policy_exception_simple\") {\n return Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"gpt-4.1\"], 0.86),\n match([\"deepseek-v4-pro\"], 0.82),\n match([\"gpt-4o-mini\"], 0.8),\n );\n }\n return Math.max(\n base,\n match([\"deepseek-v4-pro\"], 1),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"claude-opus-4.8\"], 0.84),\n match([\"gpt-5-mini\"], 0.78),\n match([\"gemini-3.5-flash\"], 0.76),\n );\n }\n if (agentDomain === \"airline\") {\n return agentRisk === \"complex_high\"\n ? Math.max(\n base,\n match([\"claude-sonnet-5\"], 1),\n match([\"gpt-5-mini\"], 0.78),\n match([\"claude-opus-4.8\"], 0.76),\n match([\"gemini-3.5-flash\"], 0.74),\n )\n : Math.max(\n base,\n match([\"gpt-5-mini\"], 1),\n match([\"claude-sonnet-5\"], 0.9),\n match([\"gemini-3.5-flash\"], 0.8),\n );\n }\n // RouterBench calibration, 2026-07-26: Opus 4.8 produced complete\n // multi-call payloads on 2/3 multilingual BFCL parallel cases. Gemini\n // 3.5 Flash, Sonnet 5, DeepSeek V4 Pro, and Grok 4.5 were 0/3. This\n // narrow prior only applies after the conservative prompt feature above.\n return Math.max(\n base,\n match([\"claude-opus-4.8\"], 1),\n match([\"claude-sonnet-5\"], 0.84),\n match([\"grok-4.5\"], 0.82),\n match([\"gemini-3.5-flash\"], 0.8),\n match([\"deepseek-v4-pro\"], 0.78),\n );\n case \"code_edit\":\n case \"debug\":\n return Math.max(\n base,\n match([\"gpt-5.3-codex\"], 1),\n match([\"claude-sonnet-4.6\"], 0.94),\n match([\"glm-5.2\"], 0.9),\n match([\"deepseek-v4-pro\"], 0.86),\n );\n case \"reasoning\":\n return Math.max(\n base,\n match([\"claude-sonnet-5\", \"claude-sonnet-4.6\"], 0.98),\n match([\"deepseek-v4-pro\"], 0.95),\n match([\"grok-4.5\"], 0.94),\n match([\"gemini-3.1-pro\", \"gemini-3.5-flash\"], 0.92),\n );\n case \"reasoning_mcq\":\n // RouterBench calibration (2026-07-28, six stratified GPQA Diamond\n // tasks, identical agent adapter and 512-token budget): Gemini 3\n // Flash Preview scored 5/6, Gemini 3.5 Flash 4/6, and Gemini 3.1 Pro\n // 3/6 while costing ~170x more than Flash. Keep the measured winner as\n // the narrow default; version recency alone is not a quality signal.\n // Unused host tools must not change this reasoning-only model choice.\n return Math.max(\n base,\n match([\"gemini-3-flash-preview\"], 1),\n match([\"gemini-3.5-flash\"], 0.91),\n match([\"grok-4.5\"], 0.9),\n match([\"claude-sonnet-5\"], 0.88),\n match([\"deepseek-v4-pro\"], 0.84),\n );\n case \"reasoning_math\":\n // Same calibration, five multilingual MGSM tasks: Gemini 3.5 Flash was\n // 5/5 with the lowest cost and latency; four current flagships were 4/5\n // and Kimi K2.7 was 3/5.\n return Math.max(\n base,\n match([\"gemini-3.5-flash\"], 1),\n match([\"grok-4.5\"], 0.93),\n match([\"claude-sonnet-5\", \"deepseek-v4-pro\", \"kimi-k3\"], 0.9),\n );\n case \"vision\":\n return Math.max(\n base,\n match([\"gemini-3.1-pro\"], 0.96),\n match([\"qwen3.7-max\", \"claude-sonnet-4.6\", \"kimi-k3\", \"grok-4.3\"], 0.9),\n );\n case \"long_context\":\n // Long-context eligibility is necessary but not sufficient: a provider\n // can advertise a 1M window yet return an empty completion near that\n // boundary. Keep the proven long-context flagship in the lead and put\n // less-established alternatives in a separate affinity band so price\n // alone cannot displace it.\n return Math.max(\n base,\n match([\"gemini-3.1-pro\"], 1),\n match([\"qwen3.7-max\", \"glm-5.2\"], 0.89),\n match([\"gemini-3.5-flash\"], 0.88),\n match([\"deepseek-v4-pro\"], 0.85),\n );\n case \"extraction\": {\n // A structured extraction must preserve both the output contract and the\n // source-language fields. For Mandarin input, keep the language-native\n // Kimi candidate in a distinct affinity band. This is deliberately a\n // candidate-pool decision (rather than a brittle post-hoc override): it\n // still falls back normally if that model is unavailable or ineligible.\n // Kimi K3 costs ~5x its retired sibling K2.7, so the band must be wider\n // than the auto affinityFloorGap (0.10) or price alone re-selects a\n // non-native model for Mandarin input; 0.12 keeps K3 alone in the\n // primary band for zh and leaves every other language untouched.\n const kimiExtractionAffinity = language === \"zh\" ? 1 : 0.9;\n const otherExtractionAffinity = language === \"zh\" ? 0.88 : 0.9;\n return Math.max(\n base,\n match([\"gemini-3.5-flash\", \"gemini-2.5-flash\", \"gpt-4o-mini\"], otherExtractionAffinity),\n match([\"claude-sonnet-5\", \"claude-sonnet-4.6\"], otherExtractionAffinity),\n match([\"kimi-k3\"], kimiExtractionAffinity),\n );\n }\n default:\n return Math.max(\n base,\n match([\"gemini-3.5-flash\", \"gemini-2.5-flash\", \"kimi-k3\"], 0.86),\n );\n }\n}\n\nfunction evidenceCandidates(task: TaskType): string[] {\n if (task === \"code_agent\") {\n return [\n \"openai/gpt-5.3-codex\",\n \"anthropic/claude-sonnet-5\",\n \"openai/gpt-5-mini\",\n \"google/gemini-3.5-flash\",\n \"moonshot/kimi-k3\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"tool_agent\") {\n return [\n \"anthropic/claude-sonnet-5\",\n \"anthropic/claude-opus-5\",\n \"openai/gpt-5-mini\",\n \"openai/gpt-4.1\",\n \"openai/gpt-4o-mini\",\n \"google/gemini-3.5-flash\",\n \"openai/gpt-5.3-codex\",\n \"moonshot/kimi-k3\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"tool_agent_parallel\") {\n return [\n \"anthropic/claude-opus-5\",\n \"anthropic/claude-opus-4.8\",\n \"anthropic/claude-sonnet-5\",\n \"openai/gpt-5-mini\",\n \"openai/gpt-4.1\",\n \"openai/gpt-4o-mini\",\n \"xai/grok-4.5\",\n \"google/gemini-3.5-flash\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"long_context\") {\n return [\n \"google/gemini-3.1-pro\",\n \"deepseek/deepseek-v4-pro\",\n \"qwen/qwen3.7-max\",\n \"zai/glm-5.2\",\n \"google/gemini-3.5-flash\",\n ];\n }\n if (task === \"reasoning_mcq\") {\n return [\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3.5-flash\",\n \"xai/grok-4.5\",\n \"anthropic/claude-sonnet-5\",\n \"deepseek/deepseek-v4-pro\",\n ];\n }\n if (task === \"extraction\") {\n // Kimi K3 is no longer on the auto MEDIUM chain (K2.7 was); the\n // language-native extraction band in affinity() needs it in the pool.\n return [\"moonshot/kimi-k3\", \"google/gemini-3.5-flash\", \"anthropic/claude-sonnet-5\"];\n }\n if (task === \"reasoning_math\") {\n return [\n \"google/gemini-3.5-flash\",\n \"xai/grok-4.5\",\n \"anthropic/claude-sonnet-5\",\n \"deepseek/deepseek-v4-pro\",\n \"moonshot/kimi-k3\",\n ];\n }\n return [];\n}\n\nfunction isEligible(\n modelId: string,\n features: TaskFeatures,\n maxOutputTokens: number,\n options: RouterOptions,\n): boolean {\n const model = options.modelCapabilities?.[modelId] ?? DEFAULT_MODEL_CAPABILITIES[modelId];\n // Preserve compatibility for temporarily catalog-less fallback IDs. They are\n // kept behind known-model candidates but are not silently dropped.\n if (!model) return true;\n if (features.needsTools && !model.supportsTools) return false;\n if (features.needsVision && !model.supportsVision) return false;\n if (features.needsStructuredOutput && !model.supportsTools) return false;\n if (model.maxOutputTokens < maxOutputTokens) return false;\n return model.contextWindow >= (features.estimatedInputTokens + maxOutputTokens) * 1.1;\n}\n\nfunction estimatedCost(\n modelId: string,\n options: RouterOptions,\n inputTokens: number,\n outputTokens: number,\n): number {\n const price = options.modelPricing.get(modelId);\n if (!price) return Number.POSITIVE_INFINITY;\n if (price.flatPrice !== undefined) return price.flatPrice;\n return (inputTokens * price.inputPrice + outputTokens * price.outputPrice) / 1_000_000;\n}\n\nfunction profileScore(\n modelId: string,\n options: RouterOptions,\n now: Date,\n):\n | { quality?: number; speed: number; tailSpeed: number; reliability: number; freshness: number }\n | undefined {\n const profile: ModelPerformanceProfile | undefined =\n options.modelPerformance?.[modelId] ??\n LIVE_MODEL_PROFILES[modelId] ??\n HISTORICAL_MODEL_PROFILES[modelId];\n if (!profile) return undefined;\n const measuredAt = Date.parse(profile.measuredAt);\n if (!Number.isFinite(measuredAt)) return undefined;\n const ageDays = Math.max(0, (now.getTime() - measuredAt) / 86_400_000);\n // A 30-day half-life makes old data a tie-breaker only. Small probe runs are\n // also weak evidence: three quick samples should not overturn a curated\n // tier ordering merely because of a transient provider tail. Callers that\n // inject an observation without a sample count retain the legacy full\n // confidence behaviour for compatibility.\n const sampleConfidence =\n profile.samples === undefined ? 1 : Math.min(1, Math.max(0, profile.samples) / 10);\n const freshness = Math.pow(0.5, ageDays / 30) * sampleConfidence;\n const quality =\n profile.intelligenceIndex === undefined\n ? undefined\n : Math.min(1, profile.intelligenceIndex / 50);\n const speed = Math.min(\n 1,\n (2_000 / Math.max(500, profile.latencyMs) + profile.outputTokensPerSecond / 250) / 2,\n );\n const tailSpeed = Math.min(1, 3_000 / Math.max(750, profile.p95LatencyMs ?? profile.latencyMs));\n const reliability = Math.max(0, 1 - (profile.errorRate ?? 0));\n return { quality, speed, tailSpeed, reliability, freshness };\n}\n\n/** Candidate router used for Auto. Rules still set the capability tier; V3 ranks within it. */\nexport class PortfolioStrategy implements RouterStrategy {\n readonly name = \"portfolio\";\n\n route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n ) {\n const features = classifyTask(prompt, systemPrompt, options);\n const base = new RulesStrategy().route(prompt, systemPrompt, maxOutputTokens, {\n ...options,\n requiresTools: features.needsTools,\n });\n const tierConfigs = base.tierConfigs;\n if (!tierConfigs) return base;\n const targetTier: Tier =\n (features.taskType === \"reasoning_mcq\" || features.taskType === \"reasoning_math\") &&\n (base.tier === \"SIMPLE\" || base.tier === \"MEDIUM\")\n ? \"REASONING\"\n : base.tier;\n const tierConfig = tierConfigs[targetTier];\n const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];\n // Evidence candidates join the configured chain, but the host's\n // unavailable set applies to both: the configured side arrives filtered\n // through RulesStrategy, and a dead evidence model must not re-enter here.\n const unavailable = new Set(options.unavailableModels ?? []);\n const chain = [\n ...new Set([...configuredCandidates, ...evidenceCandidates(features.taskType)]),\n ].filter(\n (model): model is string =>\n typeof model === \"string\" && model.length > 0 && !unavailable.has(model),\n );\n const eligible = chain.filter((model) =>\n isEligible(model, features, maxOutputTokens, options),\n );\n const eligibleCandidates = eligible.length > 0 ? eligible : chain;\n if (eligibleCandidates.length === 0) return base;\n const profileName =\n options.routingProfile === \"eco\"\n ? \"eco\"\n : options.routingProfile === \"premium\"\n ? \"premium\"\n : \"auto\";\n const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;\n const getAffinity = (model: string) =>\n affinity(\n model,\n features.taskType,\n features.language,\n features.agentDomain,\n features.deepWebResearch,\n features.agentRisk,\n features.terminalToolSignal,\n features.terminalSafetySensitive,\n );\n const bestAffinity = Math.max(...eligibleCandidates.map(getAffinity));\n const specificAffinity = eligibleCandidates.filter((model) => getAffinity(model) > 0.68);\n // A tier's fallback list is primarily an availability/recovery chain, not a\n // set of equally validated substitutes. Re-ranking every fallback lets a\n // cheap generic model displace the curated primary merely because it has a\n // favourable short performance probe. Only promote models with explicit\n // task affinity; otherwise retain the first capability-eligible tier model.\n const affinityPool = specificAffinity.length > 0 ? specificAffinity : [eligibleCandidates[0]];\n // Generic Terminal work has much wider trajectory variance than a BFCL-like\n // one-turn parallel call. Keep the strong-model safety band, but admit the\n // next capable tier so Auto's cost/reliability score can reject an Opus\n // primary that is materially more expensive without measured benefit.\n const affinityFloorGap = features.terminalToolSignal\n ? Math.max(\n portfolio.affinityFloorGap[profileName],\n features.terminalSafetySensitive ? 0.15 : 0.12,\n )\n : portfolio.affinityFloorGap[profileName];\n const candidates = affinityPool.filter(\n (model) => getAffinity(model) >= bestAffinity - affinityFloorGap,\n );\n const costs = candidates.map((model) =>\n estimatedCost(model, options, features.estimatedInputTokens, maxOutputTokens),\n );\n const finiteCosts = costs.filter(Number.isFinite);\n const minCost = finiteCosts.length > 0 ? Math.min(...finiteCosts) : 0;\n const maxCost = finiteCosts.length > 0 ? Math.max(...finiteCosts) : 1;\n\n const now = options.now ?? new Date();\n const profileWeights = portfolio[profileName];\n const rankedEntries = candidates\n .map((model, index) => {\n const cost = estimatedCost(model, options, features.estimatedInputTokens, maxOutputTokens);\n const costScore =\n Number.isFinite(cost) && maxCost > minCost\n ? 1 - (cost - minCost) / (maxCost - minCost)\n : 0.5;\n const capabilityScore = isEligible(model, features, maxOutputTokens, options) ? 1 : 0;\n const profile = profileScore(model, options, now);\n // Fresh observations can refine affinity. Historical observations fade\n // quickly and never replace task-level RouterBench evidence.\n const observedQuality =\n profile?.quality === undefined\n ? getAffinity(model)\n : getAffinity(model) * (1 - profile.freshness) + profile.quality * profile.freshness;\n const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;\n const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;\n const observedReliability = profile\n ? profile.reliability * profile.freshness + (1 - profile.freshness)\n : 1;\n // Preserve a small amount of the hand-curated fallback order while V3's\n // task affinity and real request constraints do the primary work.\n const legacyScore = 1 - index / Math.max(1, candidates.length - 1);\n const qualityWeight =\n profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);\n const speedScore = features.latencySensitive ? observedTailSpeed : observedSpeed;\n const speedWeight =\n profileWeights.speed +\n (features.latencySensitive ? portfolio.latencySensitiveSpeedBoost : 0);\n const reliabilityWeight =\n profileWeights.reliability +\n (features.highStakes ? portfolio.highStakesBoost.reliability : 0);\n const score =\n observedQuality * qualityWeight +\n capabilityScore * profileWeights.capability +\n costScore * profileWeights.cost +\n speedScore * speedWeight +\n observedReliability * reliabilityWeight +\n legacyScore * profileWeights.legacy;\n return {\n model,\n score,\n quality: observedQuality,\n cost: costScore,\n speed: speedScore,\n reliability: observedReliability,\n };\n })\n .sort((a, b) => b.score - a.score);\n const scoredModels = rankedEntries.map((item) => item.model);\n // The affinity floor controls which models may compete for the primary;\n // it must not erase availability fallbacks. Append all remaining eligible\n // models in their curated chain order after the scored primary pool.\n const webResearchFallbackOrder = [\n \"anthropic/claude-sonnet-5\",\n \"openai/gpt-5-mini\",\n \"google/gemini-3.5-flash\",\n \"anthropic/claude-opus-5\",\n \"anthropic/claude-opus-4.8\",\n \"openai/gpt-5.3-codex\",\n ];\n const ranked =\n features.agentDomain === \"web_research\"\n ? [\n ...scoredModels,\n ...webResearchFallbackOrder.filter(\n (model) => eligibleCandidates.includes(model) && !scoredModels.includes(model),\n ),\n ...eligibleCandidates.filter(\n (model) => !scoredModels.includes(model) && !webResearchFallbackOrder.includes(model),\n ),\n ]\n : [...scoredModels, ...eligibleCandidates.filter((model) => !scoredModels.includes(model))];\n\n const model = ranked[0] ?? base.model;\n const selectedTierConfigs: Record = {\n ...tierConfigs,\n [targetTier]: { primary: model, fallback: ranked.slice(1) },\n };\n // selectModel only reads the selected tier; retain the complete tier map for host fallback.\n const decision = selectModel(\n targetTier,\n base.confidence,\n \"portfolio\",\n `${base.reasoning} | v3 task=${features.taskType} agentRisk=${features.agentRisk} deepWebResearch=${features.deepWebResearch} terminalCode=${features.implicitTerminalCode} terminalSafety=${features.terminalSafetySensitive} candidates=${ranked.length}`,\n selectedTierConfigs,\n options.modelPricing,\n features.estimatedInputTokens,\n maxOutputTokens,\n options.routingProfile,\n base.agenticScore,\n );\n return {\n ...decision,\n tierConfigs: selectedTierConfigs,\n profile: base.profile,\n candidates: ranked,\n candidateScores: rankedEntries.map(({ model, score, quality, cost, speed, reliability }) => ({\n model,\n score,\n quality,\n cost,\n speed,\n reliability,\n })),\n taskType: features.taskType,\n routerVersion: \"v3-portfolio\" as const,\n };\n }\n}\n","/**\n * Default Routing Config\n *\n * All routing parameters as a TypeScript constant.\n * Operators override via openclaw.yaml plugin config.\n *\n * Scoring uses 15 weighted dimensions with sigmoid confidence calibration.\n */\n\nimport type { RoutingConfig } from \"./types.js\";\n\nexport const DEFAULT_ROUTING_CONFIG: RoutingConfig = {\n version: \"3.5\",\n strategy: \"portfolio\",\n portfolio: {\n auto: {\n quality: 0.47,\n capability: 0.2,\n cost: 0.18,\n speed: 0.07,\n reliability: 0.03,\n legacy: 0.05,\n },\n eco: {\n quality: 0.36,\n capability: 0.2,\n cost: 0.28,\n speed: 0.1,\n reliability: 0.04,\n legacy: 0.02,\n },\n premium: {\n quality: 0.58,\n capability: 0.2,\n cost: 0.08,\n speed: 0.06,\n reliability: 0.06,\n legacy: 0.02,\n },\n highStakesBoost: { quality: 0.08, reliability: 0.05 },\n latencySensitiveSpeedBoost: 0.08,\n affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 },\n },\n\n classifier: {\n llmModel: \"google/gemini-2.5-flash\",\n llmMaxTokens: 10,\n llmTemperature: 0,\n promptTruncationChars: 500,\n cacheTtlMs: 3_600_000, // 1 hour\n },\n\n scoring: {\n tokenCountThresholds: { simple: 50, complex: 500 },\n\n // Multilingual keywords: EN + ZH + JA + RU + DE + ES + PT + KO + AR\n codeKeywords: [\n // English\n \"function\",\n \"class\",\n \"import\",\n \"def\",\n \"SELECT\",\n \"async\",\n \"await\",\n \"const\",\n \"let\",\n \"var\",\n \"return\",\n \"```\",\n // Chinese\n \"函数\",\n \"类\",\n \"导入\",\n \"定义\",\n \"查询\",\n \"异步\",\n \"等待\",\n \"常量\",\n \"变量\",\n \"返回\",\n // Japanese\n \"関数\",\n \"クラス\",\n \"インポート\",\n \"非同期\",\n \"定数\",\n \"変数\",\n // Russian\n \"функция\",\n \"класс\",\n \"импорт\",\n \"определ\",\n \"запрос\",\n \"асинхронный\",\n \"ожидать\",\n \"константа\",\n \"переменная\",\n \"вернуть\",\n // German\n \"funktion\",\n \"klasse\",\n \"importieren\",\n \"definieren\",\n \"abfrage\",\n \"asynchron\",\n \"erwarten\",\n \"konstante\",\n \"variable\",\n \"zurückgeben\",\n // Spanish\n \"función\",\n \"clase\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"asíncrono\",\n \"esperar\",\n \"constante\",\n \"variable\",\n \"retornar\",\n // Portuguese\n \"função\",\n \"classe\",\n \"importar\",\n \"definir\",\n \"consulta\",\n \"assíncrono\",\n \"aguardar\",\n \"constante\",\n \"variável\",\n \"retornar\",\n // Korean\n \"함수\",\n \"클래스\",\n \"가져오기\",\n \"정의\",\n \"쿼리\",\n \"비동기\",\n \"대기\",\n \"상수\",\n \"변수\",\n \"반환\",\n // Arabic\n \"دالة\",\n \"فئة\",\n \"استيراد\",\n \"تعريف\",\n \"استعلام\",\n \"غير متزامن\",\n \"انتظار\",\n \"ثابت\",\n \"متغير\",\n \"إرجاع\",\n ],\n reasoningKeywords: [\n // English\n \"prove\",\n \"theorem\",\n \"derive\",\n \"step by step\",\n \"chain of thought\",\n \"formally\",\n \"mathematical\",\n \"proof\",\n \"logically\",\n // Chinese\n \"证明\",\n \"定理\",\n \"推导\",\n \"逐步\",\n \"思维链\",\n \"形式化\",\n \"数学\",\n \"逻辑\",\n // Japanese\n \"証明\",\n \"定理\",\n \"導出\",\n \"ステップバイステップ\",\n \"論理的\",\n // Russian\n \"доказать\",\n \"докажи\",\n \"доказательств\",\n \"теорема\",\n \"вывести\",\n \"шаг за шагом\",\n \"пошагово\",\n \"поэтапно\",\n \"цепочка рассуждений\",\n \"рассуждени\",\n \"формально\",\n \"математически\",\n \"логически\",\n // German\n \"beweisen\",\n \"beweis\",\n \"theorem\",\n \"ableiten\",\n \"schritt für schritt\",\n \"gedankenkette\",\n \"formal\",\n \"mathematisch\",\n \"logisch\",\n // Spanish\n \"demostrar\",\n \"teorema\",\n \"derivar\",\n \"paso a paso\",\n \"cadena de pensamiento\",\n \"formalmente\",\n \"matemático\",\n \"prueba\",\n \"lógicamente\",\n // Portuguese\n \"provar\",\n \"teorema\",\n \"derivar\",\n \"passo a passo\",\n \"cadeia de pensamento\",\n \"formalmente\",\n \"matemático\",\n \"prova\",\n \"logicamente\",\n // Korean\n \"증명\",\n \"정리\",\n \"도출\",\n \"단계별\",\n \"사고의 연쇄\",\n \"형식적\",\n \"수학적\",\n \"논리적\",\n // Arabic\n \"إثبات\",\n \"نظرية\",\n \"اشتقاق\",\n \"خطوة بخطوة\",\n \"سلسلة التفكير\",\n \"رسمياً\",\n \"رياضي\",\n \"برهان\",\n \"منطقياً\",\n ],\n simpleKeywords: [\n // English\n \"what is\",\n \"define\",\n \"translate\",\n \"hello\",\n \"yes or no\",\n \"capital of\",\n \"how old\",\n \"who is\",\n \"when was\",\n // Chinese\n \"什么是\",\n \"定义\",\n \"翻译\",\n \"你好\",\n \"是否\",\n \"首都\",\n \"多大\",\n \"谁是\",\n \"何时\",\n // Japanese\n \"とは\",\n \"定義\",\n \"翻訳\",\n \"こんにちは\",\n \"はいかいいえ\",\n \"首都\",\n \"誰\",\n // Russian\n \"что такое\",\n \"определение\",\n \"перевести\",\n \"переведи\",\n \"привет\",\n \"да или нет\",\n \"столица\",\n \"сколько лет\",\n \"кто такой\",\n \"когда\",\n \"объясни\",\n // German\n \"was ist\",\n \"definiere\",\n \"übersetze\",\n \"hallo\",\n \"ja oder nein\",\n \"hauptstadt\",\n \"wie alt\",\n \"wer ist\",\n \"wann\",\n \"erkläre\",\n // Spanish\n \"qué es\",\n \"definir\",\n \"traducir\",\n \"hola\",\n \"sí o no\",\n \"capital de\",\n \"cuántos años\",\n \"quién es\",\n \"cuándo\",\n // Portuguese\n \"o que é\",\n \"definir\",\n \"traduzir\",\n \"olá\",\n \"sim ou não\",\n \"capital de\",\n \"quantos anos\",\n \"quem é\",\n \"quando\",\n // Korean\n \"무엇\",\n \"정의\",\n \"번역\",\n \"안녕하세요\",\n \"예 또는 아니오\",\n \"수도\",\n \"누구\",\n \"언제\",\n // Arabic\n \"ما هو\",\n \"تعريف\",\n \"ترجم\",\n \"مرحبا\",\n \"نعم أو لا\",\n \"عاصمة\",\n \"من هو\",\n \"متى\",\n ],\n technicalKeywords: [\n // English\n \"algorithm\",\n \"optimize\",\n \"architecture\",\n \"distributed\",\n \"kubernetes\",\n \"microservice\",\n \"database\",\n \"infrastructure\",\n // Chinese\n \"算法\",\n \"优化\",\n \"架构\",\n \"分布式\",\n \"微服务\",\n \"数据库\",\n \"基础设施\",\n // Japanese\n \"アルゴリズム\",\n \"最適化\",\n \"アーキテクチャ\",\n \"分散\",\n \"マイクロサービス\",\n \"データベース\",\n // Russian\n \"алгоритм\",\n \"оптимизировать\",\n \"оптимизаци\",\n \"оптимизируй\",\n \"архитектура\",\n \"распределённый\",\n \"микросервис\",\n \"база данных\",\n \"инфраструктура\",\n // German\n \"algorithmus\",\n \"optimieren\",\n \"architektur\",\n \"verteilt\",\n \"kubernetes\",\n \"mikroservice\",\n \"datenbank\",\n \"infrastruktur\",\n // Spanish\n \"algoritmo\",\n \"optimizar\",\n \"arquitectura\",\n \"distribuido\",\n \"microservicio\",\n \"base de datos\",\n \"infraestructura\",\n // Portuguese\n \"algoritmo\",\n \"otimizar\",\n \"arquitetura\",\n \"distribuído\",\n \"microsserviço\",\n \"banco de dados\",\n \"infraestrutura\",\n // Korean\n \"알고리즘\",\n \"최적화\",\n \"아키텍처\",\n \"분산\",\n \"마이크로서비스\",\n \"데이터베이스\",\n \"인프라\",\n // Arabic\n \"خوارزمية\",\n \"تحسين\",\n \"بنية\",\n \"موزع\",\n \"خدمة مصغرة\",\n \"قاعدة بيانات\",\n \"بنية تحتية\",\n ],\n creativeKeywords: [\n // English\n \"story\",\n \"poem\",\n \"compose\",\n \"brainstorm\",\n \"creative\",\n \"imagine\",\n \"write a\",\n // Chinese\n \"故事\",\n \"诗\",\n \"创作\",\n \"头脑风暴\",\n \"创意\",\n \"想象\",\n \"写一个\",\n // Japanese\n \"物語\",\n \"詩\",\n \"作曲\",\n \"ブレインストーム\",\n \"創造的\",\n \"想像\",\n // Russian\n \"история\",\n \"рассказ\",\n \"стихотворение\",\n \"сочинить\",\n \"сочини\",\n \"мозговой штурм\",\n \"творческий\",\n \"представить\",\n \"придумай\",\n \"напиши\",\n // German\n \"geschichte\",\n \"gedicht\",\n \"komponieren\",\n \"brainstorming\",\n \"kreativ\",\n \"vorstellen\",\n \"schreibe\",\n \"erzählung\",\n // Spanish\n \"historia\",\n \"poema\",\n \"componer\",\n \"lluvia de ideas\",\n \"creativo\",\n \"imaginar\",\n \"escribe\",\n // Portuguese\n \"história\",\n \"poema\",\n \"compor\",\n \"criativo\",\n \"imaginar\",\n \"escreva\",\n // Korean\n \"이야기\",\n \"시\",\n \"작곡\",\n \"브레인스토밍\",\n \"창의적\",\n \"상상\",\n \"작성\",\n // Arabic\n \"قصة\",\n \"قصيدة\",\n \"تأليف\",\n \"عصف ذهني\",\n \"إبداعي\",\n \"تخيل\",\n \"اكتب\",\n ],\n\n // New dimension keyword lists (multilingual)\n imperativeVerbs: [\n // English\n \"build\",\n \"create\",\n \"implement\",\n \"design\",\n \"develop\",\n \"construct\",\n \"generate\",\n \"deploy\",\n \"configure\",\n \"set up\",\n // Chinese\n \"构建\",\n \"创建\",\n \"实现\",\n \"设计\",\n \"开发\",\n \"生成\",\n \"部署\",\n \"配置\",\n \"设置\",\n // Japanese\n \"構築\",\n \"作成\",\n \"実装\",\n \"設計\",\n \"開発\",\n \"生成\",\n \"デプロイ\",\n \"設定\",\n // Russian\n \"построить\",\n \"построй\",\n \"создать\",\n \"создай\",\n \"реализовать\",\n \"реализуй\",\n \"спроектировать\",\n \"разработать\",\n \"разработай\",\n \"сконструировать\",\n \"сгенерировать\",\n \"сгенерируй\",\n \"развернуть\",\n \"разверни\",\n \"настроить\",\n \"настрой\",\n // German\n \"erstellen\",\n \"bauen\",\n \"implementieren\",\n \"entwerfen\",\n \"entwickeln\",\n \"konstruieren\",\n \"generieren\",\n \"bereitstellen\",\n \"konfigurieren\",\n \"einrichten\",\n // Spanish\n \"construir\",\n \"crear\",\n \"implementar\",\n \"diseñar\",\n \"desarrollar\",\n \"generar\",\n \"desplegar\",\n \"configurar\",\n // Portuguese\n \"construir\",\n \"criar\",\n \"implementar\",\n \"projetar\",\n \"desenvolver\",\n \"gerar\",\n \"implantar\",\n \"configurar\",\n // Korean\n \"구축\",\n \"생성\",\n \"구현\",\n \"설계\",\n \"개발\",\n \"배포\",\n \"설정\",\n // Arabic\n \"بناء\",\n \"إنشاء\",\n \"تنفيذ\",\n \"تصميم\",\n \"تطوير\",\n \"توليد\",\n \"نشر\",\n \"إعداد\",\n ],\n constraintIndicators: [\n // English\n \"under\",\n \"at most\",\n \"at least\",\n \"within\",\n \"no more than\",\n \"o(\",\n \"maximum\",\n \"minimum\",\n \"limit\",\n \"budget\",\n // Chinese\n \"不超过\",\n \"至少\",\n \"最多\",\n \"在内\",\n \"最大\",\n \"最小\",\n \"限制\",\n \"预算\",\n // Japanese\n \"以下\",\n \"最大\",\n \"最小\",\n \"制限\",\n \"予算\",\n // Russian\n \"не более\",\n \"не менее\",\n \"как минимум\",\n \"в пределах\",\n \"максимум\",\n \"минимум\",\n \"ограничение\",\n \"бюджет\",\n // German\n \"höchstens\",\n \"mindestens\",\n \"innerhalb\",\n \"nicht mehr als\",\n \"maximal\",\n \"minimal\",\n \"grenze\",\n \"budget\",\n // Spanish\n \"como máximo\",\n \"al menos\",\n \"dentro de\",\n \"no más de\",\n \"máximo\",\n \"mínimo\",\n \"límite\",\n \"presupuesto\",\n // Portuguese\n \"no máximo\",\n \"pelo menos\",\n \"dentro de\",\n \"não mais que\",\n \"máximo\",\n \"mínimo\",\n \"limite\",\n \"orçamento\",\n // Korean\n \"이하\",\n \"이상\",\n \"최대\",\n \"최소\",\n \"제한\",\n \"예산\",\n // Arabic\n \"على الأكثر\",\n \"على الأقل\",\n \"ضمن\",\n \"لا يزيد عن\",\n \"أقصى\",\n \"أدنى\",\n \"حد\",\n \"ميزانية\",\n ],\n outputFormatKeywords: [\n // English\n \"json\",\n \"yaml\",\n \"xml\",\n \"table\",\n \"csv\",\n \"markdown\",\n \"schema\",\n \"format as\",\n \"structured\",\n // Chinese\n \"表格\",\n \"格式化为\",\n \"结构化\",\n // Japanese\n \"テーブル\",\n \"フォーマット\",\n \"構造化\",\n // Russian\n \"таблица\",\n \"форматировать как\",\n \"структурированный\",\n // German\n \"tabelle\",\n \"formatieren als\",\n \"strukturiert\",\n // Spanish\n \"tabla\",\n \"formatear como\",\n \"estructurado\",\n // Portuguese\n \"tabela\",\n \"formatar como\",\n \"estruturado\",\n // Korean\n \"테이블\",\n \"형식\",\n \"구조화\",\n // Arabic\n \"جدول\",\n \"تنسيق\",\n \"منظم\",\n ],\n referenceKeywords: [\n // English\n \"above\",\n \"below\",\n \"previous\",\n \"following\",\n \"the docs\",\n \"the api\",\n \"the code\",\n \"earlier\",\n \"attached\",\n // Chinese\n \"上面\",\n \"下面\",\n \"之前\",\n \"接下来\",\n \"文档\",\n \"代码\",\n \"附件\",\n // Japanese\n \"上記\",\n \"下記\",\n \"前の\",\n \"次の\",\n \"ドキュメント\",\n \"コード\",\n // Russian\n \"выше\",\n \"ниже\",\n \"предыдущий\",\n \"следующий\",\n \"документация\",\n \"код\",\n \"ранее\",\n \"вложение\",\n // German\n \"oben\",\n \"unten\",\n \"vorherige\",\n \"folgende\",\n \"dokumentation\",\n \"der code\",\n \"früher\",\n \"anhang\",\n // Spanish\n \"arriba\",\n \"abajo\",\n \"anterior\",\n \"siguiente\",\n \"documentación\",\n \"el código\",\n \"adjunto\",\n // Portuguese\n \"acima\",\n \"abaixo\",\n \"anterior\",\n \"seguinte\",\n \"documentação\",\n \"o código\",\n \"anexo\",\n // Korean\n \"위\",\n \"아래\",\n \"이전\",\n \"다음\",\n \"문서\",\n \"코드\",\n \"첨부\",\n // Arabic\n \"أعلاه\",\n \"أدناه\",\n \"السابق\",\n \"التالي\",\n \"الوثائق\",\n \"الكود\",\n \"مرفق\",\n ],\n negationKeywords: [\n // English\n \"don't\",\n \"do not\",\n \"avoid\",\n \"never\",\n \"without\",\n \"except\",\n \"exclude\",\n \"no longer\",\n // Chinese\n \"不要\",\n \"避免\",\n \"从不\",\n \"没有\",\n \"除了\",\n \"排除\",\n // Japanese\n \"しないで\",\n \"避ける\",\n \"決して\",\n \"なしで\",\n \"除く\",\n // Russian\n \"не делай\",\n \"не надо\",\n \"нельзя\",\n \"избегать\",\n \"никогда\",\n \"без\",\n \"кроме\",\n \"исключить\",\n \"больше не\",\n // German\n \"nicht\",\n \"vermeide\",\n \"niemals\",\n \"ohne\",\n \"außer\",\n \"ausschließen\",\n \"nicht mehr\",\n // Spanish\n \"no hagas\",\n \"evitar\",\n \"nunca\",\n \"sin\",\n \"excepto\",\n \"excluir\",\n // Portuguese\n \"não faça\",\n \"evitar\",\n \"nunca\",\n \"sem\",\n \"exceto\",\n \"excluir\",\n // Korean\n \"하지 마\",\n \"피하다\",\n \"절대\",\n \"없이\",\n \"제외\",\n // Arabic\n \"لا تفعل\",\n \"تجنب\",\n \"أبداً\",\n \"بدون\",\n \"باستثناء\",\n \"استبعاد\",\n ],\n domainSpecificKeywords: [\n // English\n \"quantum\",\n \"fpga\",\n \"vlsi\",\n \"risc-v\",\n \"asic\",\n \"photonics\",\n \"genomics\",\n \"proteomics\",\n \"topological\",\n \"homomorphic\",\n \"zero-knowledge\",\n \"lattice-based\",\n // Chinese\n \"量子\",\n \"光子学\",\n \"基因组学\",\n \"蛋白质组学\",\n \"拓扑\",\n \"同态\",\n \"零知识\",\n \"格密码\",\n // Japanese\n \"量子\",\n \"フォトニクス\",\n \"ゲノミクス\",\n \"トポロジカル\",\n // Russian\n \"квантовый\",\n \"фотоника\",\n \"геномика\",\n \"протеомика\",\n \"топологический\",\n \"гомоморфный\",\n \"с нулевым разглашением\",\n \"на основе решёток\",\n // German\n \"quanten\",\n \"photonik\",\n \"genomik\",\n \"proteomik\",\n \"topologisch\",\n \"homomorph\",\n \"zero-knowledge\",\n \"gitterbasiert\",\n // Spanish\n \"cuántico\",\n \"fotónica\",\n \"genómica\",\n \"proteómica\",\n \"topológico\",\n \"homomórfico\",\n // Portuguese\n \"quântico\",\n \"fotônica\",\n \"genômica\",\n \"proteômica\",\n \"topológico\",\n \"homomórfico\",\n // Korean\n \"양자\",\n \"포토닉스\",\n \"유전체학\",\n \"위상\",\n \"동형\",\n // Arabic\n \"كمي\",\n \"ضوئيات\",\n \"جينوميات\",\n \"طوبولوجي\",\n \"تماثلي\",\n ],\n\n // Agentic task keywords - file ops, execution, multi-step, iterative work\n // Pruned: removed overly common words like \"then\", \"first\", \"run\", \"test\", \"build\"\n agenticTaskKeywords: [\n // English - File operations (clearly agentic)\n \"read file\",\n \"read the file\",\n \"look at\",\n \"check the\",\n \"open the\",\n \"edit\",\n \"modify\",\n \"update the\",\n \"change the\",\n \"write to\",\n \"create file\",\n // English - Execution (specific commands only)\n \"execute\",\n \"deploy\",\n \"install\",\n \"npm\",\n \"pip\",\n \"compile\",\n // English - Multi-step patterns (specific only)\n \"after that\",\n \"and also\",\n \"once done\",\n \"step 1\",\n \"step 2\",\n // English - Iterative work\n \"fix\",\n \"debug\",\n \"until it works\",\n \"keep trying\",\n \"iterate\",\n \"make sure\",\n \"verify\",\n \"confirm\",\n // Chinese (keep specific ones)\n \"读取文件\",\n \"查看\",\n \"打开\",\n \"编辑\",\n \"修改\",\n \"更新\",\n \"创建\",\n \"执行\",\n \"部署\",\n \"安装\",\n \"第一步\",\n \"第二步\",\n \"修复\",\n \"调试\",\n \"直到\",\n \"确认\",\n \"验证\",\n // Spanish\n \"leer archivo\",\n \"editar\",\n \"modificar\",\n \"actualizar\",\n \"ejecutar\",\n \"desplegar\",\n \"instalar\",\n \"paso 1\",\n \"paso 2\",\n \"arreglar\",\n \"depurar\",\n \"verificar\",\n // Portuguese\n \"ler arquivo\",\n \"editar\",\n \"modificar\",\n \"atualizar\",\n \"executar\",\n \"implantar\",\n \"instalar\",\n \"passo 1\",\n \"passo 2\",\n \"corrigir\",\n \"depurar\",\n \"verificar\",\n // Korean\n \"파일 읽기\",\n \"편집\",\n \"수정\",\n \"업데이트\",\n \"실행\",\n \"배포\",\n \"설치\",\n \"단계 1\",\n \"단계 2\",\n \"디버그\",\n \"확인\",\n // Arabic\n \"قراءة ملف\",\n \"تحرير\",\n \"تعديل\",\n \"تحديث\",\n \"تنفيذ\",\n \"نشر\",\n \"تثبيت\",\n \"الخطوة 1\",\n \"الخطوة 2\",\n \"إصلاح\",\n \"تصحيح\",\n \"تحقق\",\n ],\n\n // Dimension weights (sum to 1.0)\n dimensionWeights: {\n tokenCount: 0.08,\n codePresence: 0.15,\n reasoningMarkers: 0.18,\n technicalTerms: 0.1,\n creativeMarkers: 0.05,\n simpleIndicators: 0.02, // Reduced from 0.12 to make room for agenticTask\n multiStepPatterns: 0.12,\n questionComplexity: 0.05,\n imperativeVerbs: 0.03,\n constraintCount: 0.04,\n outputFormat: 0.03,\n referenceComplexity: 0.02,\n negationComplexity: 0.01,\n domainSpecificity: 0.02,\n agenticTask: 0.04, // Reduced - agentic signals influence tier selection, not dominate it\n },\n\n // Tier boundaries on weighted score axis\n tierBoundaries: {\n simpleMedium: 0.0,\n mediumComplex: 0.3, // Raised from 0.18 - prevent simple tasks from reaching expensive COMPLEX tier\n complexReasoning: 0.5, // Raised from 0.4 - reserve for true reasoning tasks\n },\n\n // Sigmoid steepness for confidence calibration\n confidenceSteepness: 12,\n // Below this confidence → ambiguous (null tier)\n confidenceThreshold: 0.7,\n },\n\n // ─── Tier chains ───\n //\n // Catalog refresh 2026-08-29 (V3.5). Every chain below names only models\n // the public catalog lists (GET https://blockrun.ai/api/v1/models). Ids the\n // gateway withholds (`hidden: true`) — kimi-k2.5/k2.6/k2.7, the grok-4-fast\n // and grok-4-1-fast pairs, grok-4-0709, claude-opus-4.6, gemini-3-pro-preview,\n // the whole `free/*` namespace — were removed everywhere, including fallback\n // rungs, so a routed model is always one a user can find on blockrun.ai/models.\n //\n // Primaries moved only where portfolio.ts already carries calibration\n // evidence for the successor (Sonnet 5 over Sonnet 4.6, GPT-5 Mini for\n // agentic MEDIUM, Gemini 3.5 Flash where Kimi K2.7 was). Newcomers with no\n // trajectory evidence yet (gemini-3.6-flash, glm-5.3, glm-5.3-flash,\n // gpt-5.6-luna, grok-4.3, minimax-m3, qwen3.7-plus) enter as fallback rungs;\n // promotion waits for a calibration run, because version recency is not a\n // quality signal.\n //\n // Latency figures in comments are the 2026-08-29 gateway probe\n // (model-profiles.generated.json); prices are the catalog list.\n\n // Auto (balanced) tier configs - current default smart routing\n tiers: {\n SIMPLE: {\n primary: \"google/gemini-2.5-flash\", // $0.30/$2.50 — 60% retention (best) in the 2026-03 run; still the fastest quality answer\n fallback: [\n \"google/gemini-3-flash-preview\", // $0.50/$3 — GPQA 5/6 in the 2026-07 calibration\n \"google/gemini-3.5-flash-lite\", // $0.30/$2.50, 1M ctx, thinking mode — same price as 2.5 Flash, newer generation\n \"deepseek/deepseek-chat\", // $0.14/$0.28, 1M ctx\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50, 1M ctx\n \"openai/gpt-5.6-luna\", // $0.20/$1.20, 1M ctx — GPT-5.6 cost tier (cut 2026-07-30)\n \"openai/gpt-5.4-nano\", // $0.20/$1.25, 1M ctx\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40\n \"nvidia/nemotron-3.5-lightning\", // FREE backstop — NVIDIA free tier (probed 2026-08-30)\n ],\n },\n MEDIUM: {\n // Was moonshot/kimi-k2.7 (hidden 2026-08). Gemini 3.5 Flash is the\n // calibrated successor: MGSM 5/5, GPQA 4/6, extraction band (portfolio.ts).\n primary: \"google/gemini-3.5-flash\", // $1.50/$9, 1M ctx, vision + tools\n fallback: [\n \"google/gemini-3.6-flash\", // $1.50/$7.50 — newest Flash, output 17% cheaper than 3.5; awaiting calibration\n \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx, vision + tools verified live 2026-08-27\n \"openai/gpt-5.6-terra\", // $2/$12, 1M ctx — GPT-5.6 balanced tier\n \"google/gemini-3-flash-preview\", // $0.50/$3\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n \"minimax/minimax-m3\", // $0.30/$1.20, 1M ctx\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n \"openai/gpt-5.6-luna\", // $0.20/$1.20\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40\n ],\n },\n COMPLEX: {\n primary: \"google/gemini-3.1-pro\", // $2/$12 — proven long-context flagship (portfolio.ts long_context lead)\n fallback: [\n \"google/gemini-3.6-flash\", // $1.50/$7.50 — Pro-level quality at Flash price (Google's claim; uncalibrated here)\n \"google/gemini-3.5-flash\", // $1.50/$9 — calibrated\n \"anthropic/claude-sonnet-5\", // $3/$15 — near-Opus quality, tau2 + Terminal-Bench calibrated\n \"xai/grok-4.5\", // $2.50/$9 — 503-resistant, independent infra (was grok-4-0709, now hidden)\n \"google/gemini-2.5-pro\", // $1.25/$10\n \"anthropic/claude-sonnet-4.6\", // $3/$15\n \"openai/gpt-5.6-terra\", // $2/$12 — GPT-5.6 balanced tier (Sol excluded: #202)\n \"openai/gpt-5.5\", // $5/$30 — prior OpenAI flagship\n \"openai/gpt-5.4\", // $2.50/$15 — previous flagship, benchmarked\n \"zai/glm-5.3\", // $1.40/$4.40, 1M ctx, always-on thinking — verified live 2026-08-19\n \"moonshot/kimi-k3\", // $3/$15, 1M ctx — Moonshot flagship (K2.7 successor)\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87 — strongest open-weight reasoner\n \"deepseek/deepseek-chat\", // $0.14/$0.28 — cheap last resort\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n REASONING: {\n // Was xai/grok-4-1-fast-reasoning ($0.20/$0.50, hidden 2026-08). DeepSeek\n // Reasoner is the cheapest listed reasoner at the same 1M context.\n primary: \"deepseek/deepseek-reasoner\", // $0.14/$0.28, 1M ctx\n fallback: [\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87 — calibrated reasoning band 0.95\n \"xai/grok-4.3\", // $1.50/$4, 1M ctx — xAI reasoning model, vision\n \"qwen/qwen3.7-plus\", // $0.32/$1.28, 1M ctx — reasoning; needs a generous max_tokens (thinking is billed)\n \"google/gemini-3.5-flash\", // $1.50/$9 — MGSM 5/5\n \"openai/o4-mini\", // $1.10/$4.40\n \"openai/o3\", // $2/$8\n ],\n },\n },\n\n // Eco tier configs - absolute cheapest (blockrun/eco)\n ecoTiers: {\n SIMPLE: {\n primary: \"nvidia/nemotron-3.5-lightning\", // FREE — NVIDIA free tier flagship, 1M ctx\n fallback: [\n // Was nvidia/nemotron-3-nano-30b until blockrun delisted it on 2026-09-08\n // (NVIDIA deprovisioned it for the account — a structured per-account\n // 404). nano-omni is blockrun's own redirect target for that id, so this\n // follows the same rule as the head: the router and the gateway name the\n // same model.\n \"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning\", // FREE — nano-30b's successor, 256K ctx\n // The free head keeps rotting with NVIDIA's hosting (deepseek-v4-flash\n // 410 2026-08-12, seed-oss-36b 410 2026-08-03, gpt-oss-120b/20b 400\n // 2026-08-21, and on 2026-08-30 FOUR of the five visible free models at\n // once — step-3.7-flash, nemotron-nano-9b-v2 and nemotron-nano-12b-v2-vl\n // all 410, mistral-nemotron hung). Each retirement retargets the two\n // free rungs to the current free tier; the paid rungs below never move.\n // The head follows blockrun's own redirect of the model it replaces, so\n // the router and the gateway never name different models.\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40 — cheapest paid rung\n \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx, vision + tools\n \"openai/gpt-5.6-luna\", // $0.20/$1.20, 1M ctx\n \"openai/gpt-5.4-nano\", // $0.20/$1.25\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n ],\n },\n MEDIUM: {\n primary: \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx, vision + tools verified live — cheapest full-capability model\n fallback: [\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n \"openai/gpt-5.6-luna\", // $0.20/$1.20\n \"openai/gpt-5.4-nano\", // $0.20/$1.25\n \"google/gemini-2.5-flash-lite\", // $0.10/$0.40\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n COMPLEX: {\n primary: \"zai/glm-5.3-flash\", // $0.15/$0.50, 1M ctx\n fallback: [\n \"deepseek/deepseek-chat\", // $0.14/$0.28, 1M ctx\n \"minimax/minimax-m3\", // $0.30/$1.20, 1M ctx\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87\n \"google/gemini-3.1-flash-lite\", // $0.25/$1.50\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n REASONING: {\n primary: \"deepseek/deepseek-reasoner\", // $0.14/$0.28, 1M ctx — cheapest listed reasoner\n fallback: [\n \"deepseek/deepseek-v4-pro\", // $0.435/$0.87\n \"qwen/qwen3.7-plus\", // $0.32/$1.28 — reasoning\n \"minimax/minimax-m3\", // $0.30/$1.20 — reasoning + coding\n \"zai/glm-5.3-flash\", // $0.15/$0.50 — reasoning tokens alongside content\n ],\n },\n },\n\n // Premium tier configs - best quality (blockrun/premium)\n // codex=complex coding, flash=simple coding, sonnet=reasoning/instructions, fable/opus=architecture/PM/audits\n premiumTiers: {\n SIMPLE: {\n // Was moonshot/kimi-k2.7 (hidden 2026-08).\n primary: \"google/gemini-3.5-flash\", // $1.50/$9, 1M ctx, vision + tools — calibrated\n fallback: [\n \"google/gemini-3.6-flash\", // $1.50/$7.50 — newest Flash\n \"anthropic/claude-haiku-4.5\", // $1/$5\n \"zai/glm-5.3\", // $1.40/$4.40, 1M ctx\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n \"google/gemini-3.5-flash-lite\", // $0.30/$2.50\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n ],\n },\n MEDIUM: {\n primary: \"openai/gpt-5.3-codex\", // $1.75/$14 - 400K context, 128K output — code_edit/debug lead (portfolio.ts)\n fallback: [\n \"anthropic/claude-sonnet-5\", // $3/$15 — code_agent band 0.98\n \"moonshot/kimi-k3\", // $3/$15, 1M ctx — Moonshot flagship\n \"zai/glm-5.3\", // $1.40/$4.40 — long-horizon coding\n \"google/gemini-3.6-flash\", // $1.50/$7.50\n \"google/gemini-3.5-flash\", // $1.50/$9\n \"google/gemini-2.5-pro\", // $1.25/$10\n \"xai/grok-4.5\", // $2.50/$9\n \"anthropic/claude-sonnet-4.6\", // $3/$15\n \"openai/gpt-5.6-terra\", // $2/$12\n ],\n },\n COMPLEX: {\n // fable-5 was promoted here 2026-06-11, force-reverted 2026-06-13 when Anthropic\n // withdrew the offer, and restored 2026-07-14 now that BlockRun has relisted it.\n primary: \"anthropic/claude-fable-5\", // Best quality for complex tasks — Mythos-class flagship above Opus ($10/$50, 1M ctx, always-on thinking)\n // Fallback chain de-Gemini'd 2026-04-22: when Anthropic 503s, Gemini is\n // also prone to \"high demand\" 503s (correlated failure — everyone falls\n // back to Google at the same time). Prefer in-family → xAI → Moonshot →\n // OpenAI flagship → Z.AI → DeepSeek → NVIDIA free instead.\n fallback: [\n \"anthropic/claude-opus-5\", // in-family hot swap first (half the price, 1M ctx + adaptive thinking)\n \"anthropic/claude-opus-4.8\", // in-family hot swap (identical cost to 5)\n \"anthropic/claude-opus-4.7\", // in-family hot swap (identical cost to 4.8)\n \"anthropic/claude-sonnet-5\", // Sonnet-tier drop-down, near-Opus quality\n \"anthropic/claude-sonnet-4.6\",\n \"xai/grok-4.5\", // xAI flagship — 503-resistant, direct-xAI SKU\n \"moonshot/kimi-k3\", // Moonshot flagship, independent infra\n \"openai/gpt-5.6-terra\", // GPT-5.6 balanced tier — stable (Sol excluded: #202)\n \"openai/gpt-5.5\", // Prior OpenAI flagship — 1M+ ctx, native agent + computer use\n \"openai/gpt-5.4\", // Previous flagship (slow but stable, benchmarked at 6,213ms)\n \"openai/gpt-5.3-codex\",\n \"zai/glm-5.3\", // Z.AI flagship, 1M ctx\n \"deepseek/deepseek-v4-pro\", // strongest open-weight reasoner\n \"deepseek/deepseek-chat\", // Cheap, reliable\n \"nvidia/nemotron-3.5-lightning\", // NVIDIA free ultimate backstop\n ],\n },\n REASONING: {\n // Sonnet 5 promoted over Sonnet 4.6 (same price; reasoning band 0.98 for both,\n // plus Sonnet 5's tau2/BrowseComp trajectory evidence).\n primary: \"anthropic/claude-sonnet-5\", // $3/$15, 1M ctx, adaptive thinking\n fallback: [\n \"anthropic/claude-sonnet-4.6\", // in-family hot swap — same cost\n \"anthropic/claude-opus-5\", // Newest flagship Opus w/ adaptive thinking\n \"anthropic/claude-opus-4.8\", // Prior flagship Opus — identical cost to 5\n \"anthropic/claude-opus-4.7\", // Flagship Opus w/ adaptive thinking\n \"xai/grok-4.5\", // reasoning band 0.94\n \"deepseek/deepseek-v4-pro\", // reasoning band 0.95\n \"xai/grok-4.3\", // $1.50/$4 — xAI reasoning model\n \"openai/o4-mini\", // $1.10/$4.40\n \"openai/o3\", // $2/$8\n ],\n },\n },\n\n // Agentic tier configs - models that excel at multi-step autonomous tasks\n agenticTiers: {\n SIMPLE: {\n primary: \"openai/gpt-4o-mini\", // $0.15/$0.60 - best tool compliance at lowest cost\n fallback: [\n \"openai/gpt-5.6-luna\", // $0.20/$1.20 — lightweight agentic tier of GPT-5.6\n \"zai/glm-5.3-flash\", // $0.15/$0.50 — tool calls verified live 2026-08-27\n \"anthropic/claude-haiku-4.5\", // $1/$5\n \"google/gemini-2.5-flash\", // $0.30/$2.50\n ],\n },\n MEDIUM: {\n // Was moonshot/kimi-k2.7 (hidden 2026-08). GPT-5 Mini carries the\n // Terminal-Bench and tau2 trajectory evidence in portfolio.ts.\n primary: \"openai/gpt-5-mini\", // $0.25/$2 — 4/7 Terminal-Bench, 5/6 tau2 airline\n fallback: [\n \"google/gemini-3.5-flash\", // $1.50/$9 — tool_agent band 0.88\n \"zai/glm-5.3-flash\", // $0.15/$0.50 — tools verified\n \"openai/gpt-5.6-terra\", // $2/$12\n \"openai/gpt-4o-mini\", // $0.15/$0.60 — reliable tool calling\n \"anthropic/claude-haiku-4.5\", // $1/$5\n \"deepseek/deepseek-chat\", // $0.14/$0.28\n \"moonshot/kimi-k3\", // $3/$15 — tool_agent band 0.85\n ],\n },\n COMPLEX: {\n // Sonnet 5 promoted over Sonnet 4.6: tau2 airline + retail reward 1.0,\n // Terminal-Bench safety band lead (portfolio.ts).\n primary: \"anthropic/claude-sonnet-5\", // $3/$15 — best agentic quality per trajectory evidence\n // Fallback chain de-Gemini'd 2026-04-22: Gemini's \"high demand\" 503s\n // correlate with Anthropic outages (everyone falls back together).\n // Prefer 503-resistant providers first.\n fallback: [\n \"anthropic/claude-sonnet-4.6\", // in-family hot swap — same cost\n \"anthropic/claude-opus-5\", // Newest flagship Opus — in-family hot swap\n \"anthropic/claude-opus-4.8\", // Prior flagship Opus — identical cost to 5\n \"anthropic/claude-opus-4.7\", // Flagship Opus — in-family hot swap\n \"xai/grok-4.5\", // xAI flagship — strong tool use, independent infra\n \"moonshot/kimi-k3\", // Moonshot flagship — independent infra\n \"openai/gpt-5.6-terra\", // GPT-5.6 balanced tier — stable (Sol excluded: #202)\n \"openai/gpt-5.5\", // Prior flagship — native agent + computer use (exactly the agentic-tier use case)\n \"openai/gpt-5.4\", // Previous flagship — reliable\n \"openai/gpt-5.3-codex\", // code_agent lead\n \"zai/glm-5.3\", // long-horizon coding\n \"deepseek/deepseek-v4-pro\", // retail high-risk 3/3\n \"deepseek/deepseek-chat\", // cheap, reliable\n \"nvidia/nemotron-3.5-lightning\", // NVIDIA free ultimate backstop\n ],\n },\n REASONING: {\n primary: \"anthropic/claude-sonnet-5\", // $3/$15 — strong tool use + adaptive thinking\n fallback: [\n \"anthropic/claude-sonnet-4.6\", // in-family hot swap — same cost\n \"anthropic/claude-opus-5\", // Newest flagship Opus w/ adaptive thinking\n \"anthropic/claude-opus-4.8\", // Prior flagship Opus — identical cost to 5\n \"anthropic/claude-opus-4.7\", // Flagship Opus w/ adaptive thinking\n \"xai/grok-4.5\", // reasoning band 0.94\n \"deepseek/deepseek-v4-pro\", // reasoning band 0.95\n \"deepseek/deepseek-reasoner\", // $0.14/$0.28\n ],\n },\n },\n\n // Time-windowed promotions — auto-applied when active, ignored when expired.\n // The GLM-5.1 launch promo (2026-04-01 → 2026-05-01) was the last entry and\n // has expired; the list is kept empty so the mechanism stays wired.\n promotions: [],\n\n overrides: {\n maxTokensForceComplex: 100_000,\n structuredOutputMinTier: \"MEDIUM\",\n ambiguousDefaultTier: \"MEDIUM\",\n // agenticMode left undefined → auto-detect via tools/agenticScore.\n // Set to `true` to force agentic tiers; `false` to disable them entirely.\n },\n};\n","/**\n * Smart Router Entry Point\n *\n * Classifies requests and routes to the cheapest capable model.\n * Delegates to pluggable RouterStrategy (default: RulesStrategy, <1ms).\n */\n\nimport type { RoutingDecision, RouterOptions } from \"./types.js\";\nimport { getStrategy, registerStrategy } from \"./strategy.js\";\nimport { PortfolioStrategy } from \"./portfolio.js\";\n\n// Register here instead of strategy.ts so PortfolioStrategy can reuse the\n// stable RulesStrategy without introducing a module cycle.\nregisterStrategy(new PortfolioStrategy());\n\n/**\n * Route a request to the cheapest capable model.\n * Delegates to the configured strategy (PortfolioStrategy by default).\n */\nexport function route(\n prompt: string,\n systemPrompt: string | undefined,\n maxOutputTokens: number,\n options: RouterOptions,\n): RoutingDecision {\n const strategy = getStrategy(options.config.strategy ?? \"portfolio\");\n return strategy.route(prompt, systemPrompt, maxOutputTokens, options);\n}\n\nexport { getStrategy, registerStrategy, applyUnavailableModels } from \"./strategy.js\";\nexport { RulesStrategy } from \"./strategy.js\";\nexport { PortfolioStrategy } from \"./portfolio.js\";\nexport { classifyByRules } from \"./rules.js\";\nexport { inferToolRequirement } from \"./tool-intent.js\";\nexport {\n getFallbackChain,\n getFallbackChainFiltered,\n filterByToolCalling,\n filterByVision,\n filterByExcludeList,\n filterCandidatesByCapacity,\n calculateModelCost,\n} from \"./selector.js\";\nexport { DEFAULT_ROUTING_CONFIG } from \"./config.js\";\nexport { DEFAULT_MODEL_CAPABILITIES } from \"./model-capabilities.js\";\nexport { LIVE_MODEL_PROFILES, HISTORICAL_MODEL_PROFILES } from \"./model-profiles.js\";\nexport type {\n RoutingDecision,\n Tier,\n TaskType,\n RoutingConfig,\n RouterOptions,\n RouterStrategy,\n} from \"./types.js\";\nexport type { ModelPricing } from \"./selector.js\";\nexport type { ModelCapabilities } from \"./model-capabilities.js\";\nexport type { ModelPerformanceProfile } from \"./model-profiles.js\";\n"],"mappings":"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;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA;AAAA,MAEd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA,IAGA,iBAAiB;AAAA;AAAA,MAEf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA,MAEpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA,MAEjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA,MAEhB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,wBAAwB;AAAA;AAAA,MAEtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;AAAA,IAIA,qBAAqB;AAAA;AAAA,MAEnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAA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","names":["confidence","decision","model"]} \ No newline at end of file diff --git a/model-capabilities.ts b/model-capabilities.ts index d9964e9..0982903 100644 --- a/model-capabilities.ts +++ b/model-capabilities.ts @@ -175,17 +175,11 @@ export const DEFAULT_MODEL_CAPABILITIES: Readonly