@episoda/cli 0.2.166 → 0.2.168
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/daemon/daemon-process.js +95 -21
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +46 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3003,7 +3003,17 @@ var status = {
|
|
|
3003
3003
|
var fs = __toESM(require("fs"));
|
|
3004
3004
|
var path = __toESM(require("path"));
|
|
3005
3005
|
var import_child_process = require("child_process");
|
|
3006
|
+
var import_crypto = require("crypto");
|
|
3006
3007
|
var import_core = __toESM(require_dist());
|
|
3008
|
+
function logSignalDispatch(input) {
|
|
3009
|
+
const payload = {
|
|
3010
|
+
correlationId: (0, import_crypto.randomUUID)(),
|
|
3011
|
+
...input,
|
|
3012
|
+
actorPid: process.pid,
|
|
3013
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
3014
|
+
};
|
|
3015
|
+
console.log(`[DaemonManager] SignalDispatch ${JSON.stringify(payload)}`);
|
|
3016
|
+
}
|
|
3007
3017
|
function killAllEpisodaProcesses() {
|
|
3008
3018
|
const currentPid = process.pid;
|
|
3009
3019
|
let killedCount = 0;
|
|
@@ -3023,6 +3033,13 @@ function killAllEpisodaProcesses() {
|
|
|
3023
3033
|
const pid = parseInt(parts[1], 10);
|
|
3024
3034
|
if (isNaN(pid) || pid === currentPid) continue;
|
|
3025
3035
|
try {
|
|
3036
|
+
logSignalDispatch({
|
|
3037
|
+
initiator: "killAllEpisodaProcesses",
|
|
3038
|
+
pid,
|
|
3039
|
+
signal: "SIGTERM",
|
|
3040
|
+
reason: "stale_process_cleanup",
|
|
3041
|
+
command: line.trim()
|
|
3042
|
+
});
|
|
3026
3043
|
process.kill(pid, "SIGTERM");
|
|
3027
3044
|
killedCount++;
|
|
3028
3045
|
console.log(`[Cleanup] Killed stale process PID ${pid}`);
|
|
@@ -3140,6 +3157,12 @@ async function stopDaemon(timeout = 5e3) {
|
|
|
3140
3157
|
return false;
|
|
3141
3158
|
}
|
|
3142
3159
|
try {
|
|
3160
|
+
logSignalDispatch({
|
|
3161
|
+
initiator: "stopDaemon",
|
|
3162
|
+
pid,
|
|
3163
|
+
signal: "SIGTERM",
|
|
3164
|
+
reason: "graceful_shutdown"
|
|
3165
|
+
});
|
|
3143
3166
|
process.kill(pid, "SIGTERM");
|
|
3144
3167
|
const startTime = Date.now();
|
|
3145
3168
|
while (Date.now() - startTime < timeout) {
|
|
@@ -3155,6 +3178,12 @@ async function stopDaemon(timeout = 5e3) {
|
|
|
3155
3178
|
}
|
|
3156
3179
|
}
|
|
3157
3180
|
console.warn(`Daemon didn't stop gracefully, forcing shutdown (PID: ${pid})`);
|
|
3181
|
+
logSignalDispatch({
|
|
3182
|
+
initiator: "stopDaemon",
|
|
3183
|
+
pid,
|
|
3184
|
+
signal: "SIGKILL",
|
|
3185
|
+
reason: `graceful_shutdown_timeout_${timeout}ms`
|
|
3186
|
+
});
|
|
3158
3187
|
process.kill(pid, "SIGKILL");
|
|
3159
3188
|
const pidPath = getPidFilePath();
|
|
3160
3189
|
if (fs.existsSync(pidPath)) {
|
|
@@ -4503,39 +4532,14 @@ shell.Run cmd, 0, False
|
|
|
4503
4532
|
}
|
|
4504
4533
|
}
|
|
4505
4534
|
|
|
4506
|
-
// src/
|
|
4507
|
-
|
|
4508
|
-
async function promptYesNo(question, defaultValue = true) {
|
|
4509
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
4510
|
-
return defaultValue;
|
|
4511
|
-
}
|
|
4512
|
-
const rl = readline.createInterface({
|
|
4513
|
-
input: process.stdin,
|
|
4514
|
-
output: process.stdout
|
|
4515
|
-
});
|
|
4516
|
-
const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
|
|
4517
|
-
const answer = await new Promise((resolve5) => {
|
|
4518
|
-
rl.question(`${question}${suffix}`, (response) => resolve5(response));
|
|
4519
|
-
});
|
|
4520
|
-
rl.close();
|
|
4521
|
-
const normalized = answer.trim().toLowerCase();
|
|
4522
|
-
if (!normalized) return defaultValue;
|
|
4523
|
-
return normalized === "y" || normalized === "yes";
|
|
4524
|
-
}
|
|
4525
|
-
|
|
4526
|
-
// src/commands/daemon.ts
|
|
4527
|
-
var CONNECTION_MAX_RETRIES = 3;
|
|
4528
|
-
async function maybeRegisterProtocolHandler() {
|
|
4535
|
+
// src/commands/protocol-registration.ts
|
|
4536
|
+
async function ensureProtocolHandlerRegistered() {
|
|
4529
4537
|
if (process.env.EPISODA_PROTOCOL_INVOKE === "1") {
|
|
4530
4538
|
return;
|
|
4531
4539
|
}
|
|
4532
4540
|
if (isProtocolHandlerRegistered()) {
|
|
4533
4541
|
return;
|
|
4534
4542
|
}
|
|
4535
|
-
const shouldRegister = await promptYesNo("Register episoda:// for one-click reconnects?");
|
|
4536
|
-
if (!shouldRegister) {
|
|
4537
|
-
return;
|
|
4538
|
-
}
|
|
4539
4543
|
const result = registerProtocolHandler();
|
|
4540
4544
|
if (result.success) {
|
|
4541
4545
|
status.success(result.message || "Protocol handler registered.");
|
|
@@ -4543,6 +4547,10 @@ async function maybeRegisterProtocolHandler() {
|
|
|
4543
4547
|
status.warning(`Protocol handler not registered: ${result.error}`);
|
|
4544
4548
|
}
|
|
4545
4549
|
}
|
|
4550
|
+
|
|
4551
|
+
// src/commands/daemon.ts
|
|
4552
|
+
var CONNECTION_MAX_RETRIES = 3;
|
|
4553
|
+
var FOREGROUND_DAEMON_MONITOR_INTERVAL_MS = 5e3;
|
|
4546
4554
|
function findGitRoot(startDir) {
|
|
4547
4555
|
try {
|
|
4548
4556
|
const result = (0, import_child_process5.execSync)("git rev-parse --show-toplevel", {
|
|
@@ -4706,7 +4714,7 @@ async function daemonCommand(options = {}) {
|
|
|
4706
4714
|
} else {
|
|
4707
4715
|
status.success("Connected to Episoda");
|
|
4708
4716
|
}
|
|
4709
|
-
await
|
|
4717
|
+
await ensureProtocolHandlerRegistered();
|
|
4710
4718
|
if (options.foreground) {
|
|
4711
4719
|
status.info("");
|
|
4712
4720
|
if (isCloudMode) {
|
|
@@ -4724,6 +4732,13 @@ Received ${signal}. Daemon continues running in background.`);
|
|
|
4724
4732
|
};
|
|
4725
4733
|
process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
|
|
4726
4734
|
process.on("SIGINT", () => shutdownHandler("SIGINT"));
|
|
4735
|
+
setInterval(() => {
|
|
4736
|
+
const activePid = isDaemonRunning();
|
|
4737
|
+
if (!activePid) {
|
|
4738
|
+
status.error("Daemon process exited unexpectedly; terminating foreground wrapper for supervisor restart.");
|
|
4739
|
+
process.exit(1);
|
|
4740
|
+
}
|
|
4741
|
+
}, FOREGROUND_DAEMON_MONITOR_INTERVAL_MS);
|
|
4727
4742
|
setInterval(() => {
|
|
4728
4743
|
}, 1e3 * 60 * 60);
|
|
4729
4744
|
await new Promise(() => {
|
|
@@ -7242,7 +7257,7 @@ function printExports(envVars) {
|
|
|
7242
7257
|
// src/commands/env.ts
|
|
7243
7258
|
var fs14 = __toESM(require("fs"));
|
|
7244
7259
|
var path16 = __toESM(require("path"));
|
|
7245
|
-
var
|
|
7260
|
+
var readline = __toESM(require("readline"));
|
|
7246
7261
|
var import_core17 = __toESM(require_dist());
|
|
7247
7262
|
async function envListCommand(options = {}) {
|
|
7248
7263
|
const config = await (0, import_core17.loadConfig)();
|
|
@@ -7438,7 +7453,7 @@ async function envPullCommand(options = {}) {
|
|
|
7438
7453
|
async function promptForValue(key) {
|
|
7439
7454
|
if (!process.stdin.isTTY) {
|
|
7440
7455
|
return new Promise((resolve5, reject) => {
|
|
7441
|
-
const rl =
|
|
7456
|
+
const rl = readline.createInterface({
|
|
7442
7457
|
input: process.stdin,
|
|
7443
7458
|
output: process.stdout
|
|
7444
7459
|
});
|
|
@@ -7452,7 +7467,7 @@ async function promptForValue(key) {
|
|
|
7452
7467
|
});
|
|
7453
7468
|
}
|
|
7454
7469
|
return new Promise((resolve5, reject) => {
|
|
7455
|
-
const rl =
|
|
7470
|
+
const rl = readline.createInterface({
|
|
7456
7471
|
input: process.stdin,
|
|
7457
7472
|
output: process.stdout
|
|
7458
7473
|
});
|