Skip to content

refactor: drop virtual model IDs and routing logic - #2199

Merged
steebchen merged 1 commit into
mainfrom
remove-virtual-models
May 15, 2026
Merged

steebchen merged 1 commit into
mainfrom
remove-virtual-models

Conversation

@steebchen

@steebchen steebchen commented May 7, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Removes the grok-4-fast and grok-4-1-fast virtual catalog entries that fanned out to concrete reasoning/non-reasoning siblings. Concrete grok-4-fast-{reasoning,non-reasoning} and grok-4-1-fast-{reasoning,non-reasoning} entries remain — callers now request those directly.
  • Drops resolveMetricsModelId and the modelName parameter on metricsKey / ProviderMetrics / getProviderMetricsForCombinations. Both existed only to disambiguate variants of a virtual model id.
  • Simplifies parseModelInput (no more multi-mapping branch) and removes the "virtual model variant routing" / resolveMetricsModelId test suites.

No backwards compatibility shim — clients calling model: "grok-4-1-fast" will now get a 400 and must switch to the explicit variant.

Net diff: -749 lines.

Test plan

  • pnpm build — 17/17 tasks
  • pnpm exec vitest run packages/actions packages/db apps/gateway/src/chat — 427/427 tests
  • Verify in staging that grok-4-fast-{reasoning,non-reasoning} and grok-4-1-fast-{reasoning,non-reasoning} resolve correctly when called explicitly

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

    • Simplified provider-metrics keying, improving consistency of auto-routing, cheapest-provider selection, multi-mapping behavior, rate-limit and low-uptime fallbacks, and direct-provider selection across chat and video.
    • Removed composite X.AI router entries; explicit variant models remain available for direct selection.
  • Tests

    • Updated test suites and fixtures to align with the new metrics key format.

Review Change Stack

Copilot AI review requested due to automatic review settings May 7, 2026 16:15
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented May 7, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Provider metrics keys were simplified to (modelId, providerId, region); code and tests across DB, actions, gateway/chat, and videos now build and read metrics using the reduced key shape and removed modelName-dependent helpers and entries.

Changes

Provider Metrics Key Simplification

Layer / File(s) Summary
Data Contract & Key Schema
packages/db/src/provider-metrics.ts
metricsKey signature removes modelName; ProviderMetrics and DB row mapping no longer include modelName; getProviderMetricsForCombinations accepts combinations without modelName.
Provider Selection Implementation
packages/actions/src/get-cheapest-from-available-providers.ts
Removed exported resolveMetricsModelId; random-exploration and weighted-score metrics lookups now use metricsKey(modelId, providerId, region).
Chat Routing Integration
apps/gateway/src/chat/chat.ts
Auto-routing, specific-provider multi-mapping, rate-limit fallback, low-uptime fallback, content-filter rerouting, and direct-selection metadata now build metric combinations and read metrics using the simplified key.
Video Routing Integration
apps/gateway/src/videos/videos.ts
resolveVideoExecution builds metrics combinations and uptime comparisons using metricsKey(modelInfo.id, providerId, region) (no modelName).
Model Input Parsing
apps/gateway/src/chat/tools/parse-model-input.ts
Provider-mapping resolution simplified to a single find lookup; requestedModel set from mapping modelName when present.
Model Registry Cleanup
packages/models/src/models/xai.ts
Removed composite routing entries grok-4-fast and grok-4-1-fast; explicit variant models retained.
Test Coverage
packages/actions/src/models.spec.ts, packages/db/src/provider-metrics.spec.ts
Fixtures and assertions updated to construct/look up metrics with three-parameter metricsKey(..., region); tests and imports for resolveMetricsModelId removed.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • theopenco/llmgateway#2158: Modifies related routing/metrics keying logic and takes a different approach to modelName/variant handling.
  • theopenco/llmgateway#2042: Changes low-uptime fallback candidate selection and interacts with the same fallback scoring paths updated here.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: drop virtual model IDs and routing logic' directly and specifically summarizes the main change in the changeset: removing virtual model catalog entries and their associated metrics/routing disambiguation logic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch remove-virtual-models

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors model routing/metrics to remove support for “virtual” Grok Fast model IDs, requiring callers to use the explicit reasoning/non-reasoning model IDs and simplifying metrics lookups accordingly.

Changes:

  • Removes grok-4-fast / grok-4-1-fast virtual catalog entries and related routing behavior.
  • Drops resolveMetricsModelId and removes modelName from metricsKey / provider-metrics APIs and call sites.
  • Simplifies parseModelInput and deletes tests that existed only for virtual-model disambiguation.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/models/src/models/xai.ts Removes virtual Grok Fast catalog entries that previously fanned out to concrete variants.
