agent-coord-mcp 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-coord-mcp",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "File-backed MCP server for coordinating multiple AI coding agents (Claude Code, Cursor, Cline, etc.) on the same machine.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -67,11 +67,19 @@ const A = {
67
67
  blue: (s) => `\x1b[34m${s}\x1b[0m`,
68
68
  magenta: (s) => `\x1b[35m${s}\x1b[0m`,
69
69
  cyan: (s) => `\x1b[36m${s}\x1b[0m`,
70
+ brightGreen: (s) => `\x1b[92m${s}\x1b[0m`,
71
+ brightYellow: (s) => `\x1b[93m${s}\x1b[0m`,
72
+ brightBlue: (s) => `\x1b[94m${s}\x1b[0m`,
73
+ brightMagenta: (s) => `\x1b[95m${s}\x1b[0m`,
74
+ brightCyan: (s) => `\x1b[96m${s}\x1b[0m`,
70
75
  };
71
76
 
72
- // Stable per-agent color from agentId hash. Skip red (reserved for errors)
73
- // and white/black; cycle the remaining 5 bright colors.
74
- const AGENT_COLORS = [A.green, A.yellow, A.blue, A.magenta, A.cyan];
77
+ // Stable per-agent color from agentId hash. 10 colors (standard + bright)
78
+ // to reduce collisions. Red is reserved for errors so we skip it.
79
+ const AGENT_COLORS = [
80
+ A.green, A.yellow, A.blue, A.magenta, A.cyan,
81
+ A.brightGreen, A.brightYellow, A.brightBlue, A.brightMagenta, A.brightCyan,
82
+ ];
75
83
  function agentColor(id) {
76
84
  let h = 0;
77
85
  for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) >>> 0;
@@ -604,19 +612,51 @@ function printMsg(kind, m, opts = {}) {
604
612
  const d = new Date(m.ts);
605
613
  const t = `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
606
614
  const who = m.from ?? "?";
615
+ const color = agentColor(who);
616
+ const gutter = color("▎");
607
617
  const tag = kind === "DM" ? A.bold(A.cyan("DM")) : A.dim("room");
608
- const meta = `${A.dim(t)} ${tag} ${agentColor(who)(who)}`;
609
- // Multi-line bodies: first line on the meta row, subsequent lines indented
610
- // to the body column for readability.
611
- const body = (m.text ?? "").split("\n");
612
- const indent = " ";
618
+ const nick = A.bold(color(who));
619
+ const meta = `${A.dim(t)} ${tag} ${nick}`;
620
+ const body = (m.text ?? "").split("\n").map(formatBody);
621
+ const indent = " ";
613
622
  const first = body[0] ?? "";
614
- const rest = body.slice(1).map((l) => indent + A.dim("│ ") + l);
623
+ const rest = body.slice(1).map((l) => `${gutter} ${indent}${A.dim("│ ")}${l}`);
615
624
  const prefix = opts.history ? A.dim(" ") : "";
616
- say(`${prefix}${meta} ${first}`);
625
+ say(`${prefix}${gutter} ${meta} ${first}`);
617
626
  for (const line of rest) say(`${prefix}${line}`);
618
627
  }
619
628
 
629
+ // Lightweight inline-only "chat markdown" formatter — no dep. Handles bold,
630
+ // italic, inline code, links, and @mentions. Order matters: pull out inline
631
+ // code spans first so we don't touch their contents, then run the rest.
632
+ function formatBody(text) {
633
+ return text.split(/(`[^`\n]+`)/).map((part) => {
634
+ if (part.startsWith("`") && part.endsWith("`") && part.length >= 2) {
635
+ return A.dim("`") + A.cyan(part.slice(1, -1)) + A.dim("`");
636
+ }
637
+ let s = part;
638
+ // @mentions first — colored in the mentioned agent's hash color, bold if
639
+ // it's the current user (so you can spot pings at a glance).
640
+ s = s.replace(/@([A-Za-z0-9._-]+)/g, (_, name) => {
641
+ const colored = agentColor(name)(`@${name}`);
642
+ return name === ID ? A.bold(colored) : colored;
643
+ });
644
+ // **bold**
645
+ s = s.replace(/\*\*([^*\n]+)\*\*/g, (_, t) => A.bold(t));
646
+ // *italic* and _italic_ (avoid matching inside **bold** by requiring
647
+ // non-asterisk neighbors)
648
+ s = s.replace(/(?<![*\w])\*([^*\n]+)\*(?![*\w])/g, (_, t) => `\x1b[3m${t}\x1b[0m`);
649
+ s = s.replace(/(?<![_\w])_([^_\n]+)_(?![_\w])/g, (_, t) => `\x1b[3m${t}\x1b[0m`);
650
+ // [text](url) — show text underlined with a dim trailing (url)
651
+ s = s.replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g, (_, t, u) =>
652
+ `\x1b[4m${t}\x1b[0m${A.dim(` (${u})`)}`,
653
+ );
654
+ // Bare URLs — underline only the URL itself
655
+ s = s.replace(/\bhttps?:\/\/[^\s)]+/g, (u) => `\x1b[4m${u}\x1b[0m`);
656
+ return s;
657
+ }).join("");
658
+ }
659
+
620
660
  async function printAgents() {
621
661
  const reg = readJsonSafe(AGENTS_FILE, {});
622
662
  const now = Date.now();