@hasna/machines 0.0.15 → 0.0.17

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/dist/index.js CHANGED
@@ -11085,9 +11085,31 @@ function detectCurrentMachineManifest() {
11085
11085
  };
11086
11086
  }
11087
11087
  // src/topology.ts
11088
- import { existsSync as existsSync3 } from "fs";
11088
+ import { existsSync as existsSync4 } from "fs";
11089
11089
  import { arch as arch2, hostname as hostname3, platform as platform2, userInfo as userInfo2 } from "os";
11090
11090
  import { spawnSync } from "child_process";
11091
+
11092
+ // src/version.ts
11093
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
11094
+ import { dirname as dirname3, join as join2 } from "path";
11095
+ import { fileURLToPath } from "url";
11096
+ function getPackageVersion() {
11097
+ try {
11098
+ const here = dirname3(fileURLToPath(import.meta.url));
11099
+ const candidates = [join2(here, "..", "package.json"), join2(here, "..", "..", "package.json")];
11100
+ const pkgPath = candidates.find((candidate) => existsSync3(candidate));
11101
+ if (!pkgPath) {
11102
+ return "0.0.0";
11103
+ }
11104
+ return JSON.parse(readFileSync2(pkgPath, "utf8")).version || "0.0.0";
11105
+ } catch {
11106
+ return "0.0.0";
11107
+ }
11108
+ }
11109
+
11110
+ // src/topology.ts
11111
+ var MACHINES_CONSUMER_CONTRACT_VERSION = 1;
11112
+ var MACHINES_PACKAGE_NAME = "@hasna/machines";
11091
11113
  function normalizePlatform2(value = platform2()) {
11092
11114
  const normalized = value.toLowerCase();
11093
11115
  if (normalized === "darwin" || normalized === "macos")
@@ -11169,16 +11191,26 @@ function findTailscalePeer(machine, machineId, peers) {
11169
11191
  }
11170
11192
  return peers.get(machineId) ?? null;
11171
11193
  }
11194
+ function envReachableHosts() {
11195
+ const raw = process.env["HASNA_MACHINES_REACHABLE_HOSTS"];
11196
+ return new Set((raw || "").split(",").map((value) => value.trim()).filter(Boolean));
11197
+ }
11198
+ function manifestHostReachable(target) {
11199
+ const overrides = envReachableHosts();
11200
+ if (overrides.size === 0)
11201
+ return null;
11202
+ return overrides.has(target);
11203
+ }
11172
11204
  function routeHints(input) {
11173
11205
  const hints = [];
11174
11206
  if (input.machineId === input.localMachineId) {
11175
11207
  hints.push({ kind: "local", target: "localhost", reachable: true });
11176
11208
  }
11177
11209
  if (input.manifest?.sshAddress) {
11178
- hints.push({ kind: "ssh", target: input.manifest.sshAddress, reachable: null });
11210
+ hints.push({ kind: "ssh", target: input.manifest.sshAddress, reachable: manifestHostReachable(input.manifest.sshAddress) });
11179
11211
  }
11180
11212
  if (input.manifest?.hostname) {
11181
- hints.push({ kind: "lan", target: input.manifest.hostname, reachable: null });
11213
+ hints.push({ kind: "lan", target: input.manifest.hostname, reachable: manifestHostReachable(input.manifest.hostname) });
11182
11214
  }
11183
11215
  const tailscaleTarget = input.manifest?.tailscaleName ?? input.peer?.DNSName ?? input.peer?.TailscaleIPs?.[0];
11184
11216
  if (tailscaleTarget) {
@@ -11186,6 +11218,28 @@ function routeHints(input) {
11186
11218
  }
11187
11219
  return hints;
11188
11220
  }
11221
+ function routeRank(hint) {
11222
+ if (hint.kind === "local")
11223
+ return 0;
11224
+ if (hint.reachable === true && hint.kind === "ssh")
11225
+ return 1;
11226
+ if (hint.reachable === true && hint.kind === "lan")
11227
+ return 2;
11228
+ if (hint.reachable === true && hint.kind === "tailscale")
11229
+ return 3;
11230
+ if (hint.reachable === false)
11231
+ return 8;
11232
+ if (hint.kind === "ssh")
11233
+ return 4;
11234
+ if (hint.kind === "lan")
11235
+ return 5;
11236
+ if (hint.kind === "tailscale")
11237
+ return 6;
11238
+ return 9;
11239
+ }
11240
+ function selectRouteHint(hints) {
11241
+ return [...hints].sort((left, right) => routeRank(left) - routeRank(right))[0] ?? null;
11242
+ }
11189
11243
  function buildEntry(input) {
11190
11244
  const manifest = input.manifest;
11191
11245
  const peer = input.peer;
@@ -11195,8 +11249,8 @@ function buildEntry(input) {
11195
11249
  manifest,
11196
11250
  peer
11197
11251
  });
11198
- const selectedRoute = hints.find((hint) => hint.kind === "local") ?? hints.find((hint) => hint.kind === "ssh") ?? hints.find((hint) => hint.kind === "lan") ?? hints.find((hint) => hint.kind === "tailscale");
11199
- const route = selectedRoute?.kind === "ssh" ? "lan" : selectedRoute?.kind ?? "unknown";
11252
+ const selectedRoute = selectRouteHint(hints);
11253
+ const route = selectedRoute?.kind === "ssh" ? "ssh" : selectedRoute?.kind ?? "unknown";
11200
11254
  return {
11201
11255
  machine_id: input.machineId,
11202
11256
  hostname: manifest?.hostname ?? peer?.HostName ?? null,
@@ -11251,15 +11305,140 @@ function discoverMachineTopology(options = {}) {
11251
11305
  });
11252
11306
  });