packages/db/src/provider-metrics.ts Simplifies metrics keying and metrics query payload by removing modelName from the metrics identity.
packages/db/src/provider-metrics.spec.ts Updates tests to the new metricsKey(modelId, providerId, region) behavior and removes virtual-variant disambiguation coverage.
packages/actions/src/models.spec.ts Removes resolveMetricsModelId tests and updates metrics-keyed fixtures to the new key shape.
packages/actions/src/get-cheapest-from-available-providers.ts Removes resolveMetricsModelId and switches metrics lookups to use the catalog modelId directly.
apps/gateway/src/videos/videos.ts Updates metrics combination construction / lookups to no longer include modelName/variant model IDs.
apps/gateway/src/chat/tools/parse-model-input.ts Removes the multi-mapping “routing model” branch and always resolves to the provider mapping’s modelName when available.
apps/gateway/src/chat/chat.ts Updates all metrics combination construction / lookups to use base model IDs and the simplified metricsKey.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 18 to 27
/**
* Build a metrics map key from modelId, providerId, optional region, and
* optional provider modelName. Including modelName disambiguates virtual
* model variants (e.g. reasoning vs non-reasoning) that share the same
* (modelId, providerId, region) tuple in the routing tables.
* Build a metrics map key from modelId, providerId, and optional region.
*/
export function metricsKey(
modelId: string,
providerId: string,
region?: string | null,
modelName?: string | null,
): string {
return `${modelId}:${providerId}:${region ?? ""}:${modelName ?? ""}`;
return `${modelId}:${providerId}:${region ?? ""}`;
}
@steebchen
steebchen force-pushed the remove-virtual-models branch from a98bbef to bc90077 Compare May 13, 2026 11:12
Removes the grok-4-fast and grok-4-1-fast virtual catalog entries that
fanned out to concrete reasoning/non-reasoning siblings, along with the
helpers that existed solely to disambiguate them:

- resolveMetricsModelId (and call sites in chat.ts, videos.ts)
- modelName param on metricsKey / ProviderMetrics / combinations
- the multi-provider-mapping branch in parseModelInput
- the test fixtures and "virtual model variant routing" suite

