@hasna/machines 0.0.17 → 0.0.19

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/mcp/index.js CHANGED
@@ -4019,9 +4019,52 @@ var NEVER = INVALID;
4019
4019
  // src/commands/backup.ts
4020
4020
  import { homedir } from "os";
4021
4021
  import { join as join2 } from "path";
4022
+ var MACHINES_BACKUP_BUCKET_ENV = "HASNA_MACHINES_S3_BUCKET";
4023
+ var MACHINES_BACKUP_BUCKET_FALLBACK_ENV = "MACHINES_S3_BUCKET";
4024
+ var MACHINES_BACKUP_PREFIX_ENV = "HASNA_MACHINES_S3_PREFIX";
4025
+ var MACHINES_BACKUP_PREFIX_FALLBACK_ENV = "MACHINES_S3_PREFIX";
4026
+ var DEFAULT_BACKUP_PREFIX = "machines";
4022
4027
  function quote(value) {
4023
4028
  return `'${value.replace(/'/g, `'\\''`)}'`;
4024
4029
  }
4030
+ function readEnv(name) {
4031
+ const value = process.env[name]?.trim();
4032
+ return value || undefined;
4033
+ }
4034
+ function readBackupBucketEnv() {
4035
+ const primary = readEnv(MACHINES_BACKUP_BUCKET_ENV);
4036
+ if (primary)
4037
+ return { bucket: primary, bucketSource: MACHINES_BACKUP_BUCKET_ENV };
4038
+ const fallback = readEnv(MACHINES_BACKUP_BUCKET_FALLBACK_ENV);
4039
+ if (fallback)
4040
+ return { bucket: fallback, bucketSource: MACHINES_BACKUP_BUCKET_FALLBACK_ENV };
4041
+ return null;
4042
+ }
4043
+ function readBackupPrefixEnv() {
4044
+ const primary = readEnv(MACHINES_BACKUP_PREFIX_ENV);
4045
+ if (primary)
4046
+ return { prefix: primary, prefixSource: MACHINES_BACKUP_PREFIX_ENV };
4047
+ const fallback = readEnv(MACHINES_BACKUP_PREFIX_FALLBACK_ENV);
4048
+ if (fallback)
4049
+ return { prefix: fallback, prefixSource: MACHINES_BACKUP_PREFIX_FALLBACK_ENV };
4050
+ return null;
4051
+ }
4052
+ function resolveBackupTarget(options = {}) {
4053
+ const explicitBucket = options.bucket?.trim();
4054
+ const envBucket = explicitBucket ? null : readBackupBucketEnv();
4055
+ const bucket = explicitBucket || envBucket?.bucket;
4056
+ if (!bucket) {
4057
+ throw new Error(`Missing S3 backup bucket. Pass --bucket or set ${MACHINES_BACKUP_BUCKET_ENV} or ${MACHINES_BACKUP_BUCKET_FALLBACK_ENV}.`);
4058
+ }
4059
+ const explicitPrefix = options.prefix?.trim();
4060
+ const envPrefix = explicitPrefix ? null : readBackupPrefixEnv();
4061
+ return {
4062
+ bucket,
4063
+ prefix: explicitPrefix || envPrefix?.prefix || DEFAULT_BACKUP_PREFIX,
4064
+ bucketSource: explicitBucket ? "argument" : envBucket.bucketSource,
4065
+ prefixSource: explicitPrefix ? "argument" : envPrefix?.prefixSource || "default"
4066
+ };
4067
+ }
4025
4068
  function defaultBackupSources() {
4026
4069
  const home = homedir();
4027
4070
  return [
@@ -4030,7 +4073,8 @@ function defaultBackupSources() {
4030
4073
  join2(home, ".secrets")
4031
4074
  ];
4032
4075
  }
4033
- function buildBackupPlan(bucket, prefix = "machines") {
4076
+ function buildBackupPlan(bucket, prefix) {
4077
+ const target = resolveBackupTarget({ bucket, prefix });
4034
4078
  const archivePath = join2(homedir(), ".hasna", "machines", "backup.tgz");
4035
4079
  const sources = defaultBackupSources();
4036
4080
  const steps = [
@@ -4043,7 +4087,7 @@ function buildBackupPlan(bucket, prefix = "machines") {
4043
4087
  {
4044
4088
  id: "backup-upload",
4045
4089
  title: "Upload archive to S3",
4046
- command: `aws s3 cp ${quote(archivePath)} s3://${bucket}/${prefix}/$(hostname)-backup.tgz`,
4090
+ command: `aws s3 cp ${quote(archivePath)} s3://${target.bucket}/${target.prefix}/$(hostname)-backup.tgz`,
4047
4091
  manager: "custom"
4048
4092
  }
4049
4093
  ];
@@ -4054,7 +4098,7 @@ function buildBackupPlan(bucket, prefix = "machines") {
4054
4098
  executed: 0
4055
4099
  };
4056
4100
  }
