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 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 100)
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
+ | ![agent-comm-hub-app (EN)](assets/ach-en.png) | ![agent-comm-hub-app (CN)](assets/ach-cn.png) |
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> 保留的历史条数(默认 100
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
+ | ![agent-comm-hub-app (CN)](assets/ach-cn.png) | ![agent-comm-hub-app (EN)](assets/ach-en.png) |
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: "Recent messages involving you (newest first); pass `peer` to inspect another peer's conversation. Use to refresh context after a reconnect.",
844
- inputSchema: schema({ peer: optStr("PeerId whose conversation to inspect; default: yourself."), limit: int("How many messages to return (default 20).") }),
845
- handler: wrap(true, async (args, peer) => ({ messages: hub.history(args.peer === void 0 ? peer : String(args.peer), Math.min(args.limit === void 0 ? 20 : Number(args.limit), 100)).map(present) }))
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.4.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
- historyLimit: 100,
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 100)
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: "Recent messages involving you (newest first); pass `peer` to inspect another peer's conversation. Use to refresh context after a reconnect.",
847
- inputSchema: schema({ peer: optStr("PeerId whose conversation to inspect; default: yourself."), limit: int("How many messages to return (default 20).") }),
848
- handler: wrap(true, async (args, peer) => ({ messages: hub.history(args.peer === void 0 ? peer : String(args.peer), Math.min(args.limit === void 0 ? 20 : Number(args.limit), 100)).map(present) }))
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.4.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
- historyLimit: 100,
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.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
- "prepublishOnly": "pnpm run test && pnpm run build",
44
- "prepare": "pnpm run build"
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
+ }