@hasna/machines 0.0.43 → 0.0.45

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
@@ -144,6 +144,7 @@ CLI and MCP expose the same topology view:
144
144
  machines topology --json
145
145
  machines topology --no-tailscale --json
146
146
  machines route --machine linux-dev-01 --json
147
+ machines ssh --machine linux-dev-01 --private-metadata
147
148
  ```
148
149
 
149
150
  ## Screen sharing
@@ -322,6 +323,11 @@ set `HASNA_MACHINES_ALLOW_PRIVATE_OUTPUT=1` and pass the explicit
322
323
  `privateMetadata=true` query parameter or MCP `private_metadata` argument. The
323
324
  caller flag alone is ignored.
324
325
 
326
+ Default status and SSH-resolution output is public-safe: local paths, machine
327
+ identifiers, route targets, and generated SSH commands are redacted unless
328
+ private output is explicitly requested. CLI commands that print raw SSH targets
329
+ require `--private-metadata`.
330
+
325
331
  Doctor summaries are also opt-in with `--doctor-summary` or
326
332
  `HASNA_MACHINES_AGENT_DOCTOR_SUMMARY=1`. The daemon records a compact
327
333
  ok/warn/fail count plus redacted blockers and avoids optional private adapters
package/dist/cli/index.js CHANGED
@@ -9972,7 +9972,8 @@ function parseJsonObject(value) {
9972
9972
  return null;
9973
9973
  }
9974
9974
  }
9975
- function getStatus() {
9975
+ function getStatus(options = {}) {
9976
+ const privateMetadata = options.privateMetadata === true;
9976
9977
  const manifest = readManifest();
9977
9978
  const heartbeats = listHeartbeats();
9978
9979
  const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
@@ -9981,17 +9982,17 @@ function getStatus() {
9981
9982
  ...heartbeats.map((heartbeat) => heartbeat.machine_id)
9982
9983
  ]);
9983
9984
  return {
9984
- machineId: getLocalMachineId(),
9985
- manifestPath: getManifestPath(),
9986
- dbPath: getDbPath(),
9987
- notificationsPath: getNotificationsPath(),
9985
+ machineId: privateMetadata ? getLocalMachineId() : REDACTED_VALUE,
9986
+ manifestPath: privateMetadata ? getManifestPath() : REDACTED_VALUE,
9987
+ dbPath: privateMetadata ? getDbPath() : REDACTED_VALUE,
9988
+ notificationsPath: privateMetadata ? getNotificationsPath() : REDACTED_VALUE,
9988
9989
  manifestMachineCount: manifest.machines.length,
9989
9990
  heartbeatCount: heartbeats.length,
9990
9991
  machines: [...machineIds].sort().map((machineId) => {
9991
9992
  const declared = manifest.machines.find((machine) => machine.id === machineId);
9992
9993
  const heartbeat = heartbeatByMachine.get(machineId);
9993
9994
  return {
9994
- machineId,
9995
+ machineId: privateMetadata ? machineId : REDACTED_VALUE,
9995
9996
  platform: declared?.platform,
9996
9997
  manifestDeclared: Boolean(declared),
9997
9998
  heartbeatStatus: heartbeat?.status || "unknown",
@@ -9999,7 +10000,7 @@ function getStatus() {
9999
10000
  daemonVersion: heartbeat?.daemon_version ?? null,
10000
10001
  agentMode: heartbeat?.agent_mode ?? null,
10001
10002
  storageSyncStatus: heartbeat?.storage_sync_status ?? null,
10002
- doctorSummary: parseJsonObject(heartbeat?.doctor_summary_json),
10003
+ doctorSummary: privateMetadata ? parseJsonObject(heartbeat?.doctor_summary_json) : null,
10003
10004
  privateMetadata: Boolean(heartbeat?.private_metadata)
10004
10005
  };
10005
10006
  }),
@@ -10588,8 +10589,8 @@ function runDoctor(machineId, options = {}) {
10588
10589
 
10589
10590
  // src/commands/daemon.ts
10590
10591
  import { execFileSync } from "child_process";
10591
- import { chmodSync, existsSync as existsSync8, mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
10592
- import { dirname as dirname4 } from "path";
10592
+ import { chmodSync, existsSync as existsSync8, readFileSync as readFileSync6, statSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
10593
+ import { delimiter, dirname as dirname4 } from "path";
10593
10594
  import { platform as osPlatform } from "os";
10594
10595
  var DEFAULT_SERVICE_NAME = "machines-agent";
10595
10596
  var DEFAULT_EXECUTABLE = "/usr/local/bin/machines-agent";
@@ -10979,13 +10980,46 @@ WantedBy=${options.mode === "system" ? "multi-user.target" : "default.target"}
10979
10980
  `;
10980
10981
  }
10981
10982
  function daemonProgramArguments(options) {
10982
- const bunRuntime = siblingBunRuntime(options.executable);
10983
+ const bunRuntime = bunRuntimeForExecutable(options.executable);
10983
10984
  const base = bunRuntime ? [bunRuntime, options.executable] : [options.executable];
10984
10985
  return [...base, "--interval-ms", String(options.intervalMs)];
10985
10986
  }
