@hasna/machines 0.0.18 → 0.0.20

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()
@@ -4325,6 +4370,16 @@ import { arch as arch2, hostname as hostname3, platform as platform2, userInfo a
4325
4370
  import { spawnSync } from "child_process";
4326
4371
  var MACHINES_CONSUMER_CONTRACT_VERSION = 1;
4327
4372
  var MACHINES_PACKAGE_NAME = "@hasna/machines";
4373
+ var MACHINES_CONSUMER_CAPABILITIES = {
4374
+ topology: true,
4375
+ compatibility: true,
4376
+ route_resolution: true,
4377
+ cli_json_fallback: true,
4378
+ workspace_path_mapping: true
4379
+ };
4380
+ function getMachinesConsumerCapabilities() {
4381
+ return { ...MACHINES_CONSUMER_CAPABILITIES };
4382
+ }
4328
4383
  function normalizePlatform2(value = platform2()) {
4329
4384
  const normalized = value.toLowerCase();
4330
4385
  if (normalized === "darwin" || normalized === "macos")
@@ -4525,12 +4580,7 @@ function discoverMachineTopology(options = {}) {
4525
4580
  name: MACHINES_PACKAGE_NAME,
4526
4581
  version: getPackageVersion()
4527
4582
  },
4528
- capabilities: {
4529
- topology: true,
4530
- compatibility: true,
4531
- route_resolution: true,
4532
- cli_json_fallback: true
4533
- },
4583
+ capabilities: getMachinesConsumerCapabilities(),
4534
4584
  generated_at: now.toISOString(),
4535
4585
  local_machine_id: localMachineId,
4536
4586
  local_hostname: hostname3(),
@@ -4654,6 +4704,215 @@ function resolveMachineRoute(machineId, options = {}) {
4654
4704
  warnings
4655
4705
  };
4656
4706
  }
4707
+ function isRecord(value) {
4708
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4709
+ }
4710
+ function metadataString(metadata, keys) {
4711
+ for (const key of keys) {
4712
+ const value = metadata[key];
4713
+ if (typeof value === "string" && value.trim())
4714
+ return value.trim();
4715
+ }
4716
+ return null;
4717
+ }
4718
+ function metadataBoolean(metadata, keys) {
4719
+ for (const key of keys) {
4720
+ const value = metadata[key];
4721
+ if (typeof value === "boolean")
4722
+ return value;
4723
+ }
4724
+ return null;
4725
+ }
4726
+ function metadataStringArray(metadata, keys) {
4727
+ for (const key of keys) {
4728
+ const value = metadata[key];
4729
+ if (Array.isArray(value))
4730
+ return value.filter((entry) => typeof entry === "string");
4731
+ }
4732
+ return [];
4733
+ }
4734
+ function readMappedPath(input) {
4735
+ for (const containerName of input.containers) {
4736
+ const container = input.metadata[containerName];
4737
+ if (!isRecord(container))
4738
+ continue;
4739
+ for (const key of input.keys) {
4740
+ const value = container[key];
4741
+ if (typeof value === "string" && value.trim())
4742
+ return value.trim();
4743
+ if (isRecord(value)) {
4744
+ const path = metadataString(value, ["path", "root", "workspacePath", "workspace_path"]);
4745
+ if (path)
4746
+ return path;
4747
+ }
4748
+ }
4749
+ }
4750
+ return null;
4751
+ }
4752
+ function trimTrailingSlash(value) {
4753
+ return value.replace(/\/+$/, "");
4754
+ }
4755
+ function joinPath(left, right) {
4756
+ return `${trimTrailingSlash(left)}/${right.replace(/^\/+/, "")}`;
4757
+ }
4758
+ function inferRepoRoot(workspaceRoot, repoName) {
4759
+ if (!workspaceRoot || !repoName)
4760
+ return null;
4761
+ const root = trimTrailingSlash(workspaceRoot);
4762
+ if (root.endsWith(`/${repoName}`) || root === repoName)
4763
+ return root;
4764
+ if (root.endsWith("/workspace") || root.endsWith("/Workspace")) {
4765
+ return joinPath(root, `hasna/opensource/${repoName}`);
4766
+ }
4767
+ return joinPath(root, repoName);
4768
+ }
4769
+ function projectPathFromMetadata(metadata, projectId, repoName) {
4770
+ const keys = [projectId, repoName].filter((value) => Boolean(value));
4771
+ return readMappedPath({
4772
+ metadata,
4773
+ containers: ["workspace_paths", "workspacePaths", "repo_paths", "repoPaths", "project_paths", "projectPaths", "projects"],
4774
+ keys
4775
+ });
4776
+ }
4777
+ function openFilesPathFromMetadata(metadata, projectId, repoName) {
4778
+ const direct = metadataString(metadata, ["open_files_root", "openFilesRoot", "open_files_path", "openFilesPath"]);
4779
+ if (direct)
4780
+ return direct;
4781
+ const keys = [projectId, repoName, "open-files", "open_files", "default"].filter((value) => Boolean(value));
4782
+ return readMappedPath({
4783
+ metadata,
4784
+ containers: ["open_files_roots", "openFilesRoots", "open_files_paths", "openFilesPaths"],
4785
+ keys
4786
+ });
4787
+ }
4788
+ function trustStatus(machine) {
4789
+ if (!machine)
4790
+ return "unknown";
4791
+ const explicit = metadataString(machine.metadata, ["trust_status", "trustStatus"]);
4792
+ if (explicit === "trusted" || explicit === "untrusted" || explicit === "unknown")
4793
+ return explicit;
4794
+ const trusted = metadataBoolean(machine.metadata, ["trusted", "syncTrusted", "sync_trusted"]);
4795
+ if (trusted === true)
4796
+ return "trusted";
4797
+ if (trusted === false)
4798
+ return "untrusted";
4799
+ if (machine.route_hints.some((hint) => hint.kind === "local"))
4800
+ return "trusted";
4801
+ if (machine.tags.includes("trusted"))
4802
+ return "trusted";
4803
+ return "unknown";
4804
+ }
4805
+ function authStatus(machine) {
4806
+ if (!machine)
4807
+ return "unknown";
4808
+ const explicit = metadataString(machine.metadata, ["auth_status", "authStatus"]);
4809
+ if (explicit === "authenticated" || explicit === "unauthenticated" || explicit === "unknown")
4810
+ return explicit;
4811
+ const authenticated = metadataBoolean(machine.metadata, ["authenticated", "sshAuthorized", "ssh_authorized"]);
4812
+ if (authenticated === true)
4813
+ return "authenticated";
4814
+ if (authenticated === false)
4815
+ return "unauthenticated";
4816
+ if (machine.route_hints.some((hint) => hint.kind === "local"))
4817
+ return "authenticated";
4818
+ return "unknown";
4819
+ }
4820
+ function primaryMachine(machine, projectId, primaryMachineId) {
4821
+ if (!machine)
4822
+ return false;
4823
+ if (primaryMachineId)
4824
+ return machine.machine_id === primaryMachineId;
4825
+ if (metadataBoolean(machine.metadata, ["primary", "primary_machine", "primaryMachine"]) === true)
4826
+ return true;
4827
+ const primaryProjects = metadataStringArray(machine.metadata, ["primary_projects", "primaryProjects"]);
4828
+ if (primaryProjects.includes(projectId))
4829
+ return true;
4830
+ return machine.tags.includes("primary");
4831
+ }
4832
+ function metadataKeysForDiagnostics(metadata) {
4833
+ return Object.keys(metadata).filter((key) => !/(secret|token|key|password|credential)/i.test(key)).sort();
4834
+ }
4835
+ function resolveMachineWorkspace(options) {
4836
+ const topology = options.topology ?? discoverMachineTopology(options);
4837
+ const warnings = [...topology.warnings];
4838
+ const { machine, matchedBy } = findRouteMachine(topology, options.machineId);
4839
+ const generatedAt = (options.now ?? new Date).toISOString();
4840
+ const repoName = options.repoName ?? options.projectId;
4841
+ const openFilesRepoName = options.openFilesRepoName ?? "open-files";
4842
+ if (!machine) {
4843
+ warnings.push(`machine_not_found:${options.machineId}`);
4844
+ return {
4845
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
4846
+ package: topology.package,
4847
+ ok: false,
4848
+ requested_machine_id: options.machineId,
4849
+ machine_id: null,
4850
+ generated_at: generatedAt,
4851
+ project: { project_id: options.projectId, repo_name: repoName, canonical: Boolean(options.projectId) },
4852
+ machine: { current: false, primary: false, trust_status: "unknown", auth_status: "unknown" },
4853
+ paths: {
4854
+ workspace_root: { path: null, source: "unresolved" },
4855
+ project_root: { path: null, source: "unresolved" },
4856
+ open_files_root: { path: null, source: "unresolved" }
4857
+ },
4858
+ evidence: {
4859
+ topology: true,
4860
+ matched_by: matchedBy,
4861
+ manifest_declared: null,
4862
+ metadata_keys: []
4863
+ },
4864
+ warnings
4865
+ };
4866
+ }
4867
+ const metadata = machine.metadata;
4868
+ const workspaceRootPath = options.workspaceRoot ?? machine.workspace_path;
4869
+ const workspaceRootSource = options.workspaceRoot ? "argument" : machine.workspace_path ? "manifest" : "unresolved";
4870
+ const metadataProjectRoot = projectPathFromMetadata(metadata, options.projectId, repoName);
4871
+ const inferredProjectRoot = inferRepoRoot(workspaceRootPath, repoName);
4872
+ const projectRootPath = options.projectRoot ?? metadataProjectRoot ?? inferredProjectRoot;
4873
+ const projectRootSource = options.projectRoot ? "argument" : metadataProjectRoot ? "manifest_metadata" : inferredProjectRoot ? "inferred" : "unresolved";
4874
+ const metadataOpenFilesRoot = openFilesPathFromMetadata(metadata, options.projectId, openFilesRepoName);
4875
+ const inferredOpenFilesRoot = inferRepoRoot(workspaceRootPath, openFilesRepoName);
4876
+ const openFilesRootPath = options.openFilesRoot ?? metadataOpenFilesRoot ?? inferredOpenFilesRoot;
4877
+ const openFilesRootSource = options.openFilesRoot ? "argument" : metadataOpenFilesRoot ? "manifest_metadata" : inferredOpenFilesRoot ? "inferred" : "unresolved";
4878
+ if (projectRootSource === "inferred")
4879
+ warnings.push(`project_root_inferred:${options.projectId}`);
4880
+ if (openFilesRootSource === "inferred")
4881
+ warnings.push(`open_files_root_inferred:${options.projectId}`);
4882
+ if (!projectRootPath)
4883
+ warnings.push(`project_root_unresolved:${options.projectId}`);
4884
+ return {
4885
+ schema_version: MACHINES_CONSUMER_CONTRACT_VERSION,
4886
+ package: topology.package,
4887
+ ok: Boolean(projectRootPath),
4888
+ requested_machine_id: options.machineId,
4889
+ machine_id: machine.machine_id,
4890
+ generated_at: generatedAt,
4891
+ project: {
4892
+ project_id: options.projectId,
4893
+ repo_name: repoName,
4894
+ canonical: Boolean(options.projectId && repoName)
4895
+ },
4896
+ machine: {
4897
+ current: machine.machine_id === topology.local_machine_id,
4898
+ primary: primaryMachine(machine, options.projectId, options.primaryMachineId),
4899
+ trust_status: trustStatus(machine),
4900
+ auth_status: authStatus(machine)
4901
+ },
4902
+ paths: {
4903
+ workspace_root: { path: workspaceRootPath, source: workspaceRootSource },
4904
+ project_root: { path: projectRootPath, source: projectRootSource },
4905
+ open_files_root: { path: openFilesRootPath, source: openFilesRootSource }
4906
+ },
4907
+ evidence: {
4908
+ topology: true,
4909
+ matched_by: matchedBy,
4910
+ manifest_declared: machine.manifest_declared,
4911
+ metadata_keys: metadataKeysForDiagnostics(metadata)
4912
+ },
4913
+ warnings
4914
+ };
4915
+ }
4657
4916
 
4658
4917
  // src/commands/ssh.ts
4659
4918
  function shellQuote(value) {
@@ -6327,12 +6586,7 @@ function checkMachineCompatibility(options = {}) {
6327
6586
  name: MACHINES_PACKAGE_NAME,
6328
6587
  version: getPackageVersion()
6329
6588
  },
6330
- capabilities: {
6331
- topology: true,
6332
- compatibility: true,
6333
- route_resolution: true,
6334
- cli_json_fallback: true
6335
- },
6589
+ capabilities: getMachinesConsumerCapabilities(),
6336
6590
  ok: summary.fail === 0,
6337
6591
  machine_id: machineId,
6338
6592
  source: checks[0]?.source ?? "local",
@@ -6421,7 +6675,7 @@ var PRIMARY_KEYS = {
6421
6675
  setup_runs: ["id"],
6422
6676
  sync_runs: ["id"]
6423
6677
  };
6424
- function readEnv(name) {
6678
+ function readEnv2(name) {
6425
6679
  const value = process.env[name]?.trim();
6426
6680
  return value || undefined;
6427
6681
  }
@@ -6433,7 +6687,7 @@ function normalizeStorageMode(value) {
6433
6687
  }
6434
6688
  function getStorageDatabaseEnvName() {
6435
6689
  for (const name of STORAGE_DATABASE_ENV) {
6436
- if (readEnv(name))
6690
+ if (readEnv2(name))
6437
6691
  return name;
6438
6692
  }
6439
6693
  return null;
@@ -6444,10 +6698,10 @@ function getStorageDatabaseEnv() {
6444
6698
  }
6445
6699
  function getStorageDatabaseUrl() {
6446
6700
  const env = getStorageDatabaseEnv();
6447
- return env ? readEnv(env.name) ?? null : null;
6701
+ return env ? readEnv2(env.name) ?? null : null;
6448
6702
  }
6449
6703
  function getStorageMode() {
6450
- const mode = normalizeStorageMode(readEnv(MACHINES_STORAGE_MODE_ENV)) ?? normalizeStorageMode(readEnv(MACHINES_STORAGE_MODE_FALLBACK_ENV));
6704
+ const mode = normalizeStorageMode(readEnv2(MACHINES_STORAGE_MODE_ENV)) ?? normalizeStorageMode(readEnv2(MACHINES_STORAGE_MODE_FALLBACK_ENV));
6451
6705
  if (mode)
6452
6706
  return mode;
6453
6707
  return getStorageDatabaseUrl() ? "hybrid" : "local";
@@ -6755,14 +7009,50 @@ function createMcpServer(version) {
6755
7009
  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 }) => ({
6756
7010
  content: [{ type: "text", text: JSON.stringify(resolveMachineRoute(machine_id, { includeTailscale: include_tailscale !== false }), null, 2) }]
6757
7011
  }));
7012
+ server.tool("machines_workspace_resolve", "Resolve sync-safe repo and open-files roots for an open-* consumer.", {
7013
+ machine_id: exports_external.string().describe("Machine identifier"),
7014
+ project_id: exports_external.string().describe("Canonical project id"),
7015
+ repo_name: exports_external.string().optional().describe("Repository name; defaults to project id"),
7016
+ open_files_repo_name: exports_external.string().optional().describe("Open-files repository name"),
7017
+ primary_machine_id: exports_external.string().optional().describe("Primary machine id for this project"),
7018
+ workspace_root: exports_external.string().optional().describe("Override the machine workspace root"),
7019
+ project_root: exports_external.string().optional().describe("Override the resolved project root"),
7020
+ open_files_root: exports_external.string().optional().describe("Override the resolved open-files root"),
7021
+ include_tailscale: exports_external.boolean().optional().describe("Whether to probe tailscale status --json")
7022
+ }, async ({
7023
+ machine_id,
7024
+ project_id,
7025
+ repo_name,
7026
+ open_files_repo_name,
7027
+ primary_machine_id,
7028
+ workspace_root,
7029
+ project_root,
7030
+ open_files_root,
7031
+ include_tailscale
7032
+ }) => ({
7033
+ content: [{
7034
+ type: "text",
7035
+ text: JSON.stringify(resolveMachineWorkspace({
7036
+ machineId: machine_id,
7037
+ projectId: project_id,
7038
+ repoName: repo_name,
7039
+ openFilesRepoName: open_files_repo_name,
7040
+ primaryMachineId: primary_machine_id,
7041
+ workspaceRoot: workspace_root,
7042
+ projectRoot: project_root,
7043
+ openFilesRoot: open_files_root,
7044
+ includeTailscale: include_tailscale !== false
7045
+ }), null, 2)
7046
+ }]
7047
+ }));
6758
7048
  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 }) => ({
6759
7049
  content: [{ type: "text", text: JSON.stringify({ resolved: resolveMachineRoute(machine_id), command: buildSshCommand(machine_id, remote_command) }, null, 2) }]
6760
7050
  }));
