Files
bullpen/bin/room_tail
T
claude-noether c415899b03 bullpen MVP1: room (room_say/room_read) + room_tail window + @callboy worker
Self-made multi-agent chatroom. Append-only JSONL room on lmcp; reactive thin worker
with a mechanically-enforced tool allowlist; human window via room_tail. Engine = a
small local tool-model. Verified end-to-end (ask->ack->fetch_url reply incl. artifact
spill; non-tool ask -> graceful decline).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 10:40:21 +02:00

69 lines
2.3 KiB
Python
Executable File

#!/usr/bin/env python3
"""bullpen human window: watch the room, or post to it.
room_tail # print history, then follow live
room_tail read [since] # one-shot dump (optionally since id)
room_tail say <text...> # post as 'markus' (broadcast)
room_tail say @nick <text...> # post addressed to @nick
"""
import sys, json, time, os, subprocess
LOG = "/var/lib/bullpen/room.jsonl"
def fmt(d):
ts = time.strftime("%H:%M", time.localtime(d.get("ts", 0)))
rid = d.get("id", "?")
frm = d.get("from", "?")
to = d.get("to", "") or ""
typ = d.get("type", "chat")
body= d.get("body", "")
arrow = f"{to}" if to else ""
if typ == "ack": return f"{rid:>4} {ts} {frm}{arrow} ·ack·"
if typ == "system": return f"{rid:>4} {ts} * {body}"
tag = {"ask": "ask: ", "reply": "reply: "}.get(typ, "")
return f"{rid:>4} {ts} {frm}{arrow} {tag}{body}"
def dump(since=0):
if not os.path.exists(LOG): return 0
last = since
with open(LOG) as f:
for line in f:
line = line.strip()
if not line: continue
try: d = json.loads(line)
except Exception: continue
if d.get("id", 0) > since:
print(fmt(d)); last = d.get("id", last)
return last
def say(args):
text = " ".join(args).strip()
frm, to = "markus", ""
if text.startswith("@"):
p2 = text.split(None, 1); to = p2[0]; text = p2[1] if len(p2) > 1 else ""
body = text
if not body:
print("usage: room_tail say [@nick] <text>", file=sys.stderr); sys.exit(2)
cmd = ["lmcp-tool", "room_say", f"from={frm}", f"body={body}"]
if to: cmd.append(f"to={to}")
r = subprocess.run(cmd, capture_output=True, text=True)
sys.stdout.write(r.stdout); sys.stderr.write(r.stderr)
sys.exit(r.returncode)
def follow():
last = dump(0)
print("--- following (Ctrl-C to quit) ---")
while True:
time.sleep(1.0)
last = dump(last)
def main():
a = sys.argv[1:]
if not a: follow()
elif a[0] == "say": say(a[1:])
elif a[0] == "read": dump(int(a[1]) if len(a) > 1 else 0)
elif a[0] in ("follow","-f"): follow()
else: print(__doc__)
if __name__ == "__main__":
try: main()
except KeyboardInterrupt: pass