@aiaiai-pt/martha-cli 0.53.0 → 0.54.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
@@ -2,6 +2,37 @@
2
2
 
3
3
  All notable changes to `@aiaiai-pt/martha-cli`. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project adheres to semver — `0.x` releases may include breaking changes between minor versions.
4
4
 
5
+ ## [0.54.0] — 2026-08-03
6
+
7
+ ### Added — `channels` uses the Buzz binaries Desktop already ships
8
+
9
+ - `buzz` and `buzz-acp` are now resolved from the user's PATH **or** from Buzz
10
+ Desktop's own bundle (`Buzz.app/Contents/MacOS` and the platform
11
+ equivalents), and `connect` prepends that directory to the harness's PATH so
12
+ `acp-serve --post-reply` can reach `buzz` to deliver. Desktop ships both as
13
+ Tauri sidecars and does exactly this for the agents it spawns itself
14
+ (`runtime/path.rs`); doing the same means a machine with Buzz Desktop
15
+ installed needs nothing on PATH and nothing built. Telling someone to
16
+ `cargo build` a binary sitting in their Applications folder was a
17
+ prerequisite we invented.
18
+ - The two checks now read `buzz-acp` / `buzz CLI` rather than `… on PATH`,
19
+ since PATH is no longer the only place they can come from, and the detail
20
+ says which copy is in use. When neither has it, the fix leads with installing
21
+ Buzz Desktop and keeps the build-from-source path as the alternative.
22
+
23
+ ## [0.53.1] — 2026-08-03
24
+
25
+ ### Fixed — `channels install-harness` told a Buzz-less machine to "launch Buzz once"
26
+
27
+ - The command registers Martha as a runtime *inside* Buzz Desktop, so with no
28
+ Desktop on the machine there is nothing to register with. It correctly
29
+ refused and wrote nothing, but the remedy assumed the app was installed and
30
+ merely unopened. It now probes for the application itself and says which of
31
+ the two situations it is: **not installed** (with the release link, and a
32
+ pointer to `martha channels connect buzz`, which needs no Desktop at all) or
33
+ **installed but never launched** (open it once). Both still name the exact
34
+ app-data paths so `--app-data` stays actionable.
35
+
5
36
  ## [0.53.0] — 2026-08-02
6
37
 
7
38
  ### Added — `martha channels`: connect an agent to a channel from either side (#1140)
package/dist/index.js CHANGED
@@ -11129,7 +11129,7 @@ init_config();
11129
11129
  init_errors();
11130
11130
 
11131
11131
  // src/version.ts
11132
- var CLI_VERSION = "0.53.0";
11132
+ var CLI_VERSION = "0.54.0";
11133
11133
 
11134
11134
  // src/commands/sessions.ts
