feat(box): passkey fetch, agent key-approval flow, unified lookups, tmux agent UX

- box passkey [show|fetch] (+ muse passkey): documents VM-only passkey
  (/srv/box/passkey.txt, fallback /etc/netvm/passkey.txt on 34.139.37.135),
  probes VM over SSH with graceful fallback; --json supported. No secrets on bl.
- approvals: request_key_approval / check_node_key_request; KEY_APPROVAL status
  surfaced in `box approvals check`; allow/deny resolve + audit to box-ctl.jsonl;
  never auto-approved. New `box approvals request-key <node> --reason`.
- box lookup (summary|fleet|threads|unread|approvals|key|docs) and docs-lookup
  engine with lookup_internal/ database (docs_internal symlink).
- muse-tmux: non-TTY attach falls back to scrollback capture; prune NameError fix.
- box/muse passthrough for tmux/muse/docs; thread list/view alias + prefix resolve.
- Docs: AGENTS.md, AGENT-TOOLING.md, BOX-WEB-SURFACE-GUIDE.md, README.
- Tests: key-approval + passkey tests; sync stale sidechat UUIDs and manifest name.
- .gitignore runtime trackers (subagent-sessions, conversation-nudge-tracker).
This commit is contained in:
operator
2026-10-05 20:18:47 +00:00
parent 59c9965791
commit adfcd2e602
38 changed files with 5948 additions and 168 deletions
+461 -71
View File
@@ -48,11 +48,55 @@ TRUSTED_IPS = {
"34.139.37.135", # VM (gateway)
"100.123.153.75", # bl (main compute)
"100.81.31.9", # VM tailnet
"1.1.1.1", # Cloudflare DNS
"1.0.0.1", # Cloudflare DNS
}
# Trusted infrastructure domains safe for automated approval
TRUSTED_DOMAINS = {
"muse-dev.online",
}
def is_trusted_target(target: str, card_text: str = "") -> bool:
"""Check if the extracted approval target is trusted infrastructure.
Fail-closed: only the parsed target (IP or hostname) is evaluated. Free-form
card text is deliberately NOT substring-matched, since an untrusted request
could mention a trusted domain in its purpose string. `card_text` is kept
for signature compatibility.
"""
if not target:
return False
target = target.strip().lower().rstrip(".")
if target in TRUSTED_IPS:
return True
for dom in TRUSTED_DOMAINS:
if target == dom or target.endswith("." + dom):
return True
return False
REDACT_PATTERNS = [
(re.compile(r"Bearer\s+[A-Za-z0-9._~+/-]+=*", re.IGNORECASE), "Bearer [REDACTED]"),
(re.compile(r"eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}", re.IGNORECASE), "[JWT-REDACTED]"),
(re.compile(r"(?i)\b(api[_-]?key|token|secret|password|auth|passkey)\s*[:=]\s*(['\"]?)([A-Za-z0-9_\-\.]{4,})\2"), r"\1: \2[REDACTED]\2"),
(re.compile(r"-----BEGIN [A-Z ]+ PRIVATE KEY-----[\s\S]*?-----END [A-Z ]+ PRIVATE KEY-----"), "[PRIVATE-KEY-REDACTED]"),
]
def redact_sensitive(text: str) -> str:
"""Mask credentials, tokens, and passkeys in text."""
if not text or not isinstance(text, str):
return text
out = text
for pattern, repl in REDACT_PATTERNS:
out = pattern.sub(repl, out)
return out
def log_box_ctl(action: str, name: str = None, caller: str = "box-approvals", extra: dict = None):
"""Log an audit event to box-ctl.jsonl."""
"""Log an audit event to box-ctl.jsonl with secret redaction."""
try:
rec = {
"ts": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
@@ -61,13 +105,76 @@ def log_box_ctl(action: str, name: str = None, caller: str = "box-approvals", ex
"caller": caller,
}
if extra:
rec.update(extra)
clean_extra = {}
for k, v in extra.items():
if isinstance(v, str):
clean_extra[k] = redact_sensitive(v)
else:
clean_extra[k] = v
rec.update(clean_extra)
with open(CTL_LOG, "a") as f:
f.write(json.dumps(rec) + "\n")
except Exception:
pass
def request_key_approval(node: str, reason: str = "", caller: str = "agent") -> dict:
"""Register a key/passkey approval request for a node in box-ctl.jsonl."""
reason = reason or "Operator passkey access requested"
log_box_ctl(
"key-approval-request",
name=node,
caller=caller,
extra={"reason": reason},
)
return {
"ok": True,
"node": node,
"status": "KEY_APPROVAL_REQUESTED",
"reason": reason,
"caller": caller,
"note": "Request recorded in audit log. Operator can approve via 'box approvals allow <node>'."
}
def check_node_key_request(node: str) -> dict:
"""Check if node has an active unfulfilled key approval request in box-ctl.jsonl."""
if not CTL_LOG.exists():
return None
latest_req = None
resolved = False
try:
with open(CTL_LOG, "r") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
rec = json.loads(line)
except Exception:
continue
if rec.get("name") != node:
continue
act = rec.get("action")
if act == "key-approval-request":
latest_req = rec
resolved = False
elif act in ("key-approval-allow", "key-approval-deny", "approval-allow", "approval-deny"):
resolved = True
except Exception:
return None
if latest_req and not resolved:
return {
"node": node,
"reason": latest_req.get("reason", "Operator passkey access requested"),
"requested_at": latest_req.get("ts", ""),
"caller": latest_req.get("caller", ""),
}
return None
def get_node_connection_info(node: str) -> dict:
"""Return peer_ip, cdp_port, and netns for a given node."""
if netvm_registry:
@@ -94,8 +201,8 @@ def get_node_connection_info(node: str) -> dict:
}
def get_cdp_ws(node: str, timeout: float = 3.0):
"""Connect to the node's active browser page over CDP WebSocket."""
def get_node_pages(node: str, timeout: float = 3.0) -> list:
"""Return all active page targets for a node."""
if websocket is None:
raise RuntimeError("websocket-client library is required")
@@ -125,13 +232,20 @@ def get_cdp_ws(node: str, timeout: float = 3.0):
pages = [t for t in tabs if t.get("type") == "page"]
if not pages:
raise ConnectionError(f"No active page found for node {node}")
return pages
ws_url = pages[0].get("webSocketDebuggerUrl")
def get_cdp_ws(node: str, page_idx: int = 0, timeout: float = 3.0):
"""Connect to a node's browser page over CDP WebSocket."""
pages = get_node_pages(node, timeout=timeout)
if page_idx >= len(pages):
page_idx = 0
target_page = pages[page_idx]
ws_url = target_page.get("webSocketDebuggerUrl")
if not ws_url:
raise ConnectionError(f"No webSocketDebuggerUrl for node {node}")
ws = websocket.create_connection(ws_url, timeout=timeout)
return ws, pages[0]
return ws, target_page
def cdp_evaluate(ws, js_expr: str, await_promise: bool = False, timeout: float = 3.0):
@@ -233,6 +347,16 @@ JS_INSPECT_APPROVALS = """(() => {
}
}
// Task rows in the Activity sidebar waiting on human input
// (e.g. "Launch 5 OPM Sub-Agents\\nAsked for input to start the launch\\n5:53 pm").
const inputWaits = [];
for (const b of document.querySelectorAll('button.rounded-10, a.rounded-10')) {
const lines = (b.innerText || '').split('\\n').map(s => s.trim()).filter(Boolean);
if (lines.length >= 2 && /^(asked for (input|details)|waiting for (your )?(input|reply|approval)|needs your input)/i.test(lines[1])) {
inputWaits.push({ task: lines[0], status: lines[1], when: lines[2] || '' });
}
}
return JSON.stringify({
has_pending: !!activeCard && (hasAllowOnce || hasDeny),
card_text: cardText.slice(0, 1000),
@@ -240,16 +364,40 @@ JS_INSPECT_APPROVALS = """(() => {
has_allow_once: hasAllowOnce,
has_always_allow: hasAlwaysAllow,
has_deny: hasDeny,
history: historyBadges.slice(0, 5)
history: historyBadges.slice(0, 5),
input_waits: inputWaits.slice(0, 10)
});
})()"""
def inspect_node_approvals(node: str) -> dict:
"""Inspect a node for active browser approval prompts."""
"""Inspect a node across all open page targets for active approval prompts and input waits."""
try:
ws, page = get_cdp_ws(node, timeout=2.5)
pages = get_node_pages(node, timeout=2.5)
except Exception as e:
key_req = check_node_key_request(node)
if key_req:
return {
"node": node,
"status": "KEY_APPROVAL",
"has_pending": True,
"title": f"Passkey requested: {key_req.get('reason')}",
"purpose": key_req.get("reason"),
"ip": "34.139.37.135",
"target": "34.139.37.135 (VM passkey)",
"is_trusted": True,
"buttons": ["Allow", "Deny"],
"has_allow_once": True,
"has_always_allow": False,
"has_deny": True,
"raw_text": f"Agent on node {node} requested passkey: {key_req.get('reason')}",
"history": [],
"input_waits": [],
"page_title": "",
"page_url": "",
"ws_url": "",
"key_request": key_req,
}
return {
"node": node,
"status": "UNREACHABLE",
@@ -257,66 +405,140 @@ def inspect_node_approvals(node: str) -> dict:
"has_pending": False,
}
try:
val_str = cdp_evaluate(ws, JS_INSPECT_APPROVALS, timeout=3.0)
ws.close()
if not val_str or not isinstance(val_str, str):
return {
"node": node,
"status": "CLEAR",
"has_pending": False,
"page_title": page.get("title", ""),
"page_url": page.get("url", ""),
}
all_input_waits = []
first_page = pages[0]
last_err = None
data = json.loads(val_str)
has_pending = data.get("has_pending", False)
card_text = data.get("card_text", "")
# Parse details
ip = None
m_ip = re.search(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", card_text)
if m_ip:
ip = m_ip.group(0)
# Extract title and purpose summary
lines = [line.strip() for line in card_text.split("\n") if line.strip()]
title = lines[0] if lines else "Permission request"
purpose = lines[1] if len(lines) > 1 else ""
is_trusted = False
if ip:
is_trusted = ip in TRUSTED_IPS
return {
"node": node,
"status": "PENDING" if has_pending else "CLEAR",
"has_pending": has_pending,
"title": title,
"purpose": purpose,
"ip": ip,
"is_trusted": is_trusted,
"buttons": data.get("buttons", []),
"has_allow_once": data.get("has_allow_once", False),
"has_always_allow": data.get("has_always_allow", False),
"has_deny": data.get("has_deny", False),
"raw_text": card_text,
"history": data.get("history", []),
"page_title": page.get("title", ""),
"page_url": page.get("url", ""),
}
except Exception as e:
for page in pages:
ws_url = page.get("webSocketDebuggerUrl")
if not ws_url:
continue
ws = None
try:
ws = websocket.create_connection(ws_url, timeout=2.0)
val_str = cdp_evaluate(ws, JS_INSPECT_APPROVALS, timeout=2.5)
ws.close()
except Exception:
pass
ws = None
if not val_str or not isinstance(val_str, str):
continue
data = json.loads(val_str)
if data.get("input_waits"):
all_input_waits.extend(data["input_waits"])
if data.get("has_pending"):
card_text = data.get("card_text", "")
ip = None
target = None
m_t = re.search(
r"(?:connection to|share information with|contact|connect to)\s+([A-Za-z0-9][A-Za-z0-9.-]*[A-Za-z0-9])",
card_text,
)
if m_t:
target = m_t.group(1)
m_ip = re.search(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", target or card_text)
if m_ip:
ip = m_ip.group(0)
if not target:
target = ip
if not target:
m_domain = re.search(r"\b([a-zA-Z0-9-]+\.)+(?:online|com|net|org|io|dev)\b", card_text)
if m_domain:
target = m_domain.group(0)
lines = [line.strip() for line in card_text.split("\n") if line.strip()]
title = redact_sensitive(lines[0] if lines else "Permission request")
purpose = redact_sensitive(lines[1] if len(lines) > 1 else "")
is_trusted = is_trusted_target(target or ip, card_text)
return {
"node": node,
"status": "PENDING",
"has_pending": True,
"title": title,
"purpose": purpose,
"ip": ip,
"target": target or ip or "-",
"is_trusted": is_trusted,
"buttons": data.get("buttons", []),
"has_allow_once": data.get("has_allow_once", False),
"has_always_allow": data.get("has_always_allow", False),
"has_deny": data.get("has_deny", False),
"raw_text": redact_sensitive(card_text),
"history": data.get("history", []),
"input_waits": all_input_waits,
"page_title": page.get("title", ""),
"page_url": page.get("url", ""),
"ws_url": ws_url,
}
except Exception as e:
last_err = e
if ws:
try:
ws.close()
except Exception:
pass
# Deduplicate input waits by task name
unique_waits = []
seen_tasks = set()
for w in all_input_waits:
t_name = redact_sensitive(w.get("task", ""))
status_text = redact_sensitive(w.get("status", ""))
if t_name not in seen_tasks:
seen_tasks.add(t_name)
unique_waits.append({
"task": t_name,
"status": status_text,
"when": w.get("when", ""),
})
key_req = check_node_key_request(node)
if key_req:
return {
"node": node,
"status": "ERROR",
"error": str(e),
"has_pending": False,
"status": "KEY_APPROVAL",
"has_pending": True,
"title": f"Passkey requested: {key_req.get('reason')}",
"purpose": key_req.get("reason"),
"ip": "34.139.37.135",
"target": "34.139.37.135 (VM passkey)",
"is_trusted": True,
"buttons": ["Allow", "Deny"],
"has_allow_once": True,
"has_always_allow": False,
"has_deny": True,
"raw_text": f"Agent on node {node} requested passkey: {key_req.get('reason')}",
"history": [],
"input_waits": unique_waits,
"page_title": first_page.get("title", ""),
"page_url": first_page.get("url", ""),
"ws_url": first_page.get("webSocketDebuggerUrl", ""),
"key_request": key_req,
}
status = "INPUT_WAIT" if unique_waits else ("ERROR" if last_err and not first_page else "CLEAR")
return {
"node": node,
"status": status,
"has_pending": False,
"title": "No pending approvals",
"purpose": "",
"ip": None,
"target": "-",
"is_trusted": False,
"buttons": [],
"has_allow_once": False,
"has_always_allow": False,
"has_deny": False,
"raw_text": "",
"history": [],
"input_waits": unique_waits,
"page_title": first_page.get("title", ""),
"page_url": first_page.get("url", ""),
"ws_url": first_page.get("webSocketDebuggerUrl", ""),
}
def check_fleet_approvals(nodes: list = None) -> list:
"""Check approval status across the fleet."""
@@ -333,6 +555,28 @@ def allow_node_approval(node: str, always: bool = False, force: bool = False, ca
if not info.get("has_pending"):
return {"ok": False, "node": node, "error": "No pending approval dialog found on node"}
if info.get("status") == "KEY_APPROVAL":
key_req = info.get("key_request") or check_node_key_request(node) or {}
reason = key_req.get("reason", info.get("purpose", ""))
log_box_ctl(
"key-approval-allow",
name=node,
caller=caller,
extra={
"reason": reason,
"forced": force,
},
)
return {
"ok": True,
"node": node,
"type": "key_approval",
"decision": "allow",
"dismissed": True,
"reason": reason,
"title": info.get("title"),
}
if not info.get("is_trusted") and not force:
target = info.get("ip") or "unrecognized target"
return {
@@ -343,7 +587,11 @@ def allow_node_approval(node: str, always: bool = False, force: bool = False, ca
}
try:
ws, _ = get_cdp_ws(node, timeout=3.0)
ws_url = info.get("ws_url")
if ws_url:
ws = websocket.create_connection(ws_url, timeout=3.0)
else:
ws, _ = get_cdp_ws(node, timeout=3.0)
except Exception as e:
return {"ok": False, "node": node, "error": f"Failed to connect to CDP: {e}"}
@@ -351,11 +599,19 @@ def allow_node_approval(node: str, always: bool = False, force: bool = False, ca
if always:
js_click = """(() => {
const btns = Array.from(document.querySelectorAll('button'));
const btn = btns.find(b => (b.innerText||'').toLowerCase().includes('always allow'));
let btn = btns.find(b => (b.innerText||'').toLowerCase().includes('always allow'));
if (btn) {
btn.click();
return 'CLICKED_ALWAYS';
}
btn = document.querySelector('button[data-hatch-approval-primary-action="true"]');
if (!btn) {
btn = btns.find(b => (b.innerText||'').toLowerCase().includes('allow once') || (b.innerText||'').trim().toLowerCase() === 'allow');
}
if (btn) {
btn.click();
return 'CLICKED_PRIMARY_FALLBACK';
}
return 'NOT_FOUND';
})()"""
else:
@@ -422,13 +678,38 @@ def allow_node_approval(node: str, always: bool = False, force: bool = False, ca
def deny_node_approval(node: str, caller: str = "box-approvals") -> dict:
"""Deny a pending approval on a node (click 'Deny')."""
"""Deny a pending approval on a node (click 'Deny' or deny key request)."""
info = inspect_node_approvals(node)
if not info.get("has_pending"):
return {"ok": False, "node": node, "error": "No pending approval dialog found on node"}
if info.get("status") == "KEY_APPROVAL":
key_req = info.get("key_request") or check_node_key_request(node) or {}
reason = key_req.get("reason", info.get("purpose", ""))
log_box_ctl(
"key-approval-deny",
name=node,
caller=caller,
extra={
"reason": reason,
},
)
return {
"ok": True,
"node": node,
"type": "key_approval",
"decision": "deny",
"dismissed": True,
"reason": reason,
"title": info.get("title"),
}
try:
ws, _ = get_cdp_ws(node, timeout=3.0)
ws_url = info.get("ws_url")
if ws_url:
ws = websocket.create_connection(ws_url, timeout=3.0)
else:
ws, _ = get_cdp_ws(node, timeout=3.0)
except Exception as e:
return {"ok": False, "node": node, "error": f"Failed to connect to CDP: {e}"}
@@ -481,8 +762,8 @@ def deny_node_approval(node: str, caller: str = "box-approvals") -> dict:
return {"ok": False, "node": node, "error": str(e)}
def auto_approve_fleet(nodes: list = None, caller: str = "box-approvals") -> dict:
"""Scan fleet nodes and automatically approve any requests to TRUSTED_IPS."""
def auto_approve_fleet(nodes: list = None, always: bool = True, caller: str = "box-approvals") -> dict:
"""Scan fleet nodes and automatically approve any requests to TRUSTED_IPS with Always Allow."""
fleet = check_fleet_approvals(nodes)
approved = []
untrusted = []
@@ -491,12 +772,16 @@ def auto_approve_fleet(nodes: list = None, caller: str = "box-approvals") -> dic
for item in fleet:
node = item["node"]
if item.get("has_pending"):
if item.get("is_trusted"):
res = allow_node_approval(node, caller=caller)
if item.get("status") == "KEY_APPROVAL":
# Key approvals require explicit operator decision, never auto-approve
untrusted.append(item)
elif item.get("is_trusted"):
res = allow_node_approval(node, always=always, caller=caller)
approved.append({
"node": node,
"target_ip": item.get("ip"),
"title": item.get("title"),
"decision": "always" if always else "allow_once",
"res": res,
})
else:
@@ -510,3 +795,108 @@ def auto_approve_fleet(nodes: list = None, caller: str = "box-approvals") -> dic
"untrusted_pending": untrusted,
"clear_nodes": clear,
}
def reply_node_task(node: str, message: str, allow_main_chat: bool = False, caller: str = "box-approvals") -> dict:
"""Send an operator reply into the waiting agent's thread to answer an input prompt."""
info = inspect_node_approvals(node)
page_url = info.get("page_url", "")
page_title = info.get("page_title", "")
ws_url = info.get("ws_url")
# Check if target is Main Chat
# Main chat signatures: not sidechat and (no /thread/ or title contains 'Chat —')
is_main = "sidechat" not in page_url.lower() and ("/thread/" not in page_url or "chat —" in page_title.lower())
if is_main and not allow_main_chat:
return {
"ok": False,
"node": node,
"error": "Active thread appears to be Main Chat. Refusing reply by sidechat-first policy. Pass --allow-main-chat to confirm intentional operator override.",
"page_title": page_title,
"page_url": page_url,
}
try:
if ws_url:
ws = websocket.create_connection(ws_url, timeout=3.0)
else:
ws, _ = get_cdp_ws(node, timeout=3.0)
except Exception as e:
return {"ok": False, "node": node, "error": f"Failed to connect to CDP: {e}"}
try:
msg_esc = message.replace('\\', '\\\\').replace('`', '\\`').replace('$', '\\$').replace('"', '\\"')
js_type_and_send = f"""(async() => {{
const input = document.querySelector('[contenteditable="true"]') ||
document.querySelector('textarea[placeholder*="Message"]') ||
document.querySelector('textarea');
if (!input) return 'NO_INPUT';
input.focus();
document.execCommand('insertText', false, "{msg_esc}");
await new Promise(r => setTimeout(r, 400));
const sendBtn = Array.from(document.querySelectorAll('button')).find(b => {{
const a = (b.getAttribute('aria-label') || '').toLowerCase();
const t = (b.innerText || '').toLowerCase();
return a.includes('send') || t === 'send';
}});
if (sendBtn && !sendBtn.disabled) {{
sendBtn.click();
return 'CLICKED_SEND';
}}
const ke = new KeyboardEvent('keydown', {{key: 'Enter', code: 'Enter', keyCode: 13, bubbles: true}});
input.dispatchEvent(ke);
return 'ENTER_SENT';
}})()"""
send_res = cdp_evaluate(ws, js_type_and_send, await_promise=True, timeout=5.0)
ws.close()
log_box_ctl(
"approval-reply",
name=node,
caller=caller,
extra={
"message_len": len(message),
"page_url": page_url,
"allow_main_chat": allow_main_chat,
"send_res": send_res,
},
)
return {
"ok": True,
"node": node,
"send_result": send_res,
"page_title": page_title,
"page_url": page_url,
}
except Exception as e:
try:
ws.close()
except Exception:
pass
return {"ok": False, "node": node, "error": str(e)}
def dismiss_node_task(node: str, caller: str = "box-approvals") -> dict:
"""Close any open task modal dialog or popup on a node."""
try:
ws, _ = get_cdp_ws(node, timeout=3.0)
except Exception as e:
return {"ok": False, "node": node, "error": f"Failed to connect to CDP: {e}"}
try:
js_dismiss = """(() => {
const close = document.querySelector('[aria-label="Close"], button[data-slot="dialog-close"]');
if (close) { close.click(); return 'CLICKED_CLOSE'; }
document.dispatchEvent(new KeyboardEvent('keydown', {key: 'Escape', code: 'Escape', keyCode: 27, bubbles: true}));
return 'ESCAPE_SENT';
})()"""
res = cdp_evaluate(ws, js_dismiss, timeout=2.0)
ws.close()
return {"ok": True, "node": node, "result": res}
except Exception as e:
try:
ws.close()
except Exception:
pass
return {"ok": False, "node": node, "error": str(e)}
+1
View File
@@ -0,0 +1 @@
/home/super/Projects/NetVM/bin/docs-lookup.py
+606
View File
@@ -0,0 +1,606 @@
#!/usr/bin/env python3
"""docs-lookup.py — Unified Lookup & Regex Passing Tool for docs_internal/.
Provides high-speed queries, regex passing, grammar validation, and surface
lookups for autonomous agents and operators interfacing with NetVM, Box,
and box.muse-dev.online.
Usage:
docs-lookup.py search <query>
docs-lookup.py surfaces [name]
docs-lookup.py sentence [name]
docs-lookup.py regex [name] [--test "<string>"]
docs-lookup.py parse "<string>"
docs-lookup.py get <collection> [key]
docs-lookup.py cli [domain]
docs-lookup.py overview
"""
import argparse
import json
import os
import re
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
NETVM_ROOT = Path(__file__).resolve().parent.parent
LOOKUP_INTERNAL = NETVM_ROOT / "lookup_internal"
if not LOOKUP_INTERNAL.exists() and (NETVM_ROOT / "docs_internal").exists():
LOOKUP_INTERNAL = NETVM_ROOT / "docs_internal"
DOCS_INTERNAL = LOOKUP_INTERNAL
USE_COLOR = sys.stdout.isatty() and os.environ.get("NO_COLOR") is None
def _c(code: str, text: str) -> str:
return f"\033[{code}m{text}\033[0m" if USE_COLOR else str(text)
def c_bold(s: str) -> str: return _c("1", s)
def c_dim(s: str) -> str: return _c("2", s)
def c_green(s: str) -> str: return _c("32", s)
def c_red(s: str) -> str: return _c("31", s)
def c_yellow(s: str) -> str: return _c("33", s)
def c_blue(s: str) -> str: return _c("34", s)
def c_cyan(s: str) -> str: return _c("36", s)
def c_magenta(s: str) -> str: return _c("35", s)
def load_json_file(filename: str) -> Dict[str, Any]:
"""Safely load a JSON file from docs_internal."""
p = DOCS_INTERNAL / filename
if not p.is_file():
return {}
try:
with open(p, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
print(f"Error reading {p}: {e}", file=sys.stderr)
return {}
def load_manifest() -> Dict[str, Any]:
return load_json_file("manifest.json")
def load_sentence_structures() -> Dict[str, Any]:
return load_json_file("sentence_structure.json")
def load_regex_patterns() -> Dict[str, Any]:
return load_json_file("regex_patterns.json")
def load_assistive_surfaces() -> Dict[str, Any]:
return load_json_file("assistive_surfaces.json")
def load_cli_tools() -> Dict[str, Any]:
return load_json_file("cli_tools.json")
def load_fleet_nodes() -> Dict[str, Any]:
return load_json_file("fleet_nodes.json")
def compile_pattern(pat_entry: Dict[str, Any]) -> Tuple[Optional[re.Pattern], Optional[str]]:
"""Compile a regex entry with its configured flags."""
raw_pat = pat_entry.get("pattern", "")
flag_names = pat_entry.get("flags", [])
flags = 0
for fn in flag_names:
if hasattr(re, fn):
flags |= getattr(re, fn)
try:
return re.compile(raw_pat, flags), None
except Exception as e:
return None, str(e)
# ---------------------------------------------------------------------------
# Core Lookup Actions
# ---------------------------------------------------------------------------
def handle_overview(json_mode: bool = False):
manifest = load_manifest()
if json_mode:
print(json.dumps(manifest, indent=2))
return
print(c_bold("\n=== docs_internal — Internal Agent & Operator Lookup Database ==="))
print(c_dim(f"Location: {DOCS_INTERNAL} | Host: {manifest.get('host', 'box.muse-dev.online')}"))
print(f"{manifest.get('description', '')}\n")
print(c_cyan("Available Collections:"))
collections = manifest.get("collections", [])
for col in collections:
cid = col.get("id")
name = col.get("name")
desc = col.get("description")
jfile = col.get("json_file")
mfile = col.get("md_file")
print(f" • {c_bold(cid):<20} {c_green(name)}")
print(f" {c_dim(desc)}")
print(f" {c_dim('Files:')} {c_yellow(jfile)} | {c_yellow(mfile)}")
print()
print(c_dim("Query commands: super docs [search|surfaces|sentence|regex|parse|get|cli]"))
def handle_search(query: str, json_mode: bool = False):
q = query.lower()
results = []
# Search in all JSON files
for jpath in sorted(DOCS_INTERNAL.glob("*.json")):
try:
data = json.loads(jpath.read_text(encoding="utf-8"))
except Exception:
continue
def recurse_search(obj, path=""):
if isinstance(obj, dict):
for k, v in obj.items():
subpath = f"{path}.{k}" if path else k
if q in str(k).lower():
results.append({
"file": jpath.name,
"type": "json_key",
"path": subpath,
"match": str(k),
"preview": str(v)[:160]
})
recurse_search(v, subpath)
elif isinstance(obj, list):
for idx, item in enumerate(obj):
recurse_search(item, f"{path}[{idx}]")
elif isinstance(obj, str):
if q in obj.lower():
results.append({
"file": jpath.name,
"type": "json_value",
"path": path,
"match": obj[:120],
"preview": obj[:240]
})
recurse_search(data)
# Search in Markdown files
for mpath in sorted(DOCS_INTERNAL.glob("*.md")):
try:
content = mpath.read_text(encoding="utf-8")
except Exception:
continue
lines = content.splitlines()
for idx, line in enumerate(lines, 1):
if q in line.lower():
results.append({
"file": mpath.name,
"type": "markdown",
"line": idx,
"match": line.strip(),
"preview": line.strip()
})
if json_mode:
print(json.dumps({"query": query, "count": len(results), "results": results}, indent=2))
return
print(c_bold(f"\nSearch results for '{query}' ({len(results)} matches):"))
if not results:
print(c_dim(" (no matching entries found)"))
return
for r in results[:40]:
if r["type"] == "markdown":
print(f" [{c_yellow(r['file'])}:{c_cyan(str(r['line']))}] {r['match']}")
else:
print(f" [{c_blue(r['file'])}:{c_magenta(r['path'])}] {r['preview']}")
def handle_surfaces(view_name: Optional[str] = None, json_mode: bool = False):
data = load_assistive_surfaces()
views = data.get("views", {})
if view_name:
key = view_name.lower().strip()
v = views.get(key)
if not v:
for k, val in views.items():
if key in k or key in val.get("name", "").lower():
v = val
key = k
break
if not v:
err = {"error": f"Surface '{view_name}' not found", "available": list(views.keys())}
if json_mode:
print(json.dumps(err, indent=2))
else:
print(c_red(f"Error: Surface '{view_name}' not found. Available: {', '.join(views.keys())}"))
sys.exit(1)
if json_mode:
print(json.dumps({key: v}, indent=2))
return
print(c_bold(f"\n=== Assistive Surface: {v.get('name')} (`{key}`) ==="))
print(c_dim(f"Host: {data.get('host')} | Tab ID: {v.get('tab_id')}"))
print(f"{c_cyan('DOM Tab Selector:')} {c_yellow(str(v.get('dom_tab_selector')))}")
print(f"{c_cyan('DOM Pane Selector:')} {c_yellow(str(v.get('dom_pane_selector')))}")
elements = v.get("key_elements", {})
if elements:
print(c_bold("\nKey DOM Elements / Selectors:"))
for el_name, sel in elements.items():
print(f" • {c_magenta(el_name):<20} {c_green(sel)}")
endpoints = v.get("api_endpoints", [])
if endpoints:
print(c_bold("\nAssociated REST API Endpoints:"))
for ep in endpoints:
print(f" • {c_bold(ep.get('method'))} {c_cyan(ep.get('path'))}")
print(f" {c_dim(ep.get('description'))}")
if ep.get("curl_example"):
print(f" {c_dim('curl:')} {c_yellow(ep.get('curl_example'))}")
recipe = v.get("assistive_recipe")
if recipe:
print(c_bold("\nAssistive Recipe:"))
print(f" {recipe}")
print()
return
# All views
if json_mode:
print(json.dumps(data, indent=2))
return
print(c_bold(f"\n=== Assistive Surfaces for {data.get('host', 'box.muse-dev.online')} ==="))
print(c_dim(f"Operator PIN: {data.get('auth', {}).get('pin')} | Session Cookie: {data.get('auth', {}).get('cookie_name')}"))
print()
for k, v in views.items():
name = v.get("name", k)
tab_sel = v.get("dom_tab_selector") or "(modal/overlay)"
eps = [f"{ep.get('method')} {ep.get('path')}" for ep in v.get("api_endpoints", [])]
ep_summary = ", ".join(eps) if eps else "(no direct endpoint)"
print(f" • {c_bold(k):<16} {c_cyan(name):<30} {c_yellow(tab_sel)}")
print(f" {c_dim('API:')} {ep_summary}")
if v.get("assistive_recipe"):
print(f" {c_dim('Hint:')} {v.get('assistive_recipe')[:100]}...")
print()
def handle_sentence(name: Optional[str] = None, json_mode: bool = False):
data = load_sentence_structures()
structs = data.get("structures", {})
if name:
key = name.lower().strip()
s = structs.get(key)
if not s:
for k, val in structs.items():
if key in k or key in val.get("name", "").lower() or key in val.get("protocol_tag", "").lower():
s = val
key = k
break
if not s:
err = {"error": f"Sentence structure '{name}' not found", "available": list(structs.keys())}
if json_mode:
print(json.dumps(err, indent=2))
else:
print(c_red(f"Error: Sentence structure '{name}' not found. Available: {', '.join(structs.keys())}"))
sys.exit(1)
if json_mode:
print(json.dumps({key: s}, indent=2))
return
print(c_bold(f"\n=== Protocol Structure: {s.get('name')} (`{key}`) ==="))
print(f"{c_cyan('Tag:')} {c_bold(s.get('protocol_tag'))}")
print(f"{c_cyan('Template:')} {c_green(s.get('template'))}")
print(f"{c_cyan('Lifecycle:')} {c_yellow(s.get('lifecycle_transition', ''))}")
print(f"\n{c_bold('Description:')}\n {s.get('description')}")
print(f"\n{c_bold('Required Fields:')} {', '.join(s.get('required_fields', []))}")
if s.get("optional_fields"):
print(f"{c_bold('Optional Fields:')} {', '.join(s.get('optional_fields', []))}")
print(f"\n{c_bold('Example:')}\n {c_cyan(s.get('example'))}")
print(f"\n{c_bold('Reply Expectation:')}\n {s.get('reply_expectation')}")
print()
return
if json_mode:
print(json.dumps(data, indent=2))
return
print(c_bold("\n=== Agent Sentence Structures & Conversational Contracts ==="))
print(c_dim("Format rules enforced by response-harvester and self_main_loop.\n"))
for k, s in structs.items():
tag = s.get("protocol_tag", "")
desc = s.get("description", "")
print(f" • {c_bold(k):<18} {c_green(tag):<25} {s.get('name')}")
print(f" {c_dim(desc)}")
print(f" {c_dim('Template:')} {c_cyan(s.get('template', ''))}")
print()
def handle_regex(name: Optional[str] = None, test_str: Optional[str] = None, json_mode: bool = False):
data = load_regex_patterns()
pats = data.get("patterns", {})
if name:
key = name.lower().strip()
p = pats.get(key)
if not p:
for k, val in pats.items():
if key in k or key in val.get("name", "").lower():
p = val
key = k
break
if not p:
err = {"error": f"Regex pattern '{name}' not found", "available": list(pats.keys())}
if json_mode:
print(json.dumps(err, indent=2))
else:
print(c_red(f"Error: Pattern '{name}' not found. Available: {', '.join(pats.keys())}"))
sys.exit(1)
compiled, comp_err = compile_pattern(p)
test_result = None
if test_str is not None:
if compiled:
m = compiled.search(test_str)
test_result = {
"matched": bool(m),
"match_span": m.span() if m else None,
"matched_text": m.group(0) if m else None,
"named_groups": m.groupdict() if m else {},
"groups": list(m.groups()) if m else []
}
else:
test_result = {"matched": False, "error": comp_err}
if json_mode:
out = {key: p, "compiled_ok": bool(compiled)}
if test_str is not None:
out["test_evaluation"] = test_result
print(json.dumps(out, indent=2))
return
print(c_bold(f"\n=== Regex Pattern: {p.get('name')} (`{key}`) ==="))
print(f"{c_cyan('Pattern:')} {c_yellow(p.get('pattern'))}")
print(f"{c_cyan('Flags:')} {', '.join(p.get('flags', [])) or '(none)'}")
print(f"{c_cyan('Description:')} {p.get('description')}")
print(f"{c_cyan('Usage:')} {c_dim(p.get('usage', ''))}")
ng = p.get("named_groups", {})
if ng:
print(c_bold("\nNamed Groups:"))
for gname, gdesc in ng.items():
print(f" • {c_magenta(gname):<16} {gdesc}")
if test_str is not None:
print(c_bold("\nTest Execution Result:"))
print(f" Input: {c_dim(test_str)}")
if test_result.get("matched"):
print(f" Verdict: {c_green('✔ MATCHED')}")
print(f" Matched Text: {c_cyan(test_result['matched_text'])}")
if test_result["named_groups"]:
print(f" Extracted Tokens:")
for k_grp, v_grp in test_result["named_groups"].items():
print(f" - {c_magenta(k_grp)}: {c_yellow(str(v_grp))}")
else:
print(f" Verdict: {c_red('✖ NO MATCH')}")
if comp_err:
print(f" Compile Error: {comp_err}")
print()
return
# List patterns
if json_mode:
print(json.dumps(data, indent=2))
return
print(c_bold("\n=== Master Regex Patterns & Passing Dictionary ==="))
print(c_dim("Patterns tested and calibrated across response-harvester, dm, and loop engines.\n"))
for k, p in pats.items():
print(f" • {c_bold(k):<18} {c_green(p.get('name'))}")
print(f" {c_dim('Pattern:')} {c_yellow(p.get('pattern'))}")
print(f" {c_dim(p.get('description'))}")
print()
def handle_parse(candidate_str: str, json_mode: bool = False):
"""Pass candidate_str through all registered regexes and extract tokens."""
data = load_regex_patterns()
pats = data.get("patterns", {})
matches = []
for k, p in pats.items():
compiled, err = compile_pattern(p)
if not compiled:
continue
m = compiled.search(candidate_str)
if m:
matches.append({
"pattern_key": k,
"pattern_name": p.get("name"),
"matched_text": m.group(0),
"named_groups": m.groupdict(),
"span": m.span()
})
if json_mode:
print(json.dumps({
"input": candidate_str,
"matched_patterns_count": len(matches),
"matches": matches
}, indent=2))
return
print(c_bold(f"\n=== Regex Parse Analysis ==="))
print(f"Input: {c_dim(candidate_str)}\n")
if not matches:
print(c_yellow(" ⚠ No registered regex pattern matched this string."))
return
print(c_green(f"Matched {len(matches)} pattern(s):"))
for match in matches:
print(f"\n • Pattern: {c_bold(match['pattern_name'])} (`{c_cyan(match['pattern_key'])}`)")
print(f" Matched Chunk: {c_yellow(match['matched_text'])}")
ng = match["named_groups"]
if ng:
print(f" Extracted Tokens:")
for gk, gv in ng.items():
print(f" - {c_magenta(gk)}: {c_green(str(gv))}")
print()
def handle_get(collection: str, key: Optional[str] = None, json_mode: bool = False):
col_map = {
"manifest": "manifest.json",
"sentence": "sentence_structure.json",
"sentence_structure": "sentence_structure.json",
"regex": "regex_patterns.json",
"regex_patterns": "regex_patterns.json",
"surfaces": "assistive_surfaces.json",
"assistive_surfaces": "assistive_surfaces.json",
"cli": "cli_tools.json",
"cli_tools": "cli_tools.json",
"fleet": "fleet_nodes.json",
"fleet_nodes": "fleet_nodes.json",
}
fname = col_map.get(collection.lower().strip())
if not fname:
print(c_red(f"Error: Unknown collection '{collection}'. Available: {', '.join(col_map.keys())}"), file=sys.stderr)
sys.exit(1)
data = load_json_file(fname)
if key:
# Check top level or primary container
val = None
for primary in ["structures", "patterns", "views", "domains", "nodes", "collections"]:
if primary in data and isinstance(data[primary], dict) and key in data[primary]:
val = data[primary][key]
break
if val is None and key in data:
val = data[key]
if val is None:
print(c_red(f"Error: Key '{key}' not found in {fname}"), file=sys.stderr)
sys.exit(1)
data = {key: val}
print(json.dumps(data, indent=2))
def handle_cli(domain: Optional[str] = None, json_mode: bool = False):
data = load_cli_tools()
domains = data.get("domains", {})
if domain:
d = domains.get(domain.lower().strip())
if not d:
print(c_red(f"Error: CLI domain '{domain}' not found. Available: {', '.join(domains.keys())}"), file=sys.stderr)
sys.exit(1)
if json_mode:
print(json.dumps({domain: d}, indent=2))
return
print(c_bold(f"\n=== CLI Tool Domain: super {domain} / box {domain} ==="))
print(f"Summary: {d.get('summary')}\n")
for sub in d.get("subcommands", []):
print(f" • {c_green(sub['cmd'])}")
print(f" {c_dim(sub['desc'])}\n")
return
if json_mode:
print(json.dumps(data, indent=2))
return
print(c_bold("\n=== Unified NetVM & Box CLI Tool Catalog ==="))
print(c_dim("Powered by super-cli.py and bin/muse wrapper.\n"))
for dom_k, dom_v in domains.items():
print(f" • {c_bold(dom_k):<16} {c_cyan(dom_v.get('summary'))}")
for sub in dom_v.get("subcommands", [])[:2]:
print(f" - {c_dim(sub['cmd'])}")
print()
# ---------------------------------------------------------------------------
# CLI Argument Parser
# ---------------------------------------------------------------------------
def build_parser():
common = argparse.ArgumentParser(add_help=False)
common.add_argument("--json", action="store_true", help="Output machine-readable JSON")
parser = argparse.ArgumentParser(
description="docs-lookup — Internal Agent & Operator Documentation Query Engine",
parents=[common],
formatter_class=argparse.RawDescriptionHelpFormatter
)
sub = parser.add_subparsers(dest="action")
p_search = sub.add_parser("search", parents=[common], help="Full-text search across docs_internal")
p_search.add_argument("query", help="Search keyword or phrase")
p_surfaces = sub.add_parser("surfaces", parents=[common], help="Lookup assistive surfaces for box.muse-dev.online")
p_surfaces.add_argument("name", nargs="?", default=None, help="Surface or tab name")
p_sentence = sub.add_parser("sentence", parents=[common], help="Lookup agent sentence structures & protocols")
p_sentence.add_argument("name", nargs="?", default=None, help="Structure name (e.g. work_order, result)")
p_regex = sub.add_parser("regex", parents=[common], help="Lookup and test regex patterns")
p_regex.add_argument("name", nargs="?", default=None, help="Pattern name (e.g. work_order, verb)")
p_regex.add_argument("--test", dest="test_str", default=None, help="Test string to evaluate against pattern")
p_parse = sub.add_parser("parse", parents=[common], help="Parse an agent utterance through all regex patterns")
p_parse.add_argument("string", help="String/utterance to parse")
p_get = sub.add_parser("get", parents=[common], help="Query raw JSON collection and key")
p_get.add_argument("collection", help="Collection name (sentence, regex, surfaces, cli, fleet)")
p_get.add_argument("key", nargs="?", default=None, help="Optional specific key")
p_cli = sub.add_parser("cli", parents=[common], help="Lookup CLI commands and syntax")
p_cli.add_argument("domain", nargs="?", default=None, help="CLI domain (fleet, dm, job, etc.)")
p_overview = sub.add_parser("overview", parents=[common], help="Database overview and collections manifest")
return parser
def main():
parser = build_parser()
args = parser.parse_args()
act = args.action
json_mode = getattr(args, "json", False)
if not act or act == "overview":
handle_overview(json_mode)
elif act == "search":
handle_search(args.query, json_mode)
elif act == "surfaces":
handle_surfaces(args.name, json_mode)
elif act == "sentence":
handle_sentence(args.name, json_mode)
elif act == "regex":
handle_regex(args.name, args.test_str, json_mode)
elif act == "parse":
handle_parse(args.string, json_mode)
elif act == "get":
handle_get(args.collection, args.key, json_mode)
elif act == "cli":
handle_cli(args.domain, json_mode)
else:
parser.print_help()
if __name__ == "__main__":
main()
+32 -30
View File
@@ -49,7 +49,7 @@ import sys
import tempfile
import threading
import time
from http.server import HTTPServer, BaseHTTPRequestHandler
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
import ssl
# ---------------------------------------------------------------- config
@@ -139,33 +139,34 @@ def check_token(token):
def check_nonce(nonce):
now = time.time()
fresh = []
try:
with open(NONCE_FILE) as f:
for line in f:
parts = line.split()
if len(parts) != 2:
continue
n, t = parts
try:
if now - float(t) < 2 * SIG_MAX_SKEW:
fresh.append((n, t))
except ValueError:
pass
except FileNotFoundError:
pass
if any(n == nonce for n, _ in fresh):
return False
fresh.append((nonce, str(now)))
try:
with open(NONCE_FILE, 'w') as f:
for n, t in fresh:
f.write(f'{n} {t}\n')
os.chmod(NONCE_FILE, 0o600)
except OSError:
return False
return True
with _nonce_lock:
now = time.time()
fresh = []
try:
with open(NONCE_FILE) as f:
for line in f:
parts = line.split()
if len(parts) != 2:
continue
n, t = parts
try:
if now - float(t) < 2 * SIG_MAX_SKEW:
fresh.append((n, t))
except ValueError:
pass
except FileNotFoundError:
pass
if any(n == nonce for n, _ in fresh):
return False
fresh.append((nonce, str(now)))
try:
with open(NONCE_FILE, 'w') as f:
for n, t in fresh:
f.write(f'{n} {t}\n')
os.chmod(NONCE_FILE, 0o600)
except OSError:
return False
return True
def check_signature(identity, payload, signature):
@@ -364,7 +365,7 @@ def _dm_read_validate(raw):
def _dm_read_build(a):
return [sys.executable, os.path.join(BIN_DIR, 'dm.py'), 'read',
'--agent', a['agent'], '--target', a['target'],
'--limit', str(a['limit'])]
'--n', str(a['limit'])]
def _job_run_validate(raw):
@@ -1294,6 +1295,7 @@ def permitted(ident, op):
# ------------------------------------------------------- audit log
_audit_lock = threading.Lock()
_nonce_lock = threading.Lock()
def audit(entry):
@@ -1501,7 +1503,7 @@ def main():
BIN_DIR, JOBS_DIR = args.bin_dir, args.jobs_dir
WORK_DIR = args.work_dir
server = HTTPServer((args.host, args.port), Handler)
server = ThreadingHTTPServer((args.host, args.port), Handler)
cert_file = args.cert_file
key_file = args.key_file
+47 -9
View File
@@ -185,22 +185,29 @@ HEALTHY_AGENTS=""
esac
done
# --- Agent approval blockage detection (catches agents held up on approvals) ---
# --- Agent approval blockage & input wait detection ---
"$BIN/netvm-registry.py" 2>/dev/null | while IFS=: read -r node port; do
[ -n "$node" ] || continue
cond="approval:$node"
pending_info=$(python3 -c "
import sys
node_data=$(python3 -c "
import sys, json
sys.path.insert(0, '$BIN')
import approvals
info = approvals.inspect_node_approvals('$node')
if info.get('has_pending'):
print(f\"{info.get('ip') or 'unknown'}|{info.get('title') or ''}\")
" 2>/dev/null || true)
out = {
'has_pending': info.get('has_pending', False),
'target': info.get('target') or info.get('ip') or 'unknown',
'title': info.get('title') or '',
'waits': info.get('input_waits') or []
}
print(json.dumps(out))
" 2>/dev/null || echo '{"has_pending":false,"target":"unknown","title":"","waits":[]}')
if [ -n "$pending_info" ]; then
# 1. Egress permission dialog
cond="approval:$node"
has_pending=$(python3 -c "import json,sys; print(1 if json.loads(sys.argv[1]).get('has_pending') else 0)" "$node_data" 2>/dev/null || echo 0)
if [ "$has_pending" = "1" ]; then
failing=1
target="${pending_info%%|*}"
target=$(python3 -c "import json,sys; print(json.loads(sys.argv[1]).get('target','unknown'))" "$node_data" 2>/dev/null || echo unknown)
detail="Agent $node held up on browser approval for $target"
else
failing=0
@@ -220,6 +227,37 @@ if info.get('has_pending'):
log "$cond still critical x$fails — re-page suppressed"
;;
esac
# 2. Sidebar task waiting on human input
cond_in="input_wait:$node"
wait_summary=$(python3 -c "
import json,sys
w = json.loads(sys.argv[1]).get('waits', [])
if w:
print('; '.join(f\"{item.get('task')}: {item.get('status')}\" for item in w)[:120])
" "$node_data" 2>/dev/null || true)
if [ -n "$wait_summary" ]; then
failing_in=1
detail_in="Agent $node task waiting for human input: $wait_summary"
else
failing_in=0
detail_in="Agent $node tasks running"
fi
injected "$cond_in" && failing_in=1
read -r action_in fails_in < <(state_machine "$cond_in" "$failing_in")
case "$action_in" in
ALERT_FIRST|ALERT_REALERT)
emit_record "ALERT" "$cond_in" "$detail_in" "$fails_in"
echo "$cond_in" >> "$STATE_DIR/.alerts.tmp"
;;
RECOVERY)
emit_record "RECOVERY" "$cond_in" "$detail_in" "$fails_in"
;;
SUPPRESSED)
log "$cond_in still critical x$fails_in — re-page suppressed"
;;
esac
done
# --- Warp partition detection (2026-10-04) ---
+12 -2
View File
@@ -632,7 +632,7 @@ def diagnose_breaks() -> list:
if app.get("has_pending"):
node = app["node"]
is_trusted = app.get("is_trusted", False)
ip = app.get("ip") or "unknown target"
ip = app.get("target") or app.get("ip") or "unknown target"
breaks.append({
"type": "approval_blocked",
"severity": "WARNING" if is_trusted else "CRITICAL",
@@ -641,6 +641,16 @@ def diagnose_breaks() -> list:
"detail": f"Agent {node} is held up on browser approval for {ip}",
"remedy": f"Run 'box approvals auto' or 'box approvals allow {node}'."
})
for w in app.get("input_waits") or []:
node = app["node"]
breaks.append({
"type": "input_wait",
"severity": "WARNING",
"component": f"node:{node}",
"agent": node,
"detail": f"Agent {node} task '{w.get('task')}' is waiting: {w.get('status')} ({w.get('when')})",
"remedy": f"Open {node}'s task and answer it, or 'box approvals check --node {node}'."
})
except Exception:
pass
@@ -758,7 +768,7 @@ def remediate_breaks(dry_run=False) -> dict:
if app.get("has_pending") and app.get("is_trusted"):
node = app["node"]
if not dry_run:
approvals.allow_node_approval(node, caller="loop-remediate")
approvals.allow_node_approval(node, always=True, caller="loop-remediate")
remediated.append({
"type": "approval_auto_allowed",
"agent": node,
+20
View File
@@ -503,6 +503,26 @@ def main():
elif job.get("target"):
target = job.get("target").strip()
# Pre-dispatch approval & input check (auto-approve trusted; warn if blocked)
if not dry_run:
try:
import approvals
app_info = approvals.inspect_node_approvals(agent)
if app_info.get("has_pending"):
if app_info.get("is_trusted"):
print(f"Pre-dispatch: auto-approving trusted request for {agent} ({app_info.get('target')})")
approvals.allow_node_approval(agent, always=True, caller="job-dispatch")
else:
print(f"Warning: Agent '{agent}' has untrusted pending approval ({app_info.get('target')}). Dispatch may stall.", file=sys.stderr)
log_event("job_dispatch_approval_blocked", {"job_id": job_id, "agent": agent, "target": app_info.get("target")})
elif app_info.get("status") == "INPUT_WAIT":
waits = app_info.get("input_waits", [])
w_desc = "; ".join(w.get("task", "") for w in waits)[:80]
print(f"Notice: Agent '{agent}' has task waiting for input ({w_desc}).", file=sys.stderr)
log_event("job_dispatch_agent_input_wait", {"job_id": job_id, "agent": agent, "waits": w_desc})
except Exception:
pass
# Sidechat-first policy (2026-10-04): refuse to dispatch to main chat
# unless the job explicitly opts in. Never fall back to main silently.
allow_main = bool(job.get("allow_main_chat")) or args.allow_main_chat
Symlink
+1
View File
@@ -0,0 +1 @@
/home/super/Projects/NetVM/bin/docs-lookup.py
+200
View File
@@ -0,0 +1,200 @@
#!/usr/bin/env python3
"""lookup_engine.py — Shared Zero-Downtime Hot-Reloading Pattern & Schema Engine.
Provides authoritative runtime access to lookup_internal/ databases for
daemons (response-harvester, self_main_loop, job-dispatch), CLI commands,
and agents.
Features:
- Dynamic mtime-based zero-downtime hot reloading of compiled regex patterns.
- Pre-flight soft validation of outbound agent sentences and work orders.
- Direct helper functions for core protocol regexes (RESULT, VERB, TOOL, etc.).
"""
import json
import os
import re
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
NETVM_ROOT = Path(__file__).resolve().parent.parent
LOOKUP_INTERNAL = NETVM_ROOT / "lookup_internal"
if not LOOKUP_INTERNAL.exists() and (NETVM_ROOT / "docs_internal").exists():
LOOKUP_INTERNAL = NETVM_ROOT / "docs_internal"
# In-memory cache structures with modification timestamps
_CACHE_MTIMES: Dict[str, float] = {}
_RAW_CACHE: Dict[str, Any] = {}
_COMPILED_PATTERNS: Dict[str, re.Pattern] = {}
# Fallback hardcoded regexes in case files are missing or unreadable
_FALLBACK_RESULT_RE = re.compile(r"\[RESULT\s+([A-Za-z0-9_/-]+)\]\s*(.*?)(?=\[RESULT\s|\Z)", re.S)
_FALLBACK_VERB_RE = re.compile(r"\[(ACK|CLAIM|RESULT|DECLINE|NO-ACTION)\s+([A-Za-z0-9_/-]+)\]")
_FALLBACK_TOOL_RE = re.compile(r"\[(TOOL|EXEC)\s+([a-zA-Z0-9_.-]+)\s+(\{.*?\})\]", re.S)
_FALLBACK_CONTRACT_FOOTER = (
"Reply: [ACK id] seen | [CLAIM id] mine | "
"[RESULT id] done | [DECLINE id] | [NO-ACTION id]."
)
def load_lookup_json(filename: str) -> Dict[str, Any]:
"""Load JSON from lookup_internal/ with mtime-based caching."""
target_path = LOOKUP_INTERNAL / filename
if not target_path.is_file():
return {}
try:
current_mtime = os.path.getmtime(target_path)
except OSError:
return _RAW_CACHE.get(filename, {})
if filename in _RAW_CACHE and _CACHE_MTIMES.get(filename) == current_mtime:
return _RAW_CACHE[filename]
try:
with open(target_path, "r", encoding="utf-8") as f:
data = json.load(f)
_RAW_CACHE[filename] = data
_CACHE_MTIMES[filename] = current_mtime
return data
except Exception as e:
print(f"[lookup_engine] Warning: Error reading {target_path}: {e}", file=sys.stderr)
return _RAW_CACHE.get(filename, {})
def _refresh_compiled_patterns_if_needed():
"""Checks regex_patterns.json mtime and recompiles if changed."""
global _COMPILED_PATTERNS
data = load_lookup_json("regex_patterns.json")
patterns_data = data.get("patterns", {})
target_path = LOOKUP_INTERNAL / "regex_patterns.json"
current_mtime = _CACHE_MTIMES.get("regex_patterns.json", 0.0)
compiled_mtime = _CACHE_MTIMES.get("_compiled_patterns_mtime", 0.0)
if current_mtime == compiled_mtime and _COMPILED_PATTERNS:
return
new_compiled = {}
for key, entry in patterns_data.items():
raw_pat = entry.get("pattern", "")
flag_names = entry.get("flags", [])
flags = 0
for fn in flag_names:
if hasattr(re, fn):
flags |= getattr(re, fn)
try:
new_compiled[key] = re.compile(raw_pat, flags)
except Exception as e:
print(f"[lookup_engine] Warning: Failed to compile pattern '{key}': {e}", file=sys.stderr)
_COMPILED_PATTERNS = new_compiled
_CACHE_MTIMES["_compiled_patterns_mtime"] = current_mtime
def get_compiled_pattern(name: str) -> Optional[re.Pattern]:
"""Retrieve a compiled pattern by name, hot-reloading if the database was modified."""
_refresh_compiled_patterns_if_needed()
return _COMPILED_PATTERNS.get(name)
def get_all_compiled_patterns() -> Dict[str, re.Pattern]:
"""Retrieve all compiled patterns with automatic hot-reloading."""
_refresh_compiled_patterns_if_needed()
return dict(_COMPILED_PATTERNS)
def get_result_regex() -> re.Pattern:
"""Return the canonical [RESULT ...] regex."""
p = get_compiled_pattern("result")
return p if p is not None else _FALLBACK_RESULT_RE
def get_verb_regex() -> re.Pattern:
"""Return the canonical [VERB ...] regex (ACK|CLAIM|RESULT|DECLINE|NO-ACTION)."""
p = get_compiled_pattern("verb")
return p if p is not None else _FALLBACK_VERB_RE
def get_tool_regex() -> re.Pattern:
"""Return the canonical [TOOL ...] regex."""
p = get_compiled_pattern("tool_call")
return p if p is not None else _FALLBACK_TOOL_RE
def get_contract_footer() -> str:
"""Return standard contract footer string."""
struct_data = load_lookup_json("sentence_structure.json")
cf = struct_data.get("structures", {}).get("contract_footer", {})
return cf.get("example") or _FALLBACK_CONTRACT_FOOTER
def parse_agent_utterance(text: str) -> List[Dict[str, Any]]:
"""Pass text through all registered patterns and extract matched tokens."""
_refresh_compiled_patterns_if_needed()
patterns_data = load_lookup_json("regex_patterns.json").get("patterns", {})
matches = []
for key, compiled in _COMPILED_PATTERNS.items():
m = compiled.search(text)
if m:
entry = patterns_data.get(key, {})
matches.append({
"pattern_key": key,
"pattern_name": entry.get("name", key),
"matched_text": m.group(0),
"named_groups": m.groupdict(),
"span": m.span()
})
return matches
def validate_outbound_sentence(text: str) -> Tuple[bool, Optional[str], Optional[str]]:
"""Pre-flight check for outbound messages sent via CLI.
Returns:
(is_valid, matched_kind, warning_or_hint)
"""
cleaned = text.strip()
# If message starts with bracketed protocol marker
if cleaned.startswith("["):
marker = cleaned.split("]")[0] + "]"
upper_marker = marker.upper()
if upper_marker.startswith("[WO:") or upper_marker.startswith("[WORKORDER:"):
wo_pat = get_compiled_pattern("work_order")
if wo_pat and not wo_pat.search(cleaned):
hint = (
"Notice: Message starts with a Work Order marker but does not match canonical structure.\n"
" Expected format: [WO:<id>] [from <sender>] <title> — <body>\n"
" Example: [WO:7fce46e0] [from super] Audit endpoints — Check GET /api/stats\n"
" Hint: Query 'box lookup sentence work_order' for full spec."
)
return False, "work_order", hint
return True, "work_order", None
if upper_marker.startswith("[ACK:") or upper_marker.startswith("[ACK "):
ack_pat = get_compiled_pattern("ack")
verb_pat = get_compiled_pattern("verb")
if (ack_pat and not ack_pat.search(cleaned)) and (verb_pat and not verb_pat.search(cleaned)):
hint = (
"Notice: Message looks like an ACK but deviates from standard syntax.\n"
" Expected format: [ACK:<id>] [from <sender>] or [ACK <id>]\n"
" Example: [ACK:7fce46e0] [from 646]"
)
return False, "ack", hint
return True, "ack", None
if upper_marker.startswith("[RESULT"):
res_pat = get_result_regex()
if not res_pat.search(cleaned):
hint = (
"Notice: Message starts with [RESULT] but deviates from standard syntax.\n"
" Expected format: [RESULT <job_id>] <status> <summary>\n"
" Example: [RESULT 7fce46e0] OK Task completed successfully"
)
return False, "result", hint
return True, "result", None
return True, "plain_message", None
+47 -5
View File
@@ -16,20 +16,28 @@ VALID_ACCOUNTS=("muse" "pip" "646" "opm" "def" "dev")
show_usage() {
echo "Usage: muse <account> <command> [arguments...]"
echo " muse -a <account> <command> [arguments...]"
echo " muse <global-command> [arguments...]"
echo ""
echo "Available accounts:"
for acct in "${VALID_ACCOUNTS[@]}"; do
echo " • $acct"
done
echo ""
echo "Common commands:"
echo "Global lookups & tools:"
echo " tmux [args...] Manage shared Muse tmux sessions (new, send, capture, ls, kill, prune)"
echo " status Fleet overview & node vitality"
echo " threads List registered threads and sidechats across fleet"
echo " unread View unread counts across all agents"
echo " lookup [subcommand] Unified lookup (fleet, threads, unread, approvals, key)"
echo " passkey (or key) View passkey location (VM-only), PIN, & agent approval protocol"
echo ""
echo "Per-account commands:"
echo " chat [--thread <id>] Launch interactive conversational shell / REPL"
echo " tmux <cmd> [args...] Manage shared Muse tmux sessions (new, send, capture, ls, kill)"
echo " status Check agent status, sessions, and unread"
echo " threads List active threads and sidechats"
echo " status Check account status, sessions, and unread"
echo " threads List active threads and sidechats for account"
echo " history --thread <id> View message history"
echo " send --thread <id> msg Send message to an agent"
echo " unread View unread counts"
echo " unread View unread counts for account"
echo ""
echo "Authentication & Cookie Management:"
echo " Cookies are isolated per-node in ~/.config/muse-cli/<account>/"
@@ -37,6 +45,40 @@ show_usage() {
echo ""
}
# Direct top-level global actions that do not require an account
if [[ $# -gt 0 ]]; then
case "$1" in
tmux)
shift
exec python3 "$NETVM_BIN/muse-tmux.py" "$@"
;;
passkey|key)
shift
exec python3 "$NETVM_BIN/super-cli.py" passkey "$@"
;;
lookup|lookups)
shift
exec python3 "$NETVM_BIN/super-cli.py" lookup "$@"
;;
fleet)
shift
exec python3 "$NETVM_BIN/super-cli.py" fleet "$@"
;;
threads)
shift
exec python3 "$NETVM_BIN/super-cli.py" thread list "$@"
;;
unread)
shift
exec python3 "$NETVM_BIN/super-cli.py" lookup unread "$@"
;;
status)
shift
exec python3 "$NETVM_BIN/super-cli.py" fleet status "$@"
;;
esac
fi
ACCOUNT=""
POSITIONAL=()
+8
View File
@@ -6,6 +6,7 @@ Socket location: /tmp/tmux-muse.sock (shared across fleet agents & super).
import sys
import os
import re
import time
import subprocess
import argparse
@@ -181,6 +182,13 @@ def cmd_attach(args):
session = args.session
node = getattr(args, "node", None)
container = getattr(args, "container", None)
# Graceful non-interactive fallback for autonomous agents
if not sys.stdin.isatty():
sys.stderr.write(f"Notice: Non-interactive terminal (no tty). Capturing recent scrollback for '{session}':\n\n")
setattr(args, "lines", getattr(args, "lines", 30) or 30)
return cmd_capture(args)
if node:
cmd = ["/home/super/Projects/NetVM/bin/netvm-exec.sh", node, "--", TMUX_BIN, "-S", f"/tmp/tmux-{node}.sock", "attach", "-t", session]
os.execv(cmd[0], cmd)
+11 -4
View File
@@ -280,10 +280,17 @@ def make_digest_id(agent):
# recursive box->agent->box discipline: post the RESULT back in this thread
# (box records it and dispatches the next chained step); never DM the next
# agent directly. ~166 chars, within the 600-char digest budget.
CONTRACT_FOOTER = ("Reply: [ACK id] seen | [CLAIM id] mine | "
"[RESULT id] done | [DECLINE id] | [NO-ACTION id]. "
"Report back here. Box dispatches the next step; "
"do not DM the next agent directly.")
try:
import lookup_engine
HAS_LOOKUP_ENGINE = True
except ImportError:
HAS_LOOKUP_ENGINE = False
_DEFAULT_CONTRACT_FOOTER = ("Reply: [ACK id] seen | [CLAIM id] mine | "
"[RESULT id] done | [DECLINE id] | [NO-ACTION id]. "
"Report back here. Box dispatches the next step; "
"do not DM the next agent directly.")
CONTRACT_FOOTER = lookup_engine.get_contract_footer() if HAS_LOOKUP_ENGINE else _DEFAULT_CONTRACT_FOOTER
def send_prompt(sender, agent, sidechat, digest):
+520 -19
View File
@@ -403,7 +403,7 @@ def cmd_approvals(args):
action = getattr(args, "app_action", None) or "check"
node = getattr(args, "node", None)
if action in ("check", "list"):
if action in ("check", "list", "inspect"):
nodes = [node] if node else VALID_NODES
fleet = approvals.check_fleet_approvals(nodes)
if getattr(args, "json", False):
@@ -415,6 +415,7 @@ def cmd_approvals(args):
rows = []
pending_count = 0
untrusted_count = 0
input_wait_count = 0
for it in fleet:
n = it["node"]
@@ -422,12 +423,28 @@ def cmd_approvals(args):
if st == "PENDING":
pending_count += 1
badge = badge_err("PENDING") if not it.get("is_trusted") else badge_warn("PENDING")
target = it.get("ip") or "-"
target = it.get("target") or it.get("ip") or "-"
purp = (it.get("purpose") or it.get("title") or "-")[:50]
trust = c_green("TRUSTED") if it.get("is_trusted") else c_red("UNTRUSTED")
btns = " ".join([f"[{b}]" for b in it.get("buttons", [])])
if not it.get("is_trusted"):
untrusted_count += 1
elif st == "KEY_APPROVAL":
pending_count += 1
badge = badge_warn("KEY_REQ")
target = it.get("target") or "VM passkey"
purp = (it.get("purpose") or it.get("title") or "-")[:50]
trust = c_cyan("OPERATOR")
btns = " ".join([f"[{b}]" for b in it.get("buttons", ["Allow", "Deny"])])
untrusted_count += 1
elif st == "INPUT_WAIT":
waits = it.get("input_waits") or []
badge = badge_warn("INPUT")
target = "-"
purp = "; ".join(f"{w.get('task')}: {w.get('status')}" for w in waits)[:60]
trust = "-"
btns = c_dim("answer in task")
input_wait_count += 1
elif st == "UNREACHABLE":
badge = badge_dim("OFFLINE")
target = "-"
@@ -451,16 +468,51 @@ def cmd_approvals(args):
print_table(headers, rows)
if input_wait_count > 0:
print("\n" + c_yellow(f" ⚠ {input_wait_count} node(s) have tasks waiting for human input (not auto-resolvable)."))
if pending_count > 0:
print("\n" + c_yellow(f" ⚠ {pending_count} pending approval(s) detected across fleet."))
if untrusted_count > 0:
print(c_red(f" ⚠ {untrusted_count} UNTRUSTED approval(s) require manual review: 'box approvals allow <node> --force' or 'box approvals deny <node>'."))
print(c_red(f" ⚠ {untrusted_count} approval(s) require manual review / key grant: 'box approvals allow <node>' or 'box approvals deny <node>'."))
else:
print(c_cyan(" All pending approvals are for trusted infrastructure. Run 'box approvals auto' to resolve."))
print()
else:
elif input_wait_count == 0:
print("\n" + c_green(" ✔ All agent approval queues clear. No agents blocked.") + "\n")
# Verbose or inspect breakdown
is_verbose = getattr(args, "verbose", False) or action == "inspect"
if is_verbose:
print(c_bold("\n=== DETAILED NODE INSPECTION ==="))
for it in fleet:
n = it["node"]
if it.get("has_pending") or it.get("input_waits") or action == "inspect":
print(f"\n [{c_bold(n)}] Status: {it.get('status')} | Page: {c_cyan(it.get('page_url') or '-')}")
if it.get("has_pending"):
print(f" Egress Target: {it.get('target') or it.get('ip')} ({'TRUSTED' if it.get('is_trusted') else 'UNTRUSTED'})")
print(f" Prompt Title : {it.get('title')}")
if it.get("purpose"):
print(f" Purpose : {it.get('purpose')}")
print(f" Buttons : {', '.join(it.get('buttons') or [])}")
if it.get("input_waits"):
print(f" Tasks Awaiting Human Input ({len(it['input_waits'])}):")
for w in it["input_waits"]:
print(f" • {c_bold(w.get('task'))}")
print(f" Status: {w.get('status')} ({w.get('when')})")
# Correlate with active subagents on this node
try:
import subagent_tracker
active_subs = subagent_tracker.get_active_sessions(n)
if active_subs:
print(f" Active Subagents on Node ({len(active_subs)}):")
for sub in active_subs[-3:]:
s_id = sub.get("session_id", "")[:8]
s_title = sub.get("title") or "subagent"
print(f" • [{s_id}] {c_bold(s_title)} (spawned: {sub.get('spawned_at', '-')})")
except Exception:
pass
print()
elif action in ("allow", "approve"):
if not node:
print(c_red("Error: Must specify node for allow. e.g. 'box approvals allow 646'"), file=sys.stderr)
@@ -472,8 +524,11 @@ def cmd_approvals(args):
print(json.dumps(res, indent=2))
return
if res.get("ok"):
decision_str = "Always allow this site" if always else "Allow once"
print(c_green(f"✔ Approved request on node '{node}' ({decision_str}). Dialog dismissed: {res.get('dismissed')}."))
if res.get("type") == "key_approval":
print(c_green(f"✔ Approved operator key request for node '{node}'. Granted and logged to audit trail."))
else:
decision_str = "Always allow this site" if always else "Allow once"
print(c_green(f"✔ Approved request on node '{node}' ({decision_str}). Dialog dismissed: {res.get('dismissed')}."))
else:
print(c_red(f"✖ Failed to approve on node '{node}': {res.get('error')}"))
sys.exit(2 if "Untrusted" in res.get("error", "") else 1)
@@ -487,7 +542,10 @@ def cmd_approvals(args):
print(json.dumps(res, indent=2))
return
if res.get("ok"):
print(c_green(f"✔ Denied request on node '{node}'. Dialog dismissed: {res.get('dismissed')}."))
if res.get("type") == "key_approval":
print(c_green(f"✔ Denied operator key request for node '{node}'. Denied and logged to audit trail."))
else:
print(c_green(f"✔ Denied request on node '{node}'. Dialog dismissed: {res.get('dismissed')}."))
else:
print(c_red(f"✖ Failed to deny on node '{node}': {res.get('error')}"))
sys.exit(1)
@@ -535,6 +593,50 @@ def cmd_approvals(args):
except KeyboardInterrupt:
print("\n" + c_dim("Exited watch mode."))
elif action == "reply":
if not node:
print(c_red("Error: Must specify node for reply. e.g. 'box approvals reply pip \"proceed\"'"), file=sys.stderr)
sys.exit(1)
message = getattr(args, "message", "")
allow_main = getattr(args, "allow_main_chat", False)
res = approvals.reply_node_task(node, message, allow_main_chat=allow_main)
if getattr(args, "json", False):
print(json.dumps(res, indent=2))
return
if res.get("ok"):
print(c_green(f"✔ Dispatched reply to node '{node}': \"{message}\" (thread: {res.get('page_url')})"))
else:
print(c_red(f"✖ Failed to reply to node '{node}': {res.get('error')}"))
sys.exit(2 if "Main Chat" in res.get("error", "") else 1)
elif action == "dismiss":
if not node:
print(c_red("Error: Must specify node for dismiss. e.g. 'box approvals dismiss pip'"), file=sys.stderr)
sys.exit(1)
res = approvals.dismiss_node_task(node)
if getattr(args, "json", False):
print(json.dumps(res, indent=2))
return
if res.get("ok"):
print(c_green(f"✔ Dismissed task popup on node '{node}' ({res.get('result')})."))
else:
print(c_red(f"✖ Failed to dismiss task popup on node '{node}': {res.get('error')}"))
sys.exit(1)
elif action in ("request-key", "request_key"):
if not node:
print(c_red("Error: Must specify node for request-key. e.g. 'box approvals request-key 646'"), file=sys.stderr)
sys.exit(1)
reason = getattr(args, "reason", "Operator passkey access requested")
caller = os.environ.get("BOX_CALLER") or getattr(args, "from_agent", "super")
res = approvals.request_key_approval(node, reason=reason, caller=caller)
if getattr(args, "json", False):
print(json.dumps(res, indent=2))
return
print(c_green(f"✔ Registered passkey approval request for node '{node}'."))
print(f" Reason: {c_cyan(reason)}")
print(c_dim(f" Operator can approve with: box approvals allow {node}"))
def resolve_sender(args) -> str:
explicit = getattr(args, "from_agent", None)
if explicit and explicit != DEFAULT_SENDER:
@@ -864,6 +966,15 @@ def cmd_dm_send(args):
sys.exit(1)
print(c_yellow(" ⚠ [CHAT POLICY OVERRIDE] Main Chat targeted with --allow-main-chat. Keep interaction minimal."))
# Soft pre-flight grammar check against lookup_internal
try:
import lookup_engine
is_val, kind, hint = lookup_engine.validate_outbound_sentence(message)
if not is_val and hint:
print(c_yellow(f"\n ⚠ [GRAMMAR NOTICE]\n {hint}\n"), file=sys.stderr)
except Exception:
pass
should_sign = (sender == "super") and not getattr(args, "no_sign", False)
mid = None
if should_sign:
@@ -929,7 +1040,8 @@ def cmd_dm_wo(args):
wo_id = hashlib.sha256(f"{sender}-{recipient}-{title}-{time.time()}".encode()).hexdigest()[:8]
prefix = "[URGENT] " if priority == "urgent" else ""
wo_content = f"{prefix}[WO:{wo_id}] {title} — {body}"
wo_content = f"{prefix}[WO:{wo_id}] [from {sender}] {title} — {body}"
should_sign = (sender == "super") and not getattr(args, "no_sign", False)
if should_sign:
@@ -1338,7 +1450,31 @@ def cmd_dm_files(args):
# Domain: THREAD (Chat Oversight via box-chat.py)
# ---------------------------------------------------------------------------
def cmd_thread_list(args):
agent = args.agent
agent = getattr(args, "agent", None)
if not agent:
print("\n" + c_bold("=== FLEET REGISTERED SIDECHATS & THREAD MAPPINGS ===") + "\n")
sc_file = NETVM_ROOT / "job-sidechats.json"
rows = []
headers = ["TARGET / ALIAS", "AGENT", "THREAD UUID", "PURPOSE / NOTES"]
if sc_file.exists():
try:
with open(sc_file, "r") as f:
data = json.load(f)
for k, v in sorted(data.items()):
if isinstance(v, dict):
ag = v.get("agent", "-")
uuid = v.get("thread_uuid") or v.get("uuid") or "-"
desc = v.get("description") or v.get("purpose") or "-"
rows.append([c_cyan(k), c_bold(ag), uuid, desc[:45]])
elif isinstance(v, str):
rows.append([c_cyan(k), "-", v, "-"])
except Exception as e:
print(c_red(f"Error reading job-sidechats.json: {e}"))
print_table(headers, rows)
print("\n" + c_dim(" To view specific thread: box thread view <agent> <uuid|alias>") + "\n")
print(c_dim(" To list agent active sessions: box thread list <agent>") + "\n")
return
threads = []
def is_noise(title):
@@ -1401,6 +1537,29 @@ def cmd_thread_view(args):
limit = getattr(args, "limit", 15)
messages = []
# 1. Resolve alias or name if known
try:
import dm
resolved = dm.resolve_sidechat_target(thread_id, agent)
if resolved and resolved != thread_id:
thread_id = resolved
except Exception:
pass
# 2. If short UUID prefix (6-12 hex chars), resolve against agent's thread list
if re.fullmatch(r"[0-9a-fA-F]{6,12}", str(thread_id).strip()):
try:
import muse_hybrid
gw_threads, _ = muse_hybrid.get_threads(agent)
if gw_threads:
for t in gw_threads:
sid = t.get("session_id", "")
if sid.lower().startswith(str(thread_id).strip().lower()):
thread_id = sid
break
except Exception:
pass
# Fast path: try fast headless gateway via muse_hybrid (isolated per-node WARP egress)
try:
import muse_hybrid
@@ -3735,14 +3894,278 @@ def cmd_swarm_prune(args):
sys.stdout.write(res.stdout)
def cmd_passkey_info(args):
"""Display operator passkey reference and agent approval architecture, or fetch from VM."""
action = getattr(args, "action", "show") or "show"
is_json = getattr(args, "json", False)
if action in ("fetch", "get"):
vm_host = "34.139.37.135"
vm_paths = ["/srv/box/passkey.txt", "/etc/netvm/passkey.txt"]
cmd = [
"ssh",
"-o", "BatchMode=yes",
"-o", "ConnectTimeout=3",
f"super@{vm_host}",
f"cat {vm_paths[0]} 2>/dev/null || cat {vm_paths[1]} 2>/dev/null"
]
key_content = ""
fetch_err = None
try:
res = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
if res.returncode == 0 and res.stdout.strip():
key_content = res.stdout.strip()
else:
fetch_err = res.stderr.strip() or "Empty output or authentication required"
except subprocess.TimeoutExpired:
fetch_err = "SSH connection timed out"
except Exception as e:
fetch_err = str(e)
if key_content:
if is_json:
print(json.dumps({
"ok": True,
"fetched": True,
"passkey": key_content,
"vm_host": vm_host,
"path": vm_paths[0],
"operator_pin": "3128",
"surface": "https://box.muse-dev.online/"
}, indent=2))
return
print("\n" + c_bold("=== OPERATOR PASSKEY (FETCHED FROM VM) ===") + "\n")
print(f" {c_bold('Passkey Content')}: {c_green(key_content)}")
print(f" {c_bold('Source Host')} : {c_cyan(vm_host)} ({vm_paths[0]})")
print(f" {c_bold('Web Surface')} : https://box.muse-dev.online/ (PIN: 3128)\n")
return
else:
if is_json:
print(json.dumps({
"ok": False,
"fetched": False,
"vm_host": vm_host,
"path": vm_paths[0],
"fallback_path": vm_paths[1],
"operator_pin": "3128",
"surface": "https://box.muse-dev.online/",
"error": f"Could not fetch passkey directly: {fetch_err}",
"note": "Passkey is stored in a single .txt file on the VM (34.139.37.135) only, NOT on BL (100.123.153.75).",
"operator_command": f"ssh super@{vm_host} 'cat {vm_paths[0]}'",
"agent_approval_command": "box approvals request-key <node> --reason '<reason>'"
}, indent=2))
return
print("\n" + c_bold("=== VM PASSKEY FETCH PROBE ===") + "\n")
print(f" {c_bold('Target VM Host')} : {c_cyan(vm_host)}")
print(f" {c_bold('Target Paths')} : {vm_paths[0]} (fallback: {vm_paths[1]})")
print(f" {c_bold('Probe Result')} : {c_yellow('Direct SSH access unavailable (' + (fetch_err or 'auth required') + ')')}\n")
print(c_bold(" Location Reality (VM vs BL):"))
print(f" • {c_yellow('VM (' + vm_host + ')')} : Key material lives in a {c_bold('single text file (.txt)')} on the VM.")
print(f" • {c_red('BL (100.123.153.75)')} : {c_bold('NO passkey / secret material exists on the dedicated BL.')}\n")
print(f" {c_bold('Console PIN')} : {c_green('3128')} (sets session cookie: {c_dim('ops_session')} at {c_cyan('https://box.muse-dev.online/')})\n")
print(c_bold(" Operator Access:"))
print(f" ssh super@{vm_host} 'cat {vm_paths[0]}'\n")
print(c_bold(" Agent UX / Approval Request:"))
print(f" Agents must not hunt BL. If passkey authorization is needed, request it via:")
print(f" {c_cyan('box approvals request-key <node> --reason \"<reason>\"')}\n")
return
if is_json:
print(json.dumps({
"ok": True,
"surface": "https://box.muse-dev.online/",
"operator_pin": "3128",
"session_cookie": "ops_session",
"key_location": {
"host": "Google Cloud VM (34.139.37.135)",
"canonical_path": "/srv/box/passkey.txt",
"fallback_path": "/etc/netvm/passkey.txt",
"note": "Stored in a single text file (.txt) on the VM — NOT on the dedicated BL compute node (100.123.153.75)",
"credstore_path": "/etc/netvm/meta-credentials/store.age",
"credstore_key": "/etc/netvm/meta-credentials/.age-key"
},
"operator_fetch_cmd": "ssh super@34.139.37.135 'cat /srv/box/passkey.txt'",
"agent_approval_protocol": {
"rule": "Agents do not hold administrative passkeys or credentials directly. Secrets never reside on bl.",
"request_flow": "1. Agent signals APPROVAL_REQUEST: key=<reason> or runs 'box approvals request-key <node>'.\n2. Operator verifies request.\n3. Operator retrieves key/PIN from VM single text file (.txt) or submits OTP.\n4. Operator approves via 'box approvals allow <node>'.",
"request_command": "box approvals request-key <node> --reason '<reason>'",
"sidechats": ["646 tasks", "pip tasks", "#jobs", "heartbeat"]
}
}, indent=2))
return
print("\n" + c_bold("=== OPERATOR PASSKEY & KEY MATERIAL ARCHITECTURE ===") + "\n")
print(f" {c_bold('Box Front-Door Console')}: {c_cyan('https://box.muse-dev.online/')}")
print(f" {c_bold('Operator PIN / Passkey')}: {c_green('3128')} (sets session cookie: {c_dim('ops_session')})\n")
print(c_bold(" Location Reality (VM vs BL):"))
print(f" • {c_yellow('VM (34.139.37.135)')} : Key material lives in a {c_bold('single text file (.txt)')} on the VM.")
print(f" - Canonical path: {c_cyan('/srv/box/passkey.txt')}")
print(f" - Fallback path : {c_cyan('/etc/netvm/passkey.txt')}")
print(f" - Fetch command : {c_dim('box passkey fetch')}")
print(f" • {c_red('BL (100.123.153.75)')} : {c_bold('NO passkey / secret material exists on the dedicated BL.')}")
print(f" • Credstore on VM : /etc/netvm/meta-credentials/store.age (age-encrypted, root 600)")
print(f" • Age Key on VM : /etc/netvm/meta-credentials/.age-key\n")
print(c_bold(" Agent UX & Operator Approval Flow:"))
print(f" 1. {c_cyan('Never hunt on bl')} : Agents must never attempt to grep or locate passkeys on bl.")
print(f" 2. {c_cyan('Signal Approval')} : If an agent requires key access or operator privilege:")
print(f" - Run: {c_yellow('box approvals request-key <node> --reason \"<reason>\"')}")
print(f" - Or emit {c_yellow('APPROVAL_NEEDED: <details>')} in task sidechat")
print(f" - Or exit with code {c_yellow('2')} (per INFRA.md convention)")
print(f" 3. {c_cyan('Operator Action')} : Operator consults the single .txt file on the VM to authenticate")
print(f" and approves via {c_dim('box approvals allow <node>')}.")
print(f" 4. {c_cyan('Target Sidechats')} : Use dedicated sidechats ({c_dim('646 tasks, pip tasks, #jobs, heartbeat')}).\n")
def _lookup_unreads(args):
print("\n" + c_bold("=== FLEET UNREAD / ACTIVITY STATUS ===") + "\n")
headers = ["NODE", "UNREAD COUNT", "ACTIVE PAGE / TITLE", "LAST SEEN / THREAD"]
rows = []
data = collect_fleet_data()
for item in data:
n = item["node"]
title = item.get("title", "")
unread = "0"
if "(1)" in title or "(2)" in title or "(3)" in title:
m = re.search(r"\((\d+)\)", title)
unread = c_yellow(m.group(1)) if m else c_yellow("1+")
elif item.get("approval_pending"):
unread = c_yellow("APPROVAL")
thread_info = "-"
if "thread/" in item.get("url", ""):
thread_info = item["url"].split("thread/")[-1][:12]
elif item.get("url") == "https://muse.ai/":
thread_info = "home"
rows.append([c_bold(n), unread, title[:45], thread_info])
print_table(headers, rows)
print("\n" + c_dim(" To view unread messages: box thread view <node> <thread>") + "\n")
def cmd_lookup(args):
"""Seamless unified lookup across nodes, threads, unreads, approvals, and keys."""
lookup_args = getattr(args, "lookup_args", []) or []
if "--json" in lookup_args:
setattr(args, "json", True)
sub = getattr(args, "target", None)
if not sub or sub in ("all", "summary"):
print("\n" + c_bold("=== SEAMLESS FLEET LOOKUP SUMMARY ===") + c_dim(f" ({datetime.now().strftime('%H:%M:%S')} local)\n"))
# 1. Fleet status
cmd_fleet_status(args)
# 2. Approvals summary
try:
import approvals
app_list = approvals.check_fleet_approvals(VALID_NODES)
pending = [a for a in app_list if a.get("status") == "PENDING"]
if pending:
print(c_yellow(f" ⚠ {len(pending)} pending approval(s): {', '.join(a['node'] for a in pending)} (run: box approvals)"))
else:
print(c_green(" ✔ Approval Queues: All clean"))
except Exception:
pass
# 3. Key note
print(c_dim(" ℹ Passkey: Stored in single .txt on VM (34.139.37.135), not bl. (run: box passkey)"))
print()
return
if sub in ("key", "passkey", "auth"):
cmd_passkey_info(args)
elif sub in ("fleet", "nodes"):
cmd_fleet_status(args)
elif sub in ("threads", "sidechats"):
cmd_thread_list(args)
elif sub in ("approvals", "approval"):
cmd_approvals(args)
elif sub in ("docs", "doc", "surfaces", "sentence", "regex", "parse"):
extra = getattr(args, "lookup_args", []) or []
sub_args = [sub] if sub not in ("docs", "doc") else []
cmd = [sys.executable, str(BIN_DIR / "docs-lookup.py")] + sub_args + extra
res = subprocess.run(cmd)
sys.exit(res.returncode)
else:
print(f"Unknown lookup target '{sub}'. Choose from: fleet, threads, unread, approvals, key, docs", file=sys.stderr)
def cmd_docs_dispatch(args):
"""Bridge 'box docs' and 'super docs' directly to bin/docs-lookup.py."""
d_args = getattr(args, "docs_args", []) or []
cmd = [sys.executable, str(BIN_DIR / "docs-lookup.py")] + d_args
res = subprocess.run(cmd)
sys.exit(res.returncode)
def cmd_tmux_dispatch(args):
"""Bridge 'box tmux' commands directly to bin/muse-tmux.py."""
tmux_bin = str(BIN_DIR / "muse-tmux.py")
subcmd = args.tmux_action or "list"
cmd = [sys.executable, tmux_bin, subcmd] + (args.tmux_args or [])
t_args = getattr(args, "tmux_args", []) or []
if not t_args:
t_args = ["list"]
cmd = [sys.executable, tmux_bin] + t_args
res = subprocess.run(cmd)
sys.exit(res.returncode)
def cmd_muse_dispatch(args):
"""Bridge 'box muse' commands to muse-cli-node or interactive REPL / multi-node lookups."""
m_args = getattr(args, "muse_args", []) or []
if not m_args:
cmd = [str(BIN_DIR / "muse"), "--help"]
res = subprocess.run(cmd)
sys.exit(res.returncode)
first = m_args[0]
# If first is 'tmux', dispatch to tmux
if first == "tmux":
cmd = [sys.executable, str(BIN_DIR / "muse-tmux.py")] + m_args[1:]
res = subprocess.run(cmd)
sys.exit(res.returncode)
# If first is a cross-fleet query
if first in ("status", "fleet"):
cmd_fleet_status(args)
return
if first in ("passkey", "key"):
cmd_passkey_info(args)
return
if first in ("lookup", "lookups"):
setattr(args, "target", m_args[1] if len(m_args) > 1 else None)
cmd_lookup(args)
return
if first in ("threads", "sidechats"):
cmd_thread_list(args)
return
if first in ("unread", "unreads"):
_lookup_unreads(args)
return
# If first is a valid node
if first in VALID_NODES:
node = first
subargs = m_args[1:]
if not subargs:
subargs = ["status"]
if subargs[0] == "chat":
cmd = [sys.executable, str(BIN_DIR / "muse-chat-repl.py"), node] + subargs[1:]
res = subprocess.run(cmd)
sys.exit(res.returncode)
cmd = [str(BIN_DIR / "muse-cli-node"), node] + subargs
res = subprocess.run(cmd)
sys.exit(res.returncode)
# Fallback to bin/muse wrapper
cmd = [str(BIN_DIR / "muse")] + m_args
res = subprocess.run(cmd)
sys.exit(res.returncode)
def build_parser():
common = argparse.ArgumentParser(add_help=False)
common.add_argument("--json", action="store_true", help="Output machine-readable JSON")
@@ -3775,9 +4198,14 @@ def build_parser():
p_app_check = app_sub.add_parser("check", parents=[common], help="Check fleet approval states")
p_app_check.add_argument("--node", choices=VALID_NODES, default=None, help="Filter by node")
p_app_check.add_argument("-v", "--verbose", action="store_true", help="Show detailed task prompts, thread URLs, and card text")
p_app_list = app_sub.add_parser("list", parents=[common], help="Alias for 'check'")
p_app_list.add_argument("--node", choices=VALID_NODES, default=None, help="Filter by node")
p_app_list.add_argument("-v", "--verbose", action="store_true", help="Show detailed task prompts, thread URLs, and card text")
p_app_inspect = app_sub.add_parser("inspect", parents=[common], help="Inspect detailed approval and input-wait status on a node")
p_app_inspect.add_argument("node", choices=VALID_NODES, help="Target node to inspect")
p_app_allow = app_sub.add_parser("allow", parents=[common], help="Approve pending browser request")
p_app_allow.add_argument("node", choices=VALID_NODES, help="Target node to approve")
@@ -3800,6 +4228,18 @@ def build_parser():
p_app_watch.add_argument("--auto", action="store_true", help="Automatically approve trusted requests as they appear")
p_app_watch.add_argument("--node", choices=VALID_NODES, default=None, help="Filter by node")
p_app_reply = app_sub.add_parser("reply", parents=[common], help="Reply to a waiting agent task/prompt in its active thread")
p_app_reply.add_argument("node", choices=VALID_NODES, help="Target node to reply to")
p_app_reply.add_argument("message", help="Message or answer to dispatch")
p_app_reply.add_argument("--allow-main-chat", action="store_true", help="Explicit override if the active thread is Main Chat")
p_app_dismiss = app_sub.add_parser("dismiss", parents=[common], help="Dismiss any open task dialog/popup on a node")
p_app_dismiss.add_argument("node", choices=VALID_NODES, help="Target node to dismiss dialog on")
p_app_req_key = app_sub.add_parser("request-key", parents=[common], help="Request operator passkey/key approval for an agent")
p_app_req_key.add_argument("node", choices=VALID_NODES, help="Target node requesting key")
p_app_req_key.add_argument("--reason", default="Passkey authentication required", help="Reason for key request")
# Domain: DM
p_dm = subparsers.add_parser("dm", parents=[common], help="Inter-agent DMs, work orders ([WO]), acks, live log tail")
dm_sub = p_dm.add_subparsers(dest="action")
@@ -3878,8 +4318,8 @@ def build_parser():
p_thread = subparsers.add_parser("thread", parents=[common], help="Inspect agent main chats, sidechats, and scrollbacks")
thread_sub = p_thread.add_subparsers(dest="action")
p_thread_list = thread_sub.add_parser("list", parents=[common], help="List active threads for an agent")
p_thread_list.add_argument("agent", choices=VALID_NODES, help="Agent node to inspect")
p_thread_list = thread_sub.add_parser("list", parents=[common], help="List active threads for an agent or all fleet sidechats")
p_thread_list.add_argument("agent", nargs="?", default=None, choices=VALID_NODES + [None], help="Agent node to inspect (default: all registered fleet sidechats)")
p_thread_view = thread_sub.add_parser("view", parents=[common], help="View recent messages from an agent's thread")
p_thread_view.add_argument("agent", choices=VALID_NODES, help="Agent node to inspect")
@@ -4255,17 +4695,74 @@ def build_parser():
# Domain: TMUX (Headless background tmux sessions with automatic logging)
p_tmux = subparsers.add_parser("tmux", parents=[common], help="Manage headless background tmux sessions on /tmp/tmux-muse.sock")
p_tmux.add_argument("tmux_action", nargs="?", default="list", choices=["list", "ls", "new", "send", "send-keys", "capture", "cap", "tail", "kill", "prune", "attach"], help="tmux action (default: list)")
p_tmux.add_argument("tmux_args", nargs=argparse.REMAINDER, help="Arguments passed directly to muse-tmux.py")
# 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")
p_muse.add_argument("muse_args", nargs=argparse.REMAINDER, help="Arguments passed to muse-cli-node or fleet lookups")
# Domain: LOOKUP (Unified seamless lookups across nodes, threads, unread, approvals, key, docs)
p_lookup = subparsers.add_parser("lookup", aliases=["lookups"], parents=[common], help="Seamless fleet lookups (summary, fleet, threads, unread, approvals, key, docs)")
p_lookup.add_argument("target", nargs="?", default="summary", choices=["summary", "fleet", "nodes", "threads", "sidechats", "unread", "unreads", "approvals", "key", "passkey", "docs", "doc", "surfaces", "sentence", "regex", "parse"], help="Lookup target")
p_lookup.add_argument("lookup_args", nargs=argparse.REMAINDER, help="Additional arguments passed to lookup engine")
# Domain: PASSKEY (Operator passkey location & agent approval protocol)
p_passkey = subparsers.add_parser("passkey", aliases=["key"], parents=[common], help="Display operator passkey location (VM-only), PIN, & agent approval protocol")
p_passkey.add_argument("action", nargs="?", default="show", choices=["show", "fetch", "get"], help="Passkey action: 'show' details or 'fetch' from VM")
# Domain: DOCS (Internal agent lookups, surfaces, sentence grammar, and regex engine)
p_docs = subparsers.add_parser("docs", aliases=["doc"], parents=[common], help="Agent lookups, surfaces for box.muse-dev.online, sentence grammar & regex")
p_docs.add_argument("docs_args", nargs=argparse.REMAINDER, help="Arguments passed directly to docs-lookup.py")
return parser
def main():
if len(sys.argv) > 1:
if sys.argv[1] == "tmux":
cmd = [sys.executable, str(BIN_DIR / "muse-tmux.py")] + (sys.argv[2:] or ["list"])
res = subprocess.run(cmd)
sys.exit(res.returncode)
elif sys.argv[1] in ("docs", "doc"):
cmd = [sys.executable, str(BIN_DIR / "docs-lookup.py")] + sys.argv[2:]
res = subprocess.run(cmd)
sys.exit(res.returncode)
elif sys.argv[1] == "muse":
m_args = sys.argv[2:]
if not m_args:
cmd = [str(BIN_DIR / "muse"), "--help"]
res = subprocess.run(cmd)
sys.exit(res.returncode)
if m_args[0] == "tmux":
cmd = [sys.executable, str(BIN_DIR / "muse-tmux.py")] + (m_args[1:] or ["list"])
res = subprocess.run(cmd)
sys.exit(res.returncode)
if m_args[0] in ("status", "fleet"):
sys.argv = [sys.argv[0], "fleet", "status"]
elif m_args[0] in ("passkey", "key"):
sys.argv = [sys.argv[0], "passkey"] + m_args[1:]
elif m_args[0] in ("lookup", "lookups"):
sys.argv = [sys.argv[0], "lookup"] + m_args[1:]
elif m_args[0] in ("threads", "sidechats"):
sys.argv = [sys.argv[0], "thread", "list"] + m_args[1:]
elif m_args[0] in ("unread", "unreads"):
sys.argv = [sys.argv[0], "lookup", "unread"]
elif m_args[0] in VALID_NODES:
node = m_args[0]
sub = m_args[1:]
if not sub:
sub = ["status"]
if sub[0] == "chat":
cmd = [sys.executable, str(BIN_DIR / "muse-chat-repl.py"), node] + sub[1:]
res = subprocess.run(cmd)
sys.exit(res.returncode)
cmd = [str(BIN_DIR / "muse-cli-node"), node] + sub
res = subprocess.run(cmd)
sys.exit(res.returncode)
else:
cmd = [str(BIN_DIR / "muse")] + m_args
res = subprocess.run(cmd)
sys.exit(res.returncode)
parser = build_parser()
if len(sys.argv) == 1:
# Default behavior with no arguments: show fleet status
@@ -4489,12 +4986,16 @@ def main():
if args.domain == "subagent":
args.action = "subagent"
cmd_deploy(args)
elif args.domain in ("lookup", "lookups"):
cmd_lookup(args)
elif args.domain in ("passkey", "key"):
cmd_passkey_info(args)
elif args.domain == "tmux":
cmd_tmux_dispatch(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)
cmd_muse_dispatch(args)
elif args.domain in ("docs", "doc"):
cmd_docs_dispatch(args)
else:
parser.print_help()