orchestrating 0.1.25 → 0.1.26
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/bin/orch +40 -22
- package/package.json +1 -1
package/bin/orch
CHANGED
|
@@ -221,6 +221,18 @@ async function handleDaemon() {
|
|
|
221
221
|
process.stderr.write(`${GREEN}${PREFIX} Listening for remote sessions as "${hostname}"${RESET}\n`);
|
|
222
222
|
process.stderr.write(`${DIM}${PREFIX} Tip: Use 'nohup orch daemon &' to run in background${RESET}\n`);
|
|
223
223
|
|
|
224
|
+
let reconnecting = false;
|
|
225
|
+
|
|
226
|
+
function scheduleReconnect(delaySec) {
|
|
227
|
+
if (reconnecting) return;
|
|
228
|
+
reconnecting = true;
|
|
229
|
+
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
230
|
+
reconnectTimer = setTimeout(() => {
|
|
231
|
+
reconnecting = false;
|
|
232
|
+
connect();
|
|
233
|
+
}, delaySec * 1000);
|
|
234
|
+
}
|
|
235
|
+
|
|
224
236
|
async function connect() {
|
|
225
237
|
// Refresh token if needed before connecting
|
|
226
238
|
if (isTokenExpired()) {
|
|
@@ -230,15 +242,20 @@ async function handleDaemon() {
|
|
|
230
242
|
process.stderr.write(`${DIM}${PREFIX} Token refreshed${RESET}\n`);
|
|
231
243
|
} else {
|
|
232
244
|
process.stderr.write(`${RED}${PREFIX} Token refresh failed — retrying in 10s${RESET}\n`);
|
|
233
|
-
|
|
245
|
+
scheduleReconnect(10);
|
|
234
246
|
return;
|
|
235
247
|
}
|
|
236
248
|
}
|
|
237
249
|
|
|
238
|
-
|
|
250
|
+
if (ws) {
|
|
251
|
+
ws.removeAllListeners();
|
|
252
|
+
ws.close();
|
|
253
|
+
}
|
|
254
|
+
const sock = new WebSocket(serverUrl);
|
|
255
|
+
ws = sock;
|
|
239
256
|
|
|
240
|
-
|
|
241
|
-
|
|
257
|
+
sock.on("open", () => {
|
|
258
|
+
sock.send(JSON.stringify({
|
|
242
259
|
type: "register_daemon",
|
|
243
260
|
token,
|
|
244
261
|
hostname,
|
|
@@ -250,30 +267,31 @@ async function handleDaemon() {
|
|
|
250
267
|
if (pingTimer) clearInterval(pingTimer);
|
|
251
268
|
if (pongTimer) clearTimeout(pongTimer);
|
|
252
269
|
pingTimer = setInterval(() => {
|
|
253
|
-
if (
|
|
254
|
-
|
|
270
|
+
if (sock.readyState === WebSocket.OPEN) {
|
|
271
|
+
sock.ping();
|
|
255
272
|
pongTimer = setTimeout(() => {
|
|
256
|
-
|
|
273
|
+
sock.terminate();
|
|
257
274
|
}, PONG_TIMEOUT_MS);
|
|
258
275
|
}
|
|
259
276
|
}, PING_INTERVAL_MS);
|
|
260
277
|
});
|
|
261
278
|
|
|
262
|
-
|
|
279
|
+
sock.on("pong", () => {
|
|
263
280
|
if (pongTimer) { clearTimeout(pongTimer); pongTimer = null; }
|
|
264
281
|
});
|
|
265
282
|
|
|
266
|
-
|
|
283
|
+
sock.on("message", (raw) => {
|
|
267
284
|
let msg;
|
|
268
285
|
try { msg = JSON.parse(raw.toString()); } catch { return; }
|
|
269
286
|
|
|
270
287
|
if (msg.type === "error") {
|
|
271
288
|
process.stderr.write(`${RED}${PREFIX} Server: ${msg.error}${RESET}\n`);
|
|
272
289
|
if (/unauthorized|auth|token/i.test(msg.error || "")) {
|
|
290
|
+
// Don't reconnect from here — let the close handler do it after refreshing
|
|
273
291
|
refreshAuthToken().then((refreshed) => {
|
|
274
292
|
if (refreshed) {
|
|
275
293
|
token = refreshed;
|
|
276
|
-
|
|
294
|
+
process.stderr.write(`${DIM}${PREFIX} Token refreshed — will reconnect${RESET}\n`);
|
|
277
295
|
} else {
|
|
278
296
|
process.stderr.write(`${RED}${PREFIX} Auth failed. Run 'orch login'.${RESET}\n`);
|
|
279
297
|
process.exit(1);
|
|
@@ -284,15 +302,15 @@ async function handleDaemon() {
|
|
|
284
302
|
}
|
|
285
303
|
|
|
286
304
|
if (msg.type === "start_session") {
|
|
287
|
-
const { requestId, command, args, cwd, label, yolo } = msg;
|
|
288
|
-
const cmdStr = [
|
|
305
|
+
const { requestId, command: cmd, args: cmdArgs, cwd, label: lbl, yolo } = msg;
|
|
306
|
+
const cmdStr = [cmd, ...cmdArgs].join(" ");
|
|
289
307
|
process.stderr.write(`${GREEN}${PREFIX} Spawning: ${cmdStr}${RESET}\n`);
|
|
290
308
|
|
|
291
309
|
try {
|
|
292
310
|
const childArgs = [];
|
|
293
|
-
if (
|
|
311
|
+
if (lbl) childArgs.push("-l", lbl);
|
|
294
312
|
if (yolo) childArgs.push("-y");
|
|
295
|
-
childArgs.push(
|
|
313
|
+
childArgs.push(cmd, ...cmdArgs);
|
|
296
314
|
|
|
297
315
|
const child = spawn(process.execPath, [orchPath, ...childArgs], {
|
|
298
316
|
stdio: "ignore",
|
|
@@ -302,8 +320,8 @@ async function handleDaemon() {
|
|
|
302
320
|
});
|
|
303
321
|
child.unref();
|
|
304
322
|
|
|
305
|
-
if (
|
|
306
|
-
|
|
323
|
+
if (sock.readyState === WebSocket.OPEN) {
|
|
324
|
+
sock.send(JSON.stringify({
|
|
307
325
|
type: "session_started",
|
|
308
326
|
requestId,
|
|
309
327
|
success: true,
|
|
@@ -311,8 +329,8 @@ async function handleDaemon() {
|
|
|
311
329
|
}
|
|
312
330
|
} catch (err) {
|
|
313
331
|
process.stderr.write(`${RED}${PREFIX} Spawn failed: ${err.message}${RESET}\n`);
|
|
314
|
-
if (
|
|
315
|
-
|
|
332
|
+
if (sock.readyState === WebSocket.OPEN) {
|
|
333
|
+
sock.send(JSON.stringify({
|
|
316
334
|
type: "session_started",
|
|
317
335
|
requestId,
|
|
318
336
|
success: false,
|
|
@@ -323,15 +341,15 @@ async function handleDaemon() {
|
|
|
323
341
|
}
|
|
324
342
|
});
|
|
325
343
|
|
|
326
|
-
|
|
327
|
-
ws = null;
|
|
344
|
+
sock.on("close", () => {
|
|
345
|
+
if (ws === sock) ws = null;
|
|
328
346
|
if (pingTimer) { clearInterval(pingTimer); pingTimer = null; }
|
|
329
347
|
if (pongTimer) { clearTimeout(pongTimer); pongTimer = null; }
|
|
330
348
|
process.stderr.write(`${DIM}${PREFIX} Disconnected — reconnecting in 2s${RESET}\n`);
|
|
331
|
-
|
|
349
|
+
scheduleReconnect(2);
|
|
332
350
|
});
|
|
333
351
|
|
|
334
|
-
|
|
352
|
+
sock.on("error", () => {
|
|
335
353
|
// Will trigger close
|
|
336
354
|
});
|
|
337
355
|
}
|