@algosuite/vo-mcp 0.2.0-beta.29 → 0.2.0-beta.30

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.
@@ -3,7 +3,7 @@ import { createRequire as __cr } from 'module'; const require = __cr(import.meta
3
3
 
4
4
  // src/autostart.ts
5
5
  import { homedir, platform } from "node:os";
6
- import { join } from "node:path";
6
+ import { isAbsolute, join } from "node:path";
7
7
  import { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync, copyFileSync } from "node:fs";
8
8
  var WINDOWS_RESTART_BACKOFF_MS = 1e4;
9
9
  var WINDOWS_HEALTHY_RUN_MS = 6e4;
@@ -11,6 +11,24 @@ var WINDOWS_MAX_BACKOFF_MS = 3e5;
11
11
  function resolveRunnerCommand(override) {
12
12
  return override ?? "vo-mcp runner";
13
13
  }
14
+ function quotePosixShellArgument(value) {
15
+ if (value.includes("\0") || value.includes("\r") || value.includes("\n")) {
16
+ throw new Error("Runner command must not contain NUL, carriage return, or newline characters.");
17
+ }
18
+ return `'${value.replace(/'/gu, `'"'"'`)}'`;
19
+ }
20
+ function resolveLinuxConfigHome(home, env) {
21
+ const configured = env["XDG_CONFIG_HOME"]?.trim();
22
+ return configured && isAbsolute(configured) ? configured : join(home, ".config");
23
+ }
24
+ function launcherIsCurrent(path, desiredContent, label, log) {
25
+ if (!existsSync(path)) return false;
26
+ if (readFileSync(path, "utf8") === desiredContent) return true;
27
+ const backupPath = `${path}.backup-${Date.now()}`;
28
+ copyFileSync(path, backupPath);
29
+ log(` Backed up existing ${label} to: ${backupPath}`);
30
+ return false;
31
+ }
14
32
  function installWindowsAutostart(runnerCommand, log, env) {
15
33
  const appData = env["APPDATA"] ?? join(homedir(), "AppData", "Roaming");
16
34
  const startupDir = join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
@@ -25,17 +43,6 @@ function installWindowsAutostart(runnerCommand, log, env) {
25
43
  log(`\u26A0 Could not remove legacy launcher ${legacyCmdPath} (${error instanceof Error ? error.message : String(error)}); remove it manually to avoid a double start`);
26
44
  }
27
45
  }
28
- if (existsSync(launcherPath)) {
29
- const existing = readFileSync(launcherPath, "utf8");
30
- if (existing.includes("vo-mcp runner")) {
31
- log(`\u2713 Auto-start is already configured (Windows Startup folder)`);
32
- log(` Path: ${launcherPath}`);
33
- return;
34
- }
35
- const backupPath = `${launcherPath}.backup-${Date.now()}`;
36
- copyFileSync(launcherPath, backupPath);
37
- log(` Backed up existing launcher to: ${backupPath}`);
38
- }
39
46
  const hiddenCommand = `cmd /c ${runnerCommand} >> "%USERPROFILE%\\.claude\\vo-runner.log" 2>&1`.replace(/"/g, '""');
40
47
  const launcherContent = `' Auto-start launcher for vo-mcp runner
41
48
  ' Created by vo-mcp autostart installer
@@ -45,6 +52,8 @@ function installWindowsAutostart(runnerCommand, log, env) {
45
52
  Dim sh, fso, stopFile, backoff, startedAt, ranMs
46
53
  Set sh = CreateObject("WScript.Shell")
47
54
  Set fso = CreateObject("Scripting.FileSystemObject")
55
+ sh.CurrentDirectory = sh.ExpandEnvironmentStrings("%USERPROFILE%")
56
+ sh.Environment("Process")("VO_CODE_RUNNER_CLONES_ROOT") = sh.ExpandEnvironmentStrings("%APPDATA%\\ai.algosuite.vo-runner\\clones")
48
57
  stopFile = sh.ExpandEnvironmentStrings("%USERPROFILE%\\.claude\\vo-runner.stop")
49
58
  backoff = ${WINDOWS_RESTART_BACKOFF_MS}
50
59
  Do
@@ -64,6 +73,11 @@ Do
64
73
  WScript.Sleep backoff
65
74
  Loop
66
75
  `;
76
+ if (launcherIsCurrent(launcherPath, launcherContent, "launcher", log)) {
77
+ log(`\u2713 Auto-start is already configured (Windows Startup folder)`);
78
+ log(` Path: ${launcherPath}`);
79
+ return;
80
+ }
67
81
  writeFileSync(launcherPath, launcherContent, "utf8");
68
82
  log(`\u2713 Installed Windows auto-start launcher`);
69
83
  log(` Path: ${launcherPath}`);
@@ -85,21 +99,11 @@ function uninstallWindowsAutostart(log, env) {
85
99
  log(`\u2713 Auto-start launcher not found (already removed)`);
86
100
  }
87
101
  }
88
- async function installMacAutostart(runnerCommand, log) {
89
- const launchAgentsDir = join(homedir(), "Library", "LaunchAgents");
102
+ async function installMacAutostart(runnerCommand, log, env) {
103
+ const home = env["HOME"]?.trim() || homedir();
104
+ const launchAgentsDir = join(home, "Library", "LaunchAgents");
90
105
  mkdirSync(launchAgentsDir, { recursive: true });
91
106
  const plistPath = join(launchAgentsDir, "ai.algosuite.vo-runner.plist");
92
- if (existsSync(plistPath)) {
93
- const existing = readFileSync(plistPath, "utf8");
94
- if (existing.includes("vo-mcp runner")) {
95
- log(`\u2713 Auto-start is already configured (launchd)`);
96
- log(` Path: ${plistPath}`);
97
- return;
98
- }
99
- const backupPath = `${plistPath}.backup-${Date.now()}`;
100
- copyFileSync(plistPath, backupPath);
101
- log(` Backed up existing plist to: ${backupPath}`);
102
- }
103
107
  const parts = runnerCommand.split(/\s+/);
104
108
  const program = parts[0] ?? "vo-mcp";
105
109
  const args = parts.length > 1 ? parts.slice(1) : ["runner"];
@@ -118,13 +122,25 @@ ${args.map((a) => ` <string>${a}</string>`).join("\n")}
118
122
  <true/>
119
123
  <key>KeepAlive</key>
120
124
  <true/>
125
+ <key>WorkingDirectory</key>
126
+ <string>${home}</string>
127
+ <key>EnvironmentVariables</key>
128
+ <dict>
129
+ <key>VO_CODE_RUNNER_CLONES_ROOT</key>
130
+ <string>${join(home, "Library", "Application Support", "ai.algosuite.vo-runner", "clones")}</string>
131
+ </dict>
121
132
  <key>StandardOutPath</key>
122
- <string>${join(homedir(), ".claude", "vo-runner.log")}</string>
133
+ <string>${join(home, ".claude", "vo-runner.log")}</string>
123
134
  <key>StandardErrorPath</key>
124
- <string>${join(homedir(), ".claude", "vo-runner-error.log")}</string>
135
+ <string>${join(home, ".claude", "vo-runner-error.log")}</string>
125
136
  </dict>
126
137
  </plist>
127
138
  `;
139
+ if (launcherIsCurrent(plistPath, plistContent, "plist", log)) {
140
+ log(`\u2713 Auto-start is already configured (launchd)`);
141
+ log(` Path: ${plistPath}`);
142
+ return;
143
+ }
128
144
  writeFileSync(plistPath, plistContent, "utf8");
129
145
  log(`\u2713 Installed launchd plist`);
130
146
  log(` Path: ${plistPath}`);
@@ -132,14 +148,15 @@ ${args.map((a) => ` <string>${a}</string>`).join("\n")}
132
148
  const { execSync } = await import("node:child_process");
133
149
  execSync(`launchctl load "${plistPath}"`, { stdio: "ignore" });
134
150
  log(`\u2713 Loaded plist with launchctl (runner will start at next login)`);
135
- log(` Logs: ${join(homedir(), ".claude", "vo-runner.log")}`);
151
+ log(` Logs: ${join(home, ".claude", "vo-runner.log")}`);
136
152
  } catch {
137
153
  log(`\u26A0 Failed to load plist with launchctl (you may need to load it manually)`);
138
154
  log(` Run: launchctl load "${plistPath}"`);
139
155
  }
140
156
  }
141
- async function uninstallMacAutostart(log) {
142
- const launchAgentsDir = join(homedir(), "Library", "LaunchAgents");
157
+ async function uninstallMacAutostart(log, env) {
158
+ const home = env["HOME"]?.trim() || homedir();
159
+ const launchAgentsDir = join(home, "Library", "LaunchAgents");
143
160
  const plistPath = join(launchAgentsDir, "ai.algosuite.vo-runner.plist");
144
161
  if (!existsSync(plistPath)) {
145
162
  log(`\u2713 Auto-start plist not found (already removed)`);
@@ -158,22 +175,13 @@ async function uninstallMacAutostart(log) {
158
175
  }
159
176
  async function installLinuxAutostart(runnerCommand, log, env) {
160
177
  const home = env["HOME"]?.trim() || homedir();
161
- const unitDir = join(home, ".config", "systemd", "user");
178
+ const configHome = resolveLinuxConfigHome(home, env);
179
+ const unitDir = join(configHome, "systemd", "user");
162
180
  mkdirSync(unitDir, { recursive: true });
163
181
  const unitPath = join(unitDir, "vo-runner.service");
164
- if (existsSync(unitPath)) {
165
- const existing = readFileSync(unitPath, "utf8");
166
- if (existing.includes(runnerCommand) || existing.includes("vo-mcp runner")) {
167
- log(`\u2713 Auto-start is already configured (systemd user unit)`);
168
- log(` Path: ${unitPath}`);
169
- return;
170
- }
171
- const backupPath = `${unitPath}.backup-${Date.now()}`;
172
- copyFileSync(unitPath, backupPath);
173
- log(` Backed up existing unit to: ${backupPath}`);
174
- }
175
182
  const logFile = join(home, ".claude", "vo-runner.log");
176
183
  const errFile = join(home, ".claude", "vo-runner-error.log");
184
+ const quotedRunnerCommand = quotePosixShellArgument(runnerCommand);
177
185
  mkdirSync(join(home, ".claude"), { recursive: true });
178
186
  const unit = `[Unit]
179
187
  Description=AlgoHQ Code Runner (vo-mcp)
@@ -182,7 +190,9 @@ Wants=network-online.target
182
190
 
183
191
  [Service]
184
192
  Type=simple
185
- ExecStart=/bin/sh -lc '${runnerCommand}'
193
+ WorkingDirectory=${home}
194
+ Environment="VO_CODE_RUNNER_CLONES_ROOT=${join(configHome, "ai.algosuite.vo-runner", "clones")}"
195
+ ExecStart=/bin/sh -lc ${quotedRunnerCommand}
186
196
  Restart=on-failure
187
197
  RestartSec=10
188
198
  StandardOutput=append:${logFile}
@@ -191,6 +201,11 @@ StandardError=append:${errFile}
191
201
  [Install]
192
202
  WantedBy=default.target
193
203
  `;
204
+ if (launcherIsCurrent(unitPath, unit, "unit", log)) {
205
+ log(`\u2713 Auto-start is already configured (systemd user unit)`);
206
+ log(` Path: ${unitPath}`);
207
+ return;
208
+ }
194
209
  writeFileSync(unitPath, unit, "utf8");
195
210
  log(`\u2713 Installed systemd user unit`);
196
211
  log(` Path: ${unitPath}`);
@@ -211,7 +226,8 @@ WantedBy=default.target
211
226
  }
212
227
  async function uninstallLinuxAutostart(log, env) {
213
228
  const home = env["HOME"]?.trim() || homedir();
214
- const unitPath = join(home, ".config", "systemd", "user", "vo-runner.service");
229
+ const configHome = resolveLinuxConfigHome(home, env);
230
+ const unitPath = join(configHome, "systemd", "user", "vo-runner.service");
215
231
  if (!existsSync(unitPath)) {
216
232
  log(`\u2713 Auto-start unit not found (already removed)`);
217
233
  return;
@@ -237,7 +253,7 @@ async function installAutostart(opts = {}) {
237
253
  if (plat === "win32") {
238
254
  installWindowsAutostart(runnerCommand, log, env);
239
255
  } else if (plat === "darwin") {
240
- await installMacAutostart(runnerCommand, log);
256
+ await installMacAutostart(runnerCommand, log, env);
241
257
  } else if (plat === "linux") {
242
258
  await installLinuxAutostart(runnerCommand, log, env);
243
259
  } else {
@@ -252,7 +268,7 @@ async function uninstallAutostart(opts = {}) {
252
268
  if (plat === "win32") {
253
269
  uninstallWindowsAutostart(log, env);
254
270
  } else if (plat === "darwin") {
255
- await uninstallMacAutostart(log);
271
+ await uninstallMacAutostart(log, env);
256
272
  } else if (plat === "linux") {
257
273
  await uninstallLinuxAutostart(log, env);
258
274
  } else {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/autostart.ts", "../src/autostart-cli.ts"],
4
- "sourcesContent": ["/**\n * Cross-platform auto-start registration for `vo-mcp runner`.\n *\n * WINDOWS: Uses the user Startup folder, NOT Task Scheduler. Headless\n * `claude -p` (which the runner spawns) HANGS under the Task Scheduler\n * service session \u2014 it only runs from an interactive, Explorer-descended\n * session. The Startup folder launches the runner HIDDEN at user login via a\n * .vbs shim (wscript is windowless; a .cmd launcher always parks a console on\n * the taskbar \u2014 `start /min` minimizes, it does not hide).\n *\n * MACOS: Uses ~/Library/LaunchAgents (launchd) with RunAtLoad + KeepAlive.\n *\n * LINUX: Uses ~/.config/systemd/user (systemd user unit) with Restart=on-failure;\n * ExecStart runs via a login shell so the npm-global `vo-mcp` resolves on PATH.\n *\n * All operations are idempotent and create backups where applicable.\n */\nimport { homedir, platform } from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync, copyFileSync } from 'node:fs';\n\nexport interface AutostartOptions {\n readonly log?: (msg: string) => void;\n readonly runnerCommand?: string; // Override for tests\n readonly env?: Readonly<Record<string, string | undefined>>;\n /**\n * Override the detected platform. Injectable ONLY so the Windows branch can be\n * exercised on a Linux CI runner \u2014 every Windows assertion in autostart.test.ts\n * used to early-return on ubuntu-latest, so no Windows autostart behaviour was\n * verified anywhere.\n */\n readonly platform?: NodeJS.Platform;\n}\n\n/**\n * Base restart backoff for the Windows keepalive loop \u2014 short enough that a real\n * crash recovers well within a heartbeat interval.\n */\nconst WINDOWS_RESTART_BACKOFF_MS = 10_000;\n\n/**\n * A run lasting at least this long counts as HEALTHY and resets the backoff.\n * Anything shorter is treated as a fast-fail and doubles the wait.\n */\nconst WINDOWS_HEALTHY_RUN_MS = 60_000;\n\n/**\n * Ceiling for the escalating backoff. Without one, a permanently broken runner\n * (missing credential, bad install) would relaunch every 10s forever \u2014 ~8,600\n * restarts a day, each appending to vo-runner.log. That is a disk-fill risk on a\n * machine nobody is watching, which is the whole premise here. launchd throttles\n * to a 10s floor and systemd has StartLimitBurst for the same reason.\n */\nconst WINDOWS_MAX_BACKOFF_MS = 300_000;\n\n/**\n * Resolve the path to the vo-mcp runner command. Defaults to 'vo-mcp runner'\n * (assumes it's in PATH). Can be overridden for tests.\n */\nfunction resolveRunnerCommand(override?: string): string {\n return override ?? 'vo-mcp runner';\n}\n\n/**\n * Windows: Install a launcher script in the Startup folder.\n *\n * Creates a .vbs file that starts `vo-mcp runner` with a hidden window\n * (WScript.Shell.Run window style 0 \u2014 wscript itself never shows a window,\n * unlike a .cmd whose console `start /min` only minimizes). The Startup\n * folder is %APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\.\n */\nfunction installWindowsAutostart(runnerCommand: string, log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): void {\n const appData = env['APPDATA'] ?? join(homedir(), 'AppData', 'Roaming');\n const startupDir = join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');\n mkdirSync(startupDir, { recursive: true });\n\n const launcherPath = join(startupDir, 'vo-runner.vbs');\n const legacyCmdPath = join(startupDir, 'vo-runner.cmd');\n\n // Migrate: drop the pre-.vbs minimized launcher so logon can't start two runners.\n // Best-effort \u2014 an ACL-blocked/locked .cmd must not prevent installing the .vbs.\n if (existsSync(legacyCmdPath)) {\n try {\n unlinkSync(legacyCmdPath);\n log(` Removed legacy minimized .cmd launcher: ${legacyCmdPath}`);\n } catch (error) {\n log(`\u26A0 Could not remove legacy launcher ${legacyCmdPath} (${error instanceof Error ? error.message : String(error)}); remove it manually to avoid a double start`);\n }\n }\n\n // Idempotent: if the launcher already exists with our content, skip\n if (existsSync(launcherPath)) {\n const existing = readFileSync(launcherPath, 'utf8');\n if (existing.includes('vo-mcp runner')) {\n log(`\u2713 Auto-start is already configured (Windows Startup folder)`);\n log(` Path: ${launcherPath}`);\n return;\n }\n // Backup if content differs\n const backupPath = `${launcherPath}.backup-${Date.now()}`;\n copyFileSync(launcherPath, backupPath);\n log(` Backed up existing launcher to: ${backupPath}`);\n }\n\n // Write the launcher. VBS escapes embedded double quotes by doubling them.\n // The hidden window discards stdio, so redirect the runner's output to the\n // same log file the macOS plist and Linux unit use \u2014 otherwise every\n // [orphan-sweep]/[orphan-reaper] warning on Windows lands nowhere.\n const hiddenCommand = `cmd /c ${runnerCommand} >> \"%USERPROFILE%\\\\.claude\\\\vo-runner.log\" 2>&1`.replace(/\"/g, '\"\"');\n // KEEPALIVE. Windows was the ONLY platform with no restart supervision: macOS\n // sets launchd `KeepAlive`, Linux sets systemd `Restart=on-failure`, and this\n // was `.Run(..., 0, False)` \u2014 fire-and-forget. If the runner died mid-session\n // nothing restarted it until the next logon, which is why a Windows host could\n // sit dead for hours (2026-07-25) with no way to reach it.\n //\n // `True` makes .Run WAIT for the process, turning this into a supervisor loop.\n // The sleep is a restart backoff so a runner failing instantly cannot spin hot.\n //\n // The stop-sentinel is the escape hatch: wscript has no console, so without it\n // the only way to stop the loop is Task Manager. The file is CONSUMED (deleted)\n // once honoured, so a later logon starts clean instead of silently refusing.\n const launcherContent = `' Auto-start launcher for vo-mcp runner\n' Created by vo-mcp autostart installer\n' Keepalive supervisor: restarts the runner if it exits (parity with launchd\n' KeepAlive on macOS and systemd Restart=on-failure on Linux).\n' To stop: create %USERPROFILE%\\\\.claude\\\\vo-runner.stop, or end wscript.exe.\nDim sh, fso, stopFile, backoff, startedAt, ranMs\nSet sh = CreateObject(\"WScript.Shell\")\nSet fso = CreateObject(\"Scripting.FileSystemObject\")\nstopFile = sh.ExpandEnvironmentStrings(\"%USERPROFILE%\\\\.claude\\\\vo-runner.stop\")\nbackoff = ${WINDOWS_RESTART_BACKOFF_MS}\nDo\n If fso.FileExists(stopFile) Then\n fso.DeleteFile stopFile\n WScript.Quit 0\n End If\n startedAt = Timer\n sh.Run \"${hiddenCommand}\", 0, True\n ranMs = (Timer - startedAt) * 1000\n If ranMs < 0 Then ranMs = ${WINDOWS_HEALTHY_RUN_MS}\n If ranMs >= ${WINDOWS_HEALTHY_RUN_MS} Then\n backoff = ${WINDOWS_RESTART_BACKOFF_MS}\n ElseIf backoff < ${WINDOWS_MAX_BACKOFF_MS} Then\n backoff = backoff * 2\n End If\n WScript.Sleep backoff\nLoop\n`;\n\n writeFileSync(launcherPath, launcherContent, 'utf8');\n log(`\u2713 Installed Windows auto-start launcher`);\n log(` Path: ${launcherPath}`);\n log(` The runner will start hidden at next login.`);\n}\n\n/**\n * Windows: Uninstall the Startup folder launcher.\n */\nfunction uninstallWindowsAutostart(log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): void {\n const appData = env['APPDATA'] ?? join(homedir(), 'AppData', 'Roaming');\n const startupDir = join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');\n // Remove the current .vbs launcher AND any legacy .cmd from older installs.\n const launcherPaths = [join(startupDir, 'vo-runner.vbs'), join(startupDir, 'vo-runner.cmd')];\n\n let removedAny = false;\n for (const launcherPath of launcherPaths) {\n if (!existsSync(launcherPath)) continue;\n unlinkSync(launcherPath);\n removedAny = true;\n log(`\u2713 Removed Windows auto-start launcher`);\n log(` Path: ${launcherPath}`);\n }\n if (!removedAny) {\n log(`\u2713 Auto-start launcher not found (already removed)`);\n }\n}\n\n/**\n * macOS: Install a launchd plist in ~/Library/LaunchAgents.\n *\n * The plist runs `vo-mcp runner` at login with RunAtLoad=true and\n * KeepAlive=true (restarts if it crashes).\n */\nasync function installMacAutostart(runnerCommand: string, log: (msg: string) => void): Promise<void> {\n const launchAgentsDir = join(homedir(), 'Library', 'LaunchAgents');\n mkdirSync(launchAgentsDir, { recursive: true });\n\n const plistPath = join(launchAgentsDir, 'ai.algosuite.vo-runner.plist');\n\n // Idempotent: if the plist already exists with our content, skip\n if (existsSync(plistPath)) {\n const existing = readFileSync(plistPath, 'utf8');\n if (existing.includes('vo-mcp runner')) {\n log(`\u2713 Auto-start is already configured (launchd)`);\n log(` Path: ${plistPath}`);\n return;\n }\n // Backup if content differs\n const backupPath = `${plistPath}.backup-${Date.now()}`;\n copyFileSync(plistPath, backupPath);\n log(` Backed up existing plist to: ${backupPath}`);\n }\n\n // Parse the runner command into program + args for launchd\n const parts = runnerCommand.split(/\\s+/);\n const program = parts[0] ?? 'vo-mcp';\n const args = parts.length > 1 ? parts.slice(1) : ['runner'];\n\n const plistContent = `<?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>ai.algosuite.vo-runner</string>\n <key>ProgramArguments</key>\n <array>\n <string>${program}</string>\n${args.map((a) => ` <string>${a}</string>`).join('\\n')}\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>${join(homedir(), '.claude', 'vo-runner.log')}</string>\n <key>StandardErrorPath</key>\n <string>${join(homedir(), '.claude', 'vo-runner-error.log')}</string>\n</dict>\n</plist>\n`;\n\n writeFileSync(plistPath, plistContent, 'utf8');\n log(`\u2713 Installed launchd plist`);\n log(` Path: ${plistPath}`);\n\n // Load the plist with launchctl\n try {\n const { execSync } = await import('node:child_process');\n execSync(`launchctl load \"${plistPath}\"`, { stdio: 'ignore' });\n log(`\u2713 Loaded plist with launchctl (runner will start at next login)`);\n log(` Logs: ${join(homedir(), '.claude', 'vo-runner.log')}`);\n } catch {\n log(`\u26A0 Failed to load plist with launchctl (you may need to load it manually)`);\n log(` Run: launchctl load \"${plistPath}\"`);\n }\n}\n\n/**\n * macOS: Uninstall the launchd plist.\n */\nasync function uninstallMacAutostart(log: (msg: string) => void): Promise<void> {\n const launchAgentsDir = join(homedir(), 'Library', 'LaunchAgents');\n const plistPath = join(launchAgentsDir, 'ai.algosuite.vo-runner.plist');\n\n if (!existsSync(plistPath)) {\n log(`\u2713 Auto-start plist not found (already removed)`);\n return;\n }\n\n // Unload the plist with launchctl\n try {\n const { execSync } = await import('node:child_process');\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: 'ignore' });\n log(`\u2713 Unloaded plist with launchctl`);\n } catch {\n log(`\u26A0 Failed to unload plist with launchctl (continuing anyway)`);\n }\n\n unlinkSync(plistPath);\n log(`\u2713 Removed launchd plist`);\n log(` Path: ${plistPath}`);\n}\n\n/**\n * Linux: Install a systemd USER unit at ~/.config/systemd/user/vo-runner.service,\n * then enable + start it (`systemctl --user enable --now`). Restart=on-failure\n * mirrors the macOS KeepAlive. ExecStart runs via a login shell so the npm-global\n * `vo-mcp` resolves under systemd's minimal PATH.\n */\nasync function installLinuxAutostart(\n runnerCommand: string,\n log: (msg: string) => void,\n env: Readonly<Record<string, string | undefined>>,\n): Promise<void> {\n const home = env['HOME']?.trim() || homedir();\n const unitDir = join(home, '.config', 'systemd', 'user');\n mkdirSync(unitDir, { recursive: true });\n const unitPath = join(unitDir, 'vo-runner.service');\n\n if (existsSync(unitPath)) {\n const existing = readFileSync(unitPath, 'utf8');\n if (existing.includes(runnerCommand) || existing.includes('vo-mcp runner')) {\n log(`\u2713 Auto-start is already configured (systemd user unit)`);\n log(` Path: ${unitPath}`);\n return;\n }\n const backupPath = `${unitPath}.backup-${Date.now()}`;\n copyFileSync(unitPath, backupPath);\n log(` Backed up existing unit to: ${backupPath}`);\n }\n\n const logFile = join(home, '.claude', 'vo-runner.log');\n const errFile = join(home, '.claude', 'vo-runner-error.log');\n mkdirSync(join(home, '.claude'), { recursive: true });\n\n const unit = `[Unit]\nDescription=AlgoHQ Code Runner (vo-mcp)\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=/bin/sh -lc '${runnerCommand}'\nRestart=on-failure\nRestartSec=10\nStandardOutput=append:${logFile}\nStandardError=append:${errFile}\n\n[Install]\nWantedBy=default.target\n`;\n writeFileSync(unitPath, unit, 'utf8');\n log(`\u2713 Installed systemd user unit`);\n log(` Path: ${unitPath}`);\n\n // In tests, write the unit but NEVER actually enable/start a real service.\n if (process.env['VITEST']) {\n log(` (test mode: skipping systemctl enable)`);\n return;\n }\n try {\n const { execSync } = await import('node:child_process');\n execSync('systemctl --user daemon-reload', { stdio: 'ignore' });\n execSync('systemctl --user enable --now vo-runner.service', { stdio: 'ignore' });\n log(`\u2713 Enabled + started vo-runner.service (starts at login)`);\n log(` Logs: ${logFile}`);\n } catch {\n log(`\u26A0 Could not enable via systemctl (enable it manually):`);\n log(` systemctl --user daemon-reload && systemctl --user enable --now vo-runner.service`);\n }\n}\n\n/**\n * Linux: Uninstall the systemd user unit.\n */\nasync function uninstallLinuxAutostart(\n log: (msg: string) => void,\n env: Readonly<Record<string, string | undefined>>,\n): Promise<void> {\n const home = env['HOME']?.trim() || homedir();\n const unitPath = join(home, '.config', 'systemd', 'user', 'vo-runner.service');\n if (!existsSync(unitPath)) {\n log(`\u2713 Auto-start unit not found (already removed)`);\n return;\n }\n if (!process.env['VITEST']) {\n try {\n const { execSync } = await import('node:child_process');\n execSync('systemctl --user disable --now vo-runner.service', { stdio: 'ignore' });\n log(`\u2713 Disabled + stopped vo-runner.service`);\n } catch {\n log(`\u26A0 Could not disable via systemctl (continuing anyway)`);\n }\n }\n unlinkSync(unitPath);\n log(`\u2713 Removed systemd user unit`);\n log(` Path: ${unitPath}`);\n}\n\n/**\n * Install auto-start for the runner daemon. Cross-platform.\n */\nexport async function installAutostart(opts: AutostartOptions = {}): Promise<void> {\n const log = opts.log ?? ((m: string) => console.error(m));\n const env = opts.env ?? process.env;\n const runnerCommand = resolveRunnerCommand(opts.runnerCommand);\n const plat = opts.platform ?? platform();\n\n if (plat === 'win32') {\n installWindowsAutostart(runnerCommand, log, env);\n } else if (plat === 'darwin') {\n await installMacAutostart(runnerCommand, log);\n } else if (plat === 'linux') {\n await installLinuxAutostart(runnerCommand, log, env);\n } else {\n log(`\u2717 Auto-start is not supported on platform: ${plat}`);\n log(` Supported platforms: win32 (Windows), darwin (macOS), linux (Linux)`);\n }\n}\n\n/**\n * Uninstall auto-start for the runner daemon. Cross-platform.\n */\nexport async function uninstallAutostart(opts: AutostartOptions = {}): Promise<void> {\n const log = opts.log ?? ((m: string) => console.error(m));\n const env = opts.env ?? process.env;\n const plat = opts.platform ?? platform();\n\n if (plat === 'win32') {\n uninstallWindowsAutostart(log, env);\n } else if (plat === 'darwin') {\n await uninstallMacAutostart(log);\n } else if (plat === 'linux') {\n await uninstallLinuxAutostart(log, env);\n } else {\n log(`\u2717 Auto-start is not supported on platform: ${plat}`);\n log(` Supported platforms: win32 (Windows), darwin (macOS), linux (Linux)`);\n }\n}\n", "#!/usr/bin/env node\n/**\n * `vo-mcp runner --install-autostart` / `--uninstall-autostart` CLI entrypoints.\n *\n * Registers or unregisters the runner daemon to start automatically at user login.\n */\nimport { installAutostart, uninstallAutostart } from './autostart.js';\n\nexport async function installAutostartCli(): Promise<void> {\n const log = (m: string): void => console.error(m);\n\n log('\u2501\u2501\u2501 vo-mcp runner auto-start installer \u2501\u2501\u2501\\n');\n\n await installAutostart({ log });\n\n log('\\nAuto-start is now configured. The runner will launch automatically at your next login.');\n log('To remove: vo-mcp runner --uninstall-autostart');\n}\n\nexport async function uninstallAutostartCli(): Promise<void> {\n const log = (m: string): void => console.error(m);\n\n log('\u2501\u2501\u2501 vo-mcp runner auto-start uninstaller \u2501\u2501\u2501\\n');\n\n await uninstallAutostart({ log });\n\n log('\\nAuto-start has been removed. The runner will no longer launch automatically.');\n log('To reinstall: vo-mcp runner --install-autostart');\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Cross-platform auto-start registration for `vo-mcp runner`.\n *\n * WINDOWS: Uses the user Startup folder, NOT Task Scheduler. Headless\n * `claude -p` (which the runner spawns) HANGS under the Task Scheduler\n * service session \u2014 it only runs from an interactive, Explorer-descended\n * session. The Startup folder launches the runner HIDDEN at user login via a\n * .vbs shim (wscript is windowless; a .cmd launcher always parks a console on\n * the taskbar \u2014 `start /min` minimizes, it does not hide).\n *\n * MACOS: Uses ~/Library/LaunchAgents (launchd) with RunAtLoad + KeepAlive.\n *\n * LINUX: Uses ~/.config/systemd/user (systemd user unit) with Restart=on-failure;\n * ExecStart runs via a login shell so the npm-global `vo-mcp` resolves on PATH.\n *\n * All operations are idempotent and create backups where applicable.\n */\nimport { homedir, platform } from 'node:os';\nimport { isAbsolute, join } from 'node:path';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync, copyFileSync } from 'node:fs';\n\nexport interface AutostartOptions {\n readonly log?: (msg: string) => void;\n readonly runnerCommand?: string; // Override for tests\n readonly env?: Readonly<Record<string, string | undefined>>;\n /**\n * Override the detected platform. Injectable ONLY so the Windows branch can be\n * exercised on a Linux CI runner \u2014 every Windows assertion in autostart.test.ts\n * used to early-return on ubuntu-latest, so no Windows autostart behaviour was\n * verified anywhere.\n */\n readonly platform?: NodeJS.Platform;\n}\n\n/**\n * Base restart backoff for the Windows keepalive loop \u2014 short enough that a real\n * crash recovers well within a heartbeat interval.\n */\nconst WINDOWS_RESTART_BACKOFF_MS = 10_000;\n\n/**\n * A run lasting at least this long counts as HEALTHY and resets the backoff.\n * Anything shorter is treated as a fast-fail and doubles the wait.\n */\nconst WINDOWS_HEALTHY_RUN_MS = 60_000;\n\n/**\n * Ceiling for the escalating backoff. Without one, a permanently broken runner\n * (missing credential, bad install) would relaunch every 10s forever \u2014 ~8,600\n * restarts a day, each appending to vo-runner.log. That is a disk-fill risk on a\n * machine nobody is watching, which is the whole premise here. launchd throttles\n * to a 10s floor and systemd has StartLimitBurst for the same reason.\n */\nconst WINDOWS_MAX_BACKOFF_MS = 300_000;\n\n/**\n * Resolve the path to the vo-mcp runner command. Defaults to 'vo-mcp runner'\n * (assumes it's in PATH). Can be overridden for tests.\n */\nfunction resolveRunnerCommand(override?: string): string {\n return override ?? 'vo-mcp runner';\n}\n\n/** Preserve one command string as a single POSIX shell argument. */\nfunction quotePosixShellArgument(value: string): string {\n if (value.includes('\\u0000') || value.includes('\\r') || value.includes('\\n')) {\n throw new Error('Runner command must not contain NUL, carriage return, or newline characters.');\n }\n return `'${value.replace(/'/gu, `'\"'\"'`)}'`;\n}\n\n/**\n * Resolve the freedesktop config root used by both the systemd user unit and\n * the runner's managed clone directory. XDG_CONFIG_HOME is valid only when it\n * is absolute; a relative value falls back to the documented ~/.config root.\n */\nfunction resolveLinuxConfigHome(\n home: string,\n env: Readonly<Record<string, string | undefined>>,\n): string {\n const configured = env['XDG_CONFIG_HOME']?.trim();\n return configured && isAbsolute(configured) ? configured : join(home, '.config');\n}\n\n/**\n * A managed launcher is current only when every byte matches the template.\n * Matching the command substring cannot distinguish an up-to-date launcher\n * from an older broken version that happens to invoke the same command.\n */\nfunction launcherIsCurrent(\n path: string,\n desiredContent: string,\n label: string,\n log: (msg: string) => void,\n): boolean {\n if (!existsSync(path)) return false;\n if (readFileSync(path, 'utf8') === desiredContent) return true;\n const backupPath = `${path}.backup-${Date.now()}`;\n copyFileSync(path, backupPath);\n log(` Backed up existing ${label} to: ${backupPath}`);\n return false;\n}\n\n/**\n * Windows: Install a launcher script in the Startup folder.\n *\n * Creates a .vbs file that starts `vo-mcp runner` with a hidden window\n * (WScript.Shell.Run window style 0 \u2014 wscript itself never shows a window,\n * unlike a .cmd whose console `start /min` only minimizes). The Startup\n * folder is %APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\.\n */\nfunction installWindowsAutostart(runnerCommand: string, log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): void {\n const appData = env['APPDATA'] ?? join(homedir(), 'AppData', 'Roaming');\n const startupDir = join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');\n mkdirSync(startupDir, { recursive: true });\n\n const launcherPath = join(startupDir, 'vo-runner.vbs');\n const legacyCmdPath = join(startupDir, 'vo-runner.cmd');\n\n // Migrate: drop the pre-.vbs minimized launcher so logon can't start two runners.\n // Best-effort \u2014 an ACL-blocked/locked .cmd must not prevent installing the .vbs.\n if (existsSync(legacyCmdPath)) {\n try {\n unlinkSync(legacyCmdPath);\n log(` Removed legacy minimized .cmd launcher: ${legacyCmdPath}`);\n } catch (error) {\n log(`\u26A0 Could not remove legacy launcher ${legacyCmdPath} (${error instanceof Error ? error.message : String(error)}); remove it manually to avoid a double start`);\n }\n }\n\n // Write the launcher. VBS escapes embedded double quotes by doubling them.\n // The hidden window discards stdio, so redirect the runner's output to the\n // same log file the macOS plist and Linux unit use \u2014 otherwise every\n // [orphan-sweep]/[orphan-reaper] warning on Windows lands nowhere.\n const hiddenCommand = `cmd /c ${runnerCommand} >> \"%USERPROFILE%\\\\.claude\\\\vo-runner.log\" 2>&1`.replace(/\"/g, '\"\"');\n // KEEPALIVE. Windows was the ONLY platform with no restart supervision: macOS\n // sets launchd `KeepAlive`, Linux sets systemd `Restart=on-failure`, and this\n // was `.Run(..., 0, False)` \u2014 fire-and-forget. If the runner died mid-session\n // nothing restarted it until the next logon, which is why a Windows host could\n // sit dead for hours (2026-07-25) with no way to reach it.\n //\n // `True` makes .Run WAIT for the process, turning this into a supervisor loop.\n // The sleep is a restart backoff so a runner failing instantly cannot spin hot.\n //\n // The stop-sentinel is the escape hatch: wscript has no console, so without it\n // the only way to stop the loop is Task Manager. The file is CONSUMED (deleted)\n // once honoured, so a later logon starts clean instead of silently refusing.\n const launcherContent = `' Auto-start launcher for vo-mcp runner\n' Created by vo-mcp autostart installer\n' Keepalive supervisor: restarts the runner if it exits (parity with launchd\n' KeepAlive on macOS and systemd Restart=on-failure on Linux).\n' To stop: create %USERPROFILE%\\\\.claude\\\\vo-runner.stop, or end wscript.exe.\nDim sh, fso, stopFile, backoff, startedAt, ranMs\nSet sh = CreateObject(\"WScript.Shell\")\nSet fso = CreateObject(\"Scripting.FileSystemObject\")\nsh.CurrentDirectory = sh.ExpandEnvironmentStrings(\"%USERPROFILE%\")\nsh.Environment(\"Process\")(\"VO_CODE_RUNNER_CLONES_ROOT\") = sh.ExpandEnvironmentStrings(\"%APPDATA%\\\\ai.algosuite.vo-runner\\\\clones\")\nstopFile = sh.ExpandEnvironmentStrings(\"%USERPROFILE%\\\\.claude\\\\vo-runner.stop\")\nbackoff = ${WINDOWS_RESTART_BACKOFF_MS}\nDo\n If fso.FileExists(stopFile) Then\n fso.DeleteFile stopFile\n WScript.Quit 0\n End If\n startedAt = Timer\n sh.Run \"${hiddenCommand}\", 0, True\n ranMs = (Timer - startedAt) * 1000\n If ranMs < 0 Then ranMs = ${WINDOWS_HEALTHY_RUN_MS}\n If ranMs >= ${WINDOWS_HEALTHY_RUN_MS} Then\n backoff = ${WINDOWS_RESTART_BACKOFF_MS}\n ElseIf backoff < ${WINDOWS_MAX_BACKOFF_MS} Then\n backoff = backoff * 2\n End If\n WScript.Sleep backoff\nLoop\n`;\n\n if (launcherIsCurrent(launcherPath, launcherContent, 'launcher', log)) {\n log(`\u2713 Auto-start is already configured (Windows Startup folder)`);\n log(` Path: ${launcherPath}`);\n return;\n }\n\n writeFileSync(launcherPath, launcherContent, 'utf8');\n log(`\u2713 Installed Windows auto-start launcher`);\n log(` Path: ${launcherPath}`);\n log(` The runner will start hidden at next login.`);\n}\n\n/**\n * Windows: Uninstall the Startup folder launcher.\n */\nfunction uninstallWindowsAutostart(log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): void {\n const appData = env['APPDATA'] ?? join(homedir(), 'AppData', 'Roaming');\n const startupDir = join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');\n // Remove the current .vbs launcher AND any legacy .cmd from older installs.\n const launcherPaths = [join(startupDir, 'vo-runner.vbs'), join(startupDir, 'vo-runner.cmd')];\n\n let removedAny = false;\n for (const launcherPath of launcherPaths) {\n if (!existsSync(launcherPath)) continue;\n unlinkSync(launcherPath);\n removedAny = true;\n log(`\u2713 Removed Windows auto-start launcher`);\n log(` Path: ${launcherPath}`);\n }\n if (!removedAny) {\n log(`\u2713 Auto-start launcher not found (already removed)`);\n }\n}\n\n/**\n * macOS: Install a launchd plist in ~/Library/LaunchAgents.\n *\n * The plist runs `vo-mcp runner` at login with RunAtLoad=true and\n * KeepAlive=true (restarts if it crashes).\n */\nasync function installMacAutostart(\n runnerCommand: string,\n log: (msg: string) => void,\n env: Readonly<Record<string, string | undefined>>,\n): Promise<void> {\n const home = env['HOME']?.trim() || homedir();\n const launchAgentsDir = join(home, 'Library', 'LaunchAgents');\n mkdirSync(launchAgentsDir, { recursive: true });\n\n const plistPath = join(launchAgentsDir, 'ai.algosuite.vo-runner.plist');\n\n // Parse the runner command into program + args for launchd\n const parts = runnerCommand.split(/\\s+/);\n const program = parts[0] ?? 'vo-mcp';\n const args = parts.length > 1 ? parts.slice(1) : ['runner'];\n\n const plistContent = `<?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>ai.algosuite.vo-runner</string>\n <key>ProgramArguments</key>\n <array>\n <string>${program}</string>\n${args.map((a) => ` <string>${a}</string>`).join('\\n')}\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>${home}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>VO_CODE_RUNNER_CLONES_ROOT</key>\n <string>${join(home, 'Library', 'Application Support', 'ai.algosuite.vo-runner', 'clones')}</string>\n </dict>\n <key>StandardOutPath</key>\n <string>${join(home, '.claude', 'vo-runner.log')}</string>\n <key>StandardErrorPath</key>\n <string>${join(home, '.claude', 'vo-runner-error.log')}</string>\n</dict>\n</plist>\n`;\n\n if (launcherIsCurrent(plistPath, plistContent, 'plist', log)) {\n log(`\u2713 Auto-start is already configured (launchd)`);\n log(` Path: ${plistPath}`);\n return;\n }\n\n writeFileSync(plistPath, plistContent, 'utf8');\n log(`\u2713 Installed launchd plist`);\n log(` Path: ${plistPath}`);\n\n // Load the plist with launchctl\n try {\n const { execSync } = await import('node:child_process');\n execSync(`launchctl load \"${plistPath}\"`, { stdio: 'ignore' });\n log(`\u2713 Loaded plist with launchctl (runner will start at next login)`);\n log(` Logs: ${join(home, '.claude', 'vo-runner.log')}`);\n } catch {\n log(`\u26A0 Failed to load plist with launchctl (you may need to load it manually)`);\n log(` Run: launchctl load \"${plistPath}\"`);\n }\n}\n\n/**\n * macOS: Uninstall the launchd plist.\n */\nasync function uninstallMacAutostart(\n log: (msg: string) => void,\n env: Readonly<Record<string, string | undefined>>,\n): Promise<void> {\n const home = env['HOME']?.trim() || homedir();\n const launchAgentsDir = join(home, 'Library', 'LaunchAgents');\n const plistPath = join(launchAgentsDir, 'ai.algosuite.vo-runner.plist');\n\n if (!existsSync(plistPath)) {\n log(`\u2713 Auto-start plist not found (already removed)`);\n return;\n }\n\n // Unload the plist with launchctl\n try {\n const { execSync } = await import('node:child_process');\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: 'ignore' });\n log(`\u2713 Unloaded plist with launchctl`);\n } catch {\n log(`\u26A0 Failed to unload plist with launchctl (continuing anyway)`);\n }\n\n unlinkSync(plistPath);\n log(`\u2713 Removed launchd plist`);\n log(` Path: ${plistPath}`);\n}\n\n/**\n * Linux: Install a systemd USER unit at\n * $XDG_CONFIG_HOME/systemd/user/vo-runner.service (default ~/.config),\n * then enable + start it (`systemctl --user enable --now`). Restart=on-failure\n * mirrors the macOS KeepAlive. ExecStart runs via a login shell so the npm-global\n * `vo-mcp` resolves under systemd's minimal PATH.\n */\nasync function installLinuxAutostart(\n runnerCommand: string,\n log: (msg: string) => void,\n env: Readonly<Record<string, string | undefined>>,\n): Promise<void> {\n const home = env['HOME']?.trim() || homedir();\n const configHome = resolveLinuxConfigHome(home, env);\n const unitDir = join(configHome, 'systemd', 'user');\n mkdirSync(unitDir, { recursive: true });\n const unitPath = join(unitDir, 'vo-runner.service');\n\n const logFile = join(home, '.claude', 'vo-runner.log');\n const errFile = join(home, '.claude', 'vo-runner-error.log');\n const quotedRunnerCommand = quotePosixShellArgument(runnerCommand);\n mkdirSync(join(home, '.claude'), { recursive: true });\n\n const unit = `[Unit]\nDescription=AlgoHQ Code Runner (vo-mcp)\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nWorkingDirectory=${home}\nEnvironment=\"VO_CODE_RUNNER_CLONES_ROOT=${join(configHome, 'ai.algosuite.vo-runner', 'clones')}\"\nExecStart=/bin/sh -lc ${quotedRunnerCommand}\nRestart=on-failure\nRestartSec=10\nStandardOutput=append:${logFile}\nStandardError=append:${errFile}\n\n[Install]\nWantedBy=default.target\n`;\n if (launcherIsCurrent(unitPath, unit, 'unit', log)) {\n log(`\u2713 Auto-start is already configured (systemd user unit)`);\n log(` Path: ${unitPath}`);\n return;\n }\n writeFileSync(unitPath, unit, 'utf8');\n log(`\u2713 Installed systemd user unit`);\n log(` Path: ${unitPath}`);\n\n // In tests, write the unit but NEVER actually enable/start a real service.\n if (process.env['VITEST']) {\n log(` (test mode: skipping systemctl enable)`);\n return;\n }\n try {\n const { execSync } = await import('node:child_process');\n execSync('systemctl --user daemon-reload', { stdio: 'ignore' });\n execSync('systemctl --user enable --now vo-runner.service', { stdio: 'ignore' });\n log(`\u2713 Enabled + started vo-runner.service (starts at login)`);\n log(` Logs: ${logFile}`);\n } catch {\n log(`\u26A0 Could not enable via systemctl (enable it manually):`);\n log(` systemctl --user daemon-reload && systemctl --user enable --now vo-runner.service`);\n }\n}\n\n/**\n * Linux: Uninstall the systemd user unit.\n */\nasync function uninstallLinuxAutostart(\n log: (msg: string) => void,\n env: Readonly<Record<string, string | undefined>>,\n): Promise<void> {\n const home = env['HOME']?.trim() || homedir();\n const configHome = resolveLinuxConfigHome(home, env);\n const unitPath = join(configHome, 'systemd', 'user', 'vo-runner.service');\n if (!existsSync(unitPath)) {\n log(`\u2713 Auto-start unit not found (already removed)`);\n return;\n }\n if (!process.env['VITEST']) {\n try {\n const { execSync } = await import('node:child_process');\n execSync('systemctl --user disable --now vo-runner.service', { stdio: 'ignore' });\n log(`\u2713 Disabled + stopped vo-runner.service`);\n } catch {\n log(`\u26A0 Could not disable via systemctl (continuing anyway)`);\n }\n }\n unlinkSync(unitPath);\n log(`\u2713 Removed systemd user unit`);\n log(` Path: ${unitPath}`);\n}\n\n/**\n * Install auto-start for the runner daemon. Cross-platform.\n */\nexport async function installAutostart(opts: AutostartOptions = {}): Promise<void> {\n const log = opts.log ?? ((m: string) => console.error(m));\n const env = opts.env ?? process.env;\n const runnerCommand = resolveRunnerCommand(opts.runnerCommand);\n const plat = opts.platform ?? platform();\n\n if (plat === 'win32') {\n installWindowsAutostart(runnerCommand, log, env);\n } else if (plat === 'darwin') {\n await installMacAutostart(runnerCommand, log, env);\n } else if (plat === 'linux') {\n await installLinuxAutostart(runnerCommand, log, env);\n } else {\n log(`\u2717 Auto-start is not supported on platform: ${plat}`);\n log(` Supported platforms: win32 (Windows), darwin (macOS), linux (Linux)`);\n }\n}\n\n/**\n * Uninstall auto-start for the runner daemon. Cross-platform.\n */\nexport async function uninstallAutostart(opts: AutostartOptions = {}): Promise<void> {\n const log = opts.log ?? ((m: string) => console.error(m));\n const env = opts.env ?? process.env;\n const plat = opts.platform ?? platform();\n\n if (plat === 'win32') {\n uninstallWindowsAutostart(log, env);\n } else if (plat === 'darwin') {\n await uninstallMacAutostart(log, env);\n } else if (plat === 'linux') {\n await uninstallLinuxAutostart(log, env);\n } else {\n log(`\u2717 Auto-start is not supported on platform: ${plat}`);\n log(` Supported platforms: win32 (Windows), darwin (macOS), linux (Linux)`);\n }\n}\n", "#!/usr/bin/env node\n/**\n * `vo-mcp runner --install-autostart` / `--uninstall-autostart` CLI entrypoints.\n *\n * Registers or unregisters the runner daemon to start automatically at user login.\n */\nimport { installAutostart, uninstallAutostart } from './autostart.js';\n\nexport async function installAutostartCli(): Promise<void> {\n const log = (m: string): void => console.error(m);\n\n log('\u2501\u2501\u2501 vo-mcp runner auto-start installer \u2501\u2501\u2501\\n');\n\n await installAutostart({ log });\n\n log('\\nAuto-start is now configured. The runner will launch automatically at your next login.');\n log('To remove: vo-mcp runner --uninstall-autostart');\n}\n\nexport async function uninstallAutostartCli(): Promise<void> {\n const log = (m: string): void => console.error(m);\n\n log('\u2501\u2501\u2501 vo-mcp runner auto-start uninstaller \u2501\u2501\u2501\\n');\n\n await uninstallAutostart({ log });\n\n log('\\nAuto-start has been removed. The runner will no longer launch automatically.');\n log('To reinstall: vo-mcp runner --install-autostart');\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }