agent-comm-hub 0.1.7 → 0.1.9

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
@@ -63,6 +63,13 @@ npm install -D agent-comm-hub
63
63
  npx agent-comm-hub
64
64
  ```
65
65
 
66
+ Update later without a manual reinstall (files are replaced in place, so an
67
+ installed auto-start launcher keeps working; restart the hub afterwards):
68
+
69
+ ```bash
70
+ agent-comm-hub update
71
+ ```
72
+
66
73
  ### 2. Start the hub
67
74
 
68
75
  ```bash
@@ -93,11 +100,11 @@ agent-comm-hub setup
93
100
  ```
94
101
 
95
102
  `setup` incrementally merges the `agent-hub` MCP entry into every installed
96
- agent's own config (mcode, opencode, Kimi Code, Gemini CLI, Codex) and installs
97
- the English skill into `~/.agents/skills/` (the cross-agent standard) plus each
98
- agent's private skills dir. Only the `agent-hub` key is touched, every file is
99
- backed up first, and re-running is a no-op. Claude Code and DSH stay manual
100
- (see below).
103
+ agent's own config (mcode, opencode, Kimi Code, Gemini CLI, Codex, zcode) and
104
+ installs the English skill into `~/.agents/skills/` (the cross-agent standard)
105
+ plus each agent's private skills dir. Only the `agent-hub` key is touched,
106
+ every file is backed up first, and re-running is a no-op. Claude Code and DSH
107
+ stay manual (see below).
101
108
 
102
109
  **Registration is automatic**: once an agent session starts, the MCP handshake
103
110
  registers it with the hub (client name becomes the peer id) — no manual step.
@@ -117,9 +124,9 @@ Each agent gets **one MCP server entry** pointing at `http://127.0.0.1:18764/mcp
117
124
 
118
125
  **One-shot incremental sync** (recommended): `agents/install-all.ps1` merges the
119
126
  `agent-hub` entry into every installed agent's MCP config (mcode, opencode,
120
- Kimi Code, Gemini CLI, Codex) and installs the skill — it only touches the
121
- `agent-hub` key, backs up each file, and is idempotent. Claude Code and DSH are
122
- manual (below).
127
+ Kimi Code, Gemini CLI, Codex, zcode) and installs the skill — it only touches
128
+ the `agent-hub` key, backs up each file, and is idempotent. Claude Code and DSH
129
+ are manual (below).
123
130
 
124
131
  | Agent | Config file | Template | Skill location |
125
132
  |---|---|---|---|
@@ -128,6 +135,7 @@ manual (below).
128
135
  | Kimi Code | `~/.kimi-code/mcp.json` | [`agents/kimi-code/mcp-entry.json`](agents/kimi-code/mcp-entry.json) | `~/.kimi-code/skills/agent-comm-hub/SKILL.md` |
129
136
  | Gemini CLI | `~/.gemini/settings.json` | [`agents/gemini-cli/settings.json`](agents/gemini-cli/settings.json) | `~/.gemini/skills/agent-comm-hub/SKILL.md` |
130
137
  | Codex | `~/.codex/config.toml` | [`agents/codex/config.toml`](agents/codex/config.toml) | `~/.codex/skills/agent-comm-hub/SKILL.md` |
138
+ | zcode | `~/.zcode/cli/config.json` (`mcp.servers`) | [`agents/zcode/config.json`](agents/zcode/config.json) | `~/.zcode/skills/agent-comm-hub/SKILL.md` |
131
139
  | Claude Code | project `.mcp.json` (manual; `~/.claude.json` is never touched) | [`agents/claude-code/.mcp.json`](agents/claude-code/.mcp.json) | `~/.claude/skills/agent-comm-hub/SKILL.md` |
132
140
  | DeepSeek Harness (DSH) | profile `cordis.patch.yml` (manual) | [`agents/dsh/cordis.patch.yml`](agents/dsh/cordis.patch.yml) | `$DSH_HOME/skills/agent-comm-hub/SKILL.md` |
