feat(operators): agent markdown drive management via Hatch and SSH runbook
This commit is contained in:
@@ -3110,6 +3110,246 @@ def cmd_ssh_show(args):
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_ssh_ports(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "ssh-ports"]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
tunnels = d.get("tunnels", {})
|
||||
jump = d.get("jump_host", "34.139.37.135")
|
||||
print("\n" + c_bold(f"=== CONTAINER SSH & REVERSE TUNNEL REGISTRY (JUMP: {jump}) ===") + "\n")
|
||||
headers = ["AGENT", "SSH PORT", "TERM PORT", "USER", "DIAL-IN COMMAND"]
|
||||
rows = []
|
||||
for name, info in tunnels.items():
|
||||
port = info.get("port")
|
||||
tport = info.get("terminal")
|
||||
u = info.get("user", "hatch")
|
||||
dial = f"ssh -J super@{jump} -p {port} {u}@localhost"
|
||||
rows.append([c_cyan(name), str(port), str(tport), u, c_yellow(dial)])
|
||||
print_table(headers, rows)
|
||||
print("\n" + c_dim(" To execute remote cmd: ssh -J super@<jump> -p <port> hatch@localhost '<cmd>'") + "\n")
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_ssh_info(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "ssh-info", args.name]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
name = d.get("account", args.name)
|
||||
port = d.get("port")
|
||||
u = d.get("container_user", "hatch")
|
||||
jump = d.get("jump_host", "34.139.37.135")
|
||||
print("\n" + c_bold(f"=== SSH DIAL-IN FOR AGENT: {name} ===") + "\n")
|
||||
print(f" Container User: {c_cyan(u)}")
|
||||
print(f" Reverse SSH Port:{c_yellow(str(port))}")
|
||||
print(f" GCP Jump Host: {jump}")
|
||||
print(f" From VM directly: {c_green(d.get('direct_from_vm', ''))}")
|
||||
print(f" Via Jump Host: {c_green(d.get('jump_command', ''))}")
|
||||
print(f"\n Modify .md via SSH:")
|
||||
print(f" {c_dim(d.get('cat_example', ''))}\n")
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_md_audit(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "md-audit"] + (args.accounts or [])
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
agents = d.get("agents", {})
|
||||
print("\n" + c_bold(f"=== MUSE AGENT .MD & OPERATIONAL DRIVE AUDIT ({len(agents)} AGENTS) ===") + "\n")
|
||||
for acct, info in agents.items():
|
||||
if not info.get("connected"):
|
||||
print(c_red(f"[{acct.upper()}] ✗ Connection failed: {info.get('error')}"))
|
||||
continue
|
||||
score = info.get("drive_score", 0)
|
||||
score_str = c_green(f"{score}/100 [HIGH DRIVE]") if score >= 75 else (c_yellow(f"{score}/100 [PARTIAL]") if score >= 50 else c_red(f"{score}/100 [LOW/STALE]"))
|
||||
vm = info.get("vm_id", "unknown")
|
||||
print(f"[{c_bold(acct.upper())}] Drive: {score_str} VM: {c_dim(vm)}")
|
||||
headers = ["FILE", "STATUS", "SIZE", "MODIFIED"]
|
||||
rows = []
|
||||
for fname, finfo in info.get("files", {}).items():
|
||||
exists = finfo.get("exists")
|
||||
st = c_green("✓ present") if exists else c_red("✗ missing")
|
||||
sz = f"{finfo.get('size', 0)} B"
|
||||
mod = (finfo.get("modified") or "-")[:19]
|
||||
rows.append([fname, st, sz, mod])
|
||||
print_table(headers, rows)
|
||||
issues = info.get("issues", [])
|
||||
if issues:
|
||||
print(c_dim(" Issues / Gaps:"))
|
||||
for iss in issues:
|
||||
print(c_yellow(f" • {iss}"))
|
||||
print()
|
||||
print(c_dim(" Fix agent drive: box md inject-drive <agent> | box md sync-all") + "\n")
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_md_list(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "md-list", args.account, args.path]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
entries = d.get("entries", [])
|
||||
print("\n" + c_bold(f"=== FILES IN {args.account}:{args.path or '/'} ({len(entries)}) ===") + "\n")
|
||||
headers = ["NAME", "TYPE", "SIZE", "MODIFIED"]
|
||||
rows = []
|
||||
for e in entries:
|
||||
t = e.get("type", "file")
|
||||
name_colored = c_cyan(e.get("name")) if t == "directory" else e.get("name")
|
||||
rows.append([name_colored, t, str(e.get("size", "-")), (e.get("modifiedAt") or "-")[:19]])
|
||||
print_table(headers, rows)
|
||||
print()
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_md_read(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "md-read", args.account, args.filename]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
text = d.get("text", "")
|
||||
print(f"\n{c_bold('--- ' + args.account + ':' + args.filename + ' (' + str(len(text)) + ' chars) ---')}\n")
|
||||
print(text)
|
||||
print()
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_md_write(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "md-write", args.account, args.filename]
|
||||
if args.file:
|
||||
cmd.extend(["--file", args.file])
|
||||
elif args.content:
|
||||
cmd.extend(["--content", args.content])
|
||||
else:
|
||||
print(c_red("Error: specify --content or --file"))
|
||||
return
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
print(c_green(f"✓ Wrote {d.get('bytes_written')} bytes to {args.account}:{args.filename} via Hatch"))
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_md_diff(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "md-diff", args.account, args.filename]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
if d.get("identical"):
|
||||
print(c_green(f"✓ {args.account}:{args.filename} matches local shared/operators/{args.filename} exactly."))
|
||||
else:
|
||||
print(f"\n{c_bold('=== DIFF: ' + args.account + ':' + args.filename + ' vs shared/operators/' + args.filename + ' ===')}\n")
|
||||
diff = d.get("diff", "")
|
||||
for line in diff.splitlines():
|
||||
if line.startswith("+"):
|
||||
print(c_green(line))
|
||||
elif line.startswith("-"):
|
||||
print(c_red(line))
|
||||
elif line.startswith("@@"):
|
||||
print(c_cyan(line))
|
||||
else:
|
||||
print(line)
|
||||
print()
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_md_inject_drive(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "md-inject-drive", args.account]
|
||||
if args.force:
|
||||
cmd.append("--force")
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
print("\n" + c_bold(f"=== INJECTED OPERATIONAL DRIVE INTO AGENT: {args.account.upper()} ===") + "\n")
|
||||
for u in d.get("updates", []):
|
||||
print(c_green(f" ✓ Injected {u.get('file'):26} ({u.get('bytes')} bytes)"))
|
||||
print(f"\n{c_green('✓ Successfully activated SOUL.md, PROACTIVE_PREFERENCES.md, and HEARTBEAT.md!')}\n")
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_md_sync_all(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "md-sync-all"]
|
||||
if args.force:
|
||||
cmd.append("--force")
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if args.json:
|
||||
sys.stdout.write(res.stdout)
|
||||
return
|
||||
try:
|
||||
d = json.loads(res.stdout)
|
||||
if d.get("ok"):
|
||||
print("\n" + c_bold("=== FLEET-WIDE OPERATIONAL DRIVE INJECTION ===") + "\n")
|
||||
results = d.get("results", {})
|
||||
for acct, r in results.items():
|
||||
if r.get("ok"):
|
||||
files_str = ", ".join(u.get("file") for u in r.get("updates", []))
|
||||
print(c_green(f" ✓ {acct.upper():6} drive injected ({files_str})"))
|
||||
else:
|
||||
print(c_red(f" ✗ {acct.upper():6} failed: {r.get('error')}"))
|
||||
print(f"\n{c_green('✓ Fleet synchronization complete.')}\n")
|
||||
else:
|
||||
print(c_red(f"✗ Failed: {d.get('error')}"))
|
||||
except Exception:
|
||||
sys.stdout.write(res.stdout)
|
||||
|
||||
|
||||
def cmd_swarm_list(args):
|
||||
cmd = ["python3", str(BIN_DIR / "box-ctl.py"), "swarm-list"]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
@@ -3433,6 +3673,42 @@ def build_parser():
|
||||
p_s_show = ssh_sub.add_parser("show", parents=[common], help="Show public key content and fingerprint")
|
||||
p_s_show.add_argument("name", help="Identity/agent name")
|
||||
|
||||
p_s_ports = ssh_sub.add_parser("ports", parents=[common], help="List container reverse tunnel port mappings")
|
||||
p_s_info = ssh_sub.add_parser("info", parents=[common], help="Show SSH dial-in commands and reverse tunnel coordinates")
|
||||
p_s_info.add_argument("name", help="Agent identity (e.g. 646, muse, pip)")
|
||||
|
||||
# Domain: MD (Hatch Agent Markdown & Operational Drive)
|
||||
p_md = subparsers.add_parser("md", parents=[common], help="Manage agent .md system files & inject operational DRIVE via Hatch")
|
||||
md_sub = p_md.add_subparsers(dest="action")
|
||||
|
||||
p_md_audit = md_sub.add_parser("audit", parents=[common], help="Audit .md files and DRIVE scores across fleet agents")
|
||||
p_md_audit.add_argument("accounts", nargs="*", help="Optional account filter")
|
||||
|
||||
p_md_list = md_sub.add_parser("list", parents=[common], help="List files in agent container via Hatch")
|
||||
p_md_list.add_argument("account", help="Agent account (e.g. muse, pip, 646, opm, def, dev)")
|
||||
p_md_list.add_argument("path", nargs="?", default="", help="Subdirectory path")
|
||||
|
||||
p_md_read = md_sub.add_parser("read", parents=[common], help="Read an agent .md file via Hatch")
|
||||
p_md_read.add_argument("account", help="Agent account")
|
||||
p_md_read.add_argument("filename", help="Filename (e.g. SOUL.md, HEARTBEAT.md)")
|
||||
|
||||
p_md_write = md_sub.add_parser("write", parents=[common], help="Write an agent .md file via Hatch")
|
||||
p_md_write.add_argument("account", help="Agent account")
|
||||
p_md_write.add_argument("filename", help="Filename (e.g. SOUL.md)")
|
||||
p_md_write.add_argument("--content", help="Text content to write")
|
||||
p_md_write.add_argument("--file", help="Local file to copy from")
|
||||
|
||||
p_md_diff = md_sub.add_parser("diff", parents=[common], help="Diff container .md file against shared operator template")
|
||||
p_md_diff.add_argument("account", help="Agent account")
|
||||
p_md_diff.add_argument("filename", help="Filename (e.g. SOUL.md)")
|
||||
|
||||
p_md_drive = md_sub.add_parser("inject-drive", parents=[common], help="Inject high-drive operator files into an agent container")
|
||||
p_md_drive.add_argument("account", help="Agent account")
|
||||
p_md_drive.add_argument("--force", action="store_true", help="Force overwrite")
|
||||
|
||||
p_md_sync = md_sub.add_parser("sync-all", parents=[common], help="Inject high-drive operator files across all active fleet agents")
|
||||
p_md_sync.add_argument("--force", action="store_true", help="Force overwrite")
|
||||
|
||||
# Domain: HARVEST
|
||||
p_harvest = subparsers.add_parser("harvest", parents=[common], help="Readback & response harvesting engine")
|
||||
harvest_sub = p_harvest.add_subparsers(dest="action")
|
||||
@@ -3771,8 +4047,30 @@ def main():
|
||||
cmd_ssh_mint(args)
|
||||
elif act == "show":
|
||||
cmd_ssh_show(args)
|
||||
elif act == "ports":
|
||||
cmd_ssh_ports(args)
|
||||
elif act == "info":
|
||||
cmd_ssh_info(args)
|
||||
else:
|
||||
p_ssh.print_help()
|
||||
elif args.domain == "md":
|
||||
act = getattr(args, "action", None)
|
||||
if not act or act == "audit":
|
||||
cmd_md_audit(args)
|
||||
elif act == "list":
|
||||
cmd_md_list(args)
|
||||
elif act == "read":
|
||||
cmd_md_read(args)
|
||||
elif act == "write":
|
||||
cmd_md_write(args)
|
||||
elif act == "diff":
|
||||
cmd_md_diff(args)
|
||||
elif act == "inject-drive":
|
||||
cmd_md_inject_drive(args)
|
||||
elif act == "sync-all":
|
||||
cmd_md_sync_all(args)
|
||||
else:
|
||||
p_md.print_help()
|
||||
elif args.domain == "harvest":
|
||||
act = getattr(args, "action", None)
|
||||
if not act or act == "status":
|
||||
|
||||
Reference in New Issue
Block a user