agent-comms 1.22.0 → 1.23.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/.claude-plugin/marketplace.json +19 -19
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/commands/agents.md +5 -0
- package/commands/dm.md +6 -0
- package/commands/hide.md +5 -0
- package/commands/join.md +6 -0
- package/commands/leave.md +6 -0
- package/commands/read.md +6 -0
- package/commands/rooms.md +5 -0
- package/commands/send.md +6 -0
- package/commands/show.md +5 -0
- package/commands/status.md +6 -0
- package/commands/whoami.md +5 -0
- package/dist/bridges/claude-code/channel.d.ts.map +1 -1
- package/dist/bridges/claude-code/channel.js +96 -4
- package/dist/bridges/claude-code/channel.js.map +1 -1
- package/hooks/drain.sh +32 -1
- package/hooks/hooks.json +1 -2
- package/package.json +2 -1
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
2
|
+
"name": "agent-comms",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "ExaDev"
|
|
5
|
+
},
|
|
6
|
+
"metadata": {
|
|
7
|
+
"description": "Cross-harness communication mesh for LLM agents",
|
|
8
|
+
"homepage": "https://github.com/ExaDev/agent-comms#readme"
|
|
9
|
+
},
|
|
10
|
+
"plugins": [
|
|
11
|
+
{
|
|
12
|
+
"name": "agent-comms",
|
|
13
|
+
"source": {
|
|
14
|
+
"source": "url",
|
|
15
|
+
"url": "https://github.com/ExaDev/agent-comms.git"
|
|
16
|
+
},
|
|
17
|
+
"description": "Cross-harness LLM agent communication mesh — rooms, DMs, and presence",
|
|
18
|
+
"version": "1.23.0"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
21
|
}
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/ExaDev/agent-comms)
|
|
4
4
|
[](https://www.npmjs.com/package/agent-comms)
|
|
5
|
-
[](https://github.com/ExaDev/agent-comms/releases/tag/v1.23.0)
|
|
6
6
|
[](https://github.com/ExaDev/agent-comms/actions)
|
|
7
7
|
|
|
8
8
|
Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
|
package/commands/dm.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Send a direct message to an agent
|
|
3
|
+
argument-hint: <agent-id-or-name> <message>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Parse `$ARGUMENTS` as `<target> <message>` — first whitespace-separated token is the target agent id or name; everything after is the message body. Call the `agent_comms` MCP tool with `action: "dm"`, `target: <target>`, `content: <message>`, and `streamingBehavior: "steer"`. Confirm with a single line containing the returned message id. If the target is unknown, surface the error verbatim.
|
package/commands/hide.md
ADDED
package/commands/join.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Join a room
|
|
3
|
+
argument-hint: <room-name>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Call the `agent_comms` MCP tool with `action: "join_room"` and `room: "$ARGUMENTS"`. Confirm with a single line — room name and current member count. If the room doesn't exist, surface the error verbatim.
|
package/commands/read.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Read recent messages from a room
|
|
3
|
+
argument-hint: <room>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Call the `agent_comms` MCP tool with `action: "read_room"` and `room: "$ARGUMENTS"`. Present each message on its own line in chronological order, using the format `[HH:MM] <sender>: <content>`. If `<sender>` is a long fingerprint, truncate to the last 8 characters. No commentary.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: List all rooms in the mesh
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Call the `agent_comms` MCP tool with `action: "list_rooms"` and present the result as a compact list — one room per line — showing the name, type, and member count, with a `[✓]` marker for rooms this session has joined. Don't add commentary.
|
package/commands/send.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Broadcast a message to a room
|
|
3
|
+
argument-hint: <room> <message>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Parse `$ARGUMENTS` as `<room> <message>` — first whitespace-separated token is the room name; everything after is the message body. Call the `agent_comms` MCP tool with `action: "send"`, `target: <room>`, `content: <message>`, and `streamingBehavior: "info"`. Confirm with a single line containing the returned message id. If the room isn't joined, surface the error verbatim.
|
package/commands/show.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Set this session's presence status
|
|
3
|
+
argument-hint: <active|idle|busy>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Validate that `$ARGUMENTS` is one of `active`, `idle`, or `busy`. If invalid, print an error and stop. Otherwise call the `agent_comms` MCP tool with `action: "update"` and `status: "$ARGUMENTS"`. Confirm with a single line: the new status.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show this session's agent identity, status, and room memberships
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Call the `agent_comms` MCP tool with `action: "whoami"` and present the result concisely: agent ID (short form), name, current status, visibility, and the list of joined rooms. No commentary.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/bridges/claude-code/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/bridges/claude-code/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA4IH,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAwHzC"}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* so the asyncRewake hook scripts (hooks/drain.sh) can drain them out-of-process
|
|
12
12
|
* and wake idle Claude via exit code 2.
|
|
13
13
|
*/
|
|
14
|
+
import { execFileSync } from "node:child_process";
|
|
14
15
|
import * as fs from "node:fs";
|
|
15
16
|
import * as os from "node:os";
|
|
16
17
|
import * as path from "node:path";
|
|
@@ -27,9 +28,95 @@ function isRecord(value) {
|
|
|
27
28
|
function isErrnoException(err) {
|
|
28
29
|
return typeof err === "object" && err !== null && "code" in err;
|
|
29
30
|
}
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
function cwdSlug(cwd) {
|
|
32
|
+
return cwd.replace(/[^a-zA-Z0-9]/g, "_");
|
|
33
|
+
}
|
|
34
|
+
function pendingDir() {
|
|
35
|
+
return path.join(os.homedir(), ".agents", "bus", "pending");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Walk up the process tree to find the Claude Code CLI PID.
|
|
39
|
+
*
|
|
40
|
+
* The bridge runs ~3 hops below claude (tsx wrapper → tsx loader → bridge),
|
|
41
|
+
* so process.ppid alone isn't enough. We walk until we find an ancestor
|
|
42
|
+
* whose command basename is "claude".
|
|
43
|
+
*
|
|
44
|
+
* Two Claude Code instances in the same cwd would otherwise share one
|
|
45
|
+
* pending file and consume each other's messages. Keying by Claude PID
|
|
46
|
+
* isolates them. Returns undefined if no claude ancestor can be located
|
|
47
|
+
* within 10 hops — caller falls back to cwd-only path.
|
|
48
|
+
*/
|
|
49
|
+
function findClaudeCodePid() {
|
|
50
|
+
let pid = process.ppid;
|
|
51
|
+
for (let i = 0; i < 10 && pid > 1; i++) {
|
|
52
|
+
let out;
|
|
53
|
+
try {
|
|
54
|
+
out = execFileSync("ps", ["-o", "ppid=,comm=", "-p", String(pid)], {
|
|
55
|
+
encoding: "utf-8",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const trimmed = out.trim();
|
|
62
|
+
const match = /^(\d+)\s+(.+)$/.exec(trimmed);
|
|
63
|
+
if (!match)
|
|
64
|
+
return undefined;
|
|
65
|
+
const parentPid = Number.parseInt(match[1] ?? "", 10);
|
|
66
|
+
const comm = (match[2] ?? "").trim();
|
|
67
|
+
if (/(^|\/)claude$/.test(comm))
|
|
68
|
+
return pid;
|
|
69
|
+
if (!Number.isFinite(parentPid))
|
|
70
|
+
return undefined;
|
|
71
|
+
pid = parentPid;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
function pendingFilePath(cwd, claudePid) {
|
|
76
|
+
const slug = cwdSlug(cwd);
|
|
77
|
+
const name = claudePid !== undefined
|
|
78
|
+
? `claude-code--${slug}--${String(claudePid)}.jsonl`
|
|
79
|
+
: `claude-code--${slug}.jsonl`;
|
|
80
|
+
return path.join(pendingDir(), name);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Drop pending files in this cwd whose owning Claude Code PID is no longer
|
|
84
|
+
* alive. Prevents accumulation when sessions exit without graceful shutdown.
|
|
85
|
+
*/
|
|
86
|
+
function cleanupStalePendingFiles(cwd) {
|
|
87
|
+
const dir = pendingDir();
|
|
88
|
+
const slug = cwdSlug(cwd);
|
|
89
|
+
const prefix = `claude-code--${slug}--`;
|
|
90
|
+
let entries;
|
|
91
|
+
try {
|
|
92
|
+
entries = fs.readdirSync(dir);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
if (isErrnoException(err) && err.code === "ENOENT")
|
|
96
|
+
return;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
for (const entry of entries) {
|
|
100
|
+
if (!entry.startsWith(prefix) || !entry.endsWith(".jsonl"))
|
|
101
|
+
continue;
|
|
102
|
+
const pidStr = entry.slice(prefix.length, -".jsonl".length);
|
|
103
|
+
const pid = Number.parseInt(pidStr, 10);
|
|
104
|
+
if (!Number.isFinite(pid) || pid <= 1)
|
|
105
|
+
continue;
|
|
106
|
+
try {
|
|
107
|
+
process.kill(pid, 0);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
if (isErrnoException(err) && err.code === "ESRCH") {
|
|
111
|
+
try {
|
|
112
|
+
fs.unlinkSync(path.join(dir, entry));
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// best-effort cleanup, ignore failures
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
33
120
|
}
|
|
34
121
|
function appendPending(filePath, line) {
|
|
35
122
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
@@ -59,7 +146,12 @@ export async function run() {
|
|
|
59
146
|
store.setTransport(new TlsTransport(store.events, identity));
|
|
60
147
|
const tool = new CommsTool(store, store.discovery);
|
|
61
148
|
let agentId;
|
|
62
|
-
const
|
|
149
|
+
const claudeCodePid = findClaudeCodePid();
|
|
150
|
+
if (claudeCodePid === undefined) {
|
|
151
|
+
process.stderr.write("agent-comms bridge: could not locate Claude Code PID; using shared cwd pending file (concurrent sessions in the same cwd will share messages)\n");
|
|
152
|
+
}
|
|
153
|
+
cleanupStalePendingFiles(process.cwd());
|
|
154
|
+
const pendingFile = pendingFilePath(process.cwd(), claudeCodePid);
|
|
63
155
|
const mcp = new McpServer({ name: "agent-comms", version: "0.2.0" }, {
|
|
64
156
|
capabilities: {
|
|
65
157
|
experimental: { "claude/channel": {} },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../../src/bridges/claude-code/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAY;IACpC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,CAAC;AAClE,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../../src/bridges/claude-code/channel.ts"],"names":[],"mappings":"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"}
|
package/hooks/drain.sh
CHANGED
|
@@ -11,7 +11,38 @@
|
|
|
11
11
|
set -euo pipefail
|
|
12
12
|
|
|
13
13
|
SLUG="${PWD//[^a-zA-Z0-9]/_}"
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
# Walk up the process tree to find the Claude Code PID. Two Claude Code
|
|
16
|
+
# instances in the same cwd would otherwise share one pending file and consume
|
|
17
|
+
# each other's messages. Each Claude Code session has a unique PID; the bridge
|
|
18
|
+
# discovers and uses the same value, so each session gets its own file.
|
|
19
|
+
find_claude_pid() {
|
|
20
|
+
local pid=$PPID
|
|
21
|
+
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
|
22
|
+
[ "$pid" -le 1 ] && return 1
|
|
23
|
+
local info ppid comm
|
|
24
|
+
info=$(ps -p "$pid" -o ppid=,comm= 2>/dev/null) || return 1
|
|
25
|
+
info=${info#"${info%%[![:space:]]*}"}
|
|
26
|
+
[ -z "$info" ] && return 1
|
|
27
|
+
ppid=${info%%[[:space:]]*}
|
|
28
|
+
comm=${info#*[[:space:]]}
|
|
29
|
+
comm=${comm#"${comm%%[![:space:]]*}"}
|
|
30
|
+
case "$comm" in
|
|
31
|
+
*/claude|claude) echo "$pid"; return 0 ;;
|
|
32
|
+
esac
|
|
33
|
+
pid=$ppid
|
|
34
|
+
done
|
|
35
|
+
return 1
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
CLAUDE_PID=$(find_claude_pid 2>/dev/null || true)
|
|
39
|
+
if [ -n "$CLAUDE_PID" ]; then
|
|
40
|
+
PENDING="$HOME/.agents/bus/pending/claude-code--${SLUG}--${CLAUDE_PID}.jsonl"
|
|
41
|
+
else
|
|
42
|
+
echo "agent-comms drain.sh: could not locate Claude Code PID, falling back to shared cwd file" >&2
|
|
43
|
+
PENDING="$HOME/.agents/bus/pending/claude-code--${SLUG}.jsonl"
|
|
44
|
+
fi
|
|
45
|
+
|
|
15
46
|
DRAINING="${PENDING}.draining-$$-$(date +%s%N 2>/dev/null || date +%s)"
|
|
16
47
|
|
|
17
48
|
# Atomic drain — if rename fails (file absent), nothing to surface.
|
package/hooks/hooks.json
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/drain.sh",
|
|
9
|
-
"asyncRewake": true,
|
|
10
9
|
"timeout": 5
|
|
11
10
|
}
|
|
12
11
|
]
|
|
@@ -19,7 +18,6 @@
|
|
|
19
18
|
{
|
|
20
19
|
"type": "command",
|
|
21
20
|
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/drain.sh",
|
|
22
|
-
"asyncRewake": true,
|
|
23
21
|
"timeout": 5
|
|
24
22
|
}
|
|
25
23
|
]
|
|
@@ -32,6 +30,7 @@
|
|
|
32
30
|
{
|
|
33
31
|
"type": "command",
|
|
34
32
|
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/drain.sh",
|
|
33
|
+
"asyncRewake": true,
|
|
35
34
|
"timeout": 5
|
|
36
35
|
}
|
|
37
36
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-comms",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.0",
|
|
4
4
|
"description": "Cross-harness communication mesh for LLM agents — rooms, DMs, presence, and real-time push delivery over TCP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@10.33.0",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"files": [
|
|
36
36
|
"dist",
|
|
37
37
|
".claude-plugin/",
|
|
38
|
+
"commands/",
|
|
38
39
|
"hooks/"
|
|
39
40
|
],
|
|
40
41
|
"bin": {
|