Route models by harness namespace, not a curated allow-list#2
Merged
Conversation
A model routes to the harness whose name namespace owns it (Harness.has_model), so a provider's new model runs the day it ships — no druks release to extend a hardcoded tuple. The per-harness `models` tuple demotes from an allow-list to picker suggestions. Write-boundary validation keeps two coherence checks as namespace checks: a harness row's model must be in its own namespace, and an agent override must be runnable by some installed harness (else it'd 500 the settings read). Drops the unused ExtensionsSettingsResponse model union and the dead frontend ALLOWED_*_MODELS constants. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Adding any new model — a new Claude or Codex release — currently means editing hardcoded
modelstuples on each harness and cutting a druks release. Codex CLI never does this: it passes the model string through and routes by provider, so a new model works the day it ships. This does the same.What
model_prefixes;Harness.has_model(model)matches on them (or the family token).get_harness_for_modeluses it, soclaude-opus-5/gpt-6route with no code change.modelsdemotes from allow-list → picker suggestions (advisory). TheHarnessResponse.allowedModelsthe settings UI renders is unchanged, so the dropdowns keep working.gpt-5.5on the claude row), and an agent override must be runnable by some installed harness (else it 500s the settings read). Neither is a curated list — a new in-namespace model passes.ExtensionsSettingsResponse.allowed_modelsunion + its registry function, and the dead frontendALLOWED_*_MODELSconstants (zero consumers).get_harness_for_modelnow raises the typedHarnessError(wasValueError).Not in this PR
The settings model pickers are still suggestion dropdowns — the new-model-without-release path is via the settings API / config (like codex's
config.toml), not free-text in the UI yet. A free-text combobox is an easy follow-up if wanted.Verification
ruff check backendclean; frontendtsc -b+eslintclean.test_harness_model_routing.pycovers namespace routing, the family token, and the unroutable-model raise.The one line that'd ever need touching for a brand-new provider namespace:
CodexHarness.model_prefixes/ClaudeHarness.model_prefixes.