Skip to content

OpenRouter: stop rejecting every free model id - #283

Open
yalexx wants to merge 1 commit into
betafrom
fix/openrouter-free-model-ids
Open

OpenRouter: stop rejecting every free model id#283
yalexx wants to merge 1 commit 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

Copy link
Copy Markdown

πŸ¦€ ClawReview

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

The regex guarding OpenRouter model IDs never allowed a colon, which silently blocked every free-tier model (addressed as <org>/<model>:free) and all routing variants (:online, :nitro, etc.) from being saved. One character-class extension β€” (?::[a-z0-9][a-z0-9._-]*)? β€” admits exactly one well-formed trailing variant while still rejecting malformed IDs. A user on Discord reported their correct model ID as invalid; this is the underlying cause.

At a glance

  • πŸ”§ Fix Β· touches OpenRouter model ID validation in AI-model config (AIModelsStep β†’ isValidModelId)
  • 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

  • 🟑 Fixes a silent user-facing regression: every free OpenRouter model was unusable β€” the device rejected a correct ID with no clear error message.
  • ℹ️ Change is surgical (one regex group added); 30 new test cases cover the previously untested :variant paths, 810 total pass.
  • ℹ️ Candidate for 3.1.12 per PR body β€” touches the model-ID path used during both setup and live provider changes.

β€” 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.37%, branches 60.28%, functions 65.71%, lines 72.35%

βœ… 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.

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.

1 participant