fix(python-sdk): preserve reused session ancestry
This commit is contained in:
@@ -445,7 +445,7 @@ class HarnessClient:
|
||||
self._notification_subscribers.pop(subscription_id, None)
|
||||
|
||||
def _record_session_relationship_locked(self, notification: Notification) -> None:
|
||||
if notification.method not in {"subagent.started", "subagent.finished"}:
|
||||
if notification.method != "subagent.started":
|
||||
return
|
||||
parent_id = notification.payload.get("parentSessionId")
|
||||
child_id = notification.payload.get("childSessionId")
|
||||
@@ -461,15 +461,18 @@ class HarnessClient:
|
||||
def _notification_belongs_to_session_tree(self, session_id: str) -> NotificationFilter:
|
||||
def belongs(notification: Notification) -> bool:
|
||||
payload = notification.payload
|
||||
related_ids = (
|
||||
payload.get("sessionId"),
|
||||
payload.get("parentSessionId"),
|
||||
payload.get("childSessionId"),
|
||||
)
|
||||
return any(
|
||||
if notification.method in {"subagent.started", "subagent.finished"}:
|
||||
parent_id = payload.get("parentSessionId")
|
||||
if (
|
||||
isinstance(parent_id, str)
|
||||
and self._session_is_descendant_of(parent_id, session_id)
|
||||
):
|
||||
return True
|
||||
return payload.get("childSessionId") == session_id
|
||||
related_id = payload.get("sessionId")
|
||||
return (
|
||||
isinstance(related_id, str)
|
||||
and self._session_is_descendant_of(related_id, session_id)
|
||||
for related_id in related_ids
|
||||
)
|
||||
|
||||
return belongs
|
||||
|
||||
@@ -9,7 +9,7 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from deepseek_harness import DeepSeekHarness, HarnessClient, HarnessConfig
|
||||
from deepseek_harness import DeepSeekHarness, HarnessClient, HarnessConfig, Notification
|
||||
|
||||
|
||||
def test_high_level_sdk_runs_turn_and_collects_final_response(tmp_path: Path) -> None:
|
||||
@@ -442,6 +442,65 @@ def test_session_subscription_keeps_descendant_relationships_across_subscription
|
||||
assert client._notifications.qsize() == 0
|
||||
|
||||
|
||||
def test_session_subscription_preserves_reused_child_ancestry_after_late_finish() -> None:
|
||||
client = HarnessClient()
|
||||
old_seen: list[Notification] = []
|
||||
new_seen: list[Notification] = []
|
||||
with (
|
||||
client.subscribe_session_notifications("old-parent") as old_subscription,
|
||||
client.subscribe_session_notifications("new-parent") as new_subscription,
|
||||
):
|
||||
client._handle_message({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "subagent.started",
|
||||
"params": {"parentSessionId": "old-parent", "childSessionId": "reused-child"},
|
||||
})
|
||||
old_subscription.drain(old_seen.append)
|
||||
new_subscription.drain(new_seen.append)
|
||||
assert [notification.method for notification in old_seen] == ["subagent.started"]
|
||||
assert new_seen == []
|
||||
|
||||
client._handle_message({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "subagent.started",
|
||||
"params": {"parentSessionId": "new-parent", "childSessionId": "reused-child"},
|
||||
})
|
||||
old_subscription.drain(old_seen.append)
|
||||
new_subscription.drain(new_seen.append)
|
||||
assert [notification.method for notification in new_seen] == ["subagent.started"]
|
||||
|
||||
client._handle_message({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "subagent.finished",
|
||||
"params": {"parentSessionId": "old-parent", "childSessionId": "reused-child"},
|
||||
})
|
||||
old_subscription.drain(old_seen.append)
|
||||
new_subscription.drain(new_seen.append)
|
||||
assert [notification.method for notification in old_seen] == [
|
||||
"subagent.started",
|
||||
"subagent.finished",
|
||||
]
|
||||
assert [notification.method for notification in new_seen] == ["subagent.started"]
|
||||
|
||||
client._handle_message({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "session.event",
|
||||
"params": {"sessionId": "reused-child", "event": {"type": "assistant/message"}},
|
||||
})
|
||||
old_subscription.drain(old_seen.append)
|
||||
new_subscription.drain(new_seen.append)
|
||||
|
||||
assert [notification.method for notification in old_seen] == [
|
||||
"subagent.started",
|
||||
"subagent.finished",
|
||||
]
|
||||
assert [notification.method for notification in new_seen] == [
|
||||
"subagent.started",
|
||||
"session.event",
|
||||
]
|
||||
assert client._notifications.qsize() == 0
|
||||
|
||||
|
||||
def test_client_contains_notification_filter_failure_to_its_subscription(tmp_path: Path) -> None:
|
||||
script = tmp_path / "fake_bridge.py"
|
||||
script.write_text(
|
||||
|
||||
Reference in New Issue
Block a user