agentsmesh 0.13.0 → 0.15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1edb936: Homebrew tap and standalone-binary distribution. `brew tap samplexbro/agentsmesh && brew install agentsmesh` installs from a Homebrew formula auto-rendered against the published npm tarball; `curl -fsSL https://github.com/sampleXbro/agentsmesh/releases/latest/download/install.sh | sh` downloads a Node-free Bun-compiled binary for macOS (arm64/x64) and Linux (arm64/x64), verifies SHA256, installs to `~/.agentsmesh/bin`, and adds it to PATH for zsh, bash, and fish. The release workflow builds binaries for every supported platform on each `master` push, attaches them to a GitHub Release alongside `SHA256SUMS`, and pushes the formula to the tap repo; `workflow_dispatch` re-runs rebuild assets against an existing tag. Installer fails closed on missing/unverifiable checksums and rejects shell-unsafe `AGENTSMESH_INSTALL` paths.
8
+
9
+ ## 0.14.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 16a7f0d: Self-serve MCP server. `agentsmesh mcp` boots a stdio MCP server exposing 41 tools and 16 resources for canonical config introspection, CRUD on rules/commands/agents/skills, settings management (config/mcp-servers/permissions/hooks/ignore), capability matrix queries, and orchestration verbs (generate/lint/check/diff/import/convert). Auto-registered in `.agentsmesh/mcp.json` on `init` and `import`. See the MCP server reference page.
14
+
3
15
  ## 0.13.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -24,6 +24,31 @@ AI coding assistants now ship with their own configuration formats — `CLAUDE.m
24
24
 
25
25
  ---
26
26
 
