@integrity-labs/agt-cli 0.19.2 → 0.19.4
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/bin/agt.js +7 -3
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-BEIZXSG4.js → chunk-MC3SMG4A.js} +191 -8
- package/dist/chunk-MC3SMG4A.js.map +1 -0
- package/dist/lib/manager-worker.js +356 -165
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{manager-supervisor-PU5YK5QE.js → manager-supervisor-P63HG5MR.js} +193 -3
- package/dist/manager-supervisor-P63HG5MR.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-BEIZXSG4.js.map +0 -1
- package/dist/manager-supervisor-PU5YK5QE.js.map +0 -1
|
@@ -316,27 +316,217 @@ function shellQuoteForSystemd(arg) {
|
|
|
316
316
|
if (/^[A-Za-z0-9_./:=-]+$/.test(arg)) return arg;
|
|
317
317
|
return `"${arg.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
318
318
|
}
|
|
319
|
+
var LINUX_SYSTEM_UNIT_PATH = "/etc/systemd/system/agt-manager.service";
|
|
320
|
+
var LINUX_SYSTEM_ENV_FILE_PATH = "/etc/agt/agt-manager.env";
|
|
321
|
+
async function installSystemUnit(opts) {
|
|
322
|
+
if (platform() !== "linux") {
|
|
323
|
+
return {
|
|
324
|
+
ok: false,
|
|
325
|
+
error: `installSystemUnit is Linux-only (current platform: ${platform()}). For local dev on macOS use installSupervisor.`
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
if (process.getuid?.() !== 0) {
|
|
329
|
+
return {
|
|
330
|
+
ok: false,
|
|
331
|
+
error: "installSystemUnit requires root. Re-run with sudo, or call from the EC2 user-data bootstrap which already runs as root."
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
if (!existsSync(opts.agtBin)) {
|
|
335
|
+
return { ok: false, error: `agt binary not found at ${opts.agtBin}` };
|
|
336
|
+
}
|
|
337
|
+
if (opts.intervalSec < 5) {
|
|
338
|
+
return { ok: false, error: "intervalSec must be >= 5" };
|
|
339
|
+
}
|
|
340
|
+
if (!opts.env.AGT_HOST || !opts.env.AGT_API_KEY) {
|
|
341
|
+
return {
|
|
342
|
+
ok: false,
|
|
343
|
+
error: "AGT_HOST and AGT_API_KEY must be set so the system unit can pass them through. Run `agt setup <token>` first (it writes them to /etc/environment, which this installer reads)."
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
bestEffort(() => execFileSync("systemctl", ["stop", LINUX_UNIT_NAME], { stdio: "ignore" }));
|
|
347
|
+
bestEffort(() => {
|
|
348
|
+
const out = execFileSync("pgrep", ["-f", "agt manager start"], { stdio: ["ignore", "pipe", "ignore"], encoding: "utf-8" });
|
|
349
|
+
const pids = out.split("\n").map((s) => s.trim()).filter((s) => s.length > 0 && /^\d+$/.test(s) && Number(s) !== process.pid);
|
|
350
|
+
if (pids.length === 0) return;
|
|
351
|
+
for (const pid of pids) {
|
|
352
|
+
bestEffort(() => process.kill(Number(pid), "SIGTERM"));
|
|
353
|
+
}
|
|
354
|
+
const deadline = Date.now() + 3e3;
|
|
355
|
+
while (Date.now() < deadline) {
|
|
356
|
+
try {
|
|
357
|
+
execFileSync("pgrep", ["-f", "agt manager start"], { stdio: "ignore" });
|
|
358
|
+
} catch {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
for (const pid of pids) {
|
|
363
|
+
bestEffort(() => process.kill(Number(pid), "SIGKILL"));
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
mkdirSync(dirname(LINUX_SYSTEM_ENV_FILE_PATH), { recursive: true, mode: 448 });
|
|
367
|
+
writeFileSync(LINUX_SYSTEM_ENV_FILE_PATH, renderLinuxEnvFile(opts), { mode: 384 });
|
|
368
|
+
chmodSync(LINUX_SYSTEM_ENV_FILE_PATH, 384);
|
|
369
|
+
writeFileSync(LINUX_SYSTEM_UNIT_PATH, renderLinuxSystemUnit(opts), { mode: 420 });
|
|
370
|
+
chmodSync(LINUX_SYSTEM_UNIT_PATH, 420);
|
|
371
|
+
try {
|
|
372
|
+
execFileSync("systemctl", ["daemon-reload"], { stdio: "pipe" });
|
|
373
|
+
} catch (err) {
|
|
374
|
+
return { ok: false, error: `systemctl daemon-reload failed: ${err.message}` };
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
execFileSync("systemctl", ["enable", "--now", LINUX_UNIT_NAME], { stdio: "pipe" });
|
|
378
|
+
} catch (err) {
|
|
379
|
+
return { ok: false, error: `systemctl enable --now failed: ${err.message}` };
|
|
380
|
+
}
|
|
381
|
+
let isActive = "";
|
|
382
|
+
try {
|
|
383
|
+
isActive = execFileSync("systemctl", ["is-active", LINUX_UNIT_NAME], { encoding: "utf-8" }).trim();
|
|
384
|
+
} catch (err) {
|
|
385
|
+
isActive = (err.stdout?.toString() ?? "").trim() || "unknown";
|
|
386
|
+
}
|
|
387
|
+
if (isActive !== "active") {
|
|
388
|
+
return {
|
|
389
|
+
ok: false,
|
|
390
|
+
error: `systemd loaded ${LINUX_UNIT_NAME} but it did not become active (status: ${isActive}). Run 'systemctl status ${LINUX_UNIT_NAME}' or 'journalctl -u ${LINUX_UNIT_NAME} -n 50' for details.`
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
ok: true,
|
|
395
|
+
details: `Loaded systemd system unit ${LINUX_UNIT_NAME} at ${LINUX_SYSTEM_UNIT_PATH} (status: ${isActive}). Will auto-start on reboot via multi-user.target. Logs: ${join(opts.configDir, "manager.log")} and 'journalctl -u ${LINUX_UNIT_NAME}'.`
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
async function uninstallSystemUnit() {
|
|
399
|
+
if (platform() !== "linux") {
|
|
400
|
+
return { ok: false, error: `uninstallSystemUnit is Linux-only (current platform: ${platform()}).` };
|
|
401
|
+
}
|
|
402
|
+
if (process.getuid?.() !== 0) {
|
|
403
|
+
return { ok: false, error: "uninstallSystemUnit requires root." };
|
|
404
|
+
}
|
|
405
|
+
bestEffort(() => execFileSync("systemctl", ["disable", "--now", LINUX_UNIT_NAME], { stdio: "ignore" }));
|
|
406
|
+
let removed = false;
|
|
407
|
+
if (existsSync(LINUX_SYSTEM_UNIT_PATH)) {
|
|
408
|
+
try {
|
|
409
|
+
unlinkSync(LINUX_SYSTEM_UNIT_PATH);
|
|
410
|
+
removed = true;
|
|
411
|
+
} catch (err) {
|
|
412
|
+
return { ok: false, error: `Failed to remove ${LINUX_SYSTEM_UNIT_PATH}: ${err.message}` };
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (existsSync(LINUX_SYSTEM_ENV_FILE_PATH)) {
|
|
416
|
+
bestEffort(() => unlinkSync(LINUX_SYSTEM_ENV_FILE_PATH));
|
|
417
|
+
}
|
|
418
|
+
bestEffort(() => execFileSync("systemctl", ["daemon-reload"], { stdio: "ignore" }));
|
|
419
|
+
return {
|
|
420
|
+
ok: true,
|
|
421
|
+
details: removed ? `Disabled systemd system unit ${LINUX_UNIT_NAME} and deleted ${LINUX_SYSTEM_UNIT_PATH}.` : `${LINUX_UNIT_NAME} system unit was already uninstalled (no unit file at ${LINUX_SYSTEM_UNIT_PATH}).`
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function systemUnitStatus() {
|
|
425
|
+
if (platform() !== "linux") {
|
|
426
|
+
return { kind: "unsupported-platform", platform: platform() };
|
|
427
|
+
}
|
|
428
|
+
if (!existsSync(LINUX_SYSTEM_UNIT_PATH)) return { kind: "not-installed" };
|
|
429
|
+
let pid = null;
|
|
430
|
+
let activeState = "unknown";
|
|
431
|
+
try {
|
|
432
|
+
const out = execFileSync(
|
|
433
|
+
"systemctl",
|
|
434
|
+
["show", LINUX_UNIT_NAME, "--property=MainPID,ActiveState"],
|
|
435
|
+
{ encoding: "utf-8" }
|
|
436
|
+
);
|
|
437
|
+
const pidMatch = /^MainPID=(\d+)/m.exec(out);
|
|
438
|
+
if (pidMatch && pidMatch[1] !== "0") pid = Number(pidMatch[1]);
|
|
439
|
+
const stateMatch = /^ActiveState=(\S+)/m.exec(out);
|
|
440
|
+
if (stateMatch) activeState = stateMatch[1] ?? "unknown";
|
|
441
|
+
} catch (err) {
|
|
442
|
+
return {
|
|
443
|
+
kind: "installed",
|
|
444
|
+
pid: null,
|
|
445
|
+
details: `Unit: ${LINUX_SYSTEM_UNIT_PATH} (could not query systemd: ${err.message})`
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return { kind: "installed", pid, details: `Unit: ${LINUX_SYSTEM_UNIT_PATH} (${activeState})` };
|
|
449
|
+
}
|
|
450
|
+
function renderLinuxSystemUnit(opts) {
|
|
451
|
+
const user = opts.user ?? "root";
|
|
452
|
+
const home = user === "root" ? "/root" : `/home/${user}`;
|
|
453
|
+
const envLines = Object.entries(opts.env).filter(([k, v]) => k.length > 0 && v != null && !LINUX_SECRET_ENV_KEYS.has(k)).map(([k, v]) => `Environment="${k}=${escapeForSystemdEnv(v)}"`).join("\n");
|
|
454
|
+
const execArgs = [
|
|
455
|
+
opts.agtBin,
|
|
456
|
+
"manager",
|
|
457
|
+
"start",
|
|
458
|
+
"--interval",
|
|
459
|
+
String(opts.intervalSec),
|
|
460
|
+
"--config-dir",
|
|
461
|
+
opts.configDir
|
|
462
|
+
].map(shellQuoteForSystemd).join(" ");
|
|
463
|
+
const logPath = join(opts.configDir, "manager.log");
|
|
464
|
+
return `# agt manager supervisor \u2014 system unit (ENG-4706)
|
|
465
|
+
# Managed by \`agt manager install-system-unit\` \u2014 edits will be overwritten.
|
|
466
|
+
#
|
|
467
|
+
# Unlike the sibling --user unit at ~/.config/systemd/user/agt-manager.service,
|
|
468
|
+
# this one is enabled into multi-user.target so it auto-starts on every
|
|
469
|
+
# boot regardless of any user login. Use this on EC2 / headless hosts.
|
|
470
|
+
|
|
471
|
+
[Unit]
|
|
472
|
+
Description=Augmented host manager daemon
|
|
473
|
+
After=network-online.target
|
|
474
|
+
Wants=network-online.target
|
|
475
|
+
StartLimitBurst=5
|
|
476
|
+
StartLimitIntervalSec=60
|
|
477
|
+
|
|
478
|
+
[Service]
|
|
479
|
+
Type=simple
|
|
480
|
+
User=${user}
|
|
481
|
+
WorkingDirectory=${opts.configDir}
|
|
482
|
+
Environment="HOME=${home}"
|
|
483
|
+
${envLines}
|
|
484
|
+
EnvironmentFile=${LINUX_SYSTEM_ENV_FILE_PATH}
|
|
485
|
+
ExecStart=${execArgs}
|
|
486
|
+
|
|
487
|
+
# on-failure (not always) so a clean \`systemctl stop\` doesn't fight a
|
|
488
|
+
# respawn loop. Matches the ticket spec; the 5/60s window above caps a
|
|
489
|
+
# crashloop. Logs land in ${logPath} via the manager's own writer plus
|
|
490
|
+
# journalctl -u ${LINUX_UNIT_NAME}.
|
|
491
|
+
Restart=on-failure
|
|
492
|
+
RestartSec=5
|
|
493
|
+
|
|
494
|
+
StandardOutput=append:${logPath}
|
|
495
|
+
StandardError=append:${logPath}
|
|
496
|
+
|
|
497
|
+
[Install]
|
|
498
|
+
WantedBy=multi-user.target
|
|
499
|
+
`;
|
|
500
|
+
}
|
|
319
501
|
var _internals = {
|
|
320
502
|
MACOS_LABEL,
|
|
321
503
|
MACOS_PLIST,
|
|
322
504
|
LINUX_UNIT_NAME,
|
|
323
505
|
LINUX_UNIT_PATH,
|
|
324
506
|
LINUX_ENV_FILE_PATH,
|
|
507
|
+
LINUX_SYSTEM_UNIT_PATH,
|
|
508
|
+
LINUX_SYSTEM_ENV_FILE_PATH,
|
|
325
509
|
LINUX_SECRET_ENV_KEYS,
|
|
326
510
|
renderMacosPlist,
|
|
327
511
|
renderLinuxUnit,
|
|
512
|
+
renderLinuxSystemUnit,
|
|
328
513
|
renderLinuxEnvFile,
|
|
329
514
|
escapeXml,
|
|
330
515
|
escapeForSystemdEnv,
|
|
331
516
|
shellQuoteForSystemd,
|
|
332
517
|
readPlist: () => existsSync(MACOS_PLIST) ? readFileSync(MACOS_PLIST, "utf-8") : null,
|
|
333
518
|
readUnit: () => existsSync(LINUX_UNIT_PATH) ? readFileSync(LINUX_UNIT_PATH, "utf-8") : null,
|
|
334
|
-
|
|
519
|
+
readSystemUnit: () => existsSync(LINUX_SYSTEM_UNIT_PATH) ? readFileSync(LINUX_SYSTEM_UNIT_PATH, "utf-8") : null,
|
|
520
|
+
readEnvFile: () => existsSync(LINUX_ENV_FILE_PATH) ? readFileSync(LINUX_ENV_FILE_PATH, "utf-8") : null,
|
|
521
|
+
readSystemEnvFile: () => existsSync(LINUX_SYSTEM_ENV_FILE_PATH) ? readFileSync(LINUX_SYSTEM_ENV_FILE_PATH, "utf-8") : null
|
|
335
522
|
};
|
|
336
523
|
export {
|
|
337
524
|
_internals,
|
|
338
525
|
installSupervisor,
|
|
526
|
+
installSystemUnit,
|
|
339
527
|
supervisorStatus,
|
|
340
|
-
|
|
528
|
+
systemUnitStatus,
|
|
529
|
+
uninstallSupervisor,
|
|
530
|
+
uninstallSystemUnit
|
|
341
531
|
};
|
|
342
|
-
//# sourceMappingURL=manager-supervisor-
|
|
532
|
+
//# sourceMappingURL=manager-supervisor-P63HG5MR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/manager-supervisor.ts"],"sourcesContent":["/**\n * OS-level supervision for the agt manager daemon (ENG-4593).\n *\n * Hands manager lifecycle off to the OS so a missing process is the OS's\n * problem, not ours. Replaces the in-process `agt manager start\n * --supervise` wrapper from ENG-4488.\n *\n * macOS: launchd LaunchAgent (KeepAlive=true + ThrottleInterval=10)\n * Linux: systemd --user unit (Restart=always + RestartSec=5) [Phase 2]\n * systemd system unit (Restart=on-failure, root) [Phase 3 / ENG-4706]\n *\n * Public surface:\n * - installSupervisor(opts) — write the unit, load/enable it, verify\n * - uninstallSupervisor() — unload/disable + remove the unit (idempotent)\n * - supervisorStatus() — quick readout of whether the OS knows about us\n *\n * - installSystemUnit(opts) — Linux only, root-only. Writes\n * /etc/systemd/system/agt-manager.service\n * so the manager survives EC2 reboot\n * without `loginctl enable-linger`\n * gymnastics. Used by host-bootstrap and\n * the SSM backfill runbook (ENG-4706).\n * - uninstallSystemUnit()\n * - systemUnitStatus()\n *\n * Each platform implementation lives in its own helper. The dispatcher\n * picks one based on `process.platform` and rejects unsupported OSes\n * with a clear error rather than silently no-oping.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n chmodSync,\n} from 'node:fs';\nimport { homedir, platform } from 'node:os';\nimport { dirname, join } from 'node:path';\n\n// macOS LaunchAgent label and on-disk path. Stable so install/uninstall\n// can find each other without a state file.\nconst MACOS_LABEL = 'team.augmented.agt-manager';\nconst MACOS_PLIST = join(homedir(), 'Library', 'LaunchAgents', `${MACOS_LABEL}.plist`);\n\n// Linux systemd --user unit. Lives under the operator's XDG config so it\n// survives reboot only after `loginctl enable-linger` (we surface that as\n// a follow-up step rather than running it ourselves — needs root).\nconst LINUX_UNIT_NAME = 'agt-manager.service';\nconst LINUX_UNIT_PATH = join(homedir(), '.config', 'systemd', 'user', LINUX_UNIT_NAME);\n// Secrets live in a separate EnvironmentFile (mode 0600) instead of\n// being inlined into the unit body. The unit file itself is still\n// 0600 but plain Environment= lines in it are visible to anything\n// that can read systemd's parsed unit cache (`systemctl show`,\n// `systemd-cgls --all`, etc.). EnvironmentFile content stays private\n// to the systemd manager process.\nconst LINUX_ENV_FILE_PATH = join(homedir(), '.config', 'systemd', 'user', 'agt-manager.env');\n\nexport interface InstallOpts {\n /** Absolute path to the agt binary the supervisor should launch. */\n agtBin: string;\n /** Poll interval passed to `agt manager start`. Min 5 seconds. */\n intervalSec: number;\n /** Manager config directory (where pid/log/state files live). */\n configDir: string;\n /**\n * Environment variables the supervised manager needs at launch time.\n * AGT_HOST and AGT_API_KEY are required for the manager to call the\n * API; AGT_TEAM is optional but typical.\n */\n env: Record<string, string>;\n}\n\nexport type SupervisorPresence =\n | { kind: 'installed'; pid: number | null; details: string }\n | { kind: 'not-installed' }\n | { kind: 'unsupported-platform'; platform: string };\n\n// ---------------------------------------------------------------------------\n// Public dispatcher\n// ---------------------------------------------------------------------------\n\nexport async function installSupervisor(opts: InstallOpts): Promise<{ ok: true; details: string } | { ok: false; error: string }> {\n switch (platform()) {\n case 'darwin':\n return installMacos(opts);\n case 'linux':\n return installLinux(opts);\n default:\n return { ok: false, error: `Unsupported platform: ${platform()}. Supervisor install is macOS / Linux only.` };\n }\n}\n\nexport async function uninstallSupervisor(): Promise<{ ok: true; details: string } | { ok: false; error: string }> {\n switch (platform()) {\n case 'darwin':\n return uninstallMacos();\n case 'linux':\n return uninstallLinux();\n default:\n return { ok: false, error: `Unsupported platform: ${platform()}. Supervisor uninstall is macOS / Linux only.` };\n }\n}\n\nexport function supervisorStatus(): SupervisorPresence {\n switch (platform()) {\n case 'darwin':\n return statusMacos();\n case 'linux':\n return statusLinux();\n default:\n return { kind: 'unsupported-platform', platform: platform() };\n }\n}\n\n// ---------------------------------------------------------------------------\n// macOS — launchd LaunchAgent\n// ---------------------------------------------------------------------------\n\nfunction installMacos(opts: InstallOpts): { ok: true; details: string } | { ok: false; error: string } {\n if (!existsSync(opts.agtBin)) {\n return { ok: false, error: `agt binary not found at ${opts.agtBin}` };\n }\n if (opts.intervalSec < 5) {\n return { ok: false, error: 'intervalSec must be >= 5' };\n }\n if (!opts.env.AGT_HOST || !opts.env.AGT_API_KEY) {\n return { ok: false, error: 'AGT_HOST and AGT_API_KEY must be set in the calling shell so the supervisor can pass them to the manager. Run `agt setup <token>` first.' };\n }\n\n // If a previous version is already loaded, unload it before rewriting\n // the plist — otherwise launchctl bootstrap will fail with EALREADY.\n bestEffort(() => execFileSync('launchctl', ['unload', '-w', MACOS_PLIST], { stdio: 'ignore' }));\n\n // Ensure the LaunchAgents directory exists. macOS creates it on first\n // login, but freshly-installed admin users may not have it yet.\n mkdirSync(dirname(MACOS_PLIST), { recursive: true });\n // 0o600 — plist embeds AGT_API_KEY in EnvironmentVariables. World-\n // readable would expose the host's tlk_ token to every local user.\n writeFileSync(MACOS_PLIST, renderMacosPlist(opts), { mode: 0o600 });\n chmodSync(MACOS_PLIST, 0o600);\n\n try {\n execFileSync('launchctl', ['load', '-w', MACOS_PLIST], { stdio: 'pipe' });\n } catch (err) {\n return { ok: false, error: `launchctl load failed: ${(err as Error).message}` };\n }\n\n // Verify launchd actually picked it up. `list <label>` returns 0 with\n // a plist of the loaded job's metadata; non-zero if not loaded.\n try {\n const out = execFileSync('launchctl', ['list', MACOS_LABEL], { encoding: 'utf-8' });\n return {\n ok: true,\n details: `Loaded launchd LaunchAgent ${MACOS_LABEL}. Logs: ${join(opts.configDir, 'manager.log')}.\\n${out.trim().split('\\n').slice(0, 10).join('\\n')}`,\n };\n } catch (err) {\n return { ok: false, error: `Plist written but launchctl list reported nothing for ${MACOS_LABEL}: ${(err as Error).message}` };\n }\n}\n\nfunction uninstallMacos(): { ok: true; details: string } | { ok: false; error: string } {\n // Both steps are idempotent — unload reports an error if nothing's\n // loaded, removing the file errors if it doesn't exist. Swallow both;\n // the desired end state is \"no LaunchAgent for this label\".\n bestEffort(() => execFileSync('launchctl', ['unload', '-w', MACOS_PLIST], { stdio: 'ignore' }));\n let removed = false;\n if (existsSync(MACOS_PLIST)) {\n try {\n unlinkSync(MACOS_PLIST);\n removed = true;\n } catch (err) {\n return { ok: false, error: `Failed to remove ${MACOS_PLIST}: ${(err as Error).message}` };\n }\n }\n return {\n ok: true,\n details: removed\n ? `Removed ${MACOS_LABEL} from launchd and deleted ${MACOS_PLIST}.`\n : `${MACOS_LABEL} was already uninstalled (no plist at ${MACOS_PLIST}).`,\n };\n}\n\nfunction statusMacos(): SupervisorPresence {\n if (!existsSync(MACOS_PLIST)) return { kind: 'not-installed' };\n // launchctl list emits a 3-column line: PID Status Label. PID is \"-\"\n // when the job is loaded but not currently running.\n try {\n const out = execFileSync('launchctl', ['list', MACOS_LABEL], { encoding: 'utf-8' });\n const pidMatch = /\"PID\"\\s*=\\s*(\\d+);/.exec(out);\n const pid = pidMatch ? Number(pidMatch[1]) : null;\n return { kind: 'installed', pid, details: `Plist: ${MACOS_PLIST}` };\n } catch {\n // File exists but launchctl can't find the label → user removed it\n // out-of-band. Surface as \"not installed\" so re-install just works.\n return { kind: 'not-installed' };\n }\n}\n\nfunction renderMacosPlist(opts: InstallOpts): string {\n // Load the operator's env into the plist so the manager has the same\n // AGT_HOST / AGT_API_KEY / AGT_TEAM the shell session does. launchd\n // does NOT inherit env from the user's shell — anything we don't bake\n // in here won't be visible to the process.\n const envEntries = Object.entries(opts.env)\n .filter(([k, v]) => k.length > 0 && v != null)\n .map(([k, v]) => ` <key>${escapeXml(k)}</key>\\n <string>${escapeXml(v)}</string>`)\n .join('\\n');\n\n const args = [\n 'manager',\n 'start',\n '--interval',\n String(opts.intervalSec),\n '--config-dir',\n opts.configDir,\n ];\n const argsXml = args.map((a) => ` <string>${escapeXml(a)}</string>`).join('\\n');\n\n const logPath = join(opts.configDir, 'manager.log');\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${MACOS_LABEL}</string>\n\n <key>ProgramArguments</key>\n <array>\n <string>${escapeXml(opts.agtBin)}</string>\n${argsXml}\n </array>\n\n <key>RunAtLoad</key>\n <true/>\n\n <key>KeepAlive</key>\n <true/>\n\n <!-- Throttle restarts so a crashloop doesn't peg the CPU. 10 seconds\n between launches is enough room for transient API blips while\n still recovering quickly from a real crash. -->\n <key>ThrottleInterval</key>\n <integer>10</integer>\n\n <!-- Where the manager's stdout / stderr land. The manager's logger\n redirects stderr into manager.log itself, but launchd needs an\n explicit destination at the OS level for any pre-logger output\n (e.g., Node startup errors before the watchdog wires up). -->\n <key>StandardOutPath</key>\n <string>${escapeXml(logPath)}</string>\n <key>StandardErrorPath</key>\n <string>${escapeXml(logPath)}</string>\n\n <key>WorkingDirectory</key>\n <string>${escapeXml(opts.configDir)}</string>\n\n <key>EnvironmentVariables</key>\n <dict>\n${envEntries}\n </dict>\n</dict>\n</plist>\n`;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction bestEffort(fn: () => void): void {\n try { fn(); } catch { /* swallow */ }\n}\n\nfunction escapeXml(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n// ---------------------------------------------------------------------------\n// Linux — systemd --user unit\n// ---------------------------------------------------------------------------\n\nfunction installLinux(opts: InstallOpts): { ok: true; details: string } | { ok: false; error: string } {\n if (!existsSync(opts.agtBin)) {\n return { ok: false, error: `agt binary not found at ${opts.agtBin}` };\n }\n if (opts.intervalSec < 5) {\n return { ok: false, error: 'intervalSec must be >= 5' };\n }\n if (!opts.env.AGT_HOST || !opts.env.AGT_API_KEY) {\n return { ok: false, error: 'AGT_HOST and AGT_API_KEY must be set in the calling shell so the supervisor can pass them to the unit. Run `agt setup <token>` first.' };\n }\n\n // Stop any previous instance before rewriting the unit — saves a\n // restart loop while daemon-reload picks up the new file.\n bestEffort(() => execFileSync('systemctl', ['--user', 'stop', LINUX_UNIT_NAME], { stdio: 'ignore' }));\n\n // ~/.config/systemd/user/ is the canonical user-unit path. Create it\n // recursively in case this is a fresh user with no XDG layout yet.\n mkdirSync(dirname(LINUX_UNIT_PATH), { recursive: true, mode: 0o700 });\n // Write the secrets-only env file FIRST (mode 0600) so the unit can\n // reference it via EnvironmentFile=. Non-secret env stays in the\n // unit body via Environment= lines for visibility.\n writeFileSync(LINUX_ENV_FILE_PATH, renderLinuxEnvFile(opts), { mode: 0o600 });\n chmodSync(LINUX_ENV_FILE_PATH, 0o600);\n writeFileSync(LINUX_UNIT_PATH, renderLinuxUnit(opts), { mode: 0o600 });\n chmodSync(LINUX_UNIT_PATH, 0o600);\n\n try {\n execFileSync('systemctl', ['--user', 'daemon-reload'], { stdio: 'pipe' });\n } catch (err) {\n return { ok: false, error: `systemctl --user daemon-reload failed: ${(err as Error).message}` };\n }\n\n // `enable --now` enables the unit at boot AND starts it immediately.\n // Surviving reboot on a headless host additionally requires\n // `loginctl enable-linger <user>` (root-only); we surface that as a\n // post-install hint rather than running it ourselves.\n try {\n execFileSync('systemctl', ['--user', 'enable', '--now', LINUX_UNIT_NAME], { stdio: 'pipe' });\n } catch (err) {\n return { ok: false, error: `systemctl --user enable --now failed: ${(err as Error).message}. (Hint: 'systemctl --user' requires a per-user dbus session; on a fresh SSH login try 'export XDG_RUNTIME_DIR=/run/user/$(id -u)' first.)` };\n }\n\n let isActive = '';\n try {\n isActive = execFileSync('systemctl', ['--user', 'is-active', LINUX_UNIT_NAME], { encoding: 'utf-8' }).trim();\n } catch (err) {\n // is-active exits non-zero for inactive/failed states. Capture its\n // output so the operator sees the real status.\n isActive = ((err as { stdout?: Buffer; stderr?: Buffer }).stdout?.toString() ?? '').trim() || 'unknown';\n }\n\n // Don't claim the install succeeded if the unit ended up failed /\n // inactive / unknown. Without this, the CLI would exit 0 with a\n // green \"supervisor installed\" message while the manager was\n // already broken.\n if (isActive !== 'active') {\n return {\n ok: false,\n error: `systemd loaded ${LINUX_UNIT_NAME} but it did not become active (status: ${isActive}). Run 'systemctl --user status ${LINUX_UNIT_NAME}' or 'journalctl --user -u ${LINUX_UNIT_NAME} -n 50' for details.`,\n };\n }\n\n return {\n ok: true,\n details: `Loaded systemd --user unit ${LINUX_UNIT_NAME} (status: ${isActive}). Logs: ${join(opts.configDir, 'manager.log')}.\\nFor reboot survival on a headless host run as root: 'loginctl enable-linger ${process.env['USER'] ?? '<your-user>'}'`,\n };\n}\n\nfunction uninstallLinux(): { ok: true; details: string } | { ok: false; error: string } {\n // disable --now stops + un-enables in one shot. Both legs are idempotent\n // — disable on a non-existent unit returns 0 with a notice on stderr.\n bestEffort(() => execFileSync('systemctl', ['--user', 'disable', '--now', LINUX_UNIT_NAME], { stdio: 'ignore' }));\n\n let removed = false;\n if (existsSync(LINUX_UNIT_PATH)) {\n try {\n unlinkSync(LINUX_UNIT_PATH);\n removed = true;\n } catch (err) {\n return { ok: false, error: `Failed to remove ${LINUX_UNIT_PATH}: ${(err as Error).message}` };\n }\n }\n // Best-effort cleanup of the secrets-only env file too; we don't\n // want a stale AGT_API_KEY left on disk after uninstall.\n if (existsSync(LINUX_ENV_FILE_PATH)) {\n bestEffort(() => unlinkSync(LINUX_ENV_FILE_PATH));\n }\n\n // Reload so a future install with the same path doesn't reuse the\n // stale unit metadata systemd cached in memory.\n bestEffort(() => execFileSync('systemctl', ['--user', 'daemon-reload'], { stdio: 'ignore' }));\n\n return {\n ok: true,\n details: removed\n ? `Disabled systemd --user unit ${LINUX_UNIT_NAME} and deleted ${LINUX_UNIT_PATH}.`\n : `${LINUX_UNIT_NAME} was already uninstalled (no unit file at ${LINUX_UNIT_PATH}).`,\n };\n}\n\nfunction statusLinux(): SupervisorPresence {\n if (!existsSync(LINUX_UNIT_PATH)) return { kind: 'not-installed' };\n let pid: number | null = null;\n let activeState = 'unknown';\n try {\n const out = execFileSync(\n 'systemctl',\n ['--user', 'show', LINUX_UNIT_NAME, '--property=MainPID,ActiveState'],\n { encoding: 'utf-8' },\n );\n const pidMatch = /^MainPID=(\\d+)/m.exec(out);\n if (pidMatch && pidMatch[1] !== '0') pid = Number(pidMatch[1]);\n const stateMatch = /^ActiveState=(\\S+)/m.exec(out);\n if (stateMatch) activeState = stateMatch[1] ?? 'unknown';\n } catch (err) {\n // The unit file exists but `systemctl --user` couldn't probe it\n // — most often because XDG_RUNTIME_DIR / the per-user dbus isn't\n // available in this shell. Don't lie to the operator about\n // whether the supervisor is installed; report 'installed,\n // unknown state' instead.\n return {\n kind: 'installed',\n pid: null,\n details: `Unit: ${LINUX_UNIT_PATH} (could not query systemd --user: ${(err as Error).message})`,\n };\n }\n return { kind: 'installed', pid, details: `Unit: ${LINUX_UNIT_PATH} (${activeState})` };\n}\n\n// Secrets that go into EnvironmentFile= instead of inline Environment=.\n// Anything in this set is written to LINUX_ENV_FILE_PATH (mode 0600)\n// and stripped from the unit body. Public env (PATH, AGT_HOST, AGT_TEAM)\n// stays inline for visibility in `systemctl show`.\nconst LINUX_SECRET_ENV_KEYS: ReadonlySet<string> = new Set(['AGT_API_KEY']);\n\nfunction renderLinuxUnit(opts: InstallOpts): string {\n // Non-secret env stays in the unit body via Environment= lines;\n // secrets are pulled from the EnvironmentFile= written separately.\n // systemd parses Environment= with a peculiar grammar — quotes are\n // optional but values can't contain literal newlines. We trust the\n // env values we forward and quote everything to be safe with spaces.\n const envLines = Object.entries(opts.env)\n .filter(([k, v]) => k.length > 0 && v != null && !LINUX_SECRET_ENV_KEYS.has(k))\n .map(([k, v]) => `Environment=\"${k}=${escapeForSystemdEnv(v)}\"`)\n .join('\\n');\n\n // ExecStart cannot use shell metacharacters; pass the args explicitly\n // via systemd's array-of-args style (newline-separated wouldn't\n // parse — systemd splits on whitespace within ExecStart). So we\n // shell-quote each arg and join.\n const execArgs = [\n opts.agtBin,\n 'manager',\n 'start',\n '--interval',\n String(opts.intervalSec),\n '--config-dir',\n opts.configDir,\n ]\n .map(shellQuoteForSystemd)\n .join(' ');\n\n const logPath = join(opts.configDir, 'manager.log');\n\n return `# agt manager supervisor (ENG-4593)\n# Managed by \\`agt manager install\\` — edits will be overwritten.\n\n[Unit]\nDescription=Augmented host manager daemon\nAfter=network-online.target\nWants=network-online.target\n# Restart rate-limit lives here per systemd.unit(5). Older systemds\n# tolerated these directives in the service section but newer ones\n# silently ignore them there, leaving the crashloop unprotected.\nStartLimitBurst=5\nStartLimitIntervalSec=60\n\n[Service]\nType=simple\nWorkingDirectory=${opts.configDir}\n${envLines}\nEnvironmentFile=${LINUX_ENV_FILE_PATH}\nExecStart=${execArgs}\n\n# Always come back from any exit; back off 5s between launches so a\n# crashloop can't peg the CPU. The 5/60s window above caps total\n# attempts before systemd marks the unit failed.\nRestart=always\nRestartSec=5\n\n# stdout/stderr → manager.log. journalctl --user -u agt-manager\n# still captures everything; this just gives operators a single file\n# to tail without learning systemd plumbing.\nStandardOutput=append:${logPath}\nStandardError=append:${logPath}\n\n[Install]\nWantedBy=default.target\n`;\n}\n\n/**\n * Render the secrets-only env file referenced by EnvironmentFile= in\n * the unit. Format: `KEY=VALUE` per line (systemd's EnvironmentFile\n * parser doesn't support quoting the value the way Environment= does,\n * but it tolerates literal characters as long as the value has no\n * newline). One key per line; trailing newline.\n */\nfunction renderLinuxEnvFile(opts: InstallOpts): string {\n return Object.entries(opts.env)\n .filter(([k, v]) => LINUX_SECRET_ENV_KEYS.has(k) && v != null)\n .map(([k, v]) => `${k}=${v}\\n`)\n .join('');\n}\n\nfunction escapeForSystemdEnv(value: string): string {\n // Inside an Environment=\"K=V\" line, \" and \\\\ need escaping. Newlines\n // would terminate the directive — reject them upstream.\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n\nfunction shellQuoteForSystemd(arg: string): string {\n // systemd's ExecStart parser supports double-quoted strings with\n // backslash escapes, similar to a POSIX shell but no command\n // substitution. Wrap any arg containing whitespace or shell metas.\n if (/^[A-Za-z0-9_./:=-]+$/.test(arg)) return arg;\n return `\"${arg.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n}\n\n// ---------------------------------------------------------------------------\n// Linux — systemd system unit (ENG-4706)\n// ---------------------------------------------------------------------------\n//\n// The `--user` unit above survives reboot only if `loginctl enable-linger`\n// is set per-user. On headless EC2 hosts that's a footgun: a reboot (kernel\n// patch, instance-type change, AWS-initiated maintenance) silently takes\n// every agent on the host offline until an operator manually re-launches\n// the manager. The system unit lives at /etc/systemd/system/, runs as root,\n// and is enabled into multi-user.target — so it comes up automatically at\n// boot just like any other service.\n//\n// Both unit kinds can co-exist; statusLinux() looks at the user one,\n// systemUnitStatus() looks at the system one. The CLI surfaces them as\n// `agt manager install` (user, dev workflow) and `agt manager\n// install-system-unit` (root, host-infra workflow) so the operator\n// chooses explicitly.\n\nconst LINUX_SYSTEM_UNIT_PATH = '/etc/systemd/system/agt-manager.service';\nconst LINUX_SYSTEM_ENV_FILE_PATH = '/etc/agt/agt-manager.env';\n\nexport interface InstallSystemUnitOpts extends InstallOpts {\n /**\n * Unix user the manager runs as. EC2 default is `root`. Other hosts\n * can run it as a less-privileged user, but the user must own\n * `configDir` and have permission to write to it. Defaults to `root`\n * when omitted (matches the ticket spec).\n */\n user?: string;\n}\n\nexport async function installSystemUnit(\n opts: InstallSystemUnitOpts,\n): Promise<{ ok: true; details: string } | { ok: false; error: string }> {\n if (platform() !== 'linux') {\n return {\n ok: false,\n error: `installSystemUnit is Linux-only (current platform: ${platform()}). For local dev on macOS use installSupervisor.`,\n };\n }\n if (process.getuid?.() !== 0) {\n return {\n ok: false,\n error: 'installSystemUnit requires root. Re-run with sudo, or call from the EC2 user-data bootstrap which already runs as root.',\n };\n }\n if (!existsSync(opts.agtBin)) {\n return { ok: false, error: `agt binary not found at ${opts.agtBin}` };\n }\n if (opts.intervalSec < 5) {\n return { ok: false, error: 'intervalSec must be >= 5' };\n }\n if (!opts.env.AGT_HOST || !opts.env.AGT_API_KEY) {\n return {\n ok: false,\n error: 'AGT_HOST and AGT_API_KEY must be set so the system unit can pass them through. Run `agt setup <token>` first (it writes them to /etc/environment, which this installer reads).',\n };\n }\n\n // Stop any running instance so daemon-reload picks up the rewritten\n // unit cleanly without a respawn race.\n bestEffort(() => execFileSync('systemctl', ['stop', LINUX_UNIT_NAME], { stdio: 'ignore' }));\n\n // Belt-and-braces (ENG-4706 backfill): kill any pre-existing manager\n // process that wasn't started via systemd. On hosts that were\n // bootstrapped before this PR, the manager runs nohup'd from a one-\n // shot SSM command. Installing the system unit without stopping that\n // older process leaves TWO managers polling Supabase simultaneously —\n // they race on agent ticks, double-inject channel messages, and\n // double-write audit_log rows. SIGTERM gives it 3s to wind down\n // cleanly before the systemd start grabs the supervisor seat.\n // Ignored on hosts that have no rogue manager (the typical fresh-\n // bootstrap path).\n bestEffort(() => {\n const out = execFileSync('pgrep', ['-f', 'agt manager start'], { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf-8' });\n const pids = out\n .split('\\n')\n .map((s) => s.trim())\n .filter((s) => s.length > 0 && /^\\d+$/.test(s) && Number(s) !== process.pid);\n if (pids.length === 0) return;\n for (const pid of pids) {\n bestEffort(() => process.kill(Number(pid), 'SIGTERM'));\n }\n // Brief settle so the just-killed manager releases its Supabase\n // long-polls before the new one connects. 3s matches the default\n // poll interval; a manager that hasn't shut down in that window\n // gets SIGKILLed below.\n const deadline = Date.now() + 3_000;\n while (Date.now() < deadline) {\n try {\n execFileSync('pgrep', ['-f', 'agt manager start'], { stdio: 'ignore' });\n } catch {\n return;\n }\n // Spin — busy-wait is fine for a 3s ceiling and avoids pulling in\n // a sleep helper. This path runs once at install, never on the\n // hot poll loop.\n }\n // Still alive — escalate.\n for (const pid of pids) {\n bestEffort(() => process.kill(Number(pid), 'SIGKILL'));\n }\n });\n\n // Secrets-only env file lives under /etc/agt/ (root:root, 0600). Same\n // rationale as the user-unit env file: keep AGT_API_KEY out of any\n // tool that reads systemd's parsed unit cache.\n mkdirSync(dirname(LINUX_SYSTEM_ENV_FILE_PATH), { recursive: true, mode: 0o700 });\n writeFileSync(LINUX_SYSTEM_ENV_FILE_PATH, renderLinuxEnvFile(opts), { mode: 0o600 });\n chmodSync(LINUX_SYSTEM_ENV_FILE_PATH, 0o600);\n writeFileSync(LINUX_SYSTEM_UNIT_PATH, renderLinuxSystemUnit(opts), { mode: 0o644 });\n chmodSync(LINUX_SYSTEM_UNIT_PATH, 0o644);\n\n try {\n execFileSync('systemctl', ['daemon-reload'], { stdio: 'pipe' });\n } catch (err) {\n return { ok: false, error: `systemctl daemon-reload failed: ${(err as Error).message}` };\n }\n\n // `enable --now` enables at boot AND starts immediately. Unlike the\n // --user variant, this needs no enable-linger — multi-user.target\n // pulls us in regardless of any user session.\n try {\n execFileSync('systemctl', ['enable', '--now', LINUX_UNIT_NAME], { stdio: 'pipe' });\n } catch (err) {\n return { ok: false, error: `systemctl enable --now failed: ${(err as Error).message}` };\n }\n\n let isActive = '';\n try {\n isActive = execFileSync('systemctl', ['is-active', LINUX_UNIT_NAME], { encoding: 'utf-8' }).trim();\n } catch (err) {\n isActive = ((err as { stdout?: Buffer; stderr?: Buffer }).stdout?.toString() ?? '').trim() || 'unknown';\n }\n\n if (isActive !== 'active') {\n return {\n ok: false,\n error: `systemd loaded ${LINUX_UNIT_NAME} but it did not become active (status: ${isActive}). Run 'systemctl status ${LINUX_UNIT_NAME}' or 'journalctl -u ${LINUX_UNIT_NAME} -n 50' for details.`,\n };\n }\n\n return {\n ok: true,\n details: `Loaded systemd system unit ${LINUX_UNIT_NAME} at ${LINUX_SYSTEM_UNIT_PATH} (status: ${isActive}). Will auto-start on reboot via multi-user.target. Logs: ${join(opts.configDir, 'manager.log')} and 'journalctl -u ${LINUX_UNIT_NAME}'.`,\n };\n}\n\nexport async function uninstallSystemUnit(): Promise<{ ok: true; details: string } | { ok: false; error: string }> {\n if (platform() !== 'linux') {\n return { ok: false, error: `uninstallSystemUnit is Linux-only (current platform: ${platform()}).` };\n }\n if (process.getuid?.() !== 0) {\n return { ok: false, error: 'uninstallSystemUnit requires root.' };\n }\n\n bestEffort(() => execFileSync('systemctl', ['disable', '--now', LINUX_UNIT_NAME], { stdio: 'ignore' }));\n\n let removed = false;\n if (existsSync(LINUX_SYSTEM_UNIT_PATH)) {\n try {\n unlinkSync(LINUX_SYSTEM_UNIT_PATH);\n removed = true;\n } catch (err) {\n return { ok: false, error: `Failed to remove ${LINUX_SYSTEM_UNIT_PATH}: ${(err as Error).message}` };\n }\n }\n if (existsSync(LINUX_SYSTEM_ENV_FILE_PATH)) {\n bestEffort(() => unlinkSync(LINUX_SYSTEM_ENV_FILE_PATH));\n }\n\n bestEffort(() => execFileSync('systemctl', ['daemon-reload'], { stdio: 'ignore' }));\n\n return {\n ok: true,\n details: removed\n ? `Disabled systemd system unit ${LINUX_UNIT_NAME} and deleted ${LINUX_SYSTEM_UNIT_PATH}.`\n : `${LINUX_UNIT_NAME} system unit was already uninstalled (no unit file at ${LINUX_SYSTEM_UNIT_PATH}).`,\n };\n}\n\nexport function systemUnitStatus(): SupervisorPresence {\n if (platform() !== 'linux') {\n return { kind: 'unsupported-platform', platform: platform() };\n }\n if (!existsSync(LINUX_SYSTEM_UNIT_PATH)) return { kind: 'not-installed' };\n let pid: number | null = null;\n let activeState = 'unknown';\n try {\n const out = execFileSync(\n 'systemctl',\n ['show', LINUX_UNIT_NAME, '--property=MainPID,ActiveState'],\n { encoding: 'utf-8' },\n );\n const pidMatch = /^MainPID=(\\d+)/m.exec(out);\n if (pidMatch && pidMatch[1] !== '0') pid = Number(pidMatch[1]);\n const stateMatch = /^ActiveState=(\\S+)/m.exec(out);\n if (stateMatch) activeState = stateMatch[1] ?? 'unknown';\n } catch (err) {\n return {\n kind: 'installed',\n pid: null,\n details: `Unit: ${LINUX_SYSTEM_UNIT_PATH} (could not query systemd: ${(err as Error).message})`,\n };\n }\n return { kind: 'installed', pid, details: `Unit: ${LINUX_SYSTEM_UNIT_PATH} (${activeState})` };\n}\n\nfunction renderLinuxSystemUnit(opts: InstallSystemUnitOpts): string {\n const user = opts.user ?? 'root';\n const home = user === 'root' ? '/root' : `/home/${user}`;\n\n // Non-secret env stays in the unit body via Environment= lines;\n // secrets are pulled from EnvironmentFile= written separately.\n const envLines = Object.entries(opts.env)\n .filter(([k, v]) => k.length > 0 && v != null && !LINUX_SECRET_ENV_KEYS.has(k))\n .map(([k, v]) => `Environment=\"${k}=${escapeForSystemdEnv(v)}\"`)\n .join('\\n');\n\n const execArgs = [\n opts.agtBin,\n 'manager',\n 'start',\n '--interval',\n String(opts.intervalSec),\n '--config-dir',\n opts.configDir,\n ]\n .map(shellQuoteForSystemd)\n .join(' ');\n\n const logPath = join(opts.configDir, 'manager.log');\n\n return `# agt manager supervisor — system unit (ENG-4706)\n# Managed by \\`agt manager install-system-unit\\` — edits will be overwritten.\n#\n# Unlike the sibling --user unit at ~/.config/systemd/user/agt-manager.service,\n# this one is enabled into multi-user.target so it auto-starts on every\n# boot regardless of any user login. Use this on EC2 / headless hosts.\n\n[Unit]\nDescription=Augmented host manager daemon\nAfter=network-online.target\nWants=network-online.target\nStartLimitBurst=5\nStartLimitIntervalSec=60\n\n[Service]\nType=simple\nUser=${user}\nWorkingDirectory=${opts.configDir}\nEnvironment=\"HOME=${home}\"\n${envLines}\nEnvironmentFile=${LINUX_SYSTEM_ENV_FILE_PATH}\nExecStart=${execArgs}\n\n# on-failure (not always) so a clean \\`systemctl stop\\` doesn't fight a\n# respawn loop. Matches the ticket spec; the 5/60s window above caps a\n# crashloop. Logs land in ${logPath} via the manager's own writer plus\n# journalctl -u ${LINUX_UNIT_NAME}.\nRestart=on-failure\nRestartSec=5\n\nStandardOutput=append:${logPath}\nStandardError=append:${logPath}\n\n[Install]\nWantedBy=multi-user.target\n`;\n}\n\n// Exposed for unit tests / introspection.\nexport const _internals = {\n MACOS_LABEL,\n MACOS_PLIST,\n LINUX_UNIT_NAME,\n LINUX_UNIT_PATH,\n LINUX_ENV_FILE_PATH,\n LINUX_SYSTEM_UNIT_PATH,\n LINUX_SYSTEM_ENV_FILE_PATH,\n LINUX_SECRET_ENV_KEYS,\n renderMacosPlist,\n renderLinuxUnit,\n renderLinuxSystemUnit,\n renderLinuxEnvFile,\n escapeXml,\n escapeForSystemdEnv,\n shellQuoteForSystemd,\n readPlist: () => (existsSync(MACOS_PLIST) ? readFileSync(MACOS_PLIST, 'utf-8') : null),\n readUnit: () => (existsSync(LINUX_UNIT_PATH) ? readFileSync(LINUX_UNIT_PATH, 'utf-8') : null),\n readSystemUnit: () => (existsSync(LINUX_SYSTEM_UNIT_PATH) ? readFileSync(LINUX_SYSTEM_UNIT_PATH, 'utf-8') : null),\n readEnvFile: () => (existsSync(LINUX_ENV_FILE_PATH) ? readFileSync(LINUX_ENV_FILE_PATH, 'utf-8') : null),\n readSystemEnvFile: () => (existsSync(LINUX_SYSTEM_ENV_FILE_PATH) ? readFileSync(LINUX_SYSTEM_ENV_FILE_PATH, 'utf-8') : null),\n};\n"],"mappings":"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","names":[]}
|