fix: preserve subagent controls across attached session peers
This commit is contained in:
@@ -181,8 +181,12 @@ def test_reattach_preserves_child_controls_including_late_registration(runtime,
|
||||
popup = type(new)()
|
||||
with server._session_resume_lock, owner["history_lock"]:
|
||||
server._rebind_live_transport("ui-owner", owner, popup)
|
||||
for peer in (new, popup):
|
||||
assert {r["subagent_id"] for r in call("subagent.list", via=peer)["result"]["subagents"]} == {"before", "after"}
|
||||
assert call("subagent.tail", via=peer, subagent_id="before")["result"]["text"] == "live child output"
|
||||
assert server._close_sessions_for_transport(popup) == (0, 0)
|
||||
assert owner["transport"] is new
|
||||
assert server._session_transport_contains(owner, new)
|
||||
assert not server._session_transport_contains(owner, popup)
|
||||
assert {row["subagent_id"] for row in call("subagent.list", via=new)["result"]["subagents"]} == {"before", "after"}
|
||||
for sid in ("before", "after"):
|
||||
assert call("subagent.tail", via=new, subagent_id=sid)["result"]["text"] == "live child output"
|
||||
|
||||
@@ -109,6 +109,13 @@ def interrupt_subagent(subagent_id: str) -> bool:
|
||||
logger.debug("interrupt_subagent(%s) failed: %s", subagent_id, exc)
|
||||
return False
|
||||
|
||||
def _subagent_transport_matches(record, transport) -> bool:
|
||||
from tui_gateway.transport import FanoutTransport
|
||||
|
||||
bound = record.get("owner_transport")
|
||||
return bound is transport or (isinstance(bound, FanoutTransport) and bound.contains(transport))
|
||||
|
||||
|
||||
def steer_subagent(
|
||||
subagent_id: str, text: str, *, owner_session_id: Optional[str] = None, owner_transport: Any = None,
|
||||
owner_session_record: Any = None,
|
||||
@@ -130,7 +137,7 @@ def steer_subagent(
|
||||
if owner_session_id is not None and (
|
||||
record.get("owner_session_id") != owner_session_id
|
||||
or owner_transport is None
|
||||
or record.get("owner_transport") is not owner_transport
|
||||
or not _subagent_transport_matches(record, owner_transport)
|
||||
or owner_session_record is None
|
||||
or record.get("owner_session_record") is not owner_session_record
|
||||
):
|
||||
|
||||
@@ -17,12 +17,12 @@ _SUBAGENT_TAIL_BYTES = 16384
|
||||
|
||||
|
||||
def _owned_subagent_records(session_id, transport, owner):
|
||||
from tools.delegate_tool_registry import _active_subagents, _active_subagents_lock
|
||||
from tools.delegate_tool_registry import _active_subagents, _active_subagents_lock, _subagent_transport_matches
|
||||
|
||||
with _active_subagents_lock:
|
||||
return [dict(r) for r in _active_subagents.values()
|
||||
if r.get("owner_session_id") == session_id
|
||||
and r.get("owner_transport") is transport
|
||||
and _subagent_transport_matches(r, transport)
|
||||
and r.get("owner_session_record") is owner]
|
||||
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ def _rebind_live_transport(sid: str, session: dict, transport: Transport) -> Non
|
||||
if (record.get("owner_session_id") == sid
|
||||
and record.get("owner_session_record") is session
|
||||
and record.get("owner_transport") is not None):
|
||||
record["owner_transport"] = transport
|
||||
record["owner_transport"] = session["transport"]
|
||||
# Every transport that showed this session (pop-outs resume the same sid); on disconnect the last
|
||||
# viewer becomes the transport instead of the drop sentinel.
|
||||
session.setdefault("viewers", {})[transport] = time.time()
|
||||
|
||||
Reference in New Issue
Block a user