Skip to content

feat: runtime config switching across REPL, ACP, and HTTP - #563

Merged
delete-cloud merged 2 commits into
mainfrom
feat/runtime-config-switching
Jun 10, 2026
Merged

delete-cloud merged 2 commits into
mainfrom
feat/runtime-config-switching

Conversation

@delete-cloud

@delete-cloud delete-cloud commented Jun 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

Add the ability to switch model/provider/base_url at runtime on an existing session without losing conversation context. Previously only the REPL could change the model (and only via /model name). Now all three entrypoints support runtime config switching, and changing provider (e.g. codex ↔ deepseek) is also supported.

Changes

Core (RuntimeReplacementService)

  • replace_runtime_config() now accepts optional provider_name and base_url alongside model_name
  • Transactional: new config persisted atomically with rollback to old binding on failure

HTTP API

  • PATCH /sessions/{session_id}/runtime-config — accepts {model, provider, base_url} in any combination
  • Returns 409 on active turn, 400 if no fields provided

ACP Protocol

  • AcpMode dataclass for config-driven provider/model presets
  • session/set_mode now matches arbitrary modeId and calls replace internally
  • CLI: --acp-mode (repeatable) and --acp-modes-json options
  • Modes exposed in both initialize and session/new responses

REPL

  • /model [provider:]name — e.g. /model deepseek:deepseek-chat
  • Backward compatible: /model gpt-4o still works

Verification

  • 118 relevant tests pass (3 replacement service tests updated for new protocol fields)
  • Pre-existing 15 cli_pipeline failures unrelated

Usage

// HTTP: switch provider+model
PATCH /sessions/{id}/runtime-config
{"provider": "deepseek", "model": "deepseek-chat"}
// ACP: define modes and switch via session/set_mode
--acp-mode "pro:ChatGPT Pro:codex:gpt-5.5" --acp-mode "ds:DeepSeek:deepseek:deepseek-chat"
// REPL
/model deepseek:deepseek-chat
/model gpt-4o

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

Summary by CodeRabbit

  • New Features

    • Added CLI support for defining multiple ACP mode presets via --acp-mode and --acp-modes-json options.
    • Added HTTP endpoint to update session runtime configuration (provider, model, base URL).
  • Enhancements

    • Model command now supports provider:model syntax for specifying both provider and model.
    • REPL sessions can now update provider alongside model during runtime.

Add ability to switch model/provider/base_url at runtime on an
existing session without losing conversation context.

Core layer (RuntimeReplacementService):
- Expand replace_runtime_config to accept optional provider_name
  and base_url parameters alongside model_name
- Update RuntimeReplacementBuilder protocol accordingly
- Persist new config transactionally with rollback on failure

HTTP API:
- Add PATCH /sessions/{session_id}/runtime-config endpoint
  accepting {model, provider, base_url} in any combination
- Returns 409 on active turn, 400/404 on invalid input
- New schemas: RuntimeConfigUpdateRequest/Response

ACP protocol:
- Add AcpMode dataclass for provider/model presets
- session/set_mode now matches modeId against configurable modes
  and calls replace_session_runtime_config internally
- initialize response includes available modes
- CLI: --acp-mode and --acp-modes-json options

REPL:
- /model [provider:]name syntax (e.g. /model deepseek:ds-chat)
- Backward compatible: /model gpt-4 still works
- Provider displayed in /model status output

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9109aee5-d12b-43f2-88f0-746f2b150bd8

📥 Commits

Reviewing files that changed from the base of the PR and between 4d8cafe and 0568935.

📒 Files selected for processing (11)
  • coding-agent/src/coding_agent/acp/__init__.py
  • coding-agent/src/coding_agent/acp/server.py
  • coding-agent/src/coding_agent/cli/acp_command.py
  • coding-agent/src/coding_agent/cli/commands.py
  • coding-agent/src/coding_agent/cli/local_runtime.py
  • coding-agent/src/coding_agent/cli/repl.py
  • coding-agent/src/coding_agent/runs/replacement.py
  • coding-agent/src/coding_agent/server/http_server.py
  • coding-agent/src/coding_agent/server/schemas.py
  • coding-agent/src/coding_agent/server/session_manager.py
  • coding-agent/tests/coding_agent/test_runtime_replacement_service.py

📝 Walkthrough

Walkthrough

This PR extends the coding agent to support configurable ACP "modes" (provider/model presets) and adds the ability to update session runtime configuration (model, provider, base URL) through CLI commands, REPL interactions, and HTTP endpoints.

Changes

ACP Modes Configuration and Runtime Updates

