itwillsync 1.3.1 → 1.3.3
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/hub/daemon.js +17 -2
- package/dist/hub/daemon.js.map +1 -1
- package/dist/index.js +103 -16
- package/dist/index.js.map +1 -1
- package/dist/web-client/assets/{index-CpcOfuy-.js → index-lCqw1s_s.js} +17 -17
- package/dist/web-client/assets/index-xsTGRLqf.css +1 -0
- package/dist/web-client/index.html +2 -2
- package/package.json +1 -1
- package/dist/web-client/assets/index-viCDtpt6.css +0 -1
package/dist/index.js
CHANGED
|
@@ -4172,7 +4172,7 @@ async function runSetupWizard() {
|
|
|
4172
4172
|
|
|
4173
4173
|
// src/hub-client.ts
|
|
4174
4174
|
import { spawn as spawn2 } from "child_process";
|
|
4175
|
-
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
4175
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2, unlinkSync } from "fs";
|
|
4176
4176
|
import { homedir as homedir2 } from "os";
|
|
4177
4177
|
import { join as join4, dirname as dirname2 } from "path";
|
|
4178
4178
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -4219,13 +4219,70 @@ async function discoverHub() {
|
|
|
4219
4219
|
req.end();
|
|
4220
4220
|
});
|
|
4221
4221
|
}
|
|
4222
|
+
async function getHubPidFromHealth() {
|
|
4223
|
+
return new Promise((resolve) => {
|
|
4224
|
+
const req = request(
|
|
4225
|
+
{
|
|
4226
|
+
hostname: "127.0.0.1",
|
|
4227
|
+
port: HUB_INTERNAL_PORT,
|
|
4228
|
+
path: "/api/health",
|
|
4229
|
+
method: "GET",
|
|
4230
|
+
timeout: 2e3
|
|
4231
|
+
},
|
|
4232
|
+
(res) => {
|
|
4233
|
+
let data = "";
|
|
4234
|
+
res.on("data", (chunk) => {
|
|
4235
|
+
data += chunk;
|
|
4236
|
+
});
|
|
4237
|
+
res.on("end", () => {
|
|
4238
|
+
try {
|
|
4239
|
+
const json = JSON.parse(data);
|
|
4240
|
+
resolve(json.pid && typeof json.pid === "number" ? json.pid : null);
|
|
4241
|
+
} catch {
|
|
4242
|
+
resolve(null);
|
|
4243
|
+
}
|
|
4244
|
+
});
|
|
4245
|
+
}
|
|
4246
|
+
);
|
|
4247
|
+
req.on("error", () => resolve(null));
|
|
4248
|
+
req.on("timeout", () => {
|
|
4249
|
+
req.destroy();
|
|
4250
|
+
resolve(null);
|
|
4251
|
+
});
|
|
4252
|
+
req.end();
|
|
4253
|
+
});
|
|
4254
|
+
}
|
|
4255
|
+
async function killStaleHub() {
|
|
4256
|
+
const pid = await getHubPidFromHealth();
|
|
4257
|
+
if (!pid) return false;
|
|
4258
|
+
try {
|
|
4259
|
+
process.kill(pid, "SIGTERM");
|
|
4260
|
+
} catch {
|
|
4261
|
+
return false;
|
|
4262
|
+
}
|
|
4263
|
+
for (let i = 0; i < 20; i++) {
|
|
4264
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
4265
|
+
const stillRunning = await discoverHub();
|
|
4266
|
+
if (!stillRunning) break;
|
|
4267
|
+
}
|
|
4268
|
+
const hubDir = getHubDir();
|
|
4269
|
+
try {
|
|
4270
|
+
unlinkSync(join4(hubDir, "hub.json"));
|
|
4271
|
+
} catch {
|
|
4272
|
+
}
|
|
4273
|
+
try {
|
|
4274
|
+
unlinkSync(join4(hubDir, "hub.pid"));
|
|
4275
|
+
} catch {
|
|
4276
|
+
}
|
|
4277
|
+
return true;
|
|
4278
|
+
}
|
|
4222
4279
|
async function spawnHub() {
|
|
4223
4280
|
const __dirname = dirname2(fileURLToPath2(import.meta.url));
|
|
4224
4281
|
const hubPath = join4(__dirname, "hub", "daemon.js");
|
|
4225
4282
|
return new Promise((resolve, reject) => {
|
|
4226
4283
|
const child = spawn2("node", [hubPath], {
|
|
4227
4284
|
detached: true,
|
|
4228
|
-
stdio: ["ignore", "pipe", "
|
|
4285
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4229
4286
|
env: {
|
|
4230
4287
|
...process.env,
|
|
4231
4288
|
// Pass config dir to hub
|
|
@@ -4234,6 +4291,7 @@ async function spawnHub() {
|
|
|
4234
4291
|
});
|
|
4235
4292
|
child.unref();
|
|
4236
4293
|
let output = "";
|
|
4294
|
+
let stderrOutput = "";
|
|
4237
4295
|
const timeout = setTimeout(() => {
|
|
4238
4296
|
reject(new Error("Hub daemon startup timed out"));
|
|
4239
4297
|
}, 1e4);
|
|
@@ -4242,9 +4300,13 @@ async function spawnHub() {
|
|
|
4242
4300
|
if (output.includes("hub:ready:")) {
|
|
4243
4301
|
clearTimeout(timeout);
|
|
4244
4302
|
child.stdout?.destroy();
|
|
4303
|
+
child.stderr?.destroy();
|
|
4245
4304
|
resolve();
|
|
4246
4305
|
}
|
|
4247
4306
|
});
|
|
4307
|
+
child.stderr?.on("data", (data) => {
|
|
4308
|
+
stderrOutput += data.toString();
|
|
4309
|
+
});
|
|
4248
4310
|
child.on("error", (err) => {
|
|
4249
4311
|
clearTimeout(timeout);
|
|
4250
4312
|
reject(new Error(`Failed to spawn hub daemon: ${err.message}`));
|
|
@@ -4252,7 +4314,11 @@ async function spawnHub() {
|
|
|
4252
4314
|
child.on("exit", (code) => {
|
|
4253
4315
|
clearTimeout(timeout);
|
|
4254
4316
|
if (code !== null && code !== 0) {
|
|
4255
|
-
|
|
4317
|
+
const detail = stderrOutput.trim();
|
|
4318
|
+
reject(new Error(
|
|
4319
|
+
`Hub daemon exited with code ${code}${detail ? `:
|
|
4320
|
+
${detail}` : ""}`
|
|
4321
|
+
));
|
|
4256
4322
|
}
|
|
4257
4323
|
});
|
|
4258
4324
|
});
|
|
@@ -4364,11 +4430,19 @@ async function listSessions() {
|
|
|
4364
4430
|
req.end();
|
|
4365
4431
|
});
|
|
4366
4432
|
}
|
|
4367
|
-
function stopHub() {
|
|
4433
|
+
async function stopHub() {
|
|
4368
4434
|
const config = getHubConfig();
|
|
4369
|
-
if (
|
|
4435
|
+
if (config) {
|
|
4436
|
+
try {
|
|
4437
|
+
process.kill(config.pid, "SIGTERM");
|
|
4438
|
+
return true;
|
|
4439
|
+
} catch {
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
const pid = await getHubPidFromHealth();
|
|
4443
|
+
if (!pid) return false;
|
|
4370
4444
|
try {
|
|
4371
|
-
process.kill(
|
|
4445
|
+
process.kill(pid, "SIGTERM");
|
|
4372
4446
|
return true;
|
|
4373
4447
|
} catch {
|
|
4374
4448
|
return false;
|
|
@@ -4537,11 +4611,15 @@ function preventSleep() {
|
|
|
4537
4611
|
async function ensureHub() {
|
|
4538
4612
|
const hubRunning = await discoverHub();
|
|
4539
4613
|
if (hubRunning) {
|
|
4540
|
-
|
|
4614
|
+
const config = getHubConfig();
|
|
4615
|
+
if (config) {
|
|
4616
|
+
return false;
|
|
4617
|
+
}
|
|
4618
|
+
console.warn(" Detected stale hub daemon (no config). Restarting...");
|
|
4619
|
+
await killStaleHub();
|
|
4541
4620
|
}
|
|
4542
4621
|
try {
|
|
4543
4622
|
await spawnHub();
|
|
4544
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
4545
4623
|
return true;
|
|
4546
4624
|
} catch (err) {
|
|
4547
4625
|
console.warn(`
|
|
@@ -4554,11 +4632,11 @@ async function handleHubCommand(options) {
|
|
|
4554
4632
|
const hubConfig = getHubConfig();
|
|
4555
4633
|
const hubRunning = await discoverHub();
|
|
4556
4634
|
if (options.hubStop) {
|
|
4557
|
-
if (!hubRunning
|
|
4635
|
+
if (!hubRunning) {
|
|
4558
4636
|
console.log("\n No hub daemon is running.\n");
|
|
4559
4637
|
return;
|
|
4560
4638
|
}
|
|
4561
|
-
const stopped = stopHub();
|
|
4639
|
+
const stopped = await stopHub();
|
|
4562
4640
|
if (stopped) {
|
|
4563
4641
|
console.log("\n Hub daemon stopped.\n");
|
|
4564
4642
|
} else {
|
|
@@ -4585,11 +4663,16 @@ async function handleHubCommand(options) {
|
|
|
4585
4663
|
return;
|
|
4586
4664
|
}
|
|
4587
4665
|
if (options.hubInfo) {
|
|
4588
|
-
if (!hubRunning
|
|
4666
|
+
if (!hubRunning) {
|
|
4589
4667
|
console.log("\n No hub daemon is running.");
|
|
4590
4668
|
console.log(" Start a session with: itwillsync -- <agent>\n");
|
|
4591
4669
|
return;
|
|
4592
4670
|
}
|
|
4671
|
+
if (!hubConfig) {
|
|
4672
|
+
console.log("\n Hub daemon is running but its config is missing (stale state).");
|
|
4673
|
+
console.log(" Run: itwillsync hub stop\n");
|
|
4674
|
+
return;
|
|
4675
|
+
}
|
|
4593
4676
|
let networkingMode = "local";
|
|
4594
4677
|
if (options.tailscale) {
|
|
4595
4678
|
networkingMode = "tailscale";
|
|
@@ -4685,12 +4768,12 @@ async function main() {
|
|
|
4685
4768
|
}
|
|
4686
4769
|
}
|
|
4687
4770
|
const dashboardUrl = hubConfig ? `http://${ip}:${HUB_EXTERNAL_PORT}?token=${hubConfig.masterToken}` : null;
|
|
4688
|
-
if (
|
|
4771
|
+
if (dashboardUrl && !options.noQr) {
|
|
4772
|
+
if (!isFirstSession) {
|
|
4773
|
+
console.log(`
|
|
4774
|
+
Session "${cmd}" registered with hub.`);
|
|
4775
|
+
}
|
|
4689
4776
|
displayQR(dashboardUrl);
|
|
4690
|
-
console.log(` Dashboard: ${dashboardUrl}`);
|
|
4691
|
-
} else if (isFirstSession && !options.noQr) {
|
|
4692
|
-
const directUrl = `http://${ip}:${port}?token=${token}`;
|
|
4693
|
-
displayQR(directUrl);
|
|
4694
4777
|
} else if (dashboardUrl) {
|
|
4695
4778
|
console.log(`
|
|
4696
4779
|
Session "${cmd}" registered with hub.`);
|
|
@@ -4726,6 +4809,10 @@ async function main() {
|
|
|
4726
4809
|
process.stdout.on("resize", handleResize);
|
|
4727
4810
|
handleResize();
|
|
4728
4811
|
async function cleanup() {
|
|
4812
|
+
process.stdout.write(
|
|
4813
|
+
"\x1B[>0u\x1B[?2004l\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1006l\x1B[?25h\x1B[?1049l"
|
|
4814
|
+
// Exit alternate screen buffer (if active)
|
|
4815
|
+
);
|
|
4729
4816
|
if (process.stdin.isTTY) {
|
|
4730
4817
|
process.stdin.setRawMode(false);
|
|
4731
4818
|
}
|