Concrete grok-4-fast-{reasoning,non-reasoning} entries remain — callers
now request those directly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@steebchen
steebchen force-pushed the remove-virtual-models branch from bc90077 to f79e179 Compare May 15, 2026 14:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/gateway/src/chat/tools/parse-model-input.ts`:
- Around line 97-100: The current use of modelDef.providers.find(...) only picks
the first provider mapping and misses other mappings (e.g., multiple moonshot
entries); update the logic that sets requestedModel so it considers all mappings
in modelDef.providers for the requestedProvider: use filter(...) to collect all
entries where p.providerId === requestedProvider, then pick the correct mapping
either by matching an explicit version indicator in the incoming request (if
available) or by choosing the most recent/active mapping (compare version
strings/dates) and assign requestedModel from that chosen mapping (fall back to
modelName if none match); update the code around providerMapping,
modelDef.providers, requestedProvider, requestedModel and modelName accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f8b24359-701e-4d58-abca-5d13844040ff

📥 Commits

Reviewing files that changed from the base of the PR and between bc90077 and f79e179.

📒 Files selected for processing (8)
  • apps/gateway/src/chat/chat.ts
  • apps/gateway/src/chat/tools/parse-model-input.ts
  • apps/gateway/src/videos/videos.ts
  • packages/actions/src/get-cheapest-from-available-providers.ts
  • packages/actions/src/models.spec.ts
  • packages/db/src/provider-metrics.spec.ts
  • packages/db/src/provider-metrics.ts
  • packages/models/src/models/xai.ts
💤 Files with no reviewable changes (1)
  • packages/models/src/models/xai.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • apps/gateway/src/videos/videos.ts
  • packages/db/src/provider-metrics.spec.ts
  • packages/actions/src/get-cheapest-from-available-providers.ts
  • packages/actions/src/models.spec.ts
  • apps/gateway/src/chat/chat.ts
  • packages/db/src/provider-metrics.ts

Comment on lines +97 to +100
const providerMapping = modelDef.providers.find(
(p) => p.providerId === requestedProvider,
);
if (providerMappings.length > 1) {
requestedModel = modelDef.id as Model;
} else if (providerMappings.length === 1) {
requestedModel = providerMappings[0].modelName;
} else {
requestedModel = modelName as Model;
}
requestedModel = (providerMapping?.modelName ?? modelName) as Model;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find model definition files (likely TS in models package)
fd -i 'xai.ts|models.ts|model.*\.ts|.*models.*\.ts' packages/models src apps 2>/dev/null || true

# Surface provider arrays where the same providerId appears more than once within one model object.
python - <<'PY'
import re, pathlib, json

roots = [pathlib.Path("packages/models"), pathlib.Path("apps"), pathlib.Path("src")]
files = []
for r in roots:
    if r.exists():
        files.extend([p for p in r.rglob("*.ts") if "node_modules" not in p.parts])

model_block_re = re.compile(r'\{[^{}]*?\bid\s*:\s*"([^"]+)"[^{}]*?\bproviders\s*:\s*\[', re.S)
provider_id_re = re.compile(r'providerId\s*:\s*"([^"]+)"')

found_any = False
for f in files:
    text = f.read_text(encoding="utf-8", errors="ignore")
    idx = 0
    while True:
        m = model_block_re.search(text, idx)
        if not m:
            break
        model_id = m.group(1)
        start = m.end() - 1  # at '['
        depth = 0
        end = start
        for i in range(start, len(text)):
            c = text[i]
            if c == '[':
                depth += 1
            elif c == ']':
                depth -= 1
                if depth == 0:
                    end = i
                    break
        providers_chunk = text[start:end+1]
        provider_ids = provider_id_re.findall(providers_chunk)
        dups = sorted({p for p in provider_ids if provider_ids.count(p) > 1})
        if dups:
            found_any = True
            print(f"{f}: model '{model_id}' has duplicate providerId entries: {', '.join(dups)}")
        idx = end + 1

if not found_any:
    print("No duplicate providerId entries detected within model.providers arrays.")
PY

Repository: theopenco/llmgateway

Length of output: 2052


🏁 Script executed:

# First, let's understand the repository structure and find model-related files
git ls-files | head -20

Repository: theopenco/llmgateway

Length of output: 599


🏁 Script executed:

# Find files that likely contain model definitions
find . -path ./node_modules -prune -o -type f -name "*.ts" -print | grep -i model | head -30

Repository: theopenco/llmgateway

Length of output: 1378


🏁 Script executed:

# Read the file under review to understand context
cat -n ./apps/gateway/src/chat/tools/parse-model-input.ts

Repository: theopenco/llmgateway

Length of output: 5381


🏁 Script executed:

# Look at the model definitions structure
head -100 ./packages/models/src/models.ts

Repository: theopenco/llmgateway

Length of output: 3381


🏁 Script executed:

# Continue reading to see model structure
sed -n '80,200p' ./packages/models/src/models.ts

Repository: theopenco/llmgateway

Length of output: 3844


🏁 Script executed:

# Look at a specific model definition file to see structure
head -150 ./packages/models/src/models/openai.ts

Repository: theopenco/llmgateway

Length of output: 3694


🏁 Script executed:

# Search all model definition files for duplicate providerId within the same model
python3 << 'EOF'
import re
import pathlib

# Find all model definition files in packages/models/src/models/
model_files = list(pathlib.Path("./packages/models/src/models").glob("*.ts"))

duplicate_found = False

for model_file in sorted(model_files):
    content = model_file.read_text()
    
    # Match model definitions: find id and its providers array
    model_pattern = r'\{\s*id:\s*"([^"]+)"[^}]*?providers:\s*\['
    
    for m in re.finditer(model_pattern, content, re.DOTALL):
        model_id = m.group(1)
        start = m.end() - 1  # Start at '['
        
        # Find matching closing bracket
        depth = 0
        end = start
        for i in range(start, len(content)):
            if content[i] == '[':
                depth += 1
            elif content[i] == ']':
                depth -= 1
                if depth == 0:
                    end = i
                    break
        
        providers_chunk = content[start:end+1]
        
        # Find all providerId values
        provider_ids = re.findall(r'providerId:\s*"([^"]+)"', providers_chunk)
        
        # Check for duplicates
        seen = {}
        for pid in provider_ids:
            if pid in seen:
                duplicate_found = True
                print(f"{model_file.name}: model '{model_id}' has duplicate providerId '{pid}'")
                seen[pid] += 1
            else:
                seen[pid] = 1

if not duplicate_found:
    print("✓ No duplicate providerId entries found within any model definition.")
EOF

Repository: theopenco/llmgateway

Length of output: 129


🏁 Script executed:

# Find and display the kimi-k2 model definition
grep -A 100 'id: "kimi-k2"' ./packages/models/src/models/moonshot.ts | head -120

Repository: theopenco/llmgateway

Length of output: 2488


Fix .find() logic to handle multiple provider mappings per model.

The code assumes only one providerId mapping exists per model, but kimi-k2 in moonshot.ts has two entries with providerId: "moonshot" (for versions kimi-k2-0711-preview and kimi-k2-0905-preview). When a user requests "moonshot/kimi-k2", .find() silently returns the first mapping, ignoring other versions. Either match both providerId and a version indicator, or select based on which version is most recent/active.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/gateway/src/chat/tools/parse-model-input.ts` around lines 97 - 100, The
current use of modelDef.providers.find(...) only picks the first provider
mapping and misses other mappings (e.g., multiple moonshot entries); update the
logic that sets requestedModel so it considers all mappings in
modelDef.providers for the requestedProvider: use filter(...) to collect all
entries where p.providerId === requestedProvider, then pick the correct mapping
either by matching an explicit version indicator in the incoming request (if
available) or by choosing the most recent/active mapping (compare version
strings/dates) and assign requestedModel from that chosen mapping (fall back to
modelName if none match); update the code around providerMapping,
modelDef.providers, requestedProvider, requestedModel and modelName accordingly.

@steebchen
steebchen merged commit 797001b into main May 15, 2026
17 of 18 checks passed
@steebchen
steebchen deleted the remove-virtual-models branch May 15, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants