@houwert/conductor 0.8.0 → 0.9.0
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/server.js +49 -0
- package/drivers/ios/conductor-driver-ios.zip +0 -0
- package/drivers/ios/conductor-driver-iosUITests-Runner.zip +0 -0
- package/drivers/tvos/conductor-driver-tvos.zip +0 -0
- package/drivers/tvos/conductor-driver-tvosUITests-Runner.zip +0 -0
- package/package.json +1 -1
- package/skills/conductor/SKILL.md +1 -1
- package/skills/skills.yaml +1 -1
package/dist/daemon/server.js
CHANGED
|
@@ -41,6 +41,26 @@ const cdpUrl = process.env.CONDUCTOR_CDP_URL || undefined;
|
|
|
41
41
|
* URL heuristics.
|
|
42
42
|
*/
|
|
43
43
|
const cdpTargetId = process.env.CONDUCTOR_CDP_TARGET_ID || undefined;
|
|
44
|
+
/**
|
|
45
|
+
* PID of the process that should be considered the daemon's "owner". When set,
|
|
46
|
+
* the daemon polls for this process's existence and shuts down cleanly when it
|
|
47
|
+
* disappears. This prevents orphaned daemons (and their Playwright browsers)
|
|
48
|
+
* from piling up after the host app crashes or quits without calling
|
|
49
|
+
* `daemon-stop`.
|
|
50
|
+
*
|
|
51
|
+
* The daemon runs detached, so `process.ppid` becomes 1 after the parent exits
|
|
52
|
+
* and is useless for this purpose. The owner must be passed explicitly by the
|
|
53
|
+
* host app via the env when it invokes `conductor daemon-start` (or whatever
|
|
54
|
+
* code path ultimately triggers the daemon spawn).
|
|
55
|
+
*/
|
|
56
|
+
const parentPid = (() => {
|
|
57
|
+
const raw = process.env.CONDUCTOR_PARENT_PID;
|
|
58
|
+
if (!raw)
|
|
59
|
+
return undefined;
|
|
60
|
+
const n = parseInt(raw, 10);
|
|
61
|
+
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
62
|
+
})();
|
|
63
|
+
const PARENT_POLL_INTERVAL_MS = 10000;
|
|
44
64
|
const SOCKET_PATH = (0, protocol_js_1.socketPath)(sessionName);
|
|
45
65
|
const PID_FILE = (0, protocol_js_1.pidFile)(sessionName);
|
|
46
66
|
const LOG_FILE = (0, protocol_js_1.logFile)(sessionName);
|
|
@@ -123,6 +143,7 @@ async function main() {
|
|
|
123
143
|
}
|
|
124
144
|
let idleTimer;
|
|
125
145
|
let healthTimer;
|
|
146
|
+
let parentWatchTimer;
|
|
126
147
|
const idleTimeoutMs = Number(process.env.CONDUCTOR_IDLE_TIMEOUT_MS) || protocol_js_1.IDLE_TIMEOUT_MS;
|
|
127
148
|
function resetIdleTimer() {
|
|
128
149
|
if (idleTimer)
|
|
@@ -135,6 +156,10 @@ async function main() {
|
|
|
135
156
|
async function cleanup() {
|
|
136
157
|
if (healthTimer)
|
|
137
158
|
clearInterval(healthTimer);
|
|
159
|
+
if (parentWatchTimer)
|
|
160
|
+
clearInterval(parentWatchTimer);
|
|
161
|
+
if (idleTimer)
|
|
162
|
+
clearTimeout(idleTimer);
|
|
138
163
|
if (logCollector) {
|
|
139
164
|
logCollector.stop();
|
|
140
165
|
logCollector = null;
|
|
@@ -215,6 +240,30 @@ async function main() {
|
|
|
215
240
|
}, DRIVER_HEALTH_INTERVAL_MS);
|
|
216
241
|
healthTimer.unref(); // Don't keep the process alive just for health checks
|
|
217
242
|
}
|
|
243
|
+
// If the host app told us who it is, shut down when it disappears. This is
|
|
244
|
+
// the primary defence against orphaned daemons + headless Chromiums when the
|
|
245
|
+
// host app crashes or force-quits without calling daemon-stop.
|
|
246
|
+
if (parentPid !== undefined) {
|
|
247
|
+
dlog(`Watching parent pid ${parentPid}`);
|
|
248
|
+
let shuttingDown = false;
|
|
249
|
+
parentWatchTimer = setInterval(() => {
|
|
250
|
+
if (shuttingDown)
|
|
251
|
+
return;
|
|
252
|
+
try {
|
|
253
|
+
process.kill(parentPid, 0);
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
const code = err.code;
|
|
257
|
+
if (code === 'ESRCH') {
|
|
258
|
+
shuttingDown = true;
|
|
259
|
+
dlog(`Parent pid ${parentPid} exited — shutting down`);
|
|
260
|
+
cleanup().then(() => process.exit(0));
|
|
261
|
+
}
|
|
262
|
+
// EPERM means the process exists but we can't signal it — still alive.
|
|
263
|
+
}
|
|
264
|
+
}, PARENT_POLL_INTERVAL_MS);
|
|
265
|
+
parentWatchTimer.unref();
|
|
266
|
+
}
|
|
218
267
|
// ── HTTP server on Unix socket ─────────────────────────────────────────────
|
|
219
268
|
// Replaces the old raw-TCP accept-and-close with a proper HTTP server so we
|
|
220
269
|
// can serve /status (aliveness) and /logs (buffered log entries).
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED