Skip to content

OpenRouter: stop rejecting every free model id - #283

Merged
KrasimirKralev merged 2 commits into
betafrom
fix/openrouter-free-model-ids
Aug 8, 2026
Merged

KrasimirKralev merged 2 commits into
betafrom
fix/openrouter-free-model-ids

Conversation

@yalexx

@yalexx yalexx commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

The bug

OPENROUTER_SLUG_RE in src/lib/openrouter-models.ts allowed [a-z0-9._-] and no colon:

/^[a-z0-9][a-z0-9._-]*(?:\/[a-z0-9][a-z0-9._-]*)+$/i

Every free model on OpenRouter is addressed as <org>/<model>:free. So the practical effect was that no free OpenRouter model could be configured on a ClawBox at all β€” the user pastes the correct id, and we hand back "invalid model id". It reads like OpenRouter rejected it; it didn't.

Routing variants (:online, :extended, :nitro, :thinking) were broken identically.

Chain: isValidModelId('openrouter', …) β†’ isValidOpenRouterModelId() β†’ this regex.

Reported

Discord, 2026-07-30, for nvidia/nemotron-3-ultra-550b-a55b:free β€” verified as the real, current id against https://openrouter.ai/api/v1/models. The user was told twice to check his id; his id was right.

The fix

Allow exactly one non-empty trailing :variant. Everything the pattern was written to catch still fails, and the new tests add cases it never covered:

now accepted still rejected
nvidia/nemotron-3-ultra-550b-a55b:free anthropic/claude-haiku-4.5: (bare colon)
qwen/qwen-2.5-vl-72b-instruct:free anthropic/claude-haiku-4.5:free:extra
perplexity/sonar:online anthropic:free (no slash)
openai/gpt-4o:extended anthropic/claude haiku:free (whitespace)
meta-llama/llama-3.3-70b-instruct:nitro empty, /leading, trailing/, a//b

Tests

openrouter-models.test.ts 30 pass; full unit suite 810 pass. (tsc reports one pre-existing unrelated error: missing node:sqlite types in migrate-auth-profiles.test.ts.)

Candidate for 3.1.12.

πŸ€– Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation for OpenRouter model IDs with supported variant suffixes such as :free, :online, :extended, and :nitro.
    • Correctly rejects malformed IDs with empty or multiple variant suffixes.
  • Tests

    • Expanded coverage for valid and invalid model ID formats.

`OPENROUTER_SLUG_RE` allowed `[a-z0-9._-]` and no colon, so any slug with a
`:variant` suffix failed `isValidOpenRouterModelId()`. Every FREE model on
OpenRouter is addressed as `<org>/<model>:free`, so the practical effect was
that NO free OpenRouter model could be configured on a ClawBox -- the user
pasted the correct id and got "invalid model id" back from us, not from
OpenRouter. Routing variants (`:online`, `:extended`, `:nitro`, `:thinking`)
were broken the same way.

Reported in Discord 2026-07-30 for `nvidia/nemotron-3-ultra-550b-a55b:free`,
which is the real, current id per https://openrouter.ai/api/v1/models.

Allow exactly one non-empty trailing `:variant`. Still rejects the things the
pattern was written to catch: empty/whitespace, no slash, leading/trailing
slash, doubled slashes -- plus new rejections for a bare trailing colon, a
second colon, a colon with no slash, and internal whitespace.

Unit suite 810 pass (openrouter-models.test.ts 30).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@yalexx
yalexx requested a review from a team as a code owner July 30, 2026 20:20
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

πŸ“ Walkthrough

Walkthrough

OpenRouter model ID validation now accepts an optional trailing :variant suffix after a valid organization/model slug. Unit tests cover supported variants and reject empty, repeated, or malformed colon usage.

Changes

OpenRouter model validation

Layer / File(s) Summary
Support trailing model variants
src/lib/openrouter-models.ts, src/tests/unit/openrouter-models.test.ts
The slug regex and documentation now allow one non-empty trailing variant, with tests covering valid variants and invalid colon usage.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has useful detail, but it doesn't follow the required template sections for Summary, Type of change, testing, checklist, or screenshots/logs. Rewrite it to match the template and add Summary, Type of change, How was this tested?, Checklist, and Screenshots/logs sections.
βœ… Passed checks (4 passed)
Check name Status Explanation
Title check βœ… Passed The title is concise and accurately summarizes the main change to OpenRouter model ID validation.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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 fix/openrouter-free-model-ids

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

