fix(acp): preserve session provider when switching models

This commit is contained in:
Gutslabs
2026-03-20 22:13:53 +03:00
committed by Teknium
parent decc7851f2
commit 0b9526b476
4 changed files with 139 additions and 11 deletions

View File

@@ -2,6 +2,7 @@
import asyncio
import os
from types import SimpleNamespace
from unittest.mock import MagicMock, AsyncMock, patch
import pytest
@@ -23,6 +24,7 @@ from acp.schema import (
)
from acp_adapter.server import HermesACPAgent, HERMES_VERSION
from acp_adapter.session import SessionManager
from hermes_state import SessionDB
@pytest.fixture()
@@ -389,3 +391,46 @@ class TestSlashCommands:
resp = await agent.prompt(prompt=prompt, session_id=new_resp.session_id)
assert resp.stop_reason == "end_turn"
def test_model_switch_uses_requested_provider(self, tmp_path, monkeypatch):
"""`/model provider:model` should rebuild the ACP agent on that provider."""
runtime_calls = []
def fake_resolve_runtime_provider(requested=None, **kwargs):
runtime_calls.append(requested)
provider = requested or "openrouter"
return {
"provider": provider,
"api_mode": "anthropic_messages" if provider == "anthropic" else "chat_completions",
"base_url": f"https://{provider}.example/v1",
"api_key": f"{provider}-key",
"command": None,
"args": [],
}
def fake_agent(**kwargs):
return SimpleNamespace(
model=kwargs.get("model"),
provider=kwargs.get("provider"),
base_url=kwargs.get("base_url"),
api_mode=kwargs.get("api_mode"),
)
monkeypatch.setattr("hermes_cli.config.load_config", lambda: {
"model": {"provider": "openrouter", "default": "openrouter/gpt-5"}
})
monkeypatch.setattr(
"hermes_cli.runtime_provider.resolve_runtime_provider",
fake_resolve_runtime_provider,
)
manager = SessionManager(db=SessionDB(tmp_path / "state.db"))
with patch("run_agent.AIAgent", side_effect=fake_agent):
acp_agent = HermesACPAgent(session_manager=manager)
state = manager.create_session(cwd="/tmp")
result = acp_agent._cmd_model("anthropic:claude-sonnet-4-6", state)
assert "Provider: anthropic" in result
assert state.agent.provider == "anthropic"
assert state.agent.base_url == "https://anthropic.example/v1"
assert runtime_calls[-1] == "anthropic"

View File

@@ -1,8 +1,9 @@
"""Tests for acp_adapter.session — SessionManager and SessionState."""
import json
from types import SimpleNamespace
import pytest
from unittest.mock import MagicMock
from unittest.mock import MagicMock, patch
from acp_adapter.session import SessionManager, SessionState
from hermes_state import SessionDB
@@ -281,3 +282,50 @@ class TestPersistence:
assert len(restored.history) == 2
assert restored.history[0].get("tool_calls") is not None
assert restored.history[1].get("tool_call_id") == "tc_1"
def test_restore_preserves_persisted_provider_snapshot(self, tmp_path, monkeypatch):
"""Restored ACP sessions should keep their original runtime provider."""
runtime_choice = {"provider": "anthropic"}
def fake_resolve_runtime_provider(requested=None, **kwargs):
provider = requested or runtime_choice["provider"]
return {
"provider": provider,
"api_mode": "anthropic_messages" if provider == "anthropic" else "chat_completions",
"base_url": f"https://{provider}.example/v1",
"api_key": f"{provider}-key",
"command": None,
"args": [],
}
def fake_agent(**kwargs):
return SimpleNamespace(
model=kwargs.get("model"),
provider=kwargs.get("provider"),
base_url=kwargs.get("base_url"),
api_mode=kwargs.get("api_mode"),
)
monkeypatch.setattr("hermes_cli.config.load_config", lambda: {
"model": {"provider": runtime_choice["provider"], "default": "test-model"}
})
monkeypatch.setattr(
"hermes_cli.runtime_provider.resolve_runtime_provider",
fake_resolve_runtime_provider,
)
db = SessionDB(tmp_path / "state.db")
with patch("run_agent.AIAgent", side_effect=fake_agent):
manager = SessionManager(db=db)
state = manager.create_session(cwd="/work")
manager.save_session(state.session_id)
with manager._lock:
del manager._sessions[state.session_id]
runtime_choice["provider"] = "openrouter"
restored = manager.get_session(state.session_id)
assert restored is not None
assert restored.agent.provider == "anthropic"
assert restored.agent.base_url == "https://anthropic.example/v1"