6761
7051
  server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
6762
7052
  content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
6763
7053
  }));
6764
- 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) }] }));
6765
- 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) }] }));
7054
+ 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) }] }));
7055
+ 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) }] }));
6766
7056
  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) }] }));
6767
7057
  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) }] }));
6768
7058
  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"}
@@ -1,6 +1,7 @@
1
1
  import type { MachinePlatform } from "./types.js";
2
2
  export declare const MACHINES_CONSUMER_CONTRACT_VERSION = 1;
3
3
  export declare const MACHINES_PACKAGE_NAME = "@hasna/machines";
4
+ export declare const MACHINES_CONSUMER_ENTRYPOINT = "@hasna/machines/consumer";
4
5
  export interface TopologyCommandResult {
5
6
  stdout: string;
6
7
  stderr: string;
@@ -52,7 +53,20 @@ export interface MachinesConsumerCapabilities {
52
53
  compatibility: true;
53
54
  route_resolution: true;
54
55
  cli_json_fallback: true;
56
+ workspace_path_mapping?: true;
55
57
  }
58
+ export type MachinesConsumerEnvelope = "topology" | "route" | "workspace" | "compatibility";
59
+ export interface MachinesConsumerContract {
60
+ schema_version: typeof MACHINES_CONSUMER_CONTRACT_VERSION;
61
+ package_name: typeof MACHINES_PACKAGE_NAME;
62
+ entrypoint: typeof MACHINES_CONSUMER_ENTRYPOINT;
63
+ capabilities: MachinesConsumerCapabilities;
64
+ envelopes: MachinesConsumerEnvelope[];
65
+ stable_exports: string[];
66
+ }
67
+ export declare const MACHINES_CONSUMER_CAPABILITIES: MachinesConsumerCapabilities;
68
+ export declare const MACHINES_CONSUMER_CONTRACT: MachinesConsumerContract;
69
+ export declare function getMachinesConsumerCapabilities(): MachinesConsumerCapabilities;
56
70
  export interface MachineTopology {
57
71
  schema_version: typeof MACHINES_CONSUMER_CONTRACT_VERSION;
58
72
  package: MachinesContractPackage;
@@ -93,7 +107,58 @@ export interface MachineRouteResolution {
93
107
  export interface MachineRouteOptions extends MachineTopologyOptions {
94
108
  topology?: MachineTopology;
95
109
  }
110
+ export type MachineWorkspacePathSource = "argument" | "manifest" | "manifest_metadata" | "inferred" | "unresolved";
111
+ export type MachineWorkspaceTrustStatus = "trusted" | "untrusted" | "unknown";
112
+ export type MachineWorkspaceAuthStatus = "authenticated" | "unauthenticated" | "unknown";
113
+ export interface MachineWorkspacePath {
114
+ path: string | null;
115
+ source: MachineWorkspacePathSource;
116
+ }
117
+ export interface MachineWorkspaceProject {
118
+ project_id: string;
119
+ repo_name: string | null;
120
+ canonical: boolean;
121
+ }
122
+ export interface MachineWorkspaceResolution {
123
+ schema_version: typeof MACHINES_CONSUMER_CONTRACT_VERSION;
124
+ package: MachinesContractPackage;
125
+ ok: boolean;
126
+ requested_machine_id: string;
127
+ machine_id: string | null;
128
+ generated_at: string;
129
+ project: MachineWorkspaceProject;
130
+ machine: {
131
+ current: boolean;
132
+ primary: boolean;
133
+ trust_status: MachineWorkspaceTrustStatus;
134
+ auth_status: MachineWorkspaceAuthStatus;
135
+ };
136
+ paths: {
137
+ workspace_root: MachineWorkspacePath;
138
+ project_root: MachineWorkspacePath;
139
+ open_files_root: MachineWorkspacePath;
140
+ };
141
+ evidence: {
142
+ topology: boolean;
143
+ matched_by: MachineRouteResolution["evidence"]["matched_by"];
144
+ manifest_declared: boolean | null;
145
+ metadata_keys: string[];
146
+ };
147
+ warnings: string[];
148
+ }
149
+ export interface MachineWorkspaceOptions extends MachineTopologyOptions {
150
+ machineId: string;
151
+ projectId: string;
152
+ repoName?: string;
153
+ openFilesRepoName?: string;
154
+ primaryMachineId?: string;
155
+ workspaceRoot?: string;
156
+ projectRoot?: string;
157
+ openFilesRoot?: string;
158
+ topology?: MachineTopology;
159
+ }
96
160
  export declare function discoverMachineTopology(options?: MachineTopologyOptions): MachineTopology;
97
161
  export declare function resolveMachineRoute(machineId: string, options?: MachineRouteOptions): MachineRouteResolution;
162
+ export declare function resolveMachineWorkspace(options: MachineWorkspaceOptions): MachineWorkspaceResolution;
98
163
  export declare function getLocalMachineTopology(options?: MachineTopologyOptions): MachineTopologyEntry;
99
164
  //# 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;AACvD,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AAEvE,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,MAAM,wBAAwB,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,eAAe,CAAC;AAE5F,MAAM,WAAW,wBAAwB;IACvC,cAAc,EAAE,OAAO,kCAAkC,CAAC;IAC1D,YAAY,EAAE,OAAO,qBAAqB,CAAC;IAC3C,UAAU,EAAE,OAAO,4BAA4B,CAAC;IAChD,YAAY,EAAE,4BAA4B,CAAC;IAC3C,SAAS,EAAE,wBAAwB,EAAE,CAAC;IACtC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,8BAA8B,EAAE,4BAM5C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,wBAsBxC,CAAC;AAEF,wBAAgB,+BAA+B,IAAI,4BAA4B,CAE9E;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,CAyC7F;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.18",
3
+ "version": "0.0.20",
4
4
  "description": "Machine fleet management CLI + MCP for developers",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",