orchestrating 0.1.34 → 0.1.36
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 +112 -4
- package/package.json +1 -1
package/bin/orch
CHANGED
|
@@ -289,6 +289,105 @@ if (firstArg === "daemon") {
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
+
// orch daemon --enable — register as system service (survives reboot)
|
|
293
|
+
if (daemonArgs.includes("--enable")) {
|
|
294
|
+
const orchBin = process.argv[1] || execSync("which orch", { encoding: "utf-8" }).trim();
|
|
295
|
+
const nodeBin = process.execPath;
|
|
296
|
+
let extraArgs = "";
|
|
297
|
+
if (projectsDir) extraArgs = ` --projects ${projectsDir}`;
|
|
298
|
+
|
|
299
|
+
if (process.platform === "darwin") {
|
|
300
|
+
// macOS: launchd plist
|
|
301
|
+
const plistDir = path.join(os.homedir(), "Library", "LaunchAgents");
|
|
302
|
+
const plistPath = path.join(plistDir, "ing.orchestrat.daemon.plist");
|
|
303
|
+
mkdirSync(plistDir, { recursive: true });
|
|
304
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
305
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
306
|
+
<plist version="1.0">
|
|
307
|
+
<dict>
|
|
308
|
+
<key>Label</key>
|
|
309
|
+
<string>ing.orchestrat.daemon</string>
|
|
310
|
+
<key>ProgramArguments</key>
|
|
311
|
+
<array>
|
|
312
|
+
<string>${nodeBin}</string>
|
|
313
|
+
<string>${orchBin}</string>
|
|
314
|
+
<string>daemon</string>${projectsDir ? `\n <string>--projects</string>\n <string>${projectsDir}</string>` : ""}
|
|
315
|
+
</array>
|
|
316
|
+
<key>RunAtLoad</key>
|
|
317
|
+
<true/>
|
|
318
|
+
<key>KeepAlive</key>
|
|
319
|
+
<true/>
|
|
320
|
+
<key>StandardOutPath</key>
|
|
321
|
+
<string>${path.join(os.homedir(), ".orch-daemon.log")}</string>
|
|
322
|
+
<key>StandardErrorPath</key>
|
|
323
|
+
<string>${path.join(os.homedir(), ".orch-daemon.log")}</string>
|
|
324
|
+
<key>EnvironmentVariables</key>
|
|
325
|
+
<dict>
|
|
326
|
+
<key>PATH</key>
|
|
327
|
+
<string>${process.env.PATH}</string>
|
|
328
|
+
</dict>
|
|
329
|
+
</dict>
|
|
330
|
+
</plist>`;
|
|
331
|
+
writeFileSync(plistPath, plist);
|
|
332
|
+
execSync(`launchctl load -w "${plistPath}"`);
|
|
333
|
+
console.log("Daemon enabled — will start on login and auto-restart.");
|
|
334
|
+
console.log(`Logs: ~/.orch-daemon.log`);
|
|
335
|
+
console.log(`Disable: orch daemon --disable`);
|
|
336
|
+
} else {
|
|
337
|
+
// Linux: systemd user service
|
|
338
|
+
const serviceDir = path.join(os.homedir(), ".config", "systemd", "user");
|
|
339
|
+
const servicePath = path.join(serviceDir, "orch-daemon.service");
|
|
340
|
+
mkdirSync(serviceDir, { recursive: true });
|
|
341
|
+
const service = `[Unit]
|
|
342
|
+
Description=orchestrat.ing daemon
|
|
343
|
+
After=network.target
|
|
344
|
+
|
|
345
|
+
[Service]
|
|
346
|
+
ExecStart=${nodeBin} ${orchBin} daemon${extraArgs}
|
|
347
|
+
Restart=always
|
|
348
|
+
RestartSec=5
|
|
349
|
+
Environment=PATH=${process.env.PATH}
|
|
350
|
+
|
|
351
|
+
[Install]
|
|
352
|
+
WantedBy=default.target
|
|
353
|
+
`;
|
|
354
|
+
writeFileSync(servicePath, service);
|
|
355
|
+
execSync("systemctl --user daemon-reload");
|
|
356
|
+
execSync("systemctl --user enable --now orch-daemon.service");
|
|
357
|
+
// Enable lingering so user services run without active login session
|
|
358
|
+
try { execSync(`loginctl enable-linger ${os.userInfo().username}`); } catch {}
|
|
359
|
+
console.log("Daemon enabled — will start on boot and auto-restart.");
|
|
360
|
+
console.log(`Logs: journalctl --user -u orch-daemon -f`);
|
|
361
|
+
console.log(`Disable: orch daemon --disable`);
|
|
362
|
+
}
|
|
363
|
+
process.exit(0);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// orch daemon --disable — remove system service
|
|
367
|
+
if (daemonArgs.includes("--disable")) {
|
|
368
|
+
if (process.platform === "darwin") {
|
|
369
|
+
const plistPath = path.join(os.homedir(), "Library", "LaunchAgents", "ing.orchestrat.daemon.plist");
|
|
370
|
+
if (existsSync(plistPath)) {
|
|
371
|
+
try { execSync(`launchctl unload "${plistPath}"`); } catch {}
|
|
372
|
+
unlinkSync(plistPath);
|
|
373
|
+
console.log("Daemon disabled — removed from login items.");
|
|
374
|
+
} else {
|
|
375
|
+
console.log("Daemon was not enabled.");
|
|
376
|
+
}
|
|
377
|
+
} else {
|
|
378
|
+
const servicePath = path.join(os.homedir(), ".config", "systemd", "user", "orch-daemon.service");
|
|
379
|
+
if (existsSync(servicePath)) {
|
|
380
|
+
try { execSync("systemctl --user disable --now orch-daemon.service"); } catch {}
|
|
381
|
+
unlinkSync(servicePath);
|
|
382
|
+
execSync("systemctl --user daemon-reload");
|
|
383
|
+
console.log("Daemon disabled — removed systemd service.");
|
|
384
|
+
} else {
|
|
385
|
+
console.log("Daemon was not enabled.");
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
process.exit(0);
|
|
389
|
+
}
|
|
390
|
+
|
|
292
391
|
// orch daemon --background — fork and exit
|
|
293
392
|
if (background) {
|
|
294
393
|
const orchPath = fileURLToPath(import.meta.url);
|
|
@@ -623,6 +722,11 @@ while (i < args.length) {
|
|
|
623
722
|
console.error(" -y, --yolo Skip all permission prompts (auto-approve everything)");
|
|
624
723
|
console.error("");
|
|
625
724
|
console.error("Daemon options:");
|
|
725
|
+
console.error(" -b, --background Run daemon in background");
|
|
726
|
+
console.error(" --enable Start on boot (systemd/launchd)");
|
|
727
|
+
console.error(" --disable Remove boot startup");
|
|
728
|
+
console.error(" --stop Stop background daemon");
|
|
729
|
+
console.error(" --status Check if daemon is running");
|
|
626
730
|
console.error(" --projects <path> Directory to scan for projects (default: ~/projects)");
|
|
627
731
|
console.error(" -d <path> Short alias for --projects");
|
|
628
732
|
console.error("");
|
|
@@ -632,7 +736,8 @@ while (i < args.length) {
|
|
|
632
736
|
console.error(' orch -l "deploy fix" codex');
|
|
633
737
|
console.error(" orch bash");
|
|
634
738
|
console.error(" orch daemon");
|
|
635
|
-
console.error(" orch daemon
|
|
739
|
+
console.error(" orch daemon -b");
|
|
740
|
+
console.error(" orch daemon --enable");
|
|
636
741
|
console.error("");
|
|
637
742
|
console.error("Environment:");
|
|
638
743
|
console.error(" ORC_URL WebSocket server URL (default: wss://api.orchestrat.ing/ws)");
|
|
@@ -983,10 +1088,13 @@ if (adapter) {
|
|
|
983
1088
|
} catch {}
|
|
984
1089
|
}
|
|
985
1090
|
if (historyEvents.length > 0) {
|
|
986
|
-
|
|
1091
|
+
// Only keep the most recent events from history
|
|
1092
|
+
const trimmedHistory = historyEvents.length > MAX_EVENT_HISTORY
|
|
1093
|
+
? historyEvents.slice(-MAX_EVENT_HISTORY)
|
|
1094
|
+
: historyEvents;
|
|
1095
|
+
process.stderr.write(`${DIM}[orch] Forwarding ${trimmedHistory.length} history events to dashboard (${historyEvents.length} total)${RESET}\n`);
|
|
987
1096
|
// Prepend to eventHistory so they get replayed on reconnect too
|
|
988
|
-
eventHistory.unshift(...
|
|
989
|
-
while (eventHistory.length > MAX_EVENT_HISTORY) eventHistory.pop();
|
|
1097
|
+
eventHistory.unshift(...trimmedHistory);
|
|
990
1098
|
}
|
|
991
1099
|
}
|
|
992
1100
|
} catch (err) {
|