Clawdbot commited on
Commit Β·
7bec764
1
Parent(s): 84506ca
Add Direct Messaging and Zero-Bounty features
Browse files- hub/__pycache__/main.cpython-310.pyc +0 -0
- hub/__pycache__/models.cpython-310.pyc +0 -0
- hub/main.py +14 -2
- hub/models.py +1 -0
- node/test_dm.py +63 -0
hub/__pycache__/main.cpython-310.pyc
CHANGED
|
Binary files a/hub/__pycache__/main.cpython-310.pyc and b/hub/__pycache__/main.cpython-310.pyc differ
|
|
|
hub/__pycache__/models.cpython-310.pyc
CHANGED
|
Binary files a/hub/__pycache__/models.cpython-310.pyc and b/hub/__pycache__/models.cpython-310.pyc differ
|
|
|
hub/main.py
CHANGED
|
@@ -39,11 +39,23 @@ async def submit_task(task: TaskCreate):
|
|
| 39 |
"consumer_id": task.consumer_id,
|
| 40 |
"payload": task.payload,
|
| 41 |
"bounty": task.bounty,
|
| 42 |
-
"status": "pending"
|
|
|
|
| 43 |
}
|
| 44 |
active_tasks[task_id] = task_data
|
| 45 |
|
| 46 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
for node_id, ws in list(connected_nodes.items()):
|
| 48 |
if node_id != task.consumer_id:
|
| 49 |
try:
|
|
|
|
| 39 |
"consumer_id": task.consumer_id,
|
| 40 |
"payload": task.payload,
|
| 41 |
"bounty": task.bounty,
|
| 42 |
+
"status": "pending",
|
| 43 |
+
"target_node": task.target_node
|
| 44 |
}
|
| 45 |
active_tasks[task_id] = task_data
|
| 46 |
|
| 47 |
+
# Target specific node if requested (Direct Message)
|
| 48 |
+
if task.target_node:
|
| 49 |
+
if task.target_node in connected_nodes:
|
| 50 |
+
try:
|
| 51 |
+
await connected_nodes[task.target_node].send_json({"event": "new_task", "data": task_data})
|
| 52 |
+
return {"status": "success", "task_id": task_id, "routed_to": task.target_node}
|
| 53 |
+
except:
|
| 54 |
+
return {"status": "error", "detail": "Target node disconnected"}
|
| 55 |
+
else:
|
| 56 |
+
return {"status": "error", "detail": "Target node not currently connected to Hub"}
|
| 57 |
+
|
| 58 |
+
# Otherwise, Broadcast to all connected nodes EXCEPT the consumer
|
| 59 |
for node_id, ws in list(connected_nodes.items()):
|
| 60 |
if node_id != task.consumer_id:
|
| 61 |
try:
|
hub/models.py
CHANGED
|
@@ -10,6 +10,7 @@ class TaskCreate(BaseModel):
|
|
| 10 |
consumer_id: str
|
| 11 |
payload: str
|
| 12 |
bounty: float
|
|
|
|
| 13 |
|
| 14 |
class TaskResult(BaseModel):
|
| 15 |
task_id: str
|
|
|
|
| 10 |
consumer_id: str
|
| 11 |
payload: str
|
| 12 |
bounty: float
|
| 13 |
+
target_node: Optional[str] = None # Direct messaging / specific bot targeting
|
| 14 |
|
| 15 |
class TaskResult(BaseModel):
|
| 16 |
task_id: str
|
node/test_dm.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import websockets
|
| 3 |
+
import json
|
| 4 |
+
import requests
|
| 5 |
+
import uuid
|
| 6 |
+
|
| 7 |
+
HUB_URL = "http://localhost:8000"
|
| 8 |
+
WS_URL = "ws://localhost:8000"
|
| 9 |
+
|
| 10 |
+
async def test_direct_message():
|
| 11 |
+
print("=== Testing MEP Direct Messaging (Zero Bounty) ===")
|
| 12 |
+
|
| 13 |
+
# 1. Start Alice (Provider)
|
| 14 |
+
alice_id = "alice-specialist-88"
|
| 15 |
+
requests.post(f"{HUB_URL}/register", json={"pubkey": alice_id})
|
| 16 |
+
|
| 17 |
+
# 2. Start Bob (Consumer)
|
| 18 |
+
bob_id = "bob-general-12"
|
| 19 |
+
requests.post(f"{HUB_URL}/register", json={"pubkey": bob_id})
|
| 20 |
+
|
| 21 |
+
print(f"β
Registered Alice ({alice_id}) and Bob ({bob_id})")
|
| 22 |
+
|
| 23 |
+
async def alice_listen():
|
| 24 |
+
async with websockets.connect(f"{WS_URL}/ws/{alice_id}") as ws:
|
| 25 |
+
print("π§ Alice: Online and listening...")
|
| 26 |
+
msg = await asyncio.wait_for(ws.recv(), timeout=5)
|
| 27 |
+
data = json.loads(msg)
|
| 28 |
+
|
| 29 |
+
print(f"π§ Alice: Received DIRECT MESSAGE!")
|
| 30 |
+
print(f"π§ Alice: Payload: {data['data']['payload']}")
|
| 31 |
+
print(f"π§ Alice: Bounty: {data['data']['bounty']} SECONDS")
|
| 32 |
+
|
| 33 |
+
# Alice replies for free
|
| 34 |
+
requests.post(f"{HUB_URL}/tasks/complete", json={
|
| 35 |
+
"task_id": data['data']['id'],
|
| 36 |
+
"provider_id": alice_id,
|
| 37 |
+
"result_payload": "Yes Bob, I am available for a meeting tomorrow at 2 PM. Free of charge! π±"
|
| 38 |
+
})
|
| 39 |
+
print("π§ Alice: Sent reply!")
|
| 40 |
+
|
| 41 |
+
async def bob_listen():
|
| 42 |
+
async with websockets.connect(f"{WS_URL}/ws/{bob_id}") as ws:
|
| 43 |
+
# Bob submits a direct task to Alice with 0 bounty
|
| 44 |
+
await asyncio.sleep(1) # Let Alice connect first
|
| 45 |
+
print("π¦ Bob: Sending Direct Message to Alice (0.0 SECONDS)...")
|
| 46 |
+
requests.post(f"{HUB_URL}/tasks/submit", json={
|
| 47 |
+
"consumer_id": bob_id,
|
| 48 |
+
"payload": "Hey Alice, are you free for a meeting tomorrow at 2 PM?",
|
| 49 |
+
"bounty": 0.0,
|
| 50 |
+
"target_node": alice_id
|
| 51 |
+
})
|
| 52 |
+
|
| 53 |
+
# Bob waits for Alice's reply
|
| 54 |
+
msg = await asyncio.wait_for(ws.recv(), timeout=5)
|
| 55 |
+
data = json.loads(msg)
|
| 56 |
+
print(f"π¦ Bob: Received reply from {data['data']['provider_id']}:")
|
| 57 |
+
print(f"π¦ Bob: \"{data['data']['result_payload']}\"")
|
| 58 |
+
|
| 59 |
+
await asyncio.gather(alice_listen(), bob_listen())
|
| 60 |
+
print("=== Direct Messaging Test Complete! ===")
|
| 61 |
+
|
| 62 |
+
if __name__ == "__main__":
|
| 63 |
+
asyncio.run(test_direct_message())
|