11135
11135
  function relativeTime(iso) {
@@ -14770,6 +14770,62 @@ function buzzAppDataCandidates(platform, env2, home) {
14770
14770
  function chooseAppDataDir(candidates, exists) {
14771
14771
  return candidates.find((c) => exists(c.dir)) ?? null;
14772
14772
  }
14773
+ function buzzAppCandidates(platform, env2, home) {
14774
+ if (platform === "darwin") {
14775
+ return ["/Applications/Buzz.app", join3(home, "Applications", "Buzz.app")];
14776
+ }
14777
+ if (platform === "win32") {
14778
+ const base = env2.LOCALAPPDATA ?? join3(home, "AppData", "Local");
14779
+ return [join3(base, "Programs", "Buzz")];
14780
+ }
14781
+ return [
14782
+ "/opt/Buzz",
14783
+ "/usr/bin/buzz-desktop",
14784
+ join3(home, ".local", "bin", "buzz-desktop")
14785
+ ];
14786
+ }
14787
+ var BUZZ_RELEASES_URL = "https://github.com/block/buzz/releases/latest";
14788
+ function buzzSidecarDirs(platform, env2, home) {
14789
+ if (platform === "darwin") {
14790
+ return buzzAppCandidates(platform, env2, home).map((app) => join3(app, "Contents", "MacOS"));
14791
+ }
14792
+ if (platform === "win32") {
14793
+ return buzzAppCandidates(platform, env2, home);
14794
+ }
14795
+ return ["/opt/Buzz"];
14796
+ }
14797
+ function resolveBuzzBinary(bin, opts) {
14798
+ const onPath = resolveOnPath(bin, opts.env, opts.platform, opts.isExecutable);
14799
+ if (onPath)
14800
+ return { path: onPath, source: "path" };
14801
+ if (bin.includes("/") || bin.includes("\\"))
14802
+ return null;
14803
+ for (const dir of buzzSidecarDirs(opts.platform, opts.env, opts.home)) {
14804
+ const candidate = join3(dir, bin);
14805
+ if (opts.isExecutable(candidate))
14806
+ return { path: candidate, source: "desktop" };
14807
+ }
14808
+ return null;
14809
+ }
14810
+ function missingAppDataMessage(candidates, appInstalled) {
14811
+ const looked = candidates.map((c) => ` ${c.dir} (${c.build})`).join(`
14812
+ `);
14813
+ if (appInstalled) {
14814
+ return `Buzz Desktop is installed but has never been launched — it creates its ` + `data directory on first run.
14815
+
14816
+ Looked for:
14817
+ ${looked}
14818
+ ` + `Open Buzz Desktop once, then re-run this. Or pass --app-data <dir>.`;
14819
+ }
14820
+ return `Buzz Desktop is not installed on this machine. This command registers ` + `Martha as a runtime INSIDE Desktop, so there is nothing to register with.
14821
+
14822
+ ` + `Looked for:
14823
+ ${looked}
14824
+ ` + `Install it: ${BUZZ_RELEASES_URL}
14825
+
14826
+ ` + `If you do not want Desktop at all, you do not need this command — run the ` + `adapter yourself instead:
14827
+ martha channels connect buzz --agent <name> --relay <url>`;
14828
+ }
14773
14829
  var DEFAULT_BUZZ_KINDS = "9,46010,40007,7";
14774
14830
  function buzzAcpEnv(opts) {
14775
14831
  const env2 = {
@@ -14810,6 +14866,14 @@ function executableOnDisk(p) {
14810
14866
  function which(bin) {
14811
14867
  return resolveOnPath(bin, process.env, process.platform, executableOnDisk);
14812
14868
  }
14869
+ function whichBuzz(bin) {
14870
+ return resolveBuzzBinary(bin, {
14871
+ platform: process.platform,
14872
+ env: process.env,
14873
+ home: homedir(),
14874
+ isExecutable: executableOnDisk
14875
+ });
14876
+ }
14813
14877
  function runBin(bin, args, env2) {
14814
14878
  return new Promise((resolve2) => {
14815
14879
  execFile2(bin, args, { env: env2, timeout: 15000, maxBuffer: 4 * 1024 * 1024 }, (err, stdout, stderr) => {
@@ -14855,20 +14919,22 @@ async function preflightBuzz(ctx, opts) {
14855
14919
  fix: supported ? undefined : "upgrade the CLI that is FIRST on PATH: npm i -g @aiaiai-pt/martha-cli@latest (or point --martha-bin at the right one)"
14856
14920
  });
14857
14921
  }
14858
- const acpPath = which(opts.buzzAcpBin);
14922
+ const resolveBin = opts.resolveBin ?? whichBuzz;
14923
+ const acp = resolveBin(opts.buzzAcpBin);
14859
14924
  checks.push({
14860
- ok: !!acpPath,
14861
- label: "buzz-acp on PATH",
14862
- detail: acpPath ?? `'${opts.buzzAcpBin}' not found`,
14863
- fix: acpPath ? undefined : "build it from block/buzz: cargo build -p buzz-acp, then put target/debug on PATH (or pass --buzz-acp-bin)"
14925
+ ok: !!acp,
14926
+ label: "buzz-acp",
14927
+ detail: acp ? acp.source === "desktop" ? `${acp.path} (bundled with Buzz Desktop)` : acp.path : `'${opts.buzzAcpBin}' not found on PATH or in Buzz Desktop`,
14928
+ fix: acp ? undefined : `install Buzz Desktop (${BUZZ_RELEASES_URL}) — it ships this binary — or build it: cargo build -p buzz-acp (or pass --buzz-acp-bin)`
14864
14929
  });
14865
- const buzzPath = which(opts.buzzBin);
14930
+ const buzz = resolveBin(opts.buzzBin);
14866
14931
  checks.push({
14867
- ok: !!buzzPath,
14868
- label: "buzz CLI on PATH",
14869
- detail: buzzPath ?? `'${opts.buzzBin}' not found`,
14870
- fix: buzzPath ? undefined : "build it from block/buzz: cargo build -p buzz-cli — acp-serve --post-reply shells it to deliver the answer"
14932
+ ok: !!buzz,
14933
+ label: "buzz CLI",
14934
+ detail: buzz ? buzz.source === "desktop" ? `${buzz.path} (bundled with Buzz Desktop)` : buzz.path : `'${opts.buzzBin}' not found on PATH or in Buzz Desktop`,
14935
+ fix: buzz ? undefined : `install Buzz Desktop (${BUZZ_RELEASES_URL}) — it ships this binary — or build it: cargo build -p buzz-cli. acp-serve --post-reply shells it to deliver the answer`
14871
14936
  });
14937
+ const buzzPath = buzz?.path ?? null;
14872
14938
  let whoami = null;
14873
14939
  try {
14874
14940
  whoami = await ctx.api.get("/api/tasks/whoami");
@@ -15116,10 +15182,8 @@ function registerChannelCommands(program2) {
15116
15182
  const chosen = opts.appData ? { build: "release", dir: String(opts.appData) } : chooseAppDataDir(buzzAppDataCandidates(process.platform, process.env, homedir()), (d) => existsSync(d));
15117
15183
  if (!chosen) {
15118
15184
  const candidates = buzzAppDataCandidates(process.platform, process.env, homedir());
15119
- throw new CLIError("No Buzz Desktop app-data directory found.", 3 /* NotFound */, `Looked for:
15120
- ${candidates.map((c) => ` ${c.dir} (${c.build})`).join(`
15121
- `)}
15122
- Launch Buzz Desktop once so it creates one, or pass --app-data <dir>.`);
15185
+ const appInstalled = buzzAppCandidates(process.platform, process.env, homedir()).some((p) => existsSync(p));
15186
+ throw new CLIError(appInstalled ? "Buzz Desktop has no data directory yet." : "Buzz Desktop is not installed.", 3 /* NotFound */, missingAppDataMessage(candidates, appInstalled));
15123
15187
  }
15124
15188
  const dir = join3(chosen.dir, "custom_harnesses");
15125
15189
  const file = join3(dir, `${def.id}.json`);
@@ -15190,21 +15254,25 @@ Launch Buzz Desktop once so it creates one, or pass --app-data <dir>.`);
15190
15254
  process.exitCode = 1 /* Error */;
15191
15255
  return;
15192
15256
  }
15193
- const acp = which(opts.buzzAcpBin);
15257
+ const acp = whichBuzz(opts.buzzAcpBin);
15258
+ const childPath = [
15259
+ ...buzzSidecarDirs(process.platform, process.env, homedir()).filter((d) => existsSync(d)),
15260
+ process.env.PATH ?? ""
15261
+ ].filter(Boolean).join(process.platform === "win32" ? ";" : ":");
15194
15262
  if (opts.dryRun) {
15195
15263
  console.log(source_default.bold(`Would launch:
15196
15264
  `));
15197
15265
  for (const [k, v] of Object.entries(env2))
15198
15266
  console.log(` ${k}=${v}`);
15199
- console.log(` ${acp}
15267
+ console.log(` ${acp.path}
15200
15268
  `);
15201
15269
  return;
15202
15270
  }
15203
15271
  console.log(source_default.bold(`
15204
15272
  Connecting '${opts.agent}' to ${opts.relay} …
15205
15273
  `));
15206
- const child = spawn3(acp, [], {
15207
- env: { ...process.env, ...env2 },
15274
+ const child = spawn3(acp.path, [], {
15275
+ env: { ...process.env, PATH: childPath, ...env2 },
15208
15276
  stdio: "inherit"
15209
15277
  });
15210
15278
  await new Promise((resolve2) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiaiai-pt/martha-cli",
3
- "version": "0.53.0",
3
+ "version": "0.54.0",
4
4
  "description": "Terminal-first client for the Martha AI platform",
5
5
  "homepage": "https://docs.martha.nomadriver.co",
6
6
  "repository": {