4057
- function runBackup(bucket, prefix = "machines", options = {}) {
4101
+ function runBackup(bucket, prefix, options = {}) {
4058
4102
  const plan = buildBackupPlan(bucket, prefix);
4059
4103
  if (!options.apply)
4060
4104
  return plan;
@@ -4139,6 +4183,7 @@ var machineSchema = exports_external.object({
4139
4183
  workspacePath: exports_external.string(),
4140
4184
  bunPath: exports_external.string().optional(),
4141
4185
  tags: exports_external.array(exports_external.string()).optional(),
4186
+ metadata: exports_external.record(exports_external.unknown()).optional(),
4142
4187
  packages: exports_external.array(packageSchema).optional(),
4143
4188
  apps: exports_external.array(appSchema).optional(),
4144
4189
  files: exports_external.array(fileSchema).optional()
@@ -4529,7 +4574,8 @@ function discoverMachineTopology(options = {}) {
4529
4574
  topology: true,
4530
4575
  compatibility: true,
4531
4576
  route_resolution: true,
4532
- cli_json_fallback: true
4577
+ cli_json_fallback: true,
4578
+ workspace_path_mapping: true
4533
4579
  },
4534
4580
  generated_at: now.toISOString(),
4535
4581
  local_machine_id: localMachineId,
@@ -4654,8 +4700,220 @@ function resolveMachineRoute(machineId, options = {}) {
4654
4700
  warnings
4655
4701
  };
4656
4702
  }
4703
+ function isRecord(value) {
4704
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4705
+ }
4706
+ function metadataString(metadata, keys) {
4707
+ for (const key of keys) {
4708
+ const value = metadata[key];
4709
+ if (typeof value === "string" && value.trim())
4710
+ return value.trim();
4711
+ }
4712
+ return null;
4713
+ }
4714
+ function metadataBoolean(metadata, keys) {
4715
+ for (const key of keys) {
4716
+ const value = metadata[key];
4717
+ if (typeof value === "boolean")
4718
+ return value;
4719
+ }
4720
+ return null;
4721
+ }
4722
+ function metadataStringArray(metadata, keys) {
4723
+ for (const key of keys) {
4724
+ const value = metadata[key];
4725
+ if (Array.isArray(value))
4726
+ return value.filter((entry) => typeof entry === "string");
4727
+ }
4728
+ return [];
4729
+ }
4730
+ function readMappedPath(input) {
4731
+ for (const containerName of input.containers) {
4732
+ const container = input.metadata[containerName];
4733
+ if (!isRecord(container))
4734
+ continue;
4735
+ for (const key of input.keys) {
4736
+ const value = container[key];
4737
+ if (typeof value === "string" && value.trim())
4738
+ return value.trim();
4739
+ if (isRecord(value)) {
4740
+ const path = metadataString(value, ["path", "root", "workspacePath", "workspace_path"]);
4741
+ if (path)
4742
+ return path;
4743
+ }
4744
+ }
4745
+ }
4746
+ return null;
4747
+ }
4748
+ function trimTrailingSlash(value) {
4749
+ return value.replace(/\/+$/, "");
4750
+ }
4751
+ function joinPath(left, right) {
4752
+ return `${trimTrailingSlash(left)}/${right.replace(/^\/+/, "")}`;
4753
+ }
4754
+ function inferRepoRoot(workspaceRoot, repoName) {
4755
+ if (!workspaceRoot || !repoName)
4756
+ return null;
4757
+ const root = trimTrailingSlash(workspaceRoot);
4758
+ if (root.endsWith(`/${repoName}`) || root === repoName)
4759
+ return root;
4760
+ if (root.endsWith("/workspace") || root.endsWith("/Workspace")) {
4761
+ return joinPath(root, `hasna/opensource/${repoName}`);
4762
+ }
4763
+ return joinPath(root, repoName);
4764
+ }
4765
+ function projectPathFromMetadata(metadata, projectId, repoName) {
4766
+ const keys = [projectId, repoName].filter((value) => Boolean(value));
4767
+ return readMappedPath({
4768
+ metadata,
4769
+ containers: ["workspace_paths", "workspacePaths", "repo_paths", "repoPaths", "project_paths", "projectPaths", "projects"],
4770
+ keys
4771
+ });
4772
+ }
4773
+ function openFilesPathFromMetadata(metadata, projectId, repoName) {
4774
+ const direct = metadataString(metadata, ["open_files_root", "openFilesRoot", "open_files_path", "openFilesPath"]);
4775
+ if (direct)
4776
+ return direct;
4777
+ const keys = [projectId, repoName, "open-files", "open_files", "default"].filter((value) => Boolean(value));
4778
+ return readMappedPath({
4779
+ metadata,
4780
+ containers: ["open_files_roots", "openFilesRoots", "open_files_paths", "openFilesPaths"],
4781
+ keys
4782
+ });
4783
+ }
4784
+ function trustStatus(machine) {
4785
+ if (!machine)
4786
+ return "unknown";
4787
+ const explicit = metadataString(machine.metadata, ["trust_status", "trustStatus"]);
4788
+ if (explicit === "trusted" || explicit === "untrusted" || explicit === "unknown")
4789
+ return explicit;
4790
+ const trusted = metadataBoolean(machine.metadata, ["trusted", "syncTrusted", "sync_trusted"]);
4791
+ if (trusted === true)
4792
+ return "trusted";
4793
+ if (trusted === false)
4794
+ return "untrusted";
4795
+ if (machine.route_hints.some((hint) => hint.kind === "local"))
4796
+ return "trusted";
4797
+ if (machine.tags.includes("trusted"))
4798
+ return "trusted";
4799
+ return "unknown";
4800
+ }
4801
+ function authStatus(machine) {
4802
+ if (!machine)
4803
+ return "unknown";
4804
+ const explicit = metadataString(machine.metadata, ["auth_status", "authStatus"]);
4805
+ if (explicit === "authenticated" || explicit === "unauthenticated" || explicit === "unknown")
4806
+ return explicit;
4807
+ const authenticated = metadataBoolean(machine.metadata, ["authenticated", "sshAuthorized", "ssh_authorized"]);
4808
+ if (authenticated === true)
4809
+ return "authenticated";
4810
+ if (authenticated === false)
4811
+ return "unauthenticated";
4812
+ if (machine.route_hints.some((hint) => hint.kind === "local"))
4813
+ return "authenticated";
4814
+ return "unknown";
4815
+ }
4816
+ function primaryMachine(machine, projectId, primaryMachineId) {
4817
+ if (!machine)
4818
+ return false;
4819
+ if (primaryMachineId)
4820
+ return machine.machine_id === primaryMachineId;
4821
+ if (metadataBoolean(machine.metadata, ["primary", "primary_machine", "primaryMachine"]) === true)
4822
+ return true;
4823
+ const primaryProjects = metadataStringArray(machine.metadata, ["primary_projects", "primaryProjects"]);
4824
+ if (primaryProjects.includes(projectId))
4825
+ return true;
4826
+ return machine.tags.includes("primary");
4827
+ }
4828
+ function metadataKeysForDiagnostics(metadata) {
4829
+ return Object.keys(metadata).filter((key) => !/(secret|token|key|password|credential)/i.test(key)).sort();
4830
+ }
4831
+ function resolveMachineWorkspace(options) {
4832
+ const topology = options.topology ?? discoverMachineTopology(options);
4833
+ const warnings = [...topology.warnings];
4834
+ const { machine, matchedBy } = findRouteMachine(topology, options.machineId);
4835
+ const generatedAt = (options.now ?? new Date).toISOString();
4836
+ const repoName = options.repoName ?? options.projectId;
4837
+ const openFilesRepoName = options.openFilesRepoName ?? "open-files";
4838
+ if (!machine) {
4839
+ warnings.push(`machine_not_found:${options.machineId}`);
4840
+ return {
4841
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
4842
+ package: topology.package,
4843
+ ok: false,
4844
+ requested_machine_id: options.machineId,
4845
+ machine_id: null,
4846
+ generated_at: generatedAt,
4847
+ project: { project_id: options.projectId, repo_name: repoName, canonical: Boolean(options.projectId) },
4848
+ machine: { current: false, primary: false, trust_status: "unknown", auth_status: "unknown" },
4849
+ paths: {
4850
+ workspace_root: { path: null, source: "unresolved" },
4851
+ project_root: { path: null, source: "unresolved" },
4852
+ open_files_root: { path: null, source: "unresolved" }
4853
+ },
4854
+ evidence: {
4855
+ topology: true,
4856
+ matched_by: matchedBy,
4857
+ manifest_declared: null,
4858
+ metadata_keys: []
4859
+ },
4860
+ warnings
4861
+ };
4862
+ }
4863
+ const metadata = machine.metadata;
4864
+ const workspaceRootPath = options.workspaceRoot ?? machine.workspace_path;
4865
+ const workspaceRootSource = options.workspaceRoot ? "argument" : machine.workspace_path ? "manifest" : "unresolved";
4866
+ const metadataProjectRoot = projectPathFromMetadata(metadata, options.projectId, repoName);
4867
+ const inferredProjectRoot = inferRepoRoot(workspaceRootPath, repoName);
4868
+ const projectRootPath = options.projectRoot ?? metadataProjectRoot ?? inferredProjectRoot;
4869
+ const projectRootSource = options.projectRoot ? "argument" : metadataProjectRoot ? "manifest_metadata" : inferredProjectRoot ? "inferred" : "unresolved";
4870
+ const metadataOpenFilesRoot = openFilesPathFromMetadata(metadata, options.projectId, openFilesRepoName);
4871
+ const inferredOpenFilesRoot = inferRepoRoot(workspaceRootPath, openFilesRepoName);
4872
+ const openFilesRootPath = options.openFilesRoot ?? metadataOpenFilesRoot ?? inferredOpenFilesRoot;
4873
+ const openFilesRootSource = options.openFilesRoot ? "argument" : metadataOpenFilesRoot ? "manifest_metadata" : inferredOpenFilesRoot ? "inferred" : "unresolved";
4874
+ if (projectRootSource === "inferred")
4875
+ warnings.push(`project_root_inferred:${options.projectId}`);
4876
+ if (openFilesRootSource === "inferred")
4877
+ warnings.push(`open_files_root_inferred:${options.projectId}`);
4878
+ if (!projectRootPath)
4879
+ warnings.push(`project_root_unresolved:${options.projectId}`);
4880
+ return {
4881
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
4882
+ package: topology.package,
4883
+ ok: Boolean(projectRootPath),
4884
+ requested_machine_id: options.machineId,
4885
+ machine_id: machine.machine_id,
4886
+ generated_at: generatedAt,
4887
+ project: {
4888
+ project_id: options.projectId,
4889
+ repo_name: repoName,
4890
+ canonical: Boolean(options.projectId && repoName)
4891
+ },
4892
+ machine: {
4893
+ current: machine.machine_id === topology.local_machine_id,
4894
+ primary: primaryMachine(machine, options.projectId, options.primaryMachineId),
4895
+ trust_status: trustStatus(machine),
4896
+ auth_status: authStatus(machine)
4897
+ },
4898
+ paths: {
4899
+ workspace_root: { path: workspaceRootPath, source: workspaceRootSource },
4900
+ project_root: { path: projectRootPath, source: projectRootSource },
4901
+ open_files_root: { path: openFilesRootPath, source: openFilesRootSource }
4902
+ },
4903
+ evidence: {
4904
+ topology: true,
4905
+ matched_by: matchedBy,
4906
+ manifest_declared: machine.manifest_declared,
4907
+ metadata_keys: metadataKeysForDiagnostics(metadata)
4908
+ },
4909
+ warnings
4910
+ };
4911
+ }
4657
4912
 
4658
4913
  // src/commands/ssh.ts
4914
+ function shellQuote(value) {
4915
+ return `'${value.replace(/'/g, "'\\''")}'`;
4916
+ }
4659
4917
  function resolveSshTarget(machineId, options = {}) {
4660
4918
  const resolved = resolveMachineRoute(machineId, options);
4661
4919
  if (!resolved.ok || !resolved.target) {
@@ -4674,11 +4932,11 @@ function resolveSshTarget(machineId, options = {}) {
4674
4932
  }
4675
4933
  function buildSshCommand(machineId, remoteCommand, options = {}) {
4676
4934
  const resolved = resolveSshTarget(machineId, options);
4677
- return remoteCommand ? `ssh ${resolved.target} ${JSON.stringify(remoteCommand)}` : `ssh ${resolved.target}`;
4935
+ return remoteCommand ? `ssh ${resolved.target} ${shellQuote(remoteCommand)}` : `ssh ${resolved.target}`;
4678
4936
  }
4679
4937
 
4680
4938
  // src/remote.ts
4681
- function shellQuote(value) {
4939
+ function shellQuote2(value) {
4682
4940
  return `'${value.replace(/'/g, "'\\''")}'`;
4683
4941
  }
4684
4942
  function machineIsLocal(machineId, localMachineId) {
@@ -4696,7 +4954,7 @@ function resolveMachineCommand(machineId, command, localMachineId = getLocalMach
4696
4954
  } catch (error) {
4697
4955
  const message = String(error.message ?? error);
4698
4956
  if (message.includes("Machine route not found") || message.includes("Machine not found in manifest")) {
4699
- return { source: "ssh", shellCommand: `ssh ${shellQuote(machineId)} ${shellQuote(command)}` };
4957
+ return { source: "ssh", shellCommand: `ssh ${shellQuote2(machineId)} ${shellQuote2(command)}` };
4700
4958
  }
4701
4959
  throw error;
4702
4960
  }
@@ -4729,7 +4987,7 @@ function getAppManager(machine, app) {
4729
4987
  return "winget";
4730
4988
  return "apt";
4731
4989
  }
4732
- function shellQuote2(value) {
4990
+ function shellQuote3(value) {
4733
4991
  return `'${value.replace(/'/g, `'\\''`)}'`;
4734
4992
  }
4735
4993
  function buildAppCommand(machine, app) {
@@ -4750,7 +5008,7 @@ function buildAppCommand(machine, app) {
4750
5008
  return `sudo apt-get install -y ${packageName}`;
4751
5009
  }
4752
5010
  function buildAppProbeCommand(machine, app) {
4753
- const packageName = shellQuote2(getPackageName(app));
5011
+ const packageName = shellQuote3(getPackageName(app));
4754
5012
  const manager = getAppManager(machine, app);
4755
5013
  if (manager === "custom") {
4756
5014
  return `if command -v ${packageName} >/dev/null 2>&1; then printf 'installed=1\\nversion=custom\\n'; else printf 'installed=0\\n'; fi`;
@@ -5260,7 +5518,7 @@ var notificationConfigSchema = exports_external.object({
5260
5518
  function sortChannels(channels) {
5261
5519
  return [...channels].sort((left, right) => left.id.localeCompare(right.id));
5262
5520
  }
5263
- function shellQuote3(value) {
5521
+ function shellQuote4(value) {
5264
5522
  return `'${value.replace(/'/g, `'\\''`)}'`;
5265
5523
  }
5266
5524
  function hasCommand2(binary) {
@@ -5307,7 +5565,7 @@ ${message}
5307
5565
  };
5308
5566
  }
5309
5567
  if (hasCommand2("mail")) {
5310
- const command = `printf %s ${shellQuote3(message)} | mail -s ${shellQuote3(subject)} ${shellQuote3(channel.target)}`;
5568
+ const command = `printf %s ${shellQuote4(message)} | mail -s ${shellQuote4(subject)} ${shellQuote4(channel.target)}`;
5311
5569
  const result = Bun.spawnSync(["bash", "-lc", command], {
5312
5570
  stdout: "pipe",
5313
5571
  stderr: "pipe",
@@ -6101,7 +6359,7 @@ var DEFAULT_COMMANDS = [
6101
6359
  function defaultPackages() {
6102
6360
  return [{ name: "@hasna/machines", command: "machines", expectedVersion: getPackageVersion(), required: true }];
6103
6361
  }
6104
- function shellQuote4(value) {
6362
+ function shellQuote5(value) {
6105
6363
  return `'${value.replace(/'/g, "'\\''")}'`;
6106
6364
  }
6107
6365
  function commandId(value) {
@@ -6152,7 +6410,7 @@ function defaultRunner2(machineId, command) {
6152
6410
  return runMachineCommand(machineId, command);
6153
6411
  }
6154
6412
  function inspectCommand(machineId, spec, runner) {
6155
- const command = shellQuote4(spec.command);
6413
+ const command = shellQuote5(spec.command);
6156
6414
  const versionArgs = spec.versionArgs ?? "--version";
6157
6415
  const script = [
6158
6416
  `cmd=${command}`,
@@ -6181,7 +6439,7 @@ function fieldCommand(field) {
6181
6439
  }
6182
6440
  function inspectWorkspace(machineId, spec, runner) {
6183
6441
  const script = [
6184
- `path=${shellQuote4(spec.path)}`,
6442
+ `path=${shellQuote5(spec.path)}`,
6185
6443
  'printf "exists=%s\\n" "$(test -d "$path" && printf yes || printf no)"',
6186
6444
  'pkg="$path/package.json"',
6187
6445
  'printf "package_json=%s\\n" "$(test -f "$pkg" && printf yes || printf no)"',
@@ -6418,7 +6676,7 @@ var PRIMARY_KEYS = {
6418
6676
  setup_runs: ["id"],
6419
6677
  sync_runs: ["id"]
6420
6678
  };
6421
- function readEnv(name) {
6679
+ function readEnv2(name) {
6422
6680
  const value = process.env[name]?.trim();
6423
6681
  return value || undefined;
6424
6682
  }
@@ -6430,7 +6688,7 @@ function normalizeStorageMode(value) {
6430
6688
  }
6431
6689
  function getStorageDatabaseEnvName() {
6432
6690
  for (const name of STORAGE_DATABASE_ENV) {
6433
- if (readEnv(name))
6691
+ if (readEnv2(name))
6434
6692
  return name;
6435
6693
  }
6436
6694
  return null;
@@ -6441,10 +6699,10 @@ function getStorageDatabaseEnv() {
6441
6699
  }
6442
6700
  function getStorageDatabaseUrl() {
6443
6701
  const env = getStorageDatabaseEnv();
6444
- return env ? readEnv(env.name) ?? null : null;
6702
+ return env ? readEnv2(env.name) ?? null : null;
6445
6703
  }
6446
6704
  function getStorageMode() {
6447
- const mode = normalizeStorageMode(readEnv(MACHINES_STORAGE_MODE_ENV)) ?? normalizeStorageMode(readEnv(MACHINES_STORAGE_MODE_FALLBACK_ENV));
6705
+ const mode = normalizeStorageMode(readEnv2(MACHINES_STORAGE_MODE_ENV)) ?? normalizeStorageMode(readEnv2(MACHINES_STORAGE_MODE_FALLBACK_ENV));
6448
6706
  if (mode)
6449
6707
  return mode;
6450
6708
  return getStorageDatabaseUrl() ? "hybrid" : "local";
@@ -6752,14 +7010,50 @@ function createMcpServer(version) {
6752
7010
  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 }) => ({
6753
7011
  content: [{ type: "text", text: JSON.stringify(resolveMachineRoute(machine_id, { includeTailscale: include_tailscale !== false }), null, 2) }]
6754
7012
  }));
7013
+ server.tool("machines_workspace_resolve", "Resolve sync-safe repo and open-files roots for an open-* consumer.", {
7014
+ machine_id: exports_external.string().describe("Machine identifier"),
7015
+ project_id: exports_external.string().describe("Canonical project id"),
7016
+ repo_name: exports_external.string().optional().describe("Repository name; defaults to project id"),
7017
+ open_files_repo_name: exports_external.string().optional().describe("Open-files repository name"),
7018
+ primary_machine_id: exports_external.string().optional().describe("Primary machine id for this project"),
7019
+ workspace_root: exports_external.string().optional().describe("Override the machine workspace root"),
7020
+ project_root: exports_external.string().optional().describe("Override the resolved project root"),
7021
+ open_files_root: exports_external.string().optional().describe("Override the resolved open-files root"),
7022
+ include_tailscale: exports_external.boolean().optional().describe("Whether to probe tailscale status --json")
7023
+ }, async ({
7024
+ machine_id,
7025
+ project_id,
7026
+ repo_name,
7027
+ open_files_repo_name,
7028
+ primary_machine_id,
7029
+ workspace_root,
7030
+ project_root,
7031
+ open_files_root,
7032
+ include_tailscale
7033
+ }) => ({
7034
+ content: [{
7035
+ type: "text",
7036
+ text: JSON.stringify(resolveMachineWorkspace({
7037
+ machineId: machine_id,
7038
+ projectId: project_id,
7039
+ repoName: repo_name,
7040
+ openFilesRepoName: open_files_repo_name,
7041
+ primaryMachineId: primary_machine_id,
7042
+ workspaceRoot: workspace_root,
7043
+ projectRoot: project_root,
7044
+ openFilesRoot: open_files_root,
7045
+ includeTailscale: include_tailscale !== false
7046
+ }), null, 2)
7047
+ }]
7048
+ }));
6755
7049
  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 }) => ({
6756
7050
  content: [{ type: "text", text: JSON.stringify({ resolved: resolveMachineRoute(machine_id), command: buildSshCommand(machine_id, remote_command) }, null, 2) }]
6757
7051
  }));
6758
7052
  server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
6759
7053
  content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
6760
7054
  }));
6761
- server.tool("machines_backup_preview", "Preview backup steps for the current machine.", { bucket: exports_external.string().describe("S3 bucket name"), prefix: exports_external.string().optional().describe("S3 key prefix") }, async ({ bucket, prefix }) => ({ content: [{ type: "text", text: JSON.stringify(buildBackupPlan(bucket, prefix), null, 2) }] }));
6762
- server.tool("machines_backup_apply", "Execute backup steps for the current machine.", { bucket: exports_external.string().describe("S3 bucket name"), prefix: exports_external.string().optional().describe("S3 key prefix"), yes: exports_external.boolean().describe("Confirmation flag for execution") }, async ({ bucket, prefix, yes }) => ({ content: [{ type: "text", text: JSON.stringify(runBackup(bucket, prefix, { apply: true, yes }), null, 2) }] }));
7055
+ server.tool("machines_backup_preview", "Preview backup steps for the current machine.", { bucket: exports_external.string().optional().describe("S3 bucket name; defaults to HASNA_MACHINES_S3_BUCKET or MACHINES_S3_BUCKET"), prefix: exports_external.string().optional().describe("S3 key prefix; defaults to HASNA_MACHINES_S3_PREFIX, MACHINES_S3_PREFIX, or machines") }, async ({ bucket, prefix }) => ({ content: [{ type: "text", text: JSON.stringify(buildBackupPlan(bucket, prefix), null, 2) }] }));
7056
+ server.tool("machines_backup_apply", "Execute backup steps for the current machine.", { bucket: exports_external.string().optional().describe("S3 bucket name; defaults to HASNA_MACHINES_S3_BUCKET or MACHINES_S3_BUCKET"), prefix: exports_external.string().optional().describe("S3 key prefix; defaults to HASNA_MACHINES_S3_PREFIX, MACHINES_S3_PREFIX, or machines"), yes: exports_external.boolean().describe("Confirmation flag for execution") }, async ({ bucket, prefix, yes }) => ({ content: [{ type: "text", text: JSON.stringify(runBackup(bucket, prefix, { apply: true, yes }), null, 2) }] }));
6763
7057
  server.tool("machines_cert_preview", "Preview mkcert steps for one or more domains.", { domains: exports_external.array(exports_external.string()).describe("Domains to issue certificates for") }, async ({ domains }) => ({ content: [{ type: "text", text: JSON.stringify(buildCertPlan(domains), null, 2) }] }));
6764
7058
  server.tool("machines_cert_apply", "Execute mkcert steps for one or more domains.", { domains: exports_external.array(exports_external.string()).describe("Domains to issue certificates for"), yes: exports_external.boolean().describe("Confirmation flag for execution") }, async ({ domains, yes }) => ({ content: [{ type: "text", text: JSON.stringify(runCertPlan(domains, { apply: true, yes }), null, 2) }] }));
6765
7059
  server.tool("machines_dns_add", "Add or replace a local domain mapping.", { domain: exports_external.string().describe("Domain name"), port: exports_external.number().describe("Target port"), target_host: exports_external.string().optional().describe("Target host") }, async ({ domain, port, target_host }) => ({ content: [{ type: "text", text: JSON.stringify(addDomainMapping(domain, port, target_host), null, 2) }] }));
@@ -1,5 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- export declare const MACHINE_MCP_TOOL_NAMES: readonly ["machines_status", "machines_doctor", "machines_self_test", "machines_apps_list", "machines_apps_status", "machines_apps_diff", "machines_apps_plan", "machines_apps_apply", "machines_manifest", "machines_manifest_validate", "machines_manifest_bootstrap", "machines_manifest_get", "machines_manifest_remove", "machines_agent_status", "machines_setup_preview", "machines_setup_apply", "machines_sync_preview", "machines_sync_apply", "machines_topology", "machines_compatibility", "machines_diff", "machines_install_tailscale_preview", "machines_install_tailscale_apply", "machines_install_claude_status", "machines_install_claude_diff", "machines_install_claude_preview", "machines_install_claude_apply", "machines_route_resolve", "machines_ssh_resolve", "machines_ports", "machines_backup_preview", "machines_backup_apply", "machines_cert_preview", "machines_cert_apply", "machines_dns_add", "machines_dns_list", "machines_dns_render", "machines_notifications_add", "machines_notifications_list", "machines_notifications_test", "machines_notifications_dispatch", "machines_notifications_remove", "machines_serve_info", "machines_serve_dashboard", "storage_status", "storage_push", "storage_pull", "storage_sync"];
2
+ export declare const MACHINE_MCP_TOOL_NAMES: readonly ["machines_status", "machines_doctor", "machines_self_test", "machines_apps_list", "machines_apps_status", "machines_apps_diff", "machines_apps_plan", "machines_apps_apply", "machines_manifest", "machines_manifest_validate", "machines_manifest_bootstrap", "machines_manifest_get", "machines_manifest_remove", "machines_agent_status", "machines_setup_preview", "machines_setup_apply", "machines_sync_preview", "machines_sync_apply", "machines_topology", "machines_compatibility", "machines_diff", "machines_install_tailscale_preview", "machines_install_tailscale_apply", "machines_install_claude_status", "machines_install_claude_diff", "machines_install_claude_preview", "machines_install_claude_apply", "machines_route_resolve", "machines_workspace_resolve", "machines_ssh_resolve", "machines_ports", "machines_backup_preview", "machines_backup_apply", "machines_cert_preview", "machines_cert_apply", "machines_dns_add", "machines_dns_list", "machines_dns_render", "machines_notifications_add", "machines_notifications_list", "machines_notifications_test", "machines_notifications_dispatch", "machines_notifications_remove", "machines_serve_info", "machines_serve_dashboard", "storage_status", "storage_push", "storage_pull", "storage_sync"];
3
3
  export declare function buildServer(version?: string): McpServer;
4
4
  export declare function createMcpServer(version: string): McpServer;
5
5
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA+BpE,eAAO,MAAM,sBAAsB,usCAiDzB,CAAC;AAEX,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAA4B,GAAG,SAAS,CAE5E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAsW1D"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA+BpE,eAAO,MAAM,sBAAsB,quCAkDzB,CAAC;AAEX,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAA4B,GAAG,SAAS,CAE5E;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAgZ1D"}
@@ -52,6 +52,7 @@ export interface MachinesConsumerCapabilities {
52
52
  compatibility: true;
53
53
  route_resolution: true;
54
54
  cli_json_fallback: true;
55
+ workspace_path_mapping?: true;
55
56
  }
56
57
  export interface MachineTopology {
57
58
  schema_version: typeof MACHINES_CONSUMER_CONTRACT_VERSION;
@@ -93,7 +94,58 @@ export interface MachineRouteResolution {
93
94
  export interface MachineRouteOptions extends MachineTopologyOptions {
94
95
  topology?: MachineTopology;
95
96
  }
97
+ export type MachineWorkspacePathSource = "argument" | "manifest" | "manifest_metadata" | "inferred" | "unresolved";
98
+ export type MachineWorkspaceTrustStatus = "trusted" | "untrusted" | "unknown";
99
+ export type MachineWorkspaceAuthStatus = "authenticated" | "unauthenticated" | "unknown";
100
+ export interface MachineWorkspacePath {
101
+ path: string | null;
102
+ source: MachineWorkspacePathSource;
103
+ }
104
+ export interface MachineWorkspaceProject {
105
+ project_id: string;
106
+ repo_name: string | null;
107
+ canonical: boolean;
108
+ }
109
+ export interface MachineWorkspaceResolution {
110
+ schema_version: typeof MACHINES_CONSUMER_CONTRACT_VERSION;
111
+ package: MachinesContractPackage;
112
+ ok: boolean;
113
+ requested_machine_id: string;
114
+ machine_id: string | null;
115
+ generated_at: string;
116
+ project: MachineWorkspaceProject;
117
+ machine: {
118
+ current: boolean;
119
+ primary: boolean;
120
+ trust_status: MachineWorkspaceTrustStatus;
121
+ auth_status: MachineWorkspaceAuthStatus;
122
+ };
123
+ paths: {
124
+ workspace_root: MachineWorkspacePath;
125
+ project_root: MachineWorkspacePath;
126
+ open_files_root: MachineWorkspacePath;
127
+ };
128
+ evidence: {
129
+ topology: boolean;
130
+ matched_by: MachineRouteResolution["evidence"]["matched_by"];
131
+ manifest_declared: boolean | null;
132
+ metadata_keys: string[];
133
+ };
134
+ warnings: string[];
135
+ }
136
+ export interface MachineWorkspaceOptions extends MachineTopologyOptions {
137
+ machineId: string;
138
+ projectId: string;
139
+ repoName?: string;
140
+ openFilesRepoName?: string;
141
+ primaryMachineId?: string;
142
+ workspaceRoot?: string;
143
+ projectRoot?: string;
144
+ openFilesRoot?: string;
145
+ topology?: MachineTopology;
146
+ }
96
147
  export declare function discoverMachineTopology(options?: MachineTopologyOptions): MachineTopology;
97
148
  export declare function resolveMachineRoute(machineId: string, options?: MachineRouteOptions): MachineRouteResolution;
149
+ export declare function resolveMachineWorkspace(options: MachineWorkspaceOptions): MachineWorkspaceResolution;
98
150
  export declare function getLocalMachineTopology(options?: MachineTopologyOptions): MachineTopologyEntry;
99
151
  //# sourceMappingURL=topology.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,YAAY,CAAC;AAGnE,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,qBAAqB,CAAC;AAE/E,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,WAAW,GAAG,KAAK,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACnD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE;QACT,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,GAAG,EAAE,MAAM,EAAE,CAAC;QACd,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;QACvB,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,GAAG,EAAE;QACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,KAAK,EAAE,gBAAgB,CAAC;QACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC;IACF,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,OAAO,qBAAqB,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,IAAI,CAAC;IACf,aAAa,EAAE,IAAI,CAAC;IACpB,gBAAgB,EAAE,IAAI,CAAC;IACvB,iBAAiB,EAAE,IAAI,CAAC;IACxB,sBAAsB,CAAC,EAAE,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,OAAO,kCAAkC,CAAC;IAC1D,OAAO,EAAE,uBAAuB,CAAC;IACjC,YAAY,EAAE,4BAA4B,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,eAAe,GAAG,MAAM,CAAC;IAC3C,mBAAmB,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,WAAW,GAAG,KAAK,GAAG,SAAS,CAAC;AACjF,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAElF,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,OAAO,kCAAkC,CAAC;IAC1D,OAAO,EAAE,uBAAuB,CAAC;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,sBAAsB,CAAC;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE;QACR,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,aAAa,GAAG,UAAU,GAAG,IAAI,CAAC;QACzG,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAC;QAClC,gBAAgB,EAAE,oBAAoB,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;QAClE,gBAAgB,EAAE,OAAO,GAAG,IAAI,CAAC;QACjC,aAAa,EAAE,gBAAgB,GAAG,IAAI,CAAC;KACxC,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,mBAAoB,SAAQ,sBAAsB;IACjE,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,MAAM,0BAA0B,GAClC,UAAU,GACV,UAAU,GACV,mBAAmB,GACnB,UAAU,GACV,YAAY,CAAC;AAEjB,MAAM,MAAM,2BAA2B,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAC9E,MAAM,MAAM,0BAA0B,GAAG,eAAe,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAEzF,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,0BAA0B,CAAC;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,OAAO,kCAAkC,CAAC;IAC1D,OAAO,EAAE,uBAAuB,CAAC;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,uBAAuB,CAAC;IACjC,OAAO,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,2BAA2B,CAAC;QAC1C,WAAW,EAAE,0BAA0B,CAAC;KACzC,CAAC;IACF,KAAK,EAAE;QACL,cAAc,EAAE,oBAAoB,CAAC;QACrC,YAAY,EAAE,oBAAoB,CAAC;QACnC,eAAe,EAAE,oBAAoB,CAAC;KACvC,CAAC;IACF,QAAQ,EAAE;QACR,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC;QAC7D,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAC;QAClC,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,uBAAwB,SAAQ,sBAAsB;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAgMD,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,CA+C7F;AAgED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,sBAAsB,CA2DhH;AA8HD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,uBAAuB,GAAG,0BAA0B,CAmGpG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,sBAA2B,GAAG,oBAAoB,CAkBlG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/machines",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "description": "Machine fleet management CLI + MCP for developers",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",