agent-comms 1.4.0 → 1.4.2

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-comms",
3
3
  "description": "Cross-harness LLM agent communication bus — rooms, DMs, and presence",
4
- "version": "1.4.0",
4
+ "version": "1.4.2",
5
5
  "author": {
6
6
  "name": "ExaDev"
7
7
  },
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Agent Comms
2
2
 
3
- Cross-harness communication bus for LLM agents: rooms, DMs, presence, and visibility over a TCP peer mesh with zero filesystem dependencies.
3
+ Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
4
4
 
5
5
  ## Why
6
6
 
@@ -14,24 +14,48 @@ The project began as a filesystem-based bus (`~/.agents/bus/`), where agents rea
14
14
 
15
15
  Each bridge instance is a peer in a TCP mesh on localhost. The first instance to start becomes the **coordinator** (port 19876). Subsequent instances connect to the coordinator, receive the peer list, and establish direct data connections with every other peer.
16
16
 
17
- ```
18
- Agent A (pi) Agent B (Claude Code)
19
- │ │
20
- │ pi bridge ◀──TCP localhost──▶ Claude bridge
21
- │ │ │
22
- │ agent_comms( channel notification
23
- "send", │
24
- │ ... Claude surfaces it
25
- │ ) to the LLM
26
- │ │
27
- │ push to B's bridge ───────────▶ handled
17
+ ```mermaid
18
+ graph LR
19
+ subgraph Agent A ["Agent A (pi)"]
20
+ A_LLM["LLM"]
21
+ A_Bridge["pi bridge"]
22
+ end
23
+ subgraph Agent B ["Agent B (Claude Code)"]
24
+ B_Bridge["Claude bridge"]
25
+ B_LLM["LLM"]
26
+ end
27
+ A_LLM -- "agent_comms(send, ...)" --> A_Bridge
28
+ A_Bridge -- "TCP localhost" --> B_Bridge
29
+ B_Bridge -- "channel notification" --> B_LLM
28
30
  ```
29
31
 
30
32
  All state is held in memory and synchronised between peers. Delivery events are pushed directly over TCP: no polling, no filesystem, no daemon process.
31
33
 
32
34
  ### Coordinator pattern
33
35
 
34
- - **Well-known port** 19876 on localhost, the only agreed-upon constant
36
+ ```mermaid
37
+ sequenceDiagram
38
+ participant P1 as Peer 1 (first to start)
39
+ participant P2 as Peer 2
40
+ participant P3 as Peer 3
41
+ P1->>P1: binds port 19876 → becomes coordinator
42
+ P2->>P1: connect to 19876
43
+ P1-->>P2: peer list [P1]
44
+ P2->>P1: establish data connection
45
+ P3->>P1: connect to 19876
46
+ P1-->>P3: peer list [P1, P2]
47
+ P3->>P1: establish data connection
48
+ P3->>P2: establish data connection
49
+ Note over P1,P3: All peers now connected directly
50
+ rect rgb(255, 230, 230)
51
+ Note over P1: Coordinator crashes
52
+ P2->>P2: race to bind 19876
53
+ P3->>P3: race to bind 19876
54
+ Note over P2,P3: ~100ms recovery, longest-running wins
55
+ end
56
+ ```
57
+
58
+ - **Well-known port** 19876 on localhost — the only agreed-upon constant
35
59
  - The first instance to bind it becomes coordinator
36
60
  - Coordinator handles introductions only; it is not a router
37
61
  - On graceful shutdown, coordinator hands over to the longest-running peer
@@ -183,3 +207,65 @@ agent_comms({ action: "update", visibility: "hidden" })
183
207
  | `visible` | ✓ | ✓ | ✓ |
184
208
  | `hidden` | ✗ | ✓ (if ID known) | Members only |
185
209
  | `ghost` | ✗ | ✗ | ✗ |
210
+
211
+ ## Room member awareness
212
+
213
+ When an agent joins a room, it receives a `room_members` delivery event listing all current members with their status. Existing members receive `member_joined` / `member_left` notifications (excluding the joining/leaving agent).
214
+
215
+ ```mermaid
216
+ sequenceDiagram
217
+ participant A as Agent A (in room)
218
+ participant Mesh
219
+ participant B as Agent B (joining)
220
+ B->>Mesh: joinRoom("code-review")
221
+ Mesh-->>B: room_members { [{ id: A, status: active }] }
222
+ Mesh-->>A: member_joined { agent: B }
223
+ Note over A: A knows B arrived, B knows who is already there
224
+ rect rgb(255, 245, 230)
225
+ Note over B: B goes idle
226
+ B->>Mesh: update(status: idle)
227
+ Mesh-->>A: member_status { agent: B, status: idle }
228
+ end
229
+ ```
230
+
231
+ When an agent's status changes (active / idle / busy / offline), all rooms it belongs to receive a `member_status` notification. This covers:
232
+
233
+ - Explicit `update` action
234
+ - Re-registration (offline → active)
235
+ - Graceful shutdown
236
+ - Stale agent cleanup (coordinator PID probe)
237
+
238
+ ## Delivery status and read receipts
239
+
240
+ Messages carry a `readBy` field tracking which agents have consumed them. Status events are emitted to the sender automatically — no explicit action needed.
241
+
242
+ ```mermaid
243
+ sequenceDiagram
244
+ participant A as Agent A (sender)
245
+ participant Mesh
246
+ participant B as Agent B (recipient)
247
+ A->>Mesh: send("Hello")
248
+ Mesh->>B: queue room_message
249
+ Mesh-->>A: delivery_status { delivered }
250
+ alt Push bridge (pi, Claude Code)
251
+ Mesh->>B: onDelivery fires
252
+ else Drain bridge (MCP, Codex, OpenCode)
253
+ B->>Mesh: drainDelivery()
254
+ end
255
+ Mesh->>Mesh: markRead(msgId, B)
256
+ Mesh-->>A: delivery_status { read }
257
+ Mesh->>Mesh: broadcast message_read patch
258
+ ```
259
+
260
+ | Moment | Sender receives |
261
+ |--------|-----------------|
262
+ | Message queued for recipient | `delivery_status { status: "delivered" }` |
263
+ | Recipient's bridge consumes it | `delivery_status { status: "read" }` |
264
+
265
+ Read receipts fire when `onDelivery` is called (push bridges: pi, Claude Code) or when `drainDelivery` is called (drain bridges: MCP, Codex, OpenCode). Cross-peer read receipts propagate via a `message_read` mesh patch.
266
+
267
+ This works for both room messages and DMs.
268
+
269
+ ## Stale agent cleanup
270
+
271
+ The coordinator probes registered agent PIDs every 5 seconds using signal 0 (existence check). Dead agents are marked offline and the status is broadcast to all peers. Prevents zombie agents accumulating in the mesh when bridges crash without calling `shutdown()`. The probe interval only runs on the coordinator — other peers are passive.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-comms",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Cross-harness communication bus for LLM agents — TCP peer mesh with rooms, DMs, presence, and real-time push delivery",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.33.0",