@hasna/machines 0.0.39 → 0.0.41

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.
@@ -7150,6 +7150,15 @@ function listHeartbeats(machineId) {
7150
7150
  FROM agent_heartbeats
7151
7151
  ORDER BY updated_at DESC`).all();
7152
7152
  }
7153
+ function latestHeartbeatByMachine(heartbeats) {
7154
+ const byMachine = new Map;
7155
+ for (const heartbeat of heartbeats) {
7156
+ if (!byMachine.has(heartbeat.machine_id)) {
7157
+ byMachine.set(heartbeat.machine_id, heartbeat);
7158
+ }
7159
+ }
7160
+ return byMachine;
7161
+ }
7153
7162
 
7154
7163
  // src/agent/runtime.ts
7155
7164
  import { execFileSync } from "child_process";
@@ -11616,7 +11625,7 @@ function discoverMachineTopology(options = {}) {
11616
11625
  const warnings = [];
11617
11626
  const manifest = readManifest();
11618
11627
  const heartbeats = listHeartbeats();
11619
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
11628
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
11620
11629
  const localMachineId = getLocalMachineId();
11621
11630
  const peers = options.includeTailscale === false ? new Map : loadTailscalePeers(runner, warnings);
11622
11631
  const machineIds = new Set([
package/dist/cli/index.js CHANGED
@@ -2219,6 +2219,15 @@ function listHeartbeats(machineId) {
2219
2219
  FROM agent_heartbeats
2220
2220
  ORDER BY updated_at DESC`).all();
2221
2221
  }
