@algosuite/vo-mcp 0.2.0-beta.17 → 0.2.0-beta.19

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.
@@ -12,7 +12,16 @@ function installWindowsAutostart(runnerCommand, log, env) {
12
12
  const appData = env["APPDATA"] ?? join(homedir(), "AppData", "Roaming");
13
13
  const startupDir = join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
14
14
  mkdirSync(startupDir, { recursive: true });
15
- const launcherPath = join(startupDir, "vo-runner.cmd");
15
+ const launcherPath = join(startupDir, "vo-runner.vbs");
16
+ const legacyCmdPath = join(startupDir, "vo-runner.cmd");
17
+ if (existsSync(legacyCmdPath)) {
18
+ try {
19
+ unlinkSync(legacyCmdPath);
20
+ log(` Removed legacy minimized .cmd launcher: ${legacyCmdPath}`);
21
+ } catch (error) {
22
+ log(`\u26A0 Could not remove legacy launcher ${legacyCmdPath} (${error instanceof Error ? error.message : String(error)}); remove it manually to avoid a double start`);
23
+ }
24
+ }
16
25
  if (existsSync(launcherPath)) {
17
26
  const existing = readFileSync(launcherPath, "utf8");
18
27
  if (existing.includes("vo-mcp runner")) {
@@ -24,27 +33,31 @@ function installWindowsAutostart(runnerCommand, log, env) {
24
33
  copyFileSync(launcherPath, backupPath);
25
34
  log(` Backed up existing launcher to: ${backupPath}`);
26
35
  }
27
- const launcherContent = `@echo off
28
- REM Auto-start launcher for vo-mcp runner
29
- REM Created by vo-mcp autostart installer
30
- start /min cmd /c "${runnerCommand}"
36
+ const hiddenCommand = `cmd /c ${runnerCommand}`.replace(/"/g, '""');
37
+ const launcherContent = `' Auto-start launcher for vo-mcp runner
38
+ ' Created by vo-mcp autostart installer
39
+ CreateObject("WScript.Shell").Run "${hiddenCommand}", 0, False
31
40
  `;
32
41
  writeFileSync(launcherPath, launcherContent, "utf8");
33
42
  log(`\u2713 Installed Windows auto-start launcher`);
34
43
  log(` Path: ${launcherPath}`);
35
- log(` The runner will start minimized at next login.`);
44
+ log(` The runner will start hidden at next login.`);
36
45
  }
37
46
  function uninstallWindowsAutostart(log, env) {
38
47
  const appData = env["APPDATA"] ?? join(homedir(), "AppData", "Roaming");
39
48
  const startupDir = join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
40
- const launcherPath = join(startupDir, "vo-runner.cmd");
41
- if (!existsSync(launcherPath)) {
49
+ const launcherPaths = [join(startupDir, "vo-runner.vbs"), join(startupDir, "vo-runner.cmd")];
50
+ let removedAny = false;
51
+ for (const launcherPath of launcherPaths) {
52
+ if (!existsSync(launcherPath)) continue;
53
+ unlinkSync(launcherPath);
54
+ removedAny = true;
55
+ log(`\u2713 Removed Windows auto-start launcher`);
56
+ log(` Path: ${launcherPath}`);
57
+ }
58
+ if (!removedAny) {
42
59
  log(`\u2713 Auto-start launcher not found (already removed)`);
43
- return;
44
60
  }
45
- unlinkSync(launcherPath);
46
- log(`\u2713 Removed Windows auto-start launcher`);
47
- log(` Path: ${launcherPath}`);
48
61
  }
49
62
  async function installMacAutostart(runnerCommand, log) {
50
63
  const launchAgentsDir = join(homedir(), "Library", "LaunchAgents");
@@ -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 minimized at user login.\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\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 .cmd file that starts `vo-mcp runner` minimized. 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.cmd');\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. Uses `start /min` to launch minimized.\n const launcherContent = `@echo off\nREM Auto-start launcher for vo-mcp runner\nREM Created by vo-mcp autostart installer\nstart /min cmd /c \"${runnerCommand}\"\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 minimized 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 const launcherPath = join(startupDir, 'vo-runner.cmd');\n\n if (!existsSync(launcherPath)) {\n log(`\u2713 Auto-start launcher not found (already removed)`);\n return;\n }\n\n unlinkSync(launcherPath);\n log(`\u2713 Removed Windows auto-start launcher`);\n log(` Path: ${launcherPath}`);\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 = 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 = 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 { 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\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 const hiddenCommand = `cmd /c ${runnerCommand}`.replace(/\"/g, '\"\"');\n const launcherContent = `' Auto-start launcher for vo-mcp runner\n' Created by vo-mcp autostart installer\nCreateObject(\"WScript.Shell\").Run \"${hiddenCommand}\", 0, False\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 = 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 = 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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",
6
6
  "names": []
7
7
  }
package/dist/cli.js CHANGED
@@ -1625,7 +1625,7 @@ var init_sync_config = __esm({
1625
1625
  // src/cli.ts
1626
1626
  import { homedir as homedir6, hostname } from "node:os";
1627
1627
  import { randomUUID as randomUUID5 } from "node:crypto";
1628
- import { join as join8 } from "node:path";
1628
+ import { join as join10 } from "node:path";
1629
1629
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1630
1630
 
1631
1631
  // src/server.ts
@@ -2481,7 +2481,11 @@ async function handleConsensusJudgment(deps, rawInput, signal) {
2481
2481
  ...engineResult.low_confidence_sources !== void 0 ? { low_confidence_sources: engineResult.low_confidence_sources } : {},
2482
2482
  // Escalation (from citation grade or human-tiebreak synthesizer).
2483
2483
  ...engineResult.escalation_required !== void 0 ? { escalation_required: engineResult.escalation_required } : {},
2484
- ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {}
2484
+ ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {},
2485
+ // Critique-uptake (2026-07-20 red-team fix) — the engine computes this
2486
+ // on every call; this spread closes the gap where the visibility report
2487
+ // was itself silently dropped at the payload boundary.
2488
+ ...engineResult.critique_uptake !== void 0 ? { critique_uptake: engineResult.critique_uptake } : {}
2485
2489
  };
2486
2490
  const envelope = {
2487
2491
  tool: TOOL_NAME4,
@@ -5741,6 +5745,196 @@ async function handleHqWhiteboardRead(_deps, rawInput, signal) {
5741
5745
  return jsonContent(await callWhiteboard("GET", input, signal));
5742
5746
  }
5743
5747
 
5748
+ // src/tools/skills/skill-corpus.ts
5749
+ import { existsSync as existsSync6, statSync as statSync5 } from "node:fs";
5750
+ import { dirname as dirname5, isAbsolute, join as join9, resolve as resolve2 } from "node:path";
5751
+
5752
+ // ../skill-registry/src/loader.ts
5753
+ import { readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync4 } from "node:fs";
5754
+ import { join as join8 } from "node:path";
5755
+ var InvalidSkillFrontmatterError = class extends Error {
5756
+ constructor(skillFile, reason) {
5757
+ super(`Invalid frontmatter in ${skillFile}: ${reason}`);
5758
+ this.skillFile = skillFile;
5759
+ this.reason = reason;
5760
+ }
5761
+ skillFile;
5762
+ reason;
5763
+ name = "InvalidSkillFrontmatterError";
5764
+ };
5765
+ var FRONTMATTER_DELIMITER = "---";
5766
+ function parseFrontmatter(rawInput, sourcePath) {
5767
+ const raw = rawInput.replace(/\r\n/g, "\n");
5768
+ if (!raw.startsWith(`${FRONTMATTER_DELIMITER}
5769
+ `)) {
5770
+ throw new InvalidSkillFrontmatterError(sourcePath, 'file does not start with frontmatter delimiter "---"');
5771
+ }
5772
+ const afterFirst = raw.slice(FRONTMATTER_DELIMITER.length + 1);
5773
+ const closingIdx = afterFirst.indexOf(`
5774
+ ${FRONTMATTER_DELIMITER}
5775
+ `);
5776
+ if (closingIdx === -1) {
5777
+ throw new InvalidSkillFrontmatterError(sourcePath, 'missing closing frontmatter delimiter "---"');
5778
+ }
5779
+ const frontmatterText = afterFirst.slice(0, closingIdx);
5780
+ const body = afterFirst.slice(closingIdx + `
5781
+ ${FRONTMATTER_DELIMITER}
5782
+ `.length);
5783
+ let name = "";
5784
+ let description23 = "";
5785
+ for (const line of frontmatterText.split("\n")) {
5786
+ const trimmed = line.trim();
5787
+ if (trimmed.length === 0) continue;
5788
+ const colonIdx = trimmed.indexOf(":");
5789
+ if (colonIdx === -1) continue;
5790
+ const key = trimmed.slice(0, colonIdx).trim();
5791
+ const value = trimmed.slice(colonIdx + 1).trim();
5792
+ if (key === "name") name = value;
5793
+ else if (key === "description") description23 = value;
5794
+ }
5795
+ if (name.length === 0) {
5796
+ throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "name"');
5797
+ }
5798
+ if (description23.length === 0) {
5799
+ throw new InvalidSkillFrontmatterError(sourcePath, 'missing required field "description"');
5800
+ }
5801
+ return { name, description: description23, body };
5802
+ }
5803
+ function loadSkillsFromDir(skillsDir) {
5804
+ const entries = readdirSync5(skillsDir);
5805
+ const skills = [];
5806
+ for (const entry of entries) {
5807
+ const entryPath = join8(skillsDir, entry);
5808
+ let stat;
5809
+ try {
5810
+ stat = statSync4(entryPath);
5811
+ } catch {
5812
+ continue;
5813
+ }
5814
+ if (!stat.isDirectory()) continue;
5815
+ const skillFile = join8(entryPath, "SKILL.md");
5816
+ let raw;
5817
+ try {
5818
+ raw = readFileSync8(skillFile, "utf8");
5819
+ } catch {
5820
+ continue;
5821
+ }
5822
+ const { name, description: description23, body } = parseFrontmatter(raw, skillFile);
5823
+ skills.push({ name, description: description23, body, sourcePath: skillFile });
5824
+ }
5825
+ return [...skills].sort((a, b) => a.name.localeCompare(b.name));
5826
+ }
5827
+
5828
+ // src/tools/skills/skill-corpus.ts
5829
+ init_common();
5830
+ var LIST_TOOL_NAME = "vo_skill_list";
5831
+ var GET_TOOL_NAME = "vo_skill_get";
5832
+ var listDescription = "List the Algosuite skill corpus (name + trigger description for every skill). Call once near session start to learn which skills exist; then fetch the full instructions for a relevant skill with vo_skill_get. This is the same corpus Claude Code loads natively from .claude/skills \u2014 served over MCP so every vendor works from identical playbooks. Pass refresh:true to re-scan from disk.";
5833
+ var getDescription = "Fetch the full markdown instructions of one Algosuite skill by name. Follow the returned instructions for the current task the same way a native skill invocation would. Use vo_skill_list to discover skill names.";
5834
+ var listInputSchema = {
5835
+ type: "object",
5836
+ properties: {
5837
+ refresh: {
5838
+ type: "boolean",
5839
+ description: "Re-scan the skills directory instead of using the cached corpus."
5840
+ }
5841
+ },
5842
+ required: []
5843
+ };
5844
+ var getInputSchema = {
5845
+ type: "object",
5846
+ properties: {
5847
+ name: {
5848
+ type: "string",
5849
+ description: "Skill name exactly as returned by vo_skill_list."
5850
+ }
5851
+ },
5852
+ required: ["name"]
5853
+ };
5854
+ var MAX_WALK_UP_LEVELS = 8;
5855
+ var cachedCorpus = null;
5856
+ function resolveSkillsDir(env = process.env, startDir = process.cwd()) {
5857
+ const override = env.VO_SKILLS_DIR;
5858
+ if (typeof override === "string" && override.length > 0) {
5859
+ const abs = isAbsolute(override) ? override : resolve2(startDir, override);
5860
+ return existsSync6(abs) && statSync5(abs).isDirectory() ? abs : null;
5861
+ }
5862
+ let dir = resolve2(startDir);
5863
+ for (let i = 0; i < MAX_WALK_UP_LEVELS; i += 1) {
5864
+ const candidate = join9(dir, ".claude", "skills");
5865
+ if (existsSync6(candidate) && statSync5(candidate).isDirectory()) return candidate;
5866
+ const parent = dirname5(dir);
5867
+ if (parent === dir) break;
5868
+ dir = parent;
5869
+ }
5870
+ return null;
5871
+ }
5872
+ function loadCorpus() {
5873
+ const skillsDir = resolveSkillsDir();
5874
+ if (skillsDir === null) {
5875
+ return {
5876
+ skills: [],
5877
+ skillsDir: null,
5878
+ unavailableReason: "No skills directory found. Set VO_SKILLS_DIR or run inside a repo with .claude/skills."
5879
+ };
5880
+ }
5881
+ try {
5882
+ return { skills: loadSkillsFromDir(skillsDir), skillsDir, unavailableReason: null };
5883
+ } catch (err) {
5884
+ const message = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
5885
+ return { skills: [], skillsDir, unavailableReason: message };
5886
+ }
5887
+ }
5888
+ function getCorpus(refresh) {
5889
+ if (refresh || cachedCorpus === null) {
5890
+ cachedCorpus = loadCorpus();
5891
+ }
5892
+ return cachedCorpus;
5893
+ }
5894
+ async function handleSkillList(_deps, rawInput) {
5895
+ const input = rawInput ?? {};
5896
+ const refresh = input.refresh === true;
5897
+ const corpus = getCorpus(refresh);
5898
+ return jsonContent({
5899
+ corpus_available: corpus.unavailableReason === null,
5900
+ skills_dir: corpus.skillsDir,
5901
+ unavailable_reason: corpus.unavailableReason,
5902
+ skill_count: corpus.skills.length,
5903
+ skills: corpus.skills.map((s) => ({ name: s.name, description: s.description }))
5904
+ });
5905
+ }
5906
+ async function handleSkillGet(_deps, rawInput) {
5907
+ const input = rawInput ?? {};
5908
+ if (typeof input.name !== "string" || input.name.trim().length === 0) {
5909
+ throw invalidParams(GET_TOOL_NAME, 'input field "name" (non-empty string) is required');
5910
+ }
5911
+ const requested = input.name.trim();
5912
+ const corpus = getCorpus(false);
5913
+ if (corpus.unavailableReason !== null) {
5914
+ return jsonContent({
5915
+ corpus_available: false,
5916
+ unavailable_reason: corpus.unavailableReason,
5917
+ skill: null
5918
+ });
5919
+ }
5920
+ const skill = corpus.skills.find((s) => s.name === requested);
5921
+ if (skill === void 0) {
5922
+ throw invalidParams(
5923
+ GET_TOOL_NAME,
5924
+ `unknown skill "${requested}". Known skills: ${corpus.skills.map((s) => s.name).join(", ")}`
5925
+ );
5926
+ }
5927
+ return jsonContent({
5928
+ corpus_available: true,
5929
+ skill: {
5930
+ name: skill.name,
5931
+ description: skill.description,
5932
+ instructions: skill.body,
5933
+ source_path: skill.sourcePath
5934
+ }
5935
+ });
5936
+ }
5937
+
5744
5938
  // src/server.ts
5745
5939
  function buildToolRegistry() {
5746
5940
  return {
@@ -5951,6 +6145,22 @@ function buildToolRegistry() {
5951
6145
  inputSchema: readInputSchema
5952
6146
  },
5953
6147
  handler: handleHqWhiteboardRead
6148
+ },
6149
+ [LIST_TOOL_NAME]: {
6150
+ definition: {
6151
+ name: LIST_TOOL_NAME,
6152
+ description: listDescription,
6153
+ inputSchema: listInputSchema
6154
+ },
6155
+ handler: handleSkillList
6156
+ },
6157
+ [GET_TOOL_NAME]: {
6158
+ definition: {
6159
+ name: GET_TOOL_NAME,
6160
+ description: getDescription,
6161
+ inputSchema: getInputSchema
6162
+ },
6163
+ handler: handleSkillGet
5954
6164
  }
5955
6165
  };
5956
6166
  }
@@ -6006,7 +6216,7 @@ function createServer(options) {
6006
6216
  // src/cache/sqlite-cache.ts
6007
6217
  import { createHash as createHash3 } from "node:crypto";
6008
6218
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync5 } from "node:fs";
6009
- import { dirname as dirname5 } from "node:path";
6219
+ import { dirname as dirname6 } from "node:path";
6010
6220
  import { DatabaseSync } from "node:sqlite";
6011
6221
 
6012
6222
  // src/cache/canonicalize.ts
@@ -6051,7 +6261,7 @@ function normalizeString(s) {
6051
6261
  function createSqliteCache(options) {
6052
6262
  const fileBacked = options.dbPath !== ":memory:";
6053
6263
  if (fileBacked) {
6054
- mkdirSync5(dirname5(options.dbPath), { recursive: true, mode: 448 });
6264
+ mkdirSync5(dirname6(options.dbPath), { recursive: true, mode: 448 });
6055
6265
  }
6056
6266
  const versionNamespace = options.cacheVersionNamespace ?? "";
6057
6267
  const db = new DatabaseSync(options.dbPath);
@@ -6256,6 +6466,30 @@ function createMetaModelCaller(options = {}) {
6256
6466
  }
6257
6467
  var callMetaWithMetrics = createMetaModelCaller();
6258
6468
 
6469
+ // src/consensus/consensus-panel.ts
6470
+ var VO_MCP_CONSENSUS_PANEL = {
6471
+ anthropic: "claude-opus-4-7",
6472
+ openai: "gpt-5",
6473
+ // gemini-2.5-FLASH (not -pro): flash accepts the default thinkingBudget=0 from
6474
+ // callGeminiWithMetrics; 2.5-pro REJECTS budget 0 ("only works in thinking mode").
6475
+ // Flash is also ~10x cheaper. 2026-06-02.
6476
+ google: "gemini-2.5-flash",
6477
+ deepseek: "deepseek-chat",
6478
+ // Muse Spark identity is owned by meta-model-caller.ts (single source of
6479
+ // truth for the meta slot); re-exported here so the panel stays complete.
6480
+ meta: META_CONSENSUS_MODEL
6481
+ };
6482
+ function getVoMcpConsensusPanel(panel = VO_MCP_CONSENSUS_PANEL) {
6483
+ for (const [provider, modelId] of Object.entries(panel)) {
6484
+ if (typeof modelId !== "string" || modelId.trim().length === 0) {
6485
+ throw new Error(
6486
+ `getVoMcpConsensusPanel: panel slot "${provider}" has a missing or blank model ID`
6487
+ );
6488
+ }
6489
+ }
6490
+ return panel;
6491
+ }
6492
+
6259
6493
  // src/consensus/engine-options.ts
6260
6494
  var AGREEMENT_GATE_ENV_VAR = "VO_CONSENSUS_AGREEMENT_GATE";
6261
6495
  function isTruthyFlag(raw) {
@@ -6524,6 +6758,10 @@ function createEngineConsensusClient(options) {
6524
6758
  ...mapFanOutDiagnostics(response.fan_out_diagnostics) !== void 0 ? { fan_out_diagnostics: mapFanOutDiagnostics(response.fan_out_diagnostics) } : {},
6525
6759
  // Stage A7-shadow — adaptive-vs-incumbent comparison (PII-free; present iff shadow on).
6526
6760
  ...mapShadowSynthesis(response.shadow_synthesis) !== void 0 ? { shadow_synthesis: mapShadowSynthesis(response.shadow_synthesis) } : {},
6761
+ // Critique-uptake (2026-07-20 red-team fix) — verifier-critique
6762
+ // visibility report; previously computed by the engine on every
6763
+ // call but dropped at this boundary.
6764
+ ...response.critique_uptake !== void 0 ? { critique_uptake: response.critique_uptake } : {},
6527
6765
  // Source-grounded additive outputs (Tier-4 features).
6528
6766
  ...useSourceGrounded ? { source_grounded: true } : {},
6529
6767
  ...sourceExtras?.citation_grade !== void 0 ? { citation_grade: sourceExtras.citation_grade } : {},
@@ -6539,20 +6777,7 @@ function createEngineConsensusClient(options) {
6539
6777
  }
6540
6778
  };
6541
6779
  }
6542
- var DEFAULT_MODELS = {
6543
- // These ids match the strategic-roadmap §4 `newsStandard` / `newsDeep` panel
6544
- // intent — current production model ids. Per handoff §C-3 these MUST come
6545
- // from `CONSENSUS_PANELS` in `functions-shared/shared-model-resolvers.ts`
6546
- // for V1; placeholder defaults here keep Phase 2 Lane A non-blocking.
6547
- anthropic: "claude-opus-4-7",
6548
- openai: "gpt-5",
6549
- // gemini-2.5-FLASH (not -pro): flash accepts the default thinkingBudget=0 from
6550
- // callGeminiWithMetrics; 2.5-pro REJECTS budget 0 ("only works in thinking mode").
6551
- // Flash is also ~10x cheaper. 2026-06-02.
6552
- google: "gemini-2.5-flash",
6553
- deepseek: "deepseek-chat",
6554
- meta: META_CONSENSUS_MODEL
6555
- };
6780
+ var DEFAULT_MODELS = getVoMcpConsensusPanel();
6556
6781
  function probeProviders(env = process.env) {
6557
6782
  const out = [];
6558
6783
  if ((env["ANTHROPIC_API_KEY"] ?? "").trim().length > 0) out.push("anthropic");
@@ -6889,7 +7114,7 @@ function captureHtml() {
6889
7114
  function defaultOpenBrowser(url) {
6890
7115
  const platform = process.platform;
6891
7116
  if (platform === "win32") {
6892
- spawn2("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
7117
+ spawn2("rundll32", ["url.dll,FileProtocolHandler", url], { detached: true, stdio: "ignore" }).unref();
6893
7118
  } else if (platform === "darwin") {
6894
7119
  spawn2("open", [url], { detached: true, stdio: "ignore" }).unref();
6895
7120
  } else {
@@ -6904,7 +7129,7 @@ async function runLogin(opts = {}) {
6904
7129
  const nowIso = opts.nowIso ?? (() => (/* @__PURE__ */ new Date()).toISOString());
6905
7130
  const openBrowser = opts.openBrowser ?? defaultOpenBrowser;
6906
7131
  const state = randomBytes(32).toString("base64url");
6907
- return new Promise((resolve2, reject) => {
7132
+ return new Promise((resolve3, reject) => {
6908
7133
  let settled = false;
6909
7134
  const finish = (err, result) => {
6910
7135
  if (settled) return;
@@ -6912,7 +7137,7 @@ async function runLogin(opts = {}) {
6912
7137
  clearTimeout(timer);
6913
7138
  server.close();
6914
7139
  if (err) reject(err);
6915
- else resolve2(result);
7140
+ else resolve3(result);
6916
7141
  };
6917
7142
  const server = createServer2((req, res) => {
6918
7143
  const url = new URL(req.url ?? "/", "http://127.0.0.1");
@@ -7027,7 +7252,7 @@ init_common();
7027
7252
  function defaultCacheDbPath() {
7028
7253
  const env = process.env["VO_MCP_DB_PATH"];
7029
7254
  if (env && env.length > 0) return env;
7030
- return join8(homedir6(), ".claude", "vo-mcp-cache.db");
7255
+ return join10(homedir6(), ".claude", "vo-mcp-cache.db");
7031
7256
  }
7032
7257
  async function probeEngineVersion() {
7033
7258
  try {
@@ -7163,10 +7388,9 @@ if (process.argv[2] === "login") {
7163
7388
  console.error(`[vo-mcp] login successful${r.email ? ` as ${r.email}` : ""}. Credential stored at ${r.credentialPath}.`);
7164
7389
  console.error("[vo-mcp] You can now remove VO_CONTROL_PLANE_ADMIN_TOKEN (the god-token) from your MCP config.");
7165
7390
  console.error("[vo-mcp] NOTE: per-user auth requires VO_OPERATOR_ALLOWED_EMAILS (with your email) on the deployed control-plane.");
7166
- process.exit(0);
7167
7391
  }).catch((err) => {
7168
7392
  console.error("[vo-mcp] login failed:", err instanceof Error ? err.message : String(err));
7169
- process.exit(1);
7393
+ process.exitCode = 1;
7170
7394
  });
7171
7395
  } else if (process.argv[2] === "sync") {
7172
7396
  const action = process.argv[3];
@@ -7181,17 +7405,15 @@ if (process.argv[2] === "login") {
7181
7405
  const r = await runMemorySync2(action, cwd, sessionId);
7182
7406
  if (r.synced) {
7183
7407
  console.error(`[vo-mcp] sync ${action} ok: ${JSON.stringify(r)}`);
7184
- process.exit(0);
7185
- }
7186
- if (isNoopSyncReason2(r.reason)) {
7408
+ } else if (isNoopSyncReason2(r.reason)) {
7187
7409
  console.error(`[vo-mcp] sync ${action} skipped: ${r.reason}`);
7188
- process.exit(0);
7410
+ } else {
7411
+ console.error(`[vo-mcp] sync ${action} failed: ${r.reason}`);
7412
+ process.exitCode = 1;
7189
7413
  }
7190
- console.error(`[vo-mcp] sync ${action} failed: ${r.reason}`);
7191
- process.exit(1);
7192
7414
  }).catch((err) => {
7193
7415
  console.error("[vo-mcp] sync fatal:", err instanceof Error ? err.message : String(err));
7194
- process.exit(1);
7416
+ process.exitCode = 1;
7195
7417
  });
7196
7418
  } else {
7197
7419
  main().catch((err) => {