agent-coord-mcp 0.16.0 → 0.17.0
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/README.md +1 -1
- package/hooks/tier.mjs +5 -0
- package/hooks/tmux-pusher.mjs +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -303,7 +303,7 @@ Either way, `list_agents` will show the agent with `transport: "tmux-push"` so p
|
|
|
303
303
|
|
|
304
304
|
Under the hood: [`hooks/tmux-pusher.mjs`](./hooks/tmux-pusher.mjs) is the daemon. It watches `~/agent-coord/inbox/<id>.jsonl` (and, when room delivery is on, every channel the agent has joined), debounces bursts (1s default), drops self-posts and `/`-prefixed text (except allowlisted control commands — see [below](#clearing-sub-agent-context-send_command)), optionally enforces the peer allowlist, then pastes batches via `tmux load-buffer` → `paste-buffer -d` → `send-keys Enter`. Single-flight so two batches never overlap.
|
|
305
305
|
|
|
306
|
-
**Delivery tiers.** Not every message deserves an agent turn.
|
|
306
|
+
**Delivery tiers.** Not every message deserves an agent turn. All DMs push now — they're point-to-point asks, not broadcast noise. Channel traffic wakes the pane only when push-now: `BLOCKER:`, `DAVID_DECISION:`, literal `GO:` work orders, `SCOPE:`/`SCOPE CHANGE:` from a trusted sender (coordinator/gate ids resolved from the registry), `DONE:` when this agent is a gate runner (QA/coordinator — from its registry role, re-resolved every 30s, overridable with `AGENT_COORD_GATE_RUNNER=1|0`), control commands, and server-flagged messages like the post-`/clear` identity reminder. Prefixes are literal and case-sensitive. Everything else (`FYI:`, `AGENT_ACTION:`, `RISK:`, chatter) queues silently and rides the next urgent push as one coalesced digest block (banner `[agent-coord] +N routine (pre-consumed, FYI, no reply):`). Routine backlog is age-bounded: once its oldest message has queued longer than `AGENT_COORD_MAX_QUEUE_MS` (default 15s; `0` disables), the backlog flushes on its own as a routine-only digest, so a quiet bus never sits on undelivered traffic indefinitely. The on-disk cursor (shared with `read_messages`) advances only **after** a paste is confirmed, so a crash or `SIGTERM` rewinds and redelivers (at-least-once) — queued traffic stays **unread** and is never lost. An idle agent with only routine backlog is never woken; routine ops cost zero tokens. `AGENT_COORD_TIERS=0` restores legacy push-everything. The classifier and queue are pure ([`hooks/tier.mjs`](./hooks/tier.mjs)). Known trade-offs: routine messages get their delivery receipt only when their digest lands; a digest can arrive without the banner if a push carries only queued routine after a control command; within one paste, urgent lines precede the digest regardless of arrival order.
|
|
307
307
|
|
|
308
308
|
**Caveats — read these.**
|
|
309
309
|
|
package/hooks/tier.mjs
CHANGED
|
@@ -14,6 +14,11 @@ export function classifyTier(m, opts = {}) {
|
|
|
14
14
|
// Server-set push-now override (post-/clear reminder). send_message builds
|
|
15
15
|
// Messages from fixed fields, so a peer cannot smuggle this flag in.
|
|
16
16
|
if (m.urgent === true) return "urgent";
|
|
17
|
+
// DMs are always push-now: they're addressed to this agent by a peer who
|
|
18
|
+
// wants it specifically, and DM volume is tiny next to room traffic. The
|
|
19
|
+
// tiers exist to absorb broadcast noise, not point-to-point asks (the
|
|
20
|
+
// liaison relaying a David question must not sit in a digest queue).
|
|
21
|
+
if (m.kind === "DM") return "urgent";
|
|
17
22
|
if (typeof m.text !== "string") return "routine";
|
|
18
23
|
const text = m.text.trimStart();
|
|
19
24
|
// Control/slash commands are injected raw and must fire immediately.
|
package/hooks/tmux-pusher.mjs
CHANGED
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
* AGENT_COORD_DEBOUNCE_MS coalesce window for bursts (default 1000)
|
|
20
20
|
* AGENT_COORD_POLL_MS fallback poll interval (default 1000)
|
|
21
21
|
* AGENT_COORD_TARGET_GRACE missed pane probes before self-exit (default 3)
|
|
22
|
-
* AGENT_COORD_MAX_QUEUE_MS max time routine traffic may queue
|
|
23
|
-
* urgent trigger before it flushes as
|
|
24
|
-
* (default
|
|
22
|
+
* AGENT_COORD_MAX_QUEUE_MS max time routine (channel) traffic may queue
|
|
23
|
+
* without an urgent trigger before it flushes as
|
|
24
|
+
* a digest (default 15000 = 15s; 0 disables)
|
|
25
25
|
*
|
|
26
26
|
* Safety:
|
|
27
27
|
* - drops messages where from === AGENT_COORD_ID (no self-echo)
|
|
@@ -89,8 +89,9 @@ const TIERS_ENABLED = process.env.AGENT_COORD_TIERS !== "0";
|
|
|
89
89
|
// Max-age flush: routine traffic never waits longer than this for an urgent
|
|
90
90
|
// trigger — once the oldest queued message is overdue, the backlog flushes as
|
|
91
91
|
// a routine-only digest. Bounds the silent-fleet failure mode where FYI:/DONE:
|
|
92
|
-
// chatter queues forever because nothing urgent ever arrives.
|
|
93
|
-
|
|
92
|
+
// chatter queues forever because nothing urgent ever arrives. Only channel
|
|
93
|
+
// traffic queues (DMs are push-now), so the default is short.
|
|
94
|
+
const MAX_QUEUE_MS = parseInt(process.env.AGENT_COORD_MAX_QUEUE_MS || "15000", 10);
|
|
94
95
|
// Gate runners (QA/coordinator) receive DONE: as push-now; countersigned
|
|
95
96
|
// SCOPE: changes are honored only from these trusted ids. Re-resolved from
|
|
96
97
|
// the registry every 30s so a role change doesn't strand a stale pusher;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-coord-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "File-backed MCP server for coordinating multiple AI coding agents (Claude Code, Cursor, Cline, etc.). Local stdio or networked over Streamable HTTP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|