Layer / File(s) Summary
ACP Mode Data Model
coding-agent/src/coding_agent/acp/server.py, coding-agent/src/coding_agent/acp/__init__.py
Introduces AcpMode dataclass with id, name, description, provider, model, and base_url fields; adds default_acp_modes() helper; exports the type from the acp package.
ACP Server Mode Storage and Initialization
coding-agent/src/coding_agent/acp/server.py
AcpServer.__init__ accepts optional modes parameter and stores it with fallback to defaults; AcpSessionManager protocol is extended with replace_session_runtime_config method; _session_mode_state generates response payloads from configured modes.
ACP Mode Switching and Response Updates
coding-agent/src/coding_agent/acp/server.py
_session_set_mode now validates modeId, looks up the selected mode from the configured list, invokes replace_session_runtime_config with mode fields, and maps runtime/value failures to JSON-RPC errors; initialize, session/new, and session/resume responses include computed modes state.
Runtime Replacement Protocol Extension
coding-agent/src/coding_agent/runs/replacement.py
RuntimeReplacementSession protocol declares optional provider_name and base_url fields; RuntimeReplacementBuilder.__call__ and RuntimeReplacementService.replace_runtime_config accept these new optional parameters, snapshot prior values, and restore them on rollback failure.
Session Manager Runtime Config Method
coding-agent/src/coding_agent/server/session_manager.py
SessionManager.replace_session_runtime_config accepts optional model_name, provider_name, and base_url; resolves model_name from the admitted session when unset; forwards all parameters to the runtime replacement service.
Local CLI Session Manager Binding
coding-agent/src/coding_agent/cli/local_runtime.py
LocalCliSessionManager protocol and ServerBackedLocalCliSessionManager implementation extended to accept and forward optional provider_name and base_url parameters alongside model_name.
CLI Mode Configuration Parser and Options
coding-agent/src/coding_agent/cli/acp_command.py
Introduces _parse_acp_mode() to parse id:name[:provider[:model[:base_url]]] strings into AcpMode objects; adds repeatable --acp-mode and alternative --acp-modes-json Click options; implements mode selection logic and passes computed modes list to AcpServer.
REPL Session Provider and Model Updates
coding-agent/src/coding_agent/cli/repl.py
_change_model_for_next_turn extended to accept optional provider_name parameter; expands allowed provider set on session restore; syncs context with current provider when switching sessions; implements coordinated model/provider updates and rollback in runtime replacement path.
CLI /model Command Provider:Model Syntax
coding-agent/src/coding_agent/cli/commands.py
/model command now parses optional provider:model input; updates context["provider_override"] when provider prefix is present; modifies on_model_change hook signature to accept both model name and optional provider; adjusts success and current-model display messages.
HTTP Server Runtime Config Update Endpoint
coding-agent/src/coding_agent/server/schemas.py, coding-agent/src/coding_agent/server/http_server.py
Adds RuntimeConfigUpdateRequest and RuntimeConfigUpdateResponse Pydantic schemas with strict validation; implements PATCH /sessions/{session_id}/runtime-config endpoint that validates at least one field is provided, checks session state, delegates to replace_session_runtime_config, and maps errors to appropriate HTTP responses.
Runtime Replacement Service Test Updates
coding-agent/tests/coding_agent/test_runtime_replacement_service.py
Updates FakeSession fixture to track provider_name and base_url; extends build_runtime test helper signatures to accept these new parameters; adds assertions for value replacement and rollback; verifies provider_name and base_url restoration on persistent failure.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 Modes bloom in gardens new, with providers sweet and base URLs true,
The REPL hops through provider paths, while HTTP endpoints handle the math.
Runtime configs now dance and sway, replaced by dawn of brand new day! 🌅

✨ 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 feat/runtime-config-switching

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

When session/set_mode tries to replace runtime config with an invalid
provider name, create_agent_for_session raises ValueError. The ACP
handler only caught RuntimeError, so the unhandled exception would
propagate past handle_message (no generic except) and out of the
stdio reader loop instead of returning a structured error.

Also adds empty-mode-id guard in _parse_acp_mode for malformed
--acp-mode strings like '::'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@delete-cloud
delete-cloud marked this pull request as ready for review June 10, 2026 13:33
@delete-cloud
delete-cloud merged commit 453dfcb into main Jun 10, 2026
1 check was pending
@delete-cloud
delete-cloud deleted the feat/runtime-config-switching branch June 10, 2026 13:33
delete-cloud added a commit that referenced this pull request Jun 11, 2026
* feat(runtime): three-state base_url semantics with UNSET sentinel

Distinguish "not provided" (UNSET, keep current) from explicit None
(reset to provider default) across the runtime replacement chain:
RuntimeReplacementService, LocalDaemonRuntimePreparationService,
SessionManager.replace_session_runtime_config, and the local CLI
session manager protocol. Previously None was overloaded as "keep",
so a session's base_url could never be cleared back to the provider
default once set.

Verified: tests/coding_agent/test_runtime_replacement_service.py
(5 passed, including new clear + rollback-after-clear cases).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(http): three-state semantics for PATCH runtime-config

Use model_fields_set to distinguish omitted fields from explicit null:
omitted = unchanged, base_url null = reset to provider default, value =
set. Explicit null for model/provider/thinking has no meaningful reset
target and is rejected with 422 via a field validator. Empty body still
returns 400.

Verified: tests/coding_agent/test_runtime_config_schema.py (6 passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(acp): declarative base_url on mode switch

A mode that names a provider now fully describes that provider's
config: an omitted base_url resets to the provider default instead of
leaking the previous mode's endpoint onto the new provider. Model-only
modes (no provider, no base_url) keep the session's current endpoint.

Also updates three stale test assertions that predate the #563 modes
feature (initialize response now advertises modes; unknown-modeId error
message changed) and adds FakeManager.replace_session_runtime_config.

Verified: tests/acp (63 passed, was 3 pre-existing failures).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(repl): accept provider_name/base_url kwargs in runtime fakes

The repl fakes for replace_session_runtime_config and
_build_session_runtime were not updated when #563 added provider_name,
leaving two tests failing on main with TypeError. Widen the fake
signatures to match the real call sites.

Verified: tests/cli/test_repl.py (53 passed, was 2 failures).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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