agent-comm-hub 0.4.0 → 0.5.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 +31 -1
- package/README.zh.md +31 -1
- package/agents/SKILL.md +3 -1
- package/assets/ach-cn.png +0 -0
- package/assets/ach-en.png +0 -0
- package/lib/cli.js +19 -6
- package/lib/index.js +18 -5
- package/package.json +44 -46
package/README.md
CHANGED
|
@@ -309,7 +309,7 @@ agent-comm-hub service install|uninstall [options] one-shot auto-start
|
|
|
309
309
|
--port <n> Listen port (default 18764)
|
|
310
310
|
--path <p> MCP endpoint path (default /mcp)
|
|
311
311
|
--max-queue <n> Queued messages per peer before dropping oldest (default 200)
|
|
312
|
-
--history-limit <n> Retained history messages (default
|
|
312
|
+
--history-limit <n> Retained history messages (default 1000)
|
|
313
313
|
--wait-timeout-ms <n> Long-poll ceiling for bridge_wait (default 60000)
|
|
314
314
|
--default-wait-ms <n> bridge_wait default budget (default 30000)
|
|
315
315
|
--connected-window-ms <n> Peer counts as active within this window (default 30000)
|
|
@@ -397,6 +397,36 @@ pnpm run build # esbuild → lib/{cli,index,setup}.js (zero deps)
|
|
|
397
397
|
pnpm pack # build + npm pack (publishing artifact)
|
|
398
398
|
```
|
|
399
399
|
|
|
400
|
+
## Desktop GUI
|
|
401
|
+
|
|
402
|
+
A companion desktop GUI is shipped as a separate npm package: **`agent-comm-hub-app`**. It is a standalone Tauri 2 + React app, lives in `app/`, and depends on the MCP HTTP API rather than on this package's source. It does NOT relax the `dependencies: {}` constraint of the main package — workspace isolation is enforced via `app/pnpm-workspace.yaml`.
|
|
403
|
+
|
|
404
|
+
| English | 简体中文 |
|
|
405
|
+
|---|---|
|
|
406
|
+
|  |  |
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
cd app
|
|
410
|
+
pnpm install
|
|
411
|
+
pnpm tauri:dev # dev with hot reload
|
|
412
|
+
pnpm tauri:build # produces NSIS / MSI / dmg / AppImage / deb installers
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Highlights:
|
|
416
|
+
|
|
417
|
+
- **Hub lifecycle in one window**: auto-spawn on launch (4-tier PATH fallback), start / stop / restart, live log panel with stderr filter + expandable viewer, and an external-hub reuse mode with health probing
|
|
418
|
+
- **Real-time messaging**: `bridge_wait` long-poll keeps the UI live; optimistic send shows your messages instantly; `/history` merges hub memory with the SQLite archive (survives hub restarts)
|
|
419
|
+
- **Peer conversations** (PRD US-2): click any peer to view its full conversation, not just yours; unread badges per peer
|
|
420
|
+
- **Message details**: raw JSON view, task prompt/context/deliverable, ack state-machine timeline
|
|
421
|
+
- **Slash commands**: `/peers /broadcast /history /clear /help` — from the palette or typed directly
|
|
422
|
+
- **Markdown rendering** with rehype-sanitize, multi-peer cc, drag-drop attachments (≤5 MB), virtual scrolling
|
|
423
|
+
- **Theme system**: dark / light / system-follow, brand-blue palette, persisted
|
|
424
|
+
- **Frameless window**: custom titlebar (drag region, double-click maximize), close dialog with minimize-to-tray / quit / cancel
|
|
425
|
+
- **Hub tools in Settings**: install / version / check update / update the hub CLI, one-click `setup` to detect local agents and install the SKILL + MCP config, auto-start service install
|
|
426
|
+
- **System tray** with brand logo and status tooltip; i18n (zh-CN default, en-US)
|
|
427
|
+
|
|
428
|
+
See `app/README.md` for the full feature list and architecture.
|
|
429
|
+
|
|
400
430
|
Tests cover registration, duplicate rejection, chat routing, sender-filtered waits, task+ack routing back to the sender, broadcast, status/peers/history, unregister/re-register, and error paths.
|
|
401
431
|
|
|
402
432
|
## Troubleshooting
|
package/README.zh.md
CHANGED
|
@@ -220,7 +220,7 @@ agent-comm-hub service install|uninstall [options] 一键自启
|
|
|
220
220
|
--port <n> 端口(默认 18764)
|
|
221
221
|
--path <p> MCP 路径(默认 /mcp)
|
|
222
222
|
--max-queue <n> 每 peer 队列上限,溢出丢最旧(默认 200)
|
|
223
|
-
--history-limit <n> 保留的历史条数(默认
|
|
223
|
+
--history-limit <n> 保留的历史条数(默认 1000)
|
|
224
224
|
--wait-timeout-ms <n> bridge_wait 长轮询上限(默认 60000)
|
|
225
225
|
--default-wait-ms <n> bridge_wait 默认预算(默认 30000)
|
|
226
226
|
--connected-window-ms <n> 活跃窗口(默认 30000)
|
|
@@ -273,6 +273,36 @@ pnpm run build # esbuild → lib/{cli,index,setup}.js(零依赖)
|
|
|
273
273
|
pnpm pack # 构建 + npm pack(发布产物)
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
+
## 桌面端 GUI
|
|
277
|
+
|
|
278
|
+
配套桌面端是另一个独立 npm 包 **`agent-comm-hub-app`**,在 `app/` 目录,Tauri 2 + React。它只走 hub 的 MCP / HTTP API,不引入主仓源码,也不会动 `dependencies: {}` 这个零依赖约束 —— 通过 `app/pnpm-workspace.yaml` 做工作区隔离。
|
|
279
|
+
|
|
280
|
+
| 简体中文 | English |
|
|
281
|
+
|---|---|
|
|
282
|
+
|  |  |
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
cd app
|
|
286
|
+
pnpm install
|
|
287
|
+
pnpm tauri:dev # 开发模式 (HMR)
|
|
288
|
+
pnpm tauri:build # 三平台安装包 (NSIS / MSI / dmg / AppImage / deb)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
主要能力:
|
|
292
|
+
|
|
293
|
+
- **一站式 Hub 生命周期**:启动自动拉起 hub (4-tier PATH 兜底)、启停/重启、实时日志面板 (stderr 过滤 + 放大查看),外部 hub 复用模式带健康探测
|
|
294
|
+
- **实时消息**:`bridge_wait` 长轮询保持界面实时;发送即乐观显示;`/history` 合并 hub 内存与 SQLite 存档 (重启不丢)
|
|
295
|
+
- **会话视角** (PRD US-2):点击任意 peer 查看它的完整会话;per-peer 未读徽章
|
|
296
|
+
- **消息详情**:原始 JSON、task prompt/context/deliverable、ack 状态机时间线
|
|
297
|
+
- **斜杠命令**:`/peers /broadcast /history /clear /help` —— 面板选择或直接输入
|
|
298
|
+
- **Markdown 渲染** + rehype-sanitize、多会话方 cc、拖拽附件 (≤5 MB)、虚拟滚动
|
|
299
|
+
- **主题系统**:深色 / 浅色 / 跟随系统,品牌蓝主题,持久化
|
|
300
|
+
- **无边框窗口**:自绘标题栏 (拖拽区、双击最大化),关闭弹窗三选一 (最小化到托盘 / 退出 / 取消)
|
|
301
|
+
- **设置页 Hub 工具**:安装 / 版本 / 检查更新 / 更新 hub CLI,一键 `setup` 检测本地 agent 并安装 SKILL + MCP 配置,开机自启服务
|
|
302
|
+
- **系统托盘** (品牌 logo + 状态 tooltip);i18n (简中默认 + 英文)
|
|
303
|
+
|
|
304
|
+
详见 `app/README.zh.md`。
|
|
305
|
+
|
|
276
306
|
## 故障排查
|
|
277
307
|
|
|
278
308
|
| 症状 | 原因 / 解决 |
|
package/agents/SKILL.md
CHANGED
|
@@ -34,7 +34,9 @@ Optional: call `bridge_register(peerId)` to claim a readable id
|
|
|
34
34
|
30 s; loop it to hold a real-time conversation).
|
|
35
35
|
- `bridge_poll(from?)` — non-blocking drain of every queued message.
|
|
36
36
|
- `bridge_status()` / `bridge_peers()` — hub health and who is online.
|
|
37
|
-
- `bridge_history(peer?, limit?)` — recent messages (newest first).
|
|
37
|
+
- `bridge_history(peer?, limit?)` — recent messages (newest first). `peer`
|
|
38
|
+
defaults to you; pass another peer's id to read their conversation, or
|
|
39
|
+
`"all"` for the unfiltered tail across every peer.
|
|
38
40
|
|
|
39
41
|
## When to use
|
|
40
42
|
|
|
Binary file
|
|
Binary file
|
package/lib/cli.js
CHANGED
|
@@ -512,6 +512,12 @@ var AgentHub = class {
|
|
|
512
512
|
const filtered = this.historyRing.filter((message) => message.from === peerId || message.to === peerId || message.to === BROADCAST);
|
|
513
513
|
return filtered.slice(-Math.max(0, limit)).reverse();
|
|
514
514
|
}
|
|
515
|
+
/** Most recent messages across every peer, unfiltered (newest first).
|
|
516
|
+
* Backs `bridge_history { peer: "all" }` — lets an archiver (the desktop
|
|
517
|
+
* app) capture peer-to-peer traffic it is not a party of. */
|
|
518
|
+
historyAll(limit) {
|
|
519
|
+
return this.historyRing.slice(-Math.max(0, limit)).reverse();
|
|
520
|
+
}
|
|
515
521
|
/**
|
|
516
522
|
* Live summary for the status tool. `livePeers` (sessions with a live SSE
|
|
517
523
|
* stream) count as connected even without recent tool activity.
|
|
@@ -840,9 +846,13 @@ function hubTools(hub, registry, options) {
|
|
|
840
846
|
},
|
|
841
847
|
{
|
|
842
848
|
name: "bridge_history",
|
|
843
|
-
description:
|
|
844
|
-
inputSchema: schema({ peer: optStr(
|
|
845
|
-
handler: wrap(true, async (args, peer) =>
|
|
849
|
+
description: 'Recent messages involving you (newest first); pass `peer` to inspect another peer\'s conversation, or `peer: "all"` for the unfiltered tail across every peer. Use to refresh context after a reconnect.',
|
|
850
|
+
inputSchema: schema({ peer: optStr('PeerId whose conversation to inspect; "all" = every peer; default: yourself.'), limit: int("How many messages to return (default 20).") }),
|
|
851
|
+
handler: wrap(true, async (args, peer) => {
|
|
852
|
+
const limit = Math.min(args.limit === void 0 ? 20 : Number(args.limit), 1e3);
|
|
853
|
+
const messages = args.peer === "all" ? hub.historyAll(limit) : hub.history(args.peer === void 0 ? peer : String(args.peer), limit);
|
|
854
|
+
return { messages: messages.map(present) };
|
|
855
|
+
})
|
|
846
856
|
},
|
|
847
857
|
// ---- herdr control tools ------------------------------------------
|
|
848
858
|
// These type into real agent terminals via the herdr runtime. They are
|
|
@@ -1334,7 +1344,7 @@ function readBody(req) {
|
|
|
1334
1344
|
|
|
1335
1345
|
// src/index.ts
|
|
1336
1346
|
var SERVER_NAME = "agent-comm-hub";
|
|
1337
|
-
var SERVER_VERSION = "0.
|
|
1347
|
+
var SERVER_VERSION = "0.5.0";
|
|
1338
1348
|
var DEFAULT_HOST = "127.0.0.1";
|
|
1339
1349
|
var DEFAULT_PORT = 18764;
|
|
1340
1350
|
var DEFAULT_PATH = "/mcp";
|
|
@@ -1343,7 +1353,10 @@ var DEFAULT_CONFIG = {
|
|
|
1343
1353
|
port: DEFAULT_PORT,
|
|
1344
1354
|
path: DEFAULT_PATH,
|
|
1345
1355
|
maxQueue: 200,
|
|
1346
|
-
|
|
1356
|
+
// 100 was too small to survive a long multi-agent session: the ring is the
|
|
1357
|
+
// only archive source until the desktop app persists it to SQLite, and a
|
|
1358
|
+
// night of agent-to-agent chatter evicts everything within minutes.
|
|
1359
|
+
historyLimit: 1e3,
|
|
1347
1360
|
waitTimeoutMs: 6e4,
|
|
1348
1361
|
defaultWaitMs: 3e4,
|
|
1349
1362
|
connectedWindowMs: 3e4,
|
|
@@ -2130,7 +2143,7 @@ Hub options:
|
|
|
2130
2143
|
--port <n> Listen port (default 18764)
|
|
2131
2144
|
--path <p> MCP endpoint path (default /mcp)
|
|
2132
2145
|
--max-queue <n> Queued messages per peer before dropping oldest (default 200)
|
|
2133
|
-
--history-limit <n> Retained history messages (default
|
|
2146
|
+
--history-limit <n> Retained history messages (default 1000)
|
|
2134
2147
|
--wait-timeout-ms <n> Long-poll ceiling for bridge_wait (default 60000)
|
|
2135
2148
|
--default-wait-ms <n> bridge_wait default budget (default 30000)
|
|
2136
2149
|
--connected-window-ms <n> Peer counts as active within this window (default 30000)
|
package/lib/index.js
CHANGED
|
@@ -515,6 +515,12 @@ var AgentHub = class {
|
|
|
515
515
|
const filtered = this.historyRing.filter((message) => message.from === peerId || message.to === peerId || message.to === BROADCAST);
|
|
516
516
|
return filtered.slice(-Math.max(0, limit)).reverse();
|
|
517
517
|
}
|
|
518
|
+
/** Most recent messages across every peer, unfiltered (newest first).
|
|
519
|
+
* Backs `bridge_history { peer: "all" }` — lets an archiver (the desktop
|
|
520
|
+
* app) capture peer-to-peer traffic it is not a party of. */
|
|
521
|
+
historyAll(limit) {
|
|
522
|
+
return this.historyRing.slice(-Math.max(0, limit)).reverse();
|
|
523
|
+
}
|
|
518
524
|
/**
|
|
519
525
|
* Live summary for the status tool. `livePeers` (sessions with a live SSE
|
|
520
526
|
* stream) count as connected even without recent tool activity.
|
|
@@ -843,9 +849,13 @@ function hubTools(hub, registry, options) {
|
|
|
843
849
|
},
|
|
844
850
|
{
|
|
845
851
|
name: "bridge_history",
|
|
846
|
-
description:
|
|
847
|
-
inputSchema: schema({ peer: optStr(
|
|
848
|
-
handler: wrap(true, async (args, peer) =>
|
|
852
|
+
description: 'Recent messages involving you (newest first); pass `peer` to inspect another peer\'s conversation, or `peer: "all"` for the unfiltered tail across every peer. Use to refresh context after a reconnect.',
|
|
853
|
+
inputSchema: schema({ peer: optStr('PeerId whose conversation to inspect; "all" = every peer; default: yourself.'), limit: int("How many messages to return (default 20).") }),
|
|
854
|
+
handler: wrap(true, async (args, peer) => {
|
|
855
|
+
const limit = Math.min(args.limit === void 0 ? 20 : Number(args.limit), 1e3);
|
|
856
|
+
const messages = args.peer === "all" ? hub.historyAll(limit) : hub.history(args.peer === void 0 ? peer : String(args.peer), limit);
|
|
857
|
+
return { messages: messages.map(present) };
|
|
858
|
+
})
|
|
849
859
|
},
|
|
850
860
|
// ---- herdr control tools ------------------------------------------
|
|
851
861
|
// These type into real agent terminals via the herdr runtime. They are
|
|
@@ -1337,7 +1347,7 @@ function readBody(req) {
|
|
|
1337
1347
|
|
|
1338
1348
|
// src/index.ts
|
|
1339
1349
|
var SERVER_NAME = "agent-comm-hub";
|
|
1340
|
-
var SERVER_VERSION = "0.
|
|
1350
|
+
var SERVER_VERSION = "0.5.0";
|
|
1341
1351
|
var DEFAULT_HOST = "127.0.0.1";
|
|
1342
1352
|
var DEFAULT_PORT = 18764;
|
|
1343
1353
|
var DEFAULT_PATH = "/mcp";
|
|
@@ -1346,7 +1356,10 @@ var DEFAULT_CONFIG = {
|
|
|
1346
1356
|
port: DEFAULT_PORT,
|
|
1347
1357
|
path: DEFAULT_PATH,
|
|
1348
1358
|
maxQueue: 200,
|
|
1349
|
-
|
|
1359
|
+
// 100 was too small to survive a long multi-agent session: the ring is the
|
|
1360
|
+
// only archive source until the desktop app persists it to SQLite, and a
|
|
1361
|
+
// night of agent-to-agent chatter evicts everything within minutes.
|
|
1362
|
+
historyLimit: 1e3,
|
|
1350
1363
|
waitTimeoutMs: 6e4,
|
|
1351
1364
|
defaultWaitMs: 3e4,
|
|
1352
1365
|
connectedWindowMs: 3e4,
|
package/package.json
CHANGED
|
@@ -1,46 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agent-comm-hub",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Generic multi-peer MCP hub: any MCP-capable agent (MiniMax Code, Claude Code, opencode, Codex, Gemini CLI, DSH, ...) connects to one local streamable-http endpoint and they chat, delegate tasks, and acknowledge in real time",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"mcp",
|
|
7
|
-
"agent",
|
|
8
|
-
"hub",
|
|
9
|
-
"multi-agent",
|
|
10
|
-
"communication",
|
|
11
|
-
"streamable-http",
|
|
12
|
-
"cli",
|
|
13
|
-
"ai"
|
|
14
|
-
],
|
|
15
|
-
"author": "agent-comm-hub contributors",
|
|
16
|
-
"type": "module",
|
|
17
|
-
"main": "lib/index.js",
|
|
18
|
-
"bin": {
|
|
19
|
-
"agent-comm-hub": "lib/cli.js"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"lib",
|
|
23
|
-
"agents",
|
|
24
|
-
"assets",
|
|
25
|
-
"README.md"
|
|
26
|
-
],
|
|
27
|
-
"engines": {
|
|
28
|
-
"node": ">=22"
|
|
29
|
-
},
|
|
30
|
-
"license": "MIT",
|
|
31
|
-
"dependencies": {},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@types/node": "^22.0.0",
|
|
34
|
-
"esbuild": "^0.25.0",
|
|
35
|
-
"typescript": "^5.8.0"
|
|
36
|
-
},
|
|
37
|
-
"scripts": {
|
|
38
|
-
"build": "esbuild src/cli.ts --bundle --platform=node --format=esm --outfile=lib/cli.js && esbuild src/index.ts --bundle --platform=node --format=esm --outfile=lib/index.js && esbuild src/setup.ts --bundle --platform=node --format=esm --outfile=lib/setup.js",
|
|
39
|
-
"build:test": "esbuild test/entry.ts --bundle --platform=node --format=esm --outfile=test/entry.mjs && esbuild test/setup-entry.ts --bundle --platform=node --format=esm --outfile=test/setup-entry.mjs && esbuild test/ops-entry.ts --bundle --platform=node --format=esm --outfile=test/ops-entry.mjs && esbuild test/herdr-entry.ts --bundle --platform=node --format=esm --outfile=test/herdr-entry.mjs && esbuild test/discover-entry.ts --bundle --platform=node --format=esm --outfile=test/discover-entry.mjs",
|
|
40
|
-
"typecheck": "tsc --noEmit",
|
|
41
|
-
"test": "pnpm run build:test && node test/smoke.mjs && node test/setup.mjs && node test/ops.mjs && node test/herdr.mjs && node test/discover.mjs",
|
|
42
|
-
"pack": "pnpm run build && pnpm pack"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-comm-hub",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Generic multi-peer MCP hub: any MCP-capable agent (MiniMax Code, Claude Code, opencode, Codex, Gemini CLI, DSH, ...) connects to one local streamable-http endpoint and they chat, delegate tasks, and acknowledge in real time",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"agent",
|
|
8
|
+
"hub",
|
|
9
|
+
"multi-agent",
|
|
10
|
+
"communication",
|
|
11
|
+
"streamable-http",
|
|
12
|
+
"cli",
|
|
13
|
+
"ai"
|
|
14
|
+
],
|
|
15
|
+
"author": "agent-comm-hub contributors",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"bin": {
|
|
19
|
+
"agent-comm-hub": "lib/cli.js"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"lib",
|
|
23
|
+
"agents",
|
|
24
|
+
"assets",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=22"
|
|
29
|
+
},
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"esbuild": "^0.25.0",
|
|
35
|
+
"typescript": "^5.8.0"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "esbuild src/cli.ts --bundle --platform=node --format=esm --outfile=lib/cli.js && esbuild src/index.ts --bundle --platform=node --format=esm --outfile=lib/index.js && esbuild src/setup.ts --bundle --platform=node --format=esm --outfile=lib/setup.js",
|
|
39
|
+
"build:test": "esbuild test/entry.ts --bundle --platform=node --format=esm --outfile=test/entry.mjs && esbuild test/setup-entry.ts --bundle --platform=node --format=esm --outfile=test/setup-entry.mjs && esbuild test/ops-entry.ts --bundle --platform=node --format=esm --outfile=test/ops-entry.mjs && esbuild test/herdr-entry.ts --bundle --platform=node --format=esm --outfile=test/herdr-entry.mjs && esbuild test/discover-entry.ts --bundle --platform=node --format=esm --outfile=test/discover-entry.mjs",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "pnpm run build:test && node test/smoke.mjs && node test/setup.mjs && node test/ops.mjs && node test/herdr.mjs && node test/discover.mjs",
|
|
42
|
+
"pack": "pnpm run build && pnpm pack"
|
|
43
|
+
}
|
|
44
|
+
}
|