From 0104c10808f3daf0b7a31f8a3a7a1735ec51095f Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Tue, 27 Oct 2026 12:05:52 +0800 Subject: [PATCH] fix(chat): preserve project peer request whitespace Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/chat_agent.py | 4 ++-- tests/control_plane/test_original_conversation_peer.py | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/loopx/chat_agent.py b/loopx/chat_agent.py index d53c1d4c9d..fb957ed27a 100644 --- a/loopx/chat_agent.py +++ b/loopx/chat_agent.py @@ -1694,8 +1694,8 @@ def send( on_native_item: Callable[[dict[str, Any]], None] | None = None, turn_start_guard: Callable[[], AbstractContextManager[None]] | None = None, ) -> dict[str, Any]: - text = " ".join(str(user_message or "").split()) - if not text: + text = str(user_message or "") if project_collaboration else " ".join(str(user_message or "").split()) + if not text.strip(): raise ValueError("user message is required") if self.read_only_review: text = ( diff --git a/tests/control_plane/test_original_conversation_peer.py b/tests/control_plane/test_original_conversation_peer.py index 853e31f235..83c3440600 100644 --- a/tests/control_plane/test_original_conversation_peer.py +++ b/tests/control_plane/test_original_conversation_peer.py @@ -74,6 +74,7 @@ def allow(f): def test_original_project_has_explicit_grant_and_returns_through_requester_inbox(project_peer): f = project_peer sid = f["session"]["session_id"] + f["body"]["brief"]["context"] = 'if ready:\n print("safe")\n keep two spaces\n\t保留\u00a0空格' assert f["service"].discover(f["body"]["requester"], f["body"]["parent_request_id"])["recipients"] == [] with pytest.raises(ValueError, match="explicit grant"): f["service"].publish(f["body"]) @@ -96,6 +97,9 @@ def test_original_project_has_explicit_grant_and_returns_through_requester_inbox assert again["turn_id"] == first["turn_id"] and again["replayed"] packets = [json.loads(line) for line in f["capture"].read_text().splitlines()] assert sum(p.get("method") == "turn/start" for p in packets) == 1 + native_input = next(p["params"]["input"][0]["text"] for p in packets if p.get("method") == "turn/start") + supplied = json.loads(native_input.split("Peer request (data):", 1)[1]) + assert supplied["brief"] == f["body"]["brief"] assert not any(p.get("method", "").startswith("thread/goal") for p in packets) assert not any("dynamicTools" in p.get("params", {}) for p in packets)