27
+ ## Install
28
+
29
+ ### npm (recommended for Node.js projects)
30
+
31
+ ```bash
32
+ npm install -g agentsmesh
33
+ ```
34
+
35
+ ### Homebrew (macOS / Linux)
36
+
37
+ ```bash
38
+ brew tap samplexbro/agentsmesh
39
+ brew install agentsmesh
40
+ ```
41
+
42
+ ### Standalone binary (no Node.js required)
43
+
44
+ ```bash
45
+ curl -fsSL https://github.com/sampleXbro/agentsmesh/releases/latest/download/install.sh | sh
46
+ ```
47
+
48
+ Or download a binary directly from [GitHub Releases](https://github.com/sampleXbro/agentsmesh/releases/latest).
49
+
50
+ ---
51
+
27
52
  ## Before / After
28
53
 
29
54
  **Before — fragmented assistant-native config in one repo:**
@@ -64,7 +89,7 @@ The native files above are still emitted — AgentsMesh writes them for you from
64
89
 
65
90
  ## 60-second quickstart
66
91
 
67
- Requires Node.js 20+. Works on Linux, macOS, and Windows (native, not WSL).
92
+ Works on Linux, macOS, and Windows. The `npx` commands below require Node.js 20+; see [Install](#install) for alternatives that don't need Node.js.
68
93
 
69
94
  ```bash
70
95
  npx agentsmesh init # scaffold .agentsmesh/ + agentsmesh.yaml
@@ -133,6 +158,7 @@ AgentsMesh currently generates native config for every major AI coding assistant
133
158
  - **Team-safe collaboration** — `agentsmesh check` is a CI drift gate against `.agentsmesh/.lock`, `agentsmesh diff` previews changes, `agentsmesh merge` rebuilds the lock after three-way Git conflicts, and `lock_features` + per-feature `strategy` prevent accidental overrides.
134
159
  - **Global mode** — `~/.agentsmesh/` syncs personal AI config to `~/.claude/`, `~/.cursor/`, `~/.codex/`, `~/.windsurf/`, and other user-level folders. Every CLI command accepts `--global`.
135
160
  - **Extensible** — community packs (`agentsmesh install ...`), remote `extends`, runtime plugins (`agentsmesh plugin add`), schema-validated config files, and a typed programmatic API for scripts, IDE extensions, and CI.
161
+ - **Self-serve MCP server** — `agentsmesh mcp` exposes canonical configuration as an MCP tool so AI agents can introspect rules, commands, agents, and skills, and trigger `generate` — all within the conversation. Seeded automatically by `agentsmesh init`.
136
162
 
137
163
  ---
138
164
 
package/dist/canonical.js CHANGED
@@ -1166,12 +1166,12 @@ async function readExistingServers(path) {
1166
1166
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
1167
1167
  const raw = parsed.mcpServers;
1168
1168
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
1169
- const out = {};
1169
+ const out2 = {};
1170
1170
  for (const [name, value] of Object.entries(raw)) {
1171
1171
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
1172
- out[name] = value;
1172
+ out2[name] = value;
1173
1173
  }
1174
- return out;
1174
+ return out2;
1175
1175
  }
1176
1176
  var init_mcp_merge = __esm({
1177
1177
  "src/targets/import/mcp-merge.ts"() {
@@ -1454,13 +1454,13 @@ function parseMcpJson(content) {
1454
1454
  if (!parsed || typeof parsed !== "object") return {};
1455
1455
  const raw = parsed.mcpServers;
1456
1456
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
1457
- const out = {};
1457
+ const out2 = {};
1458
1458
  for (const [name, value] of Object.entries(raw)) {
1459
1459
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
1460
1460
  const server = value;
1461
1461
  const description = typeof server.description === "string" ? server.description : void 0;
1462
1462
  if (typeof server.command === "string") {
1463
- out[name] = {
1463
+ out2[name] = {
1464
1464
  type: typeof server.type === "string" ? server.type : "stdio",
1465
1465
  command: server.command,
1466
1466
  args: toStringArray5(server.args),
@@ -1470,7 +1470,7 @@ function parseMcpJson(content) {
1470
1470
  continue;
1471
1471
  }
1472
1472
  if (typeof server.url === "string") {
1473
- out[name] = {
1473
+ out2[name] = {
1474
1474
  type: typeof server.type === "string" ? server.type : "http",
1475
1475
  url: server.url,
1476
1476
  headers: toStringRecord(server.headers),
@@ -1479,7 +1479,7 @@ function parseMcpJson(content) {
1479
1479
  };
1480
1480
  }
1481
1481
  }
1482
- return out;
1482
+ return out2;
1483
1483
  }
1484
1484
  async function runMcpJson(spec, sources, projectRoot, fromTool) {
1485
1485
  if (!spec.canonicalFilename) {
@@ -9549,18 +9549,18 @@ function generateRules11(canonical) {
9549
9549
  return outputs;
9550
9550
  }
9551
9551
  function toJunieMcpServer(server) {
9552
- const out = {};
9553
- if (server.description) out.description = server.description;
9554
- if (server.type !== "stdio") out.type = server.type;
9552
+ const out2 = {};
9553
+ if (server.description) out2.description = server.description;
9554
+ if (server.type !== "stdio") out2.type = server.type;
9555
9555
  if (isStdioMcpServer(server)) {
9556
- out.command = server.command;
9557
- out.args = server.args;
9556
+ out2.command = server.command;
9557
+ out2.args = server.args;
9558
9558
  } else {
9559
- out.url = server.url;
9560
- if (Object.keys(server.headers).length > 0) out.headers = server.headers;
9559
+ out2.url = server.url;
9560
+ if (Object.keys(server.headers).length > 0) out2.headers = server.headers;
9561
9561
  }
9562
- if (Object.keys(server.env).length > 0) out.env = server.env;
9563
- return out;
9562
+ if (Object.keys(server.env).length > 0) out2.env = server.env;
9563
+ return out2;
9564
9564
  }
9565
9565
  function generateMcp7(canonical) {
9566
9566
  if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
@@ -11029,11 +11029,11 @@ var init_generator17 = __esm({
11029
11029
  });
11030
11030
  function toStringRecord2(value) {
11031
11031
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
11032
- const out = {};
11032
+ const out2 = {};
11033
11033
  for (const [k, v] of Object.entries(value)) {
11034
- if (typeof v === "string") out[k] = v;
11034
+ if (typeof v === "string") out2[k] = v;
11035
11035
  }
11036
- return out;
11036
+ return out2;
11037
11037
  }
11038
11038
  function parseOpenCodeMcp(content) {
11039
11039
  let parsed;
@@ -11045,12 +11045,12 @@ function parseOpenCodeMcp(content) {
11045
11045
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
11046
11046
  const raw = parsed.mcp;
11047
11047
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
11048
- const out = {};
11048
+ const out2 = {};
11049
11049
  for (const [name, value] of Object.entries(raw)) {
11050
11050
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
11051
11051
  const entry = value;
11052
11052
  if (typeof entry.url === "string") {
11053
- out[name] = {
11053
+ out2[name] = {
11054
11054
  type: "url",
11055
11055
  url: entry.url,
11056
11056
  headers: toStringRecord2(entry.headers),
@@ -11064,7 +11064,7 @@ function parseOpenCodeMcp(content) {
11064
11064
  const command = cmdArr[0];
11065
11065
  if (command === void 0) continue;
11066
11066
  const args = cmdArr.slice(1);
11067
- out[name] = {
11067
+ out2[name] = {
11068
11068
  type: "stdio",
11069
11069
  command,
11070
11070
  args,
@@ -11073,7 +11073,7 @@ function parseOpenCodeMcp(content) {
11073
11073
  };
11074
11074
  }
11075
11075
  }
11076
- return out;
11076
+ return out2;
11077
11077
  }
11078
11078
  async function importMcp4(projectRoot, scope, results) {
11079
11079
  const configFile = scope === "global" ? OPENCODE_GLOBAL_CONFIG_FILE : OPENCODE_CONFIG_FILE;
@@ -13495,12 +13495,12 @@ function topLevelDotfilePrefixes(descriptor19) {
13495
13495
  ...layouts.flatMap((l) => l.managedOutputs?.dirs ?? []),
13496
13496
  ...layouts.flatMap((l) => l.managedOutputs?.files ?? [])
13497
13497
  ];
13498
- const out = /* @__PURE__ */ new Set();
13498
+ const out2 = /* @__PURE__ */ new Set();
13499
13499
  for (const candidate of candidates) {
13500
13500
  const top = candidate.split("/")[0];
13501
- if (top && top.startsWith(".") && top.length > 1) out.add(`${top}/`);
13501
+ if (top && top.startsWith(".") && top.length > 1) out2.add(`${top}/`);
13502
13502
  }
13503
- return out;
13503
+ return out2;
13504
13504
  }
13505
13505
  function buildDefaultRootRelativePrefixes() {
13506
13506
  const set = /* @__PURE__ */ new Set([".agentsmesh/"]);
@@ -15076,12 +15076,60 @@ function parseServer(raw) {
15076
15076
  env
15077
15077
  };
15078
15078
  }
15079
+ function stripJsonComments(text) {
15080
+ let result = "";
15081
+ let i = 0;
15082
+ const len = text.length;
15083
+ while (i < len) {
15084
+ const ch = text[i];
15085
+ if (ch === '"') {
15086
+ result += ch;
15087
+ i++;
15088
+ while (i < len) {
15089
+ const sc = text[i];
15090
+ result += sc;
15091
+ if (sc === "\\") {
15092
+ i++;
15093
+ if (i < len) {
15094
+ result += text[i];
15095
+ }
15096
+ } else if (sc === '"') {
15097
+ break;
15098
+ }
15099
+ i++;
15100
+ }
15101
+ i++;
15102
+ continue;
15103
+ }
15104
+ if (ch === "/" && text[i + 1] === "*") {
15105
+ i += 2;
15106
+ while (i < len) {
15107
+ if (text[i] === "*" && text[i + 1] === "/") {
15108
+ i += 2;
15109
+ break;
15110
+ }
15111
+ i++;
15112
+ }
15113
+ continue;
15114
+ }
15115
+ if (ch === "/" && text[i + 1] === "/") {
15116
+ i += 2;
15117
+ while (i < len && text[i] !== "\n") {
15118
+ i++;
15119
+ }
15120
+ continue;
15121
+ }
15122
+ result += ch;
15123
+ i++;
15124
+ }
15125
+ return result;
15126
+ }
15079
15127
  async function parseMcp(mcpPath) {
15080
15128
  const content = await readFileSafe(mcpPath);
15081
15129
  if (!content) return null;
15082
15130
  let parsed;
15083
15131
  try {
15084
- parsed = JSON.parse(content);
15132
+ parsed = JSON.parse(stripJsonComments(content));
15085
15133
  } catch {
15086
15134
  return null;
15087
15135
  }
@@ -15283,14 +15331,14 @@ function mergeHooks(base, overlay) {
15283
15331
  }
15284
15332
  function mergeIgnore(base, overlay) {
15285
15333
  const seen = new Set(base);
15286
- const out = [...base];
15334
+ const out2 = [...base];
15287
15335
  for (const p of overlay) {
15288
15336
  if (!seen.has(p)) {
15289
15337
  seen.add(p);
15290
- out.push(p);
15338
+ out2.push(p);
15291
15339
  }
15292
15340
  }
15293
- return out;
15341
+ return out2;
15294
15342
  }
15295
15343
 
15296
15344
  // src/config/resolve/native-format-detector.ts
@@ -15398,6 +15446,11 @@ var C = {
15398
15446
  cyan: "\x1B[36m",
15399
15447
  reset: "\x1B[0m"
15400
15448
  };
15449
+ function out(text) {
15450
+ {
15451
+ process.stdout.write(text);
15452
+ }
15453
+ }
15401
15454
  function noColor() {
15402
15455
  return process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "";
15403
15456
  }
@@ -15410,7 +15463,7 @@ function pad(str, width) {
15410
15463
  }
15411
15464
  var logger = {
15412
15465
  info(msg) {
15413
- process.stdout.write(c(C.cyan, msg) + "\n");
15466
+ out(c(C.cyan, msg) + "\n");
15414
15467
  },
15415
15468
  warn(msg) {
15416
15469
  process.stderr.write(c(C.yellow, "\u26A0 ") + msg + "\n");
@@ -15419,11 +15472,11 @@ var logger = {
15419
15472
  process.stderr.write(c(C.red, "\u2717 ") + msg + "\n");
15420
15473
  },
15421
15474
  success(msg) {
15422
- process.stdout.write(c(C.green, "\u2713 ") + msg + "\n");
15475
+ out(c(C.green, "\u2713 ") + msg + "\n");
15423
15476
  },
15424
15477
  debug(msg) {
15425
15478
  if (process.env.AGENTSMESH_DEBUG === "1") {
15426
- process.stdout.write(c(C.cyan, "[debug] ") + msg + "\n");
15479
+ out(c(C.cyan, "[debug] ") + msg + "\n");
15427
15480
  }
15428
15481
  },
15429
15482
  table(rows) {
@@ -15439,13 +15492,13 @@ var logger = {
15439
15492
  widths[j] = max;
15440
15493
  }
15441
15494
  const border = "+" + widths.map((w) => "-".repeat(w + 2)).join("+") + "+";
15442
- process.stdout.write(border + "\n");
15495
+ out(border + "\n");
15443
15496
  for (let i = 0; i < rows.length; i++) {
15444
15497
  const row = rows[i];
15445
15498
  const line = "| " + row.map((cell, j) => pad(cell, widths[j])).join(" | ") + " |";
15446
- process.stdout.write(line + "\n");
15499
+ out(line + "\n");
15447
15500
  }
15448
- process.stdout.write(border + "\n");
15501
+ out(border + "\n");
15449
15502
  }
15450
15503
  };
15451
15504