fix(gateway): carry desktop_contract when activating a lazy session (#68392)
_live_session_payload() falls back to _fallback_session_info() while a session's agent is still None (lazy/deferred build). That fallback omitted desktop_contract, so session.activate returned lazy metadata with no contract field. Desktop feeds the value straight into reportBackendContract(), where a missing field reads as contract 0 — a current backend is then falsely flagged "Backend out of date" on every activate of a live lazy session. The sibling session.create shape (_lazy_resume_info) was fixed the same way in #36112; this closes the remaining session.activate gap by advertising DESKTOP_BACKEND_CONTRACT in the fallback payload. Adds test_session_activate_lazy_info_reports_desktop_contract pinning the session.activate path against a lazy (agent=None) session.
This commit is contained in:
parent
ad2c7af86a
commit
a1da384c6d
|
|
@ -11270,6 +11270,41 @@ def test_session_create_lazy_info_reports_desktop_contract(monkeypatch):
|
|||
server._sessions.pop(resp["result"]["session_id"], None)
|
||||
|
||||
|
||||
def test_session_activate_lazy_info_reports_desktop_contract():
|
||||
"""Activating an already-live *lazy* session (agent not built yet) must
|
||||
still advertise desktop_contract. _live_session_payload falls back to
|
||||
_fallback_session_info while session["agent"] is None; the desktop reads a
|
||||
missing field as contract 0 and falsely warns "Backend out of date" against
|
||||
a current backend (#68392). The sibling session.create path was fixed in
|
||||
#36112; this pins the session.activate path."""
|
||||
import threading
|
||||
|
||||
sid = "lazy-activate-contract"
|
||||
server._sessions[sid] = {
|
||||
"agent": None,
|
||||
"created_at": 123.0,
|
||||
"history": [],
|
||||
"history_lock": threading.RLock(),
|
||||
"last_active": 123.0,
|
||||
"running": False,
|
||||
"session_key": sid,
|
||||
"transport": server._stdio_transport,
|
||||
}
|
||||
try:
|
||||
resp = server.handle_request(
|
||||
{
|
||||
"id": "activate-lazy",
|
||||
"method": "session.activate",
|
||||
"params": {"session_id": sid},
|
||||
}
|
||||
)
|
||||
info = resp["result"]["info"]
|
||||
assert info["lazy"] is True
|
||||
assert info["desktop_contract"] == server.DESKTOP_BACKEND_CONTRACT
|
||||
finally:
|
||||
server._sessions.pop(sid, None)
|
||||
|
||||
|
||||
def test_session_list_returns_clean_error_when_state_db_is_unavailable(monkeypatch):
|
||||
monkeypatch.setattr(server, "_get_db", lambda: None)
|
||||
monkeypatch.setattr(server, "_db_error", "locking protocol")
|
||||
|
|
|
|||
|
|
@ -8083,6 +8083,12 @@ def _fallback_session_info(session: dict) -> dict:
|
|||
"model": _resolve_model(),
|
||||
"skills": {},
|
||||
"tools": {},
|
||||
# A lazy session (agent not built yet) is still served by *this* backend,
|
||||
# so it must advertise the current contract. Desktop feeds this straight
|
||||
# into reportBackendContract(); a missing field is read as contract 0 and
|
||||
# a current backend is falsely flagged "out of date" (#68392). The sibling
|
||||
# session.create shape (_lazy_resume_info) already carries it (#36112).
|
||||
"desktop_contract": DESKTOP_BACKEND_CONTRACT,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue