feat: zero-config OpenRouter for the plan() pipeline#90
Merged
Conversation
…ro-config
The OpenRouter auto-selection only reached the build/execute path
(ExecutionConfig/BuildConfig default_factory=_default_runtime). The plan
pipeline and its per-role model args hardcoded ai_provider="claude" and
model="sonnet", so on an OpenRouter-only deployment `af call
swe-planner.plan {...}` tried Claude and failed unless the caller passed
ai_provider/model on every call.
Make plan()'s ai_provider and *_model arguments default to None and
resolve from the environment, mirroring build/execute:
- ai_provider → _default_runtime() (honors SWE_DEFAULT_RUNTIME; auto
open_code when only an OpenRouter key is present, else claude_code).
- *_model → new _default_planning_model(): deployer env cascade
(SWE_DEFAULT_MODEL → AI_MODEL → HARNESS_MODEL), then the OpenRouter
default when OpenRouter-only, else "sonnet".
Explicit arguments always win, so Claude users see no behavior change
(claude_code maps to the same claude-code harness as the old "claude").
Tests: unit tests for _default_planning_model across the env matrix, and
plan()-wiring tests asserting the resolved ai_provider/model reach the
first sub-reasoner call (OpenRouter-only, Claude, explicit-override, and
SWE_DEFAULT_MODEL cases).
Co-Authored-By: Claude Opus 4.8 (1M context) <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.
Summary
The OpenRouter auto-selection added in #88 only reaches the build/execute path (
ExecutionConfig/BuildConfigusedefault_factory=_default_runtime). The plan pipeline and its per-role model args hardcodedai_provider="claude"/model="sonnet", so on an OpenRouter-only deployment:tried Claude and failed — you had to pass
ai_provider=open_code+model=openrouter/...on every call. (Discovered while smoke-testing an OpenRouter-only install:run_product_manageronly succeeded once those were passed explicitly.)Change
plan()'sai_providerand the five*_modelarguments now default toNoneand resolve from the environment, mirroring build/execute:ai_provider→_default_runtime()— honorsSWE_DEFAULT_RUNTIME; auto-selectsopen_codewhen only an OpenRouter key is present, elseclaude_code.*_model→ new_default_planning_model():SWE_DEFAULT_MODEL → AI_MODEL → HARNESS_MODELopenrouter/deepseek/deepseek-v4-flash) when OpenRouter-only"sonnet"otherwise (historical default)Explicit arguments always win. Claude users see no behavior change —
claude_codemaps to the sameclaude-codeharness the old"claude"did.Validation contract
ai_provider="open_code",model="openrouter/deepseek/deepseek-v4-flash".ai_provider="claude_code",model="sonnet"(unchanged).SWE_DEFAULT_MODEL(orAI_MODEL/HARNESS_MODEL) set → that model wins, on either path.ai_provider/*_modelargs → always honored over the env.Tests
TestDefaultPlanningModel—_default_planning_model()across the env matrix (claude / none / openrouter-only / SWE_DEFAULT_MODEL / AI_MODEL cascade).plan()-wiring tests asserting the resolvedai_provider/modelreach the first sub-reasoner call.make check(pytesttest_planner_pipeline.py+test_model_config.py= 68 passed incl. new;compileall) green.🤖 Generated with Claude Code