10986
- function siblingBunRuntime(executable) {
10987
- const candidate = `${dirname4(executable)}/bun`;
10988
- return existsSync8(candidate) ? candidate : null;
10987
+ function bunRuntimeForExecutable(executable) {
10988
+ if (!isBunShebangScript(executable))
10989
+ return null;
10990
+ for (const candidate of bunRuntimeCandidates(executable)) {
10991
+ if (isExecutableFile(candidate))
10992
+ return candidate;
10993
+ }
10994
+ return null;
10995
+ }
10996
+ function bunRuntimeCandidates(executable) {
10997
+ const candidates = [
10998
+ `${dirname4(executable)}/bun`,
10999
+ process.env["BUN_INSTALL"] ? `${process.env["BUN_INSTALL"]}/bin/bun` : null,
11000
+ process.env["HOME"] ? `${process.env["HOME"]}/.bun/bin/bun` : null,
11001
+ ...(process.env["PATH"] ?? "").split(delimiter).filter(Boolean).map((entry) => `${entry}/bun`)
11002
+ ].filter((value) => Boolean(value));
11003
+ return [...new Set(candidates)];
11004
+ }
11005
+ function isBunShebangScript(executable) {
11006
+ try {
11007
+ const content = readFileSync6(executable, "utf8").slice(0, 256);
11008
+ const firstLine2 = content.split(/\r?\n/, 1)[0] ?? "";
11009
+ return /^#!.*\bbun\b/.test(firstLine2);
11010
+ } catch {
11011
+ return false;
11012
+ }
11013
+ }
11014
+ function isExecutableFile(path) {
11015
+ if (!existsSync8(path))
11016
+ return false;
11017
+ try {
11018
+ const stats = statSync(path);
11019
+ return stats.isFile() && (stats.mode & 73) !== 0;
11020
+ } catch {
11021
+ return false;
11022
+ }
10989
11023
  }
10990
11024
  function launchdDomain(options) {
10991
11025
  return options.mode === "system" ? "system" : "gui/$UID";
@@ -11343,7 +11377,7 @@ function startDashboardServer(options = {}) {
11343
11377
  return Response.json({ ok: true, ...getServeInfo(options) });
11344
11378
  }
11345
11379
  if (url.pathname === "/api/status") {
11346
- return Response.json(getStatus());
11380
+ return Response.json(appendWarnings(getStatus({ privateMetadata }), privateWarnings));
11347
11381
  }
11348
11382
  if (url.pathname === "/api/topology") {
11349
11383
  const topology = discoverMachineTopology({ includeTailscale: url.searchParams.get("tailscale") !== "false" });
@@ -11481,15 +11515,16 @@ function check(id, status, summary, detail) {
11481
11515
  function runSelfTest() {
11482
11516
  const version = getPackageVersion();
11483
11517
  const status = getStatus();
11518
+ const machineId = getLocalMachineId();
11484
11519
  const doctor = runDoctor();
11485
11520
  const serveInfo = getServeInfo();
11486
11521
  const html = renderDashboardHtml();
11487
11522
  const notifications = listNotificationChannels();
11488
- const apps = listApps(status.machineId);
11489
- const appsDiff = diffApps(status.machineId);
11490
- const cliPlan = buildClaudeInstallPlan(status.machineId);
11523
+ const apps = listApps(machineId);
11524
+ const appsDiff = diffApps(machineId);
11525
+ const cliPlan = buildClaudeInstallPlan(machineId);
11491
11526
  return {
11492
- machineId: getLocalMachineId(),
11527
+ machineId,
11493
11528
  checks: [
11494
11529
  check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
11495
11530
  check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
@@ -11507,7 +11542,7 @@ function runSelfTest() {
11507
11542
  // src/commands/clipboard.ts
11508
11543
  init_paths();
11509
11544
  import { createHash } from "crypto";
11510
- import { existsSync as existsSync9, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync5 } from "fs";
11545
+ import { existsSync as existsSync9, readFileSync as readFileSync7, rmSync, writeFileSync as writeFileSync5 } from "fs";
11511
11546
  import { join as join6 } from "path";
11512
11547
  var DEFAULT_CONFIG = {
11513
11548
  version: 1,
@@ -11541,7 +11576,7 @@ function readConfig(configPath) {
11541
11576
  if (!existsSync9(path)) {
11542
11577
  return getDefaultConfig();
11543
11578
  }
11544
- const parsed = JSON.parse(readFileSync6(path, "utf8"));
11579
+ const parsed = JSON.parse(readFileSync7(path, "utf8"));
11545
11580
  return { ...getDefaultConfig(), ...parsed };
11546
11581
  }
11547
11582
  function writeConfig(config, configPath) {
@@ -11556,7 +11591,7 @@ function readHistory(historyPath) {
11556
11591
  return [];
11557
11592
  }
11558
11593
  try {
11559
- return JSON.parse(readFileSync6(path, "utf8"));
11594
+ return JSON.parse(readFileSync7(path, "utf8"));
11560
11595
  } catch {
11561
11596
  return [];
11562
11597
  }
@@ -11586,7 +11621,7 @@ function sanitizeClipboardForRead(content, maxSizeBytes, skipPatterns) {
11586
11621
  function getOrCreateClipboardKey() {
11587
11622
  const keyPath = getClipboardKeyPath();
11588
11623
  if (existsSync9(keyPath)) {
11589
- return readFileSync6(keyPath, "utf8").trim();
11624
+ return readFileSync7(keyPath, "utf8").trim();
11590
11625
  }
11591
11626
  const key = createHash("sha256").update(crypto.randomUUID()).digest("hex").slice(0, 32);
11592
11627
  ensureParentDir(keyPath);
@@ -11641,7 +11676,7 @@ function getClipboardStatus(historyPath) {
11641
11676
 
11642
11677
  // src/commands/clipboard-daemon.ts
11643
11678
  init_paths();
11644
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
11679
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
11645
11680
  import { join as join7 } from "path";
11646
11681
  import { createHash as createHash3 } from "crypto";
11647
11682
 
@@ -11649,7 +11684,7 @@ import { createHash as createHash3 } from "crypto";
11649
11684
  init_paths();
11650
11685
  import { createServer } from "http";
11651
11686
  import { createHash as createHash2 } from "crypto";
11652
- import { readFileSync as readFileSync7 } from "fs";
11687
+ import { readFileSync as readFileSync8 } from "fs";
11653
11688
  function readLocalClipboardSync() {
11654
11689
  const platform5 = process.platform;
11655
11690
  if (platform5 === "darwin") {
@@ -11695,7 +11730,7 @@ function hasCommand3(binary) {
11695
11730
  function loadSharedSecret() {
11696
11731
  const keyPath = getClipboardKeyPath();
11697
11732
  try {
11698
- return readFileSync7(keyPath, "utf8").trim();
11733
+ return readFileSync8(keyPath, "utf8").trim();
11699
11734
  } catch {
11700
11735
  return "";
11701
11736
  }
@@ -11862,7 +11897,7 @@ function computeHash2(content) {
11862
11897
  }
11863
11898
  function loadSharedSecret2() {
11864
11899
  try {
11865
- return readFileSync8(getClipboardKeyPath(), "utf8").trim();
11900
+ return readFileSync9(getClipboardKeyPath(), "utf8").trim();
11866
11901
  } catch {
11867
11902
  return "";
11868
11903
  }
@@ -11873,7 +11908,7 @@ function writePid(pid) {
11873
11908
  }
11874
11909
  function readPid() {
11875
11910
  try {
11876
- const pid = Number.parseInt(readFileSync8(DAEMON_PID_PATH, "utf8").trim());
11911
+ const pid = Number.parseInt(readFileSync9(DAEMON_PID_PATH, "utf8").trim());
11877
11912
  return Number.isFinite(pid) ? pid : null;
11878
11913
  } catch {
11879
11914
  return null;
@@ -11974,7 +12009,7 @@ async function discoverPeers() {
11974
12009
 
11975
12010
  // src/commands/heal.ts
11976
12011
  init_paths();
11977
- import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
12012
+ import { existsSync as existsSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
11978
12013
  import { join as join8 } from "path";
11979
12014
  var DEFAULT_THRESHOLDS = {
11980
12015
  reconnect: 3,
@@ -12028,7 +12063,7 @@ function readHealConfig(path) {
12028
12063
  const p = path || getHealConfigPath();
12029
12064
  if (!existsSync10(p))
12030
12065
  return { ...DEFAULT_HEAL_CONFIG, thresholds: { ...DEFAULT_THRESHOLDS } };
12031
- const parsed = JSON.parse(readFileSync9(p, "utf8"));
12066
+ const parsed = JSON.parse(readFileSync10(p, "utf8"));
12032
12067
  return {
12033
12068
  ...DEFAULT_HEAL_CONFIG,
12034
12069
  ...parsed,
@@ -12047,7 +12082,7 @@ function readHealState(path) {
12047
12082
  if (!existsSync10(p))
12048
12083
  return defaultHealState();
12049
12084
  try {
12050
- return { ...defaultHealState(), ...JSON.parse(readFileSync9(p, "utf8")) };
12085
+ return { ...defaultHealState(), ...JSON.parse(readFileSync10(p, "utf8")) };
12051
12086
  } catch {
12052
12087
  return defaultHealState();
12053
12088
  }
@@ -12174,7 +12209,7 @@ function sh(cmd, timeoutMs = 8000) {
12174
12209
  }
12175
12210
  function getCurrentBootId() {
12176
12211
  try {
12177
- return readFileSync9("/proc/sys/kernel/random/boot_id", "utf8").trim();
12212
+ return readFileSync10("/proc/sys/kernel/random/boot_id", "utf8").trim();
12178
12213
  } catch {
12179
12214
  return "";
12180
12215
  }
@@ -12260,7 +12295,7 @@ function executeAction(action, config) {
12260
12295
 
12261
12296
  // src/commands/heal-daemon.ts
12262
12297
  init_paths();
12263
- import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
12298
+ import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
12264
12299
  import { join as join9 } from "path";
12265
12300
  var DAEMON_PID_PATH2 = join9(getDataDir(), "heal-daemon.pid");
12266
12301
  var SERVICE_PATH = "/etc/systemd/system/machines-heal.service";
@@ -12308,7 +12343,7 @@ function writePid2(pid) {
12308
12343
  }
12309
12344
  function readPid2() {
12310
12345
  try {
12311
- const pid = Number.parseInt(readFileSync10(DAEMON_PID_PATH2, "utf8").trim());
12346
+ const pid = Number.parseInt(readFileSync11(DAEMON_PID_PATH2, "utf8").trim());
12312
12347
  return Number.isFinite(pid) ? pid : null;
12313
12348
  } catch {
12314
12349
  return null;
@@ -12382,7 +12417,7 @@ function enableHardwareWatchdog() {
12382
12417
  const log2 = [];
12383
12418
  if (!existsSync11(SYSTEM_CONF))
12384
12419
  return ["/etc/systemd/system.conf not found; skipping hardware watchdog"];
12385
- let conf = readFileSync10(SYSTEM_CONF, "utf8");
12420
+ let conf = readFileSync11(SYSTEM_CONF, "utf8");
12386
12421
  const set = (key, value) => {
12387
12422
  const re = new RegExp(`^#?\\s*${key}=.*$`, "m");
12388
12423
  if (re.test(conf))
@@ -12499,7 +12534,7 @@ ${items.map((item) => `- ${item}`).join(`
12499
12534
 
12500
12535
  // src/cli/index.ts
12501
12536
  import { rmSync as rmSync2 } from "fs";
12502
- import { readFileSync as readFileSync11 } from "fs";
12537
+ import { readFileSync as readFileSync12 } from "fs";
12503
12538
  var program2 = new Command;
12504
12539
  function printJsonOrText(data, text, json = false) {
12505
12540
  if (json || program2.opts().quiet) {
@@ -12831,7 +12866,7 @@ manifestCommand.command("add").description("Add or replace a machine in the flee
12831
12866
  console.error("error: --from-stdin requires piped input");
12832
12867
  process.exit(1);
12833
12868
  }
12834
- const input = readFileSync11(0, "utf8");
12869
+ const input = readFileSync12(0, "utf8");
12835
12870
  const machine2 = JSON.parse(input);
12836
12871
  console.log(JSON.stringify(manifestAdd(machine2), null, 2));
12837
12872
  return;
@@ -13160,13 +13195,25 @@ program2.command("route").description("Resolve the best route for a machine").re
13160
13195
  }
13161
13196
  console.log(options.privateMetadata ? command2 ?? `${resolved.route}:${resolved.target}` : `${publicResolved.route}:${publicResolved.target ?? "unresolved"}`);
13162
13197
  });
13163
- program2.command("ssh").description("Choose the best SSH route for a machine").requiredOption("--machine <id>", "Machine identifier").option("--cmd <command>", "Remote command to run").option("-j, --json", "Print JSON output", false).action((options) => {
13198
+ program2.command("ssh").description("Choose the best SSH route for a machine").requiredOption("--machine <id>", "Machine identifier").option("--cmd <command>", "Remote command to run").option("--private-metadata", "Print private SSH target and command", false).option("-j, --json", "Print JSON output", false).action((options) => {
13199
+ const resolved = resolveMachineRoute(options.machine);
13200
+ const publicResolved = redactRouteForOutput(resolved, { privateMetadata: options.privateMetadata });
13201
+ const command2 = resolved.ok && options.privateMetadata ? buildSshCommand(options.machine, options.cmd) : resolved.ok ? REDACTED_VALUE : null;
13164
13202
  if (options.json) {
13165
- const resolved = resolveMachineRoute(options.machine);
13166
- console.log(JSON.stringify({ resolved, command: resolved.ok ? buildSshCommand(options.machine, options.cmd) : null }, null, 2));
13203
+ console.log(JSON.stringify({ resolved: publicResolved, command: command2 }, null, 2));
13167
13204
  return;
13168
13205
  }
13169
- console.log(buildSshCommand(options.machine, options.cmd));
13206
+ if (!resolved.ok) {
13207
+ console.error(source_default.red(resolved.warnings.join("; ") || `No route found for ${options.machine}`));
13208
+ process.exitCode = 1;
13209
+ return;
13210
+ }
13211
+ if (!options.privateMetadata) {
13212
+ console.error(source_default.red("Refusing to print private SSH target; rerun with --private-metadata."));
13213
+ process.exitCode = 1;
13214
+ return;
13215
+ }
13216
+ console.log(command2);
13170
13217
  });
13171
13218
  program2.command("screen").description("Open Screen Sharing (VNC) to a machine using its best live route").argument("[machine]", "Machine identifier").option("--machine <id>", "Machine identifier (alternative to positional arg)").option("--all", "Open every reachable machine", false).option("--print", "Print the vnc:// URL instead of opening it", false).option("-j, --json", "Print JSON output", false).action((machineArg, options) => {
13172
13219
  if (options.all) {
@@ -13314,8 +13361,8 @@ storageCommand.command("sync").description("Bidirectional storage sync: pull the
13314
13361
  printStorageError(error);
13315
13362
  }
13316
13363
  });
13317
- program2.command("status").description("Print local machine and storage status").option("-j, --json", "Print JSON output", false).action((options) => {
13318
- const status = getStatus();
13364
+ program2.command("status").description("Print local machine and storage status").option("--private-metadata", "Print private local paths and machine identifiers", false).option("-j, --json", "Print JSON output", false).action((options) => {
13365
+ const status = getStatus({ privateMetadata: options.privateMetadata });
13319
13366
  printJsonOrText(status, renderFleetStatus(status), options.json);
13320
13367
  });
13321
13368
  program2.command("doctor").description("Run machine preflight checks").option("--machine <id>", "Machine identifier").option("-j, --json", "Print JSON output", false).action((options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"self-test.d.ts","sourceRoot":"","sources":["../../src/commands/self-test.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,aAAa,CAAC;AAMjE,wBAAgB,WAAW,IAAI,cAAc,CAkD5C"}
1
+ {"version":3,"file":"self-test.d.ts","sourceRoot":"","sources":["../../src/commands/self-test.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,aAAa,CAAC;AAMjE,wBAAgB,WAAW,IAAI,cAAc,CAmD5C"}
@@ -1,3 +1,6 @@
1
1
  import type { FleetStatus } from "../types.js";
2
- export declare function getStatus(): FleetStatus;
2
+ export interface FleetStatusOptions {
3
+ privateMetadata?: boolean;
4
+ }
5
+ export declare function getStatus(options?: FleetStatusOptions): FleetStatus;
3
6
  //# sourceMappingURL=status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C,wBAAgB,SAAS,IAAI,WAAW,CAmCvC"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAoCvE"}
package/dist/index.js CHANGED
@@ -13728,8 +13728,8 @@ function renderDomainMapping(domain) {
13728
13728
  }
13729
13729
  // src/commands/daemon.ts
13730
13730
  import { execFileSync as execFileSync2 } from "child_process";
13731
- import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
13732
- import { dirname as dirname4 } from "path";
13731
+ import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync4, statSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
13732
+ import { delimiter, dirname as dirname4 } from "path";
13733
13733
  import { platform as osPlatform } from "os";
13734
13734
  var DEFAULT_SERVICE_NAME = "machines-agent";
13735
13735
  var DEFAULT_EXECUTABLE = "/usr/local/bin/machines-agent";
@@ -14142,13 +14142,46 @@ WantedBy=${options.mode === "system" ? "multi-user.target" : "default.target"}
14142
14142
  `;
14143
14143
  }
14144
14144
  function daemonProgramArguments(options) {
14145
- const bunRuntime = siblingBunRuntime(options.executable);
14145
+ const bunRuntime = bunRuntimeForExecutable(options.executable);
14146
14146
  const base = bunRuntime ? [bunRuntime, options.executable] : [options.executable];
14147
14147
  return [...base, "--interval-ms", String(options.intervalMs)];
14148
14148
  }
14149
- function siblingBunRuntime(executable) {
14150
- const candidate = `${dirname4(executable)}/bun`;
14151
- return existsSync6(candidate) ? candidate : null;
14149
+ function bunRuntimeForExecutable(executable) {
14150
+ if (!isBunShebangScript(executable))
14151
+ return null;
14152
+ for (const candidate of bunRuntimeCandidates(executable)) {
14153
+ if (isExecutableFile(candidate))
14154
+ return candidate;
14155
+ }
14156
+ return null;
14157
+ }
14158
+ function bunRuntimeCandidates(executable) {
14159
+ const candidates = [
14160
+ `${dirname4(executable)}/bun`,
14161
+ process.env["BUN_INSTALL"] ? `${process.env["BUN_INSTALL"]}/bin/bun` : null,
14162
+ process.env["HOME"] ? `${process.env["HOME"]}/.bun/bin/bun` : null,
14163
+ ...(process.env["PATH"] ?? "").split(delimiter).filter(Boolean).map((entry) => `${entry}/bun`)
14164
+ ].filter((value) => Boolean(value));
14165
+ return [...new Set(candidates)];
14166
+ }
14167
+ function isBunShebangScript(executable) {
14168
+ try {
14169
+ const content = readFileSync4(executable, "utf8").slice(0, 256);
14170
+ const firstLine2 = content.split(/\r?\n/, 1)[0] ?? "";
14171
+ return /^#!.*\bbun\b/.test(firstLine2);
14172
+ } catch {
14173
+ return false;
14174
+ }
14175
+ }
14176
+ function isExecutableFile(path) {
14177
+ if (!existsSync6(path))
14178
+ return false;
14179
+ try {
14180
+ const stats = statSync(path);
14181
+ return stats.isFile() && (stats.mode & 73) !== 0;
14182
+ } catch {
14183
+ return false;
14184
+ }
14152
14185
  }
14153
14186
  function launchdDomain(options) {
14154
14187
  return options.mode === "system" ? "system" : "gui/$UID";
@@ -14430,7 +14463,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
14430
14463
  };
14431
14464
  }
14432
14465
  // src/commands/notifications.ts
14433
- import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
14466
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
14434
14467
  var notificationChannelSchema = exports_external.object({
14435
14468
  id: exports_external.string(),
14436
14469
  type: exports_external.enum(["email", "webhook", "command"]),
@@ -14589,7 +14622,7 @@ function readNotificationConfig(path = getNotificationsPath()) {
14589
14622
  if (!existsSync7(path)) {
14590
14623
  return getDefaultNotificationConfig();
14591
14624
  }
14592
- return notificationConfigSchema.parse(JSON.parse(readFileSync4(path, "utf8")));
14625
+ return notificationConfigSchema.parse(JSON.parse(readFileSync5(path, "utf8")));
14593
14626
  }
14594
14627
  function writeNotificationConfig(config, path = getNotificationsPath()) {
14595
14628
  ensureParentDir(path);
@@ -14830,7 +14863,8 @@ function parseJsonObject2(value) {
14830
14863
  return null;
14831
14864
  }
14832
14865
  }
14833
- function getStatus() {
14866
+ function getStatus(options = {}) {
14867
+ const privateMetadata = options.privateMetadata === true;
14834
14868
  const manifest = readManifest();
14835
14869
  const heartbeats = listHeartbeats();
14836
14870
  const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
@@ -14839,17 +14873,17 @@ function getStatus() {
14839
14873
  ...heartbeats.map((heartbeat) => heartbeat.machine_id)
14840
14874
  ]);
14841
14875
  return {
14842
- machineId: getLocalMachineId(),
14843
- manifestPath: getManifestPath(),
14844
- dbPath: getDbPath(),
14845
- notificationsPath: getNotificationsPath(),
14876
+ machineId: privateMetadata ? getLocalMachineId() : REDACTED_VALUE,
14877
+ manifestPath: privateMetadata ? getManifestPath() : REDACTED_VALUE,
14878
+ dbPath: privateMetadata ? getDbPath() : REDACTED_VALUE,
14879
+ notificationsPath: privateMetadata ? getNotificationsPath() : REDACTED_VALUE,
14846
14880
  manifestMachineCount: manifest.machines.length,
14847
14881
  heartbeatCount: heartbeats.length,
14848
14882
  machines: [...machineIds].sort().map((machineId) => {
14849
14883
  const declared = manifest.machines.find((machine) => machine.id === machineId);
14850
14884
  const heartbeat = heartbeatByMachine.get(machineId);
14851
14885
  return {
14852
- machineId,
14886
+ machineId: privateMetadata ? machineId : REDACTED_VALUE,
14853
14887
  platform: declared?.platform,
14854
14888
  manifestDeclared: Boolean(declared),
14855
14889
  heartbeatStatus: heartbeat?.status || "unknown",
@@ -14857,7 +14891,7 @@ function getStatus() {
14857
14891
  daemonVersion: heartbeat?.daemon_version ?? null,
14858
14892
  agentMode: heartbeat?.agent_mode ?? null,
14859
14893
  storageSyncStatus: heartbeat?.storage_sync_status ?? null,
14860
- doctorSummary: parseJsonObject2(heartbeat?.doctor_summary_json),
14894
+ doctorSummary: privateMetadata ? parseJsonObject2(heartbeat?.doctor_summary_json) : null,
14861
14895
  privateMetadata: Boolean(heartbeat?.private_metadata)
14862
14896
  };
14863
14897
  }),
@@ -15099,7 +15133,7 @@ function startDashboardServer(options = {}) {
15099
15133
  return Response.json({ ok: true, ...getServeInfo(options) });
15100
15134
  }
15101
15135
  if (url.pathname === "/api/status") {
15102
- return Response.json(getStatus());
15136
+ return Response.json(appendWarnings(getStatus({ privateMetadata }), privateWarnings));
15103
15137
  }
15104
15138
  if (url.pathname === "/api/topology") {
15105
15139
  const topology = discoverMachineTopology({ includeTailscale: url.searchParams.get("tailscale") !== "false" });
@@ -15237,15 +15271,16 @@ function check(id, status, summary, detail) {
15237
15271
  function runSelfTest() {
15238
15272
  const version = getPackageVersion();
15239
15273
  const status = getStatus();
15274
+ const machineId = getLocalMachineId();
15240
15275
  const doctor = runDoctor();
15241
15276
  const serveInfo = getServeInfo();
15242
15277
  const html = renderDashboardHtml();
15243
15278
  const notifications = listNotificationChannels();
15244
- const apps = listApps(status.machineId);
15245
- const appsDiff = diffApps(status.machineId);
15246
- const cliPlan = buildClaudeInstallPlan(status.machineId);
15279
+ const apps = listApps(machineId);
15280
+ const appsDiff = diffApps(machineId);
15281
+ const cliPlan = buildClaudeInstallPlan(machineId);
15247
15282
  return {
15248
- machineId: getLocalMachineId(),
15283
+ machineId,
15249
15284
  checks: [
15250
15285
  check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
15251
15286
  check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
@@ -15526,7 +15561,7 @@ function buildScreenEnableCommand(machineId, options = {}) {
15526
15561
  };
15527
15562
  }
15528
15563
  // src/commands/sync.ts
15529
- import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync5, symlinkSync, copyFileSync } from "fs";
15564
+ import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync6, symlinkSync, copyFileSync } from "fs";
15530
15565
  import { homedir as homedir5 } from "os";
15531
15566
  function quote4(value) {
15532
15567
  return `'${value.replace(/'/g, `'\\''`)}'`;
@@ -15586,8 +15621,8 @@ function detectFileActions(machine) {
15586
15621
  if (file.mode === "symlink") {
15587
15622
  status = lstatSync(file.target).isSymbolicLink() ? "ok" : "drifted";
15588
15623
  } else {
15589
- const source = readFileSync5(file.source, "utf8");
15590
- const target = readFileSync5(file.target, "utf8");
15624
+ const source = readFileSync6(file.source, "utf8");
15625
+ const target = readFileSync6(file.target, "utf8");
15591
15626
  status = source === target ? "ok" : "drifted";
15592
15627
  }
15593
15628
  }
@@ -24815,14 +24850,17 @@ function privateOutputWarnings2(requested, allowed) {
24815
24850
  function appendWarnings2(payload, warnings) {
24816
24851
  if (warnings.length === 0)
24817
24852
  return payload;
24818
- return { ...payload, warnings: [...payload.warnings ?? [], ...warnings] };
24853
+ const currentWarnings = typeof payload === "object" && payload && "warnings" in payload && Array.isArray(payload.warnings) ? payload.warnings : [];
24854
+ return { ...payload, warnings: [...currentWarnings, ...warnings] };
24819
24855
  }
24820
24856
  function createMcpServer(version2) {
24821
24857
  const server = new McpServer({ name: "machines", version: version2 });
24822
24858
  const events = new EventsClient3;
24823
- server.tool("machines_status", "Return local machine fleet status paths and machine identity.", {}, async () => ({
24824
- content: [{ type: "text", text: JSON.stringify(getStatus(), null, 2) }]
24825
- }));
24859
+ server.tool("machines_status", "Return local machine fleet status paths and machine identity.", { private_metadata: exports_external.boolean().optional().describe("Include private local paths and machine identifiers") }, async ({ private_metadata }) => {
24860
+ const privateMetadata = privateMetadataAllowed(private_metadata);
24861
+ const warnings = privateOutputWarnings2(private_metadata, privateMetadata);
24862
+ return { content: [{ type: "text", text: JSON.stringify(appendWarnings2(getStatus({ privateMetadata }), warnings), null, 2) }] };
24863
+ });
24826
24864
  server.tool("machines_doctor", "Run machine preflight checks.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({ content: [{ type: "text", text: JSON.stringify(runDoctor(machine_id), null, 2) }] }));
24827
24865
  server.tool("machines_self_test", "Run local package smoke checks.", {}, async () => ({
24828
24866
  content: [{ type: "text", text: JSON.stringify(runSelfTest(), null, 2) }]
@@ -25003,9 +25041,23 @@ function createMcpServer(version2) {
25003
25041
  }), null, 2)
25004
25042
  }]
25005
25043
  }));
25006
- server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", { machine_id: exports_external.string().describe("Machine identifier"), remote_command: exports_external.string().optional().describe("Optional remote command") }, async ({ machine_id, remote_command }) => ({
25007
- content: [{ type: "text", text: JSON.stringify({ resolved: resolveMachineRoute(machine_id), command: buildSshCommand(machine_id, remote_command) }, null, 2) }]
25008
- }));
25044
+ server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
25045
+ machine_id: exports_external.string().describe("Machine identifier"),
25046
+ remote_command: exports_external.string().optional().describe("Optional remote command"),
25047
+ private_metadata: exports_external.boolean().optional().describe("Include private SSH target and command")
25048
+ }, async ({ machine_id, remote_command, private_metadata }) => {
25049
+ const privateMetadata = privateMetadataAllowed(private_metadata);
25050
+ const warnings = privateOutputWarnings2(private_metadata, privateMetadata);
25051
+ const resolved = resolveMachineRoute(machine_id);
25052
+ const publicResolved = redactRouteForOutput(resolved, { privateMetadata });
25053
+ const command2 = resolved.ok && privateMetadata ? buildSshCommand(machine_id, remote_command) : resolved.ok ? "[redacted]" : null;
25054
+ return {
25055
+ content: [{
25056
+ type: "text",
25057
+ text: JSON.stringify(appendWarnings2({ resolved: publicResolved, command: command2 }, warnings), null, 2)
25058
+ }]
25059
+ };
25060
+ });
25009
25061
  server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
25010
25062
  content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
25011
25063
  }));
package/dist/mcp/index.js CHANGED
@@ -5954,8 +5954,8 @@ function diffMachines(leftMachineId, rightMachineId) {
5954
5954
  }
5955
5955
 
5956
5956
  // src/commands/daemon.ts
5957
- import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
5958
- import { dirname as dirname4 } from "path";
5957
+ import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync4, statSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
5958
+ import { delimiter, dirname as dirname4 } from "path";
5959
5959
  import { platform as osPlatform } from "os";
5960
5960
  var DEFAULT_SERVICE_NAME = "machines-agent";
5961
5961
  var DEFAULT_EXECUTABLE = "/usr/local/bin/machines-agent";
@@ -6219,13 +6219,46 @@ WantedBy=${options.mode === "system" ? "multi-user.target" : "default.target"}
6219
6219
  `;
6220
6220
  }
6221
6221
  function daemonProgramArguments(options) {
6222
- const bunRuntime = siblingBunRuntime(options.executable);
6222
+ const bunRuntime = bunRuntimeForExecutable(options.executable);
6223
6223
  const base = bunRuntime ? [bunRuntime, options.executable] : [options.executable];
6224
6224
  return [...base, "--interval-ms", String(options.intervalMs)];
6225
6225
  }
6226
- function siblingBunRuntime(executable) {
6227
- const candidate = `${dirname4(executable)}/bun`;
6228
- return existsSync6(candidate) ? candidate : null;
6226
+ function bunRuntimeForExecutable(executable) {
6227
+ if (!isBunShebangScript(executable))
6228
+ return null;
6229
+ for (const candidate of bunRuntimeCandidates(executable)) {
6230
+ if (isExecutableFile(candidate))
6231
+ return candidate;
6232
+ }
6233
+ return null;
6234
+ }
6235
+ function bunRuntimeCandidates(executable) {
6236
+ const candidates = [
6237
+ `${dirname4(executable)}/bun`,
6238
+ process.env["BUN_INSTALL"] ? `${process.env["BUN_INSTALL"]}/bin/bun` : null,
6239
+ process.env["HOME"] ? `${process.env["HOME"]}/.bun/bin/bun` : null,
6240
+ ...(process.env["PATH"] ?? "").split(delimiter).filter(Boolean).map((entry) => `${entry}/bun`)
6241
+ ].filter((value) => Boolean(value));
6242
+ return [...new Set(candidates)];
6243
+ }
6244
+ function isBunShebangScript(executable) {
6245
+ try {
6246
+ const content = readFileSync4(executable, "utf8").slice(0, 256);
6247
+ const firstLine = content.split(/\r?\n/, 1)[0] ?? "";
6248
+ return /^#!.*\bbun\b/.test(firstLine);
6249
+ } catch {
6250
+ return false;
6251
+ }
6252
+ }
6253
+ function isExecutableFile(path) {
6254
+ if (!existsSync6(path))
6255
+ return false;
6256
+ try {
6257
+ const stats = statSync(path);
6258
+ return stats.isFile() && (stats.mode & 73) !== 0;
6259
+ } catch {
6260
+ return false;
6261
+ }
6229
6262
  }
6230
6263
  function launchdDomain(options) {
6231
6264
  return options.mode === "system" ? "system" : "gui/$UID";
@@ -6621,7 +6654,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
6621
6654
  }
6622
6655
 
6623
6656
  // src/commands/notifications.ts
6624
- import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
6657
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
6625
6658
  var notificationChannelSchema = exports_external.object({
6626
6659
  id: exports_external.string(),
6627
6660
  type: exports_external.enum(["email", "webhook", "command"]),
@@ -6780,7 +6813,7 @@ function readNotificationConfig(path = getNotificationsPath()) {
6780
6813
  if (!existsSync7(path)) {
6781
6814
  return getDefaultNotificationConfig();
6782
6815
  }
6783
- return notificationConfigSchema.parse(JSON.parse(readFileSync4(path, "utf8")));
6816
+ return notificationConfigSchema.parse(JSON.parse(readFileSync5(path, "utf8")));
6784
6817
  }
6785
6818
  function writeNotificationConfig(config, path = getNotificationsPath()) {
6786
6819
  ensureParentDir(path);
@@ -7408,7 +7441,8 @@ function parseJsonObject2(value) {
7408
7441
  return null;
7409
7442
  }
7410
7443
  }
7411
- function getStatus() {
7444
+ function getStatus(options = {}) {
7445
+ const privateMetadata = options.privateMetadata === true;
7412
7446
  const manifest = readManifest();
7413
7447
  const heartbeats = listHeartbeats();
7414
7448
  const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
@@ -7417,17 +7451,17 @@ function getStatus() {
7417
7451
  ...heartbeats.map((heartbeat) => heartbeat.machine_id)
7418
7452
  ]);
7419
7453
  return {
7420
- machineId: getLocalMachineId(),
7421
- manifestPath: getManifestPath(),
7422
- dbPath: getDbPath(),
7423
- notificationsPath: getNotificationsPath(),
7454
+ machineId: privateMetadata ? getLocalMachineId() : REDACTED_VALUE,
7455
+ manifestPath: privateMetadata ? getManifestPath() : REDACTED_VALUE,
7456
+ dbPath: privateMetadata ? getDbPath() : REDACTED_VALUE,
7457
+ notificationsPath: privateMetadata ? getNotificationsPath() : REDACTED_VALUE,
7424
7458
  manifestMachineCount: manifest.machines.length,
7425
7459
  heartbeatCount: heartbeats.length,
7426
7460
  machines: [...machineIds].sort().map((machineId) => {
7427
7461
  const declared = manifest.machines.find((machine) => machine.id === machineId);
7428
7462
  const heartbeat = heartbeatByMachine.get(machineId);
7429
7463
  return {
7430
- machineId,
7464
+ machineId: privateMetadata ? machineId : REDACTED_VALUE,
7431
7465
  platform: declared?.platform,
7432
7466
  manifestDeclared: Boolean(declared),
7433
7467
  heartbeatStatus: heartbeat?.status || "unknown",
@@ -7435,7 +7469,7 @@ function getStatus() {
7435
7469
  daemonVersion: heartbeat?.daemon_version ?? null,
7436
7470
  agentMode: heartbeat?.agent_mode ?? null,
7437
7471
  storageSyncStatus: heartbeat?.storage_sync_status ?? null,
7438
- doctorSummary: parseJsonObject2(heartbeat?.doctor_summary_json),
7472
+ doctorSummary: privateMetadata ? parseJsonObject2(heartbeat?.doctor_summary_json) : null,
7439
7473
  privateMetadata: Boolean(heartbeat?.private_metadata)
7440
7474
  };
7441
7475
  }),
@@ -7451,15 +7485,16 @@ function check(id, status, summary, detail) {
7451
7485
  function runSelfTest() {
7452
7486
  const version = getPackageVersion();
7453
7487
  const status = getStatus();
7488
+ const machineId = getLocalMachineId();
7454
7489
  const doctor = runDoctor();
7455
7490
  const serveInfo = getServeInfo();
7456
7491
  const html = renderDashboardHtml();
7457
7492
  const notifications = listNotificationChannels();
7458
- const apps = listApps(status.machineId);
7459
- const appsDiff = diffApps(status.machineId);
7460
- const cliPlan = buildClaudeInstallPlan(status.machineId);
7493
+ const apps = listApps(machineId);
7494
+ const appsDiff = diffApps(machineId);
7495
+ const cliPlan = buildClaudeInstallPlan(machineId);
7461
7496
  return {
7462
- machineId: getLocalMachineId(),
7497
+ machineId,
7463
7498
  checks: [
7464
7499
  check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
7465
7500
  check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
@@ -7818,7 +7853,7 @@ function runSetup(machineId, options = {}, runner = runMachineCommand) {
7818
7853
  }
7819
7854
 
7820
7855
  // src/commands/sync.ts
7821
- import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync5, symlinkSync, copyFileSync } from "fs";
7856
+ import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync6, symlinkSync, copyFileSync } from "fs";
7822
7857
  import { homedir as homedir5 } from "os";
7823
7858
  function quote4(value) {
7824
7859
  return `'${value.replace(/'/g, `'\\''`)}'`;
@@ -7878,8 +7913,8 @@ function detectFileActions(machine) {
7878
7913
  if (file.mode === "symlink") {
7879
7914
  status = lstatSync(file.target).isSymbolicLink() ? "ok" : "drifted";
7880
7915
  } else {
7881
- const source = readFileSync5(file.source, "utf8");
7882
- const target = readFileSync5(file.target, "utf8");
7916
+ const source = readFileSync6(file.source, "utf8");
7917
+ const target = readFileSync6(file.target, "utf8");
7883
7918
  status = source === target ? "ok" : "drifted";
7884
7919
  }
7885
7920
  }
@@ -8229,14 +8264,17 @@ function privateOutputWarnings(requested, allowed) {
8229
8264
  function appendWarnings(payload, warnings) {
8230
8265
  if (warnings.length === 0)
8231
8266
  return payload;
8232
- return { ...payload, warnings: [...payload.warnings ?? [], ...warnings] };
8267
+ const currentWarnings = typeof payload === "object" && payload && "warnings" in payload && Array.isArray(payload.warnings) ? payload.warnings : [];
8268
+ return { ...payload, warnings: [...currentWarnings, ...warnings] };
8233
8269
  }
8234
8270
  function createMcpServer(version) {
8235
8271
  const server = new McpServer({ name: "machines", version });
8236
8272
  const events = new EventsClient2;
8237
- server.tool("machines_status", "Return local machine fleet status paths and machine identity.", {}, async () => ({
8238
- content: [{ type: "text", text: JSON.stringify(getStatus(), null, 2) }]
8239
- }));
8273
+ server.tool("machines_status", "Return local machine fleet status paths and machine identity.", { private_metadata: exports_external.boolean().optional().describe("Include private local paths and machine identifiers") }, async ({ private_metadata }) => {
8274
+ const privateMetadata = privateMetadataAllowed(private_metadata);
8275
+ const warnings = privateOutputWarnings(private_metadata, privateMetadata);
8276
+ return { content: [{ type: "text", text: JSON.stringify(appendWarnings(getStatus({ privateMetadata }), warnings), null, 2) }] };
8277
+ });
8240
8278
  server.tool("machines_doctor", "Run machine preflight checks.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({ content: [{ type: "text", text: JSON.stringify(runDoctor(machine_id), null, 2) }] }));
8241
8279
  server.tool("machines_self_test", "Run local package smoke checks.", {}, async () => ({
8242
8280
  content: [{ type: "text", text: JSON.stringify(runSelfTest(), null, 2) }]
@@ -8417,9 +8455,23 @@ function createMcpServer(version) {
8417
8455
  }), null, 2)
8418
8456
  }]
8419
8457
  }));
8420
- server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", { machine_id: exports_external.string().describe("Machine identifier"), remote_command: exports_external.string().optional().describe("Optional remote command") }, async ({ machine_id, remote_command }) => ({
8421
- content: [{ type: "text", text: JSON.stringify({ resolved: resolveMachineRoute(machine_id), command: buildSshCommand(machine_id, remote_command) }, null, 2) }]
8422
- }));
8458
+ server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
8459
+ machine_id: exports_external.string().describe("Machine identifier"),
8460
+ remote_command: exports_external.string().optional().describe("Optional remote command"),
8461
+ private_metadata: exports_external.boolean().optional().describe("Include private SSH target and command")
8462
+ }, async ({ machine_id, remote_command, private_metadata }) => {
8463
+ const privateMetadata = privateMetadataAllowed(private_metadata);
8464
+ const warnings = privateOutputWarnings(private_metadata, privateMetadata);
8465
+ const resolved = resolveMachineRoute(machine_id);
8466
+ const publicResolved = redactRouteForOutput(resolved, { privateMetadata });
8467
+ const command2 = resolved.ok && privateMetadata ? buildSshCommand(machine_id, remote_command) : resolved.ok ? "[redacted]" : null;
8468
+ return {
8469
+ content: [{
8470
+ type: "text",
8471
+ text: JSON.stringify(appendWarnings({ resolved: publicResolved, command: command2 }, warnings), null, 2)
8472
+ }]
8473
+ };
8474
+ });
8423
8475
  server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
8424
8476
  content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
8425
8477
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiCpE,eAAO,MAAM,sBAAsB,k9CA2DzB,CAAC;AAEX,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAA4B,GAAG,SAAS,CAE5E;AAeD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAojB1D"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiCpE,eAAO,MAAM,sBAAsB,k9CA2DzB,CAAC;AAEX,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAA4B,GAAG,SAAS,CAE5E;AAkBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAykB1D"}
package/dist/types.d.ts CHANGED
@@ -116,6 +116,7 @@ export interface FleetStatus {
116
116
  machines: FleetStatusMachine[];
117
117
  recentSetupRuns: number;
118
118
  recentSyncRuns: number;
119
+ warnings?: string[];
119
120
  }
120
121
  export type NotificationChannelType = "email" | "webhook" | "command";
121
122
  export interface NotificationChannel {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/machines",
3
- "version": "0.0.43",
3
+ "version": "0.0.45",
4
4
  "description": "Machine fleet management CLI + MCP for developers",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",