queue.ts and server.ts now know about dev-c alongside pm/dev-a/dev-b so the four-role coordination paradigm works end-to-end. start.sh opens a fourth window for dev-c. call.py and call.ts are HTTP shims that agents can use when the MCP relay tools aren't registered in their session (the kickoff prompts reference call.py by path as a fallback). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
57 lines
1.2 KiB
TypeScript
57 lines
1.2 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
|
|
export type Role = "pm" | "dev-a" | "dev-b" | "dev-c";
|
|
export type MessageKind = "status" | "question" | "directive" | "free";
|
|
|
|
export interface RelayMessage {
|
|
id: string;
|
|
from: Role;
|
|
to: Role;
|
|
kind: MessageKind;
|
|
body: string;
|
|
ts: string;
|
|
}
|
|
|
|
const KNOWN_ROLES = new Set<string>(["pm", "dev-a", "dev-b", "dev-c"]);
|
|
|
|
export function isRole(s: string): s is Role {
|
|
return KNOWN_ROLES.has(s);
|
|
}
|
|
|
|
export class RelayQueue {
|
|
private readonly queues = new Map<Role, RelayMessage[]>([
|
|
["pm", []],
|
|
["dev-a", []],
|
|
["dev-b", []],
|
|
["dev-c", []],
|
|
]);
|
|
|
|
post(from: Role, to: Role, kind: MessageKind, body: string): RelayMessage {
|
|
const msg: RelayMessage = {
|
|
id: randomUUID(),
|
|
from,
|
|
to,
|
|
kind,
|
|
body,
|
|
ts: new Date().toISOString(),
|
|
};
|
|
this.queues.get(to)!.push(msg);
|
|
return msg;
|
|
}
|
|
|
|
read(forRole: Role): RelayMessage[] {
|
|
const inbox = this.queues.get(forRole)!;
|
|
const messages = [...inbox];
|
|
inbox.length = 0;
|
|
return messages;
|
|
}
|
|
|
|
pending(forRole: Role): { count: number; kinds: MessageKind[] } {
|
|
const inbox = this.queues.get(forRole)!;
|
|
return {
|
|
count: inbox.length,
|
|
kinds: inbox.map((m) => m.kind),
|
|
};
|
|
}
|
|
}
|