133
141
 
package/README.zh.md CHANGED
@@ -63,6 +63,12 @@ npm install -D agent-comm-hub
63
63
  npx agent-comm-hub
64
64
  ```
65
65
 
66
+ 之后想更新(免手动重装,文件原地替换,已装的自启动器不受影响;更新后重启 hub):
67
+
68
+ ```bash
69
+ agent-comm-hub update
70
+ ```
71
+
66
72
  ### 2. 启动 hub
67
73
 
68
74
  ```bash
@@ -90,7 +96,7 @@ agent-comm-hub setup
90
96
  ```
91
97
 
92
98
  `setup` 会把 `agent-hub` 的 MCP 条目**增量合并**进每个已安装 agent 的配置
93
- (mcode / opencode / kimi-code / gemini / codex),并把英文 SKILL 装到
99
+ (mcode / opencode / kimi-code / gemini / codex / zcode),并把英文 SKILL 装到
94
100
  `~/.agents/skills/`(跨 agent 标准位置)+ 各 agent 私有技能目录。只动
95
101
  `agent-hub` 这一个键、每个文件先备份、幂等可重跑。Claude Code 与 DSH 手动(见下)。
96
102
 
@@ -115,6 +121,7 @@ curl -X POST http://127.0.0.1:18764/mcp \
115
121
  | Kimi Code | `~/.kimi-code/mcp.json` | [`agents/kimi-code/mcp-entry.json`](agents/kimi-code/mcp-entry.json) | `~/.kimi-code/skills/agent-comm-hub/SKILL.md` |
116
122
  | Gemini CLI | `~/.gemini/settings.json` | [`agents/gemini-cli/settings.json`](agents/gemini-cli/settings.json) | `~/.gemini/skills/agent-comm-hub/SKILL.md` |
117
123
  | Codex | `~/.codex/config.toml` | [`agents/codex/config.toml`](agents/codex/config.toml) | `~/.codex/skills/agent-comm-hub/SKILL.md` |
124
+ | zcode | `~/.zcode/cli/config.json`(`mcp.servers`) | [`agents/zcode/config.json`](agents/zcode/config.json) | `~/.zcode/skills/agent-comm-hub/SKILL.md` |
118
125
  | Claude Code | 项目根 `.mcp.json`(手动;**绝不碰 `~/.claude.json`**——含凭据) | [`agents/claude-code/.mcp.json`](agents/claude-code/.mcp.json) | `~/.claude/skills/agent-comm-hub/SKILL.md` |
119
126
  | DeepSeek Harness (DSH) | profile `cordis.patch.yml`(手动) | [`agents/dsh/cordis.patch.yml`](agents/dsh/cordis.patch.yml) | `$DSH_HOME/skills/agent-comm-hub/SKILL.md` |
120
127
 
package/agents/README.md CHANGED
@@ -16,7 +16,7 @@ powershell -ExecutionPolicy Bypass -File install-all.ps1
16
16
  `install-all.ps1` 会把 `agent-hub` 条目**增量合并**进每个已安装 agent 的 MCP 配置
17
17
  (只动 `agent-hub` 这个键,其余内容原样保留;每个文件先备份、幂等可重跑),并同步
18
18
  英文 SKILL 到各 agent 的技能目录。覆盖:mcode / opencode / kimi-code / Gemini CLI /
19
- Codex(TOML 追加)。Claude Code 和 DSH 需手动(见下表)。
19
+ Codex(TOML 追加)/ zcode(`mcp.servers`)。Claude Code 和 DSH 需手动(见下表)。
20
20
 
21
21
  接入即自动上线(MCP 握手时用客户端名注册,无需手动 register);想要可读的 peerId
22
22
  可以让 agent 调一次 `bridge_register(peerId)`。
@@ -28,6 +28,7 @@ Codex(TOML 追加)。Claude Code 和 DSH 需手动(见下表)。
28
28
  | Kimi Code | `~/.kimi-code/mcp.json` | `kimi-code/mcp-entry.json`(`transport: "http"`,url 自动推断为 http) | `~/.kimi-code/skills/agent-comm-hub/SKILL.md` |
29
29
  | Gemini CLI | `~/.gemini/settings.json` | `gemini-cli/settings.json` | `~/.gemini/skills/agent-comm-hub/SKILL.md` |
30
30
  | Codex | `~/.codex/config.toml` | `codex/config.toml` | `~/.codex/skills/agent-comm-hub/SKILL.md` |
31
+ | zcode | `~/.zcode/cli/config.json` | `zcode/config.json` | `~/.zcode/skills/agent-comm-hub/SKILL.md` |
31
32
  | Claude Code | 项目根 `.mcp.json`(手动复制;**不碰 `~/.claude.json`**——含凭据且无法安全往返) | `claude-code/.mcp.json` | `~/.claude/skills/agent-comm-hub/SKILL.md` |
32
33
  | DeepSeek Harness (DSH) | profile `cordis.patch.yml`(手动合并) | `dsh/cordis.patch.yml`(用 `@deepseek-ai/dsh-mcp-client`,工具名为 `mcp__agent-hub__bridge_*`) | `$DSH_HOME/skills/agent-comm-hub/SKILL.md` |
33
34
 
@@ -11,6 +11,7 @@ Covered agents (auto-skipped when not installed):
11
11
  - Kimi Code ~/.kimi-code/mcp.json
12
12
  - Gemini CLI ~/.gemini/settings.json
13
13
  - Codex ~/.codex/config.toml (appends the section if missing)
14
+ - zcode ~/.zcode/cli/config.json (mcp.servers)
14
15
 
15
16
  Not covered (manual, documented in agents/README.md):
16
17
  - Claude Code -> project-level .mcp.json (copy agents/claude-code/.mcp.json)
@@ -69,11 +70,13 @@ function Merge-JsonServer($label, $file, $sectionName, $entry) {
69
70
  try {
70
71
  $doc = Read-Json $file
71
72
  if ($null -eq $doc) { Write-Step " ${label}: empty config (skipped)"; return }
72
- $servers = $doc.$sectionName
73
- if ($null -eq $servers) {
74
- # Incremental: create only the missing section, keep the rest untouched.
75
- $servers = [ordered]@{}
76
- $doc | Add-Member -NotePropertyName $sectionName -NotePropertyValue $servers -Force
73
+ # Resolve (creating when missing) a dotted section path like 'mcp.servers'.
74
+ $servers = $doc
75
+ foreach ($part in $sectionName.Split('.')) {
76
+ if ($null -eq $servers.$part) {
77
+ $servers | Add-Member -NotePropertyName $part -NotePropertyValue ([ordered]@{}) -Force
78
+ }
79
+ $servers = $servers.$part
77
80
  }
78
81
  $changed = $false
79
82
  if ($servers.PSObject.Properties.Name -contains $ServerName) {
@@ -161,6 +164,12 @@ if (Test-Path $codexFile) {
161
164
  Write-Step " codex: not installed ($codexFile missing, skipped)"
162
165
  }
163
166
 
167
+ # ---------- zcode: mcp.servers in ~/.zcode/cli/config.json
168
+ $zcodeEntry = [ordered]@{ enabled = $true; type = 'remote'; url = $Url }
169
+ Write-Step '- zcode'
170
+ Merge-JsonServer 'zcode' (Join-Path $userHome '.zcode\cli\config.json') 'mcp.servers' $zcodeEntry
171
+ Sync-Skill 'zcode' (Join-Path $userHome ".zcode\skills\$ServerName")
172
+
164
173
  # ---------- skills: cross-agent standard location + each agent's private dir
165
174
  $skillDirs = @(
166
175
  (Join-Path $userHome ".agents\skills\$ServerName"), # cross-agent standard
@@ -169,6 +178,7 @@ $skillDirs = @(
169
178
  (Join-Path $userHome ".kimi-code\skills\$ServerName"),
170
179
  (Join-Path $userHome ".gemini\skills\$ServerName"),
171
180
  (Join-Path $userHome ".codex\skills\$ServerName"),
181
+ (Join-Path $userHome ".zcode\skills\$ServerName"),
172
182
  (Join-Path $userHome ".claude\skills\$ServerName") # config is manual; skill still useful
173
183
  )
174
184
  foreach ($dir in $skillDirs) { Sync-Skill 'skill' $dir }
@@ -0,0 +1,11 @@
1
+ {
2
+ "mcp": {
3
+ "servers": {
4
+ "agent-hub": {
5
+ "enabled": true,
6
+ "type": "remote",
7
+ "url": "http://127.0.0.1:18764/mcp"
8
+ }
9
+ }
10
+ }
11
+ }
package/lib/cli.js CHANGED
@@ -710,7 +710,7 @@ function readBody(req) {
710
710
 
711
711
  // src/index.ts
712
712
  var SERVER_NAME = "agent-comm-hub";
713
- var SERVER_VERSION = "0.1.7";
713
+ var SERVER_VERSION = "0.1.9";
714
714
  var DEFAULT_HOST = "127.0.0.1";
715
715
  var DEFAULT_PORT = 18764;
716
716
  var DEFAULT_PATH = "/mcp";
@@ -806,15 +806,23 @@ async function backup(file) {
806
806
  await copyFile(file, bak);
807
807
  return bak;
808
808
  }
809
+ function resolveSection(doc, section) {
810
+ let node = doc;
811
+ for (const part of section.split(".")) {
812
+ let next = node[part];
813
+ if (next === void 0 || typeof next !== "object" || Array.isArray(next)) {
814
+ next = {};
815
+ node[part] = next;
816
+ }
817
+ node = next;
818
+ }
819
+ return node;
820
+ }
809
821
  async function mergeJsonServer(file, section, entry, opts) {
810
822
  if (!existsSync(file)) return "skipped";
811
823
  const doc = await readJson(file);
812
824
  if (doc === null) return "skipped";
813
- let servers = doc[section];
814
- if (servers === void 0 || typeof servers !== "object" || Array.isArray(servers)) {
815
- servers = {};
816
- doc[section] = servers;
817
- }
825
+ const servers = resolveSection(doc, section);
818
826
  const has = Object.prototype.hasOwnProperty.call(servers, opts.serverName);
819
827
  if (opts.remove) {
820
828
  if (!has) return "absent";
@@ -896,7 +904,8 @@ async function runSetup(options = {}) {
896
904
  { label: "mcode", file: join(home, ".minimax", "mcp", "mcp.json"), section: "mcpServers", entry: { url, type: "streamable-http", enabled: true, configured: true, timeout: 12e4, description: "agent-comm-hub: talk to every other agent connected to the hub." } },
897
905
  { label: "opencode", file: join(home, ".config", "opencode", "opencode.json"), section: "mcp", entry: { type: "remote", url, enabled: true } },
898
906
  { label: "kimi-code", file: join(home, ".kimi-code", "mcp.json"), section: "mcpServers", entry: { transport: "http", url, startupTimeoutMs: 3e4, toolTimeoutMs: 12e4 } },
899
- { label: "gemini-cli", file: join(home, ".gemini", "settings.json"), section: "mcpServers", entry: { type: "http", url } }
907
+ { label: "gemini-cli", file: join(home, ".gemini", "settings.json"), section: "mcpServers", entry: { type: "http", url } },
908
+ { label: "zcode", file: join(home, ".zcode", "cli", "config.json"), section: "mcp.servers", entry: { type: "remote", url, enabled: true } }
900
909
  ];
901
910
  for (const target of jsonTargets) {
902
911
  try {
@@ -923,6 +932,7 @@ async function runSetup(options = {}) {
923
932
  join(home, ".kimi-code", "skills", serverName),
924
933
  join(home, ".gemini", "skills", serverName),
925
934
  join(home, ".codex", "skills", serverName),
935
+ join(home, ".zcode", "skills", serverName),
926
936
  join(home, ".claude", "skills", serverName)
927
937
  // config is manual; skill still useful
928
938
  ];
@@ -942,9 +952,9 @@ async function runSetup(options = {}) {
942
952
  // src/ops.ts
943
953
  import { execFileSync } from "node:child_process";
944
954
  import { request } from "node:http";
945
- import { mkdirSync, rmSync, writeFileSync } from "node:fs";
955
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
946
956
  import { homedir as homedir2 } from "node:os";
947
- import { join as join2 } from "node:path";
957
+ import { dirname as dirname2, join as join2 } from "node:path";
948
958
  import { fileURLToPath as fileURLToPath2 } from "node:url";
949
959
  async function runStatus(options = {}) {
950
960
  const host = options.host ?? "127.0.0.1";
@@ -994,6 +1004,32 @@ async function runStatus(options = {}) {
994
1004
  return { ...notRunning, error: error.message };
995
1005
  }
996
1006
  }
1007
+ function runUpdate() {
1008
+ const messages = [];
1009
+ const pkgFile = join2(dirname2(fileURLToPath2(import.meta.url)), "..", "package.json");
1010
+ const readVersion = () => {
1011
+ try {
1012
+ return JSON.parse(readFileSync(pkgFile, "utf8")).version ?? "?";
1013
+ } catch {
1014
+ return "?";
1015
+ }
1016
+ };
1017
+ try {
1018
+ const before = readVersion();
1019
+ messages.push(`current version: ${before}`);
1020
+ const npmBin = process.platform === "win32" ? "npm.cmd" : "npm";
1021
+ const out = execFileSync(npmBin, ["install", "-g", "agent-comm-hub@latest"], { encoding: "utf8", windowsHide: true, shell: process.platform === "win32" });
1022
+ const tail = out.trim().split(/\r?\n/).slice(-3).filter(Boolean).join(" | ");
1023
+ if (tail) messages.push(tail);
1024
+ const after = readVersion();
1025
+ if (after === before) messages.push(`already up to date (v${after})`);
1026
+ else messages.push(`updated: v${before} -> v${after}`);
1027
+ messages.push("restart the hub (agent-comm-hub) to pick up the new version");
1028
+ return { ok: true, messages };
1029
+ } catch (error) {
1030
+ return { ok: false, messages: [`update failed: ${error.message}`] };
1031
+ }
1032
+ }
997
1033
  function cliPath() {
998
1034
  return fileURLToPath2(import.meta.url);
999
1035
  }
@@ -1133,6 +1169,9 @@ Usage:
1133
1169
  one-shot auto-start (Windows Run
1134
1170
  key + hidden VBS launcher, no admin;
1135
1171
  Linux systemd; --dry-run prints)
1172
+ agent-comm-hub update self-update from the npm registry
1173
+ (files updated in place; restart
1174
+ the hub afterwards)
1136
1175
 
1137
1176
  Hub options:
1138
1177
  --host <addr> Bind address (default 127.0.0.1)
@@ -1221,6 +1260,20 @@ try {
1221
1260
  }
1222
1261
  process.exit(0);
1223
1262
  }
1263
+ if (command === "update") {
1264
+ const args2 = parseArgs(rest);
1265
+ if (args2["--help"] || args2["-h"]) {
1266
+ printHelp();
1267
+ process.exit(0);
1268
+ }
1269
+ const result = runUpdate();
1270
+ for (const message of result.messages) log.info(message);
1271
+ if (!result.ok) {
1272
+ console.error("update: failed \u2014 see messages above");
1273
+ process.exit(1);
1274
+ }
1275
+ process.exit(0);
1276
+ }
1224
1277
  const args = parseArgs(argv);
1225
1278
  if (args["--help"] || args["-h"]) {
1226
1279
  printHelp();
package/lib/index.js CHANGED
@@ -713,7 +713,7 @@ function readBody(req) {
713
713
 
714
714
  // src/index.ts
715
715
  var SERVER_NAME = "agent-comm-hub";
716
- var SERVER_VERSION = "0.1.7";
716
+ var SERVER_VERSION = "0.1.9";
717
717
  var DEFAULT_HOST = "127.0.0.1";
718
718
  var DEFAULT_PORT = 18764;
719
719
  var DEFAULT_PATH = "/mcp";
package/lib/setup.js CHANGED
@@ -31,15 +31,23 @@ async function backup(file) {
31
31
  await copyFile(file, bak);
32
32
  return bak;
33
33
  }
34
+ function resolveSection(doc, section) {
35
+ let node = doc;
36
+ for (const part of section.split(".")) {
37
+ let next = node[part];
38
+ if (next === void 0 || typeof next !== "object" || Array.isArray(next)) {
39
+ next = {};
40
+ node[part] = next;
41
+ }
42
+ node = next;
43
+ }
44
+ return node;
45
+ }
34
46
  async function mergeJsonServer(file, section, entry, opts) {
35
47
  if (!existsSync(file)) return "skipped";
36
48
  const doc = await readJson(file);
37
49
  if (doc === null) return "skipped";
38
- let servers = doc[section];
39
- if (servers === void 0 || typeof servers !== "object" || Array.isArray(servers)) {
40
- servers = {};
41
- doc[section] = servers;
42
- }
50
+ const servers = resolveSection(doc, section);
43
51
  const has = Object.prototype.hasOwnProperty.call(servers, opts.serverName);
44
52
  if (opts.remove) {
45
53
  if (!has) return "absent";
@@ -121,7 +129,8 @@ async function runSetup(options = {}) {
121
129
  { label: "mcode", file: join(home, ".minimax", "mcp", "mcp.json"), section: "mcpServers", entry: { url, type: "streamable-http", enabled: true, configured: true, timeout: 12e4, description: "agent-comm-hub: talk to every other agent connected to the hub." } },
122
130
  { label: "opencode", file: join(home, ".config", "opencode", "opencode.json"), section: "mcp", entry: { type: "remote", url, enabled: true } },
123
131
  { label: "kimi-code", file: join(home, ".kimi-code", "mcp.json"), section: "mcpServers", entry: { transport: "http", url, startupTimeoutMs: 3e4, toolTimeoutMs: 12e4 } },
124
- { label: "gemini-cli", file: join(home, ".gemini", "settings.json"), section: "mcpServers", entry: { type: "http", url } }
132
+ { label: "gemini-cli", file: join(home, ".gemini", "settings.json"), section: "mcpServers", entry: { type: "http", url } },
133
+ { label: "zcode", file: join(home, ".zcode", "cli", "config.json"), section: "mcp.servers", entry: { type: "remote", url, enabled: true } }
125
134
  ];
126
135
  for (const target of jsonTargets) {
127
136
  try {
@@ -148,6 +157,7 @@ async function runSetup(options = {}) {
148
157
  join(home, ".kimi-code", "skills", serverName),
149
158
  join(home, ".gemini", "skills", serverName),
150
159
  join(home, ".codex", "skills", serverName),
160
+ join(home, ".zcode", "skills", serverName),
151
161
  join(home, ".claude", "skills", serverName)
152
162
  // config is manual; skill still useful
153
163
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-comm-hub",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
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
5
  "keywords": [
6
6
  "mcp",