panopticon-cli 0.5.4 → 0.5.6

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.
Files changed (119) hide show
  1. package/dist/{agents-HNMF52RM.js → agents-5HWTDR4S.js} +12 -9
  2. package/dist/archive-planning-U3AZAKWI.js +16 -0
  3. package/dist/{chunk-KBHRXV5T.js → chunk-43F4LDZ4.js} +3 -3
  4. package/dist/chunk-6OYUJ4AJ.js +146 -0
  5. package/dist/chunk-6OYUJ4AJ.js.map +1 -0
  6. package/dist/{chunk-MOPGR3CL.js → chunk-AAP4G6U7.js} +1 -1
  7. package/dist/chunk-AAP4G6U7.js.map +1 -0
  8. package/dist/{chunk-4HST45MO.js → chunk-BYWVPPAZ.js} +19 -12
  9. package/dist/chunk-BYWVPPAZ.js.map +1 -0
  10. package/dist/{chunk-CFCUOV3Q.js → chunk-DMRTN432.js} +4 -1
  11. package/dist/chunk-DMRTN432.js.map +1 -0
  12. package/dist/{chunk-HOGYHJ2G.js → chunk-DW3PKGIS.js} +2 -2
  13. package/dist/{chunk-KY2E2Q3T.js → chunk-FUUP55PE.js} +104 -46
  14. package/dist/chunk-FUUP55PE.js.map +1 -0
  15. package/dist/chunk-GUV2EPBG.js +692 -0
  16. package/dist/chunk-GUV2EPBG.js.map +1 -0
  17. package/dist/{chunk-44EOY2ZL.js → chunk-HHL3AWXA.js} +46 -2
  18. package/dist/chunk-HHL3AWXA.js.map +1 -0
  19. package/dist/{chunk-6N2KBSJA.js → chunk-IZIXJYXZ.js} +40 -6
  20. package/dist/chunk-IZIXJYXZ.js.map +1 -0
  21. package/dist/chunk-MJXYTGK5.js +64 -0
  22. package/dist/chunk-MJXYTGK5.js.map +1 -0
  23. package/dist/chunk-OJF4QS3S.js +269 -0
  24. package/dist/chunk-OJF4QS3S.js.map +1 -0
  25. package/dist/{chunk-FQ66DECN.js → chunk-QAJAJBFW.js} +1 -1
  26. package/dist/chunk-QAJAJBFW.js.map +1 -0
  27. package/dist/chunk-R4KPLLRB.js +36 -0
  28. package/dist/chunk-R4KPLLRB.js.map +1 -0
  29. package/dist/{chunk-DFNVHK3N.js → chunk-SUM2WVPF.js} +4 -4
  30. package/dist/{chunk-T7BBPDEJ.js → chunk-UKSGE6RH.js} +45 -15
  31. package/dist/chunk-UKSGE6RH.js.map +1 -0
  32. package/dist/chunk-W2OTF6OS.js +201 -0
  33. package/dist/chunk-W2OTF6OS.js.map +1 -0
  34. package/dist/chunk-WEQW3EAT.js +78 -0
  35. package/dist/chunk-WEQW3EAT.js.map +1 -0
  36. package/dist/{chunk-ID4OYXVH.js → chunk-WJJ3ZIQ6.js} +112 -45
  37. package/dist/chunk-WJJ3ZIQ6.js.map +1 -0
  38. package/dist/chunk-YAAT66RT.js +70 -0
  39. package/dist/chunk-YAAT66RT.js.map +1 -0
  40. package/dist/{chunk-RLZQB7HS.js → chunk-ZMJFEHGF.js} +13 -1
  41. package/dist/chunk-ZMJFEHGF.js.map +1 -0
  42. package/dist/{chunk-HRU7S4TA.js → chunk-ZN5RHWGR.js} +18 -208
  43. package/dist/{chunk-HRU7S4TA.js.map → chunk-ZN5RHWGR.js.map} +1 -1
  44. package/dist/{chunk-ZTYHZMEC.js → chunk-ZWZNEA26.js} +2 -2
  45. package/dist/clean-planning-7Z5YY64X.js +9 -0
  46. package/dist/cli/index.js +1301 -2142
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/close-issue-CTZK777I.js +9 -0
  49. package/dist/compact-beads-72SHALOL.js +9 -0
  50. package/dist/{config-4CJNUE3O.js → config-FFTMBVHM.js} +2 -2
  51. package/dist/dashboard/public/assets/{index-DSvt5pPn.css → index-Bx4NCn9A.css} +1 -1
  52. package/dist/dashboard/public/assets/index-Db9NOz4z.js +756 -0
  53. package/dist/dashboard/public/index.html +3 -2
  54. package/dist/dashboard/server.js +34714 -34296
  55. package/dist/{feedback-writer-T43PI5S2.js → feedback-writer-T2WCT6EZ.js} +2 -2
  56. package/dist/{hume-CKJJ3OUU.js → hume-GVTB5BKW.js} +3 -3
  57. package/dist/index.d.ts +24 -16
  58. package/dist/index.js +4 -4
  59. package/dist/label-cleanup-4HJVX6NP.js +103 -0
  60. package/dist/label-cleanup-4HJVX6NP.js.map +1 -0
  61. package/dist/merge-agent-WM7ZKUET.js +1725 -0
  62. package/dist/merge-agent-WM7ZKUET.js.map +1 -0
  63. package/dist/{projects-KVM3MN3Y.js → projects-3CRF57ZU.js} +2 -2
  64. package/dist/{rally-RKFSWC7E.js → rally-LBY24P4C.js} +2 -2
  65. package/dist/{remote-agents-ULPD6C5U.js → remote-agents-3NZPSHYG.js} +2 -3
  66. package/dist/{remote-workspace-XX6ARE6I.js → remote-workspace-M4IULGFZ.js} +24 -49
  67. package/dist/remote-workspace-M4IULGFZ.js.map +1 -0
  68. package/dist/{review-status-XKUKZF6J.js → review-status-J2YJGL3E.js} +2 -2
  69. package/dist/{specialist-context-C66TEMXS.js → specialist-context-74RQF5SR.js} +7 -5
  70. package/dist/{specialist-context-C66TEMXS.js.map → specialist-context-74RQF5SR.js.map} +1 -1
  71. package/dist/{specialist-logs-CJKXM3SR.js → specialist-logs-T5GW7CSU.js} +6 -4
  72. package/dist/{specialists-NXYD4Z62.js → specialists-HTYYFXHQ.js} +6 -4
  73. package/dist/specialists-HTYYFXHQ.js.map +1 -0
  74. package/dist/tmux-X2I5SAIJ.js +31 -0
  75. package/dist/tmux-X2I5SAIJ.js.map +1 -0
  76. package/dist/{traefik-5GL3Q7DJ.js → traefik-QXLZ4PO2.js} +4 -4
  77. package/dist/traefik-QXLZ4PO2.js.map +1 -0
  78. package/dist/{tunnel-BKC7KLBX.js → tunnel-7IOSRZVH.js} +3 -3
  79. package/dist/tunnel-7IOSRZVH.js.map +1 -0
  80. package/dist/{workspace-manager-ALBR62AS.js → workspace-manager-G6TTBPC3.js} +6 -6
  81. package/dist/workspace-manager-G6TTBPC3.js.map +1 -0
  82. package/package.json +2 -2
  83. package/scripts/build-cost-script.mjs +17 -0
  84. package/scripts/heartbeat-hook +28 -8
  85. package/scripts/record-cost-event.js +46 -7
  86. package/scripts/record-cost-event.ts +2 -1
  87. package/dist/chunk-44EOY2ZL.js.map +0 -1
  88. package/dist/chunk-4HST45MO.js.map +0 -1
  89. package/dist/chunk-565HZ6VV.js +0 -159
  90. package/dist/chunk-565HZ6VV.js.map +0 -1
  91. package/dist/chunk-6N2KBSJA.js.map +0 -1
  92. package/dist/chunk-CFCUOV3Q.js.map +0 -1
  93. package/dist/chunk-FQ66DECN.js.map +0 -1
  94. package/dist/chunk-ID4OYXVH.js.map +0 -1
  95. package/dist/chunk-KY2E2Q3T.js.map +0 -1
  96. package/dist/chunk-MOPGR3CL.js.map +0 -1
  97. package/dist/chunk-RLZQB7HS.js.map +0 -1
  98. package/dist/chunk-T7BBPDEJ.js.map +0 -1
  99. package/dist/chunk-ZDNQFWR5.js +0 -650
  100. package/dist/chunk-ZDNQFWR5.js.map +0 -1
  101. package/dist/dashboard/public/assets/index-DA6pnizT.js +0 -767
  102. package/dist/remote-workspace-XX6ARE6I.js.map +0 -1
  103. /package/dist/{agents-HNMF52RM.js.map → agents-5HWTDR4S.js.map} +0 -0
  104. /package/dist/{config-4CJNUE3O.js.map → archive-planning-U3AZAKWI.js.map} +0 -0
  105. /package/dist/{chunk-KBHRXV5T.js.map → chunk-43F4LDZ4.js.map} +0 -0
  106. /package/dist/{chunk-HOGYHJ2G.js.map → chunk-DW3PKGIS.js.map} +0 -0
  107. /package/dist/{chunk-DFNVHK3N.js.map → chunk-SUM2WVPF.js.map} +0 -0
  108. /package/dist/{chunk-ZTYHZMEC.js.map → chunk-ZWZNEA26.js.map} +0 -0
  109. /package/dist/{hume-CKJJ3OUU.js.map → clean-planning-7Z5YY64X.js.map} +0 -0
  110. /package/dist/{projects-KVM3MN3Y.js.map → close-issue-CTZK777I.js.map} +0 -0
  111. /package/dist/{rally-RKFSWC7E.js.map → compact-beads-72SHALOL.js.map} +0 -0
  112. /package/dist/{remote-agents-ULPD6C5U.js.map → config-FFTMBVHM.js.map} +0 -0
  113. /package/dist/{feedback-writer-T43PI5S2.js.map → feedback-writer-T2WCT6EZ.js.map} +0 -0
  114. /package/dist/{review-status-XKUKZF6J.js.map → hume-GVTB5BKW.js.map} +0 -0
  115. /package/dist/{specialist-logs-CJKXM3SR.js.map → projects-3CRF57ZU.js.map} +0 -0
  116. /package/dist/{specialists-NXYD4Z62.js.map → rally-LBY24P4C.js.map} +0 -0
  117. /package/dist/{traefik-5GL3Q7DJ.js.map → remote-agents-3NZPSHYG.js.map} +0 -0
  118. /package/dist/{tunnel-BKC7KLBX.js.map → review-status-J2YJGL3E.js.map} +0 -0
  119. /package/dist/{workspace-manager-ALBR62AS.js.map → specialist-logs-T5GW7CSU.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/remote/exe-provider.ts"],"sourcesContent":["/**\n * exe.dev Remote Provider\n *\n * Implements the RemoteProvider interface for exe.dev cloud VMs.\n * exe.dev provides affordable dev VMs with persistent storage.\n *\n * exe.dev uses an SSH-based API:\n * - `ssh exe.dev` - Access the CLI\n * - `ssh exe.dev new` - Create a new VM\n * - `ssh exe.dev ls` - List VMs\n * - `ssh vmname.exe.xyz` - SSH into a VM\n *\n * Pricing (as of 2025):\n * - Individual: $20/month, 8GB RAM\n * - Team: $25/month/user, 8GB RAM\n * - Enterprise: $30/month/user, 16GB RAM\n *\n * @see https://exe.dev/docs\n */\n\nimport { exec, spawn } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync, readFileSync, readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type {\n RemoteProvider,\n VmInfo,\n VmStatus,\n ExecResult,\n} from './interface.js';\n\nconst execAsync = promisify(exec);\n\nexport interface ExeProviderConfig {\n /** Shared infrastructure VM name (for postgres, redis, traefik) */\n infraVm?: string;\n}\n\n/**\n * Parse exe.dev ls output for VM list\n * Format appears to be: vmname (status info)\n */\nfunction parseVmList(output: string): VmInfo[] {\n const vms: VmInfo[] = [];\n const lines = output.trim().split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('Your VMs')) continue;\n\n // exe.dev format: \" • pan-pan-81-ws.exe.xyz - running (boldsoftware/exeuntu)\"\n // Extract VM name (without .exe.xyz suffix) and status\n const match = trimmed.match(/[•\\-]\\s*([a-z0-9-]+)\\.exe\\.xyz\\s*-\\s*(\\w+)/i);\n if (match) {\n const name = match[1];\n const statusText = match[2].toLowerCase();\n const status: VmStatus = statusText === 'running' ? 'running' :\n statusText === 'stopped' ? 'stopped' : 'unknown';\n vms.push({ name, status });\n }\n }\n\n return vms;\n}\n\n/**\n * Check if SSH key is configured for exe.dev\n */\nasync function canSshToExeDev(): Promise<boolean> {\n try {\n // Try a quick command - ssh exe.dev ls should work if authenticated\n const { stdout } = await execAsync('ssh -o BatchMode=yes -o ConnectTimeout=5 exe.dev ls 2>&1', {\n timeout: 10000,\n });\n // If we get output without permission denied, we're good\n return !stdout.includes('Permission denied') && !stdout.includes('Host key verification failed');\n } catch (error: any) {\n // Check if it's just an empty list (which is fine)\n if (error.stdout && !error.stdout.includes('Permission denied')) {\n return true;\n }\n return false;\n }\n}\n\nexport class ExeProvider implements RemoteProvider {\n readonly name = 'exe';\n private config: ExeProviderConfig;\n\n constructor(config: ExeProviderConfig = {}) {\n this.config = config;\n }\n\n /**\n * Check if user is authenticated with exe.dev\n * This checks if SSH key is configured and can connect\n */\n async isAuthenticated(): Promise<boolean> {\n return canSshToExeDev();\n }\n\n /**\n * Execute a command on the exe.dev CLI (via ssh exe.dev)\n */\n private async exeCmd(command: string): Promise<ExecResult> {\n try {\n const { stdout, stderr } = await execAsync(`ssh exe.dev ${command}`, {\n timeout: 60000,\n maxBuffer: 10 * 1024 * 1024,\n });\n return { stdout, stderr, exitCode: 0 };\n } catch (error: any) {\n return {\n stdout: error.stdout || '',\n stderr: error.stderr || error.message,\n exitCode: error.code || 1,\n };\n }\n }\n\n /**\n * Create a new VM on exe.dev\n */\n async createVm(name: string): Promise<VmInfo> {\n try {\n // exe.dev uses --name flag, and names must be valid hostnames\n const result = await this.exeCmd(`new --name=${name}`);\n\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create VM: ${result.stderr}`);\n }\n\n // Wait a moment for VM to be ready\n await new Promise(resolve => setTimeout(resolve, 5000));\n\n return { name, status: 'running' };\n } catch (error: any) {\n throw new Error(`Failed to create VM ${name}: ${error.message}`);\n }\n }\n\n /**\n * Delete a VM on exe.dev\n */\n async deleteVm(name: string): Promise<void> {\n try {\n const result = await this.exeCmd(`rm ${name}`);\n\n if (result.exitCode !== 0 && !result.stderr.includes('not found')) {\n throw new Error(result.stderr);\n }\n } catch (error: any) {\n throw new Error(`Failed to delete VM ${name}: ${error.message}`);\n }\n }\n\n /**\n * List all VMs\n */\n async listVms(): Promise<VmInfo[]> {\n try {\n const result = await this.exeCmd('ls');\n\n if (result.exitCode !== 0) {\n throw new Error(result.stderr);\n }\n\n return parseVmList(result.stdout);\n } catch (error: any) {\n throw new Error(`Failed to list VMs: ${error.message}`);\n }\n }\n\n /**\n * Get VM status\n */\n async getStatus(name: string): Promise<VmStatus> {\n try {\n const vms = await this.listVms();\n const vm = vms.find(v => v.name === name);\n return vm?.status || 'unknown';\n } catch {\n return 'unknown';\n }\n }\n\n /**\n * Get detailed VM info\n */\n async getVmInfo(name: string): Promise<VmInfo | null> {\n try {\n const vms = await this.listVms();\n return vms.find(v => v.name === name) || null;\n } catch {\n return null;\n }\n }\n\n /**\n * Start a stopped VM\n * Note: exe.dev VMs are persistent and always running\n */\n async startVm(name: string): Promise<void> {\n // exe.dev VMs don't have start/stop - they're always running\n // Check if VM exists\n const status = await this.getStatus(name);\n if (status === 'unknown') {\n throw new Error(`VM ${name} not found`);\n }\n }\n\n /**\n * Stop a running VM\n * Note: exe.dev VMs are persistent - use rm to delete\n */\n async stopVm(name: string): Promise<void> {\n // exe.dev doesn't have stop - VMs are always running or deleted\n // We can implement \"stop\" as a no-op or throw\n console.warn(`exe.dev VMs cannot be stopped, only deleted. VM ${name} continues running.`);\n }\n\n /**\n * Execute a command on VM via SSH\n * SSH to vmname.exe.xyz\n */\n async ssh(vm: string, command: string): Promise<ExecResult> {\n try {\n const sshHost = `${vm}.exe.xyz`;\n const escapedCmd = command.replace(/\"/g, '\\\\\"');\n\n // Use -A for agent forwarding so the VM can access GitHub with user's SSH keys\n const { stdout, stderr } = await execAsync(`ssh -A ${sshHost} \"${escapedCmd}\"`, {\n timeout: 300000, // 5 minutes\n maxBuffer: 50 * 1024 * 1024, // 50MB\n });\n\n return { stdout, stderr, exitCode: 0 };\n } catch (error: any) {\n return {\n stdout: error.stdout || '',\n stderr: error.stderr || error.message,\n exitCode: error.code || 1,\n };\n }\n }\n\n /**\n * Execute a command and stream output\n */\n async *sshStream(vm: string, command: string): AsyncIterable<string> {\n const sshHost = `${vm}.exe.xyz`;\n // Use -A for agent forwarding\n const child = spawn('ssh', ['-A', sshHost, command], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n for await (const chunk of child.stdout) {\n yield chunk.toString();\n }\n\n for await (const chunk of child.stderr) {\n yield chunk.toString();\n }\n }\n\n /**\n * Copy file to VM\n */\n async copyToVm(vm: string, localPath: string, remotePath: string): Promise<void> {\n try {\n const sshHost = `${vm}.exe.xyz`;\n await execAsync(`scp \"${localPath}\" ${sshHost}:${remotePath}`, { timeout: 300000 });\n } catch (error: any) {\n throw new Error(`Failed to copy ${localPath} to ${vm}:${remotePath}: ${error.message}`);\n }\n }\n\n /**\n * Copy file from VM\n */\n async copyFromVm(vm: string, remotePath: string, localPath: string): Promise<void> {\n try {\n const sshHost = `${vm}.exe.xyz`;\n await execAsync(`scp ${sshHost}:${remotePath} \"${localPath}\"`, { timeout: 300000 });\n } catch (error: any) {\n throw new Error(`Failed to copy ${vm}:${remotePath} to ${localPath}: ${error.message}`);\n }\n }\n\n /**\n * Expose a port on VM (returns public URL)\n *\n * exe.dev provides automatic HTTPS URLs for services:\n * https://vmname.exe.xyz:PORT\n */\n async exposePort(vm: string, port: number): Promise<string> {\n // exe.dev automatically exposes all ports via HTTPS\n // The URL format is: https://vmname.exe.xyz:PORT\n // Or for default HTTP (80/443): https://vmname.exe.xyz\n if (port === 80 || port === 443) {\n return `https://${vm}.exe.xyz`;\n }\n return `https://${vm}.exe.xyz:${port}`;\n }\n\n /**\n * Create SSH tunnel to VM\n */\n async tunnel(vm: string, remotePort: number, localPort: number): Promise<{ close: () => void }> {\n const sshHost = `${vm}.exe.xyz`;\n const child = spawn('ssh', ['-N', '-L', `${localPort}:localhost:${remotePort}`, sshHost], {\n stdio: 'ignore',\n detached: true,\n });\n\n child.unref();\n\n return {\n close: () => {\n child.kill();\n },\n };\n }\n\n /**\n * Get the configured infrastructure VM name\n */\n getInfraVm(): string | undefined {\n return this.config.infraVm;\n }\n\n /**\n * Initialize the shared infrastructure VM\n *\n * Sets up postgres, redis, and traefik on a dedicated VM.\n */\n async initInfrastructure(vmName: string): Promise<void> {\n // Check if VM exists\n let status = await this.getStatus(vmName);\n\n if (status === 'unknown') {\n // Create the VM\n await this.createVm(vmName);\n // Wait for it to be ready\n await new Promise(resolve => setTimeout(resolve, 10000));\n }\n\n // Install Docker if not present\n const dockerCheck = await this.ssh(vmName, 'which docker');\n if (dockerCheck.exitCode !== 0) {\n await this.ssh(vmName, 'curl -fsSL https://get.docker.com | sh');\n await this.ssh(vmName, 'sudo usermod -aG docker $USER');\n }\n\n // Create docker-compose.yml for shared services\n const composeContent = `\nversion: '3.8'\nservices:\n postgres:\n image: postgres:16\n restart: unless-stopped\n environment:\n POSTGRES_PASSWORD: \\${PAN_POSTGRES_PASSWORD:-panopticon}\n volumes:\n - postgres_data:/var/lib/postgresql/data\n ports:\n - \"5432:5432\"\n\n redis:\n image: redis:7\n restart: unless-stopped\n volumes:\n - redis_data:/data\n ports:\n - \"6379:6379\"\n\n traefik:\n image: traefik:v3.0\n restart: unless-stopped\n ports:\n - \"80:80\"\n - \"443:443\"\n - \"8080:8080\"\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock:ro\n command:\n - --api.dashboard=true\n - --providers.docker=true\n - --providers.docker.exposedbydefault=false\n - --entrypoints.web.address=:80\n - --entrypoints.websecure.address=:443\n\nvolumes:\n postgres_data:\n redis_data:\n`;\n\n // Write compose file and start services\n await this.ssh(vmName, `mkdir -p /opt/panopticon && cat > /opt/panopticon/docker-compose.yml << 'COMPOSE_EOF'\n${composeContent}\nCOMPOSE_EOF`);\n\n await this.ssh(vmName, 'cd /opt/panopticon && docker compose up -d');\n\n // Store as infra VM\n this.config.infraVm = vmName;\n }\n\n /**\n * Sync Claude Code credentials from local macOS Keychain to remote VM\n *\n * This should be called before spawning agents to ensure fresh credentials.\n * Credentials can expire, and re-running this ensures the VM has valid auth.\n *\n * @returns true if credentials were synced, false if not available\n */\n async syncClaudeCredentials(vmName: string): Promise<boolean> {\n try {\n // Get credentials from macOS Keychain\n const { stdout: credentials } = await execAsync(\n 'security find-generic-password -s \"Claude Code-credentials\" -w 2>/dev/null',\n { encoding: 'utf-8' }\n );\n\n if (!credentials || !credentials.trim()) {\n return false;\n }\n\n // Ensure ~/.claude directory exists\n await this.ssh(vmName, 'mkdir -p ~/.claude');\n\n // Send credentials to VM (base64 encode to handle special characters)\n const credsBase64 = Buffer.from(credentials.trim()).toString('base64');\n const result = await this.ssh(vmName, `echo '${credsBase64}' | base64 -d > ~/.claude/.credentials.json`);\n\n return result.exitCode === 0;\n } catch (error: any) {\n // Credentials not found in Keychain or other error\n return false;\n }\n }\n\n /**\n * Sync GitHub CLI authentication from local macOS to remote VM\n *\n * GitHub CLI on macOS stores tokens in Keychain. On Linux VMs, it stores\n * them directly in ~/.config/gh/hosts.yml. This extracts from Keychain\n * and writes to the VM's config file.\n *\n * @returns true if auth was synced, false if not available\n */\n async syncGitHubAuth(vmName: string): Promise<boolean> {\n try {\n // Get GitHub token from macOS Keychain\n const { stdout: tokenRaw } = await execAsync(\n 'security find-generic-password -s \"gh:github.com\" -w 2>/dev/null',\n { encoding: 'utf-8' }\n );\n\n if (!tokenRaw || !tokenRaw.trim()) {\n return false;\n }\n\n // The token may be base64-encoded with go-keyring prefix\n let token = tokenRaw.trim();\n if (token.startsWith('go-keyring-base64:')) {\n token = Buffer.from(token.replace('go-keyring-base64:', ''), 'base64').toString('utf-8');\n }\n\n // Get GitHub username from local config\n let username = 'user';\n try {\n const { stdout: configOutput } = await execAsync('cat ~/.config/gh/hosts.yml 2>/dev/null', { encoding: 'utf-8' });\n const userMatch = configOutput.match(/user:\\s*(\\S+)/);\n if (userMatch) {\n username = userMatch[1];\n }\n } catch {\n // Use default\n }\n\n // Create hosts.yml content for Linux (token stored directly in file)\n const hostsYml = `github.com:\n oauth_token: ${token}\n git_protocol: ssh\n user: ${username}\n`;\n\n // Ensure ~/.config/gh directory exists and write hosts.yml\n await this.ssh(vmName, 'mkdir -p ~/.config/gh');\n const hostsBase64 = Buffer.from(hostsYml).toString('base64');\n const result = await this.ssh(vmName, `echo '${hostsBase64}' | base64 -d > ~/.config/gh/hosts.yml && chmod 600 ~/.config/gh/hosts.yml`);\n\n return result.exitCode === 0;\n } catch (error: any) {\n // Token not found in Keychain or other error\n return false;\n }\n }\n\n /**\n * Sync GitLab CLI (glab) authentication to a remote VM\n *\n * Copies the glab config from local machine to the remote VM.\n * This allows the remote agent to use glab commands for MRs, etc.\n */\n async syncGitLabAuth(vmName: string): Promise<boolean> {\n try {\n // glab stores config in ~/.config/glab-cli/config.yml\n const glabConfigPath = join(homedir(), '.config', 'glab-cli', 'config.yml');\n\n if (!existsSync(glabConfigPath)) {\n console.log(`[exe-provider] No glab config found at ${glabConfigPath}`);\n return false;\n }\n\n // Read local glab config\n const glabConfig = readFileSync(glabConfigPath, 'utf-8');\n\n // Ensure ~/.config/glab-cli directory exists on remote\n await this.ssh(vmName, 'mkdir -p ~/.config/glab-cli');\n\n // Write config to remote\n const configBase64 = Buffer.from(glabConfig).toString('base64');\n const result = await this.ssh(vmName, `echo '${configBase64}' | base64 -d > ~/.config/glab-cli/config.yml && chmod 600 ~/.config/glab-cli/config.yml`);\n\n if (result.exitCode === 0) {\n console.log(`[exe-provider] GitLab auth synced to ${vmName}`);\n return true;\n }\n\n return false;\n } catch (error: any) {\n console.error(`[exe-provider] Failed to sync GitLab auth: ${error.message}`);\n return false;\n }\n }\n\n /**\n * Sync all credentials needed for remote workspace operation\n *\n * This syncs:\n * - Claude Code OAuth credentials\n * - GitHub CLI authentication\n *\n * Call this before spawning agents to ensure fresh credentials.\n *\n * @returns object with sync status for each credential type\n */\n async syncAllCredentials(vmName: string): Promise<{\n claude: boolean;\n github: boolean;\n }> {\n const [claude, github] = await Promise.all([\n this.syncClaudeCredentials(vmName),\n this.syncGitHubAuth(vmName),\n ]);\n\n return { claude, github };\n }\n\n /**\n * Install beads CLI (bd) on a remote VM\n *\n * Beads is required for planning agents to create task breakdowns.\n * Downloads the binary from GitHub releases since npm/node are often\n * not available on exe.dev VMs.\n *\n * @returns true if bd is available (already installed or just installed)\n */\n async installBeads(vmName: string): Promise<boolean> {\n const FALLBACK_BEADS_VERSION = '0.49.4';\n\n try {\n // Check if bd is already installed\n const checkResult = await this.ssh(vmName, 'which bd');\n if (checkResult.exitCode === 0 && checkResult.stdout.trim()) {\n console.log(`[exe-provider] bd already installed on ${vmName}`);\n return true;\n }\n\n console.log(`[exe-provider] Installing bd (beads CLI) on ${vmName}...`);\n\n // Download from GitHub releases - exe.dev VMs typically don't have npm/node\n // but do have curl and sudo access.\n // Resolve the latest version dynamically with fallback to known-good version.\n const installCmd = `\n cd /tmp && \\\n BEADS_VERSION=$(curl -sI \"https://github.com/steveyegge/beads/releases/latest\" 2>/dev/null | grep -i '^location:' | sed 's|.*/v||' | tr -d '\\\\r\\\\n') && \\\n if [ -z \"$BEADS_VERSION\" ]; then BEADS_VERSION=\"${FALLBACK_BEADS_VERSION}\"; echo \"Using fallback version: $BEADS_VERSION\"; else echo \"Detected version: $BEADS_VERSION\"; fi && \\\n echo \"Downloading beads v$BEADS_VERSION...\" && \\\n curl -sL \"https://github.com/steveyegge/beads/releases/download/v\\${BEADS_VERSION}/beads_\\${BEADS_VERSION}_linux_amd64.tar.gz\" -o beads.tar.gz && \\\n tar -xzf beads.tar.gz && \\\n sudo mv bd /usr/local/bin/ && \\\n rm -f beads.tar.gz CHANGELOG.md LICENSE README.md\n `.trim().replace(/\\n\\s+/g, ' ');\n\n const installResult = await this.ssh(vmName, installCmd);\n if (installResult.stderr) {\n console.log(`[exe-provider] bd install stderr on ${vmName}: ${installResult.stderr}`);\n }\n if (installResult.stdout) {\n console.log(`[exe-provider] bd install output on ${vmName}: ${installResult.stdout.trim()}`);\n }\n\n // Verify installation\n const verifyResult = await this.ssh(vmName, 'which bd && bd --version');\n if (verifyResult.exitCode === 0 && verifyResult.stdout.includes('bd version')) {\n console.log(`[exe-provider] bd installed successfully on ${vmName}: ${verifyResult.stdout.trim()}`);\n return true;\n }\n\n console.warn(`[exe-provider] Failed to install bd on ${vmName} - verify exitCode: ${verifyResult.exitCode}, stdout: ${verifyResult.stdout}, stderr: ${verifyResult.stderr}`);\n return false;\n } catch (error: any) {\n console.error(`[exe-provider] Error installing bd on ${vmName}:`, error.message);\n return false;\n }\n }\n\n /**\n * Initialize beads in a workspace on a remote VM\n *\n * Creates .beads/ directory and initializes the database if needed.\n */\n async initBeads(vmName: string, workspacePath: string = '/workspace'): Promise<boolean> {\n try {\n // Check if .beads already exists\n const checkResult = await this.ssh(vmName, `test -d ${workspacePath}/.beads && echo \"exists\"`);\n if (checkResult.stdout.includes('exists')) {\n console.log(`[exe-provider] .beads already initialized on ${vmName}`);\n return true;\n }\n\n console.log(`[exe-provider] Initializing beads on ${vmName}...`);\n\n // Initialize beads in the workspace\n const initResult = await this.ssh(vmName, `cd ${workspacePath} && bd init 2>/dev/null || true`);\n\n // Verify\n const verifyResult = await this.ssh(vmName, `test -d ${workspacePath}/.beads && echo \"ok\"`);\n if (verifyResult.stdout.includes('ok')) {\n console.log(`[exe-provider] beads initialized on ${vmName}`);\n return true;\n }\n\n // If bd init failed, create the directory manually\n await this.ssh(vmName, `mkdir -p ${workspacePath}/.beads`);\n return true;\n } catch (error: any) {\n console.error(`[exe-provider] Error initializing beads on ${vmName}:`, error.message);\n return false;\n }\n }\n\n /**\n * Sync beads from remote VM to git\n *\n * Exports beads database to JSONL, commits, and pushes.\n * This should be called after planning completes to persist tasks.\n */\n async syncBeadsToGit(vmName: string, workspacePath: string = '/workspace', commitMessage?: string): Promise<boolean> {\n try {\n console.log(`[exe-provider] Syncing beads to git on ${vmName}...`);\n\n // Export beads to JSONL\n const syncResult = await this.ssh(vmName, `cd ${workspacePath} && bd sync 2>/dev/null || true`);\n\n // Check if there are changes to commit\n const statusResult = await this.ssh(vmName, `cd ${workspacePath} && git status --porcelain .beads/ .planning/ 2>/dev/null`);\n\n if (!statusResult.stdout.trim()) {\n console.log(`[exe-provider] No beads changes to commit on ${vmName}`);\n return true;\n }\n\n // Add and commit\n const msg = commitMessage || 'Sync beads from planning session';\n await this.ssh(vmName, `cd ${workspacePath} && git add .beads/ && git add -f .planning/ 2>/dev/null || true`);\n await this.ssh(vmName, `cd ${workspacePath} && git commit -m \"${msg}\" 2>/dev/null || true`);\n\n // Push - use -u to set upstream if not already set\n const branchResult = await this.ssh(vmName, `cd ${workspacePath} && git branch --show-current`);\n const branch = branchResult.stdout.trim() || 'main';\n const pushResult = await this.ssh(vmName, `cd ${workspacePath} && git push -u origin ${branch} 2>&1`);\n if (pushResult.exitCode !== 0) {\n console.warn(`[exe-provider] Git push failed on ${vmName}: ${pushResult.stderr || pushResult.stdout}`);\n return false;\n }\n\n console.log(`[exe-provider] Beads synced and pushed from ${vmName}`);\n return true;\n } catch (error: any) {\n console.error(`[exe-provider] Error syncing beads on ${vmName}:`, error.message);\n return false;\n }\n }\n\n /**\n * Query beads on a remote VM\n *\n * Runs bd search on the remote and returns results.\n */\n async queryBeads(vmName: string, searchTerm: string, workspacePath: string = '/workspace'): Promise<any[]> {\n try {\n const result = await this.ssh(vmName, `cd ${workspacePath} && bd search \"${searchTerm}\" --json 2>/dev/null || echo \"[]\"`);\n\n if (result.exitCode !== 0 || !result.stdout.trim()) {\n return [];\n }\n\n try {\n return JSON.parse(result.stdout.trim());\n } catch {\n return [];\n }\n } catch (error: any) {\n console.error(`[exe-provider] Error querying beads on ${vmName}:`, error.message);\n return [];\n }\n }\n\n /**\n * Configure Claude Code on a VM for autonomous operation\n *\n * Sets up:\n * - ~/.claude.json with bypass permissions and onboarding settings\n * - ~/.bashrc with proper terminal environment (TERM, LANG, etc.)\n *\n * This is required for remote agents to run without human interaction.\n */\n async configureClaudeCode(vmName: string): Promise<void> {\n // Configure Claude settings\n const setupScript = `\nimport json, os\npath = os.path.expanduser(\"~/.claude.json\")\ndata = {}\nif os.path.exists(path):\n with open(path, \"r\") as f:\n data = json.load(f)\ndata[\"bypassPermissionsModeAccepted\"] = True\ndata[\"hasCompletedOnboarding\"] = True\nwith open(path, \"w\") as f:\n json.dump(data, f, indent=2)\n`;\n const scriptBase64 = Buffer.from(setupScript).toString('base64');\n const result = await this.ssh(vmName, `echo '${scriptBase64}' | base64 -d | python3`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to configure Claude Code on ${vmName}: ${result.stderr}`);\n }\n\n // Configure terminal environment in .bashrc for proper rendering\n const termEnv = `\n# Panopticon terminal settings\nexport TERM=xterm-256color\nexport LANG=C.UTF-8\nexport LC_ALL=C.UTF-8\nexport COLORTERM=truecolor\n`;\n const termEnvBase64 = Buffer.from(termEnv).toString('base64');\n await this.ssh(vmName, `grep -q \"Panopticon terminal settings\" ~/.bashrc 2>/dev/null || echo '${termEnvBase64}' | base64 -d >> ~/.bashrc`);\n }\n\n /**\n * Copy essential skills from local ~/.panopticon/skills/ to remote VM ~/.claude/skills/\n *\n * Skills are read locally and written to the VM via base64-encoded SSH.\n * Only copies SKILL.md and resource files (not symlinks or deep directories).\n */\n async copySkillsToVm(vmName: string): Promise<void> {\n const essentialSkills = [\n 'beads',\n 'beads-completion-check',\n 'beads-panopticon-guide',\n 'work-complete',\n 'session-health',\n ];\n\n const skillsSourceDir = join(homedir(), '.panopticon', 'skills');\n if (!existsSync(skillsSourceDir)) {\n console.log(`[exe-provider] No skills source directory at ${skillsSourceDir}`);\n return;\n }\n\n // Create skills directory on remote\n await this.ssh(vmName, 'mkdir -p ~/.claude/skills');\n\n for (const skillName of essentialSkills) {\n const skillDir = join(skillsSourceDir, skillName);\n if (!existsSync(skillDir)) {\n continue;\n }\n\n try {\n // Create skill directory on remote\n await this.ssh(vmName, `mkdir -p ~/.claude/skills/${skillName}`);\n\n // Copy SKILL.md\n const skillMdPath = join(skillDir, 'SKILL.md');\n if (existsSync(skillMdPath)) {\n const content = readFileSync(skillMdPath, 'utf-8');\n const contentBase64 = Buffer.from(content).toString('base64');\n await this.ssh(vmName, `echo '${contentBase64}' | base64 -d > ~/.claude/skills/${skillName}/SKILL.md`);\n }\n\n // Copy resources/ directory if it exists\n const resourcesDir = join(skillDir, 'resources');\n if (existsSync(resourcesDir) && statSync(resourcesDir).isDirectory()) {\n await this.ssh(vmName, `mkdir -p ~/.claude/skills/${skillName}/resources`);\n const resourceFiles = readdirSync(resourcesDir).filter(f => f.endsWith('.md'));\n for (const resourceFile of resourceFiles) {\n const resourcePath = join(resourcesDir, resourceFile);\n if (statSync(resourcePath).isFile()) {\n const resourceContent = readFileSync(resourcePath, 'utf-8');\n const resourceBase64 = Buffer.from(resourceContent).toString('base64');\n await this.ssh(vmName, `echo '${resourceBase64}' | base64 -d > ~/.claude/skills/${skillName}/resources/${resourceFile}`);\n }\n }\n }\n\n console.log(`[exe-provider] Copied skill ${skillName} to ${vmName}`);\n } catch (error: any) {\n console.warn(`[exe-provider] Failed to copy skill ${skillName} to ${vmName}: ${error.message}`);\n }\n }\n }\n}\n\n/**\n * Factory function to create an ExeProvider with config from Panopticon settings\n */\nexport function createExeProvider(config?: ExeProviderConfig): ExeProvider {\n return new ExeProvider(config);\n}\n"],"mappings":"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","names":[]}