2222
+ function latestHeartbeatByMachine(heartbeats) {
2223
+ const byMachine = new Map;
2224
+ for (const heartbeat of heartbeats) {
2225
+ if (!byMachine.has(heartbeat.machine_id)) {
2226
+ byMachine.set(heartbeat.machine_id, heartbeat);
2227
+ }
2228
+ }
2229
+ return byMachine;
2230
+ }
2222
2231
  function countRuns(table) {
2223
2232
  const db = getDb();
2224
2233
  const row = db.query(`SELECT COUNT(*) as count FROM ${table}`).get();
@@ -7755,7 +7764,7 @@ function discoverMachineTopology(options = {}) {
7755
7764
  const warnings = [];
7756
7765
  const manifest = readManifest();
7757
7766
  const heartbeats = listHeartbeats();
7758
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
7767
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
7759
7768
  const localMachineId = getLocalMachineId();
7760
7769
  const peers = options.includeTailscale === false ? new Map : loadTailscalePeers(runner, warnings);
7761
7770
  const machineIds = new Set([
@@ -9966,7 +9975,7 @@ function parseJsonObject(value) {
9966
9975
  function getStatus() {
9967
9976
  const manifest = readManifest();
9968
9977
  const heartbeats = listHeartbeats();
9969
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
9978
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
9970
9979
  const machineIds = new Set([
9971
9980
  ...manifest.machines.map((machine) => machine.id),
9972
9981
  ...heartbeats.map((heartbeat) => heartbeat.machine_id)
@@ -10721,7 +10730,7 @@ function resolveDaemonServiceOptions(options) {
10721
10730
  serviceId: serviceName,
10722
10731
  executable,
10723
10732
  intervalMs,
10724
- env: buildEnvironment(serviceName, options, warnings),
10733
+ env: buildEnvironment(serviceName, executable, options, warnings),
10725
10734
  warnings
10726
10735
  };
10727
10736
  }
@@ -10749,11 +10758,15 @@ function normalizeIntervalMs(value, warnings) {
10749
10758
  warnings.push(`Invalid intervalMs "${String(value)}"; using ${DEFAULT_INTERVAL_MS}.`);
10750
10759
  return DEFAULT_INTERVAL_MS;
10751
10760
  }
10752
- function buildEnvironment(serviceName, options, warnings) {
10761
+ function buildEnvironment(serviceName, executable, options, warnings) {
10753
10762
  const env2 = {
10754
10763
  HASNA_MACHINES_AGENT_MODE: "daemon",
10755
10764
  HASNA_MACHINES_AGENT_SERVICE: serviceName
10756
10765
  };
10766
+ const executableDir = dirname4(executable);
10767
+ if (!isStandardExecutableDir(executableDir)) {
10768
+ env2["PATH"] = `${executableDir}:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`;
10769
+ }
10757
10770
  if (options.storagePush) {
10758
10771
  env2["HASNA_MACHINES_AGENT_STORAGE_PUSH"] = "1";
10759
10772
  env2["HASNA_MACHINES_AGENT_STORAGE_PUSH_BACKOFF_MS"] = "250";
@@ -10774,6 +10787,9 @@ function buildEnvironment(serviceName, options, warnings) {
10774
10787
  addEnvPlaceholders(env2, options.env ?? [], warnings);
10775
10788
  return Object.fromEntries(Object.entries(env2).sort(([left], [right]) => left.localeCompare(right)));
10776
10789
  }
10790
+ function isStandardExecutableDir(path) {
10791
+ return ["/bin", "/usr/bin", "/usr/local/bin", "/usr/sbin", "/sbin"].includes(path);
10792
+ }
10777
10793
  function addEnvPlaceholders(env2, names, warnings) {
10778
10794
  for (const rawName of names) {
10779
10795
  const name = rawName.trim();
package/dist/consumer.js CHANGED
@@ -253,6 +253,15 @@ function listHeartbeats(machineId) {
253
253
  FROM agent_heartbeats
254
254
  ORDER BY updated_at DESC`).all();
255
255
  }
256
+ function latestHeartbeatByMachine(heartbeats) {
257
+ const byMachine = new Map;
258
+ for (const heartbeat of heartbeats) {
259
+ if (!byMachine.has(heartbeat.machine_id)) {
260
+ byMachine.set(heartbeat.machine_id, heartbeat);
261
+ }
262
+ }
263
+ return byMachine;
264
+ }
256
265
  function countRuns(table) {
257
266
  const db = getDb();
258
267
  const row = db.query(`SELECT COUNT(*) as count FROM ${table}`).get();
@@ -4886,7 +4895,7 @@ function discoverMachineTopology(options = {}) {
4886
4895
  const warnings = [];
4887
4896
  const manifest = readManifest();
4888
4897
  const heartbeats = listHeartbeats();
4889
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
4898
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
4890
4899
  const localMachineId = getLocalMachineId();
4891
4900
  const peers = options.includeTailscale === false ? new Map : loadTailscalePeers(runner, warnings);
4892
4901
  const machineIds = new Set([
package/dist/db.d.ts CHANGED
@@ -44,6 +44,7 @@ export interface StoredHeartbeat {
44
44
  private_metadata: number;
45
45
  }
46
46
  export declare function listHeartbeats(machineId?: string): StoredHeartbeat[];
47
+ export declare function latestHeartbeatByMachine(heartbeats: readonly StoredHeartbeat[]): Map<string, StoredHeartbeat>;
47
48
  export declare function countRuns(table: "setup_runs" | "sync_runs"): number;
48
49
  export declare function setHeartbeatStatus(machineId: string, pid: number, status: "online" | "offline"): void;
49
50
  export declare function recordSetupRun(machineId: string, status: string, details: unknown): void;
package/dist/db.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6720,6 +6720,15 @@ function listHeartbeats(machineId) {
6720
6720
  FROM agent_heartbeats
6721
6721
  ORDER BY updated_at DESC`).all();
6722
6722
  }
6723
+ function latestHeartbeatByMachine(heartbeats) {
6724
+ const byMachine = new Map;
6725
+ for (const heartbeat of heartbeats) {
6726
+ if (!byMachine.has(heartbeat.machine_id)) {
6727
+ byMachine.set(heartbeat.machine_id, heartbeat);
6728
+ }
6729
+ }
6730
+ return byMachine;
6731
+ }
6723
6732
  function countRuns(table) {
6724
6733
  const db = getDb();
6725
6734
  const row = db.query(`SELECT COUNT(*) as count FROM ${table}`).get();
@@ -11726,7 +11735,7 @@ function discoverMachineTopology(options = {}) {
11726
11735
  const warnings = [];
11727
11736
  const manifest = readManifest();
11728
11737
  const heartbeats = listHeartbeats();
11729
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
11738
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
11730
11739
  const localMachineId = getLocalMachineId();
11731
11740
  const peers = options.includeTailscale === false ? new Map : loadTailscalePeers(runner, warnings);
11732
11741
  const machineIds = new Set([
@@ -13884,7 +13893,7 @@ function resolveDaemonServiceOptions(options) {
13884
13893
  serviceId: serviceName,
13885
13894
  executable,
13886
13895
  intervalMs,
13887
- env: buildEnvironment(serviceName, options, warnings),
13896
+ env: buildEnvironment(serviceName, executable, options, warnings),
13888
13897
  warnings
13889
13898
  };
13890
13899
  }
@@ -13912,11 +13921,15 @@ function normalizeIntervalMs(value, warnings) {
13912
13921
  warnings.push(`Invalid intervalMs "${String(value)}"; using ${DEFAULT_INTERVAL_MS}.`);
13913
13922
  return DEFAULT_INTERVAL_MS;
13914
13923
  }
13915
- function buildEnvironment(serviceName, options, warnings) {
13924
+ function buildEnvironment(serviceName, executable, options, warnings) {
13916
13925
  const env = {
13917
13926
  HASNA_MACHINES_AGENT_MODE: "daemon",
13918
13927
  HASNA_MACHINES_AGENT_SERVICE: serviceName
13919
13928
  };
13929
+ const executableDir = dirname4(executable);
13930
+ if (!isStandardExecutableDir(executableDir)) {
13931
+ env["PATH"] = `${executableDir}:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`;
13932
+ }
13920
13933
  if (options.storagePush) {
13921
13934
  env["HASNA_MACHINES_AGENT_STORAGE_PUSH"] = "1";
13922
13935
  env["HASNA_MACHINES_AGENT_STORAGE_PUSH_BACKOFF_MS"] = "250";
@@ -13937,6 +13950,9 @@ function buildEnvironment(serviceName, options, warnings) {
13937
13950
  addEnvPlaceholders(env, options.env ?? [], warnings);
13938
13951
  return Object.fromEntries(Object.entries(env).sort(([left], [right]) => left.localeCompare(right)));
13939
13952
  }
13953
+ function isStandardExecutableDir(path) {
13954
+ return ["/bin", "/usr/bin", "/usr/local/bin", "/usr/sbin", "/sbin"].includes(path);
13955
+ }
13940
13956
  function addEnvPlaceholders(env, names, warnings) {
13941
13957
  for (const rawName of names) {
13942
13958
  const name = rawName.trim();
@@ -14807,7 +14823,7 @@ function parseJsonObject2(value) {
14807
14823
  function getStatus() {
14808
14824
  const manifest = readManifest();
14809
14825
  const heartbeats = listHeartbeats();
14810
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
14826
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
14811
14827
  const machineIds = new Set([
14812
14828
  ...manifest.machines.map((machine) => machine.id),
14813
14829
  ...heartbeats.map((heartbeat) => heartbeat.machine_id)
@@ -25145,6 +25161,7 @@ export {
25145
25161
  listHeartbeats,
25146
25162
  listDomainMappings,
25147
25163
  listApps,
25164
+ latestHeartbeatByMachine,
25148
25165
  isSensitiveKey,
25149
25166
  isPrivateOutputEnabled,
25150
25167
  isPrivateMetadataEnabled,
package/dist/mcp/index.js CHANGED
@@ -4582,6 +4582,15 @@ function listHeartbeats(machineId) {
4582
4582
  FROM agent_heartbeats
4583
4583
  ORDER BY updated_at DESC`).all();
4584
4584
  }
4585
+ function latestHeartbeatByMachine(heartbeats) {
4586
+ const byMachine = new Map;
4587
+ for (const heartbeat of heartbeats) {
4588
+ if (!byMachine.has(heartbeat.machine_id)) {
4589
+ byMachine.set(heartbeat.machine_id, heartbeat);
4590
+ }
4591
+ }
4592
+ return byMachine;
4593
+ }
4585
4594
  function countRuns(table) {
4586
4595
  const db = getDb();
4587
4596
  const row = db.query(`SELECT COUNT(*) as count FROM ${table}`).get();
@@ -4836,7 +4845,7 @@ function discoverMachineTopology(options = {}) {
4836
4845
  const warnings = [];
4837
4846
  const manifest = readManifest();
4838
4847
  const heartbeats = listHeartbeats();
4839
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
4848
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
4840
4849
  const localMachineId = getLocalMachineId();
4841
4850
  const peers = options.includeTailscale === false ? new Map : loadTailscalePeers(runner, warnings);
4842
4851
  const machineIds = new Set([
@@ -5945,6 +5954,7 @@ function diffMachines(leftMachineId, rightMachineId) {
5945
5954
  }
5946
5955
 
5947
5956
  // src/commands/daemon.ts
5957
+ import { dirname as dirname4 } from "path";
5948
5958
  import { platform as osPlatform } from "os";
5949
5959
  var DEFAULT_SERVICE_NAME = "machines-agent";
5950
5960
  var DEFAULT_EXECUTABLE = "/usr/local/bin/machines-agent";
@@ -5986,7 +5996,7 @@ function resolveDaemonServiceOptions(options) {
5986
5996
  serviceId: serviceName,
5987
5997
  executable,
5988
5998
  intervalMs,
5989
- env: buildEnvironment(serviceName, options, warnings),
5999
+ env: buildEnvironment(serviceName, executable, options, warnings),
5990
6000
  warnings
5991
6001
  };
5992
6002
  }
@@ -6014,11 +6024,15 @@ function normalizeIntervalMs(value, warnings) {
6014
6024
  warnings.push(`Invalid intervalMs "${String(value)}"; using ${DEFAULT_INTERVAL_MS}.`);
6015
6025
  return DEFAULT_INTERVAL_MS;
6016
6026
  }
6017
- function buildEnvironment(serviceName, options, warnings) {
6027
+ function buildEnvironment(serviceName, executable, options, warnings) {
6018
6028
  const env = {
6019
6029
  HASNA_MACHINES_AGENT_MODE: "daemon",
6020
6030
  HASNA_MACHINES_AGENT_SERVICE: serviceName
6021
6031
  };
6032
+ const executableDir = dirname4(executable);
6033
+ if (!isStandardExecutableDir(executableDir)) {
6034
+ env["PATH"] = `${executableDir}:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`;
6035
+ }
6022
6036
  if (options.storagePush) {
6023
6037
  env["HASNA_MACHINES_AGENT_STORAGE_PUSH"] = "1";
6024
6038
  env["HASNA_MACHINES_AGENT_STORAGE_PUSH_BACKOFF_MS"] = "250";
@@ -6039,6 +6053,9 @@ function buildEnvironment(serviceName, options, warnings) {
6039
6053
  addEnvPlaceholders(env, options.env ?? [], warnings);
6040
6054
  return Object.fromEntries(Object.entries(env).sort(([left], [right]) => left.localeCompare(right)));
6041
6055
  }
6056
+ function isStandardExecutableDir(path) {
6057
+ return ["/bin", "/usr/bin", "/usr/local/bin", "/usr/sbin", "/sbin"].includes(path);
6058
+ }
6042
6059
  function addEnvPlaceholders(env, names, warnings) {
6043
6060
  for (const rawName of names) {
6044
6061
  const name = rawName.trim();
@@ -7383,7 +7400,7 @@ function parseJsonObject2(value) {
7383
7400
  function getStatus() {
7384
7401
  const manifest = readManifest();
7385
7402
  const heartbeats = listHeartbeats();
7386
- const heartbeatByMachine = new Map(heartbeats.map((heartbeat) => [heartbeat.machine_id, heartbeat]));
7403
+ const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
7387
7404
  const machineIds = new Set([
7388
7405
  ...manifest.machines.map((machine) => machine.id),
7389
7406
  ...heartbeats.map((heartbeat) => heartbeat.machine_id)
package/dist/storage.js CHANGED
@@ -248,6 +248,15 @@ function listHeartbeats(machineId) {
248
248
  FROM agent_heartbeats
249
249
  ORDER BY updated_at DESC`).all();
250
250
  }
251
+ function latestHeartbeatByMachine(heartbeats) {
252
+ const byMachine = new Map;
253
+ for (const heartbeat of heartbeats) {
254
+ if (!byMachine.has(heartbeat.machine_id)) {
255
+ byMachine.set(heartbeat.machine_id, heartbeat);
256
+ }
257
+ }
258
+ return byMachine;
259
+ }
251
260
  function countRuns(table) {
252
261
  const db = getDb();
253
262
  const row = db.query(`SELECT COUNT(*) as count FROM ${table}`).get();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/machines",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "description": "Machine fleet management CLI + MCP for developers",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",