(plan: CodexNativeApiDaemonInstallPlan)
| 546 | } |
| 547 | |
| 548 | async function installDaemon(plan: CodexNativeApiDaemonInstallPlan): Promise<void> { |
| 549 | await ensureDaemonDirectories(plan.layout); |
| 550 | await fsp.writeFile(plan.layout.envFile, plan.serviceEnvFileContent, 'utf8'); |
| 551 | |
| 552 | switch (plan.layout.platform) { |
| 553 | case 'darwin': |
| 554 | await fsp.writeFile(plan.layout.launchdPlistPath!, plan.artifactContent ?? '', 'utf8'); |
| 555 | await runCommand('launchctl', ['bootout', `gui/${process.getuid?.() ?? 0}`, plan.layout.launchdPlistPath!], { allowFailure: true }); |
| 556 | await runCommand('launchctl', ['bootstrap', `gui/${process.getuid?.() ?? 0}`, plan.layout.launchdPlistPath!]); |
| 557 | await runCommand('launchctl', ['enable', `gui/${process.getuid?.() ?? 0}/${plan.layout.launchdLabel!}`]); |
| 558 | await runCommand('launchctl', ['kickstart', '-k', `gui/${process.getuid?.() ?? 0}/${plan.layout.launchdLabel!}`]); |
| 559 | return; |
| 560 | case 'linux': |
| 561 | await fsp.mkdir(path.dirname(plan.layout.systemdUnitPath!), { recursive: true }); |
| 562 | await fsp.writeFile(plan.layout.systemdUnitPath!, plan.artifactContent ?? '', 'utf8'); |
| 563 | await runCommand('systemctl', ['--user', 'daemon-reload']); |
| 564 | await runCommand('systemctl', ['--user', 'enable', '--now', plan.layout.systemdServiceName!]); |
| 565 | if (await commandExists('loginctl')) { |
| 566 | await runCommand('loginctl', ['enable-linger', resolveUserName(process.env)], { allowFailure: true }); |
| 567 | } |
| 568 | return; |
| 569 | case 'win32': |
| 570 | await runPowerShellScript(buildWindowsInstallScript(plan)); |
| 571 | return; |
| 572 | default: |
| 573 | throw new Error(`Unsupported daemon platform: ${plan.layout.platform}`); |
| 574 | } |
| 575 | } |
| 576 | |
| 577 | async function startDaemon(): Promise<void> { |
| 578 | const layout = resolveDaemonLayout(); |
no test coverage detected