Spaces:
Running on Zero
Running on Zero
GitHub Actions commited on
Commit ·
fa5b4a9
1
Parent(s): caa7fae
fix(chat): wire ChatService with bus in app.py so cross-node sends deliver
Browse filesThe HF Space / UI entry point constructed ChatService without a bus=
reference, so _deliver_remote short-circuited to 'queued' before ever
attempting remote delivery. Pass bus=node.bus (matching node.py wiring)
so local->peer chat is delivered over the bus transport.
Verified live: local browser UI -> HF Space now reports 'delivered' and
the message lands in the Space chat log.
Add regression tests covering manual ChatService wiring + the no-bus
failure mode. Tidy stray blank lines in relay_client.
- app.py +1 -1
- hearthnet/transport/relay_client.py +0 -2
- tests/test_chat_cross_node.py +41 -0
app.py
CHANGED
|
@@ -378,7 +378,7 @@ def _build_node():
|
|
| 378 |
|
| 379 |
# Marketplace, Chat, Files — now durably event-sourced where supported.
|
| 380 |
node.bus.register_service(MarketplaceService(event_log=event_log, node_id=node.node_id))
|
| 381 |
-
node.bus.register_service(ChatService(node.node_id, event_log=event_log))
|
| 382 |
node.bus.register_service(FileService())
|
| 383 |
|
| 384 |
return node
|
|
|
|
| 378 |
|
| 379 |
# Marketplace, Chat, Files — now durably event-sourced where supported.
|
| 380 |
node.bus.register_service(MarketplaceService(event_log=event_log, node_id=node.node_id))
|
| 381 |
+
node.bus.register_service(ChatService(node.node_id, event_log=event_log, bus=node.bus))
|
| 382 |
node.bus.register_service(FileService())
|
| 383 |
|
| 384 |
return node
|
hearthnet/transport/relay_client.py
CHANGED
|
@@ -336,8 +336,6 @@ class RelayClient:
|
|
| 336 |
self._bus.registry.update_from_peer_manifest(record, manifest)
|
| 337 |
|
| 338 |
|
| 339 |
-
|
| 340 |
-
|
| 341 |
class RelayStrategy:
|
| 342 |
"""Adapts a :class:`RelayClient` to the bus ``DeliveryStrategy`` protocol."""
|
| 343 |
|
|
|
|
| 336 |
self._bus.registry.update_from_peer_manifest(record, manifest)
|
| 337 |
|
| 338 |
|
|
|
|
|
|
|
| 339 |
class RelayStrategy:
|
| 340 |
"""Adapts a :class:`RelayClient` to the bus ``DeliveryStrategy`` protocol."""
|
| 341 |
|
tests/test_chat_cross_node.py
CHANGED
|
@@ -74,3 +74,44 @@ async def test_send_to_unknown_node_returns_queued(two_nodes):
|
|
| 74 |
)
|
| 75 |
status = r.get("output", {}).get("delivered")
|
| 76 |
assert status == "queued", f"Expected 'queued' for unknown node, got {status!r}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
)
|
| 75 |
status = r.get("output", {}).get("delivered")
|
| 76 |
assert status == "queued", f"Expected 'queued' for unknown node, got {status!r}"
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
@pytest.mark.asyncio
|
| 80 |
+
async def test_manually_wired_chat_service_delivers():
|
| 81 |
+
"""Regression: a ChatService registered manually (as app.py / the HF Space
|
| 82 |
+
entry point does) must receive a ``bus=`` reference, otherwise
|
| 83 |
+
``_deliver_remote`` short-circuits to ``"queued"`` before attempting
|
| 84 |
+
delivery. Mirrors the app.py wiring to guard against that regression.
|
| 85 |
+
"""
|
| 86 |
+
from hearthnet.node import HearthNode
|
| 87 |
+
from hearthnet.services.chat.service import ChatService
|
| 88 |
+
|
| 89 |
+
net = InMemoryTransport()
|
| 90 |
+
alice = HearthNode("node-alice", "Alice", "ed25519:test", transport=net)
|
| 91 |
+
# Wire chat exactly like app.py: explicit bus= argument is required.
|
| 92 |
+
alice.bus.register_service(ChatService(alice.node_id, bus=alice.bus))
|
| 93 |
+
net.register(alice.bus)
|
| 94 |
+
|
| 95 |
+
bob = HearthNode("node-bob", "Bob", "ed25519:test", transport=net)
|
| 96 |
+
bob.bus.register_service(ChatService(bob.node_id, bus=bob.bus))
|
| 97 |
+
net.register(bob.bus)
|
| 98 |
+
|
| 99 |
+
r = await alice.bus.call(
|
| 100 |
+
"chat.send", (1, 0), {"input": {"recipient": "node-bob", "body": "wired"}}
|
| 101 |
+
)
|
| 102 |
+
assert r.get("output", {}).get("delivered") == "delivered"
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
@pytest.mark.asyncio
|
| 106 |
+
async def test_chat_service_without_bus_cannot_deliver():
|
| 107 |
+
"""A ChatService constructed without a bus reference can only queue —
|
| 108 |
+
documents the failure mode the app.py wiring fix prevents.
|
| 109 |
+
"""
|
| 110 |
+
from hearthnet.services.chat.service import ChatService
|
| 111 |
+
|
| 112 |
+
svc = ChatService("node-alice") # no bus=
|
| 113 |
+
status = await svc._deliver_remote(
|
| 114 |
+
{"to": "node-bob", "from": "node-alice", "body": "x", "event_id": "e1"}
|
| 115 |
+
)
|
| 116 |
+
assert status == "queued"
|
| 117 |
+
|