@hasna/machines 0.0.42 → 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/cli/index.js +96 -51
- package/dist/commands/self-test.d.ts.map +1 -1
- package/dist/commands/status.d.ts +4 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/index.js +82 -32
- package/dist/mcp/index.js +82 -31
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -144,6 +144,7 @@ CLI and MCP expose the same topology view:
|
|
|
144
144
|
machines topology --json
|
|
145
145
|
machines topology --no-tailscale --json
|
|
146
146
|
machines route --machine linux-dev-01 --json
|
|
147
|
+
machines ssh --machine linux-dev-01 --private-metadata
|
|
147
148
|
```
|
|
148
149
|
|
|
149
150
|
## Screen sharing
|
|
@@ -322,6 +323,11 @@ set `HASNA_MACHINES_ALLOW_PRIVATE_OUTPUT=1` and pass the explicit
|
|
|
322
323
|
`privateMetadata=true` query parameter or MCP `private_metadata` argument. The
|
|
323
324
|
caller flag alone is ignored.
|
|
324
325
|
|
|
326
|
+
Default status and SSH-resolution output is public-safe: local paths, machine
|
|
327
|
+
identifiers, route targets, and generated SSH commands are redacted unless
|
|
328
|
+
private output is explicitly requested. CLI commands that print raw SSH targets
|
|
329
|
+
require `--private-metadata`.
|
|
330
|
+
|
|
325
331
|
Doctor summaries are also opt-in with `--doctor-summary` or
|
|
326
332
|
`HASNA_MACHINES_AGENT_DOCTOR_SUMMARY=1`. The daemon records a compact
|
|
327
333
|
ok/warn/fail count plus redacted blockers and avoids optional private adapters
|
package/dist/cli/index.js
CHANGED
|
@@ -9972,7 +9972,8 @@ function parseJsonObject(value) {
|
|
|
9972
9972
|
return null;
|
|
9973
9973
|
}
|
|
9974
9974
|
}
|
|
9975
|
-
function getStatus() {
|
|
9975
|
+
function getStatus(options = {}) {
|
|
9976
|
+
const privateMetadata = options.privateMetadata === true;
|
|
9976
9977
|
const manifest = readManifest();
|
|
9977
9978
|
const heartbeats = listHeartbeats();
|
|
9978
9979
|
const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
|
|
@@ -9981,17 +9982,17 @@ function getStatus() {
|
|
|
9981
9982
|
...heartbeats.map((heartbeat) => heartbeat.machine_id)
|
|
9982
9983
|
]);
|
|
9983
9984
|
return {
|
|
9984
|
-
machineId: getLocalMachineId(),
|
|
9985
|
-
manifestPath: getManifestPath(),
|
|
9986
|
-
dbPath: getDbPath(),
|
|
9987
|
-
notificationsPath: getNotificationsPath(),
|
|
9985
|
+
machineId: privateMetadata ? getLocalMachineId() : REDACTED_VALUE,
|
|
9986
|
+
manifestPath: privateMetadata ? getManifestPath() : REDACTED_VALUE,
|
|
9987
|
+
dbPath: privateMetadata ? getDbPath() : REDACTED_VALUE,
|
|
9988
|
+
notificationsPath: privateMetadata ? getNotificationsPath() : REDACTED_VALUE,
|
|
9988
9989
|
manifestMachineCount: manifest.machines.length,
|
|
9989
9990
|
heartbeatCount: heartbeats.length,
|
|
9990
9991
|
machines: [...machineIds].sort().map((machineId) => {
|
|
9991
9992
|
const declared = manifest.machines.find((machine) => machine.id === machineId);
|
|
9992
9993
|
const heartbeat = heartbeatByMachine.get(machineId);
|
|
9993
9994
|
return {
|
|
9994
|
-
machineId,
|
|
9995
|
+
machineId: privateMetadata ? machineId : REDACTED_VALUE,
|
|
9995
9996
|
platform: declared?.platform,
|
|
9996
9997
|
manifestDeclared: Boolean(declared),
|
|
9997
9998
|
heartbeatStatus: heartbeat?.status || "unknown",
|
|
@@ -9999,7 +10000,7 @@ function getStatus() {
|
|
|
9999
10000
|
daemonVersion: heartbeat?.daemon_version ?? null,
|
|
10000
10001
|
agentMode: heartbeat?.agent_mode ?? null,
|
|
10001
10002
|
storageSyncStatus: heartbeat?.storage_sync_status ?? null,
|
|
10002
|
-
doctorSummary: parseJsonObject(heartbeat?.doctor_summary_json),
|
|
10003
|
+
doctorSummary: privateMetadata ? parseJsonObject(heartbeat?.doctor_summary_json) : null,
|
|
10003
10004
|
privateMetadata: Boolean(heartbeat?.private_metadata)
|
|
10004
10005
|
};
|
|
10005
10006
|
}),
|
|
@@ -10588,7 +10589,7 @@ function runDoctor(machineId, options = {}) {
|
|
|
10588
10589
|
|
|
10589
10590
|
// src/commands/daemon.ts
|
|
10590
10591
|
import { execFileSync } from "child_process";
|
|
10591
|
-
import { chmodSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
10592
|
+
import { chmodSync, existsSync as existsSync8, readFileSync as readFileSync6, statSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
10592
10593
|
import { dirname as dirname4 } from "path";
|
|
10593
10594
|
import { platform as osPlatform } from "os";
|
|
10594
10595
|
var DEFAULT_SERVICE_NAME = "machines-agent";
|
|
@@ -10929,6 +10930,8 @@ function escapeSystemdEnvironmentValue(value) {
|
|
|
10929
10930
|
function launchdPlist(options) {
|
|
10930
10931
|
const env2 = Object.entries(options.env).map(([name, value]) => ` <key>${xmlEscape(name)}</key>
|
|
10931
10932
|
<string>${xmlEscape(value)}</string>`).join(`
|
|
10933
|
+
`);
|
|
10934
|
+
const programArguments = daemonProgramArguments(options).map((value) => ` <string>${xmlEscape(value)}</string>`).join(`
|
|
10932
10935
|
`);
|
|
10933
10936
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
10934
10937
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -10938,9 +10941,7 @@ function launchdPlist(options) {
|
|
|
10938
10941
|
<string>${xmlEscape(options.serviceId)}</string>
|
|
10939
10942
|
<key>ProgramArguments</key>
|
|
10940
10943
|
<array>
|
|
10941
|
-
|
|
10942
|
-
<string>--interval-ms</string>
|
|
10943
|
-
<string>${options.intervalMs}</string>
|
|
10944
|
+
${programArguments}
|
|
10944
10945
|
</array>
|
|
10945
10946
|
<key>EnvironmentVariables</key>
|
|
10946
10947
|
<dict>
|
|
@@ -10961,6 +10962,7 @@ ${env2}
|
|
|
10961
10962
|
function systemdUnit(options) {
|
|
10962
10963
|
const env2 = Object.entries(options.env).map(([name, value]) => `Environment=${quoteSystemdEnvironment(name, value)}`).join(`
|
|
10963
10964
|
`);
|
|
10965
|
+
const execStart = daemonProgramArguments(options).map(quoteSystemdExecArg).join(" ");
|
|
10964
10966
|
return `[Unit]
|
|
10965
10967
|
Description=Hasna machines agent
|
|
10966
10968
|
After=network-online.target
|
|
@@ -10968,7 +10970,7 @@ Wants=network-online.target
|
|
|
10968
10970
|
|
|
10969
10971
|
[Service]
|
|
10970
10972
|
Type=simple
|
|
10971
|
-
ExecStart=${
|
|
10973
|
+
ExecStart=${execStart}
|
|
10972
10974
|
Restart=always
|
|
10973
10975
|
RestartSec=10
|
|
10974
10976
|
${env2}
|
|
@@ -10977,6 +10979,36 @@ ${env2}
|
|
|
10977
10979
|
WantedBy=${options.mode === "system" ? "multi-user.target" : "default.target"}
|
|
10978
10980
|
`;
|
|
10979
10981
|
}
|
|
10982
|
+
function daemonProgramArguments(options) {
|
|
10983
|
+
const bunRuntime = siblingBunRuntime(options.executable);
|
|
10984
|
+
const base = bunRuntime ? [bunRuntime, options.executable] : [options.executable];
|
|
10985
|
+
return [...base, "--interval-ms", String(options.intervalMs)];
|
|
10986
|
+
}
|
|
10987
|
+
function siblingBunRuntime(executable) {
|
|
10988
|
+
if (!isBunShebangScript(executable))
|
|
10989
|
+
return null;
|
|
10990
|
+
const candidate = `${dirname4(executable)}/bun`;
|
|
10991
|
+
return isExecutableFile(candidate) ? candidate : null;
|
|
10992
|
+
}
|
|
10993
|
+
function isBunShebangScript(executable) {
|
|
10994
|
+
try {
|
|
10995
|
+
const content = readFileSync6(executable, "utf8").slice(0, 256);
|
|
10996
|
+
const firstLine2 = content.split(/\r?\n/, 1)[0] ?? "";
|
|
10997
|
+
return /^#!.*\bbun\b/.test(firstLine2);
|
|
10998
|
+
} catch {
|
|
10999
|
+
return false;
|
|
11000
|
+
}
|
|
11001
|
+
}
|
|
11002
|
+
function isExecutableFile(path) {
|
|
11003
|
+
if (!existsSync8(path))
|
|
11004
|
+
return false;
|
|
11005
|
+
try {
|
|
11006
|
+
const stats = statSync(path);
|
|
11007
|
+
return stats.isFile() && (stats.mode & 73) !== 0;
|
|
11008
|
+
} catch {
|
|
11009
|
+
return false;
|
|
11010
|
+
}
|
|
11011
|
+
}
|
|
10980
11012
|
function launchdDomain(options) {
|
|
10981
11013
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
10982
11014
|
}
|
|
@@ -11333,7 +11365,7 @@ function startDashboardServer(options = {}) {
|
|
|
11333
11365
|
return Response.json({ ok: true, ...getServeInfo(options) });
|
|
11334
11366
|
}
|
|
11335
11367
|
if (url.pathname === "/api/status") {
|
|
11336
|
-
return Response.json(getStatus());
|
|
11368
|
+
return Response.json(appendWarnings(getStatus({ privateMetadata }), privateWarnings));
|
|
11337
11369
|
}
|
|
11338
11370
|
if (url.pathname === "/api/topology") {
|
|
11339
11371
|
const topology = discoverMachineTopology({ includeTailscale: url.searchParams.get("tailscale") !== "false" });
|
|
@@ -11471,15 +11503,16 @@ function check(id, status, summary, detail) {
|
|
|
11471
11503
|
function runSelfTest() {
|
|
11472
11504
|
const version = getPackageVersion();
|
|
11473
11505
|
const status = getStatus();
|
|
11506
|
+
const machineId = getLocalMachineId();
|
|
11474
11507
|
const doctor = runDoctor();
|
|
11475
11508
|
const serveInfo = getServeInfo();
|
|
11476
11509
|
const html = renderDashboardHtml();
|
|
11477
11510
|
const notifications = listNotificationChannels();
|
|
11478
|
-
const apps = listApps(
|
|
11479
|
-
const appsDiff = diffApps(
|
|
11480
|
-
const cliPlan = buildClaudeInstallPlan(
|
|
11511
|
+
const apps = listApps(machineId);
|
|
11512
|
+
const appsDiff = diffApps(machineId);
|
|
11513
|
+
const cliPlan = buildClaudeInstallPlan(machineId);
|
|
11481
11514
|
return {
|
|
11482
|
-
machineId
|
|
11515
|
+
machineId,
|
|
11483
11516
|
checks: [
|
|
11484
11517
|
check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
|
|
11485
11518
|
check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
|
|
@@ -11497,7 +11530,7 @@ function runSelfTest() {
|
|
|
11497
11530
|
// src/commands/clipboard.ts
|
|
11498
11531
|
init_paths();
|
|
11499
11532
|
import { createHash } from "crypto";
|
|
11500
|
-
import { existsSync as
|
|
11533
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, rmSync, writeFileSync as writeFileSync5 } from "fs";
|
|
11501
11534
|
import { join as join6 } from "path";
|
|
11502
11535
|
var DEFAULT_CONFIG = {
|
|
11503
11536
|
version: 1,
|
|
@@ -11528,10 +11561,10 @@ function getDefaultConfig() {
|
|
|
11528
11561
|
}
|
|
11529
11562
|
function readConfig(configPath) {
|
|
11530
11563
|
const path = resolveConfigPath(configPath);
|
|
11531
|
-
if (!
|
|
11564
|
+
if (!existsSync9(path)) {
|
|
11532
11565
|
return getDefaultConfig();
|
|
11533
11566
|
}
|
|
11534
|
-
const parsed = JSON.parse(
|
|
11567
|
+
const parsed = JSON.parse(readFileSync7(path, "utf8"));
|
|
11535
11568
|
return { ...getDefaultConfig(), ...parsed };
|
|
11536
11569
|
}
|
|
11537
11570
|
function writeConfig(config, configPath) {
|
|
@@ -11542,11 +11575,11 @@ function writeConfig(config, configPath) {
|
|
|
11542
11575
|
}
|
|
11543
11576
|
function readHistory(historyPath) {
|
|
11544
11577
|
const path = resolveHistoryPath(historyPath);
|
|
11545
|
-
if (!
|
|
11578
|
+
if (!existsSync9(path)) {
|
|
11546
11579
|
return [];
|
|
11547
11580
|
}
|
|
11548
11581
|
try {
|
|
11549
|
-
return JSON.parse(
|
|
11582
|
+
return JSON.parse(readFileSync7(path, "utf8"));
|
|
11550
11583
|
} catch {
|
|
11551
11584
|
return [];
|
|
11552
11585
|
}
|
|
@@ -11575,8 +11608,8 @@ function sanitizeClipboardForRead(content, maxSizeBytes, skipPatterns) {
|
|
|
11575
11608
|
}
|
|
11576
11609
|
function getOrCreateClipboardKey() {
|
|
11577
11610
|
const keyPath = getClipboardKeyPath();
|
|
11578
|
-
if (
|
|
11579
|
-
return
|
|
11611
|
+
if (existsSync9(keyPath)) {
|
|
11612
|
+
return readFileSync7(keyPath, "utf8").trim();
|
|
11580
11613
|
}
|
|
11581
11614
|
const key = createHash("sha256").update(crypto.randomUUID()).digest("hex").slice(0, 32);
|
|
11582
11615
|
ensureParentDir(keyPath);
|
|
@@ -11615,7 +11648,7 @@ function addClipboardEntry(entry, historyPath) {
|
|
|
11615
11648
|
}
|
|
11616
11649
|
function clearClipboardHistory(historyPath) {
|
|
11617
11650
|
const path = resolveHistoryPath(historyPath);
|
|
11618
|
-
if (
|
|
11651
|
+
if (existsSync9(path)) {
|
|
11619
11652
|
rmSync(path);
|
|
11620
11653
|
}
|
|
11621
11654
|
}
|
|
@@ -11631,7 +11664,7 @@ function getClipboardStatus(historyPath) {
|
|
|
11631
11664
|
|
|
11632
11665
|
// src/commands/clipboard-daemon.ts
|
|
11633
11666
|
init_paths();
|
|
11634
|
-
import { readFileSync as
|
|
11667
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
11635
11668
|
import { join as join7 } from "path";
|
|
11636
11669
|
import { createHash as createHash3 } from "crypto";
|
|
11637
11670
|
|
|
@@ -11639,7 +11672,7 @@ import { createHash as createHash3 } from "crypto";
|
|
|
11639
11672
|
init_paths();
|
|
11640
11673
|
import { createServer } from "http";
|
|
11641
11674
|
import { createHash as createHash2 } from "crypto";
|
|
11642
|
-
import { readFileSync as
|
|
11675
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
11643
11676
|
function readLocalClipboardSync() {
|
|
11644
11677
|
const platform5 = process.platform;
|
|
11645
11678
|
if (platform5 === "darwin") {
|
|
@@ -11685,7 +11718,7 @@ function hasCommand3(binary) {
|
|
|
11685
11718
|
function loadSharedSecret() {
|
|
11686
11719
|
const keyPath = getClipboardKeyPath();
|
|
11687
11720
|
try {
|
|
11688
|
-
return
|
|
11721
|
+
return readFileSync8(keyPath, "utf8").trim();
|
|
11689
11722
|
} catch {
|
|
11690
11723
|
return "";
|
|
11691
11724
|
}
|
|
@@ -11852,7 +11885,7 @@ function computeHash2(content) {
|
|
|
11852
11885
|
}
|
|
11853
11886
|
function loadSharedSecret2() {
|
|
11854
11887
|
try {
|
|
11855
|
-
return
|
|
11888
|
+
return readFileSync9(getClipboardKeyPath(), "utf8").trim();
|
|
11856
11889
|
} catch {
|
|
11857
11890
|
return "";
|
|
11858
11891
|
}
|
|
@@ -11863,7 +11896,7 @@ function writePid(pid) {
|
|
|
11863
11896
|
}
|
|
11864
11897
|
function readPid() {
|
|
11865
11898
|
try {
|
|
11866
|
-
const pid = Number.parseInt(
|
|
11899
|
+
const pid = Number.parseInt(readFileSync9(DAEMON_PID_PATH, "utf8").trim());
|
|
11867
11900
|
return Number.isFinite(pid) ? pid : null;
|
|
11868
11901
|
} catch {
|
|
11869
11902
|
return null;
|
|
@@ -11964,7 +11997,7 @@ async function discoverPeers() {
|
|
|
11964
11997
|
|
|
11965
11998
|
// src/commands/heal.ts
|
|
11966
11999
|
init_paths();
|
|
11967
|
-
import { existsSync as
|
|
12000
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
11968
12001
|
import { join as join8 } from "path";
|
|
11969
12002
|
var DEFAULT_THRESHOLDS = {
|
|
11970
12003
|
reconnect: 3,
|
|
@@ -12016,9 +12049,9 @@ function getHealStatePath() {
|
|
|
12016
12049
|
}
|
|
12017
12050
|
function readHealConfig(path) {
|
|
12018
12051
|
const p = path || getHealConfigPath();
|
|
12019
|
-
if (!
|
|
12052
|
+
if (!existsSync10(p))
|
|
12020
12053
|
return { ...DEFAULT_HEAL_CONFIG, thresholds: { ...DEFAULT_THRESHOLDS } };
|
|
12021
|
-
const parsed = JSON.parse(
|
|
12054
|
+
const parsed = JSON.parse(readFileSync10(p, "utf8"));
|
|
12022
12055
|
return {
|
|
12023
12056
|
...DEFAULT_HEAL_CONFIG,
|
|
12024
12057
|
...parsed,
|
|
@@ -12034,10 +12067,10 @@ function writeHealConfig(config, path) {
|
|
|
12034
12067
|
}
|
|
12035
12068
|
function readHealState(path) {
|
|
12036
12069
|
const p = path || getHealStatePath();
|
|
12037
|
-
if (!
|
|
12070
|
+
if (!existsSync10(p))
|
|
12038
12071
|
return defaultHealState();
|
|
12039
12072
|
try {
|
|
12040
|
-
return { ...defaultHealState(), ...JSON.parse(
|
|
12073
|
+
return { ...defaultHealState(), ...JSON.parse(readFileSync10(p, "utf8")) };
|
|
12041
12074
|
} catch {
|
|
12042
12075
|
return defaultHealState();
|
|
12043
12076
|
}
|
|
@@ -12164,7 +12197,7 @@ function sh(cmd, timeoutMs = 8000) {
|
|
|
12164
12197
|
}
|
|
12165
12198
|
function getCurrentBootId() {
|
|
12166
12199
|
try {
|
|
12167
|
-
return
|
|
12200
|
+
return readFileSync10("/proc/sys/kernel/random/boot_id", "utf8").trim();
|
|
12168
12201
|
} catch {
|
|
12169
12202
|
return "";
|
|
12170
12203
|
}
|
|
@@ -12250,7 +12283,7 @@ function executeAction(action, config) {
|
|
|
12250
12283
|
|
|
12251
12284
|
// src/commands/heal-daemon.ts
|
|
12252
12285
|
init_paths();
|
|
12253
|
-
import { existsSync as
|
|
12286
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
|
|
12254
12287
|
import { join as join9 } from "path";
|
|
12255
12288
|
var DAEMON_PID_PATH2 = join9(getDataDir(), "heal-daemon.pid");
|
|
12256
12289
|
var SERVICE_PATH = "/etc/systemd/system/machines-heal.service";
|
|
@@ -12298,7 +12331,7 @@ function writePid2(pid) {
|
|
|
12298
12331
|
}
|
|
12299
12332
|
function readPid2() {
|
|
12300
12333
|
try {
|
|
12301
|
-
const pid = Number.parseInt(
|
|
12334
|
+
const pid = Number.parseInt(readFileSync11(DAEMON_PID_PATH2, "utf8").trim());
|
|
12302
12335
|
return Number.isFinite(pid) ? pid : null;
|
|
12303
12336
|
} catch {
|
|
12304
12337
|
return null;
|
|
@@ -12370,9 +12403,9 @@ function applyDeterminism(config) {
|
|
|
12370
12403
|
}
|
|
12371
12404
|
function enableHardwareWatchdog() {
|
|
12372
12405
|
const log2 = [];
|
|
12373
|
-
if (!
|
|
12406
|
+
if (!existsSync11(SYSTEM_CONF))
|
|
12374
12407
|
return ["/etc/systemd/system.conf not found; skipping hardware watchdog"];
|
|
12375
|
-
let conf =
|
|
12408
|
+
let conf = readFileSync11(SYSTEM_CONF, "utf8");
|
|
12376
12409
|
const set = (key, value) => {
|
|
12377
12410
|
const re = new RegExp(`^#?\\s*${key}=.*$`, "m");
|
|
12378
12411
|
if (re.test(conf))
|
|
@@ -12402,7 +12435,7 @@ function binPath() {
|
|
|
12402
12435
|
candidates.push(`${home}/.bun/bin/machines`);
|
|
12403
12436
|
candidates.push("/root/.bun/bin/machines", "/usr/local/bin/machines");
|
|
12404
12437
|
for (const c of candidates) {
|
|
12405
|
-
if (c &&
|
|
12438
|
+
if (c && existsSync11(c))
|
|
12406
12439
|
return c;
|
|
12407
12440
|
}
|
|
12408
12441
|
return "machines";
|
|
@@ -12438,7 +12471,7 @@ WantedBy=multi-user.target
|
|
|
12438
12471
|
function uninstallHealService() {
|
|
12439
12472
|
const log2 = [];
|
|
12440
12473
|
sh2("systemctl disable --now machines-heal.service 2>/dev/null || true");
|
|
12441
|
-
if (
|
|
12474
|
+
if (existsSync11(SERVICE_PATH)) {
|
|
12442
12475
|
sh2(`rm -f ${SERVICE_PATH}`);
|
|
12443
12476
|
sh2("systemctl daemon-reload");
|
|
12444
12477
|
log2.push(`removed ${SERVICE_PATH}`);
|
|
@@ -12449,7 +12482,7 @@ function uninstallHealService() {
|
|
|
12449
12482
|
}
|
|
12450
12483
|
function healServiceStatus() {
|
|
12451
12484
|
return {
|
|
12452
|
-
installed:
|
|
12485
|
+
installed: existsSync11(SERVICE_PATH),
|
|
12453
12486
|
active: sh2("systemctl is-active machines-heal.service").out === "active",
|
|
12454
12487
|
enabled: sh2("systemctl is-enabled machines-heal.service 2>/dev/null").out === "enabled"
|
|
12455
12488
|
};
|
|
@@ -12489,7 +12522,7 @@ ${items.map((item) => `- ${item}`).join(`
|
|
|
12489
12522
|
|
|
12490
12523
|
// src/cli/index.ts
|
|
12491
12524
|
import { rmSync as rmSync2 } from "fs";
|
|
12492
|
-
import { readFileSync as
|
|
12525
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
12493
12526
|
var program2 = new Command;
|
|
12494
12527
|
function printJsonOrText(data, text, json = false) {
|
|
12495
12528
|
if (json || program2.opts().quiet) {
|
|
@@ -12821,7 +12854,7 @@ manifestCommand.command("add").description("Add or replace a machine in the flee
|
|
|
12821
12854
|
console.error("error: --from-stdin requires piped input");
|
|
12822
12855
|
process.exit(1);
|
|
12823
12856
|
}
|
|
12824
|
-
const input =
|
|
12857
|
+
const input = readFileSync12(0, "utf8");
|
|
12825
12858
|
const machine2 = JSON.parse(input);
|
|
12826
12859
|
console.log(JSON.stringify(manifestAdd(machine2), null, 2));
|
|
12827
12860
|
return;
|
|
@@ -13150,13 +13183,25 @@ program2.command("route").description("Resolve the best route for a machine").re
|
|
|
13150
13183
|
}
|
|
13151
13184
|
console.log(options.privateMetadata ? command2 ?? `${resolved.route}:${resolved.target}` : `${publicResolved.route}:${publicResolved.target ?? "unresolved"}`);
|
|
13152
13185
|
});
|
|
13153
|
-
program2.command("ssh").description("Choose the best SSH route for a machine").requiredOption("--machine <id>", "Machine identifier").option("--cmd <command>", "Remote command to run").option("-j, --json", "Print JSON output", false).action((options) => {
|
|
13186
|
+
program2.command("ssh").description("Choose the best SSH route for a machine").requiredOption("--machine <id>", "Machine identifier").option("--cmd <command>", "Remote command to run").option("--private-metadata", "Print private SSH target and command", false).option("-j, --json", "Print JSON output", false).action((options) => {
|
|
13187
|
+
const resolved = resolveMachineRoute(options.machine);
|
|
13188
|
+
const publicResolved = redactRouteForOutput(resolved, { privateMetadata: options.privateMetadata });
|
|
13189
|
+
const command2 = resolved.ok && options.privateMetadata ? buildSshCommand(options.machine, options.cmd) : resolved.ok ? REDACTED_VALUE : null;
|
|
13154
13190
|
if (options.json) {
|
|
13155
|
-
|
|
13156
|
-
|
|
13191
|
+
console.log(JSON.stringify({ resolved: publicResolved, command: command2 }, null, 2));
|
|
13192
|
+
return;
|
|
13193
|
+
}
|
|
13194
|
+
if (!resolved.ok) {
|
|
13195
|
+
console.error(source_default.red(resolved.warnings.join("; ") || `No route found for ${options.machine}`));
|
|
13196
|
+
process.exitCode = 1;
|
|
13157
13197
|
return;
|
|
13158
13198
|
}
|
|
13159
|
-
|
|
13199
|
+
if (!options.privateMetadata) {
|
|
13200
|
+
console.error(source_default.red("Refusing to print private SSH target; rerun with --private-metadata."));
|
|
13201
|
+
process.exitCode = 1;
|
|
13202
|
+
return;
|
|
13203
|
+
}
|
|
13204
|
+
console.log(command2);
|
|
13160
13205
|
});
|
|
13161
13206
|
program2.command("screen").description("Open Screen Sharing (VNC) to a machine using its best live route").argument("[machine]", "Machine identifier").option("--machine <id>", "Machine identifier (alternative to positional arg)").option("--all", "Open every reachable machine", false).option("--print", "Print the vnc:// URL instead of opening it", false).option("-j, --json", "Print JSON output", false).action((machineArg, options) => {
|
|
13162
13207
|
if (options.all) {
|
|
@@ -13304,8 +13349,8 @@ storageCommand.command("sync").description("Bidirectional storage sync: pull the
|
|
|
13304
13349
|
printStorageError(error);
|
|
13305
13350
|
}
|
|
13306
13351
|
});
|
|
13307
|
-
program2.command("status").description("Print local machine and storage status").option("-j, --json", "Print JSON output", false).action((options) => {
|
|
13308
|
-
const status = getStatus();
|
|
13352
|
+
program2.command("status").description("Print local machine and storage status").option("--private-metadata", "Print private local paths and machine identifiers", false).option("-j, --json", "Print JSON output", false).action((options) => {
|
|
13353
|
+
const status = getStatus({ privateMetadata: options.privateMetadata });
|
|
13309
13354
|
printJsonOrText(status, renderFleetStatus(status), options.json);
|
|
13310
13355
|
});
|
|
13311
13356
|
program2.command("doctor").description("Run machine preflight checks").option("--machine <id>", "Machine identifier").option("-j, --json", "Print JSON output", false).action((options) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self-test.d.ts","sourceRoot":"","sources":["../../src/commands/self-test.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,aAAa,CAAC;AAMjE,wBAAgB,WAAW,IAAI,cAAc,
|
|
1
|
+
{"version":3,"file":"self-test.d.ts","sourceRoot":"","sources":["../../src/commands/self-test.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,aAAa,CAAC;AAMjE,wBAAgB,WAAW,IAAI,cAAc,CAmD5C"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import type { FleetStatus } from "../types.js";
|
|
2
|
-
export
|
|
2
|
+
export interface FleetStatusOptions {
|
|
3
|
+
privateMetadata?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function getStatus(options?: FleetStatusOptions): FleetStatus;
|
|
3
6
|
//# sourceMappingURL=status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAoCvE"}
|
package/dist/index.js
CHANGED
|
@@ -13728,7 +13728,7 @@ function renderDomainMapping(domain) {
|
|
|
13728
13728
|
}
|
|
13729
13729
|
// src/commands/daemon.ts
|
|
13730
13730
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
13731
|
-
import { chmodSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
13731
|
+
import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync4, statSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
13732
13732
|
import { dirname as dirname4 } from "path";
|
|
13733
13733
|
import { platform as osPlatform } from "os";
|
|
13734
13734
|
var DEFAULT_SERVICE_NAME = "machines-agent";
|
|
@@ -14092,6 +14092,8 @@ function escapeSystemdEnvironmentValue(value) {
|
|
|
14092
14092
|
function launchdPlist(options) {
|
|
14093
14093
|
const env = Object.entries(options.env).map(([name, value]) => ` <key>${xmlEscape(name)}</key>
|
|
14094
14094
|
<string>${xmlEscape(value)}</string>`).join(`
|
|
14095
|
+
`);
|
|
14096
|
+
const programArguments = daemonProgramArguments(options).map((value) => ` <string>${xmlEscape(value)}</string>`).join(`
|
|
14095
14097
|
`);
|
|
14096
14098
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
14097
14099
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -14101,9 +14103,7 @@ function launchdPlist(options) {
|
|
|
14101
14103
|
<string>${xmlEscape(options.serviceId)}</string>
|
|
14102
14104
|
<key>ProgramArguments</key>
|
|
14103
14105
|
<array>
|
|
14104
|
-
|
|
14105
|
-
<string>--interval-ms</string>
|
|
14106
|
-
<string>${options.intervalMs}</string>
|
|
14106
|
+
${programArguments}
|
|
14107
14107
|
</array>
|
|
14108
14108
|
<key>EnvironmentVariables</key>
|
|
14109
14109
|
<dict>
|
|
@@ -14124,6 +14124,7 @@ ${env}
|
|
|
14124
14124
|
function systemdUnit(options) {
|
|
14125
14125
|
const env = Object.entries(options.env).map(([name, value]) => `Environment=${quoteSystemdEnvironment(name, value)}`).join(`
|
|
14126
14126
|
`);
|
|
14127
|
+
const execStart = daemonProgramArguments(options).map(quoteSystemdExecArg).join(" ");
|
|
14127
14128
|
return `[Unit]
|
|
14128
14129
|
Description=Hasna machines agent
|
|
14129
14130
|
After=network-online.target
|
|
@@ -14131,7 +14132,7 @@ Wants=network-online.target
|
|
|
14131
14132
|
|
|
14132
14133
|
[Service]
|
|
14133
14134
|
Type=simple
|
|
14134
|
-
ExecStart=${
|
|
14135
|
+
ExecStart=${execStart}
|
|
14135
14136
|
Restart=always
|
|
14136
14137
|
RestartSec=10
|
|
14137
14138
|
${env}
|
|
@@ -14140,6 +14141,36 @@ ${env}
|
|
|
14140
14141
|
WantedBy=${options.mode === "system" ? "multi-user.target" : "default.target"}
|
|
14141
14142
|
`;
|
|
14142
14143
|
}
|
|
14144
|
+
function daemonProgramArguments(options) {
|
|
14145
|
+
const bunRuntime = siblingBunRuntime(options.executable);
|
|
14146
|
+
const base = bunRuntime ? [bunRuntime, options.executable] : [options.executable];
|
|
14147
|
+
return [...base, "--interval-ms", String(options.intervalMs)];
|
|
14148
|
+
}
|
|
14149
|
+
function siblingBunRuntime(executable) {
|
|
14150
|
+
if (!isBunShebangScript(executable))
|
|
14151
|
+
return null;
|
|
14152
|
+
const candidate = `${dirname4(executable)}/bun`;
|
|
14153
|
+
return isExecutableFile(candidate) ? candidate : null;
|
|
14154
|
+
}
|
|
14155
|
+
function isBunShebangScript(executable) {
|
|
14156
|
+
try {
|
|
14157
|
+
const content = readFileSync4(executable, "utf8").slice(0, 256);
|
|
14158
|
+
const firstLine2 = content.split(/\r?\n/, 1)[0] ?? "";
|
|
14159
|
+
return /^#!.*\bbun\b/.test(firstLine2);
|
|
14160
|
+
} catch {
|
|
14161
|
+
return false;
|
|
14162
|
+
}
|
|
14163
|
+
}
|
|
14164
|
+
function isExecutableFile(path) {
|
|
14165
|
+
if (!existsSync6(path))
|
|
14166
|
+
return false;
|
|
14167
|
+
try {
|
|
14168
|
+
const stats = statSync(path);
|
|
14169
|
+
return stats.isFile() && (stats.mode & 73) !== 0;
|
|
14170
|
+
} catch {
|
|
14171
|
+
return false;
|
|
14172
|
+
}
|
|
14173
|
+
}
|
|
14143
14174
|
function launchdDomain(options) {
|
|
14144
14175
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
14145
14176
|
}
|
|
@@ -14420,7 +14451,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
|
|
|
14420
14451
|
};
|
|
14421
14452
|
}
|
|
14422
14453
|
// src/commands/notifications.ts
|
|
14423
|
-
import { existsSync as
|
|
14454
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
14424
14455
|
var notificationChannelSchema = exports_external.object({
|
|
14425
14456
|
id: exports_external.string(),
|
|
14426
14457
|
type: exports_external.enum(["email", "webhook", "command"]),
|
|
@@ -14576,10 +14607,10 @@ function getDefaultNotificationConfig() {
|
|
|
14576
14607
|
};
|
|
14577
14608
|
}
|
|
14578
14609
|
function readNotificationConfig(path = getNotificationsPath()) {
|
|
14579
|
-
if (!
|
|
14610
|
+
if (!existsSync7(path)) {
|
|
14580
14611
|
return getDefaultNotificationConfig();
|
|
14581
14612
|
}
|
|
14582
|
-
return notificationConfigSchema.parse(JSON.parse(
|
|
14613
|
+
return notificationConfigSchema.parse(JSON.parse(readFileSync5(path, "utf8")));
|
|
14583
14614
|
}
|
|
14584
14615
|
function writeNotificationConfig(config, path = getNotificationsPath()) {
|
|
14585
14616
|
ensureParentDir(path);
|
|
@@ -14820,7 +14851,8 @@ function parseJsonObject2(value) {
|
|
|
14820
14851
|
return null;
|
|
14821
14852
|
}
|
|
14822
14853
|
}
|
|
14823
|
-
function getStatus() {
|
|
14854
|
+
function getStatus(options = {}) {
|
|
14855
|
+
const privateMetadata = options.privateMetadata === true;
|
|
14824
14856
|
const manifest = readManifest();
|
|
14825
14857
|
const heartbeats = listHeartbeats();
|
|
14826
14858
|
const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
|
|
@@ -14829,17 +14861,17 @@ function getStatus() {
|
|
|
14829
14861
|
...heartbeats.map((heartbeat) => heartbeat.machine_id)
|
|
14830
14862
|
]);
|
|
14831
14863
|
return {
|
|
14832
|
-
machineId: getLocalMachineId(),
|
|
14833
|
-
manifestPath: getManifestPath(),
|
|
14834
|
-
dbPath: getDbPath(),
|
|
14835
|
-
notificationsPath: getNotificationsPath(),
|
|
14864
|
+
machineId: privateMetadata ? getLocalMachineId() : REDACTED_VALUE,
|
|
14865
|
+
manifestPath: privateMetadata ? getManifestPath() : REDACTED_VALUE,
|
|
14866
|
+
dbPath: privateMetadata ? getDbPath() : REDACTED_VALUE,
|
|
14867
|
+
notificationsPath: privateMetadata ? getNotificationsPath() : REDACTED_VALUE,
|
|
14836
14868
|
manifestMachineCount: manifest.machines.length,
|
|
14837
14869
|
heartbeatCount: heartbeats.length,
|
|
14838
14870
|
machines: [...machineIds].sort().map((machineId) => {
|
|
14839
14871
|
const declared = manifest.machines.find((machine) => machine.id === machineId);
|
|
14840
14872
|
const heartbeat = heartbeatByMachine.get(machineId);
|
|
14841
14873
|
return {
|
|
14842
|
-
machineId,
|
|
14874
|
+
machineId: privateMetadata ? machineId : REDACTED_VALUE,
|
|
14843
14875
|
platform: declared?.platform,
|
|
14844
14876
|
manifestDeclared: Boolean(declared),
|
|
14845
14877
|
heartbeatStatus: heartbeat?.status || "unknown",
|
|
@@ -14847,7 +14879,7 @@ function getStatus() {
|
|
|
14847
14879
|
daemonVersion: heartbeat?.daemon_version ?? null,
|
|
14848
14880
|
agentMode: heartbeat?.agent_mode ?? null,
|
|
14849
14881
|
storageSyncStatus: heartbeat?.storage_sync_status ?? null,
|
|
14850
|
-
doctorSummary: parseJsonObject2(heartbeat?.doctor_summary_json),
|
|
14882
|
+
doctorSummary: privateMetadata ? parseJsonObject2(heartbeat?.doctor_summary_json) : null,
|
|
14851
14883
|
privateMetadata: Boolean(heartbeat?.private_metadata)
|
|
14852
14884
|
};
|
|
14853
14885
|
}),
|
|
@@ -15089,7 +15121,7 @@ function startDashboardServer(options = {}) {
|
|
|
15089
15121
|
return Response.json({ ok: true, ...getServeInfo(options) });
|
|
15090
15122
|
}
|
|
15091
15123
|
if (url.pathname === "/api/status") {
|
|
15092
|
-
return Response.json(getStatus());
|
|
15124
|
+
return Response.json(appendWarnings(getStatus({ privateMetadata }), privateWarnings));
|
|
15093
15125
|
}
|
|
15094
15126
|
if (url.pathname === "/api/topology") {
|
|
15095
15127
|
const topology = discoverMachineTopology({ includeTailscale: url.searchParams.get("tailscale") !== "false" });
|
|
@@ -15227,15 +15259,16 @@ function check(id, status, summary, detail) {
|
|
|
15227
15259
|
function runSelfTest() {
|
|
15228
15260
|
const version = getPackageVersion();
|
|
15229
15261
|
const status = getStatus();
|
|
15262
|
+
const machineId = getLocalMachineId();
|
|
15230
15263
|
const doctor = runDoctor();
|
|
15231
15264
|
const serveInfo = getServeInfo();
|
|
15232
15265
|
const html = renderDashboardHtml();
|
|
15233
15266
|
const notifications = listNotificationChannels();
|
|
15234
|
-
const apps = listApps(
|
|
15235
|
-
const appsDiff = diffApps(
|
|
15236
|
-
const cliPlan = buildClaudeInstallPlan(
|
|
15267
|
+
const apps = listApps(machineId);
|
|
15268
|
+
const appsDiff = diffApps(machineId);
|
|
15269
|
+
const cliPlan = buildClaudeInstallPlan(machineId);
|
|
15237
15270
|
return {
|
|
15238
|
-
machineId
|
|
15271
|
+
machineId,
|
|
15239
15272
|
checks: [
|
|
15240
15273
|
check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
|
|
15241
15274
|
check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
|
|
@@ -15516,7 +15549,7 @@ function buildScreenEnableCommand(machineId, options = {}) {
|
|
|
15516
15549
|
};
|
|
15517
15550
|
}
|
|
15518
15551
|
// src/commands/sync.ts
|
|
15519
|
-
import { existsSync as
|
|
15552
|
+
import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync6, symlinkSync, copyFileSync } from "fs";
|
|
15520
15553
|
import { homedir as homedir5 } from "os";
|
|
15521
15554
|
function quote4(value) {
|
|
15522
15555
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -15569,15 +15602,15 @@ function detectFileActions(machine) {
|
|
|
15569
15602
|
throw new Error(`Remote file sync planning is not supported for ${machine.id}; refusing to inspect or apply local paths as remote state.`);
|
|
15570
15603
|
}
|
|
15571
15604
|
return (machine.files || []).map((file, index) => {
|
|
15572
|
-
const sourceExists =
|
|
15573
|
-
const targetExists =
|
|
15605
|
+
const sourceExists = existsSync8(file.source);
|
|
15606
|
+
const targetExists = existsSync8(file.target);
|
|
15574
15607
|
let status = "missing";
|
|
15575
15608
|
if (sourceExists && targetExists) {
|
|
15576
15609
|
if (file.mode === "symlink") {
|
|
15577
15610
|
status = lstatSync(file.target).isSymbolicLink() ? "ok" : "drifted";
|
|
15578
15611
|
} else {
|
|
15579
|
-
const source =
|
|
15580
|
-
const target =
|
|
15612
|
+
const source = readFileSync6(file.source, "utf8");
|
|
15613
|
+
const target = readFileSync6(file.target, "utf8");
|
|
15581
15614
|
status = source === target ? "ok" : "drifted";
|
|
15582
15615
|
}
|
|
15583
15616
|
}
|
|
@@ -24805,14 +24838,17 @@ function privateOutputWarnings2(requested, allowed) {
|
|
|
24805
24838
|
function appendWarnings2(payload, warnings) {
|
|
24806
24839
|
if (warnings.length === 0)
|
|
24807
24840
|
return payload;
|
|
24808
|
-
|
|
24841
|
+
const currentWarnings = typeof payload === "object" && payload && "warnings" in payload && Array.isArray(payload.warnings) ? payload.warnings : [];
|
|
24842
|
+
return { ...payload, warnings: [...currentWarnings, ...warnings] };
|
|
24809
24843
|
}
|
|
24810
24844
|
function createMcpServer(version2) {
|
|
24811
24845
|
const server = new McpServer({ name: "machines", version: version2 });
|
|
24812
24846
|
const events = new EventsClient3;
|
|
24813
|
-
server.tool("machines_status", "Return local machine fleet status paths and machine identity.", {}, async () =>
|
|
24814
|
-
|
|
24815
|
-
|
|
24847
|
+
server.tool("machines_status", "Return local machine fleet status paths and machine identity.", { private_metadata: exports_external.boolean().optional().describe("Include private local paths and machine identifiers") }, async ({ private_metadata }) => {
|
|
24848
|
+
const privateMetadata = privateMetadataAllowed(private_metadata);
|
|
24849
|
+
const warnings = privateOutputWarnings2(private_metadata, privateMetadata);
|
|
24850
|
+
return { content: [{ type: "text", text: JSON.stringify(appendWarnings2(getStatus({ privateMetadata }), warnings), null, 2) }] };
|
|
24851
|
+
});
|
|
24816
24852
|
server.tool("machines_doctor", "Run machine preflight checks.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({ content: [{ type: "text", text: JSON.stringify(runDoctor(machine_id), null, 2) }] }));
|
|
24817
24853
|
server.tool("machines_self_test", "Run local package smoke checks.", {}, async () => ({
|
|
24818
24854
|
content: [{ type: "text", text: JSON.stringify(runSelfTest(), null, 2) }]
|
|
@@ -24993,9 +25029,23 @@ function createMcpServer(version2) {
|
|
|
24993
25029
|
}), null, 2)
|
|
24994
25030
|
}]
|
|
24995
25031
|
}));
|
|
24996
|
-
server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
|
|
24997
|
-
|
|
24998
|
-
|
|
25032
|
+
server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
|
|
25033
|
+
machine_id: exports_external.string().describe("Machine identifier"),
|
|
25034
|
+
remote_command: exports_external.string().optional().describe("Optional remote command"),
|
|
25035
|
+
private_metadata: exports_external.boolean().optional().describe("Include private SSH target and command")
|
|
25036
|
+
}, async ({ machine_id, remote_command, private_metadata }) => {
|
|
25037
|
+
const privateMetadata = privateMetadataAllowed(private_metadata);
|
|
25038
|
+
const warnings = privateOutputWarnings2(private_metadata, privateMetadata);
|
|
25039
|
+
const resolved = resolveMachineRoute(machine_id);
|
|
25040
|
+
const publicResolved = redactRouteForOutput(resolved, { privateMetadata });
|
|
25041
|
+
const command2 = resolved.ok && privateMetadata ? buildSshCommand(machine_id, remote_command) : resolved.ok ? "[redacted]" : null;
|
|
25042
|
+
return {
|
|
25043
|
+
content: [{
|
|
25044
|
+
type: "text",
|
|
25045
|
+
text: JSON.stringify(appendWarnings2({ resolved: publicResolved, command: command2 }, warnings), null, 2)
|
|
25046
|
+
}]
|
|
25047
|
+
};
|
|
25048
|
+
});
|
|
24999
25049
|
server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
|
|
25000
25050
|
content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
|
|
25001
25051
|
}));
|
package/dist/mcp/index.js
CHANGED
|
@@ -5954,6 +5954,7 @@ function diffMachines(leftMachineId, rightMachineId) {
|
|
|
5954
5954
|
}
|
|
5955
5955
|
|
|
5956
5956
|
// src/commands/daemon.ts
|
|
5957
|
+
import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync4, statSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
5957
5958
|
import { dirname as dirname4 } from "path";
|
|
5958
5959
|
import { platform as osPlatform } from "os";
|
|
5959
5960
|
var DEFAULT_SERVICE_NAME = "machines-agent";
|
|
@@ -6168,6 +6169,8 @@ function command(id, description, program, args, sudo, mutates, allowFailure = f
|
|
|
6168
6169
|
function launchdPlist(options) {
|
|
6169
6170
|
const env = Object.entries(options.env).map(([name, value]) => ` <key>${xmlEscape(name)}</key>
|
|
6170
6171
|
<string>${xmlEscape(value)}</string>`).join(`
|
|
6172
|
+
`);
|
|
6173
|
+
const programArguments = daemonProgramArguments(options).map((value) => ` <string>${xmlEscape(value)}</string>`).join(`
|
|
6171
6174
|
`);
|
|
6172
6175
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
6173
6176
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -6177,9 +6180,7 @@ function launchdPlist(options) {
|
|
|
6177
6180
|
<string>${xmlEscape(options.serviceId)}</string>
|
|
6178
6181
|
<key>ProgramArguments</key>
|
|
6179
6182
|
<array>
|
|
6180
|
-
|
|
6181
|
-
<string>--interval-ms</string>
|
|
6182
|
-
<string>${options.intervalMs}</string>
|
|
6183
|
+
${programArguments}
|
|
6183
6184
|
</array>
|
|
6184
6185
|
<key>EnvironmentVariables</key>
|
|
6185
6186
|
<dict>
|
|
@@ -6200,6 +6201,7 @@ ${env}
|
|
|
6200
6201
|
function systemdUnit(options) {
|
|
6201
6202
|
const env = Object.entries(options.env).map(([name, value]) => `Environment=${quoteSystemdEnvironment(name, value)}`).join(`
|
|
6202
6203
|
`);
|
|
6204
|
+
const execStart = daemonProgramArguments(options).map(quoteSystemdExecArg).join(" ");
|
|
6203
6205
|
return `[Unit]
|
|
6204
6206
|
Description=Hasna machines agent
|
|
6205
6207
|
After=network-online.target
|
|
@@ -6207,7 +6209,7 @@ Wants=network-online.target
|
|
|
6207
6209
|
|
|
6208
6210
|
[Service]
|
|
6209
6211
|
Type=simple
|
|
6210
|
-
ExecStart=${
|
|
6212
|
+
ExecStart=${execStart}
|
|
6211
6213
|
Restart=always
|
|
6212
6214
|
RestartSec=10
|
|
6213
6215
|
${env}
|
|
@@ -6216,6 +6218,36 @@ ${env}
|
|
|
6216
6218
|
WantedBy=${options.mode === "system" ? "multi-user.target" : "default.target"}
|
|
6217
6219
|
`;
|
|
6218
6220
|
}
|
|
6221
|
+
function daemonProgramArguments(options) {
|
|
6222
|
+
const bunRuntime = siblingBunRuntime(options.executable);
|
|
6223
|
+
const base = bunRuntime ? [bunRuntime, options.executable] : [options.executable];
|
|
6224
|
+
return [...base, "--interval-ms", String(options.intervalMs)];
|
|
6225
|
+
}
|
|
6226
|
+
function siblingBunRuntime(executable) {
|
|
6227
|
+
if (!isBunShebangScript(executable))
|
|
6228
|
+
return null;
|
|
6229
|
+
const candidate = `${dirname4(executable)}/bun`;
|
|
6230
|
+
return isExecutableFile(candidate) ? candidate : null;
|
|
6231
|
+
}
|
|
6232
|
+
function isBunShebangScript(executable) {
|
|
6233
|
+
try {
|
|
6234
|
+
const content = readFileSync4(executable, "utf8").slice(0, 256);
|
|
6235
|
+
const firstLine = content.split(/\r?\n/, 1)[0] ?? "";
|
|
6236
|
+
return /^#!.*\bbun\b/.test(firstLine);
|
|
6237
|
+
} catch {
|
|
6238
|
+
return false;
|
|
6239
|
+
}
|
|
6240
|
+
}
|
|
6241
|
+
function isExecutableFile(path) {
|
|
6242
|
+
if (!existsSync6(path))
|
|
6243
|
+
return false;
|
|
6244
|
+
try {
|
|
6245
|
+
const stats = statSync(path);
|
|
6246
|
+
return stats.isFile() && (stats.mode & 73) !== 0;
|
|
6247
|
+
} catch {
|
|
6248
|
+
return false;
|
|
6249
|
+
}
|
|
6250
|
+
}
|
|
6219
6251
|
function launchdDomain(options) {
|
|
6220
6252
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
6221
6253
|
}
|
|
@@ -6610,7 +6642,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
|
|
|
6610
6642
|
}
|
|
6611
6643
|
|
|
6612
6644
|
// src/commands/notifications.ts
|
|
6613
|
-
import { existsSync as
|
|
6645
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
6614
6646
|
var notificationChannelSchema = exports_external.object({
|
|
6615
6647
|
id: exports_external.string(),
|
|
6616
6648
|
type: exports_external.enum(["email", "webhook", "command"]),
|
|
@@ -6766,10 +6798,10 @@ function getDefaultNotificationConfig() {
|
|
|
6766
6798
|
};
|
|
6767
6799
|
}
|
|
6768
6800
|
function readNotificationConfig(path = getNotificationsPath()) {
|
|
6769
|
-
if (!
|
|
6801
|
+
if (!existsSync7(path)) {
|
|
6770
6802
|
return getDefaultNotificationConfig();
|
|
6771
6803
|
}
|
|
6772
|
-
return notificationConfigSchema.parse(JSON.parse(
|
|
6804
|
+
return notificationConfigSchema.parse(JSON.parse(readFileSync5(path, "utf8")));
|
|
6773
6805
|
}
|
|
6774
6806
|
function writeNotificationConfig(config, path = getNotificationsPath()) {
|
|
6775
6807
|
ensureParentDir(path);
|
|
@@ -6778,7 +6810,7 @@ function writeNotificationConfig(config, path = getNotificationsPath()) {
|
|
|
6778
6810
|
updatedAt: new Date().toISOString(),
|
|
6779
6811
|
channels: sortChannels(config.channels)
|
|
6780
6812
|
};
|
|
6781
|
-
|
|
6813
|
+
writeFileSync4(path, `${JSON.stringify(nextConfig, null, 2)}
|
|
6782
6814
|
`, "utf8");
|
|
6783
6815
|
return nextConfig;
|
|
6784
6816
|
}
|
|
@@ -7397,7 +7429,8 @@ function parseJsonObject2(value) {
|
|
|
7397
7429
|
return null;
|
|
7398
7430
|
}
|
|
7399
7431
|
}
|
|
7400
|
-
function getStatus() {
|
|
7432
|
+
function getStatus(options = {}) {
|
|
7433
|
+
const privateMetadata = options.privateMetadata === true;
|
|
7401
7434
|
const manifest = readManifest();
|
|
7402
7435
|
const heartbeats = listHeartbeats();
|
|
7403
7436
|
const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
|
|
@@ -7406,17 +7439,17 @@ function getStatus() {
|
|
|
7406
7439
|
...heartbeats.map((heartbeat) => heartbeat.machine_id)
|
|
7407
7440
|
]);
|
|
7408
7441
|
return {
|
|
7409
|
-
machineId: getLocalMachineId(),
|
|
7410
|
-
manifestPath: getManifestPath(),
|
|
7411
|
-
dbPath: getDbPath(),
|
|
7412
|
-
notificationsPath: getNotificationsPath(),
|
|
7442
|
+
machineId: privateMetadata ? getLocalMachineId() : REDACTED_VALUE,
|
|
7443
|
+
manifestPath: privateMetadata ? getManifestPath() : REDACTED_VALUE,
|
|
7444
|
+
dbPath: privateMetadata ? getDbPath() : REDACTED_VALUE,
|
|
7445
|
+
notificationsPath: privateMetadata ? getNotificationsPath() : REDACTED_VALUE,
|
|
7413
7446
|
manifestMachineCount: manifest.machines.length,
|
|
7414
7447
|
heartbeatCount: heartbeats.length,
|
|
7415
7448
|
machines: [...machineIds].sort().map((machineId) => {
|
|
7416
7449
|
const declared = manifest.machines.find((machine) => machine.id === machineId);
|
|
7417
7450
|
const heartbeat = heartbeatByMachine.get(machineId);
|
|
7418
7451
|
return {
|
|
7419
|
-
machineId,
|
|
7452
|
+
machineId: privateMetadata ? machineId : REDACTED_VALUE,
|
|
7420
7453
|
platform: declared?.platform,
|
|
7421
7454
|
manifestDeclared: Boolean(declared),
|
|
7422
7455
|
heartbeatStatus: heartbeat?.status || "unknown",
|
|
@@ -7424,7 +7457,7 @@ function getStatus() {
|
|
|
7424
7457
|
daemonVersion: heartbeat?.daemon_version ?? null,
|
|
7425
7458
|
agentMode: heartbeat?.agent_mode ?? null,
|
|
7426
7459
|
storageSyncStatus: heartbeat?.storage_sync_status ?? null,
|
|
7427
|
-
doctorSummary: parseJsonObject2(heartbeat?.doctor_summary_json),
|
|
7460
|
+
doctorSummary: privateMetadata ? parseJsonObject2(heartbeat?.doctor_summary_json) : null,
|
|
7428
7461
|
privateMetadata: Boolean(heartbeat?.private_metadata)
|
|
7429
7462
|
};
|
|
7430
7463
|
}),
|
|
@@ -7440,15 +7473,16 @@ function check(id, status, summary, detail) {
|
|
|
7440
7473
|
function runSelfTest() {
|
|
7441
7474
|
const version = getPackageVersion();
|
|
7442
7475
|
const status = getStatus();
|
|
7476
|
+
const machineId = getLocalMachineId();
|
|
7443
7477
|
const doctor = runDoctor();
|
|
7444
7478
|
const serveInfo = getServeInfo();
|
|
7445
7479
|
const html = renderDashboardHtml();
|
|
7446
7480
|
const notifications = listNotificationChannels();
|
|
7447
|
-
const apps = listApps(
|
|
7448
|
-
const appsDiff = diffApps(
|
|
7449
|
-
const cliPlan = buildClaudeInstallPlan(
|
|
7481
|
+
const apps = listApps(machineId);
|
|
7482
|
+
const appsDiff = diffApps(machineId);
|
|
7483
|
+
const cliPlan = buildClaudeInstallPlan(machineId);
|
|
7450
7484
|
return {
|
|
7451
|
-
machineId
|
|
7485
|
+
machineId,
|
|
7452
7486
|
checks: [
|
|
7453
7487
|
check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
|
|
7454
7488
|
check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
|
|
@@ -7807,7 +7841,7 @@ function runSetup(machineId, options = {}, runner = runMachineCommand) {
|
|
|
7807
7841
|
}
|
|
7808
7842
|
|
|
7809
7843
|
// src/commands/sync.ts
|
|
7810
|
-
import { existsSync as
|
|
7844
|
+
import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync6, symlinkSync, copyFileSync } from "fs";
|
|
7811
7845
|
import { homedir as homedir5 } from "os";
|
|
7812
7846
|
function quote4(value) {
|
|
7813
7847
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -7860,15 +7894,15 @@ function detectFileActions(machine) {
|
|
|
7860
7894
|
throw new Error(`Remote file sync planning is not supported for ${machine.id}; refusing to inspect or apply local paths as remote state.`);
|
|
7861
7895
|
}
|
|
7862
7896
|
return (machine.files || []).map((file, index) => {
|
|
7863
|
-
const sourceExists =
|
|
7864
|
-
const targetExists =
|
|
7897
|
+
const sourceExists = existsSync8(file.source);
|
|
7898
|
+
const targetExists = existsSync8(file.target);
|
|
7865
7899
|
let status = "missing";
|
|
7866
7900
|
if (sourceExists && targetExists) {
|
|
7867
7901
|
if (file.mode === "symlink") {
|
|
7868
7902
|
status = lstatSync(file.target).isSymbolicLink() ? "ok" : "drifted";
|
|
7869
7903
|
} else {
|
|
7870
|
-
const source =
|
|
7871
|
-
const target =
|
|
7904
|
+
const source = readFileSync6(file.source, "utf8");
|
|
7905
|
+
const target = readFileSync6(file.target, "utf8");
|
|
7872
7906
|
status = source === target ? "ok" : "drifted";
|
|
7873
7907
|
}
|
|
7874
7908
|
}
|
|
@@ -8218,14 +8252,17 @@ function privateOutputWarnings(requested, allowed) {
|
|
|
8218
8252
|
function appendWarnings(payload, warnings) {
|
|
8219
8253
|
if (warnings.length === 0)
|
|
8220
8254
|
return payload;
|
|
8221
|
-
|
|
8255
|
+
const currentWarnings = typeof payload === "object" && payload && "warnings" in payload && Array.isArray(payload.warnings) ? payload.warnings : [];
|
|
8256
|
+
return { ...payload, warnings: [...currentWarnings, ...warnings] };
|
|
8222
8257
|
}
|
|
8223
8258
|
function createMcpServer(version) {
|
|
8224
8259
|
const server = new McpServer({ name: "machines", version });
|
|
8225
8260
|
const events = new EventsClient2;
|
|
8226
|
-
server.tool("machines_status", "Return local machine fleet status paths and machine identity.", {}, async () =>
|
|
8227
|
-
|
|
8228
|
-
|
|
8261
|
+
server.tool("machines_status", "Return local machine fleet status paths and machine identity.", { private_metadata: exports_external.boolean().optional().describe("Include private local paths and machine identifiers") }, async ({ private_metadata }) => {
|
|
8262
|
+
const privateMetadata = privateMetadataAllowed(private_metadata);
|
|
8263
|
+
const warnings = privateOutputWarnings(private_metadata, privateMetadata);
|
|
8264
|
+
return { content: [{ type: "text", text: JSON.stringify(appendWarnings(getStatus({ privateMetadata }), warnings), null, 2) }] };
|
|
8265
|
+
});
|
|
8229
8266
|
server.tool("machines_doctor", "Run machine preflight checks.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({ content: [{ type: "text", text: JSON.stringify(runDoctor(machine_id), null, 2) }] }));
|
|
8230
8267
|
server.tool("machines_self_test", "Run local package smoke checks.", {}, async () => ({
|
|
8231
8268
|
content: [{ type: "text", text: JSON.stringify(runSelfTest(), null, 2) }]
|
|
@@ -8406,9 +8443,23 @@ function createMcpServer(version) {
|
|
|
8406
8443
|
}), null, 2)
|
|
8407
8444
|
}]
|
|
8408
8445
|
}));
|
|
8409
|
-
server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
|
|
8410
|
-
|
|
8411
|
-
|
|
8446
|
+
server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
|
|
8447
|
+
machine_id: exports_external.string().describe("Machine identifier"),
|
|
8448
|
+
remote_command: exports_external.string().optional().describe("Optional remote command"),
|
|
8449
|
+
private_metadata: exports_external.boolean().optional().describe("Include private SSH target and command")
|
|
8450
|
+
}, async ({ machine_id, remote_command, private_metadata }) => {
|
|
8451
|
+
const privateMetadata = privateMetadataAllowed(private_metadata);
|
|
8452
|
+
const warnings = privateOutputWarnings(private_metadata, privateMetadata);
|
|
8453
|
+
const resolved = resolveMachineRoute(machine_id);
|
|
8454
|
+
const publicResolved = redactRouteForOutput(resolved, { privateMetadata });
|
|
8455
|
+
const command2 = resolved.ok && privateMetadata ? buildSshCommand(machine_id, remote_command) : resolved.ok ? "[redacted]" : null;
|
|
8456
|
+
return {
|
|
8457
|
+
content: [{
|
|
8458
|
+
type: "text",
|
|
8459
|
+
text: JSON.stringify(appendWarnings({ resolved: publicResolved, command: command2 }, warnings), null, 2)
|
|
8460
|
+
}]
|
|
8461
|
+
};
|
|
8462
|
+
});
|
|
8412
8463
|
server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
|
|
8413
8464
|
content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
|
|
8414
8465
|
}));
|
package/dist/mcp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiCpE,eAAO,MAAM,sBAAsB,k9CA2DzB,CAAC;AAEX,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAA4B,GAAG,SAAS,CAE5E;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiCpE,eAAO,MAAM,sBAAsB,k9CA2DzB,CAAC;AAEX,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAA4B,GAAG,SAAS,CAE5E;AAkBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAykB1D"}
|
package/dist/types.d.ts
CHANGED
|
@@ -116,6 +116,7 @@ export interface FleetStatus {
|
|
|
116
116
|
machines: FleetStatusMachine[];
|
|
117
117
|
recentSetupRuns: number;
|
|
118
118
|
recentSyncRuns: number;
|
|
119
|
+
warnings?: string[];
|
|
119
120
|
}
|
|
120
121
|
export type NotificationChannelType = "email" | "webhook" | "command";
|
|
121
122
|
export interface NotificationChannel {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|