feat(hybrid-gateway): integrate muse-cli with Cloudflare netns isolation, symmetric sidechat routing, and 646-pip sync unblock

This commit is contained in:
operator
2026-10-04 22:54:01 +00:00
parent 3d5fbe5aeb
commit 1a271b1bbd
60 changed files with 5068 additions and 55 deletions
+61 -24
View File
@@ -1174,24 +1174,38 @@ def cmd_dm_files(args):
# ---------------------------------------------------------------------------
def cmd_thread_list(args):
agent = args.agent
cmd = ["python3", str(BIN_DIR / "box-chat.py"), "thread-list", agent]
res = subprocess.run(cmd, capture_output=True, text=True)
threads = []
# Fast path: try fast headless gateway via muse_hybrid (isolated per-node WARP egress)
try:
data = json.loads(res.stdout)
import muse_hybrid
gw_threads, gw_err = muse_hybrid.get_threads(agent)
if gw_threads and not gw_err:
for t in gw_threads:
threads.append({
"id": t.get("session_id", ""),
"kind": "thread" if t.get("thread") else "chat",
"title": t.get("title") or "(no title)",
"participants": [agent],
"last_message_at": t.get("updated", "")
})
except Exception:
print(c_red("Failed to parse box-chat.py response:") + f"\n{res.stdout}\n{res.stderr}")
return
pass
# Fallback to box-chat.py / CDP if gateway returned no threads
if not threads:
cmd = ["python3", str(BIN_DIR / "box-chat.py"), "thread-list", agent]
res = subprocess.run(cmd, capture_output=True, text=True)
try:
data = json.loads(res.stdout)
threads = data.get("threads", []) if data.get("ok") else []
except Exception:
threads = []
if args.json:
print(json.dumps(data, indent=2))
print(json.dumps({"ok": True, "threads": threads}, indent=2))
return
if not data.get("ok"):
print(c_red(f"Error fetching threads for {agent}: {data.get('error', 'unknown error')}"))
return
threads = data.get("threads", [])
print("\n" + c_bold(f"=== ACTIVE THREADS FOR {agent.upper()} ({len(threads)}) ===") + "\n")
headers = ["ID / UUID", "KIND", "TITLE", "PARTICIPANTS", "LAST ACTIVE"]
@@ -1213,25 +1227,39 @@ def cmd_thread_view(args):
agent = args.agent
thread_id = args.thread_id
limit = getattr(args, "limit", 15)
messages = []
cmd = ["python3", str(BIN_DIR / "box-chat.py"), "thread-messages", agent, thread_id, "--limit", str(limit)]
res = subprocess.run(cmd, capture_output=True, text=True)
# Fast path: try fast headless gateway via muse_hybrid (isolated per-node WARP egress)
try:
data = json.loads(res.stdout)
import muse_hybrid
gw_msgs, gw_err = muse_hybrid.get_history(agent, thread_id=thread_id, limit=limit)
if gw_msgs and not gw_err:
for m in gw_msgs:
role = m.get("role", "unknown")
messages.append({
"from": {"name": role, "role": role},
"text": m.get("text", "")
})
except Exception:
print(c_red("Failed to parse box-chat.py response:") + f"\n{res.stdout}\n{res.stderr}")
return
pass
# Fallback to box-chat.py / CDP if gateway returned no messages
if not messages:
cmd = ["python3", str(BIN_DIR / "box-chat.py"), "thread-messages", agent, thread_id, "--limit", str(limit)]
res = subprocess.run(cmd, capture_output=True, text=True)
try:
data = json.loads(res.stdout)
messages = data.get("messages", []) if data.get("ok") else []
except Exception:
messages = []
if not messages:
print(c_red(f"Error viewing thread {thread_id}: no messages returned"))
return
if args.json:
print(json.dumps(data, indent=2))
print(json.dumps({"ok": True, "messages": messages}, indent=2))
return
if not data.get("ok"):
print(c_red(f"Error viewing thread {thread_id}: {data.get('error', 'unknown error')}"))
return
messages = data.get("messages", [])
print("\n" + c_bold(f"=== THREAD {thread_id} ({agent}) — {len(messages)} messages ===") + "\n")
for msg in messages:
@@ -3280,6 +3308,11 @@ def build_parser():
p_va_rb.add_argument("name", help="Variable name")
p_va_rb.add_argument("--revision", default=None, help="Revision step (int) or timestamp")
# Domain: muse (fast headless gateway via muse-cli-node with isolated per-node Cloudflare WARP egress)
p_muse = subparsers.add_parser("muse", parents=[common], help="Direct headless gateway client (muse-cli-node)")
p_muse.add_argument("node", choices=VALID_NODES, help="Target agent node")
p_muse.add_argument("muse_args", nargs=argparse.REMAINDER, help="Arguments passed directly to muse-cli-node")
return parser
def main():
@@ -3446,6 +3479,10 @@ def main():
cmd_loop_strat(args)
elif args.domain == "vars":
cmd_loop_vars(args)
elif args.domain == "muse":
cmd = [str(BIN_DIR / "muse-cli-node"), args.node] + (args.muse_args or [])
res = subprocess.run(cmd)
sys.exit(res.returncode)
else:
parser.print_help()