@braingrid/cli 0.2.28 → 0.2.29
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.
- package/CHANGELOG.md +39 -0
- package/dist/{chunk-6GC3UJCM.js → chunk-PQ37NXJH.js} +4 -3
- package/dist/chunk-PQ37NXJH.js.map +1 -0
- package/dist/{chunk-RAV3B4UY.js → chunk-S3D6P3QC.js} +4 -3
- package/dist/chunk-S3D6P3QC.js.map +1 -0
- package/dist/cli.js +5876 -5668
- package/dist/cli.js.map +1 -1
- package/dist/{command-execution-7JMH2DK4.js → command-execution-HEGDCOLO.js} +2 -2
- package/dist/{gh-installer-LNR25TO7.js → gh-installer-DWTEK33P.js} +2 -2
- package/package.json +17 -18
- package/dist/chunk-6GC3UJCM.js.map +0 -1
- package/dist/chunk-RAV3B4UY.js.map +0 -1
- /package/dist/{command-execution-7JMH2DK4.js.map → command-execution-HEGDCOLO.js.map} +0 -0
- /package/dist/{gh-installer-LNR25TO7.js.map → gh-installer-DWTEK33P.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.29] - 2025-02-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Tree view for requirements listing**
|
|
15
|
+
- `requirement list --tree` displays requirements with nested tasks
|
|
16
|
+
- Shows task status indicators and completion counts
|
|
17
|
+
- Hierarchical view improves requirement-to-task visibility
|
|
18
|
+
|
|
19
|
+
- **Automatic context detection for specify command**
|
|
20
|
+
- Detects project context from `.braingrid/project.json`
|
|
21
|
+
- Auto-enhances prompts with relevant codebase context
|
|
22
|
+
- Improves AI-generated requirement quality
|
|
23
|
+
|
|
24
|
+
- **Auto-generated tab completions**
|
|
25
|
+
- Tab completions now generated from CLI command definitions
|
|
26
|
+
- Ensures completions stay in sync with available commands
|
|
27
|
+
- Run `pnpm generate:completions` to regenerate
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- **Task status synchronization**
|
|
32
|
+
- Requirement status now auto-syncs when all tasks are completed
|
|
33
|
+
- Status sync hook triggers on task status updates
|
|
34
|
+
|
|
35
|
+
- **Breakdown command validation**
|
|
36
|
+
- Prevents breakdown of requirements that already have tasks
|
|
37
|
+
- Avoids duplicate task generation
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **Build configuration**
|
|
42
|
+
- Removed stale mapping file reference from build
|
|
43
|
+
|
|
44
|
+
### Tests
|
|
45
|
+
|
|
46
|
+
- **Comprehensive tests for review acceptance handler**
|
|
47
|
+
- Added full test coverage for `handleReviewAcceptance`
|
|
48
|
+
|
|
10
49
|
## [0.2.28] - 2025-01-28
|
|
11
50
|
|
|
12
51
|
### Added
|
|
@@ -26,7 +26,8 @@ async function execStreamAsync(command, onOutput, isTestMode = false, mockExecHa
|
|
|
26
26
|
const lines = result.stdout.split("\n");
|
|
27
27
|
for (const line of lines) {
|
|
28
28
|
if (line.trim()) {
|
|
29
|
-
onOutput(line
|
|
29
|
+
onOutput(`${line}
|
|
30
|
+
`);
|
|
30
31
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
31
32
|
}
|
|
32
33
|
}
|
|
@@ -50,7 +51,7 @@ async function execStreamAsync(command, onOutput, isTestMode = false, mockExecHa
|
|
|
50
51
|
args = promptMatch ? [promptMatch[1]] : [];
|
|
51
52
|
} else if (command.startsWith("git commit")) {
|
|
52
53
|
const parts = command.match(/^git\s+commit\s+(.*)$/);
|
|
53
|
-
if (parts
|
|
54
|
+
if (parts?.[1]) {
|
|
54
55
|
cmd = "git";
|
|
55
56
|
args = ["commit"];
|
|
56
57
|
const argString = parts[1];
|
|
@@ -227,4 +228,4 @@ export {
|
|
|
227
228
|
execStreamAsync,
|
|
228
229
|
createMockExecHandler
|
|
229
230
|
};
|
|
230
|
-
//# sourceMappingURL=chunk-
|
|
231
|
+
//# sourceMappingURL=chunk-PQ37NXJH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/command-execution.ts"],"sourcesContent":["import { exec, spawn } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nexport interface ExecResult {\n\tstdout: string;\n\tstderr: string;\n}\n\nexport interface ExecOptions {\n\tmaxBuffer?: number;\n\ttimeout?: number;\n\tcwd?: string;\n\tenv?: NodeJS.ProcessEnv;\n}\n\nconst execAsyncReal = promisify(exec);\n\n/**\n * Execute a command asynchronously with proper buffer limits and timeout handling\n */\nexport async function execAsync(\n\tcommand: string,\n\toptions?: ExecOptions,\n\tisTestMode: boolean = false,\n\tmockExecHandler?: (command: string) => Promise<ExecResult>\n): Promise<ExecResult> {\n\tif (isTestMode && mockExecHandler) {\n\t\treturn mockExecHandler(command);\n\t}\n\n\t// Set appropriate buffer limits based on command type\n\tconst defaultOptions: ExecOptions = {\n\t\tmaxBuffer: 1024 * 1024 * 10, // 10MB default\n\t\ttimeout: 300000, // 5 minutes\n\t\t...options,\n\t};\n\n\t// Increase buffer for Claude commands that may produce large outputs\n\tif (command.includes('claude')) {\n\t\tdefaultOptions.maxBuffer = 1024 * 1024 * 50; // 50MB for Claude commands\n\t\tdefaultOptions.timeout = 600000; // 10 minutes for Claude\n\t}\n\n\treturn execAsyncReal(command, defaultOptions);\n}\n\n/**\n * Execute a command with streaming output support\n */\nexport async function execStreamAsync(\n\tcommand: string,\n\tonOutput?: (chunk: string) => void,\n\tisTestMode: boolean = false,\n\tmockExecHandler?: (command: string) => Promise<ExecResult>,\n\toptions?: {\n\t\ttimeout?: number;\n\t\tinactivityTimeout?: number;\n\t}\n): Promise<ExecResult> {\n\tif (isTestMode && mockExecHandler) {\n\t\t// For test mode, simulate streaming\n\t\tconst result = await mockExecHandler(command);\n\t\tif (onOutput) {\n\t\t\t// Simulate streaming by sending output in chunks\n\t\t\tconst lines = result.stdout.split('\\n');\n\t\t\tfor (const line of lines) {\n\t\t\t\tif (line.trim()) {\n\t\t\t\t\tonOutput(`${line}\\n`);\n\t\t\t\t\tawait new Promise(resolve => setTimeout(resolve, 200));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\treturn new Promise((resolve, reject) => {\n\t\t// Parse command to handle quotes properly\n\t\tlet cmd: string;\n\t\tlet args: string[];\n\n\t\tif (command.startsWith('claude -p --dangerously-skip-permissions \"')) {\n\t\t\tcmd = 'claude';\n\t\t\t// Extract the quoted content for non-interactive mode with skip permissions\n\t\t\tconst promptMatch = command.match(/^claude -p --dangerously-skip-permissions \"(.*)\"/s);\n\t\t\targs = promptMatch ? ['-p', '--dangerously-skip-permissions', promptMatch[1]] : [];\n\t\t} else if (command.startsWith('claude -p \"')) {\n\t\t\tcmd = 'claude';\n\t\t\t// Extract the quoted content for non-interactive mode\n\t\t\tconst promptMatch = command.match(/^claude -p \"(.*)\"/s);\n\t\t\targs = promptMatch ? ['-p', promptMatch[1]] : [];\n\t\t} else if (command.startsWith('claude \"')) {\n\t\t\tcmd = 'claude';\n\t\t\t// Extract the quoted content for interactive mode\n\t\t\tconst promptMatch = command.match(/^claude \"(.*)\"/s);\n\t\t\targs = promptMatch ? [promptMatch[1]] : [];\n\t\t} else if (command.startsWith('git commit')) {\n\t\t\t// Special handling for git commit to properly parse the message\n\t\t\tconst parts = command.match(/^git\\s+commit\\s+(.*)$/);\n\t\t\tif (parts?.[1]) {\n\t\t\t\tcmd = 'git';\n\t\t\t\targs = ['commit'];\n\t\t\t\t// Parse the rest of the arguments, handling -m \"message\" properly\n\t\t\t\tconst argString = parts[1];\n\t\t\t\tconst messageMatch = argString.match(/-m\\s+\"([^\"]+)\"/);\n\t\t\t\tif (messageMatch) {\n\t\t\t\t\targs.push('-m', messageMatch[1]);\n\t\t\t\t\t// Add any other arguments that might be before or after -m\n\t\t\t\t\tconst beforeMessage = argString.substring(0, argString.indexOf('-m')).trim();\n\t\t\t\t\tconst afterMessage = argString\n\t\t\t\t\t\t.substring(argString.indexOf(messageMatch[0]) + messageMatch[0].length)\n\t\t\t\t\t\t.trim();\n\t\t\t\t\tif (beforeMessage) args.unshift(...beforeMessage.split(' '));\n\t\t\t\t\tif (afterMessage) args.push(...afterMessage.split(' '));\n\t\t\t\t} else {\n\t\t\t\t\targs.push(...argString.split(' '));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t[cmd, ...args] = command.split(' ');\n\t\t\t}\n\t\t} else {\n\t\t\t// Simple command splitting for other commands\n\t\t\t[cmd, ...args] = command.split(' ');\n\t\t}\n\n\t\tconst child = spawn(cmd, args, {\n\t\t\tshell: false,\n\t\t\tstdio: ['inherit', 'pipe', 'pipe'],\n\t\t});\n\n\t\tlet stdout = '';\n\t\tlet stderr = '';\n\n\t\t// Smart timeout handling\n\t\tconst isGitCommit = cmd === 'git' && args[0] === 'commit';\n\t\tconst maxTimeout = options?.timeout || (isGitCommit ? 900000 : 300000); // 15 min for git commit, 5 min default\n\t\tconst inactivityTimeout = options?.inactivityTimeout || (isGitCommit ? 60000 : 30000); // 60s for git commit, 30s default\n\n\t\tlet globalTimeoutId: NodeJS.Timeout | null = null;\n\t\tlet inactivityTimeoutId: NodeJS.Timeout | null = null;\n\n\t\tconst clearTimeouts = () => {\n\t\t\tif (globalTimeoutId) clearTimeout(globalTimeoutId);\n\t\t\tif (inactivityTimeoutId) clearTimeout(inactivityTimeoutId);\n\t\t};\n\n\t\tconst resetInactivityTimeout = () => {\n\t\t\tif (inactivityTimeoutId) clearTimeout(inactivityTimeoutId);\n\n\t\t\tinactivityTimeoutId = setTimeout(() => {\n\t\t\t\tclearTimeouts();\n\t\t\t\tchild.kill('SIGTERM');\n\t\t\t\treject(new Error(`Command timed out due to ${inactivityTimeout / 1000}s of inactivity`));\n\t\t\t}, inactivityTimeout);\n\t\t};\n\n\t\t// Set global timeout\n\t\tglobalTimeoutId = setTimeout(() => {\n\t\t\tclearTimeouts();\n\t\t\tchild.kill('SIGTERM');\n\t\t\treject(new Error(`Command exceeded maximum timeout of ${maxTimeout / 1000}s`));\n\t\t}, maxTimeout);\n\n\t\t// Start inactivity timeout\n\t\tresetInactivityTimeout();\n\n\t\tchild.stdout?.on('data', data => {\n\t\t\tconst chunk = data.toString();\n\t\t\tstdout += chunk;\n\t\t\tif (onOutput) {\n\t\t\t\tonOutput(chunk);\n\t\t\t}\n\t\t\t// Reset inactivity timeout on any output\n\t\t\tresetInactivityTimeout();\n\t\t});\n\n\t\tchild.stderr?.on('data', data => {\n\t\t\tconst chunk = data.toString();\n\t\t\tstderr += chunk;\n\t\t\tif (onOutput) {\n\t\t\t\tonOutput(chunk);\n\t\t\t}\n\t\t\t// Reset inactivity timeout on any output (pre-commit hooks often write to stderr)\n\t\t\tresetInactivityTimeout();\n\t\t});\n\n\t\tchild.on('close', code => {\n\t\t\tclearTimeouts();\n\t\t\tif (code === 0) {\n\t\t\t\tresolve({ stdout, stderr });\n\t\t\t} else {\n\t\t\t\treject(new Error(`Command failed with exit code ${code}: ${stderr}`));\n\t\t\t}\n\t\t});\n\n\t\tchild.on('error', error => {\n\t\t\tclearTimeouts();\n\t\t\treject(error);\n\t\t});\n\t});\n}\n\n/**\n * Mock execution handler for testing\n */\nexport async function createMockExecHandler(\n\taddMessage?: (type: 'info' | 'error' | 'system', content: string) => void\n): Promise<(command: string) => Promise<ExecResult>> {\n\treturn async (command: string): Promise<ExecResult> => {\n\t\tif (addMessage) {\n\t\t\taddMessage('info', `🧪 TEST MODE: Simulating command: ${command}`);\n\t\t}\n\n\t\t// Simulate delays\n\t\tawait new Promise(resolve => setTimeout(resolve, 500));\n\n\t\t// Git commands\n\t\tif (command.includes('git branch --show-current')) {\n\t\t\treturn { stdout: 'feature/test-branch', stderr: '' };\n\t\t}\n\t\tif (command.includes('gh repo view')) {\n\t\t\treturn { stdout: 'main', stderr: '' };\n\t\t}\n\t\tif (command.includes('git checkout -b')) {\n\t\t\tconst branchName = command.split(' ').pop();\n\t\t\treturn { stdout: `Switched to a new branch '${branchName}'`, stderr: '' };\n\t\t}\n\t\tif (command.includes('git checkout main')) {\n\t\t\treturn { stdout: 'Switched to branch main', stderr: '' };\n\t\t}\n\t\tif (command.includes('git pull')) {\n\t\t\treturn { stdout: 'Already up to date.', stderr: '' };\n\t\t}\n\t\tif (command.includes('git add .')) {\n\t\t\treturn { stdout: '', stderr: '' };\n\t\t}\n\t\tif (command.includes('git diff --cached --quiet')) {\n\t\t\tthrow new Error('Changes to commit'); // Simulate changes exist\n\t\t}\n\t\tif (command.includes('git commit')) {\n\t\t\treturn { stdout: '[feature/test abc123] feat: mock commit', stderr: '' };\n\t\t}\n\t\tif (command.includes('git push')) {\n\t\t\tconst branchName = command.includes('feature/') ? 'feature/test-branch' : 'current-branch';\n\t\t\treturn {\n\t\t\t\tstdout: `To github.com:test/repo.git\\n * [new branch] ${branchName} -> ${branchName}\\nBranch '${branchName}' set up to track remote branch '${branchName}' from 'origin'.`,\n\t\t\t\tstderr: '',\n\t\t\t};\n\t\t}\n\n\t\t// CLI version checks\n\t\tif (command.includes('claude --version')) {\n\t\t\treturn { stdout: 'claude version 2.1.3', stderr: '' };\n\t\t}\n\t\tif (command.includes('gh --version')) {\n\t\t\treturn { stdout: 'gh version 2.40.1', stderr: '' };\n\t\t}\n\n\t\t// GitHub commands\n\t\tif (command.includes('gh pr create')) {\n\t\t\treturn { stdout: 'https://github.com/test/repo/pull/123', stderr: '' };\n\t\t}\n\n\t\t// Claude commands\n\t\tif (command.includes('Generate a conventional commit')) {\n\t\t\tconst taskTitle = command.includes('login')\n\t\t\t\t? 'login component'\n\t\t\t\t: command.includes('JWT')\n\t\t\t\t\t? 'JWT authentication'\n\t\t\t\t\t: command.includes('logout')\n\t\t\t\t\t\t? 'logout functionality'\n\t\t\t\t\t\t: 'test feature';\n\t\t\treturn { stdout: `feat(auth): add ${taskTitle}`, stderr: '' };\n\t\t}\n\t\tif (command.includes('Generate a comprehensive GitHub Pull Request')) {\n\t\t\treturn {\n\t\t\t\tstdout: `## Summary\\nImplemented mock authentication system with all required functionality.\\n\\n## Tasks Completed\\n- [x] Mock login component\\n- [x] Mock JWT authentication\\n- [x] Mock logout functionality\\n\\n## Testing\\nTest the mock implementation thoroughly.\\n\\n## Notes\\nThis is a test implementation.`,\n\t\t\t\tstderr: '',\n\t\t\t};\n\t\t}\n\t\tif (\n\t\t\tcommand.startsWith('claude -p --dangerously-skip-permissions \"') ||\n\t\t\tcommand.startsWith('claude -p \"') ||\n\t\t\tcommand.startsWith('claude \"')\n\t\t) {\n\t\t\t// Handle task content and other prompts\n\t\t\tconst taskTitle = command.includes('login')\n\t\t\t\t? 'Login Component'\n\t\t\t\t: command.includes('JWT')\n\t\t\t\t\t? 'JWT Authentication'\n\t\t\t\t\t: command.includes('logout')\n\t\t\t\t\t\t? 'Logout Functionality'\n\t\t\t\t\t\t: 'Test Feature';\n\t\t\treturn {\n\t\t\t\tstdout: `# ${taskTitle} Implementation\\n\\n## Files Created/Modified\\n- src/components/auth/${taskTitle.replace(' ', '')}.tsx\\n- src/hooks/useAuth.ts\\n- src/utils/auth.ts\\n\\n## Implementation Details\\nCreated comprehensive ${taskTitle.toLowerCase()} with modern React patterns, TypeScript support, and proper error handling.\\n\\n## Testing\\nAdded unit tests and integration tests for the ${taskTitle.toLowerCase()}.`,\n\t\t\t\tstderr: '',\n\t\t\t};\n\t\t}\n\n\t\t// Default response\n\t\treturn { stdout: 'Mock command executed successfully', stderr: '' };\n\t};\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,10 +5,10 @@ import chalk from "chalk";
|
|
|
5
5
|
|
|
6
6
|
// src/utils/cli-tools.ts
|
|
7
7
|
import { exec } from "child_process";
|
|
8
|
-
import { promisify } from "util";
|
|
9
8
|
import { access, constants } from "fs/promises";
|
|
10
9
|
import { homedir, platform } from "os";
|
|
11
10
|
import { join } from "path";
|
|
11
|
+
import { promisify } from "util";
|
|
12
12
|
var execAsync = promisify(exec);
|
|
13
13
|
var CLAUDE_LOCAL_PATH = join(homedir(), ".claude", "local", "claude");
|
|
14
14
|
async function checkClaudeInstalled() {
|
|
@@ -48,12 +48,13 @@ function getCursorAppPaths() {
|
|
|
48
48
|
paths.push("/Applications/Cursor.app");
|
|
49
49
|
paths.push(join(home, "Library/Application Support/Cursor"));
|
|
50
50
|
break;
|
|
51
|
-
case "win32":
|
|
51
|
+
case "win32": {
|
|
52
52
|
const localAppData = process.env.LOCALAPPDATA || join(home, "AppData", "Local");
|
|
53
53
|
const appData = process.env.APPDATA || join(home, "AppData", "Roaming");
|
|
54
54
|
paths.push(join(localAppData, "Programs", "Cursor"));
|
|
55
55
|
paths.push(join(appData, "Cursor"));
|
|
56
56
|
break;
|
|
57
|
+
}
|
|
57
58
|
case "linux":
|
|
58
59
|
paths.push(join(home, ".config", "Cursor"));
|
|
59
60
|
paths.push(join(home, ".cursor"));
|
|
@@ -450,4 +451,4 @@ export {
|
|
|
450
451
|
installGh,
|
|
451
452
|
getGhManualInstallInstructions
|
|
452
453
|
};
|
|
453
|
-
//# sourceMappingURL=chunk-
|
|
454
|
+
//# sourceMappingURL=chunk-S3D6P3QC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/gh-installer.ts","../src/utils/cli-tools.ts","../src/utils/package-manager-installer.ts"],"sourcesContent":["/**\n * GitHub CLI Installer Utility\n *\n * Automatically installs GitHub CLI on the user's system using platform-specific methods:\n * - macOS: Homebrew (if installed) or Webi (automated installer)\n * - Windows: winget\n * - Linux: apt/dnf/pacman (auto-detected)\n */\n\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport chalk from 'chalk';\nimport { getCliVersion, isCliInstalled } from './cli-tools.js';\nimport {\n\tdetectLinuxPackageManager,\n\tisHomebrewInstalled,\n\tisWingetAvailable,\n} from './package-manager-installer.js';\n\nconst execAsync = promisify(exec);\n\nexport interface GhInstallResult {\n\tsuccess: boolean;\n\tmessage: string;\n\tversion?: string;\n}\n\n/**\n * Check if GitHub CLI is installed\n */\nexport async function isGhInstalled(): Promise<boolean> {\n\treturn isCliInstalled('gh');\n}\n\n/**\n * Get GitHub CLI version if installed\n */\nexport async function getGhVersion(): Promise<string | null> {\n\treturn getCliVersion('gh', '--version', output => {\n\t\tconst match = output.match(/gh version ([\\d.]+)/);\n\t\treturn match ? match[1] : null;\n\t});\n}\n\n/**\n * Install GitHub CLI on macOS via Homebrew (when Homebrew is already installed)\n */\nasync function installViaHomebrew(): Promise<GhInstallResult> {\n\tconsole.log(chalk.blue('📦 Installing GitHub CLI via Homebrew...'));\n\n\ttry {\n\t\tawait execAsync('brew install gh', {\n\t\t\ttimeout: 300000, // 5 minutes\n\t\t});\n\n\t\t// Verify installation\n\t\tconst version = await getGhVersion();\n\t\tif (!version) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: chalk.red('❌ GitHub CLI installation completed but gh command not found'),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tmessage: chalk.green(`✅ GitHub CLI installed successfully (version ${version})!`),\n\t\t\tversion,\n\t\t};\n\t} catch (error: unknown) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmessage:\n\t\t\t\tchalk.red('❌ Failed to install GitHub CLI via Homebrew\\n\\n') +\n\t\t\t\tchalk.dim('Error: ') +\n\t\t\t\terrorMsg +\n\t\t\t\t'\\n\\n' +\n\t\t\t\tchalk.dim('Please install GitHub CLI manually from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/'),\n\t\t};\n\t}\n}\n\n/**\n * Install GitHub CLI on macOS via Webi (automated installer, no Homebrew needed)\n */\nasync function installViaWebi(): Promise<GhInstallResult> {\n\tconsole.log(chalk.blue('📦 Installing GitHub CLI via Webi...'));\n\tconsole.log(chalk.dim('This will install gh to ~/.local/bin/\\n'));\n\n\ttry {\n\t\tawait execAsync('curl -sS https://webi.sh/gh | sh', {\n\t\t\ttimeout: 300000, // 5 minutes\n\t\t});\n\n\t\t// Verify installation\n\t\tconst version = await getGhVersion();\n\t\tif (!version) {\n\t\t\t// Installation succeeded but PATH not updated yet\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage:\n\t\t\t\t\tchalk.green('✅ GitHub CLI installed successfully!\\n') +\n\t\t\t\t\tchalk.dim(\n\t\t\t\t\t\t'Note: You may need to restart your terminal for the gh command to be available.'\n\t\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tmessage: chalk.green(`✅ GitHub CLI installed successfully (version ${version})!`),\n\t\t\tversion,\n\t\t};\n\t} catch (error: unknown) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmessage:\n\t\t\t\tchalk.red('❌ Failed to install GitHub CLI via Webi\\n\\n') +\n\t\t\t\tchalk.dim('Error: ') +\n\t\t\t\terrorMsg +\n\t\t\t\t'\\n\\n' +\n\t\t\t\tchalk.dim('Please install GitHub CLI manually from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/'),\n\t\t};\n\t}\n}\n\n/**\n * Install GitHub CLI on macOS using best available method\n * Strategy: Use Homebrew if installed, otherwise use Webi\n */\nasync function installGhMacOS(): Promise<GhInstallResult> {\n\t// Check if Homebrew is already installed\n\tconst hasHomebrew = await isHomebrewInstalled();\n\n\tif (hasHomebrew) {\n\t\t// User already has Homebrew - use it (fast and familiar)\n\t\treturn installViaHomebrew();\n\t}\n\n\t// No Homebrew - use Webi (automated installer, no package manager needed)\n\treturn installViaWebi();\n}\n\n/**\n * Install GitHub CLI on Windows using winget\n */\nasync function installGhWindows(): Promise<GhInstallResult> {\n\t// Check if winget is available\n\tconst hasWinget = await isWingetAvailable();\n\n\tif (!hasWinget) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmessage:\n\t\t\t\tchalk.red('❌ winget is not available on this system\\n\\n') +\n\t\t\t\tchalk.dim('winget is included in Windows 10 (version 1809+) and Windows 11.\\n') +\n\t\t\t\tchalk.dim('Please install GitHub CLI manually from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/'),\n\t\t};\n\t}\n\n\tconsole.log(chalk.blue('📦 Installing GitHub CLI via winget...'));\n\n\ttry {\n\t\tawait execAsync('winget install --id GitHub.cli --silent', {\n\t\t\ttimeout: 300000, // 5 minutes\n\t\t});\n\n\t\t// Verify installation\n\t\tconst version = await getGhVersion();\n\t\tif (!version) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: chalk.red('❌ GitHub CLI installation completed but gh command not found'),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tmessage: chalk.green(`✅ GitHub CLI installed successfully (version ${version})!`),\n\t\t\tversion,\n\t\t};\n\t} catch (error: unknown) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmessage:\n\t\t\t\tchalk.red('❌ Failed to install GitHub CLI via winget\\n\\n') +\n\t\t\t\tchalk.dim('Error: ') +\n\t\t\t\terrorMsg +\n\t\t\t\t'\\n\\n' +\n\t\t\t\tchalk.dim('Please install GitHub CLI manually from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/'),\n\t\t};\n\t}\n}\n\n/**\n * Install GitHub CLI on Linux using detected package manager\n */\nasync function installGhLinux(): Promise<GhInstallResult> {\n\tconst packageManager = await detectLinuxPackageManager();\n\n\tif (!packageManager) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmessage:\n\t\t\t\tchalk.red('❌ Could not detect a supported package manager\\n\\n') +\n\t\t\t\tchalk.dim('Supported package managers: apt, dnf, yum, pacman\\n') +\n\t\t\t\tchalk.dim('Please install GitHub CLI manually from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/'),\n\t\t};\n\t}\n\n\tconsole.log(chalk.blue(`📦 Installing GitHub CLI via ${packageManager.name}...`));\n\tconsole.log(chalk.dim('This may prompt for your sudo password.\\n'));\n\n\ttry {\n\t\tlet installCommand: string;\n\n\t\tswitch (packageManager.name) {\n\t\t\tcase 'apt':\n\t\t\t\t// Add GitHub CLI repository and install\n\t\t\t\tinstallCommand =\n\t\t\t\t\t'curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && ' +\n\t\t\t\t\t'sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && ' +\n\t\t\t\t\t'echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main\" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && ' +\n\t\t\t\t\t'sudo apt update && sudo apt install gh -y';\n\t\t\t\tbreak;\n\t\t\tcase 'dnf':\n\t\t\t\tinstallCommand = 'sudo dnf install gh -y';\n\t\t\t\tbreak;\n\t\t\tcase 'yum':\n\t\t\t\tinstallCommand = 'sudo yum install gh -y';\n\t\t\t\tbreak;\n\t\t\tcase 'pacman':\n\t\t\t\tinstallCommand = 'sudo pacman -S --noconfirm github-cli';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tmessage: chalk.red(`❌ Unsupported package manager: ${packageManager.name}`),\n\t\t\t\t};\n\t\t}\n\n\t\tawait execAsync(installCommand, {\n\t\t\ttimeout: 300000, // 5 minutes\n\t\t});\n\n\t\t// Verify installation\n\t\tconst version = await getGhVersion();\n\t\tif (!version) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: chalk.red('❌ GitHub CLI installation completed but gh command not found'),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tmessage: chalk.green(`✅ GitHub CLI installed successfully (version ${version})!`),\n\t\t\tversion,\n\t\t};\n\t} catch (error: unknown) {\n\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tmessage:\n\t\t\t\tchalk.red('❌ Failed to install GitHub CLI\\n\\n') +\n\t\t\t\tchalk.dim('Error: ') +\n\t\t\t\terrorMsg +\n\t\t\t\t'\\n\\n' +\n\t\t\t\tchalk.dim('Please install GitHub CLI manually from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/'),\n\t\t};\n\t}\n}\n\n/**\n * Install GitHub CLI on the current platform\n * Auto-detects platform and uses appropriate installation method\n */\nexport async function installGh(): Promise<GhInstallResult> {\n\tconst platform = process.platform;\n\n\tswitch (platform) {\n\t\tcase 'darwin':\n\t\t\treturn installGhMacOS();\n\n\t\tcase 'win32':\n\t\t\treturn installGhWindows();\n\n\t\tcase 'linux':\n\t\t\treturn installGhLinux();\n\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage:\n\t\t\t\t\tchalk.red(`❌ Unsupported platform: ${platform}\\n\\n`) +\n\t\t\t\t\tchalk.dim('Please install GitHub CLI manually from: ') +\n\t\t\t\t\tchalk.cyan('https://cli.github.com/'),\n\t\t\t};\n\t}\n}\n\n/**\n * Get manual installation instructions for the current platform\n */\nexport function getGhManualInstallInstructions(): string {\n\tconst platform = process.platform;\n\n\tswitch (platform) {\n\t\tcase 'darwin':\n\t\t\treturn (\n\t\t\t\tchalk.yellow('📖 Manual GitHub CLI Installation (macOS)\\n\\n') +\n\t\t\t\tchalk.dim('Option 1 - Webi (recommended, no Homebrew needed):\\n') +\n\t\t\t\tchalk.cyan(' curl -sS https://webi.sh/gh | sh\\n\\n') +\n\t\t\t\tchalk.dim('Option 2 - Homebrew:\\n') +\n\t\t\t\tchalk.cyan(' brew install gh\\n\\n') +\n\t\t\t\tchalk.dim('Option 3 - Direct download:\\n') +\n\t\t\t\tchalk.cyan(' Download from: https://cli.github.com/')\n\t\t\t);\n\n\t\tcase 'win32':\n\t\t\treturn (\n\t\t\t\tchalk.yellow('📖 Manual GitHub CLI Installation (Windows)\\n\\n') +\n\t\t\t\tchalk.dim('Option 1 - winget (Windows 10+):\\n') +\n\t\t\t\tchalk.cyan(' winget install --id GitHub.cli\\n\\n') +\n\t\t\t\tchalk.dim('Option 2 - Direct download:\\n') +\n\t\t\t\tchalk.cyan(' Download from: https://cli.github.com/')\n\t\t\t);\n\n\t\tcase 'linux':\n\t\t\treturn (\n\t\t\t\tchalk.yellow('📖 Manual GitHub CLI Installation (Linux)\\n\\n') +\n\t\t\t\tchalk.dim('Debian/Ubuntu:\\n') +\n\t\t\t\tchalk.cyan(\n\t\t\t\t\t' See instructions at: https://github.com/cli/cli/blob/trunk/docs/install_linux.md#debian-ubuntu-linux-raspberry-pi-os-apt\\n\\n'\n\t\t\t\t) +\n\t\t\t\tchalk.dim('Fedora/RHEL:\\n') +\n\t\t\t\tchalk.cyan(' sudo dnf install gh\\n\\n') +\n\t\t\t\tchalk.dim('Arch Linux:\\n') +\n\t\t\t\tchalk.cyan(' sudo pacman -S github-cli\\n\\n') +\n\t\t\t\tchalk.dim('Or download from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/')\n\t\t\t);\n\n\t\tdefault:\n\t\t\treturn (\n\t\t\t\tchalk.yellow('📖 Manual GitHub CLI Installation\\n\\n') +\n\t\t\t\tchalk.dim('Download from: ') +\n\t\t\t\tchalk.cyan('https://cli.github.com/')\n\t\t\t);\n\t}\n}\n","/**\n * CLI Tools Detection Utilities\n *\n * Detects installed AI coding tools and CLI utilities:\n * - Checks if common AI IDE CLIs are installed\n * - Gets version information where available\n * - Cross-platform support (macOS, Linux, Windows)\n */\n\nimport { exec } from 'node:child_process';\nimport { access, constants } from 'node:fs/promises';\nimport { homedir, platform } from 'node:os';\nimport { join } from 'node:path';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\n// Claude Code local installation path after migrate-installer\nconst CLAUDE_LOCAL_PATH = join(homedir(), '.claude', 'local', 'claude');\n\nexport interface CliToolInfo {\n\tname: string; // Display name (e.g., \"GitHub CLI\")\n\tcommand: string; // Command to check (e.g., \"gh\")\n\tinstalled: boolean; // Whether it's installed\n\tversion?: string; // Version string if available\n}\n\ninterface CliToolConfig {\n\tname: string;\n\tcommand: string;\n\tversionFlag?: string;\n\tversionParser?: (output: string) => string | null;\n\tspecialCheck?: () => Promise<boolean>;\n\tspecialVersionCheck?: () => Promise<string | null>;\n}\n\n/**\n * Check if Claude Code is installed\n * Special handling for Claude CLI after `claude migrate-installer`\n *\n * The migrate-installer command moves the Claude Code executable from PATH\n * to ~/.claude/local/claude, so standard PATH checks fail.\n *\n * Detection priority:\n * 1. Check ~/.claude/local/claude (after migrate-installer)\n * 2. Try executing `claude --version` (may work via shell alias)\n * 3. Check PATH with `which claude`\n */\nasync function checkClaudeInstalled(): Promise<boolean> {\n\t// Priority 1: Check ~/.claude/local/claude (after migrate-installer)\n\ttry {\n\t\tawait access(CLAUDE_LOCAL_PATH, constants.X_OK);\n\t\treturn true;\n\t} catch {\n\t\t// Fall through to next check\n\t}\n\n\t// Priority 2: Try executing claude --version (may work via shell alias)\n\ttry {\n\t\tawait execAsync('claude --version 2>&1', { timeout: 2000 });\n\t\treturn true;\n\t} catch {\n\t\t// Fall through to PATH check\n\t}\n\n\t// Priority 3: Check PATH with which\n\treturn isCliInstalled('claude');\n}\n\n/**\n * Get Claude Code version\n * Tries local path first, then falls back to standard version check\n */\nasync function getClaudeVersion(): Promise<string | null> {\n\t// Try local path first\n\ttry {\n\t\tawait access(CLAUDE_LOCAL_PATH, constants.X_OK);\n\t\tconst result = await execAsync(`\"${CLAUDE_LOCAL_PATH}\" --version 2>&1`, {\n\t\t\ttimeout: 2000,\n\t\t});\n\t\tconst output = result.stdout || result.stderr;\n\t\tconst match = output.match(/([\\d.]+)/);\n\t\treturn match ? match[1] : null;\n\t} catch {\n\t\t// Fall through to regular version check\n\t}\n\n\t// Fall back to regular claude command\n\treturn getCliVersion('claude', '--version', output => {\n\t\tconst match = output.match(/([\\d.]+)/);\n\t\treturn match ? match[1] : null;\n\t});\n}\n\n/**\n * Get platform-specific Cursor IDE application paths\n */\nfunction getCursorAppPaths(): string[] {\n\tconst paths: string[] = [];\n\tconst home = homedir();\n\n\tswitch (platform()) {\n\t\tcase 'darwin': // macOS\n\t\t\tpaths.push('/Applications/Cursor.app');\n\t\t\tpaths.push(join(home, 'Library/Application Support/Cursor'));\n\t\t\tbreak;\n\n\t\tcase 'win32': {\n\t\t\t// Windows\n\t\t\tconst localAppData = process.env.LOCALAPPDATA || join(home, 'AppData', 'Local');\n\t\t\tconst appData = process.env.APPDATA || join(home, 'AppData', 'Roaming');\n\t\t\tpaths.push(join(localAppData, 'Programs', 'Cursor'));\n\t\t\tpaths.push(join(appData, 'Cursor'));\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'linux':\n\t\t\t// Linux: Check config directory (most reliable for AppImage)\n\t\t\tpaths.push(join(home, '.config', 'Cursor'));\n\t\t\tpaths.push(join(home, '.cursor'));\n\t\t\t// Common AppImage locations\n\t\t\tpaths.push('/opt/cursor.appimage');\n\t\t\tpaths.push('/usr/local/bin/cursor.appimage');\n\t\t\tbreak;\n\t}\n\n\treturn paths;\n}\n\n/**\n * Check if Cursor IDE is installed\n * Checks platform-specific application paths and config directories\n */\nasync function checkCursorIdeInstalled(): Promise<boolean> {\n\tconst paths = getCursorAppPaths();\n\n\t// Try each path\n\tfor (const path of paths) {\n\t\ttry {\n\t\t\tawait access(path);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\t// Continue to next path\n\t\t}\n\t}\n\n\t// Fallback: Check if cursor CLI is available\n\treturn isCliInstalled('cursor');\n}\n\n/**\n * Get Cursor IDE version\n * Falls back to CLI version if app version unavailable\n */\nasync function getCursorIdeVersion(): Promise<string | null> {\n\t// Try CLI version first (simplest)\n\tconst cliVersion = await getCliVersion('cursor', '--version', output => {\n\t\tconst match = output.match(/([\\d.]+)/);\n\t\treturn match ? match[1] : null;\n\t});\n\n\treturn cliVersion;\n}\n\nconst CLI_TOOLS: CliToolConfig[] = [\n\t{\n\t\tname: 'Git',\n\t\tcommand: 'git',\n\t\tversionFlag: '--version',\n\t\tversionParser: output => {\n\t\t\tconst match = output.match(/git version ([\\d.]+)/);\n\t\t\treturn match ? match[1] : null;\n\t\t},\n\t},\n\t{\n\t\tname: 'GitHub CLI',\n\t\tcommand: 'gh',\n\t\tversionFlag: '--version',\n\t\tversionParser: output => {\n\t\t\tconst match = output.match(/gh version ([\\d.]+)/);\n\t\t\treturn match ? match[1] : null;\n\t\t},\n\t},\n\t{\n\t\tname: 'Claude Code',\n\t\tcommand: 'claude',\n\t\tspecialCheck: checkClaudeInstalled,\n\t\tspecialVersionCheck: getClaudeVersion,\n\t\tversionFlag: '--version',\n\t\tversionParser: output => {\n\t\t\t// Output format: \"2.0.1 (Claude Code)\"\n\t\t\tconst match = output.match(/([\\d.]+)/);\n\t\t\treturn match ? match[1] : null;\n\t\t},\n\t},\n\t{\n\t\tname: 'Cursor',\n\t\tcommand: 'cursor',\n\t\tspecialCheck: checkCursorIdeInstalled,\n\t\tspecialVersionCheck: getCursorIdeVersion,\n\t\tversionFlag: '--version',\n\t\tversionParser: output => {\n\t\t\tconst match = output.match(/([\\d.]+)/);\n\t\t\treturn match ? match[1] : null;\n\t\t},\n\t},\n];\n\n/**\n * Check if a CLI command is installed\n * Uses user's shell to access PATH (supports shell-installed CLIs)\n */\nexport async function isCliInstalled(command: string): Promise<boolean> {\n\ttry {\n\t\tif (process.platform === 'win32') {\n\t\t\tawait execAsync(`where ${command}`, { timeout: 2000 });\n\t\t} else {\n\t\t\t// Use which command to check PATH\n\t\t\tawait execAsync(`which ${command} 2>/dev/null`, { timeout: 2000 });\n\t\t}\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Get the version of a CLI tool\n * Returns null if version cannot be determined\n */\nexport async function getCliVersion(\n\tcommand: string,\n\tversionFlag: string = '--version',\n\tparser?: (output: string) => string | null\n): Promise<string | null> {\n\ttry {\n\t\tconst result = await execAsync(`${command} ${versionFlag} 2>&1`, {\n\t\t\ttimeout: 2000,\n\t\t});\n\n\t\tconst output = result.stdout || result.stderr;\n\n\t\tif (parser) {\n\t\t\treturn parser(output);\n\t\t}\n\n\t\t// Default: return first line, trimmed\n\t\treturn output.trim().split('\\n')[0] || null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Check a single CLI tool (installed status and version)\n */\nasync function checkCliTool(config: CliToolConfig): Promise<CliToolInfo> {\n\t// Use special check if provided, otherwise use standard check\n\tconst installed = config.specialCheck\n\t\t? await config.specialCheck()\n\t\t: await isCliInstalled(config.command);\n\n\tif (!installed) {\n\t\treturn {\n\t\t\tname: config.name,\n\t\t\tcommand: config.command,\n\t\t\tinstalled: false,\n\t\t};\n\t}\n\n\t// Try to get version - use special version check if provided\n\tlet version: string | undefined;\n\tif (config.specialVersionCheck) {\n\t\tconst versionStr = await config.specialVersionCheck();\n\t\tif (versionStr) {\n\t\t\tversion = versionStr;\n\t\t}\n\t} else if (config.versionFlag) {\n\t\tconst versionStr = await getCliVersion(\n\t\t\tconfig.command,\n\t\t\tconfig.versionFlag,\n\t\t\tconfig.versionParser\n\t\t);\n\t\tif (versionStr) {\n\t\t\tversion = versionStr;\n\t\t}\n\t}\n\n\treturn {\n\t\tname: config.name,\n\t\tcommand: config.command,\n\t\tinstalled: true,\n\t\tversion,\n\t};\n}\n\n/**\n * Check all configured CLI tools in parallel\n * Returns array of CLI tool information\n */\nexport async function checkInstalledCliTools(): Promise<CliToolInfo[]> {\n\ttry {\n\t\tconst results = await Promise.all(CLI_TOOLS.map(config => checkCliTool(config)));\n\t\treturn results;\n\t} catch {\n\t\t// If something goes catastrophically wrong, return empty array\n\t\t// This ensures status command never fails due to CLI detection\n\t\treturn CLI_TOOLS.map(config => ({\n\t\t\tname: config.name,\n\t\t\tcommand: config.command,\n\t\t\tinstalled: false,\n\t\t}));\n\t}\n}\n","/**\n * Package Manager Detection Utilities\n *\n * Detects package managers on different platforms:\n * - Homebrew on macOS\n * - winget on Windows (typically pre-installed on Windows 10+)\n * - apt/dnf/pacman on Linux\n */\n\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\nexport interface PackageManagerInfo {\n\tname: string;\n\tcommand: string;\n\tavailable: boolean;\n}\n\n/**\n * Check if Homebrew is installed (macOS)\n */\nexport async function isHomebrewInstalled(): Promise<boolean> {\n\tif (process.platform !== 'darwin') {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tawait execAsync('which brew', { timeout: 2000 });\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Check if winget is available (Windows)\n * winget is pre-installed on Windows 10 (version 1809+) and Windows 11\n */\nexport async function isWingetAvailable(): Promise<boolean> {\n\tif (process.platform !== 'win32') {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tawait execAsync('winget --version', { timeout: 2000 });\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Detect available package manager on Linux\n * Returns the first available package manager found\n */\nexport async function detectLinuxPackageManager(): Promise<PackageManagerInfo | null> {\n\tif (process.platform !== 'linux') {\n\t\treturn null;\n\t}\n\n\tconst packageManagers: PackageManagerInfo[] = [\n\t\t{ name: 'apt', command: 'apt-get', available: false },\n\t\t{ name: 'dnf', command: 'dnf', available: false },\n\t\t{ name: 'yum', command: 'yum', available: false },\n\t\t{ name: 'pacman', command: 'pacman', available: false },\n\t];\n\n\tfor (const pm of packageManagers) {\n\t\ttry {\n\t\t\tawait execAsync(`which ${pm.command}`, { timeout: 2000 });\n\t\t\treturn { ...pm, available: true };\n\t\t} catch {\n\t\t\t// Package manager not found, continue checking\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Get the appropriate package manager for the current platform\n */\nexport async function detectPackageManager(): Promise<{\n\tplatform: string;\n\tpackageManager: string | null;\n\tavailable: boolean;\n}> {\n\tconst platform = process.platform;\n\n\tswitch (platform) {\n\t\tcase 'darwin': {\n\t\t\tconst hasHomebrew = await isHomebrewInstalled();\n\t\t\treturn {\n\t\t\t\tplatform: 'macOS',\n\t\t\t\tpackageManager: 'brew',\n\t\t\t\tavailable: hasHomebrew,\n\t\t\t};\n\t\t}\n\n\t\tcase 'win32': {\n\t\t\tconst hasWinget = await isWingetAvailable();\n\t\t\treturn {\n\t\t\t\tplatform: 'Windows',\n\t\t\t\tpackageManager: 'winget',\n\t\t\t\tavailable: hasWinget,\n\t\t\t};\n\t\t}\n\n\t\tcase 'linux': {\n\t\t\tconst linuxPM = await detectLinuxPackageManager();\n\t\t\treturn {\n\t\t\t\tplatform: 'Linux',\n\t\t\t\tpackageManager: linuxPM?.name || null,\n\t\t\t\tavailable: linuxPM !== null,\n\t\t\t};\n\t\t}\n\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\tplatform: platform,\n\t\t\t\tpackageManager: null,\n\t\t\t\tavailable: false,\n\t\t\t};\n\t}\n}\n"],"mappings":";AASA,SAAS,QAAAA,aAAY;AACrB,SAAS,aAAAC,kBAAiB;AAC1B,OAAO,WAAW;;;ACFlB,SAAS,YAAY;AACrB,SAAS,QAAQ,iBAAiB;AAClC,SAAS,SAAS,gBAAgB;AAClC,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAE1B,IAAM,YAAY,UAAU,IAAI;AAGhC,IAAM,oBAAoB,KAAK,QAAQ,GAAG,WAAW,SAAS,QAAQ;AA8BtE,eAAe,uBAAyC;AAEvD,MAAI;AACH,UAAM,OAAO,mBAAmB,UAAU,IAAI;AAC9C,WAAO;AAAA,EACR,QAAQ;AAAA,EAER;AAGA,MAAI;AACH,UAAM,UAAU,yBAAyB,EAAE,SAAS,IAAK,CAAC;AAC1D,WAAO;AAAA,EACR,QAAQ;AAAA,EAER;AAGA,SAAO,eAAe,QAAQ;AAC/B;AAMA,eAAe,mBAA2C;AAEzD,MAAI;AACH,UAAM,OAAO,mBAAmB,UAAU,IAAI;AAC9C,UAAM,SAAS,MAAM,UAAU,IAAI,iBAAiB,oBAAoB;AAAA,MACvE,SAAS;AAAA,IACV,CAAC;AACD,UAAM,SAAS,OAAO,UAAU,OAAO;AACvC,UAAM,QAAQ,OAAO,MAAM,UAAU;AACrC,WAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,EAC3B,QAAQ;AAAA,EAER;AAGA,SAAO,cAAc,UAAU,aAAa,YAAU;AACrD,UAAM,QAAQ,OAAO,MAAM,UAAU;AACrC,WAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,EAC3B,CAAC;AACF;AAKA,SAAS,oBAA8B;AACtC,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,QAAQ;AAErB,UAAQ,SAAS,GAAG;AAAA,IACnB,KAAK;AACJ,YAAM,KAAK,0BAA0B;AACrC,YAAM,KAAK,KAAK,MAAM,oCAAoC,CAAC;AAC3D;AAAA,IAED,KAAK,SAAS;AAEb,YAAM,eAAe,QAAQ,IAAI,gBAAgB,KAAK,MAAM,WAAW,OAAO;AAC9E,YAAM,UAAU,QAAQ,IAAI,WAAW,KAAK,MAAM,WAAW,SAAS;AACtE,YAAM,KAAK,KAAK,cAAc,YAAY,QAAQ,CAAC;AACnD,YAAM,KAAK,KAAK,SAAS,QAAQ,CAAC;AAClC;AAAA,IACD;AAAA,IAEA,KAAK;AAEJ,YAAM,KAAK,KAAK,MAAM,WAAW,QAAQ,CAAC;AAC1C,YAAM,KAAK,KAAK,MAAM,SAAS,CAAC;AAEhC,YAAM,KAAK,sBAAsB;AACjC,YAAM,KAAK,gCAAgC;AAC3C;AAAA,EACF;AAEA,SAAO;AACR;AAMA,eAAe,0BAA4C;AAC1D,QAAM,QAAQ,kBAAkB;AAGhC,aAAW,QAAQ,OAAO;AACzB,QAAI;AACH,YAAM,OAAO,IAAI;AACjB,aAAO;AAAA,IACR,QAAQ;AAAA,IAER;AAAA,EACD;AAGA,SAAO,eAAe,QAAQ;AAC/B;AAMA,eAAe,sBAA8C;AAE5D,QAAM,aAAa,MAAM,cAAc,UAAU,aAAa,YAAU;AACvE,UAAM,QAAQ,OAAO,MAAM,UAAU;AACrC,WAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,EAC3B,CAAC;AAED,SAAO;AACR;AAEA,IAAM,YAA6B;AAAA,EAClC;AAAA,IACC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,eAAe,YAAU;AACxB,YAAM,QAAQ,OAAO,MAAM,sBAAsB;AACjD,aAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC3B;AAAA,EACD;AAAA,EACA;AAAA,IACC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,eAAe,YAAU;AACxB,YAAM,QAAQ,OAAO,MAAM,qBAAqB;AAChD,aAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC3B;AAAA,EACD;AAAA,EACA;AAAA,IACC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,aAAa;AAAA,IACb,eAAe,YAAU;AAExB,YAAM,QAAQ,OAAO,MAAM,UAAU;AACrC,aAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC3B;AAAA,EACD;AAAA,EACA;AAAA,IACC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,cAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,aAAa;AAAA,IACb,eAAe,YAAU;AACxB,YAAM,QAAQ,OAAO,MAAM,UAAU;AACrC,aAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC3B;AAAA,EACD;AACD;AAMA,eAAsB,eAAe,SAAmC;AACvE,MAAI;AACH,QAAI,QAAQ,aAAa,SAAS;AACjC,YAAM,UAAU,SAAS,OAAO,IAAI,EAAE,SAAS,IAAK,CAAC;AAAA,IACtD,OAAO;AAEN,YAAM,UAAU,SAAS,OAAO,gBAAgB,EAAE,SAAS,IAAK,CAAC;AAAA,IAClE;AACA,WAAO;AAAA,EACR,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAMA,eAAsB,cACrB,SACA,cAAsB,aACtB,QACyB;AACzB,MAAI;AACH,UAAM,SAAS,MAAM,UAAU,GAAG,OAAO,IAAI,WAAW,SAAS;AAAA,MAChE,SAAS;AAAA,IACV,CAAC;AAED,UAAM,SAAS,OAAO,UAAU,OAAO;AAEvC,QAAI,QAAQ;AACX,aAAO,OAAO,MAAM;AAAA,IACrB;AAGA,WAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,EACxC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAKA,eAAe,aAAa,QAA6C;AAExE,QAAM,YAAY,OAAO,eACtB,MAAM,OAAO,aAAa,IAC1B,MAAM,eAAe,OAAO,OAAO;AAEtC,MAAI,CAAC,WAAW;AACf,WAAO;AAAA,MACN,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,MAChB,WAAW;AAAA,IACZ;AAAA,EACD;AAGA,MAAI;AACJ,MAAI,OAAO,qBAAqB;AAC/B,UAAM,aAAa,MAAM,OAAO,oBAAoB;AACpD,QAAI,YAAY;AACf,gBAAU;AAAA,IACX;AAAA,EACD,WAAW,OAAO,aAAa;AAC9B,UAAM,aAAa,MAAM;AAAA,MACxB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AACA,QAAI,YAAY;AACf,gBAAU;AAAA,IACX;AAAA,EACD;AAEA,SAAO;AAAA,IACN,MAAM,OAAO;AAAA,IACb,SAAS,OAAO;AAAA,IAChB,WAAW;AAAA,IACX;AAAA,EACD;AACD;AAMA,eAAsB,yBAAiD;AACtE,MAAI;AACH,UAAM,UAAU,MAAM,QAAQ,IAAI,UAAU,IAAI,YAAU,aAAa,MAAM,CAAC,CAAC;AAC/E,WAAO;AAAA,EACR,QAAQ;AAGP,WAAO,UAAU,IAAI,aAAW;AAAA,MAC/B,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,MAChB,WAAW;AAAA,IACZ,EAAE;AAAA,EACH;AACD;;;AChTA,SAAS,QAAAC,aAAY;AACrB,SAAS,aAAAC,kBAAiB;AAE1B,IAAMC,aAAYD,WAAUD,KAAI;AAWhC,eAAsB,sBAAwC;AAC7D,MAAI,QAAQ,aAAa,UAAU;AAClC,WAAO;AAAA,EACR;AAEA,MAAI;AACH,UAAME,WAAU,cAAc,EAAE,SAAS,IAAK,CAAC;AAC/C,WAAO;AAAA,EACR,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAMA,eAAsB,oBAAsC;AAC3D,MAAI,QAAQ,aAAa,SAAS;AACjC,WAAO;AAAA,EACR;AAEA,MAAI;AACH,UAAMA,WAAU,oBAAoB,EAAE,SAAS,IAAK,CAAC;AACrD,WAAO;AAAA,EACR,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAMA,eAAsB,4BAAgE;AACrF,MAAI,QAAQ,aAAa,SAAS;AACjC,WAAO;AAAA,EACR;AAEA,QAAM,kBAAwC;AAAA,IAC7C,EAAE,MAAM,OAAO,SAAS,WAAW,WAAW,MAAM;AAAA,IACpD,EAAE,MAAM,OAAO,SAAS,OAAO,WAAW,MAAM;AAAA,IAChD,EAAE,MAAM,OAAO,SAAS,OAAO,WAAW,MAAM;AAAA,IAChD,EAAE,MAAM,UAAU,SAAS,UAAU,WAAW,MAAM;AAAA,EACvD;AAEA,aAAW,MAAM,iBAAiB;AACjC,QAAI;AACH,YAAMA,WAAU,SAAS,GAAG,OAAO,IAAI,EAAE,SAAS,IAAK,CAAC;AACxD,aAAO,EAAE,GAAG,IAAI,WAAW,KAAK;AAAA,IACjC,QAAQ;AAAA,IAER;AAAA,EACD;AAEA,SAAO;AACR;;;AF5DA,IAAMC,aAAYC,WAAUC,KAAI;AAWhC,eAAsB,gBAAkC;AACvD,SAAO,eAAe,IAAI;AAC3B;AAKA,eAAsB,eAAuC;AAC5D,SAAO,cAAc,MAAM,aAAa,YAAU;AACjD,UAAM,QAAQ,OAAO,MAAM,qBAAqB;AAChD,WAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,EAC3B,CAAC;AACF;AAKA,eAAe,qBAA+C;AAC7D,UAAQ,IAAI,MAAM,KAAK,iDAA0C,CAAC;AAElE,MAAI;AACH,UAAMF,WAAU,mBAAmB;AAAA,MAClC,SAAS;AAAA;AAAA,IACV,CAAC;AAGD,UAAM,UAAU,MAAM,aAAa;AACnC,QAAI,CAAC,SAAS;AACb,aAAO;AAAA,QACN,SAAS;AAAA,QACT,SAAS,MAAM,IAAI,mEAA8D;AAAA,MAClF;AAAA,IACD;AAEA,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SAAS,MAAM,MAAM,qDAAgD,OAAO,IAAI;AAAA,MAChF;AAAA,IACD;AAAA,EACD,SAAS,OAAgB;AACxB,UAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACtE,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SACC,MAAM,IAAI,sDAAiD,IAC3D,MAAM,IAAI,SAAS,IACnB,WACA,SACA,MAAM,IAAI,2CAA2C,IACrD,MAAM,KAAK,yBAAyB;AAAA,IACtC;AAAA,EACD;AACD;AAKA,eAAe,iBAA2C;AACzD,UAAQ,IAAI,MAAM,KAAK,6CAAsC,CAAC;AAC9D,UAAQ,IAAI,MAAM,IAAI,yCAAyC,CAAC;AAEhE,MAAI;AACH,UAAMA,WAAU,oCAAoC;AAAA,MACnD,SAAS;AAAA;AAAA,IACV,CAAC;AAGD,UAAM,UAAU,MAAM,aAAa;AACnC,QAAI,CAAC,SAAS;AAEb,aAAO;AAAA,QACN,SAAS;AAAA,QACT,SACC,MAAM,MAAM,6CAAwC,IACpD,MAAM;AAAA,UACL;AAAA,QACD;AAAA,MACF;AAAA,IACD;AAEA,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SAAS,MAAM,MAAM,qDAAgD,OAAO,IAAI;AAAA,MAChF;AAAA,IACD;AAAA,EACD,SAAS,OAAgB;AACxB,UAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACtE,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SACC,MAAM,IAAI,kDAA6C,IACvD,MAAM,IAAI,SAAS,IACnB,WACA,SACA,MAAM,IAAI,2CAA2C,IACrD,MAAM,KAAK,yBAAyB;AAAA,IACtC;AAAA,EACD;AACD;AAMA,eAAe,iBAA2C;AAEzD,QAAM,cAAc,MAAM,oBAAoB;AAE9C,MAAI,aAAa;AAEhB,WAAO,mBAAmB;AAAA,EAC3B;AAGA,SAAO,eAAe;AACvB;AAKA,eAAe,mBAA6C;AAE3D,QAAM,YAAY,MAAM,kBAAkB;AAE1C,MAAI,CAAC,WAAW;AACf,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SACC,MAAM,IAAI,mDAA8C,IACxD,MAAM,IAAI,oEAAoE,IAC9E,MAAM,IAAI,2CAA2C,IACrD,MAAM,KAAK,yBAAyB;AAAA,IACtC;AAAA,EACD;AAEA,UAAQ,IAAI,MAAM,KAAK,+CAAwC,CAAC;AAEhE,MAAI;AACH,UAAMA,WAAU,2CAA2C;AAAA,MAC1D,SAAS;AAAA;AAAA,IACV,CAAC;AAGD,UAAM,UAAU,MAAM,aAAa;AACnC,QAAI,CAAC,SAAS;AACb,aAAO;AAAA,QACN,SAAS;AAAA,QACT,SAAS,MAAM,IAAI,mEAA8D;AAAA,MAClF;AAAA,IACD;AAEA,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SAAS,MAAM,MAAM,qDAAgD,OAAO,IAAI;AAAA,MAChF;AAAA,IACD;AAAA,EACD,SAAS,OAAgB;AACxB,UAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACtE,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SACC,MAAM,IAAI,oDAA+C,IACzD,MAAM,IAAI,SAAS,IACnB,WACA,SACA,MAAM,IAAI,2CAA2C,IACrD,MAAM,KAAK,yBAAyB;AAAA,IACtC;AAAA,EACD;AACD;AAKA,eAAe,iBAA2C;AACzD,QAAM,iBAAiB,MAAM,0BAA0B;AAEvD,MAAI,CAAC,gBAAgB;AACpB,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SACC,MAAM,IAAI,yDAAoD,IAC9D,MAAM,IAAI,qDAAqD,IAC/D,MAAM,IAAI,2CAA2C,IACrD,MAAM,KAAK,yBAAyB;AAAA,IACtC;AAAA,EACD;AAEA,UAAQ,IAAI,MAAM,KAAK,uCAAgC,eAAe,IAAI,KAAK,CAAC;AAChF,UAAQ,IAAI,MAAM,IAAI,2CAA2C,CAAC;AAElE,MAAI;AACH,QAAI;AAEJ,YAAQ,eAAe,MAAM;AAAA,MAC5B,KAAK;AAEJ,yBACC;AAID;AAAA,MACD,KAAK;AACJ,yBAAiB;AACjB;AAAA,MACD,KAAK;AACJ,yBAAiB;AACjB;AAAA,MACD,KAAK;AACJ,yBAAiB;AACjB;AAAA,MACD;AACC,eAAO;AAAA,UACN,SAAS;AAAA,UACT,SAAS,MAAM,IAAI,uCAAkC,eAAe,IAAI,EAAE;AAAA,QAC3E;AAAA,IACF;AAEA,UAAMA,WAAU,gBAAgB;AAAA,MAC/B,SAAS;AAAA;AAAA,IACV,CAAC;AAGD,UAAM,UAAU,MAAM,aAAa;AACnC,QAAI,CAAC,SAAS;AACb,aAAO;AAAA,QACN,SAAS;AAAA,QACT,SAAS,MAAM,IAAI,mEAA8D;AAAA,MAClF;AAAA,IACD;AAEA,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SAAS,MAAM,MAAM,qDAAgD,OAAO,IAAI;AAAA,MAChF;AAAA,IACD;AAAA,EACD,SAAS,OAAgB;AACxB,UAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACtE,WAAO;AAAA,MACN,SAAS;AAAA,MACT,SACC,MAAM,IAAI,yCAAoC,IAC9C,MAAM,IAAI,SAAS,IACnB,WACA,SACA,MAAM,IAAI,2CAA2C,IACrD,MAAM,KAAK,yBAAyB;AAAA,IACtC;AAAA,EACD;AACD;AAMA,eAAsB,YAAsC;AAC3D,QAAMG,YAAW,QAAQ;AAEzB,UAAQA,WAAU;AAAA,IACjB,KAAK;AACJ,aAAO,eAAe;AAAA,IAEvB,KAAK;AACJ,aAAO,iBAAiB;AAAA,IAEzB,KAAK;AACJ,aAAO,eAAe;AAAA,IAEvB;AACC,aAAO;AAAA,QACN,SAAS;AAAA,QACT,SACC,MAAM,IAAI,gCAA2BA,SAAQ;AAAA;AAAA,CAAM,IACnD,MAAM,IAAI,2CAA2C,IACrD,MAAM,KAAK,yBAAyB;AAAA,MACtC;AAAA,EACF;AACD;AAKO,SAAS,iCAAyC;AACxD,QAAMA,YAAW,QAAQ;AAEzB,UAAQA,WAAU;AAAA,IACjB,KAAK;AACJ,aACC,MAAM,OAAO,sDAA+C,IAC5D,MAAM,IAAI,sDAAsD,IAChE,MAAM,KAAK,wCAAwC,IACnD,MAAM,IAAI,wBAAwB,IAClC,MAAM,KAAK,uBAAuB,IAClC,MAAM,IAAI,+BAA+B,IACzC,MAAM,KAAK,0CAA0C;AAAA,IAGvD,KAAK;AACJ,aACC,MAAM,OAAO,wDAAiD,IAC9D,MAAM,IAAI,oCAAoC,IAC9C,MAAM,KAAK,sCAAsC,IACjD,MAAM,IAAI,+BAA+B,IACzC,MAAM,KAAK,0CAA0C;AAAA,IAGvD,KAAK;AACJ,aACC,MAAM,OAAO,sDAA+C,IAC5D,MAAM,IAAI,kBAAkB,IAC5B,MAAM;AAAA,QACL;AAAA,MACD,IACA,MAAM,IAAI,gBAAgB,IAC1B,MAAM,KAAK,2BAA2B,IACtC,MAAM,IAAI,eAAe,IACzB,MAAM,KAAK,iCAAiC,IAC5C,MAAM,IAAI,oBAAoB,IAC9B,MAAM,KAAK,yBAAyB;AAAA,IAGtC;AACC,aACC,MAAM,OAAO,8CAAuC,IACpD,MAAM,IAAI,iBAAiB,IAC3B,MAAM,KAAK,yBAAyB;AAAA,EAEvC;AACD;","names":["exec","promisify","exec","promisify","execAsync","execAsync","promisify","exec","platform"]}
|