bridge.py: front-door to muse.ai metadata bridge CLI
This commit is contained in:
Executable
+89
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Bridge CLI: Front-Door ↔ muse.ai metadata bridge
|
||||||
|
|
||||||
|
Manages mappings between front-door channels and muse.ai side chats.
|
||||||
|
Storage: ~/Projects/NetVM/bridge/mappings.json (operator-managed via SSH)
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
bridge.py list --channel #ops
|
||||||
|
bridge.py add --agent 646 --chat <id> --channel #ops --purpose "incident-123"
|
||||||
|
bridge.py remove <bridge_id>
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
BRIDGE_DIR = Path.home() / "Projects" / "NetVM" / "bridge"
|
||||||
|
MAPPINGS_FILE = BRIDGE_DIR / "mappings.json"
|
||||||
|
|
||||||
|
def load_mappings():
|
||||||
|
if not MAPPINGS_FILE.exists():
|
||||||
|
return []
|
||||||
|
with open(MAPPINGS_FILE) as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def save_mappings(mappings):
|
||||||
|
BRIDGE_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(MAPPINGS_FILE, 'w') as f:
|
||||||
|
json.dump(mappings, f, indent=2)
|
||||||
|
|
||||||
|
def cmd_list(args):
|
||||||
|
mappings = load_mappings()
|
||||||
|
if args.channel:
|
||||||
|
mappings = [m for m in mappings if m['frontdoor_channel'] == args.channel]
|
||||||
|
if not mappings:
|
||||||
|
print("No mappings found.")
|
||||||
|
return
|
||||||
|
for m in mappings:
|
||||||
|
print(f"{m['bridge_id']}: {m['agent']}/{m['muse_side_chat_id'][:8]} -> {m['frontdoor_channel']} ({m['purpose']}) [{m['status']}]")
|
||||||
|
|
||||||
|
def cmd_add(args):
|
||||||
|
mappings = load_mappings()
|
||||||
|
bridge_id = f"br-{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}"
|
||||||
|
mapping = {
|
||||||
|
"bridge_id": bridge_id,
|
||||||
|
"frontdoor_channel": args.channel,
|
||||||
|
"muse_side_chat_id": args.chat,
|
||||||
|
"agent": args.agent,
|
||||||
|
"linked_at": datetime.now(timezone.utc).isoformat(),
|
||||||
|
"linked_by": args.by or "operator",
|
||||||
|
"purpose": args.purpose,
|
||||||
|
"status": "active"
|
||||||
|
}
|
||||||
|
mappings.append(mapping)
|
||||||
|
save_mappings(mappings)
|
||||||
|
print(f"Added {bridge_id}")
|
||||||
|
|
||||||
|
def cmd_remove(args):
|
||||||
|
mappings = load_mappings()
|
||||||
|
mappings = [m for m in mappings if m['bridge_id'] != args.bridge_id]
|
||||||
|
save_mappings(mappings)
|
||||||
|
print(f"Removed {args.bridge_id}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
p = argparse.ArgumentParser(description="Bridge: front-door to muse.ai")
|
||||||
|
sub = p.add_subparsers(dest='cmd', required=True)
|
||||||
|
|
||||||
|
p_list = sub.add_parser('list', help='List mappings')
|
||||||
|
p_list.add_argument('--channel', help='Filter by front-door channel')
|
||||||
|
p_list.set_defaults(func=cmd_list)
|
||||||
|
|
||||||
|
p_add = sub.add_parser('add', help='Add a mapping')
|
||||||
|
p_add.add_argument('--agent', required=True, help='Agent (muse/pip/646)')
|
||||||
|
p_add.add_argument('--chat', required=True, help='muse.ai side chat ID')
|
||||||
|
p_add.add_argument('--channel', required=True, help='Front-door channel (#ops, #lobby, etc.)')
|
||||||
|
p_add.add_argument('--purpose', required=True, help='Purpose of the side chat')
|
||||||
|
p_add.add_argument('--by', help='Who linked (operator/agent)')
|
||||||
|
p_add.set_defaults(func=cmd_add)
|
||||||
|
|
||||||
|
p_rm = sub.add_parser('remove', help='Remove a mapping')
|
||||||
|
p_rm.add_argument('bridge_id', help='Bridge ID to remove')
|
||||||
|
p_rm.set_defaults(func=cmd_remove)
|
||||||
|
|
||||||
|
args = p.parse_args()
|
||||||
|
args.func(args)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
Reference in New Issue
Block a user