Skip to content

feat: zero-config OpenRouter for the plan() pipeline#90

Merged
AbirAbbas merged 1 commit into
mainfrom
feat/plan-openrouter-defaults
Jul 7, 2026
Merged

feat: zero-config OpenRouter for the plan() pipeline#90
AbirAbbas merged 1 commit into
mainfrom
feat/plan-openrouter-defaults

Conversation

@AbirAbbas

Copy link
Copy Markdown
Collaborator

Summary

The OpenRouter auto-selection added in #88 only reaches the build/execute path (ExecutionConfig/BuildConfig use default_factory=_default_runtime). The plan pipeline and its per-role model args hardcoded ai_provider="claude" / model="sonnet", so on an OpenRouter-only deployment:

af call swe-planner.plan '{"goal":"...","repo_path":"..."}'

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_manager only succeeded once those were passed explicitly.)

Change

plan()'s ai_provider and the five *_model arguments now default to None and resolve from the environment, mirroring build/execute:

  • ai_provider_default_runtime() — honors SWE_DEFAULT_RUNTIME; auto-selects open_code when only an OpenRouter key is present, else claude_code.
  • *_model → new _default_planning_model():
    1. deployer env cascade SWE_DEFAULT_MODEL → AI_MODEL → HARNESS_MODEL
    2. the OpenRouter default (openrouter/deepseek/deepseek-v4-flash) when OpenRouter-only
    3. "sonnet" otherwise (historical default)

Explicit arguments always win. Claude users see no behavior changeclaude_code maps to the same claude-code harness the old "claude" did.

Validation contract

  • OpenRouter-only env, no args → sub-reasoners get ai_provider="open_code", model="openrouter/deepseek/deepseek-v4-flash".
  • Anthropic key present → ai_provider="claude_code", model="sonnet" (unchanged).
  • SWE_DEFAULT_MODEL (or AI_MODEL/HARNESS_MODEL) set → that model wins, on either path.
  • Explicit ai_provider/*_model args → always honored over the env.

Tests

  • TestDefaultPlanningModel_default_planning_model() across the env matrix (claude / none / openrouter-only / SWE_DEFAULT_MODEL / AI_MODEL cascade).
  • Four plan()-wiring tests asserting the resolved ai_provider/model reach the first sub-reasoner call.

make check (pytest test_planner_pipeline.py + test_model_config.py = 68 passed incl. new; compileall) green.

Note: pairs with #89 (honor the control-plane PORT) — both needed for a clean af installaf runaf call on an OpenRouter-only box.

🤖 Generated with Claude Code

…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>
@AbirAbbas AbirAbbas merged commit 5be5ef4 into main Jul 7, 2026
2 checks passed
@AbirAbbas AbirAbbas deleted the feat/plan-openrouter-defaults branch July 7, 2026 23:48
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