@hasna/machines 0.0.42 → 0.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +28 -18
- package/dist/index.js +20 -10
- package/dist/mcp/index.js +21 -10
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -10588,7 +10588,7 @@ function runDoctor(machineId, options = {}) {
|
|
|
10588
10588
|
|
|
10589
10589
|
// src/commands/daemon.ts
|
|
10590
10590
|
import { execFileSync } from "child_process";
|
|
10591
|
-
import { chmodSync, mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
10591
|
+
import { chmodSync, existsSync as existsSync8, mkdirSync as mkdirSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
10592
10592
|
import { dirname as dirname4 } from "path";
|
|
10593
10593
|
import { platform as osPlatform } from "os";
|
|
10594
10594
|
var DEFAULT_SERVICE_NAME = "machines-agent";
|
|
@@ -10929,6 +10929,8 @@ function escapeSystemdEnvironmentValue(value) {
|
|
|
10929
10929
|
function launchdPlist(options) {
|
|
10930
10930
|
const env2 = Object.entries(options.env).map(([name, value]) => ` <key>${xmlEscape(name)}</key>
|
|
10931
10931
|
<string>${xmlEscape(value)}</string>`).join(`
|
|
10932
|
+
`);
|
|
10933
|
+
const programArguments = daemonProgramArguments(options).map((value) => ` <string>${xmlEscape(value)}</string>`).join(`
|
|
10932
10934
|
`);
|
|
10933
10935
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
10934
10936
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -10938,9 +10940,7 @@ function launchdPlist(options) {
|
|
|
10938
10940
|
<string>${xmlEscape(options.serviceId)}</string>
|
|
10939
10941
|
<key>ProgramArguments</key>
|
|
10940
10942
|
<array>
|
|
10941
|
-
|
|
10942
|
-
<string>--interval-ms</string>
|
|
10943
|
-
<string>${options.intervalMs}</string>
|
|
10943
|
+
${programArguments}
|
|
10944
10944
|
</array>
|
|
10945
10945
|
<key>EnvironmentVariables</key>
|
|
10946
10946
|
<dict>
|
|
@@ -10961,6 +10961,7 @@ ${env2}
|
|
|
10961
10961
|
function systemdUnit(options) {
|
|
10962
10962
|
const env2 = Object.entries(options.env).map(([name, value]) => `Environment=${quoteSystemdEnvironment(name, value)}`).join(`
|
|
10963
10963
|
`);
|
|
10964
|
+
const execStart = daemonProgramArguments(options).map(quoteSystemdExecArg).join(" ");
|
|
10964
10965
|
return `[Unit]
|
|
10965
10966
|
Description=Hasna machines agent
|
|
10966
10967
|
After=network-online.target
|
|
@@ -10968,7 +10969,7 @@ Wants=network-online.target
|
|
|
10968
10969
|
|
|
10969
10970
|
[Service]
|
|
10970
10971
|
Type=simple
|
|
10971
|
-
ExecStart=${
|
|
10972
|
+
ExecStart=${execStart}
|
|
10972
10973
|
Restart=always
|
|
10973
10974
|
RestartSec=10
|
|
10974
10975
|
${env2}
|
|
@@ -10977,6 +10978,15 @@ ${env2}
|
|
|
10977
10978
|
WantedBy=${options.mode === "system" ? "multi-user.target" : "default.target"}
|
|
10978
10979
|
`;
|
|
10979
10980
|
}
|
|
10981
|
+
function daemonProgramArguments(options) {
|
|
10982
|
+
const bunRuntime = siblingBunRuntime(options.executable);
|
|
10983
|
+
const base = bunRuntime ? [bunRuntime, options.executable] : [options.executable];
|
|
10984
|
+
return [...base, "--interval-ms", String(options.intervalMs)];
|
|
10985
|
+
}
|
|
10986
|
+
function siblingBunRuntime(executable) {
|
|
10987
|
+
const candidate = `${dirname4(executable)}/bun`;
|
|
10988
|
+
return existsSync8(candidate) ? candidate : null;
|
|
10989
|
+
}
|
|
10980
10990
|
function launchdDomain(options) {
|
|
10981
10991
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
10982
10992
|
}
|
|
@@ -11497,7 +11507,7 @@ function runSelfTest() {
|
|
|
11497
11507
|
// src/commands/clipboard.ts
|
|
11498
11508
|
init_paths();
|
|
11499
11509
|
import { createHash } from "crypto";
|
|
11500
|
-
import { existsSync as
|
|
11510
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync5 } from "fs";
|
|
11501
11511
|
import { join as join6 } from "path";
|
|
11502
11512
|
var DEFAULT_CONFIG = {
|
|
11503
11513
|
version: 1,
|
|
@@ -11528,7 +11538,7 @@ function getDefaultConfig() {
|
|
|
11528
11538
|
}
|
|
11529
11539
|
function readConfig(configPath) {
|
|
11530
11540
|
const path = resolveConfigPath(configPath);
|
|
11531
|
-
if (!
|
|
11541
|
+
if (!existsSync9(path)) {
|
|
11532
11542
|
return getDefaultConfig();
|
|
11533
11543
|
}
|
|
11534
11544
|
const parsed = JSON.parse(readFileSync6(path, "utf8"));
|
|
@@ -11542,7 +11552,7 @@ function writeConfig(config, configPath) {
|
|
|
11542
11552
|
}
|
|
11543
11553
|
function readHistory(historyPath) {
|
|
11544
11554
|
const path = resolveHistoryPath(historyPath);
|
|
11545
|
-
if (!
|
|
11555
|
+
if (!existsSync9(path)) {
|
|
11546
11556
|
return [];
|
|
11547
11557
|
}
|
|
11548
11558
|
try {
|
|
@@ -11575,7 +11585,7 @@ function sanitizeClipboardForRead(content, maxSizeBytes, skipPatterns) {
|
|
|
11575
11585
|
}
|
|
11576
11586
|
function getOrCreateClipboardKey() {
|
|
11577
11587
|
const keyPath = getClipboardKeyPath();
|
|
11578
|
-
if (
|
|
11588
|
+
if (existsSync9(keyPath)) {
|
|
11579
11589
|
return readFileSync6(keyPath, "utf8").trim();
|
|
11580
11590
|
}
|
|
11581
11591
|
const key = createHash("sha256").update(crypto.randomUUID()).digest("hex").slice(0, 32);
|
|
@@ -11615,7 +11625,7 @@ function addClipboardEntry(entry, historyPath) {
|
|
|
11615
11625
|
}
|
|
11616
11626
|
function clearClipboardHistory(historyPath) {
|
|
11617
11627
|
const path = resolveHistoryPath(historyPath);
|
|
11618
|
-
if (
|
|
11628
|
+
if (existsSync9(path)) {
|
|
11619
11629
|
rmSync(path);
|
|
11620
11630
|
}
|
|
11621
11631
|
}
|
|
@@ -11964,7 +11974,7 @@ async function discoverPeers() {
|
|
|
11964
11974
|
|
|
11965
11975
|
// src/commands/heal.ts
|
|
11966
11976
|
init_paths();
|
|
11967
|
-
import { existsSync as
|
|
11977
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
11968
11978
|
import { join as join8 } from "path";
|
|
11969
11979
|
var DEFAULT_THRESHOLDS = {
|
|
11970
11980
|
reconnect: 3,
|
|
@@ -12016,7 +12026,7 @@ function getHealStatePath() {
|
|
|
12016
12026
|
}
|
|
12017
12027
|
function readHealConfig(path) {
|
|
12018
12028
|
const p = path || getHealConfigPath();
|
|
12019
|
-
if (!
|
|
12029
|
+
if (!existsSync10(p))
|
|
12020
12030
|
return { ...DEFAULT_HEAL_CONFIG, thresholds: { ...DEFAULT_THRESHOLDS } };
|
|
12021
12031
|
const parsed = JSON.parse(readFileSync9(p, "utf8"));
|
|
12022
12032
|
return {
|
|
@@ -12034,7 +12044,7 @@ function writeHealConfig(config, path) {
|
|
|
12034
12044
|
}
|
|
12035
12045
|
function readHealState(path) {
|
|
12036
12046
|
const p = path || getHealStatePath();
|
|
12037
|
-
if (!
|
|
12047
|
+
if (!existsSync10(p))
|
|
12038
12048
|
return defaultHealState();
|
|
12039
12049
|
try {
|
|
12040
12050
|
return { ...defaultHealState(), ...JSON.parse(readFileSync9(p, "utf8")) };
|
|
@@ -12250,7 +12260,7 @@ function executeAction(action, config) {
|
|
|
12250
12260
|
|
|
12251
12261
|
// src/commands/heal-daemon.ts
|
|
12252
12262
|
init_paths();
|
|
12253
|
-
import { existsSync as
|
|
12263
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
12254
12264
|
import { join as join9 } from "path";
|
|
12255
12265
|
var DAEMON_PID_PATH2 = join9(getDataDir(), "heal-daemon.pid");
|
|
12256
12266
|
var SERVICE_PATH = "/etc/systemd/system/machines-heal.service";
|
|
@@ -12370,7 +12380,7 @@ function applyDeterminism(config) {
|
|
|
12370
12380
|
}
|
|
12371
12381
|
function enableHardwareWatchdog() {
|
|
12372
12382
|
const log2 = [];
|
|
12373
|
-
if (!
|
|
12383
|
+
if (!existsSync11(SYSTEM_CONF))
|
|
12374
12384
|
return ["/etc/systemd/system.conf not found; skipping hardware watchdog"];
|
|
12375
12385
|
let conf = readFileSync10(SYSTEM_CONF, "utf8");
|
|
12376
12386
|
const set = (key, value) => {
|
|
@@ -12402,7 +12412,7 @@ function binPath() {
|
|
|
12402
12412
|
candidates.push(`${home}/.bun/bin/machines`);
|
|
12403
12413
|
candidates.push("/root/.bun/bin/machines", "/usr/local/bin/machines");
|
|
12404
12414
|
for (const c of candidates) {
|
|
12405
|
-
if (c &&
|
|
12415
|
+
if (c && existsSync11(c))
|
|
12406
12416
|
return c;
|
|
12407
12417
|
}
|
|
12408
12418
|
return "machines";
|
|
@@ -12438,7 +12448,7 @@ WantedBy=multi-user.target
|
|
|
12438
12448
|
function uninstallHealService() {
|
|
12439
12449
|
const log2 = [];
|
|
12440
12450
|
sh2("systemctl disable --now machines-heal.service 2>/dev/null || true");
|
|
12441
|
-
if (
|
|
12451
|
+
if (existsSync11(SERVICE_PATH)) {
|
|
12442
12452
|
sh2(`rm -f ${SERVICE_PATH}`);
|
|
12443
12453
|
sh2("systemctl daemon-reload");
|
|
12444
12454
|
log2.push(`removed ${SERVICE_PATH}`);
|
|
@@ -12449,7 +12459,7 @@ function uninstallHealService() {
|
|
|
12449
12459
|
}
|
|
12450
12460
|
function healServiceStatus() {
|
|
12451
12461
|
return {
|
|
12452
|
-
installed:
|
|
12462
|
+
installed: existsSync11(SERVICE_PATH),
|
|
12453
12463
|
active: sh2("systemctl is-active machines-heal.service").out === "active",
|
|
12454
12464
|
enabled: sh2("systemctl is-enabled machines-heal.service 2>/dev/null").out === "enabled"
|
|
12455
12465
|
};
|
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, 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,15 @@ ${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
|
+
const candidate = `${dirname4(executable)}/bun`;
|
|
14151
|
+
return existsSync6(candidate) ? candidate : null;
|
|
14152
|
+
}
|
|
14143
14153
|
function launchdDomain(options) {
|
|
14144
14154
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
14145
14155
|
}
|
|
@@ -14420,7 +14430,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
|
|
|
14420
14430
|
};
|
|
14421
14431
|
}
|
|
14422
14432
|
// src/commands/notifications.ts
|
|
14423
|
-
import { existsSync as
|
|
14433
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
14424
14434
|
var notificationChannelSchema = exports_external.object({
|
|
14425
14435
|
id: exports_external.string(),
|
|
14426
14436
|
type: exports_external.enum(["email", "webhook", "command"]),
|
|
@@ -14576,7 +14586,7 @@ function getDefaultNotificationConfig() {
|
|
|
14576
14586
|
};
|
|
14577
14587
|
}
|
|
14578
14588
|
function readNotificationConfig(path = getNotificationsPath()) {
|
|
14579
|
-
if (!
|
|
14589
|
+
if (!existsSync7(path)) {
|
|
14580
14590
|
return getDefaultNotificationConfig();
|
|
14581
14591
|
}
|
|
14582
14592
|
return notificationConfigSchema.parse(JSON.parse(readFileSync4(path, "utf8")));
|
|
@@ -15516,7 +15526,7 @@ function buildScreenEnableCommand(machineId, options = {}) {
|
|
|
15516
15526
|
};
|
|
15517
15527
|
}
|
|
15518
15528
|
// src/commands/sync.ts
|
|
15519
|
-
import { existsSync as
|
|
15529
|
+
import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync5, symlinkSync, copyFileSync } from "fs";
|
|
15520
15530
|
import { homedir as homedir5 } from "os";
|
|
15521
15531
|
function quote4(value) {
|
|
15522
15532
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -15569,8 +15579,8 @@ function detectFileActions(machine) {
|
|
|
15569
15579
|
throw new Error(`Remote file sync planning is not supported for ${machine.id}; refusing to inspect or apply local paths as remote state.`);
|
|
15570
15580
|
}
|
|
15571
15581
|
return (machine.files || []).map((file, index) => {
|
|
15572
|
-
const sourceExists =
|
|
15573
|
-
const targetExists =
|
|
15582
|
+
const sourceExists = existsSync8(file.source);
|
|
15583
|
+
const targetExists = existsSync8(file.target);
|
|
15574
15584
|
let status = "missing";
|
|
15575
15585
|
if (sourceExists && targetExists) {
|
|
15576
15586
|
if (file.mode === "symlink") {
|
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, 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,15 @@ ${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
|
+
const candidate = `${dirname4(executable)}/bun`;
|
|
6228
|
+
return existsSync6(candidate) ? candidate : null;
|
|
6229
|
+
}
|
|
6219
6230
|
function launchdDomain(options) {
|
|
6220
6231
|
return options.mode === "system" ? "system" : "gui/$UID";
|
|
6221
6232
|
}
|
|
@@ -6610,7 +6621,7 @@ function runTailscaleInstall(machineId, options = {}, runner = runMachineCommand
|
|
|
6610
6621
|
}
|
|
6611
6622
|
|
|
6612
6623
|
// src/commands/notifications.ts
|
|
6613
|
-
import { existsSync as
|
|
6624
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
6614
6625
|
var notificationChannelSchema = exports_external.object({
|
|
6615
6626
|
id: exports_external.string(),
|
|
6616
6627
|
type: exports_external.enum(["email", "webhook", "command"]),
|
|
@@ -6766,7 +6777,7 @@ function getDefaultNotificationConfig() {
|
|
|
6766
6777
|
};
|
|
6767
6778
|
}
|
|
6768
6779
|
function readNotificationConfig(path = getNotificationsPath()) {
|
|
6769
|
-
if (!
|
|
6780
|
+
if (!existsSync7(path)) {
|
|
6770
6781
|
return getDefaultNotificationConfig();
|
|
6771
6782
|
}
|
|
6772
6783
|
return notificationConfigSchema.parse(JSON.parse(readFileSync4(path, "utf8")));
|
|
@@ -6778,7 +6789,7 @@ function writeNotificationConfig(config, path = getNotificationsPath()) {
|
|
|
6778
6789
|
updatedAt: new Date().toISOString(),
|
|
6779
6790
|
channels: sortChannels(config.channels)
|
|
6780
6791
|
};
|
|
6781
|
-
|
|
6792
|
+
writeFileSync4(path, `${JSON.stringify(nextConfig, null, 2)}
|
|
6782
6793
|
`, "utf8");
|
|
6783
6794
|
return nextConfig;
|
|
6784
6795
|
}
|
|
@@ -7807,7 +7818,7 @@ function runSetup(machineId, options = {}, runner = runMachineCommand) {
|
|
|
7807
7818
|
}
|
|
7808
7819
|
|
|
7809
7820
|
// src/commands/sync.ts
|
|
7810
|
-
import { existsSync as
|
|
7821
|
+
import { existsSync as existsSync8, lstatSync, readFileSync as readFileSync5, symlinkSync, copyFileSync } from "fs";
|
|
7811
7822
|
import { homedir as homedir5 } from "os";
|
|
7812
7823
|
function quote4(value) {
|
|
7813
7824
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -7860,8 +7871,8 @@ function detectFileActions(machine) {
|
|
|
7860
7871
|
throw new Error(`Remote file sync planning is not supported for ${machine.id}; refusing to inspect or apply local paths as remote state.`);
|
|
7861
7872
|
}
|
|
7862
7873
|
return (machine.files || []).map((file, index) => {
|
|
7863
|
-
const sourceExists =
|
|
7864
|
-
const targetExists =
|
|
7874
|
+
const sourceExists = existsSync8(file.source);
|
|
7875
|
+
const targetExists = existsSync8(file.target);
|
|
7865
7876
|
let status = "missing";
|
|
7866
7877
|
if (sourceExists && targetExists) {
|
|
7867
7878
|
if (file.mode === "symlink") {
|