11253
11307
  return {
11308
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
11309
+ package: {
11310
+ name: MACHINES_PACKAGE_NAME,
11311
+ version: getPackageVersion()
11312
+ },
11313
+ capabilities: {
11314
+ topology: true,
11315
+ compatibility: true,
11316
+ route_resolution: true,
11317
+ cli_json_fallback: true
11318
+ },
11254
11319
  generated_at: now.toISOString(),
11255
11320
  local_machine_id: localMachineId,
11256
11321
  local_hostname: hostname3(),
11257
11322
  current_platform: normalizePlatform2(),
11258
- manifest_path_known: existsSync3(getManifestPath()),
11323
+ manifest_path_known: existsSync4(getManifestPath()),
11259
11324
  machines,
11260
11325
  warnings
11261
11326
  };
11262
11327
  }
11328
+ function normalizeMachineAlias(value) {
11329
+ return value.trim().replace(/\.$/, "").toLowerCase();
11330
+ }
11331
+ function routeTargetMatches(machine, requested) {
11332
+ const normalized = normalizeMachineAlias(requested);
11333
+ const values = [
11334
+ machine.ssh.address,
11335
+ machine.ssh.command_target,
11336
+ machine.tailscale.dns_name,
11337
+ machine.tailscale.dns_name?.split(".")[0],
11338
+ ...machine.tailscale.ips,
11339
+ ...machine.route_hints.map((hint) => hint.target),
11340
+ ...machine.route_hints.map((hint) => hint.target.split("@").pop() ?? hint.target)
11341
+ ].filter((value) => Boolean(value));
11342
+ return values.some((value) => normalizeMachineAlias(value) === normalized);
11343
+ }
11344
+ function findRouteMachine(topology, requestedMachineId) {
11345
+ const requested = normalizeMachineAlias(requestedMachineId);
11346
+ if (requested === "local" || requested === "localhost" || requested === normalizeMachineAlias(hostname3()) || requested === normalizeMachineAlias(topology.local_machine_id)) {
11347
+ return {
11348
+ machine: topology.machines.find((machine) => machine.machine_id === topology.local_machine_id) ?? null,
11349
+ matchedBy: "local_alias"
11350
+ };
11351
+ }
11352
+ const machineIdMatch = topology.machines.find((machine) => normalizeMachineAlias(machine.machine_id) === requested);
11353
+ if (machineIdMatch)
11354
+ return { machine: machineIdMatch, matchedBy: "machine_id" };
11355
+ const hostnameMatch = topology.machines.find((machine) => machine.hostname && normalizeMachineAlias(machine.hostname) === requested);
11356
+ if (hostnameMatch)
11357
+ return { machine: hostnameMatch, matchedBy: "hostname" };
11358
+ const tailscaleMatch = topology.machines.find((machine) => {
11359
+ if (!machine.tailscale.dns_name)
11360
+ return false;
11361
+ const dns = normalizeMachineAlias(machine.tailscale.dns_name);
11362
+ return dns === requested || dns.split(".")[0] === requested;
11363
+ });
11364
+ if (tailscaleMatch)
11365
+ return { machine: tailscaleMatch, matchedBy: "tailscale" };
11366
+ const routeMatch = topology.machines.find((machine) => routeTargetMatches(machine, requestedMachineId));
11367
+ if (routeMatch)
11368
+ return { machine: routeMatch, matchedBy: "route_target" };
11369
+ return { machine: null, matchedBy: null };
11370
+ }
11371
+ function routeConfidence(input) {
11372
+ if (input.matchedBy === "local_alias")
11373
+ return "exact";
11374
+ if (input.hint?.kind === "local")
11375
+ return "exact";
11376
+ if (input.hint?.reachable === true)
11377
+ return "high";
11378
+ if (input.machine.manifest_declared && (input.hint?.kind === "ssh" || input.hint?.kind === "lan"))
11379
+ return "medium";
11380
+ if (input.hint)
11381
+ return "low";
11382
+ return "none";
11383
+ }
11384
+ function resolveMachineRoute(machineId, options = {}) {
11385
+ const topology = options.topology ?? discoverMachineTopology(options);
11386
+ const warnings = [...topology.warnings];
11387
+ const { machine, matchedBy } = findRouteMachine(topology, machineId);
11388
+ const generatedAt = (options.now ?? new Date).toISOString();
11389
+ if (!machine) {
11390
+ warnings.push(`machine_not_found:${machineId}`);
11391
+ return {
11392
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
11393
+ package: { name: MACHINES_PACKAGE_NAME, version: getPackageVersion() },
11394
+ ok: false,
11395
+ machine_id: null,
11396
+ requested_machine_id: machineId,
11397
+ generated_at: generatedAt,
11398
+ route: "unknown",
11399
+ source: "unknown",
11400
+ target: null,
11401
+ command_target: null,
11402
+ confidence: "none",
11403
+ local: false,
11404
+ evidence: {
11405
+ topology: true,
11406
+ matched_by: null,
11407
+ manifest_declared: null,
11408
+ heartbeat_status: null,
11409
+ tailscale_online: null,
11410
+ selected_hint: null
11411
+ },
11412
+ warnings
11413
+ };
11414
+ }
11415
+ const selectedHint = selectRouteHint(machine.route_hints);
11416
+ const route = selectedHint?.kind ?? machine.ssh.route ?? "unknown";
11417
+ const local = route === "local" || machine.machine_id === topology.local_machine_id;
11418
+ return {
11419
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
11420
+ package: topology.package,
11421
+ ok: Boolean(selectedHint?.target),
11422
+ machine_id: machine.machine_id,
11423
+ requested_machine_id: machineId,
11424
+ generated_at: generatedAt,
11425
+ route,
11426
+ source: route,
11427
+ target: selectedHint?.target ?? null,
11428
+ command_target: selectedHint?.target ?? null,
11429
+ confidence: routeConfidence({ machine, hint: selectedHint, matchedBy }),
11430
+ local,
11431
+ evidence: {
11432
+ topology: true,
11433
+ matched_by: matchedBy,
11434
+ manifest_declared: machine.manifest_declared,
11435
+ heartbeat_status: machine.heartbeat_status,
11436
+ tailscale_online: machine.tailscale.online,
11437
+ selected_hint: selectedHint
11438
+ },
11439
+ warnings
11440
+ };
11441
+ }
11263
11442
  function getLocalMachineTopology(options = {}) {
11264
11443
  const topology = discoverMachineTopology(options);
11265
11444
  return topology.machines.find((machine) => machine.machine_id === topology.local_machine_id) ?? {
@@ -11280,88 +11459,70 @@ function getLocalMachineTopology(options = {}) {
11280
11459
  };
11281
11460
  }
11282
11461
  // src/remote.ts
11283
- import { spawnSync as spawnSync3 } from "child_process";
11462
+ import { spawnSync as spawnSync2 } from "child_process";
11463
+ import { hostname as hostname4 } from "os";
11284
11464
 
11285
11465
  // src/commands/ssh.ts
11286
- import { spawnSync as spawnSync2 } from "child_process";
11287
- function envReachableHosts() {
11288
- const raw = process.env["HASNA_MACHINES_REACHABLE_HOSTS"];
11289
- return new Set((raw || "").split(",").map((value) => value.trim()).filter(Boolean));
11290
- }
11291
- function isReachable(host) {
11292
- const overrides = envReachableHosts();
11293
- if (overrides.size > 0) {
11294
- return overrides.has(host);
11466
+ function resolveSshTarget(machineId, options = {}) {
11467
+ const resolved = resolveMachineRoute(machineId, options);
11468
+ if (!resolved.ok || !resolved.target) {
11469
+ throw new Error(`Machine route not found: ${machineId}`);
11295
11470
  }
11296
- const probe = spawnSync2("bash", ["-lc", `getent hosts ${host} >/dev/null 2>&1 || ping -c 1 -W 1 ${host} >/dev/null 2>&1`], {
11297
- stdio: "ignore"
11298
- });
11299
- return probe.status === 0;
11300
- }
11301
- function resolveSshTarget(machineId) {
11302
- const machine = getManifestMachine(machineId);
11303
- if (!machine) {
11304
- throw new Error(`Machine not found in manifest: ${machineId}`);
11471
+ if (resolved.route !== "local" && resolved.route !== "lan" && resolved.route !== "tailscale" && resolved.route !== "ssh") {
11472
+ throw new Error(`Machine route is not SSH-capable: ${machineId}`);
11305
11473
  }
11306
- const current = detectCurrentMachineManifest();
11307
- if (machine.id === current.id) {
11308
- return {
11309
- machineId,
11310
- target: "localhost",
11311
- route: "local"
11312
- };
11313
- }
11314
- const lanTarget = machine.sshAddress || machine.hostname || machine.id;
11315
- const tailscaleTarget = machine.tailscaleName || machine.hostname || machine.id;
11316
- const route = isReachable(lanTarget) ? "lan" : "tailscale";
11317
11474
  return {
11318
- machineId,
11319
- target: route === "lan" ? lanTarget : tailscaleTarget,
11320
- route
11475
+ machineId: resolved.machine_id ?? machineId,
11476
+ target: resolved.target,
11477
+ route: resolved.route,
11478
+ confidence: resolved.confidence,
11479
+ warnings: resolved.warnings
11321
11480
  };
11322
11481
  }
11323
- function buildSshCommand(machineId, remoteCommand) {
11324
- const resolved = resolveSshTarget(machineId);
11482
+ function buildSshCommand(machineId, remoteCommand, options = {}) {
11483
+ const resolved = resolveSshTarget(machineId, options);
11325
11484
  return remoteCommand ? `ssh ${resolved.target} ${JSON.stringify(remoteCommand)}` : `ssh ${resolved.target}`;
11326
11485
  }
11327
11486
 
11328
11487
  // src/remote.ts
11488
+ function shellQuote(value) {
11489
+ return `'${value.replace(/'/g, "'\\''")}'`;
11490
+ }
11491
+ function machineIsLocal(machineId, localMachineId) {
11492
+ return machineId === "local" || machineId === "localhost" || machineId === localMachineId || machineId === hostname4();
11493
+ }
11494
+ function resolveMachineCommand(machineId, command, localMachineId = getLocalMachineId()) {
11495
+ if (machineIsLocal(machineId, localMachineId)) {
11496
+ return { source: "local", shellCommand: command };
11497
+ }
11498
+ try {
11499
+ return {
11500
+ source: resolveSshTarget(machineId).route,
11501
+ shellCommand: buildSshCommand(machineId, command)
11502
+ };
11503
+ } catch (error) {
11504
+ const message = String(error.message ?? error);
11505
+ if (message.includes("Machine route not found") || message.includes("Machine not found in manifest")) {
11506
+ return { source: "ssh", shellCommand: `ssh ${shellQuote(machineId)} ${shellQuote(command)}` };
11507
+ }
11508
+ throw error;
11509
+ }
11510
+ }
11329
11511
  function runMachineCommand(machineId, command) {
11330
- const localMachineId = getLocalMachineId();
11331
- const isLocal = machineId === localMachineId;
11332
- const route = isLocal ? "local" : resolveSshTarget(machineId).route;
11333
- const shellCommand = isLocal ? command : buildSshCommand(machineId, command);
11334
- const result = spawnSync3("bash", ["-c", shellCommand], {
11512
+ const resolved = resolveMachineCommand(machineId, command);
11513
+ const result = spawnSync2("bash", ["-c", resolved.shellCommand], {
11335
11514
  encoding: "utf8",
11336
11515
  env: process.env
11337
11516
  });
11338
11517
  return {
11339
11518
  machineId,
11340
- source: route,
11519
+ source: resolved.source,
11341
11520
  stdout: result.stdout || "",
11342
11521
  stderr: result.stderr || "",
11343
11522
  exitCode: result.status ?? 1
11344
11523
  };
11345
11524
  }
11346
11525
 
11347
- // src/version.ts
11348
- import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
11349
- import { dirname as dirname3, join as join2 } from "path";
11350
- import { fileURLToPath } from "url";
11351
- function getPackageVersion() {
11352
- try {
11353
- const here = dirname3(fileURLToPath(import.meta.url));
11354
- const candidates = [join2(here, "..", "package.json"), join2(here, "..", "..", "package.json")];
11355
- const pkgPath = candidates.find((candidate) => existsSync4(candidate));
11356
- if (!pkgPath) {
11357
- return "0.0.0";
11358
- }
11359
- return JSON.parse(readFileSync2(pkgPath, "utf8")).version || "0.0.0";
11360
- } catch {
11361
- return "0.0.0";
11362
- }
11363
- }
11364
-
11365
11526
  // src/compatibility.ts
11366
11527
  var DEFAULT_COMMANDS = [
11367
11528
  { command: "bun", required: true },
@@ -11370,7 +11531,7 @@ var DEFAULT_COMMANDS = [
11370
11531
  function defaultPackages() {
11371
11532
  return [{ name: "@hasna/machines", command: "machines", expectedVersion: getPackageVersion(), required: true }];
11372
11533
  }
11373
- function shellQuote(value) {
11534
+ function shellQuote2(value) {
11374
11535
  return `'${value.replace(/'/g, "'\\''")}'`;
11375
11536
  }
11376
11537
  function commandId(value) {
@@ -11421,7 +11582,7 @@ function defaultRunner2(machineId, command) {
11421
11582
  return runMachineCommand(machineId, command);
11422
11583
  }
11423
11584
  function inspectCommand(machineId, spec, runner) {
11424
- const command = shellQuote(spec.command);
11585
+ const command = shellQuote2(spec.command);
11425
11586
  const versionArgs = spec.versionArgs ?? "--version";
11426
11587
  const script = [
11427
11588
  `cmd=${command}`,
@@ -11450,7 +11611,7 @@ function fieldCommand(field) {
11450
11611
  }
11451
11612
  function inspectWorkspace(machineId, spec, runner) {
11452
11613
  const script = [
11453
- `path=${shellQuote(spec.path)}`,
11614
+ `path=${shellQuote2(spec.path)}`,
11454
11615
  'printf "exists=%s\\n" "$(test -d "$path" && printf yes || printf no)"',
11455
11616
  'pkg="$path/package.json"',
11456
11617
  'printf "package_json=%s\\n" "$(test -f "$pkg" && printf yes || printf no)"',
@@ -11588,6 +11749,17 @@ function checkMachineCompatibility(options = {}) {
11588
11749
  fail: checks.filter((check) => check.status === "fail").length
11589
11750
  };
11590
11751
  return {
11752
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
11753
+ package: {
11754
+ name: MACHINES_PACKAGE_NAME,
11755
+ version: getPackageVersion()
11756
+ },
11757
+ capabilities: {
11758
+ topology: true,
11759
+ compatibility: true,
11760
+ route_resolution: true,
11761
+ cli_json_fallback: true
11762
+ },
11591
11763
  ok: summary.fail === 0,
11592
11764
  machine_id: machineId,
11593
11765
  source: checks[0]?.source ?? "local",
@@ -11695,7 +11867,7 @@ function getAppManager(machine, app) {
11695
11867
  return "winget";
11696
11868
  return "apt";
11697
11869
  }
11698
- function shellQuote2(value) {
11870
+ function shellQuote3(value) {
11699
11871
  return `'${value.replace(/'/g, `'\\''`)}'`;
11700
11872
  }
11701
11873
  function buildAppCommand(machine, app) {
@@ -11716,7 +11888,7 @@ function buildAppCommand(machine, app) {
11716
11888
  return `sudo apt-get install -y ${packageName}`;
11717
11889
  }
11718
11890
  function buildAppProbeCommand(machine, app) {
11719
- const packageName = shellQuote2(getPackageName(app));
11891
+ const packageName = shellQuote3(getPackageName(app));
11720
11892
  const manager = getAppManager(machine, app);
11721
11893
  if (manager === "custom") {
11722
11894
  return `if command -v ${packageName} >/dev/null 2>&1; then printf 'installed=1\\nversion=custom\\n'; else printf 'installed=0\\n'; fi`;
@@ -12252,7 +12424,7 @@ var notificationConfigSchema = exports_external.object({
12252
12424
  function sortChannels(channels) {
12253
12425
  return [...channels].sort((left, right) => left.id.localeCompare(right.id));
12254
12426
  }
12255
- function shellQuote3(value) {
12427
+ function shellQuote4(value) {
12256
12428
  return `'${value.replace(/'/g, `'\\''`)}'`;
12257
12429
  }
12258
12430
  function hasCommand2(binary) {
@@ -12299,7 +12471,7 @@ ${message}
12299
12471
  };
12300
12472
  }
12301
12473
  if (hasCommand2("mail")) {
12302
- const command = `printf %s ${shellQuote3(message)} | mail -s ${shellQuote3(subject)} ${shellQuote3(channel.target)}`;
12474
+ const command = `printf %s ${shellQuote4(message)} | mail -s ${shellQuote4(subject)} ${shellQuote4(channel.target)}`;
12303
12475
  const result = Bun.spawnSync(["bash", "-lc", command], {
12304
12476
  stdout: "pipe",
12305
12477
  stderr: "pipe",
@@ -12482,7 +12654,7 @@ async function testNotificationChannel(channelId, event = "manual.test", message
12482
12654
  };
12483
12655
  }
12484
12656
  // src/commands/ports.ts
12485
- import { spawnSync as spawnSync4 } from "child_process";
12657
+ import { spawnSync as spawnSync3 } from "child_process";
12486
12658
  function parseSsOutput(output) {
12487
12659
  return output.trim().split(`
12488
12660
  `).map((line) => line.trim()).filter(Boolean).map((line) => {
@@ -12524,7 +12696,7 @@ function listPorts(machineId) {
12524
12696
  const isLocal = targetMachineId === getLocalMachineId();
12525
12697
  const localCommand = "if command -v ss >/dev/null 2>&1; then ss -ltnpH; else lsof -nP -iTCP -sTCP:LISTEN; fi";
12526
12698
  const command = isLocal ? localCommand : buildSshCommand(targetMachineId, localCommand);
12527
- const result = spawnSync4("bash", ["-lc", command], { encoding: "utf8" });
12699
+ const result = spawnSync3("bash", ["-lc", command], { encoding: "utf8" });
12528
12700
  if (result.status !== 0) {
12529
12701
  throw new Error(result.stderr || `Failed to list ports for ${targetMachineId}`);
12530
12702
  }
@@ -13839,7 +14011,7 @@ var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]
13839
14011
  var cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
13840
14012
  var base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
13841
14013
  var base64url = /^[A-Za-z0-9_-]*$/;
13842
- var hostname4 = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
14014
+ var hostname5 = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
13843
14015
  var e164 = /^\+(?:[0-9]){6,14}[0-9]$/;
13844
14016
  var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
13845
14017
  var date = /* @__PURE__ */ new RegExp(`^${dateSource}$`);
@@ -14451,7 +14623,7 @@ var $ZodURL = /* @__PURE__ */ $constructor("$ZodURL", (inst, def) => {
14451
14623
  code: "invalid_format",
14452
14624
  format: "url",
14453
14625
  note: "Invalid hostname",
14454
- pattern: hostname4.source,
14626
+ pattern: hostname5.source,
14455
14627
  input: payload.value,
14456
14628
  inst,
14457
14629
  continue: !def.abort
@@ -22052,6 +22224,7 @@ var MACHINE_MCP_TOOL_NAMES = [
22052
22224
  "machines_install_claude_diff",
22053
22225
  "machines_install_claude_preview",
22054
22226
  "machines_install_claude_apply",
22227
+ "machines_route_resolve",
22055
22228
  "machines_ssh_resolve",
22056
22229
  "machines_ports",
22057
22230
  "machines_backup_preview",
@@ -22162,8 +22335,11 @@ function createMcpServer(version2) {
22162
22335
  }));
22163
22336
  server.tool("machines_install_tailscale_preview", "Preview Tailscale install steps for a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({ content: [{ type: "text", text: JSON.stringify(buildTailscaleInstallPlan(machine_id), null, 2) }] }));
22164
22337
  server.tool("machines_install_tailscale_apply", "Execute Tailscale install steps for a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier"), yes: exports_external.boolean().describe("Confirmation flag for execution") }, async ({ machine_id, yes }) => ({ content: [{ type: "text", text: JSON.stringify(runTailscaleInstall(machine_id, { apply: true, yes }), null, 2) }] }));
22338
+ server.tool("machines_route_resolve", "Resolve the best route for a machine using manifest, heartbeat, SSH, LAN, and Tailscale topology.", { machine_id: exports_external.string().describe("Machine identifier"), include_tailscale: exports_external.boolean().optional().describe("Whether to probe tailscale status --json") }, async ({ machine_id, include_tailscale }) => ({
22339
+ content: [{ type: "text", text: JSON.stringify(resolveMachineRoute(machine_id, { includeTailscale: include_tailscale !== false }), null, 2) }]
22340
+ }));
22165
22341
  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 }) => ({
22166
- content: [{ type: "text", text: JSON.stringify({ resolved: resolveSshTarget(machine_id), command: buildSshCommand(machine_id, remote_command) }, null, 2) }]
22342
+ content: [{ type: "text", text: JSON.stringify({ resolved: resolveMachineRoute(machine_id), command: buildSshCommand(machine_id, remote_command) }, null, 2) }]
22167
22343
  }));
22168
22344
  server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
22169
22345
  content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
@@ -22228,6 +22404,7 @@ export {
22228
22404
  runAppsInstall,
22229
22405
  resolveTables,
22230
22406
  resolveSshTarget,
22407
+ resolveMachineRoute,
22231
22408
  renderDomainMapping,
22232
22409
  renderDashboardHtml,
22233
22410
  removeNotificationChannel,
@@ -22311,5 +22488,7 @@ export {
22311
22488
  MACHINES_STORAGE_MODE_ENV,
22312
22489
  MACHINES_STORAGE_FALLBACK_ENV,
22313
22490
  MACHINES_STORAGE_ENV,
22491
+ MACHINES_PACKAGE_NAME,
22492
+ MACHINES_CONSUMER_CONTRACT_VERSION,
22314
22493
  CROSSREFS_KEY
22315
22494
  };