@hasna/machines 0.0.43 → 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 +73 -38
- 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 +66 -26
- package/dist/mcp/index.js +65 -25
- 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, existsSync as existsSync8, 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";
|
|
@@ -10984,8 +10985,29 @@ function daemonProgramArguments(options) {
|
|
|
10984
10985
|
return [...base, "--interval-ms", String(options.intervalMs)];
|
|
10985
10986
|
}
|
|
10986
10987
|
function siblingBunRuntime(executable) {
|
|
10988
|
+
if (!isBunShebangScript(executable))
|
|
10989
|
+
return null;
|
|
10987
10990
|
const candidate = `${dirname4(executable)}/bun`;
|
|
10988
|
-
return
|
|
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
|
+
}
|
|
10989
11011
|
}
|
|
10990
11012
|
function launchdDomain(options) {
|
|
10991
11013
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
@@ -11343,7 +11365,7 @@ function startDashboardServer(options = {}) {
|
|
|
11343
11365
|
return Response.json({ ok: true, ...getServeInfo(options) });
|
|
11344
11366
|
}
|
|
11345
11367
|
if (url.pathname === "/api/status") {
|
|
11346
|
-
return Response.json(getStatus());
|
|
11368
|
+
return Response.json(appendWarnings(getStatus({ privateMetadata }), privateWarnings));
|
|
11347
11369
|
}
|
|
11348
11370
|
if (url.pathname === "/api/topology") {
|
|
11349
11371
|
const topology = discoverMachineTopology({ includeTailscale: url.searchParams.get("tailscale") !== "false" });
|
|
@@ -11481,15 +11503,16 @@ function check(id, status, summary, detail) {
|
|
|
11481
11503
|
function runSelfTest() {
|
|
11482
11504
|
const version = getPackageVersion();
|
|
11483
11505
|
const status = getStatus();
|
|
11506
|
+
const machineId = getLocalMachineId();
|
|
11484
11507
|
const doctor = runDoctor();
|
|
11485
11508
|
const serveInfo = getServeInfo();
|
|
11486
11509
|
const html = renderDashboardHtml();
|
|
11487
11510
|
const notifications = listNotificationChannels();
|
|
11488
|
-
const apps = listApps(
|
|
11489
|
-
const appsDiff = diffApps(
|
|
11490
|
-
const cliPlan = buildClaudeInstallPlan(
|
|
11511
|
+
const apps = listApps(machineId);
|
|
11512
|
+
const appsDiff = diffApps(machineId);
|
|
11513
|
+
const cliPlan = buildClaudeInstallPlan(machineId);
|
|
11491
11514
|
return {
|
|
11492
|
-
machineId
|
|
11515
|
+
machineId,
|
|
11493
11516
|
checks: [
|
|
11494
11517
|
check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
|
|
11495
11518
|
check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
|
|
@@ -11507,7 +11530,7 @@ function runSelfTest() {
|
|
|
11507
11530
|
// src/commands/clipboard.ts
|
|
11508
11531
|
init_paths();
|
|
11509
11532
|
import { createHash } from "crypto";
|
|
11510
|
-
import { existsSync as existsSync9, readFileSync as
|
|
11533
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, rmSync, writeFileSync as writeFileSync5 } from "fs";
|
|
11511
11534
|
import { join as join6 } from "path";
|
|
11512
11535
|
var DEFAULT_CONFIG = {
|
|
11513
11536
|
version: 1,
|
|
@@ -11541,7 +11564,7 @@ function readConfig(configPath) {
|
|
|
11541
11564
|
if (!existsSync9(path)) {
|
|
11542
11565
|
return getDefaultConfig();
|
|
11543
11566
|
}
|
|
11544
|
-
const parsed = JSON.parse(
|
|
11567
|
+
const parsed = JSON.parse(readFileSync7(path, "utf8"));
|
|
11545
11568
|
return { ...getDefaultConfig(), ...parsed };
|
|
11546
11569
|
}
|
|
11547
11570
|
function writeConfig(config, configPath) {
|
|
@@ -11556,7 +11579,7 @@ function readHistory(historyPath) {
|
|
|
11556
11579
|
return [];
|
|
11557
11580
|
}
|
|
11558
11581
|
try {
|
|
11559
|
-
return JSON.parse(
|
|
11582
|
+
return JSON.parse(readFileSync7(path, "utf8"));
|
|
11560
11583
|
} catch {
|
|
11561
11584
|
return [];
|
|
11562
11585
|
}
|
|
@@ -11586,7 +11609,7 @@ function sanitizeClipboardForRead(content, maxSizeBytes, skipPatterns) {
|
|
|
11586
11609
|
function getOrCreateClipboardKey() {
|
|
11587
11610
|
const keyPath = getClipboardKeyPath();
|
|
11588
11611
|
if (existsSync9(keyPath)) {
|
|
11589
|
-
return
|
|
11612
|
+
return readFileSync7(keyPath, "utf8").trim();
|
|
11590
11613
|
}
|
|
11591
11614
|
const key = createHash("sha256").update(crypto.randomUUID()).digest("hex").slice(0, 32);
|
|
11592
11615
|
ensureParentDir(keyPath);
|
|
@@ -11641,7 +11664,7 @@ function getClipboardStatus(historyPath) {
|
|
|
11641
11664
|
|
|
11642
11665
|
// src/commands/clipboard-daemon.ts
|
|
11643
11666
|
init_paths();
|
|
11644
|
-
import { readFileSync as
|
|
11667
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
11645
11668
|
import { join as join7 } from "path";
|
|
11646
11669
|
import { createHash as createHash3 } from "crypto";
|
|
11647
11670
|
|
|
@@ -11649,7 +11672,7 @@ import { createHash as createHash3 } from "crypto";
|
|
|
11649
11672
|
init_paths();
|
|
11650
11673
|
import { createServer } from "http";
|
|
11651
11674
|
import { createHash as createHash2 } from "crypto";
|
|
11652
|
-
import { readFileSync as
|
|
11675
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
11653
11676
|
function readLocalClipboardSync() {
|
|
11654
11677
|
const platform5 = process.platform;
|
|
11655
11678
|
if (platform5 === "darwin") {
|
|
@@ -11695,7 +11718,7 @@ function hasCommand3(binary) {
|
|
|
11695
11718
|
function loadSharedSecret() {
|
|
11696
11719
|
const keyPath = getClipboardKeyPath();
|
|
11697
11720
|
try {
|
|
11698
|
-
return
|
|
11721
|
+
return readFileSync8(keyPath, "utf8").trim();
|
|
11699
11722
|
} catch {
|
|
11700
11723
|
return "";
|
|
11701
11724
|
}
|
|
@@ -11862,7 +11885,7 @@ function computeHash2(content) {
|
|
|
11862
11885
|
}
|
|
11863
11886
|
function loadSharedSecret2() {
|
|
11864
11887
|
try {
|
|
11865
|
-
return
|
|
11888
|
+
return readFileSync9(getClipboardKeyPath(), "utf8").trim();
|
|
11866
11889
|
} catch {
|
|
11867
11890
|
return "";
|
|
11868
11891
|
}
|
|
@@ -11873,7 +11896,7 @@ function writePid(pid) {
|
|
|
11873
11896
|
}
|
|
11874
11897
|
function readPid() {
|
|
11875
11898
|
try {
|
|
11876
|
-
const pid = Number.parseInt(
|
|
11899
|
+
const pid = Number.parseInt(readFileSync9(DAEMON_PID_PATH, "utf8").trim());
|
|
11877
11900
|
return Number.isFinite(pid) ? pid : null;
|
|
11878
11901
|
} catch {
|
|
11879
11902
|
return null;
|
|
@@ -11974,7 +11997,7 @@ async function discoverPeers() {
|
|
|
11974
11997
|
|
|
11975
11998
|
// src/commands/heal.ts
|
|
11976
11999
|
init_paths();
|
|
11977
|
-
import { existsSync as existsSync10, readFileSync as
|
|
12000
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
11978
12001
|
import { join as join8 } from "path";
|
|
11979
12002
|
var DEFAULT_THRESHOLDS = {
|
|
11980
12003
|
reconnect: 3,
|
|
@@ -12028,7 +12051,7 @@ function readHealConfig(path) {
|
|
|
12028
12051
|
const p = path || getHealConfigPath();
|
|
12029
12052
|
if (!existsSync10(p))
|
|
12030
12053
|
return { ...DEFAULT_HEAL_CONFIG, thresholds: { ...DEFAULT_THRESHOLDS } };
|
|
12031
|
-
const parsed = JSON.parse(
|
|
12054
|
+
const parsed = JSON.parse(readFileSync10(p, "utf8"));
|
|
12032
12055
|
return {
|
|
12033
12056
|
...DEFAULT_HEAL_CONFIG,
|
|
12034
12057
|
...parsed,
|
|
@@ -12047,7 +12070,7 @@ function readHealState(path) {
|
|
|
12047
12070
|
if (!existsSync10(p))
|
|
12048
12071
|
return defaultHealState();
|
|
12049
12072
|
try {
|
|
12050
|
-
return { ...defaultHealState(), ...JSON.parse(
|
|
12073
|
+
return { ...defaultHealState(), ...JSON.parse(readFileSync10(p, "utf8")) };
|
|
12051
12074
|
} catch {
|
|
12052
12075
|
return defaultHealState();
|
|
12053
12076
|
}
|
|
@@ -12174,7 +12197,7 @@ function sh(cmd, timeoutMs = 8000) {
|
|
|
12174
12197
|
}
|
|
12175
12198
|
function getCurrentBootId() {
|
|
12176
12199
|
try {
|
|
12177
|
-
return
|
|
12200
|
+
return readFileSync10("/proc/sys/kernel/random/boot_id", "utf8").trim();
|
|
12178
12201
|
} catch {
|
|
12179
12202
|
return "";
|
|
12180
12203
|
}
|
|
@@ -12260,7 +12283,7 @@ function executeAction(action, config) {
|
|
|
12260
12283
|
|
|
12261
12284
|
// src/commands/heal-daemon.ts
|
|
12262
12285
|
init_paths();
|
|
12263
|
-
import { existsSync as existsSync11, readFileSync as
|
|
12286
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
|
|
12264
12287
|
import { join as join9 } from "path";
|
|
12265
12288
|
var DAEMON_PID_PATH2 = join9(getDataDir(), "heal-daemon.pid");
|
|
12266
12289
|
var SERVICE_PATH = "/etc/systemd/system/machines-heal.service";
|
|
@@ -12308,7 +12331,7 @@ function writePid2(pid) {
|
|
|
12308
12331
|
}
|
|
12309
12332
|
function readPid2() {
|
|
12310
12333
|
try {
|
|
12311
|
-
const pid = Number.parseInt(
|
|
12334
|
+
const pid = Number.parseInt(readFileSync11(DAEMON_PID_PATH2, "utf8").trim());
|
|
12312
12335
|
return Number.isFinite(pid) ? pid : null;
|
|
12313
12336
|
} catch {
|
|
12314
12337
|
return null;
|
|
@@ -12382,7 +12405,7 @@ function enableHardwareWatchdog() {
|
|
|
12382
12405
|
const log2 = [];
|
|
12383
12406
|
if (!existsSync11(SYSTEM_CONF))
|
|
12384
12407
|
return ["/etc/systemd/system.conf not found; skipping hardware watchdog"];
|
|
12385
|
-
let conf =
|
|
12408
|
+
let conf = readFileSync11(SYSTEM_CONF, "utf8");
|
|
12386
12409
|
const set = (key, value) => {
|
|
12387
12410
|
const re = new RegExp(`^#?\\s*${key}=.*$`, "m");
|
|
12388
12411
|
if (re.test(conf))
|
|
@@ -12499,7 +12522,7 @@ ${items.map((item) => `- ${item}`).join(`
|
|
|
12499
12522
|
|
|
12500
12523
|
// src/cli/index.ts
|
|
12501
12524
|
import { rmSync as rmSync2 } from "fs";
|
|
12502
|
-
import { readFileSync as
|
|
12525
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
12503
12526
|
var program2 = new Command;
|
|
12504
12527
|
function printJsonOrText(data, text, json = false) {
|
|
12505
12528
|
if (json || program2.opts().quiet) {
|
|
@@ -12831,7 +12854,7 @@ manifestCommand.command("add").description("Add or replace a machine in the flee
|
|
|
12831
12854
|
console.error("error: --from-stdin requires piped input");
|
|
12832
12855
|
process.exit(1);
|
|
12833
12856
|
}
|
|
12834
|
-
const input =
|
|
12857
|
+
const input = readFileSync12(0, "utf8");
|
|
12835
12858
|
const machine2 = JSON.parse(input);
|
|
12836
12859
|
console.log(JSON.stringify(manifestAdd(machine2), null, 2));
|
|
12837
12860
|
return;
|
|
@@ -13160,13 +13183,25 @@ program2.command("route").description("Resolve the best route for a machine").re
|
|
|
13160
13183
|
}
|
|
13161
13184
|
console.log(options.privateMetadata ? command2 ?? `${resolved.route}:${resolved.target}` : `${publicResolved.route}:${publicResolved.target ?? "unresolved"}`);
|
|
13162
13185
|
});
|
|
13163
|
-
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;
|
|
13164
13190
|
if (options.json) {
|
|
13165
|
-
|
|
13166
|
-
console.log(JSON.stringify({ resolved, command: resolved.ok ? buildSshCommand(options.machine, options.cmd) : null }, null, 2));
|
|
13191
|
+
console.log(JSON.stringify({ resolved: publicResolved, command: command2 }, null, 2));
|
|
13167
13192
|
return;
|
|
13168
13193
|
}
|
|
13169
|
-
|
|
13194
|
+
if (!resolved.ok) {
|
|
13195
|
+
console.error(source_default.red(resolved.warnings.join("; ") || `No route found for ${options.machine}`));
|
|
13196
|
+
process.exitCode = 1;
|
|
13197
|
+
return;
|
|
13198
|
+
}
|
|
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);
|
|
13170
13205
|
});
|
|
13171
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) => {
|
|
13172
13207
|
if (options.all) {
|
|
@@ -13314,8 +13349,8 @@ storageCommand.command("sync").description("Bidirectional storage sync: pull the
|
|
|
13314
13349
|
printStorageError(error);
|
|
13315
13350
|
}
|
|
13316
13351
|
});
|
|
13317
|
-
program2.command("status").description("Print local machine and storage status").option("-j, --json", "Print JSON output", false).action((options) => {
|
|
13318
|
-
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 });
|
|
13319
13354
|
printJsonOrText(status, renderFleetStatus(status), options.json);
|
|
13320
13355
|
});
|
|
13321
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, existsSync as existsSync6, 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";
|
|
@@ -14147,8 +14147,29 @@ function daemonProgramArguments(options) {
|
|
|
14147
14147
|
return [...base, "--interval-ms", String(options.intervalMs)];
|
|
14148
14148
|
}
|
|
14149
14149
|
function siblingBunRuntime(executable) {
|
|
14150
|
+
if (!isBunShebangScript(executable))
|
|
14151
|
+
return null;
|
|
14150
14152
|
const candidate = `${dirname4(executable)}/bun`;
|
|
14151
|
-
return
|
|
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
|
+
}
|
|
14152
14173
|
}
|
|
14153
14174
|
function launchdDomain(options) {
|
|
14154
14175
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
@@ -14430,7 +14451,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
|
|
|
14430
14451
|
};
|
|
14431
14452
|
}
|
|
14432
14453
|
// src/commands/notifications.ts
|
|
14433
|
-
import { existsSync as existsSync7, readFileSync as
|
|
14454
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
14434
14455
|
var notificationChannelSchema = exports_external.object({
|
|
14435
14456
|
id: exports_external.string(),
|
|
14436
14457
|
type: exports_external.enum(["email", "webhook", "command"]),
|
|
@@ -14589,7 +14610,7 @@ function readNotificationConfig(path = getNotificationsPath()) {
|
|
|
14589
14610
|
if (!existsSync7(path)) {
|
|
14590
14611
|
return getDefaultNotificationConfig();
|
|
14591
14612
|
}
|
|
14592
|
-
return notificationConfigSchema.parse(JSON.parse(
|
|
14613
|
+
return notificationConfigSchema.parse(JSON.parse(readFileSync5(path, "utf8")));
|
|
14593
14614
|
}
|
|
14594
14615
|
function writeNotificationConfig(config, path = getNotificationsPath()) {
|
|
14595
14616
|
ensureParentDir(path);
|
|
@@ -14830,7 +14851,8 @@ function parseJsonObject2(value) {
|
|
|
14830
14851
|
return null;
|
|
14831
14852
|
}
|
|
14832
14853
|
}
|
|
14833
|
-
function getStatus() {
|
|
14854
|
+
function getStatus(options = {}) {
|
|
14855
|
+
const privateMetadata = options.privateMetadata === true;
|
|
14834
14856
|
const manifest = readManifest();
|
|
14835
14857
|
const heartbeats = listHeartbeats();
|
|
14836
14858
|
const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
|
|
@@ -14839,17 +14861,17 @@ function getStatus() {
|
|
|
14839
14861
|
...heartbeats.map((heartbeat) => heartbeat.machine_id)
|
|
14840
14862
|
]);
|
|
14841
14863
|
return {
|
|
14842
|
-
machineId: getLocalMachineId(),
|
|
14843
|
-
manifestPath: getManifestPath(),
|
|
14844
|
-
dbPath: getDbPath(),
|
|
14845
|
-
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,
|
|
14846
14868
|
manifestMachineCount: manifest.machines.length,
|
|
14847
14869
|
heartbeatCount: heartbeats.length,
|
|
14848
14870
|
machines: [...machineIds].sort().map((machineId) => {
|
|
14849
14871
|
const declared = manifest.machines.find((machine) => machine.id === machineId);
|
|
14850
14872
|
const heartbeat = heartbeatByMachine.get(machineId);
|
|
14851
14873
|
return {
|
|
14852
|
-
machineId,
|
|
14874
|
+
machineId: privateMetadata ? machineId : REDACTED_VALUE,
|
|
14853
14875
|
platform: declared?.platform,
|
|
14854
14876
|
manifestDeclared: Boolean(declared),
|
|
14855
14877
|
heartbeatStatus: heartbeat?.status || "unknown",
|
|
@@ -14857,7 +14879,7 @@ function getStatus() {
|
|
|
14857
14879
|
daemonVersion: heartbeat?.daemon_version ?? null,
|
|
14858
14880
|
agentMode: heartbeat?.agent_mode ?? null,
|
|
14859
14881
|
storageSyncStatus: heartbeat?.storage_sync_status ?? null,
|
|
14860
|
-
doctorSummary: parseJsonObject2(heartbeat?.doctor_summary_json),
|
|
14882
|
+
doctorSummary: privateMetadata ? parseJsonObject2(heartbeat?.doctor_summary_json) : null,
|
|
14861
14883
|
privateMetadata: Boolean(heartbeat?.private_metadata)
|
|
14862
14884
|
};
|
|
14863
14885
|
}),
|
|
@@ -15099,7 +15121,7 @@ function startDashboardServer(options = {}) {
|
|
|
15099
15121
|
return Response.json({ ok: true, ...getServeInfo(options) });
|
|
15100
15122
|
}
|
|
15101
15123
|
if (url.pathname === "/api/status") {
|
|
15102
|
-
return Response.json(getStatus());
|
|
15124
|
+
return Response.json(appendWarnings(getStatus({ privateMetadata }), privateWarnings));
|
|
15103
15125
|
}
|
|
15104
15126
|
if (url.pathname === "/api/topology") {
|
|
15105
15127
|
const topology = discoverMachineTopology({ includeTailscale: url.searchParams.get("tailscale") !== "false" });
|
|
@@ -15237,15 +15259,16 @@ function check(id, status, summary, detail) {
|
|
|
15237
15259
|
function runSelfTest() {
|
|
15238
15260
|
const version = getPackageVersion();
|
|
15239
15261
|
const status = getStatus();
|
|
15262
|
+
const machineId = getLocalMachineId();
|
|
15240
15263
|
const doctor = runDoctor();
|
|
15241
15264
|
const serveInfo = getServeInfo();
|
|
15242
15265
|
const html = renderDashboardHtml();
|
|
15243
15266
|
const notifications = listNotificationChannels();
|
|
15244
|
-
const apps = listApps(
|
|
15245
|
-
const appsDiff = diffApps(
|
|
15246
|
-
const cliPlan = buildClaudeInstallPlan(
|
|
15267
|
+
const apps = listApps(machineId);
|
|
15268
|
+
const appsDiff = diffApps(machineId);
|
|
15269
|
+
const cliPlan = buildClaudeInstallPlan(machineId);
|
|
15247
15270
|
return {
|
|
15248
|
-
machineId
|
|
15271
|
+
machineId,
|
|
15249
15272
|
checks: [
|
|
15250
15273
|
check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
|
|
15251
15274
|
check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
|
|
@@ -15526,7 +15549,7 @@ function buildScreenEnableCommand(machineId, options = {}) {
|
|
|
15526
15549
|
};
|
|
15527
15550
|
}
|
|
15528
15551
|
// src/commands/sync.ts
|
|
15529
|
-
import { existsSync as existsSync8, lstatSync, readFileSync as
|
|
15552
|
+
import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync6, symlinkSync, copyFileSync } from "fs";
|
|
15530
15553
|
import { homedir as homedir5 } from "os";
|
|
15531
15554
|
function quote4(value) {
|
|
15532
15555
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -15586,8 +15609,8 @@ function detectFileActions(machine) {
|
|
|
15586
15609
|
if (file.mode === "symlink") {
|
|
15587
15610
|
status = lstatSync(file.target).isSymbolicLink() ? "ok" : "drifted";
|
|
15588
15611
|
} else {
|
|
15589
|
-
const source =
|
|
15590
|
-
const target =
|
|
15612
|
+
const source = readFileSync6(file.source, "utf8");
|
|
15613
|
+
const target = readFileSync6(file.target, "utf8");
|
|
15591
15614
|
status = source === target ? "ok" : "drifted";
|
|
15592
15615
|
}
|
|
15593
15616
|
}
|
|
@@ -24815,14 +24838,17 @@ function privateOutputWarnings2(requested, allowed) {
|
|
|
24815
24838
|
function appendWarnings2(payload, warnings) {
|
|
24816
24839
|
if (warnings.length === 0)
|
|
24817
24840
|
return payload;
|
|
24818
|
-
|
|
24841
|
+
const currentWarnings = typeof payload === "object" && payload && "warnings" in payload && Array.isArray(payload.warnings) ? payload.warnings : [];
|
|
24842
|
+
return { ...payload, warnings: [...currentWarnings, ...warnings] };
|
|
24819
24843
|
}
|
|
24820
24844
|
function createMcpServer(version2) {
|
|
24821
24845
|
const server = new McpServer({ name: "machines", version: version2 });
|
|
24822
24846
|
const events = new EventsClient3;
|
|
24823
|
-
server.tool("machines_status", "Return local machine fleet status paths and machine identity.", {}, async () =>
|
|
24824
|
-
|
|
24825
|
-
|
|
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
|
+
});
|
|
24826
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) }] }));
|
|
24827
24853
|
server.tool("machines_self_test", "Run local package smoke checks.", {}, async () => ({
|
|
24828
24854
|
content: [{ type: "text", text: JSON.stringify(runSelfTest(), null, 2) }]
|
|
@@ -25003,9 +25029,23 @@ function createMcpServer(version2) {
|
|
|
25003
25029
|
}), null, 2)
|
|
25004
25030
|
}]
|
|
25005
25031
|
}));
|
|
25006
|
-
server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
|
|
25007
|
-
|
|
25008
|
-
|
|
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
|
+
});
|
|
25009
25049
|
server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
|
|
25010
25050
|
content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
|
|
25011
25051
|
}));
|
package/dist/mcp/index.js
CHANGED
|
@@ -5954,7 +5954,7 @@ function diffMachines(leftMachineId, rightMachineId) {
|
|
|
5954
5954
|
}
|
|
5955
5955
|
|
|
5956
5956
|
// src/commands/daemon.ts
|
|
5957
|
-
import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
5957
|
+
import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync4, statSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
5958
5958
|
import { dirname as dirname4 } from "path";
|
|
5959
5959
|
import { platform as osPlatform } from "os";
|
|
5960
5960
|
var DEFAULT_SERVICE_NAME = "machines-agent";
|
|
@@ -6224,8 +6224,29 @@ function daemonProgramArguments(options) {
|
|
|
6224
6224
|
return [...base, "--interval-ms", String(options.intervalMs)];
|
|
6225
6225
|
}
|
|
6226
6226
|
function siblingBunRuntime(executable) {
|
|
6227
|
+
if (!isBunShebangScript(executable))
|
|
6228
|
+
return null;
|
|
6227
6229
|
const candidate = `${dirname4(executable)}/bun`;
|
|
6228
|
-
return
|
|
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
|
+
}
|
|
6229
6250
|
}
|
|
6230
6251
|
function launchdDomain(options) {
|
|
6231
6252
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
@@ -6621,7 +6642,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
|
|
|
6621
6642
|
}
|
|
6622
6643
|
|
|
6623
6644
|
// src/commands/notifications.ts
|
|
6624
|
-
import { existsSync as existsSync7, readFileSync as
|
|
6645
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
6625
6646
|
var notificationChannelSchema = exports_external.object({
|
|
6626
6647
|
id: exports_external.string(),
|
|
6627
6648
|
type: exports_external.enum(["email", "webhook", "command"]),
|
|
@@ -6780,7 +6801,7 @@ function readNotificationConfig(path = getNotificationsPath()) {
|
|
|
6780
6801
|
if (!existsSync7(path)) {
|
|
6781
6802
|
return getDefaultNotificationConfig();
|
|
6782
6803
|
}
|
|
6783
|
-
return notificationConfigSchema.parse(JSON.parse(
|
|
6804
|
+
return notificationConfigSchema.parse(JSON.parse(readFileSync5(path, "utf8")));
|
|
6784
6805
|
}
|
|
6785
6806
|
function writeNotificationConfig(config, path = getNotificationsPath()) {
|
|
6786
6807
|
ensureParentDir(path);
|
|
@@ -7408,7 +7429,8 @@ function parseJsonObject2(value) {
|
|
|
7408
7429
|
return null;
|
|
7409
7430
|
}
|
|
7410
7431
|
}
|
|
7411
|
-
function getStatus() {
|
|
7432
|
+
function getStatus(options = {}) {
|
|
7433
|
+
const privateMetadata = options.privateMetadata === true;
|
|
7412
7434
|
const manifest = readManifest();
|
|
7413
7435
|
const heartbeats = listHeartbeats();
|
|
7414
7436
|
const heartbeatByMachine = latestHeartbeatByMachine(heartbeats);
|
|
@@ -7417,17 +7439,17 @@ function getStatus() {
|
|
|
7417
7439
|
...heartbeats.map((heartbeat) => heartbeat.machine_id)
|
|
7418
7440
|
]);
|
|
7419
7441
|
return {
|
|
7420
|
-
machineId: getLocalMachineId(),
|
|
7421
|
-
manifestPath: getManifestPath(),
|
|
7422
|
-
dbPath: getDbPath(),
|
|
7423
|
-
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,
|
|
7424
7446
|
manifestMachineCount: manifest.machines.length,
|
|
7425
7447
|
heartbeatCount: heartbeats.length,
|
|
7426
7448
|
machines: [...machineIds].sort().map((machineId) => {
|
|
7427
7449
|
const declared = manifest.machines.find((machine) => machine.id === machineId);
|
|
7428
7450
|
const heartbeat = heartbeatByMachine.get(machineId);
|
|
7429
7451
|
return {
|
|
7430
|
-
machineId,
|
|
7452
|
+
machineId: privateMetadata ? machineId : REDACTED_VALUE,
|
|
7431
7453
|
platform: declared?.platform,
|
|
7432
7454
|
manifestDeclared: Boolean(declared),
|
|
7433
7455
|
heartbeatStatus: heartbeat?.status || "unknown",
|
|
@@ -7435,7 +7457,7 @@ function getStatus() {
|
|
|
7435
7457
|
daemonVersion: heartbeat?.daemon_version ?? null,
|
|
7436
7458
|
agentMode: heartbeat?.agent_mode ?? null,
|
|
7437
7459
|
storageSyncStatus: heartbeat?.storage_sync_status ?? null,
|
|
7438
|
-
doctorSummary: parseJsonObject2(heartbeat?.doctor_summary_json),
|
|
7460
|
+
doctorSummary: privateMetadata ? parseJsonObject2(heartbeat?.doctor_summary_json) : null,
|
|
7439
7461
|
privateMetadata: Boolean(heartbeat?.private_metadata)
|
|
7440
7462
|
};
|
|
7441
7463
|
}),
|
|
@@ -7451,15 +7473,16 @@ function check(id, status, summary, detail) {
|
|
|
7451
7473
|
function runSelfTest() {
|
|
7452
7474
|
const version = getPackageVersion();
|
|
7453
7475
|
const status = getStatus();
|
|
7476
|
+
const machineId = getLocalMachineId();
|
|
7454
7477
|
const doctor = runDoctor();
|
|
7455
7478
|
const serveInfo = getServeInfo();
|
|
7456
7479
|
const html = renderDashboardHtml();
|
|
7457
7480
|
const notifications = listNotificationChannels();
|
|
7458
|
-
const apps = listApps(
|
|
7459
|
-
const appsDiff = diffApps(
|
|
7460
|
-
const cliPlan = buildClaudeInstallPlan(
|
|
7481
|
+
const apps = listApps(machineId);
|
|
7482
|
+
const appsDiff = diffApps(machineId);
|
|
7483
|
+
const cliPlan = buildClaudeInstallPlan(machineId);
|
|
7461
7484
|
return {
|
|
7462
|
-
machineId
|
|
7485
|
+
machineId,
|
|
7463
7486
|
checks: [
|
|
7464
7487
|
check("package-version", version === "0.0.0" ? "fail" : "ok", "Package version resolves", version),
|
|
7465
7488
|
check("status", "ok", "Status loads", JSON.stringify({ machines: status.manifestMachineCount, heartbeats: status.heartbeatCount })),
|
|
@@ -7818,7 +7841,7 @@ function runSetup(machineId, options = {}, runner = runMachineCommand) {
|
|
|
7818
7841
|
}
|
|
7819
7842
|
|
|
7820
7843
|
// src/commands/sync.ts
|
|
7821
|
-
import { existsSync as existsSync8, lstatSync, readFileSync as
|
|
7844
|
+
import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync6, symlinkSync, copyFileSync } from "fs";
|
|
7822
7845
|
import { homedir as homedir5 } from "os";
|
|
7823
7846
|
function quote4(value) {
|
|
7824
7847
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -7878,8 +7901,8 @@ function detectFileActions(machine) {
|
|
|
7878
7901
|
if (file.mode === "symlink") {
|
|
7879
7902
|
status = lstatSync(file.target).isSymbolicLink() ? "ok" : "drifted";
|
|
7880
7903
|
} else {
|
|
7881
|
-
const source =
|
|
7882
|
-
const target =
|
|
7904
|
+
const source = readFileSync6(file.source, "utf8");
|
|
7905
|
+
const target = readFileSync6(file.target, "utf8");
|
|
7883
7906
|
status = source === target ? "ok" : "drifted";
|
|
7884
7907
|
}
|
|
7885
7908
|
}
|
|
@@ -8229,14 +8252,17 @@ function privateOutputWarnings(requested, allowed) {
|
|
|
8229
8252
|
function appendWarnings(payload, warnings) {
|
|
8230
8253
|
if (warnings.length === 0)
|
|
8231
8254
|
return payload;
|
|
8232
|
-
|
|
8255
|
+
const currentWarnings = typeof payload === "object" && payload && "warnings" in payload && Array.isArray(payload.warnings) ? payload.warnings : [];
|
|
8256
|
+
return { ...payload, warnings: [...currentWarnings, ...warnings] };
|
|
8233
8257
|
}
|
|
8234
8258
|
function createMcpServer(version) {
|
|
8235
8259
|
const server = new McpServer({ name: "machines", version });
|
|
8236
8260
|
const events = new EventsClient2;
|
|
8237
|
-
server.tool("machines_status", "Return local machine fleet status paths and machine identity.", {}, async () =>
|
|
8238
|
-
|
|
8239
|
-
|
|
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
|
+
});
|
|
8240
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) }] }));
|
|
8241
8267
|
server.tool("machines_self_test", "Run local package smoke checks.", {}, async () => ({
|
|
8242
8268
|
content: [{ type: "text", text: JSON.stringify(runSelfTest(), null, 2) }]
|
|
@@ -8417,9 +8443,23 @@ function createMcpServer(version) {
|
|
|
8417
8443
|
}), null, 2)
|
|
8418
8444
|
}]
|
|
8419
8445
|
}));
|
|
8420
|
-
server.tool("machines_ssh_resolve", "Resolve the best SSH route for a machine.", {
|
|
8421
|
-
|
|
8422
|
-
|
|
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
|
+
});
|
|
8423
8463
|
server.tool("machines_ports", "List listening ports on a machine.", { machine_id: exports_external.string().optional().describe("Machine identifier") }, async ({ machine_id }) => ({
|
|
8424
8464
|
content: [{ type: "text", text: JSON.stringify(listPorts(machine_id), null, 2) }]
|
|
8425
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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"}
|