File-based message bus. Each agent has a .jsonl inbox. Read is destructive: read_text + unlink (consumes messages). Teaching version: no file locking; real CC uses proper-lockfile.
| 338 | |
| 339 | |
| 340 | class MessageBus: |
| 341 | """File-based message bus. Each agent has a .jsonl inbox. |
| 342 | Read is destructive: read_text + unlink (consumes messages). |
| 343 | Teaching version: no file locking; real CC uses proper-lockfile.""" |
| 344 | |
| 345 | def send(self, from_agent: str, to_agent: str, content: str, |
| 346 | msg_type: str = "message", metadata: dict = None): |
| 347 | msg = {"from": from_agent, "to": to_agent, |
| 348 | "content": content, "type": msg_type, |
| 349 | "ts": time.time(), "metadata": metadata or {}} |
| 350 | inbox = MAILBOX_DIR / f"{to_agent}.jsonl" |
| 351 | with open(inbox, "a") as f: |
| 352 | f.write(json.dumps(msg) + "\n") |
| 353 | print(f" \033[33m[bus] {from_agent} → {to_agent}: " |
| 354 | f"({msg_type}) {content[:50]}\033[0m") |
| 355 | |
| 356 | def read_inbox(self, agent: str) -> list[dict]: |
| 357 | inbox = MAILBOX_DIR / f"{agent}.jsonl" |
| 358 | if not inbox.exists(): |
| 359 | return [] |
| 360 | msgs = [json.loads(line) for line in inbox.read_text().splitlines() |
| 361 | if line.strip()] |
| 362 | inbox.unlink() # consume: read + delete |
| 363 | return msgs |
| 364 | |
| 365 | |
| 366 | BUS = MessageBus() |