fix(gateway): a repeated /model --once keeps the earliest restore target
`/model X --once` then `/model Y --once` before any turn replaced the pending snapshot with one taken while X was live, so slot cleanup restored X and made the first temporary model permanent (ehz0ah, review on #106966). setdefault keeps the snapshot from the first command — the user's standing override — as the restore target. One producer-driven regression test.
This commit is contained in:
@@ -269,8 +269,10 @@ class GatewayModelCommandsMixin:
|
||||
if one_turn:
|
||||
if not hasattr(self, "_pending_one_turn_model_restores"):
|
||||
self._pending_one_turn_model_restores = {}
|
||||
self._pending_one_turn_model_restores[ctx.session_key] = dict(
|
||||
ctx.restore_snapshot or {"had_override": False, "override": None}
|
||||
# A repeated --once before the turn runs must keep the EARLIEST snapshot: the later
|
||||
# command's snapshot is the first temporary model, not the user's standing override.
|
||||
self._pending_one_turn_model_restores.setdefault(
|
||||
ctx.session_key, dict(ctx.restore_snapshot or {"had_override": False, "override": None}),
|
||||
)
|
||||
elif not picker and hasattr(self, "_pending_one_turn_model_restores"):
|
||||
self._pending_one_turn_model_restores.pop(ctx.session_key, None)
|
||||
|
||||
@@ -282,3 +282,19 @@ class TestOneTurnNeverPersisted:
|
||||
# ...but NEVER written through to the persistent session store.
|
||||
runner.async_session_store.set_model_override.assert_not_awaited()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_repeated_once_keeps_the_earliest_restore_target(self, tmp_path, monkeypatch):
|
||||
"""`/model X --once` then `/model Y --once` before any turn: the pending snapshot must still
|
||||
be the user's standing override (none here), not X — otherwise slot cleanup would make the
|
||||
first temporary model permanent."""
|
||||
runner = self._runner_with_store(tmp_path, monkeypatch)
|
||||
sk = build_session_key(_make_source())
|
||||
|
||||
await runner._handle_model_command(self._event("/model gpt-5.5 --once"))
|
||||
assert runner._session_model_overrides[sk]["model"] == "gpt-5.5"
|
||||
await runner._handle_model_command(self._event("/model gpt-5.5 --once"))
|
||||
|
||||
# The second producer call snapshotted the live gpt-5.5 override; the pending restore
|
||||
# must still be the ORIGINAL "no override" state.
|
||||
assert runner._pending_one_turn_model_restores[sk]["had_override"] is False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user