diff --git a/coding-agent/src/coding_agent/acp/__init__.py b/coding-agent/src/coding_agent/acp/__init__.py
index 99e09214a..d226f6d23 100644
--- a/coding-agent/src/coding_agent/acp/__init__.py
+++ b/coding-agent/src/coding_agent/acp/__init__.py
@@ -1,5 +1,5 @@
"""Agent Client Protocol stdio adapter for Coding Agent."""
-from coding_agent.acp.server import AcpServer, run_stdio
+from coding_agent.acp.server import AcpMode, AcpServer, run_stdio
-__all__ = ["AcpServer", "run_stdio"]
+__all__ = ["AcpMode", "AcpServer", "run_stdio"]
diff --git a/coding-agent/src/coding_agent/acp/server.py b/coding-agent/src/coding_agent/acp/server.py
index 530387c05..ae479fbf2 100644
--- a/coding-agent/src/coding_agent/acp/server.py
+++ b/coding-agent/src/coding_agent/acp/server.py
@@ -2,6 +2,7 @@
import asyncio
from collections.abc import AsyncIterator, Awaitable, Callable, Iterable
+from dataclasses import dataclass
import json
from pathlib import Path
import sys
@@ -26,6 +27,32 @@
ACP_DEFAULT_MODE_ID = "default"
+@dataclass(frozen=True)
+class AcpMode:
+ """A named provider/model preset exposed as an ACP session mode."""
+
+ id: str
+ name: str
+ description: str = ""
+ provider: str | None = None
+ model: str | None = None
+ base_url: str | None = None
+
+
+def default_acp_modes() -> list[AcpMode]:
+ """Return the default single-mode configuration.
+
+ Override by passing custom modes to AcpServer or via ACP_TOML config.
+ """
+ return [
+ AcpMode(
+ id=ACP_DEFAULT_MODE_ID,
+ name="Default",
+ description="Standard Coding Agent behavior.",
+ ),
+ ]
+
+
class AcpSessionManager(Protocol):
async def create_session(self, **kwargs: Any) -> str: ...
@@ -72,6 +99,15 @@ async def update_session_additional_directories(
additional_directories: list[str],
) -> None: ...
+ async def replace_session_runtime_config(
+ self,
+ session_id: str,
+ *,
+ model_name: str | None = None,
+ provider_name: str | None = None,
+ base_url: str | None = None,
+ ) -> Any: ...
+
class JsonRpcError(Exception):
def __init__(self, code: int, message: str) -> None:
@@ -92,6 +128,7 @@ def __init__(
model_name: str | None = None,
base_url: str | None = None,
max_steps: int = 30,
+ modes: list[AcpMode] | None = None,
) -> None:
self._session_manager = session_manager
self._emit = emit
@@ -101,6 +138,9 @@ def __init__(
self._model_name = model_name
self._base_url = base_url
self._max_steps = max_steps
+ self._modes = (
+ modes if modes is not None else default_acp_modes()
+ )
self._active_prompt_sessions: set[str] = set()
self._cancelled_prompt_sessions: set[str] = set()
@@ -173,10 +213,10 @@ async def _dispatch(self, method: str, params: JSONObject) -> object:
return await self._session_new(params)
if method == "session/load":
await self._session_load(params)
- return {"modes": _session_mode_state()}
+ return {"modes": _session_mode_state(self._modes)}
if method == "session/resume":
await self._session_resume(params)
- return {"modes": _session_mode_state()}
+ return {"modes": _session_mode_state(self._modes)}
if method == "session/list":
return await self._session_list(params)
if method == "session/close":
@@ -213,6 +253,7 @@ def _initialize(self, params: JSONObject) -> JSONObject:
"additionalDirectories": {},
},
},
+ "modes": _session_mode_state(self._modes),
"agentInfo": {
"name": "coding-agent",
"title": "Coding Agent",
@@ -260,7 +301,7 @@ async def _session_new(self, params: JSONObject) -> JSONObject:
mcp_servers=mcp_servers,
additional_directories=additional_directories,
)
- return {"sessionId": session_id, "modes": _session_mode_state()}
+ return {"sessionId": session_id, "modes": _session_mode_state(self._modes)}
async def _session_list(self, params: JSONObject) -> JSONObject:
cursor = params.get("cursor")
@@ -399,12 +440,32 @@ async def _session_set_mode(self, params: JSONObject) -> None:
-32602, "session/set_mode params.sessionId must be a string"
)
mode_id = params.get("modeId")
- if mode_id != ACP_DEFAULT_MODE_ID:
+ if not isinstance(mode_id, str) or not mode_id:
+ raise JsonRpcError(
+ -32602, "session/set_mode params.modeId must be a string"
+ )
+
+ mode = next((m for m in self._modes if m.id == mode_id), None)
+ if mode is None:
raise JsonRpcError(
-32602,
- f"session/set_mode params.modeId must be {ACP_DEFAULT_MODE_ID}",
+ f"session/set_mode unknown modeId: {mode_id}",
)
+
await self._session_manager.get_session_async(session_id)
+ try:
+ await self._session_manager.replace_session_runtime_config(
+ session_id,
+ model_name=mode.model,
+ provider_name=mode.provider,
+ base_url=mode.base_url,
+ )
+ except RuntimeError as exc:
+ if str(exc) == "turn already in progress":
+ raise JsonRpcError(-32000, "Turn already in progress") from exc
+ raise JsonRpcError(-32603, str(exc)) from exc
+ except ValueError as exc:
+ raise JsonRpcError(-32603, str(exc)) from exc
async def _session_set_config_option(self, params: JSONObject) -> JSONObject:
session_id = params.get("sessionId")
@@ -770,16 +831,19 @@ def _session_additional_directories(session: object) -> list[str]:
return list(value)
-def _session_mode_state() -> JSONObject:
+def _session_mode_state(modes: Iterable[AcpMode] | None = None) -> JSONObject:
+ available = [
+ {
+ "id": m.id,
+ "name": m.name,
+ "description": m.description or f"Provider: {m.provider or 'any'}, Model: {m.model or 'any'}",
+ }
+ for m in (modes or default_acp_modes())
+ ]
+ default_id = available[0]["id"] if available else ACP_DEFAULT_MODE_ID
return {
- "currentModeId": ACP_DEFAULT_MODE_ID,
- "availableModes": [
- {
- "id": ACP_DEFAULT_MODE_ID,
- "name": "Default",
- "description": "Standard Coding Agent behavior.",
- }
- ],
+ "currentModeId": default_id,
+ "availableModes": available,
}
diff --git a/coding-agent/src/coding_agent/cli/acp_command.py b/coding-agent/src/coding_agent/cli/acp_command.py
index 1e8e9bdd3..0e2d36229 100644
--- a/coding-agent/src/coding_agent/cli/acp_command.py
+++ b/coding-agent/src/coding_agent/cli/acp_command.py
@@ -1,13 +1,14 @@
from __future__ import annotations
import asyncio
+import json
import time
import uuid
import click
from agentkit.tracing import configure_tracing
-from coding_agent.acp import AcpServer, run_stdio
+from coding_agent.acp import AcpServer, AcpMode, run_stdio
from coding_agent.approval import ApprovalPolicy
from coding_agent.cli.local_runtime import create_local_cli_session_manager
from coding_agent.local_storage import (
@@ -29,6 +30,30 @@ def _shared_cli_arg(ctx: click.Context, name: str) -> str | None:
return value if isinstance(value, str) and value else None
+def _parse_acp_mode(mode_str: str) -> AcpMode:
+ """Parse a mode string in format 'id:name[:provider[:model[:base_url]]]'."""
+ if not mode_str:
+ raise click.BadParameter("--acp-mode value must not be empty")
+ parts = mode_str.split(":", 4)
+ mode_id = parts[0]
+ if not mode_id:
+ raise click.BadParameter(
+ f"--acp-mode '{mode_str}' has empty mode id"
+ )
+ name = parts[1] if len(parts) > 1 else mode_id
+ provider = parts[2] if len(parts) > 2 else None
+ model = parts[3] if len(parts) > 3 else None
+ base_url = parts[4] if len(parts) > 4 else None
+ return AcpMode(
+ id=mode_id,
+ name=name,
+ description=f"Provider: {provider or 'any'}, Model: {model or 'any'}",
+ provider=provider,
+ model=model,
+ base_url=base_url,
+ )
+
+
@click.command("acp")
@click.option(
"--approval",
@@ -38,16 +63,46 @@ def _shared_cli_arg(ctx: click.Context, name: str) -> str | None:
help="Tool approval policy for ACP sessions.",
)
@click.option("--max-steps", default=30, type=int, show_default=True)
-def acp(approval_policy: str, max_steps: int) -> None:
+@click.option(
+ "--acp-mode",
+ "acp_modes",
+ multiple=True,
+ default=None,
+ help=(
+ "Define an ACP mode preset (repeatable). Format: "
+ "id:name[:provider[:model[:base_url]]]. "
+ "When set, these replace the single Default mode."
+ ),
+)
+@click.option(
+ "--acp-modes-json",
+ default=None,
+ help="JSON string defining ACP modes array (alternative to --acp-mode).",
+)
+def acp(
+ approval_policy: str,
+ max_steps: int,
+ acp_modes: tuple[str, ...],
+ acp_modes_json: str | None,
+) -> None:
"""Run Coding Agent as an ACP stdio agent."""
-
- asyncio.run(_run_acp_stdio(click.get_current_context(), approval_policy, max_steps))
+ asyncio.run(
+ _run_acp_stdio(
+ click.get_current_context(),
+ approval_policy,
+ max_steps,
+ acp_modes,
+ acp_modes_json,
+ )
+ )
async def _run_acp_stdio(
ctx: click.Context,
approval_policy: str,
max_steps: int,
+ acp_modes: tuple[str, ...],
+ acp_modes_json: str | None,
) -> None:
configure_tracing(enabled=False)
data_dir = local_data_dir()
@@ -57,6 +112,19 @@ async def _run_acp_stdio(
owner_id=f"acp-stdio:{uuid.uuid4().hex}",
fencing_token=time.time_ns(),
)
+
+ modes: list[AcpMode] | None = None
+ if acp_modes:
+ modes = [_parse_acp_mode(m) for m in acp_modes]
+ elif acp_modes_json:
+ try:
+ raw = json.loads(acp_modes_json)
+ modes = [AcpMode(**m) for m in raw]
+ except (json.JSONDecodeError, TypeError, KeyError) as exc:
+ raise click.BadParameter(
+ f"Invalid --acp-modes-json: {exc}"
+ ) from exc
+
try:
await manager.start_owner_lease_renewal()
server = AcpServer(
@@ -66,6 +134,7 @@ async def _run_acp_stdio(
model_name=_shared_cli_arg(ctx, "model"),
base_url=_shared_cli_arg(ctx, "base_url"),
max_steps=max_steps,
+ modes=modes,
)
await run_stdio(server)
finally:
diff --git a/coding-agent/src/coding_agent/cli/commands.py b/coding-agent/src/coding_agent/cli/commands.py
index e2af1ace8..b277cbde8 100644
--- a/coding-agent/src/coding_agent/cli/commands.py
+++ b/coding-agent/src/coding_agent/cli/commands.py
@@ -107,27 +107,40 @@ async def cmd_plan(args: list[str], context: dict[str, Any]) -> None:
print_pt("No active plan. Use todo_write to create one.", output=_out())
-@command("model", "Show or change model")
+@command("model", "Show or change model. Syntax: [provider:]model")
async def cmd_model(args: list[str], context: dict[str, Any]) -> None:
if args:
- new_model = args[0]
- if len(new_model) < 2 or len(new_model) > 100:
+ raw = args[0]
+ if len(raw) < 2 or len(raw) > 100:
print_html(
- f"Invalid model name: {_h(new_model)}",
+ f"Invalid model name: {_h(raw)}",
output=_out(),
)
return
+ # Parse optional "provider:model" syntax
+ provider_override: str | None = None
+ model_name = raw
+ if ":" in raw:
+ provider_override, _, model_name = raw.partition(":")
+ if not provider_override or not model_name:
+ print_html(
+ f"Invalid syntax. Use [provider:]model. Got: {_h(raw)}",
+ output=_out(),
+ )
+ return
+ context["provider_override"] = provider_override
+
+ context["model"] = model_name
on_model_change = cast(
- Callable[[str], Coroutine[Any, Any, None]] | None,
+ Callable[[str, str | None], Coroutine[Any, Any, None]] | None,
context.get("on_model_change"),
)
if callable(on_model_change):
- await on_model_change(new_model)
- else:
- context["model"] = new_model
+ await on_model_change(model_name, provider_override)
output = _out()
+ label = f"{provider_override}:{model_name}" if provider_override else model_name
print_html(
- f"Model changed to: {_h(new_model)}",
+ f"Model changed to: {_h(label)}",
output=output,
)
print_html(
@@ -136,8 +149,10 @@ async def cmd_model(args: list[str], context: dict[str, Any]) -> None:
)
else:
current = context.get("model", "unknown")
+ provider_current = context.get("provider", None)
+ label = f"{provider_current}:{current}" if provider_current else current
print_html(
- f"Current model: {_h(current)}",
+ f"Current model: {_h(label)}",
output=_out(),
)
diff --git a/coding-agent/src/coding_agent/cli/local_runtime.py b/coding-agent/src/coding_agent/cli/local_runtime.py
index 31ccc20bd..69e558822 100644
--- a/coding-agent/src/coding_agent/cli/local_runtime.py
+++ b/coding-agent/src/coding_agent/cli/local_runtime.py
@@ -98,6 +98,8 @@ async def replace_session_runtime_config(
session_id: str,
*,
model_name: str,
+ provider_name: str | None = None,
+ base_url: str | None = None,
) -> Any: ...
async def restore_checkpoint(self, session_id: str, checkpoint_id: str) -> None: ...
@@ -252,10 +254,14 @@ async def replace_session_runtime_config(
session_id: str,
*,
model_name: str,
+ provider_name: str | None = None,
+ base_url: str | None = None,
) -> Any:
return await self._delegate.replace_session_runtime_config(
session_id,
model_name=model_name,
+ provider_name=provider_name,
+ base_url=base_url,
)
async def restore_checkpoint(self, session_id: str, checkpoint_id: str) -> None:
diff --git a/coding-agent/src/coding_agent/cli/repl.py b/coding-agent/src/coding_agent/cli/repl.py
index ed3621da8..162229ba4 100644
--- a/coding-agent/src/coding_agent/cli/repl.py
+++ b/coding-agent/src/coding_agent/cli/repl.py
@@ -210,6 +210,8 @@ def _sync_config_from_managed_session(self, managed_session: Any) -> None:
"kimi-code",
"kimi-code-anthropic",
"deepseek",
+ "stepfun",
+ "codex",
}
if provider_name not in allowed_providers:
raise RuntimeError(
@@ -253,6 +255,7 @@ async def _switch_session(self, session_id: str) -> None:
self._sync_config_from_managed_session(managed_session)
self.context["session_id"] = managed_session.id
self.context["model"] = self.config.model
+ self.context["provider"] = self.config.provider
self._pipeline = managed_session.runtime_pipeline
self._pipeline_ctx = managed_session.runtime_ctx
self._pipeline_adapter = managed_session.runtime_adapter
@@ -262,19 +265,31 @@ async def _switch_session(self, session_id: str) -> None:
self._pipeline_ctx.config["wire_consumer"] = self._consumer
self._refresh_command_context_from_pipeline_ctx(managed_session.runtime_ctx)
- async def _change_model_for_next_turn(self, model_name: str) -> None:
- if self.config.model == model_name:
+ async def _change_model_for_next_turn(
+ self,
+ model_name: str,
+ provider_name: str | None = None,
+ ) -> None:
+ if self.config.model == model_name and (
+ provider_name is None or self.config.provider == provider_name
+ ):
return
old_model_name = self.config.model
+ old_provider = self.config.provider
session_id = self.context.get("session_id")
if not isinstance(session_id, str):
self.config.model = model_name
self.context["model"] = model_name
+ if provider_name is not None:
+ self.config.provider = provider_name
+ self.context["provider"] = provider_name
try:
self._setup_agent()
except Exception:
self.config.model = old_model_name
+ self.config.provider = old_provider
self.context["model"] = old_model_name
+ self.context["provider"] = old_provider
raise
return
@@ -283,16 +298,20 @@ async def _change_model_for_next_turn(self, model_name: str) -> None:
await self._session_manager.replace_session_runtime_config(
session_id,
model_name=model_name,
+ provider_name=provider_name,
)
)
except Exception:
self.config.model = old_model_name
+ self.config.provider = old_provider
self.context["model"] = old_model_name
+ self.context["provider"] = old_provider
raise
self._sync_config_from_managed_session(managed_session)
self.context["session_id"] = managed_session.id
self.context["model"] = self.config.model
+ self.context["provider"] = self.config.provider
self._pipeline = managed_session.runtime_pipeline
self._pipeline_ctx = managed_session.runtime_ctx
self._pipeline_adapter = managed_session.runtime_adapter
diff --git a/coding-agent/src/coding_agent/runs/replacement.py b/coding-agent/src/coding_agent/runs/replacement.py
index 3e047ebb0..2716e4878 100644
--- a/coding-agent/src/coding_agent/runs/replacement.py
+++ b/coding-agent/src/coding_agent/runs/replacement.py
@@ -14,7 +14,9 @@
class RuntimeReplacementSession(Protocol):
id: str
provider: object | None
+ provider_name: str | None
model_name: str | None
+ base_url: str | None
tape_id: str | None
def runtime_binding_snapshot(self) -> RuntimeBindingSnapshot: ...
@@ -43,6 +45,8 @@ def __call__(
session: RuntimeReplacementSession,
*,
model_name: str,
+ provider_name: str | None = None,
+ base_url: str | None = None,
) -> Awaitable[tuple[object, object, object]]: ...
@@ -55,18 +59,31 @@ async def replace_runtime_config(
session: RuntimeReplacementSession,
*,
model_name: str,
+ provider_name: str | None = None,
+ base_url: str | None = None,
build_runtime: RuntimeReplacementBuilder,
persist_session: RuntimeReplacementPersister,
) -> RuntimeReplacementSession:
old_provider = session.provider
+ old_provider_name = session.provider_name
old_model_name = session.model_name
+ old_base_url = session.base_url
old_tape_id = session.tape_id
old_runtime_binding = session.runtime_binding_snapshot()
- pipeline, ctx, adapter = await build_runtime(session, model_name=model_name)
+ pipeline, ctx, adapter = await build_runtime(
+ session,
+ model_name=model_name,
+ provider_name=provider_name,
+ base_url=base_url,
+ )
session.provider = None
session.model_name = model_name
+ if provider_name is not None:
+ session.provider_name = provider_name
+ if base_url is not None:
+ session.base_url = base_url
session.attach_runtime_binding(
pipeline=pipeline,
ctx=ctx,
@@ -77,7 +94,9 @@ async def replace_runtime_config(
await persist_session(session)
except Exception:
session.provider = old_provider
+ session.provider_name = old_provider_name
session.model_name = old_model_name
+ session.base_url = old_base_url
session.restore_runtime_binding(old_runtime_binding)
session.tape_id = old_tape_id
await self.close_runtime_adapter(adapter)
diff --git a/coding-agent/src/coding_agent/server/http_server.py b/coding-agent/src/coding_agent/server/http_server.py
index c385547ed..065e59e5d 100644
--- a/coding-agent/src/coding_agent/server/http_server.py
+++ b/coding-agent/src/coding_agent/server/http_server.py
@@ -206,6 +206,8 @@
ReadinessResponse,
ResolveInteractionRequest,
ResumeSessionRequest,
+ RuntimeConfigUpdateRequest,
+ RuntimeConfigUpdateResponse,
RuntimeEventResponse,
RuntimeEventsResponse,
RuntimeInteractionListResponse,
@@ -2474,6 +2476,64 @@ async def create_session(
return SessionResponse(session_id=session_id)
+@app.patch("/sessions/{session_id}/runtime-config", response_model=RuntimeConfigUpdateResponse)
+@limiter.limit(RateLimits.CREATE_SESSION)
+async def update_runtime_config(
+ request: Request,
+ session_id: str,
+ body: RuntimeConfigUpdateRequest,
+ api_key: str | None = Depends(verify_api_key),
+) -> RuntimeConfigUpdateResponse:
+ """Update the session runtime provider/model/base_url config in-place.
+
+ Applies changes next turn. The session's tape and history are preserved.
+ Returns 409 if a turn is currently in progress.
+ Returns 400 if no config fields are provided.
+ """
+ if body.model is None and body.provider is None and body.base_url is None:
+ raise HTTPException(
+ status_code=400,
+ detail="At least one of model, provider, or base_url must be provided",
+ )
+
+ try:
+ session = await session_manager.get_session_async(session_id)
+ except KeyError:
+ raise HTTPException(status_code=404, detail="Session not found")
+
+ if getattr(session, "turn_in_progress", False):
+ raise HTTPException(status_code=409, detail="Turn already in progress")
+
+ try:
+ updated_session = await session_manager.replace_session_runtime_config(
+ session_id,
+ model_name=body.model,
+ provider_name=body.provider,
+ base_url=body.base_url,
+ )
+ except KeyError as exc:
+ raise HTTPException(status_code=404, detail="Session not found") from exc
+ except RuntimeError as exc:
+ if str(exc) == "turn already in progress":
+ raise HTTPException(
+ status_code=409, detail="Turn already in progress"
+ ) from exc
+ raise HTTPException(
+ status_code=500, detail=_http_exception_detail(exc)
+ ) from exc
+ except Exception as exc:
+ raise HTTPException(
+ status_code=500, detail=_http_exception_detail(exc)
+ ) from exc
+
+ return RuntimeConfigUpdateResponse(
+ session_id=session_id,
+ provider_name=getattr(updated_session, "provider_name", None),
+ model_name=getattr(updated_session, "model_name", None),
+ base_url=getattr(updated_session, "base_url", None),
+ )
+
+
@app.post("/sessions/{session_id}/prompt")
@limiter.limit(RateLimits.SEND_PROMPT)
async def send_prompt(
diff --git a/coding-agent/src/coding_agent/server/schemas.py b/coding-agent/src/coding_agent/server/schemas.py
index 67fa09279..4b8dc616a 100644
--- a/coding-agent/src/coding_agent/server/schemas.py
+++ b/coding-agent/src/coding_agent/server/schemas.py
@@ -59,6 +59,25 @@ class CreateSessionRequest(BaseModel):
max_steps: int | None = Field(None, ge=0)
+class RuntimeConfigUpdateRequest(BaseModel):
+ """Request schema for updating session runtime config."""
+
+ model_config = ConfigDict(extra="forbid")
+
+ model: str | None = Field(None, min_length=1, max_length=200)
+ provider: ProviderName | None = None
+ base_url: str | None = Field(None, min_length=1, max_length=500)
+
+
+class RuntimeConfigUpdateResponse(BaseModel):
+ """Response schema for runtime config update."""
+
+ session_id: str
+ provider_name: str | None
+ model_name: str | None
+ base_url: str | None
+
+
class ApproveRequest(BaseModel):
"""Request schema for approval response."""
diff --git a/coding-agent/src/coding_agent/server/session_manager.py b/coding-agent/src/coding_agent/server/session_manager.py
index 36c0842e2..07848df7d 100644
--- a/coding-agent/src/coding_agent/server/session_manager.py
+++ b/coding-agent/src/coding_agent/server/session_manager.py
@@ -3243,13 +3243,22 @@ async def replace_session_runtime_config(
self,
session_id: str,
*,
- model_name: str,
+ model_name: str | None = None,
+ provider_name: str | None = None,
+ base_url: str | None = None,
) -> Session:
async def replace_admitted_runtime(session: object) -> Session:
admitted_session = cast(Session, session)
+ resolved_model = (
+ model_name if model_name is not None else admitted_session.model_name
+ )
+ if not resolved_model:
+ raise RuntimeError("session is missing model_name, cannot replace runtime")
return await self._runtime_replacement_service.replace_runtime_config(
admitted_session,
- model_name=model_name,
+ model_name=resolved_model,
+ provider_name=provider_name,
+ base_url=base_url,
build_runtime=self._build_session_runtime,
persist_session=self._persist_session_async,
)
diff --git a/coding-agent/tests/coding_agent/test_runtime_replacement_service.py b/coding-agent/tests/coding_agent/test_runtime_replacement_service.py
index 0ca334c1d..217397c44 100644
--- a/coding-agent/tests/coding_agent/test_runtime_replacement_service.py
+++ b/coding-agent/tests/coding_agent/test_runtime_replacement_service.py
@@ -21,7 +21,9 @@ class FakeSession:
def __init__(self) -> None:
self.id = "session-1"
self.provider = object()
+ self.provider_name = "old-provider"
self.model_name = "old-model"
+ self.base_url = "https://old.example.com"
self.tape_id = "old-tape"
self.pipeline = "old-pipeline"
self.ctx = FakeContext(FakeTape("old-tape"))
@@ -61,9 +63,13 @@ async def build_runtime(
runtime_session: FakeSession,
*,
model_name: str,
+ provider_name: str | None = None,
+ base_url: str | None = None,
) -> tuple[object, FakeContext, object]:
assert runtime_session is session
assert model_name == "new-model"
+ assert provider_name is None
+ assert base_url is None
return "new-pipeline", FakeContext(FakeTape("new-tape")), "new-adapter"
async def persist_session(runtime_session: FakeSession) -> None:
@@ -107,8 +113,10 @@ async def build_runtime(
runtime_session: FakeSession,
*,
model_name: str,
+ provider_name: str | None = None,
+ base_url: str | None = None,
) -> tuple[object, FakeContext, object]:
- del runtime_session, model_name
+ del runtime_session, model_name, provider_name, base_url
return "new-pipeline", FakeContext(FakeTape("new-tape")), "new-adapter"
async def persist_session(runtime_session: FakeSession) -> None:
@@ -129,7 +137,9 @@ async def close_adapter(adapter: object | None) -> None:
)
assert session.provider is old_provider
+ assert session.provider_name == "old-provider"
assert session.model_name == "old-model"
+ assert session.base_url == "https://old.example.com"
assert session.tape_id == "old-tape"
assert session.pipeline == "old-pipeline"
assert session.adapter == "old-adapter"
@@ -144,8 +154,10 @@ async def build_runtime(
runtime_session: FakeSession,
*,
model_name: str,
+ provider_name: str | None = None,
+ base_url: str | None = None,
) -> tuple[object, FakeContext, object]:
- del runtime_session, model_name
+ del runtime_session, model_name, provider_name, base_url
return "new-pipeline", FakeContext(FakeTape("new-tape")), "new-adapter"
async def persist_session(runtime_session: FakeSession) -> None: