45 lines
2.5 KiB
Python
45 lines
2.5 KiB
Python
"""Live: detached delegate_task batch, one child fails immediately, siblings run ~8 s. Does the parent's
|
|
completion queue see the per-task failure notice BEFORE the consolidated batch result?
|
|
Usage: python notice_live.py <repo_root>"""
|
|
import json, os, sys, tempfile, threading, time
|
|
root = sys.argv[1]; sys.path.insert(0, root)
|
|
os.environ["HERMES_HOME"] = tempfile.mkdtemp(prefix="hh-")
|
|
os.environ["HERMES_STREAM_RETRIES"] = "0"
|
|
|
|
from run_agent import AIAgent
|
|
import tools.delegate_tool as dt
|
|
import tools.delegate_tool_dispatch as dd
|
|
from tools.process_registry import process_registry
|
|
|
|
parent = AIAgent(api_key="k", base_url="https://example.com/v1", provider="test-provider", model="test/model",
|
|
quiet_mode=True, skip_context_files=True, skip_memory=True)
|
|
parent.api_mode = "chat_completions"
|
|
|
|
# Stub the child run: task 0 fails instantly, others take 8 s and succeed.
|
|
orig_run = dd._Batch.run_child if hasattr(dd, "_Batch") else None
|
|
def fake_run_child(self, idx, task, child):
|
|
if idx == 0:
|
|
return {"task_index": 0, "status": "error", "error": "simulated 401 authentication_error", "api_calls": 0, "duration_seconds": 0.1}
|
|
time.sleep(8)
|
|
return {"task_index": idx, "status": "completed", "summary": f"ok {idx}", "api_calls": 1, "duration_seconds": 8.0}
|
|
dd._Batch.run_child = fake_run_child
|
|
|
|
# Background dispatch requires an async-capable session; emulate a CLI session key.
|
|
import tools.async_delegation as ad
|
|
t0 = time.time()
|
|
out = dt.delegate_task(# Grouped: siblings share ONE final result, so a dead sibling would otherwise wait for the slowest. (Ungrouped tasks are
|
|
# their own async unit since the per-group split landed on main and already report as they finish.)
|
|
tasks=[{"goal": "fail fast on a simulated 401 error", "group": "g"}, {"goal": "slow successful worker number one", "group": "g"}, {"goal": "slow successful worker number two", "group": "g"}], background=True, parent_agent=parent)
|
|
print("dispatch:", json.dumps(json.loads(out))[:160])
|
|
seen = []
|
|
deadline = time.time() + 30
|
|
while time.time() < deadline:
|
|
for evt, text in process_registry.drain_notifications(session_key=""):
|
|
kind = "TASK_FAILURE_NOTICE" if evt.get("task_failure_notice") else ("BATCH_FINAL" if evt.get("is_batch") else evt.get("type"))
|
|
seen.append((round(time.time() - t0, 1), kind))
|
|
print(f" t+{time.time()-t0:5.1f}s {kind}: {text.splitlines()[0][:100]}")
|
|
if any(k == "BATCH_FINAL" for _, k in seen):
|
|
break
|
|
time.sleep(0.3)
|
|
print("ORDER:", seen)
|