πŸ”§ ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


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

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

πŸ¦€ ClawReview

Your friendly reef crab, here with the lay of the land.

Fixes a regex in src/lib/openrouter-models.ts that silently rejected every OpenRouter model ID containing a colon β€” which means every free model (e.g. nvidia/nemotron-3-ultra-550b-a55b:free) and all routing variants (:online, :extended, :nitro, :thinking) were blocked at validation, not by OpenRouter. The fix teaches the slug pattern about one optional trailing :variant segment, and expands the test suite with cases covering both the new valid forms and the still-rejected malformed ones.

At a glance

  • πŸ”§ Fix Β· touches OpenRouter model ID validation in AI-model config
  • Base branch: beta Β· +13 source / +13 tests across 2 files
  • βœ… base beta matches the beta-first convention
  • 🟑 title doesn't follow type: description (feat/fix/chore/docs/…)
  • βœ… source changes come with test changes

Good to know

  • ℹ️ Real user impact: a Discord report from 2026-07-30 showed the user was told twice their (correct) model ID was wrong. This fix unblocks every free-tier OpenRouter model on ClawBox.
  • ℹ️ Change is surgical β€” one regex line in openrouter-models.ts plus new test cases. Low blast radius.
  • ℹ️ 810 unit tests pass; one pre-existing TypeScript error in migrate-auth-profiles.test.ts (missing node:sqlite types) is unrelated to this PR.

β€” ClawReview πŸ¦€. I set the scene; CodeRabbit reviews the code; you decide. Conventions: docs.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

CI Summary

βœ… Tests

  • Result: passed
  • View run
  • Coverage: statements 70.81%, branches 61.09%, functions 66.6%, lines 72.73%

βœ… E2E

βœ… E2E Install

@coderabbitai coderabbitai Bot 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.

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 `@src/lib/openrouter-models.ts`:
- Around line 44-45: Update OPENROUTER_SLUG_RE in
src/lib/openrouter-models.ts:44-45 to require exactly one slash-delimited
author/model pair while preserving the optional variant suffix. Add
org/model/extra to the rejected cases in
src/tests/unit/openrouter-models.test.ts:57-61 as a regression test.
πŸͺ„ 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 64f5a46e-ebaf-4c12-9366-df1246e3ce9b

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between aeb34cd and 793c698.

πŸ“’ Files selected for processing (2)
  • src/lib/openrouter-models.ts
  • src/tests/unit/openrouter-models.test.ts

Comment on lines 44 to +45
const OPENROUTER_SLUG_RE =
/^[a-z0-9][a-z0-9._-]*(?:\/[a-z0-9][a-z0-9._-]*)+$/i;
/^[a-z0-9][a-z0-9._-]*(?:\/[a-z0-9][a-z0-9._-]*)+(?::[a-z0-9][a-z0-9._-]*)?$/i;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚑ Quick win

Align the validator and tests with the exact <org>/<model> contract.

The + quantifier currently accepts org/model/extra; OpenRouter documents the model shape as one author and one slug, with an optional variant suffix. (openrouter.ai)

  • src/lib/openrouter-models.ts#L44-L45: require exactly one slash-delimited model path.
  • src/tests/unit/openrouter-models.test.ts#L57-L61: add org/model/extra as a rejected regression case.
πŸ“ Affects 2 files
  • src/lib/openrouter-models.ts#L44-L45 (this comment)
  • src/tests/unit/openrouter-models.test.ts#L57-L61
πŸ€– 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 `@src/lib/openrouter-models.ts` around lines 44 - 45, Update OPENROUTER_SLUG_RE
in src/lib/openrouter-models.ts:44-45 to require exactly one slash-delimited
author/model pair while preserving the optional variant suffix. Add
org/model/extra to the rejected cases in
src/tests/unit/openrouter-models.test.ts:57-61 as a regression test.

@KrasimirKralev
KrasimirKralev merged commit 40f1210 into beta Aug 8, 2026
8 checks passed
@KrasimirKralev
KrasimirKralev deleted the fix/openrouter-free-model-ids branch August 8, 2026 17:19
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