OpenRouter: stop rejecting every free model id - #283
Conversation
`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>
π WalkthroughWalkthroughOpenRouter model ID validation now accepts an optional trailing ChangesOpenRouter model validation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
π₯ Pre-merge checks | β 4 | β 1β Failed checks (1 warning)
β Passed checks (4 passed)
β¨ Finishing Touchesπ Generate docstrings
π§ͺ Generate unit tests (beta)
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
ESLint install failed: dependency version conflict. Check your lock file or package.json. Comment |
π¦ ClawReviewYour 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 At a glance
Good to know
β ClawReview π¦. I set the scene; CodeRabbit reviews the code; you decide. Conventions: docs. |
There was a problem hiding this comment.
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
π Files selected for processing (2)
src/lib/openrouter-models.tssrc/tests/unit/openrouter-models.test.ts
| 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; |
There was a problem hiding this comment.
π― 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: addorg/model/extraas 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.
The bug
OPENROUTER_SLUG_REinsrc/lib/openrouter-models.tsallowed[a-z0-9._-]and no colon:/^[a-z0-9][a-z0-9._-]*(?:\/[a-z0-9][a-z0-9._-]*)+$/iEvery 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 againsthttps://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:nvidia/nemotron-3-ultra-550b-a55b:freeanthropic/claude-haiku-4.5:(bare colon)qwen/qwen-2.5-vl-72b-instruct:freeanthropic/claude-haiku-4.5:free:extraperplexity/sonar:onlineanthropic:free(no slash)openai/gpt-4o:extendedanthropic/claude haiku:free(whitespace)meta-llama/llama-3.3-70b-instruct:nitro/leading,trailing/,a//bTests
openrouter-models.test.ts30 pass; full unit suite 810 pass. (tscreports one pre-existing unrelated error: missingnode:sqlitetypes inmigrate-auth-profiles.test.ts.)Candidate for 3.1.12.
π€ Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
:free,:online,:extended, and:nitro.Tests