@algosuite/vo-mcp 0.2.0-beta.7 → 0.2.0-beta.9

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/install.ts", "../src/cloud/pairing.ts", "../src/cloud/credential-store.ts", "../src/cloud/keychain.ts", "../src/autostart.ts", "../src/install-cli.ts"],
4
- "sourcesContent": ["/**\n * `vo-mcp install` \u2014 one-command client installer for non-coders.\n *\n * Configures Claude Desktop / Claude Code to load vo-mcp, guides login, and\n * explains starting the runner. Cross-platform (Windows + macOS/Linux).\n *\n * Steps:\n * 1. Write/merge the MCP server config (backing up existing config).\n * 2. Pair via device code (`vo-mcp pair`) to mint the scoped credential \u2014 device\n * code (not loopback) so it works in every terminal (no 127.0.0.1 callback).\n * 3. Explain `vo-mcp runner` (not started here \u2014 user does it manually).\n * 4. Print clear next steps + success summary.\n */\nimport { homedir, platform } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { runPairing } from './cloud/pairing.js';\n\n/** Live vo-control-plane Cloud Run URL \u2014 explicit (was derived from the dashboard\n * URL by string-replace, which silently broke when that default changed). */\nconst DEFAULT_CONTROL_PLANE_URL = 'https://vo-control-plane-bzjphrajaq-uc.a.run.app';\nimport { installAutostart } from './autostart.js';\n\nexport interface InstallOptions {\n readonly log?: (msg: string) => void;\n readonly skipLogin?: boolean;\n readonly skipAutostart?: boolean;\n readonly env?: Readonly<Record<string, string | undefined>>;\n}\n\ninterface McpServerEntry {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n/**\n * Resolve the Claude config path. Prefers Claude Code's `.claude.json` in the\n * user home, else Claude Desktop's `claude_desktop_config.json` in the platform\n * config directory.\n */\n/** Claude Code CLI config path (~/.claude.json). `home` is injectable for tests. */\nfunction resolveCodeConfigPath(home: string): string {\n return join(home, '.claude.json');\n}\n\n/** Claude Desktop app config path (per-OS). Linux uses capital-C 'Claude'. */\nfunction resolveDesktopConfigPath(home: string, plat: NodeJS.Platform, appData?: string): string {\n if (plat === 'win32') {\n return join(appData ?? join(home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');\n }\n if (plat === 'darwin') {\n return join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');\n }\n // Linux / others \u2014 capital-C 'Claude' (matches the Claude Desktop app dir).\n return join(home, '.config', 'Claude', 'claude_desktop_config.json');\n}\n\n/**\n * Read + parse existing Claude config (or return empty shape if missing).\n * Never throws \u2014 returns a default shape on any problem.\n */\nfunction readClaudeConfig(path: string): Record<string, unknown> {\n try {\n if (!existsSync(path)) return {};\n const raw = readFileSync(path, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n // Preserve the FULL config \u2014 Claude Code's ~/.claude.json holds `projects`,\n // history, etc., and Desktop holds `preferences`. We must keep every key and\n // only touch mcpServers, or `install` would wipe the rest of the user's config.\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n // Malformed JSON \u2014 return empty; the caller backs up the original file before\n // any write, so the on-disk original is preserved either way.\n return {};\n }\n}\n\n/**\n * Write the Claude config, creating parent directories as needed. Writes with\n * 2-space indentation for human readability.\n */\nfunction writeClaudeConfig(path: string, config: Record<string, unknown>): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 2)}\\n`, 'utf8');\n}\n\n/**\n * Resolve the absolute path to the vo-mcp CLI (dist/cli.js). Computes from\n * process.argv[1] which is the path to the currently running script\n * (dist/install-cli.js when invoked via `vo-mcp install`).\n */\nfunction resolveVoMcpCliPath(): string {\n // Resolve from this module, not process.argv[1]. When invoked as\n // `vo-mcp install`, argv[1] is the dispatcher under bin/; cli.js lives in dist/.\n return join(dirname(fileURLToPath(import.meta.url)), 'cli.js');\n}\n\n/**\n * Merge the vo-mcp MCP server entry into ONE config file. Preserves EVERY other\n * key (other mcpServers + top-level keys like Claude Code's `projects` or\n * Desktop's `preferences`) \u2014 only the `vo-mcp` entry is touched. Backs up first.\n * Idempotent: if `vo-mcp` already points at this cli.js, no-op.\n */\nfunction installMcpConfigAt(\n configPath: string,\n cliPath: string,\n controlPlaneUrl: string,\n log: (msg: string) => void,\n label: string,\n): void {\n const existing = readClaudeConfig(configPath);\n const mcpServers: Record<string, McpServerEntry> =\n existing['mcpServers'] && typeof existing['mcpServers'] === 'object'\n ? (existing['mcpServers'] as Record<string, McpServerEntry>)\n : {};\n\n // Idempotency: already wired to THIS cli.js? (re-points if the path changed.)\n const voEntry = mcpServers['vo'] ?? mcpServers['vo-mcp'];\n if (voEntry?.args?.some((a: string) => a.includes(cliPath))) {\n log(` ${label} already current: ${configPath}`);\n return;\n }\n\n // Backup before any write (protects the original even if it was malformed).\n if (existsSync(configPath)) {\n const backupPath = `${configPath}.backup-${Date.now()}`;\n copyFileSync(configPath, backupPath);\n log(` Backed up ${label} config \u2192 ${backupPath}`);\n }\n\n const merged: Record<string, unknown> = {\n ...existing,\n mcpServers: {\n ...mcpServers,\n 'vo-mcp': {\n command: 'node',\n args: [cliPath],\n // Preserve any existing env the user added (e.g. model API keys) \u2014 only\n // ensure VO_CONTROL_PLANE_URL is present. NEVER drop the user's env keys.\n env: { VO_CONTROL_PLANE_URL: controlPlaneUrl, ...(voEntry?.env ?? {}) },\n },\n },\n };\n writeClaudeConfig(configPath, merged);\n log(`\u2713 Wrote vo-mcp to ${label}: ${configPath}`);\n}\n\n/**\n * Wire vo-mcp into BOTH the Claude Code CLI (~/.claude.json) and the Claude\n * Desktop app config, so it loads in whichever the user runs. Each write is\n * idempotent + preserves all other config keys. ONLY VO_CONTROL_PLANE_URL (a\n * public URL) is written \u2014 never a secret.\n */\nfunction installMcpConfig(log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): void {\n // Resolve home from the injected env (tests pass a temp dir) \u2192 falls back to the\n // OS home. This keeps install hermetic: it never touches real configs in tests.\n const home = env['HOME']?.trim() || env['USERPROFILE']?.trim() || homedir();\n const appData = env['APPDATA']?.trim();\n const plat = platform();\n const cliPath = resolveVoMcpCliPath();\n const controlPlaneUrl = env['VO_CONTROL_PLANE_URL']?.trim() || DEFAULT_CONTROL_PLANE_URL;\n installMcpConfigAt(resolveCodeConfigPath(home), cliPath, controlPlaneUrl, log, 'Claude Code CLI');\n installMcpConfigAt(resolveDesktopConfigPath(home, plat, appData), cliPath, controlPlaneUrl, log, 'Claude Desktop');\n}\n\n/**\n * Run the DEVICE-CODE pairing flow (same as `vo-mcp pair`): a short code is shown,\n * the user enters it in their browser. Device code \u2014 NOT a loopback OAuth callback \u2014\n * so it works in every terminal (sandboxed/remote/SSH can't receive a 127.0.0.1\n * callback, which is why the old loopback `login` dead-ended at a \"link your terminal\"\n * page). Non-fatal: a pairing hiccup logs a retry hint and lets the install finish\n * (config + autostart are still useful; the user can run `vo-mcp pair` later).\n */\nasync function runPairFlow(log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): Promise<void> {\n log('\\n\u2501\u2501\u2501 Step 2: Link your VO account (device code) \u2501\u2501\u2501');\n log('A short code appears below \u2014 open the URL it prints and enter the code.');\n log('Your raw token never persists; a scoped credential is stored in your OS keychain.\\n');\n\n try {\n const result = await runPairing({ env, log });\n log(`\\n\u2713 Paired \u2014 scoped credential stored at: ${result.credentialPath}`);\n } catch (err: unknown) {\n log(`\\n\u26A0 Pairing didn't complete: ${err instanceof Error ? err.message : String(err)}`);\n log(' No problem \u2014 the rest will finish; pair anytime with: vo-mcp pair');\n }\n}\n\n/**\n * Print the runner guidance + success summary.\n */\nfunction printNextSteps(log: (msg: string) => void, autostartInstalled: boolean): void {\n log('\\n\u2501\u2501\u2501 Installation complete! \u2501\u2501\u2501\\n');\n log('What\\'s configured:');\n log(' \u2713 Claude Desktop / Claude Code will load vo-mcp on next restart');\n log(' \u2713 Your scoped credential is stored (revocable via the dashboard)');\n if (autostartInstalled) {\n log(' \u2713 Runner daemon will start automatically at login\\n');\n } else {\n log('\\n');\n }\n log('Next steps:');\n log(' 1. Restart Claude Desktop / Claude Code (if running).');\n if (autostartInstalled) {\n log(' 2. Log out and back in (or start the runner manually now: vo-mcp runner)');\n } else {\n log(' 2. Start the agent runner in a terminal (keep it running):');\n log(' vo-mcp runner');\n log(' (To set up auto-start at login: vo-mcp runner --install-autostart)');\n }\n log(' 3. Visit the VO Command Center to dispatch your first agent:');\n log(' https://algosuite.ai/virtualoffice\\n');\n log('The runner watches for tasks you dispatch and spins up agents in fresh worktrees.');\n log('Agents only run while the runner is connected. Ctrl+C to stop it anytime.\\n');\n}\n\n/**\n * Run the full install flow: MCP config \u2192 login \u2192 auto-start \u2192 guidance.\n */\nexport async function install(opts: InstallOptions = {}): Promise<void> {\n const log = opts.log ?? ((m: string) => console.error(m));\n const env = opts.env ?? process.env;\n\n log('\u2501\u2501\u2501 vo-mcp installer \u2501\u2501\u2501');\n log('This will set up your machine to dispatch VO agents from anywhere.\\n');\n\n // Step 1: MCP config\n log('\u2501\u2501\u2501 Step 1: Configure Claude Desktop / Claude Code \u2501\u2501\u2501');\n installMcpConfig(log, env);\n\n // Step 2: Pair via device code (unless skipped)\n if (!opts.skipLogin) {\n await runPairFlow(log, env);\n } else {\n log('\\n(Pairing skipped \u2014 run `vo-mcp pair` when ready.)');\n }\n\n // Step 3: Auto-start (unless skipped)\n let autostartInstalled = false;\n if (!opts.skipAutostart) {\n const plat = platform();\n if (plat === 'win32' || plat === 'darwin' || plat === 'linux') {\n log('\\n\u2501\u2501\u2501 Step 3: Set up auto-start \u2501\u2501\u2501');\n log('Would you like the runner daemon to start automatically at login?');\n log('(You can skip this and set it up later with: vo-mcp runner --install-autostart)\\n');\n await installAutostart({ log, env });\n autostartInstalled = true;\n }\n }\n\n // Step 4: Guidance\n printNextSteps(log, autostartInstalled);\n}\n", "/**\n * Device-code pairing for the BYO runner (M1) \u2014 the no-terminal-token onboarding.\n *\n * The runner calls the control-plane `pair/initiate`, shows the friend a short\n * `code` to type at `<dashboard>/pair`, then polls `pair/poll` with its SECRET\n * `poll_token` until the friend authorizes \u2014 at which point it receives a freshly\n * minted `vocred_` and stores it in the OS keychain (via writeStoredCredential).\n *\n * The friend's AI key NEVER flows through here \u2014 this only obtains the\n * control-plane credential the runner needs to claim THEIR tasks.\n */\nimport { hostname, platform } from 'node:os';\n\nimport { writeStoredCredential, type StoredCredential } from './credential-store.js';\n\nexport const DEFAULT_CONTROL_PLANE_URL = 'https://vo-control-plane-bzjphrajaq-uc.a.run.app';\nexport const DEFAULT_DASHBOARD_URL = 'https://algosuite.ai';\n\nexport interface RunPairingDeps {\n readonly env?: Record<string, string | undefined>;\n readonly log?: (message: string) => void;\n readonly fetchImpl?: typeof fetch;\n readonly sleep?: (ms: number) => Promise<void>;\n readonly now?: () => Date;\n /** Test seam: capture the stored credential instead of touching the real keychain. */\n readonly store?: (cred: StoredCredential, storedAtIso: string) => string;\n}\n\nexport interface PairingResult {\n readonly credentialPath: string;\n readonly expires_at: string;\n}\n\n/** ABCD-EFGH grouping for an 8-char code (easier to read aloud / type). */\nexport function formatPairingCode(code: string): string {\n return code.length === 8 ? `${code.slice(0, 4)}-${code.slice(4)}` : code;\n}\n\nasync function readJson(res: { json: () => Promise<unknown> }): Promise<Record<string, unknown>> {\n const body = await res.json().catch(() => ({}));\n return body && typeof body === 'object' ? (body as Record<string, unknown>) : {};\n}\n\n/**\n * Run the full pairing handshake. Resolves once a credential is stored; rejects\n * with a friendly message on expiry / consumption / fatal transport error.\n */\nexport async function runPairing(deps: RunPairingDeps = {}): Promise<PairingResult> {\n const env = deps.env ?? process.env;\n const log = deps.log ?? ((m: string) => console.error(m));\n const fetchImpl = deps.fetchImpl ?? fetch;\n const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const now = deps.now ?? (() => new Date());\n const store = deps.store ?? ((cred: StoredCredential, iso: string) => writeStoredCredential(cred, iso, env));\n\n const controlPlaneUrl = env['VO_CONTROL_PLANE_URL']?.trim() || DEFAULT_CONTROL_PLANE_URL;\n const dashboardUrl = env['VO_DASHBOARD_URL']?.trim() || DEFAULT_DASHBOARD_URL;\n const deviceLabel = `${platform()} on ${hostname()}`.slice(0, 120);\n\n // 1. initiate \u2014 get a display code + a secret poll token.\n const initRes = await fetchImpl(`${controlPlaneUrl}/api/v1/pair/initiate`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ device_label: deviceLabel }),\n });\n if (!initRes.ok) throw new Error(`Could not start pairing (server ${initRes.status}).`);\n const init = await readJson(initRes);\n const code = String(init['code'] ?? '');\n const pollToken = String(init['poll_token'] ?? '');\n if (!code || !pollToken) throw new Error('Pairing service returned an incomplete response.');\n const intervalMs = (Number(init['poll_interval_seconds']) || 5) * 1000;\n const expiresAtMs = new Date(String(init['expires_at'] ?? '')).getTime();\n\n // 2. show the friend what to do.\n log('');\n log(' To connect this runner, open this page in your browser:');\n log(` ${dashboardUrl}/pair`);\n log(' and enter this code:');\n log('');\n log(` ${formatPairingCode(code)}`);\n log('');\n log(' Your Anthropic key never leaves this computer. Waiting for you to authorize\u2026');\n\n // 3. poll with the SECRET token until authorized / expired.\n for (;;) {\n if (Number.isFinite(expiresAtMs) && now().getTime() >= expiresAtMs) {\n throw new Error('The pairing code expired before it was authorized. Run `vo-mcp pair` again.');\n }\n await sleep(intervalMs);\n const pollRes = await fetchImpl(`${controlPlaneUrl}/api/v1/pair/poll`, {\n method: 'GET',\n headers: { 'x-vo-poll-token': pollToken },\n });\n if (pollRes.status === 404) {\n throw new Error('The pairing expired. Run `vo-mcp pair` again.');\n }\n if (pollRes.status === 410) {\n throw new Error('This code was already used. Run `vo-mcp pair` again.');\n }\n if (!pollRes.ok) {\n // Transient (rate limit / blip) \u2014 keep waiting.\n continue;\n }\n const body = await readJson(pollRes);\n if (body['status'] === 'pending') continue;\n if (body['status'] === 'authorized' && typeof body['vo_credential'] === 'string') {\n const credentialPath = store(\n {\n vo_credential: body['vo_credential'] as string,\n ...(typeof body['expires_at'] === 'string'\n ? { vo_credential_expires_at: body['expires_at'] as string }\n : {}),\n },\n now().toISOString(),\n );\n return { credentialPath, expires_at: String(body['expires_at'] ?? '') };\n }\n throw new Error('Unexpected response from the pairing service.');\n }\n}\n", "/**\n * Local credential store for the thin-client `vo-mcp login` flow (Increment 3b,\n * Option A \u2014 `docs/vo/vo-command-center-inc3b-login-design-2026-06-05.md`).\n *\n * Persists the per-user Firebase refresh token (the user's OWN credential, never\n * the god-token, never model keys) captured by `login`, so the auto-refreshing\n * token source (Inc 3a) can mint fresh ID tokens across MCP restarts.\n *\n * Storage precedence (Inc 3b.3):\n * 1. **OS keychain** (Windows Credential Manager / macOS Keychain / libsecret)\n * via the optional `@napi-rs/keyring` backend (`keychain.ts`). The DEFAULT\n * when available \u2014 the secret never lands in plaintext on disk.\n * 2. **0600 file** at `$VO_MCP_CREDENTIALS_PATH` or `~/.config/vo-mcp/credentials.json`.\n * The fallback when the keychain is unavailable or disabled\n * (`VO_MCP_DISABLE_KEYCHAIN`). `VO_MCP_CREDENTIALS_PATH` only sets the file\n * LOCATION; force file storage with `VO_MCP_DISABLE_KEYCHAIN`.\n *\n * `env`-supplied tokens (`VO_USER_REFRESH_TOKEN`, etc.) still win over BOTH\n * stores \u2014 that precedence lives upstream in `auth-token-source.ts`.\n *\n * **Single source of truth.** The credential lives in EITHER the keychain OR the\n * file, never both: a write to one store CLEARS the other, so a stale entry can\n * never shadow the current credential on read, and the secret never lingers in\n * plaintext after a migration to the keychain.\n *\n * **Keychain durability.** A keychain-stored credential is only readable while\n * the `@napi-rs/keyring` native module loads. If the module later becomes\n * unavailable (an ABI break across a Node upgrade, a corrupted install), the\n * credential can't be read and the user re-runs `vo-mcp login` \u2014 the same\n * behaviour as `gh` / `gcloud` / `firebase` keychain storage. We deliberately do\n * NOT mirror the secret to a plaintext file as a fallback: that would defeat the\n * entire point of keychain storage (keeping the secret off plaintext disk).\n */\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n chmodSync,\n rmSync,\n} from 'node:fs';\n\nimport { keychainAvailable, keychainGet, keychainSet, keychainDelete } from './keychain.js';\n\nexport interface StoredCredential {\n /**\n * Firebase refresh token (long-lived; exchanged for short-lived ID tokens).\n * OPTIONAL since Inc 3b.4b: once a scoped `vo_credential` is minted, the raw\n * refresh token is dropped, so a stored credential may carry ONLY the vocred_.\n */\n readonly refresh_token?: string;\n /** Firebase Web API key (PUBLIC) needed for the securetoken refresh exchange. */\n readonly api_key?: string;\n /**\n * Scoped, revocable VO credential (`vocred_`) minted by the control-plane\n * (Inc 3b.4b). Preferred over the raw refresh token; lets the client present a\n * revocable, server-side credential instead of the Firebase refresh token.\n */\n readonly vo_credential?: string;\n /** ISO-8601 expiry of `vo_credential` (the client re-logs-in past this). */\n readonly vo_credential_expires_at?: string;\n /** The signed-in operator email (diagnostics only). */\n readonly email?: string;\n /** ISO timestamp the credential was stored. */\n readonly stored_at?: string;\n}\n\n/**\n * Pluggable OS-keychain backend. Defaults to the real `@napi-rs/keyring` wrapper;\n * tests inject a deterministic fake so they never touch the host keychain.\n */\nexport interface KeychainBackend {\n available(): boolean;\n get(): string | null;\n set(secret: string): boolean;\n delete(): boolean;\n}\n\nconst realKeychain: KeychainBackend = {\n available: keychainAvailable,\n get: keychainGet,\n set: keychainSet,\n delete: keychainDelete,\n};\n\n/** Human-readable \"location\" returned when the credential was stored in the OS keychain. */\nexport const KEYCHAIN_LOCATION = 'OS keychain (service \"vo-mcp\")';\n\n/** Resolve the credentials file path (env override \u2192 XDG-ish default under home). */\nexport function credentialPath(env: Readonly<Record<string, string | undefined>> = process.env): string {\n const override = env['VO_MCP_CREDENTIALS_PATH']?.trim();\n if (override) return override;\n return join(homedir(), '.config', 'vo-mcp', 'credentials.json');\n}\n\n/**\n * Whether the keychain should be consulted at all (read OR write). False when the\n * native backend is unavailable or `VO_MCP_DISABLE_KEYCHAIN` is set (CI/headless).\n */\nfunction keychainEnabled(\n env: Readonly<Record<string, string | undefined>>,\n keychain: KeychainBackend,\n): boolean {\n const disabled = (env['VO_MCP_DISABLE_KEYCHAIN'] ?? '').trim().toLowerCase();\n if (disabled === '1' || disabled === 'true' || disabled === 'yes') return false;\n return keychain.available();\n}\n\n/** Parse + validate a stored credential blob. Returns null on any problem (never throws). */\nfunction deserialize(raw: string): StoredCredential | null {\n try {\n const parsed = JSON.parse(raw) as Partial<StoredCredential>;\n const refresh = typeof parsed.refresh_token === 'string' ? parsed.refresh_token.trim() : '';\n const apiKey = typeof parsed.api_key === 'string' ? parsed.api_key.trim() : '';\n const voCred = typeof parsed.vo_credential === 'string' ? parsed.vo_credential.trim() : '';\n // Valid if it carries a scoped vocred_ OR a full Firebase refresh pair.\n if (!voCred && (!refresh || !apiKey)) return null;\n return {\n ...(refresh ? { refresh_token: refresh } : {}),\n ...(apiKey ? { api_key: apiKey } : {}),\n ...(voCred ? { vo_credential: voCred } : {}),\n ...(typeof parsed.vo_credential_expires_at === 'string' ? { vo_credential_expires_at: parsed.vo_credential_expires_at } : {}),\n ...(typeof parsed.email === 'string' ? { email: parsed.email } : {}),\n ...(typeof parsed.stored_at === 'string' ? { stored_at: parsed.stored_at } : {}),\n };\n } catch {\n return null;\n }\n}\n\nfunction readFromFile(env: Readonly<Record<string, string | undefined>>): StoredCredential | null {\n try {\n const p = credentialPath(env);\n if (!existsSync(p)) return null;\n return deserialize(readFileSync(p, 'utf8'));\n } catch {\n return null;\n }\n}\n\n/**\n * Read the stored credential, or `null` if absent/unreadable/invalid (never\n * throws). Consults an ENABLED keychain first (regardless of the write-target\n * flags, so a credential written to the keychain is found even if\n * `VO_MCP_CREDENTIALS_PATH` is later set), then the 0600 file.\n */\nexport function readStoredCredential(\n env: Readonly<Record<string, string | undefined>> = process.env,\n keychain: KeychainBackend = realKeychain,\n): StoredCredential | null {\n if (keychainEnabled(env, keychain)) {\n const raw = keychain.get();\n const fromKeychain = raw ? deserialize(raw) : null;\n if (fromKeychain) return fromKeychain;\n }\n return readFromFile(env);\n}\n\nfunction deleteFile(env: Readonly<Record<string, string | undefined>>): void {\n try {\n rmSync(credentialPath(env), { force: true });\n } catch {\n /* best-effort */\n }\n}\n\nfunction writeToFile(\n payload: StoredCredential,\n env: Readonly<Record<string, string | undefined>>,\n): string {\n const p = credentialPath(env);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, `${JSON.stringify(payload, null, 2)}\\n`, { mode: 0o600 });\n // Best-effort tighten (no-op / throws on some Windows filesystems \u2014 ignore).\n try {\n chmodSync(p, 0o600);\n } catch {\n /* best-effort */\n }\n return p;\n}\n\n/**\n * Persist the credential. Prefers the OS keychain (secret never hits plaintext\n * disk); otherwise writes the 0600 file. Writing to one store CLEARS the other\n * (single source of truth \u2014 no stale shadow, no lingering plaintext). Returns the\n * location it was stored (`KEYCHAIN_LOCATION` or the file path).\n */\nexport function writeStoredCredential(\n cred: StoredCredential,\n storedAt: string,\n env: Readonly<Record<string, string | undefined>> = process.env,\n keychain: KeychainBackend = realKeychain,\n): string {\n const payload: StoredCredential = {\n ...(cred.refresh_token ? { refresh_token: cred.refresh_token } : {}),\n ...(cred.api_key ? { api_key: cred.api_key } : {}),\n ...(cred.vo_credential ? { vo_credential: cred.vo_credential } : {}),\n ...(cred.vo_credential_expires_at ? { vo_credential_expires_at: cred.vo_credential_expires_at } : {}),\n ...(cred.email ? { email: cred.email } : {}),\n stored_at: cred.stored_at ?? storedAt,\n };\n if (keychainEnabled(env, keychain) && keychain.set(JSON.stringify(payload))) {\n // Stored in the keychain \u2192 clear any stale plaintext file so the secret\n // doesn't linger on disk and can't shadow the keychain on read.\n deleteFile(env);\n return KEYCHAIN_LOCATION;\n }\n const p = writeToFile(payload, env);\n // Stored in the file \u2192 clear any stale keychain entry so it can't shadow the\n // newer file credential on read.\n if (keychainEnabled(env, keychain)) keychain.delete();\n return p;\n}\n", "/**\n * Optional OS-keychain backend for the thin-client credential store (Increment\n * 3b.3 \u2014 `docs/vo/vo-command-center-inc3b-login-design-2026-06-05.md` \u00A75/\u00A76).\n *\n * Loads `@napi-rs/keyring` at runtime via `createRequire`, so it is a TRUE\n * optional dependency: if the native module is absent or fails to load\n * (unsupported platform, prebuilt binary missing, headless CI), every function\n * degrades to a no-op and the caller (`credential-store.ts`) falls back to the\n * 0600 file store. `@napi-rs/keyring`'s `Entry` API is SYNCHRONOUS, so the\n * credential store stays synchronous \u2014 no async ripple into the Inc-3a token\n * source that reads it.\n *\n * Why `createRequire` and not a static/dynamic `import`: a static import would\n * make the native module a HARD dependency (a missing prebuilt would crash the\n * MCP at startup); a dynamic `import()` is async (would force the whole read\n * path async). `createRequire(...)` inside a try/catch loads it lazily and\n * synchronously, and a load failure is just \"keychain unavailable\".\n */\nimport { createRequire } from 'node:module';\n\n/** Keychain service + account the single refresh credential is stored under. */\nconst SERVICE = 'vo-mcp';\nconst ACCOUNT = 'refresh-credential';\n\ninterface KeyringEntry {\n getPassword(): string | null;\n setPassword(password: string): void;\n deletePassword(): boolean;\n}\ninterface KeyringModule {\n Entry: new (service: string, account: string) => KeyringEntry;\n}\n\n// undefined = not yet attempted; null = attempted and unavailable.\nlet cached: KeyringModule | null | undefined;\n\nfunction loadKeyring(): KeyringModule | null {\n if (cached !== undefined) return cached;\n try {\n const req = createRequire(import.meta.url);\n const mod = req('@napi-rs/keyring') as Partial<KeyringModule>;\n cached = mod && typeof mod.Entry === 'function' ? (mod as KeyringModule) : null;\n } catch {\n cached = null;\n }\n return cached;\n}\n\n/** True when the OS keychain backend is usable in this runtime. */\nexport function keychainAvailable(): boolean {\n return loadKeyring() !== null;\n}\n\n/** Read the raw stored secret string from the OS keychain, or null. Never throws. */\nexport function keychainGet(): string | null {\n const k = loadKeyring();\n if (!k) return null;\n try {\n return new k.Entry(SERVICE, ACCOUNT).getPassword();\n } catch {\n return null;\n }\n}\n\n/** Store the raw secret string in the OS keychain. Returns true on success. Never throws. */\nexport function keychainSet(secret: string): boolean {\n const k = loadKeyring();\n if (!k) return false;\n try {\n new k.Entry(SERVICE, ACCOUNT).setPassword(secret);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Delete the stored secret from the OS keychain. Returns true if an entry was\n * removed. Never throws \u2014 a no-op (and `false`) when the backend is unavailable\n * or the entry is absent. Used to keep ONE source of truth: when the credential\n * is (re)written to the file, any stale keychain entry is cleared so it can't\n * shadow the newer file credential on read (and vice-versa).\n */\nexport function keychainDelete(): boolean {\n const k = loadKeyring();\n if (!k) return false;\n try {\n return new k.Entry(SERVICE, ACCOUNT).deletePassword();\n } catch {\n return false;\n }\n}\n\n/** Test-only seam to reset the memoised module load. */\nexport function __resetKeychainCache(): void {\n cached = undefined;\n}\n", "/**\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=VO 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 install` CLI entry point.\n *\n * Usage:\n * npx @algosuite/vo-mcp install\n * vo-mcp install\n */\nimport { install } from './install.js';\n\ninstall().catch((err: unknown) => {\n console.error('[vo-mcp install] fatal:', err);\n process.exit(1);\n});\n"],
5
- "mappings": "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",
6
- "names": ["homedir", "platform", "join", "dirname", "existsSync", "readFileSync", "writeFileSync", "mkdirSync", "copyFileSync", "credentialPath", "homedir", "platform", "join", "existsSync", "mkdirSync", "writeFileSync", "readFileSync", "join", "homedir", "mkdirSync", "existsSync", "readFileSync", "writeFileSync", "homedir", "join", "mkdirSync", "existsSync", "readFileSync", "writeFileSync", "platform", "DEFAULT_CONTROL_PLANE_URL", "join", "existsSync", "readFileSync", "mkdirSync", "dirname", "writeFileSync", "copyFileSync", "homedir", "platform"]
3
+ "sources": ["../src/install.ts", "../src/cloud/pairing.ts", "../src/cloud/credential-store.ts", "../src/cloud/keychain.ts", "../src/codex-mcp-config.ts", "../src/autostart.ts", "../src/install-cli.ts"],
4
+ "sourcesContent": ["/**\n * `vo-mcp install` \u2014 one-command client installer for non-coders.\n *\n * Configures Claude Desktop, Claude Code, and Codex to load vo-mcp; guides login; and\n * explains starting the runner. Cross-platform (Windows + macOS/Linux).\n *\n * Steps:\n * 1. Write/merge the MCP server config (backing up existing config).\n * 2. Pair via device code (`vo-mcp pair`) to mint the scoped credential \u2014 device\n * code (not loopback) so it works in every terminal (no 127.0.0.1 callback).\n * 3. Explain `vo-mcp runner` (not started here \u2014 user does it manually).\n * 4. Print clear next steps + success summary.\n */\nimport { homedir, platform } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { runPairing } from './cloud/pairing.js';\nimport { installCodexMcpConfigAt, resolveCodexConfigPath } from './codex-mcp-config.js';\n\n/** Live vo-control-plane Cloud Run URL \u2014 explicit (was derived from the dashboard\n * URL by string-replace, which silently broke when that default changed). */\nconst DEFAULT_CONTROL_PLANE_URL = 'https://vo-control-plane-bzjphrajaq-uc.a.run.app';\nimport { installAutostart } from './autostart.js';\n\nexport interface InstallOptions {\n readonly log?: (msg: string) => void;\n readonly skipLogin?: boolean;\n readonly skipAutostart?: boolean;\n readonly configOnly?: boolean;\n readonly env?: Readonly<Record<string, string | undefined>>;\n}\n\ninterface McpServerEntry {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n/**\n * Resolve the Claude config path. Prefers Claude Code's `.claude.json` in the\n * user home, else Claude Desktop's `claude_desktop_config.json` in the platform\n * config directory.\n */\n/** Claude Code CLI config path (~/.claude.json). `home` is injectable for tests. */\nfunction resolveCodeConfigPath(home: string): string {\n return join(home, '.claude.json');\n}\n\n/** Claude Desktop app config path (per-OS). Linux uses capital-C 'Claude'. */\nfunction resolveDesktopConfigPath(home: string, plat: NodeJS.Platform, appData?: string): string {\n if (plat === 'win32') {\n return join(appData ?? join(home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');\n }\n if (plat === 'darwin') {\n return join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');\n }\n // Linux / others \u2014 capital-C 'Claude' (matches the Claude Desktop app dir).\n return join(home, '.config', 'Claude', 'claude_desktop_config.json');\n}\n\n/**\n * Read + parse existing Claude config (or return empty shape if missing).\n * Never throws \u2014 returns a default shape on any problem.\n */\nfunction readClaudeConfig(path: string): Record<string, unknown> {\n try {\n if (!existsSync(path)) return {};\n const raw = readFileSync(path, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n // Preserve the FULL config \u2014 Claude Code's ~/.claude.json holds `projects`,\n // history, etc., and Desktop holds `preferences`. We must keep every key and\n // only touch mcpServers, or `install` would wipe the rest of the user's config.\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n // Malformed JSON \u2014 return empty; the caller backs up the original file before\n // any write, so the on-disk original is preserved either way.\n return {};\n }\n}\n\n/**\n * Write the Claude config, creating parent directories as needed. Writes with\n * 2-space indentation for human readability.\n */\nfunction writeClaudeConfig(path: string, config: Record<string, unknown>): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(config, null, 2)}\\n`, 'utf8');\n}\n\n/**\n * Resolve the absolute path to the vo-mcp CLI (dist/cli.js). Computes from\n * process.argv[1] which is the path to the currently running script\n * (dist/install-cli.js when invoked via `vo-mcp install`).\n */\nfunction resolveVoMcpCliPath(): string {\n // Resolve from this module, not process.argv[1]. When invoked as\n // `vo-mcp install`, argv[1] is the dispatcher under bin/; cli.js lives in dist/.\n return join(dirname(fileURLToPath(import.meta.url)), 'cli.js');\n}\n\n/**\n * Merge the vo-mcp MCP server entry into ONE config file. Preserves EVERY other\n * key (other mcpServers + top-level keys like Claude Code's `projects` or\n * Desktop's `preferences`) \u2014 only the `vo-mcp` entry is touched. Backs up first.\n * Idempotent: if `vo-mcp` already points at this cli.js, no-op.\n */\nfunction installMcpConfigAt(\n configPath: string,\n cliPath: string,\n controlPlaneUrl: string,\n log: (msg: string) => void,\n label: string,\n): void {\n const existing = readClaudeConfig(configPath);\n const mcpServers: Record<string, McpServerEntry> =\n existing['mcpServers'] && typeof existing['mcpServers'] === 'object'\n ? (existing['mcpServers'] as Record<string, McpServerEntry>)\n : {};\n\n // Idempotency: already wired to THIS cli.js? (re-points if the path changed.)\n const voEntry = mcpServers['vo'] ?? mcpServers['vo-mcp'];\n if (voEntry?.args?.some((a: string) => a.includes(cliPath))) {\n log(` ${label} already current: ${configPath}`);\n return;\n }\n\n // Backup before any write (protects the original even if it was malformed).\n if (existsSync(configPath)) {\n const backupPath = `${configPath}.backup-${Date.now()}`;\n copyFileSync(configPath, backupPath);\n log(` Backed up ${label} config \u2192 ${backupPath}`);\n }\n\n const merged: Record<string, unknown> = {\n ...existing,\n mcpServers: {\n ...mcpServers,\n 'vo-mcp': {\n command: 'node',\n args: [cliPath],\n // Preserve any existing env the user added (e.g. model API keys) \u2014 only\n // ensure VO_CONTROL_PLANE_URL is present. NEVER drop the user's env keys.\n env: { VO_CONTROL_PLANE_URL: controlPlaneUrl, ...(voEntry?.env ?? {}) },\n },\n },\n };\n writeClaudeConfig(configPath, merged);\n log(`\u2713 Wrote vo-mcp to ${label}: ${configPath}`);\n}\n\n/**\n * Wire vo-mcp into BOTH the Claude Code CLI (~/.claude.json) and the Claude\n * Desktop app config, so it loads in whichever the user runs. Each write is\n * idempotent + preserves all other config keys. ONLY VO_CONTROL_PLANE_URL (a\n * public URL) is written \u2014 never a secret.\n */\nfunction installMcpConfig(log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): void {\n // Resolve home from the injected env (tests pass a temp dir) \u2192 falls back to the\n // OS home. This keeps install hermetic: it never touches real configs in tests.\n const home = env['HOME']?.trim() || env['USERPROFILE']?.trim() || homedir();\n const appData = env['APPDATA']?.trim();\n const plat = platform();\n const cliPath = resolveVoMcpCliPath();\n const controlPlaneUrl = env['VO_CONTROL_PLANE_URL']?.trim() || DEFAULT_CONTROL_PLANE_URL;\n installMcpConfigAt(resolveCodeConfigPath(home), cliPath, controlPlaneUrl, log, 'Claude Code CLI');\n installMcpConfigAt(resolveDesktopConfigPath(home, plat, appData), cliPath, controlPlaneUrl, log, 'Claude Desktop');\n installCodexMcpConfigAt(resolveCodexConfigPath(home), cliPath, controlPlaneUrl, log);\n}\n\n/**\n * Run the DEVICE-CODE pairing flow (same as `vo-mcp pair`): a short code is shown,\n * the user enters it in their browser. Device code \u2014 NOT a loopback OAuth callback \u2014\n * so it works in every terminal (sandboxed/remote/SSH can't receive a 127.0.0.1\n * callback, which is why the old loopback `login` dead-ended at a \"link your terminal\"\n * page). Non-fatal: a pairing hiccup logs a retry hint and lets the install finish\n * (config + autostart are still useful; the user can run `vo-mcp pair` later).\n */\nasync function runPairFlow(log: (msg: string) => void, env: Readonly<Record<string, string | undefined>>): Promise<void> {\n log('\\n\u2501\u2501\u2501 Step 2: Link your VO account (device code) \u2501\u2501\u2501');\n log('A short code appears below \u2014 open the URL it prints and enter the code.');\n log('Your raw token never persists; a scoped credential is stored in your OS keychain.\\n');\n\n try {\n const result = await runPairing({ env, log });\n log(`\\n\u2713 Paired \u2014 scoped credential stored at: ${result.credentialPath}`);\n } catch (err: unknown) {\n log(`\\n\u26A0 Pairing didn't complete: ${err instanceof Error ? err.message : String(err)}`);\n log(' No problem \u2014 the rest will finish; pair anytime with: vo-mcp pair');\n }\n}\n\n/**\n * Print the runner guidance + success summary.\n */\nfunction printNextSteps(log: (msg: string) => void, autostartInstalled: boolean, configOnly: boolean): void {\n log('\\n\u2501\u2501\u2501 Installation complete! \u2501\u2501\u2501\\n');\n log('What\\'s configured:');\n log(' \u2713 Claude Desktop, Claude Code, and Codex will load AlgoHQ MCP on next restart');\n if (configOnly) {\n log(' \u2713 Existing pairing and runner auto-start settings were left unchanged');\n } else {\n log(' \u2713 Your scoped credential is stored (revocable via the dashboard)');\n }\n if (autostartInstalled) {\n log(' \u2713 Runner daemon will start automatically at login\\n');\n } else {\n log('\\n');\n }\n log('Next steps:');\n log(' 1. Restart Claude Desktop / Claude Code / Codex (if running).');\n if (configOnly) {\n log(' 2. Restart the existing AlgoHQ runner service or runner terminal.');\n } else if (autostartInstalled) {\n log(' 2. Log out and back in (or start the runner manually now: vo-mcp runner)');\n } else {\n log(' 2. Start the agent runner in a terminal (keep it running):');\n log(' vo-mcp runner');\n log(' (To set up auto-start at login: vo-mcp runner --install-autostart)');\n }\n log(' 3. Visit AlgoHQ to dispatch your first agent:');\n log(' https://algosuite.ai/algohq\\n');\n log('The runner watches for tasks you dispatch and spins up agents in fresh worktrees.');\n log('Agents only run while the runner is connected. Ctrl+C to stop it anytime.\\n');\n}\n\n/**\n * Run the full install flow: MCP config \u2192 login \u2192 auto-start \u2192 guidance.\n */\nexport async function install(opts: InstallOptions = {}): Promise<void> {\n const log = opts.log ?? ((m: string) => console.error(m));\n const env = opts.env ?? process.env;\n\n log('\u2501\u2501\u2501 vo-mcp installer \u2501\u2501\u2501');\n log('This will set up your machine to dispatch AlgoHQ agents from anywhere.\\n');\n\n // Step 1: MCP config\n log('\u2501\u2501\u2501 Step 1: Configure Claude Desktop / Claude Code / Codex \u2501\u2501\u2501');\n installMcpConfig(log, env);\n\n // Step 2: Pair via device code (unless skipped)\n if (!opts.skipLogin) {\n await runPairFlow(log, env);\n } else if (opts.configOnly) {\n log('\\n(Config-only refresh \u2014 existing pairing left unchanged.)');\n } else {\n log('\\n(Pairing skipped \u2014 run `vo-mcp pair` when ready.)');\n }\n\n // Step 3: Auto-start (unless skipped)\n let autostartInstalled = false;\n if (!opts.skipAutostart) {\n const plat = platform();\n if (plat === 'win32' || plat === 'darwin' || plat === 'linux') {\n log('\\n\u2501\u2501\u2501 Step 3: Set up auto-start \u2501\u2501\u2501');\n log('Would you like the runner daemon to start automatically at login?');\n log('(You can skip this and set it up later with: vo-mcp runner --install-autostart)\\n');\n await installAutostart({ log, env });\n autostartInstalled = true;\n }\n }\n\n // Step 4: Guidance\n printNextSteps(log, autostartInstalled, opts.configOnly === true);\n}\n\nexport function installOptionsFromArgs(args: readonly string[]): InstallOptions {\n const configOnly = args.includes('--config-only');\n return configOnly\n ? { configOnly: true, skipLogin: true, skipAutostart: true }\n : {};\n}\n", "/**\n * Device-code pairing for the BYO runner (M1) \u2014 the no-terminal-token onboarding.\n *\n * The runner calls the control-plane `pair/initiate`, shows the friend a short\n * `code` to type at `<dashboard>/pair`, then polls `pair/poll` with its SECRET\n * `poll_token` until the friend authorizes \u2014 at which point it receives a freshly\n * minted `vocred_` and stores it in the OS keychain (via writeStoredCredential).\n *\n * The friend's AI key NEVER flows through here \u2014 this only obtains the\n * control-plane credential the runner needs to claim THEIR tasks.\n */\nimport { hostname, platform } from 'node:os';\n\nimport { writeStoredCredential, type StoredCredential } from './credential-store.js';\n\nexport const DEFAULT_CONTROL_PLANE_URL = 'https://vo-control-plane-bzjphrajaq-uc.a.run.app';\nexport const DEFAULT_DASHBOARD_URL = 'https://algosuite.ai';\n\nexport interface RunPairingDeps {\n readonly env?: Record<string, string | undefined>;\n readonly log?: (message: string) => void;\n readonly fetchImpl?: typeof fetch;\n readonly sleep?: (ms: number) => Promise<void>;\n readonly now?: () => Date;\n /** Test seam: capture the stored credential instead of touching the real keychain. */\n readonly store?: (cred: StoredCredential, storedAtIso: string) => string;\n}\n\nexport interface PairingResult {\n readonly credentialPath: string;\n readonly expires_at: string;\n}\n\n/** ABCD-EFGH grouping for an 8-char code (easier to read aloud / type). */\nexport function formatPairingCode(code: string): string {\n return code.length === 8 ? `${code.slice(0, 4)}-${code.slice(4)}` : code;\n}\n\nasync function readJson(res: { json: () => Promise<unknown> }): Promise<Record<string, unknown>> {\n const body = await res.json().catch(() => ({}));\n return body && typeof body === 'object' ? (body as Record<string, unknown>) : {};\n}\n\n/**\n * Run the full pairing handshake. Resolves once a credential is stored; rejects\n * with a friendly message on expiry / consumption / fatal transport error.\n */\nexport async function runPairing(deps: RunPairingDeps = {}): Promise<PairingResult> {\n const env = deps.env ?? process.env;\n const log = deps.log ?? ((m: string) => console.error(m));\n const fetchImpl = deps.fetchImpl ?? fetch;\n const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const now = deps.now ?? (() => new Date());\n const store = deps.store ?? ((cred: StoredCredential, iso: string) => writeStoredCredential(cred, iso, env));\n\n const controlPlaneUrl = env['VO_CONTROL_PLANE_URL']?.trim() || DEFAULT_CONTROL_PLANE_URL;\n const dashboardUrl = env['VO_DASHBOARD_URL']?.trim() || DEFAULT_DASHBOARD_URL;\n const deviceLabel = `${platform()} on ${hostname()}`.slice(0, 120);\n\n // 1. initiate \u2014 get a display code + a secret poll token.\n const initRes = await fetchImpl(`${controlPlaneUrl}/api/v1/pair/initiate`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ device_label: deviceLabel }),\n });\n if (!initRes.ok) throw new Error(`Could not start pairing (server ${initRes.status}).`);\n const init = await readJson(initRes);\n const code = String(init['code'] ?? '');\n const pollToken = String(init['poll_token'] ?? '');\n if (!code || !pollToken) throw new Error('Pairing service returned an incomplete response.');\n const intervalMs = (Number(init['poll_interval_seconds']) || 5) * 1000;\n const expiresAtMs = new Date(String(init['expires_at'] ?? '')).getTime();\n\n // 2. show the friend what to do.\n log('');\n log(' To connect this runner, open this page in your browser:');\n log(` ${dashboardUrl}/pair`);\n log(' and enter this code:');\n log('');\n log(` ${formatPairingCode(code)}`);\n log('');\n log(' Your Anthropic key never leaves this computer. Waiting for you to authorize\u2026');\n\n // 3. poll with the SECRET token until authorized / expired.\n for (;;) {\n if (Number.isFinite(expiresAtMs) && now().getTime() >= expiresAtMs) {\n throw new Error('The pairing code expired before it was authorized. Run `vo-mcp pair` again.');\n }\n await sleep(intervalMs);\n const pollRes = await fetchImpl(`${controlPlaneUrl}/api/v1/pair/poll`, {\n method: 'GET',\n headers: { 'x-vo-poll-token': pollToken },\n });\n if (pollRes.status === 404) {\n throw new Error('The pairing expired. Run `vo-mcp pair` again.');\n }\n if (pollRes.status === 410) {\n throw new Error('This code was already used. Run `vo-mcp pair` again.');\n }\n if (!pollRes.ok) {\n // Transient (rate limit / blip) \u2014 keep waiting.\n continue;\n }\n const body = await readJson(pollRes);\n if (body['status'] === 'pending') continue;\n if (body['status'] === 'authorized' && typeof body['vo_credential'] === 'string') {\n const credentialPath = store(\n {\n vo_credential: body['vo_credential'] as string,\n ...(typeof body['expires_at'] === 'string'\n ? { vo_credential_expires_at: body['expires_at'] as string }\n : {}),\n },\n now().toISOString(),\n );\n return { credentialPath, expires_at: String(body['expires_at'] ?? '') };\n }\n throw new Error('Unexpected response from the pairing service.');\n }\n}\n", "/**\n * Local credential store for the thin-client `vo-mcp login` flow (Increment 3b,\n * Option A \u2014 `docs/vo/vo-command-center-inc3b-login-design-2026-06-05.md`).\n *\n * Persists the per-user Firebase refresh token (the user's OWN credential, never\n * the god-token, never model keys) captured by `login`, so the auto-refreshing\n * token source (Inc 3a) can mint fresh ID tokens across MCP restarts.\n *\n * Storage precedence (Inc 3b.3):\n * 1. **OS keychain** (Windows Credential Manager / macOS Keychain / libsecret)\n * via the optional `@napi-rs/keyring` backend (`keychain.ts`). The DEFAULT\n * when available \u2014 the secret never lands in plaintext on disk.\n * 2. **0600 file** at `$VO_MCP_CREDENTIALS_PATH` or `~/.config/vo-mcp/credentials.json`.\n * The fallback when the keychain is unavailable or disabled\n * (`VO_MCP_DISABLE_KEYCHAIN`). `VO_MCP_CREDENTIALS_PATH` only sets the file\n * LOCATION; force file storage with `VO_MCP_DISABLE_KEYCHAIN`.\n *\n * `env`-supplied tokens (`VO_USER_REFRESH_TOKEN`, etc.) still win over BOTH\n * stores \u2014 that precedence lives upstream in `auth-token-source.ts`.\n *\n * **Single source of truth.** The credential lives in EITHER the keychain OR the\n * file, never both: a write to one store CLEARS the other, so a stale entry can\n * never shadow the current credential on read, and the secret never lingers in\n * plaintext after a migration to the keychain.\n *\n * **Keychain durability.** A keychain-stored credential is only readable while\n * the `@napi-rs/keyring` native module loads. If the module later becomes\n * unavailable (an ABI break across a Node upgrade, a corrupted install), the\n * credential can't be read and the user re-runs `vo-mcp login` \u2014 the same\n * behaviour as `gh` / `gcloud` / `firebase` keychain storage. We deliberately do\n * NOT mirror the secret to a plaintext file as a fallback: that would defeat the\n * entire point of keychain storage (keeping the secret off plaintext disk).\n */\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n chmodSync,\n rmSync,\n} from 'node:fs';\n\nimport { keychainAvailable, keychainGet, keychainSet, keychainDelete } from './keychain.js';\n\nexport interface StoredCredential {\n /**\n * Firebase refresh token (long-lived; exchanged for short-lived ID tokens).\n * OPTIONAL since Inc 3b.4b: once a scoped `vo_credential` is minted, the raw\n * refresh token is dropped, so a stored credential may carry ONLY the vocred_.\n */\n readonly refresh_token?: string;\n /** Firebase Web API key (PUBLIC) needed for the securetoken refresh exchange. */\n readonly api_key?: string;\n /**\n * Scoped, revocable VO credential (`vocred_`) minted by the control-plane\n * (Inc 3b.4b). Preferred over the raw refresh token; lets the client present a\n * revocable, server-side credential instead of the Firebase refresh token.\n */\n readonly vo_credential?: string;\n /** ISO-8601 expiry of `vo_credential` (the client re-logs-in past this). */\n readonly vo_credential_expires_at?: string;\n /** The signed-in operator email (diagnostics only). */\n readonly email?: string;\n /** ISO timestamp the credential was stored. */\n readonly stored_at?: string;\n}\n\n/**\n * Pluggable OS-keychain backend. Defaults to the real `@napi-rs/keyring` wrapper;\n * tests inject a deterministic fake so they never touch the host keychain.\n */\nexport interface KeychainBackend {\n available(): boolean;\n get(): string | null;\n set(secret: string): boolean;\n delete(): boolean;\n}\n\nconst realKeychain: KeychainBackend = {\n available: keychainAvailable,\n get: keychainGet,\n set: keychainSet,\n delete: keychainDelete,\n};\n\n/** Human-readable \"location\" returned when the credential was stored in the OS keychain. */\nexport const KEYCHAIN_LOCATION = 'OS keychain (service \"vo-mcp\")';\n\n/** Resolve the credentials file path (env override \u2192 XDG-ish default under home). */\nexport function credentialPath(env: Readonly<Record<string, string | undefined>> = process.env): string {\n const override = env['VO_MCP_CREDENTIALS_PATH']?.trim();\n if (override) return override;\n return join(homedir(), '.config', 'vo-mcp', 'credentials.json');\n}\n\n/**\n * Whether the keychain should be consulted at all (read OR write). False when the\n * native backend is unavailable or `VO_MCP_DISABLE_KEYCHAIN` is set (CI/headless).\n */\nfunction keychainEnabled(\n env: Readonly<Record<string, string | undefined>>,\n keychain: KeychainBackend,\n): boolean {\n const disabled = (env['VO_MCP_DISABLE_KEYCHAIN'] ?? '').trim().toLowerCase();\n if (disabled === '1' || disabled === 'true' || disabled === 'yes') return false;\n return keychain.available();\n}\n\n/** Parse + validate a stored credential blob. Returns null on any problem (never throws). */\nfunction deserialize(raw: string): StoredCredential | null {\n try {\n const parsed = JSON.parse(raw) as Partial<StoredCredential>;\n const refresh = typeof parsed.refresh_token === 'string' ? parsed.refresh_token.trim() : '';\n const apiKey = typeof parsed.api_key === 'string' ? parsed.api_key.trim() : '';\n const voCred = typeof parsed.vo_credential === 'string' ? parsed.vo_credential.trim() : '';\n // Valid if it carries a scoped vocred_ OR a full Firebase refresh pair.\n if (!voCred && (!refresh || !apiKey)) return null;\n return {\n ...(refresh ? { refresh_token: refresh } : {}),\n ...(apiKey ? { api_key: apiKey } : {}),\n ...(voCred ? { vo_credential: voCred } : {}),\n ...(typeof parsed.vo_credential_expires_at === 'string' ? { vo_credential_expires_at: parsed.vo_credential_expires_at } : {}),\n ...(typeof parsed.email === 'string' ? { email: parsed.email } : {}),\n ...(typeof parsed.stored_at === 'string' ? { stored_at: parsed.stored_at } : {}),\n };\n } catch {\n return null;\n }\n}\n\nfunction readFromFile(env: Readonly<Record<string, string | undefined>>): StoredCredential | null {\n try {\n const p = credentialPath(env);\n if (!existsSync(p)) return null;\n return deserialize(readFileSync(p, 'utf8'));\n } catch {\n return null;\n }\n}\n\n/**\n * Read the stored credential, or `null` if absent/unreadable/invalid (never\n * throws). Consults an ENABLED keychain first (regardless of the write-target\n * flags, so a credential written to the keychain is found even if\n * `VO_MCP_CREDENTIALS_PATH` is later set), then the 0600 file.\n */\nexport function readStoredCredential(\n env: Readonly<Record<string, string | undefined>> = process.env,\n keychain: KeychainBackend = realKeychain,\n): StoredCredential | null {\n if (keychainEnabled(env, keychain)) {\n const raw = keychain.get();\n const fromKeychain = raw ? deserialize(raw) : null;\n if (fromKeychain) return fromKeychain;\n }\n return readFromFile(env);\n}\n\nfunction deleteFile(env: Readonly<Record<string, string | undefined>>): void {\n try {\n rmSync(credentialPath(env), { force: true });\n } catch {\n /* best-effort */\n }\n}\n\nfunction writeToFile(\n payload: StoredCredential,\n env: Readonly<Record<string, string | undefined>>,\n): string {\n const p = credentialPath(env);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, `${JSON.stringify(payload, null, 2)}\\n`, { mode: 0o600 });\n // Best-effort tighten (no-op / throws on some Windows filesystems \u2014 ignore).\n try {\n chmodSync(p, 0o600);\n } catch {\n /* best-effort */\n }\n return p;\n}\n\n/**\n * Persist the credential. Prefers the OS keychain (secret never hits plaintext\n * disk); otherwise writes the 0600 file. Writing to one store CLEARS the other\n * (single source of truth \u2014 no stale shadow, no lingering plaintext). Returns the\n * location it was stored (`KEYCHAIN_LOCATION` or the file path).\n */\nexport function writeStoredCredential(\n cred: StoredCredential,\n storedAt: string,\n env: Readonly<Record<string, string | undefined>> = process.env,\n keychain: KeychainBackend = realKeychain,\n): string {\n const payload: StoredCredential = {\n ...(cred.refresh_token ? { refresh_token: cred.refresh_token } : {}),\n ...(cred.api_key ? { api_key: cred.api_key } : {}),\n ...(cred.vo_credential ? { vo_credential: cred.vo_credential } : {}),\n ...(cred.vo_credential_expires_at ? { vo_credential_expires_at: cred.vo_credential_expires_at } : {}),\n ...(cred.email ? { email: cred.email } : {}),\n stored_at: cred.stored_at ?? storedAt,\n };\n if (keychainEnabled(env, keychain) && keychain.set(JSON.stringify(payload))) {\n // Stored in the keychain \u2192 clear any stale plaintext file so the secret\n // doesn't linger on disk and can't shadow the keychain on read.\n deleteFile(env);\n return KEYCHAIN_LOCATION;\n }\n const p = writeToFile(payload, env);\n // Stored in the file \u2192 clear any stale keychain entry so it can't shadow the\n // newer file credential on read.\n if (keychainEnabled(env, keychain)) keychain.delete();\n return p;\n}\n", "/**\n * Optional OS-keychain backend for the thin-client credential store (Increment\n * 3b.3 \u2014 `docs/vo/vo-command-center-inc3b-login-design-2026-06-05.md` \u00A75/\u00A76).\n *\n * Loads `@napi-rs/keyring` at runtime via `createRequire`, so it is a TRUE\n * optional dependency: if the native module is absent or fails to load\n * (unsupported platform, prebuilt binary missing, headless CI), every function\n * degrades to a no-op and the caller (`credential-store.ts`) falls back to the\n * 0600 file store. `@napi-rs/keyring`'s `Entry` API is SYNCHRONOUS, so the\n * credential store stays synchronous \u2014 no async ripple into the Inc-3a token\n * source that reads it.\n *\n * Why `createRequire` and not a static/dynamic `import`: a static import would\n * make the native module a HARD dependency (a missing prebuilt would crash the\n * MCP at startup); a dynamic `import()` is async (would force the whole read\n * path async). `createRequire(...)` inside a try/catch loads it lazily and\n * synchronously, and a load failure is just \"keychain unavailable\".\n */\nimport { createRequire } from 'node:module';\n\n/** Keychain service + account the single refresh credential is stored under. */\nconst SERVICE = 'vo-mcp';\nconst ACCOUNT = 'refresh-credential';\n\ninterface KeyringEntry {\n getPassword(): string | null;\n setPassword(password: string): void;\n deletePassword(): boolean;\n}\ninterface KeyringModule {\n Entry: new (service: string, account: string) => KeyringEntry;\n}\n\n// undefined = not yet attempted; null = attempted and unavailable.\nlet cached: KeyringModule | null | undefined;\n\nfunction loadKeyring(): KeyringModule | null {\n if (cached !== undefined) return cached;\n try {\n const req = createRequire(import.meta.url);\n const mod = req('@napi-rs/keyring') as Partial<KeyringModule>;\n cached = mod && typeof mod.Entry === 'function' ? (mod as KeyringModule) : null;\n } catch {\n cached = null;\n }\n return cached;\n}\n\n/** True when the OS keychain backend is usable in this runtime. */\nexport function keychainAvailable(): boolean {\n return loadKeyring() !== null;\n}\n\n/** Read the raw stored secret string from the OS keychain, or null. Never throws. */\nexport function keychainGet(): string | null {\n const k = loadKeyring();\n if (!k) return null;\n try {\n return new k.Entry(SERVICE, ACCOUNT).getPassword();\n } catch {\n return null;\n }\n}\n\n/** Store the raw secret string in the OS keychain. Returns true on success. Never throws. */\nexport function keychainSet(secret: string): boolean {\n const k = loadKeyring();\n if (!k) return false;\n try {\n new k.Entry(SERVICE, ACCOUNT).setPassword(secret);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Delete the stored secret from the OS keychain. Returns true if an entry was\n * removed. Never throws \u2014 a no-op (and `false`) when the backend is unavailable\n * or the entry is absent. Used to keep ONE source of truth: when the credential\n * is (re)written to the file, any stale keychain entry is cleared so it can't\n * shadow the newer file credential on read (and vice-versa).\n */\nexport function keychainDelete(): boolean {\n const k = loadKeyring();\n if (!k) return false;\n try {\n return new k.Entry(SERVICE, ACCOUNT).deletePassword();\n } catch {\n return false;\n }\n}\n\n/** Test-only seam to reset the memoised module load. */\nexport function __resetKeychainCache(): void {\n cached = undefined;\n}\n", "import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst MANAGED_BEGIN = '# BEGIN AlgoHQ MCP (managed by vo-mcp install)';\nconst MANAGED_END = '# END AlgoHQ MCP (managed by vo-mcp install)';\nconst MANAGED_SERVER_NAMES = new Set(['algohq', 'vo', 'vo-mcp', 'vo_mcp']);\n\ninterface TableSection {\n readonly path: readonly string[];\n readonly start: number;\n readonly end: number;\n}\n\nexport function resolveCodexConfigPath(home: string): string {\n return join(home, '.codex', 'config.toml');\n}\n\nfunction normalizeKey(value: string): string {\n const trimmed = value.trim();\n if ((trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction tablePath(line: string): string[] | null {\n const match = /^\\s*\\[([^\\r\\n]+)\\]\\s*(?:#.*)?$/.exec(line);\n const rawPath = match?.[1];\n if (!rawPath || rawPath.includes('[') || rawPath.includes(']')) return null;\n return rawPath.split('.').map(normalizeKey);\n}\n\nfunction tableSections(lines: readonly string[]): TableSection[] {\n const starts: Array<{ path: string[]; start: number }> = [];\n for (let index = 0; index < lines.length; index += 1) {\n const path = tablePath(lines[index] ?? '');\n if (path) starts.push({ path, start: index });\n }\n return starts.map((section, index) => ({\n ...section,\n end: starts[index + 1]?.start ?? lines.length,\n }));\n}\n\nfunction isManagedSection(section: TableSection): boolean {\n return section.path[0] === 'mcp_servers' && MANAGED_SERVER_NAMES.has(section.path[1] ?? '');\n}\n\nfunction assignmentKey(line: string): string | null {\n const match = /^\\s*((?:[A-Za-z0-9_-]+)|(?:\"[^\"]+\")|(?:'[^']+'))\\s*=/.exec(line);\n return match?.[1] ? normalizeKey(match[1]) : null;\n}\n\nfunction isStructurallySafeToml(raw: string): boolean {\n const lines = raw.split(/\\r?\\n/);\n const beginIndexes = lines.flatMap((line, index) => line.trim() === MANAGED_BEGIN ? [index] : []);\n const endIndexes = lines.flatMap((line, index) => line.trim() === MANAGED_END ? [index] : []);\n if (beginIndexes.length !== endIndexes.length || beginIndexes.length > 1) return false;\n if (beginIndexes[0] !== undefined && (endIndexes[0] ?? -1) <= beginIndexes[0]) return false;\n\n for (const line of lines) {\n const trimmed = line.trim();\n // Do not attempt to parse user-owned TOML. That would reject valid constructs\n // such as multiline strings. We only require managed-table headers to be\n // complete enough for the surgical section editor below to identify safely.\n if (/^\\[\\[?mcp_servers(?:\\.|\\s|$)/.test(trimmed) && tablePath(line) === null) return false;\n }\n return true;\n}\n\nfunction tomlString(value: string): string {\n return JSON.stringify(value);\n}\n\nfunction preservedSectionLines(\n lines: readonly string[],\n section: TableSection | undefined,\n managedKeys: ReadonlySet<string>,\n): string[] {\n if (!section) return [];\n return lines\n .slice(section.start + 1, section.end)\n .filter((line) => {\n if (line.trim() === MANAGED_BEGIN || line.trim() === MANAGED_END) return false;\n const key = assignmentKey(line);\n return key === null || !managedKeys.has(key);\n })\n .filter((line, index, all) => line.trim() !== '' || (index > 0 && index < all.length - 1));\n}\n\nexport function renderCodexMcpConfig(raw: string, cliPath: string, controlPlaneUrl: string): string {\n if (!isStructurallySafeToml(raw)) {\n throw new Error('Codex config is malformed; refusing to overwrite it');\n }\n\n const eol = raw.includes('\\r\\n') ? '\\r\\n' : '\\n';\n const lines = raw.split(/\\r?\\n/);\n const sections = tableSections(lines);\n const rootSections = sections.filter((section) => isManagedSection(section) && section.path.length === 2);\n const preferredRoot = rootSections.find((section) => section.path[1] === 'algohq') ?? rootSections[0];\n const preferredName = preferredRoot?.path[1];\n const envSection = sections.find((section) =>\n isManagedSection(section) && section.path[1] === preferredName && section.path[2] === 'env');\n const rootExtras = preservedSectionLines(lines, preferredRoot, new Set(['command', 'args', 'required']));\n const envExtras = preservedSectionLines(lines, envSection, new Set(['VO_CONTROL_PLANE_URL']));\n\n const removed = new Set<number>();\n const managedBegin = lines.findIndex((line) => line.trim() === MANAGED_BEGIN);\n const managedEnd = lines.findIndex((line) => line.trim() === MANAGED_END);\n if (managedBegin >= 0 && managedEnd >= managedBegin) {\n for (let index = managedBegin; index <= managedEnd; index += 1) removed.add(index);\n }\n for (const section of sections.filter(isManagedSection)) {\n for (let index = section.start; index < section.end; index += 1) removed.add(index);\n }\n\n const base = lines.filter((_line, index) => !removed.has(index)).join(eol).trimEnd();\n const block = [\n MANAGED_BEGIN,\n '[mcp_servers.algohq]',\n 'command = \"node\"',\n `args = [${tomlString(cliPath)}]`,\n 'required = true',\n ...rootExtras,\n '',\n '[mcp_servers.algohq.env]',\n `VO_CONTROL_PLANE_URL = ${tomlString(controlPlaneUrl)}`,\n ...envExtras,\n MANAGED_END,\n ].join(eol);\n return `${base}${base ? `${eol}${eol}` : ''}${block}${eol}`;\n}\n\nexport function installCodexMcpConfigAt(\n configPath: string,\n cliPath: string,\n controlPlaneUrl: string,\n log: (message: string) => void,\n): void {\n const exists = existsSync(configPath);\n const raw = exists ? readFileSync(configPath, 'utf8') : '';\n let rendered: string;\n try {\n rendered = renderCodexMcpConfig(raw, cliPath, controlPlaneUrl);\n } catch (error) {\n if (exists) {\n const backupPath = `${configPath}.backup-${Date.now()}`;\n copyFileSync(configPath, backupPath);\n log(` Backed up malformed Codex config \u2192 ${backupPath}`);\n }\n throw error;\n }\n if (rendered === raw) {\n log(` Codex already current: ${configPath}`);\n return;\n }\n if (exists) {\n const backupPath = `${configPath}.backup-${Date.now()}`;\n copyFileSync(configPath, backupPath);\n log(` Backed up Codex config \u2192 ${backupPath}`);\n }\n mkdirSync(dirname(configPath), { recursive: true });\n writeFileSync(configPath, rendered, 'utf8');\n log(`\u2713 Wrote AlgoHQ MCP to Codex: ${configPath}`);\n}\n", "/**\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=VO 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 install` CLI entry point.\n *\n * Usage:\n * npx @algosuite/vo-mcp install\n * vo-mcp install\n * vo-mcp install --config-only\n */\nimport { install, installOptionsFromArgs } from './install.js';\n\ninstall(installOptionsFromArgs(process.argv.slice(2))).catch((err: unknown) => {\n console.error('[vo-mcp install] fatal:', err);\n process.exit(1);\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["homedir", "platform", "join", "dirname", "existsSync", "readFileSync", "writeFileSync", "mkdirSync", "copyFileSync", "credentialPath", "existsSync", "mkdirSync", "readFileSync", "writeFileSync", "dirname", "join", "homedir", "platform", "join", "existsSync", "mkdirSync", "writeFileSync", "readFileSync", "copyFileSync", "join", "homedir", "mkdirSync", "existsSync", "readFileSync", "copyFileSync", "writeFileSync", "homedir", "join", "mkdirSync", "existsSync", "readFileSync", "copyFileSync", "writeFileSync", "platform", "DEFAULT_CONTROL_PLANE_URL", "join", "existsSync", "readFileSync", "mkdirSync", "dirname", "writeFileSync", "copyFileSync", "homedir", "platform"]
7
7
  }