{"version":3,"sources":["/home/mkabumattar/work/withrawi/rawi/dist/chunk-MGIUGMP2.cjs","../src/core/exec/executor.ts"],"names":["execAsync","promisify","getShellConfig","shell","detectedShell","detectShell","INTERACTIVE_COMMANDS","isInteractiveCommand","command","trimmedCommand","interactiveCmd"],"mappings":"AAAA;AACA,wDAAwC,8CCDd,8DACN,4BACI,4EACN,IAIZA,CAAAA,CAAYC,6BAAAA,mBAAc,CAAA,CAYhC,SAASC,CAAAA,CAAeC,CAAAA,CAAiD,CACvE,IAAMC,CAAAA,CAAgBD,CAAAA,EAASE,iCAAAA,CAAY,CAE3C,EAAA,CAAI,OAAA,CAAQ,QAAA,GAAa,OAAA,CACvB,MAAA,CAAQD,CAAAA,CAAe,CACrB,IAAK,MAAA,CACH,MAAO,CAAC,KAAA,CAAO,UAAA,CAAY,IAAA,CAAM,CAAC,YAAA,CAAc,UAAU,CAAC,CAAA,CAC7D,IAAK,YAAA,CACH,MAAO,CAAC,KAAA,CAAO,gBAAA,CAAkB,IAAA,CAAM,CAAC,YAAA,CAAc,UAAU,CAAC,CAAA,CACnE,IAAK,KAAA,CACH,MAAO,CAAC,KAAA,CAAO,SAAA,CAAW,IAAA,CAAM,CAAC,IAAI,CAAC,CAAA,CACxC,OAAA,CACE,MAAO,CAAC,KAAA,CAAO,UAAA,CAAY,IAAA,CAAM,CAAC,YAAA,CAAc,UAAU,CAAC,CAC/D,CAAA,KAGA,MAAO,CAAC,KAAA,CADUD,CAAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAS,WAAA,CACtB,IAAA,CAAM,CAAC,IAAI,CAAC,CAE1C,CAEA,IAAMG,CAAAA,CAAuB,CAC3B,MAAA,CACA,MAAA,CACA,KAAA,CACA,MAAA,CACA,KAAA,CACA,MAAA,CACA,OAAA,CACA,MAAA,CACA,MAAA,CACA,IAAA,CACA,MAAA,CACA,QAAA,CACA,OAAA,CACA,SAAA,CACA,eAAA,CACA,iBAAA,CACA,kBAAA,CACA,KAAA,CACA,OAAA,CACA,MAAA,CACA,OAAA,CACA,WAAA,CACA,YAAA,CACA,WAAA,CACA,SAAA,CACA,KAAA,CACA,MACF,CAAA,CAEA,SAASC,CAAAA,CAAqBC,CAAAA,CAA0B,CACtD,IAAMC,CAAAA,CAAiBD,CAAAA,CAAQ,IAAA,CAAK,CAAA,CAAE,WAAA,CAAY,CAAA,CAClD,OAAOF,CAAAA,CAAqB,IAAA,CACzBI,CAAAA,EACCD,CAAAA,CAAe,UAAA,CAAWC,CAAc,CAAA,EACxCD,CAAAA,CAAe,QAAA,CAAS,CAAA,CAAA,EAAIC,CAAc,CAAA,CAAA;AAiL5B;AA0DsC;ADjTk1B","file":"/home/mkabumattar/work/withrawi/rawi/dist/chunk-MGIUGMP2.cjs","sourcesContent":[null,"import {exec, spawn} from 'node:child_process';\nimport * as os from 'node:os';\nimport {promisify} from 'node:util';\nimport chalk from 'chalk';\nimport {detectShell} from '../../cli/commands/completion/utils.js';\nimport type {ExecContext, ExecResult} from '../../cli/commands/exec/types.js';\n\nconst execAsync = promisify(exec);\n\nexport interface ExecuteCommandOptions {\n  command: string;\n  shell?: string;\n  cwd?: string;\n  timeout?: number;\n  dryRun?: boolean;\n  interactive?: boolean;\n  copyCommand?: boolean;\n}\n\nfunction getShellConfig(shell?: string): {shell: string; args: string[]} {\n  const detectedShell = shell || detectShell();\n\n  if (process.platform === 'win32') {\n    switch (detectedShell) {\n      case 'pwsh':\n        return {shell: 'pwsh.exe', args: ['-NoProfile', '-Command']};\n      case 'powershell':\n        return {shell: 'powershell.exe', args: ['-NoProfile', '-Command']};\n      case 'cmd':\n        return {shell: 'cmd.exe', args: ['/c']};\n      default:\n        return {shell: 'pwsh.exe', args: ['-NoProfile', '-Command']};\n    }\n  } else {\n    const shellPath = shell || process.env.SHELL || '/bin/bash';\n    return {shell: shellPath, args: ['-c']};\n  }\n}\n\nconst INTERACTIVE_COMMANDS = [\n  'btop',\n  'htop',\n  'top',\n  'nano',\n  'vim',\n  'nvim',\n  'emacs',\n  'less',\n  'more',\n  'vi',\n  'tmux',\n  'screen',\n  'watch',\n  'tail -f',\n  'journalctl -f',\n  'docker exec -it',\n  'kubectl exec -it',\n  'ssh',\n  'mysql',\n  'psql',\n  'mongo',\n  'redis-cli',\n  'python3 -i',\n  'python -i',\n  'node -i',\n  'irb',\n  'ghci',\n];\n\nfunction isInteractiveCommand(command: string): boolean {\n  const trimmedCommand = command.trim().toLowerCase();\n  return INTERACTIVE_COMMANDS.some(\n    (interactiveCmd) =>\n      trimmedCommand.startsWith(interactiveCmd) ||\n      trimmedCommand.includes(` ${interactiveCmd}`),\n  );\n}\n\nexport async function executeCommand(\n  options: ExecuteCommandOptions,\n): Promise<ExecResult> {\n  const startTime = Date.now();\n\n  if (options.copyCommand) {\n    setTimeout(() => {\n      void copyToClipboard(options.command)\n        .then(\n          (copied) =>\n            copied && console.log(chalk.dim('📋 Command copied to clipboard')),\n        )\n        .catch(() => {});\n    }, 0);\n  }\n\n  if (options.dryRun) {\n    return {\n      command: options.command,\n      stdout: '[DRY RUN] Command would be executed here',\n      stderr: undefined,\n      exitCode: 0,\n      executionTime: Date.now() - startTime,\n      success: true,\n    };\n  }\n\n  const needsInteractive =\n    options.interactive || isInteractiveCommand(options.command);\n\n  if (needsInteractive) {\n    return await executeInteractiveCommand(options, startTime);\n  }\n\n  try {\n    if (options.command.includes('ssh-add')) {\n      await ensureSSHAgent();\n    }\n\n    const shellConfig = getShellConfig(options.shell);\n\n    const execOptions: any = {\n      cwd: options.cwd || process.cwd(),\n      timeout: options.timeout || 30000,\n      maxBuffer: 1024 * 1024,\n      encoding: 'utf8',\n    };\n\n    if (process.platform === 'win32') {\n      execOptions.shell = 'cmd.exe';\n      execOptions.windowsHide = true;\n    } else {\n      execOptions.shell = shellConfig.shell;\n    }\n\n    const {stdout, stderr} = await execAsync(options.command, execOptions);\n    const executionTime = Date.now() - startTime;\n\n    return {\n      command: options.command,\n      stdout: stdout?.toString() || undefined,\n      stderr: stderr?.toString() || undefined,\n      exitCode: 0,\n      executionTime,\n      success: true,\n    };\n  } catch (error: any) {\n    const executionTime = Date.now() - startTime;\n\n    return {\n      command: options.command,\n      stdout: error.stdout || undefined,\n      stderr: error.stderr || error.message,\n      exitCode: error.code || 1,\n      executionTime,\n      success: false,\n    };\n  }\n}\n\nasync function executeInteractiveCommand(\n  options: ExecuteCommandOptions,\n  startTime: number,\n): Promise<ExecResult> {\n  return new Promise((resolve) => {\n    const shellConfig = getShellConfig(options.shell);\n\n    let child: any;\n    if (process.platform === 'win32') {\n      child = spawn('cmd.exe', ['/c', options.command], {\n        stdio: 'inherit',\n        cwd: options.cwd || process.cwd(),\n        windowsHide: false,\n      });\n    } else {\n      child = spawn(shellConfig.shell, ['-c', options.command], {\n        stdio: 'inherit',\n        cwd: options.cwd || process.cwd(),\n      });\n    }\n\n    child.on('exit', (code: number | null) => {\n      const executionTime = Date.now() - startTime;\n\n      resolve({\n        command: options.command,\n        stdout: undefined,\n        stderr: code !== 0 ? `Process exited with code ${code}` : undefined,\n        exitCode: code || 0,\n        executionTime,\n        success: code === 0,\n      });\n    });\n\n    child.on('error', (error: Error) => {\n      const executionTime = Date.now() - startTime;\n\n      resolve({\n        command: options.command,\n        stdout: undefined,\n        stderr: error.message,\n        exitCode: 1,\n        executionTime,\n        success: false,\n      });\n    });\n  });\n}\n\nasync function ensureSSHAgent(): Promise<void> {\n  if (process.env.SSH_AUTH_SOCK) {\n    console.log('🔑 SSH agent is already running.');\n    return;\n  }\n\n  console.log('🚀 Starting SSH agent...');\n  try {\n    const {stdout} = await execAsync('ssh-agent -s');\n    stdout.split('\\n').forEach((line) => {\n      const match = line.match(/^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*?);/);\n      if (match) {\n        process.env[match[1]] = match[2];\n      }\n    });\n\n    if (!process.env.SSH_AUTH_SOCK) {\n      throw new Error('Failed to start ssh-agent');\n    }\n  } catch (sshError) {\n    console.warn('Warning: Could not start SSH agent:', sshError);\n  }\n}\n\nexport function formatExecutionResult(result: ExecResult): string {\n  const lines: string[] = [];\n\n  lines.push(`🤖 Command: ${result.command}`);\n  lines.push(`⏱️  Execution time: ${result.executionTime}ms`);\n\n  if (result.success) {\n    lines.push('✅ Success');\n    if (result.stdout) {\n      lines.push('📄 Output:');\n      lines.push(result.stdout);\n    }\n  } else {\n    lines.push(`❌ Failed (exit code: ${result.exitCode})`);\n    if (result.stderr) {\n      lines.push('⚠️ Error:');\n      lines.push(result.stderr);\n    }\n  }\n\n  return lines.join('\\n');\n}\n\nexport async function generateCommandContext(): Promise<ExecContext> {\n  let directoryListing = '';\n  try {\n    if (process.platform === 'win32') {\n      const {stdout} = await execAsync('dir /b', {encoding: 'utf8'});\n      directoryListing = stdout;\n    } else {\n      const {stdout} = await execAsync('ls', {encoding: 'utf8'});\n      directoryListing = stdout;\n    }\n  } catch (_) {\n    directoryListing = 'Unable to get directory listing';\n  }\n\n  return {\n    os: {\n      type: os.type(),\n      release: os.release(),\n      platform: os.platform(),\n      arch: os.arch(),\n    },\n    node: {\n      version: process.version,\n    },\n    shell: process.env.SHELL || detectShell() || 'unknown',\n    cwd: process.cwd(),\n    home: os.homedir(),\n    cpu: {\n      model: os.cpus()[0]?.model || 'unknown',\n      cores: os.cpus().length,\n    },\n    memory: {\n      total: Math.floor(os.totalmem() / 1024 / 1024),\n      free: Math.floor(os.freemem() / 1024 / 1024),\n    },\n    directoryListing,\n  };\n}\n\nexport async function copyToClipboard(text: string): Promise<boolean> {\n  if (!text || text.trim() === '') {\n    return false;\n  }\n\n  const fs = await import('node:fs/promises');\n  const path = await import('node:path');\n  const os = await import('node:os');\n  const {execSync} = await import('node:child_process');\n\n  const tempFile = path.join(os.tmpdir(), `clipboard-${Date.now()}.txt`);\n\n  try {\n    await fs.writeFile(tempFile, text, {flag: 'w'});\n\n    if (process.platform === 'darwin') {\n      execSync(`pbcopy < \"${tempFile}\"`, {stdio: 'ignore'});\n    } else if (process.platform === 'win32') {\n      execSync(`type \"${tempFile}\" | clip`, {stdio: 'ignore'});\n    } else {\n      try {\n        execSync(`xclip -selection clipboard < \"${tempFile}\"`, {\n          stdio: 'ignore',\n        });\n      } catch {\n        execSync(`xsel --clipboard --input < \"${tempFile}\"`, {stdio: 'ignore'});\n      }\n    }\n\n    return true;\n  } catch {\n    return false;\n  } finally {\n    void fs.unlink(tempFile).catch(() => {});\n  }\n}\n\nexport function sanitizeCommandOutput(\n  output: string,\n  options: {\n    maxLength?: number;\n    removeAnsi?: boolean;\n    extractCodeBlock?: boolean;\n  } = {},\n): string {\n  if (!output) return '';\n\n  const {\n    maxLength = 10000,\n    removeAnsi = true,\n    extractCodeBlock = false,\n  } = options;\n\n  let result =\n    output.length > maxLength\n      ? `${output.substring(0, maxLength)}... (truncated)`\n      : output;\n\n  if (removeAnsi) {\n    const escapeChar = String.fromCharCode(27);\n    const ansiRegex = new RegExp(`${escapeChar}\\\\[\\\\d+m`, 'g');\n    result = result.replace(ansiRegex, '');\n  }\n\n  if (extractCodeBlock) {\n    const codeBlockRegex = /```(?:[^\\n]*)\\n([\\s\\S]*?)```/g;\n    let lastCodeBlock: string | null = null;\n\n    const matches = [...result.matchAll(codeBlockRegex)];\n    if (matches.length > 0) {\n      const lastMatch = matches[matches.length - 1];\n      if (lastMatch[1]) {\n        lastCodeBlock = lastMatch[1];\n      }\n    }\n\n    if (lastCodeBlock) {\n      result = lastCodeBlock;\n    }\n  }\n\n  return result;\n}\n\nexport function isPotentiallyDangerousCommand(command: string): boolean {\n  const dangerousPatterns = [\n    /\\brm\\s+(-rf?|--recursive|--force)\\b.*\\//,\n    /\\bdd\\s+.*of=/,\n    /\\bmkfs\\b/,\n    /\\bformat\\b/,\n    /\\bshred\\b/,\n    /\\b:(){:|:&};:\\b/,\n    /\\bchmod\\s+-R\\s+777\\b/,\n    /\\b>.*\\/(etc|var|usr)\\//,\n    /\\bwget\\s+.*\\s+\\|\\s+bash\\b/,\n    /\\bcurl\\s+.*\\s+\\|\\s+bash\\b/,\n  ];\n\n  return dangerousPatterns.some((pattern) =>\n    pattern.test(command.toLowerCase()),\n  );\n}\n"]}