{"version":3,"sources":["../../src/core/clipboard.ts"],"names":["moduleDir","path","fileURLToPath","packageRoot","sourceExePath","FALLBACKS_DIR","WINDOWS_DIR","WINDOWS_CLIPBOARD_EXE_NAME","checkLinuxClipboardDependencies","logger","exitCode","executeShellCommand","error","getErrorMessage","WINDOWS_FALLBACK_DIR","WINDOWS_CLIPBOARD_PATH","createDirectWindowsClipboardReader","resolve","fs","command","exec","stdout","stderr","syncError","ensureClipboardExecutable","shouldCopy","createClipboardWatcher","pollInterval","callback","reader","clipboardReader","clipboardy","lastContent","intervalId","checkClipboard","content","start","stop"],"mappings":"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","file":"clipboard.cjs","sourcesContent":["import clipboardy from 'clipboardy';\nimport { logger, getErrorMessage } from '../utils/logger';\nimport fs from 'fs';\nimport path from 'path';\nimport { exec, type ExecException } from 'child_process';\nimport { executeShellCommand } from '../utils/shell';\nimport { FALLBACKS_DIR, WINDOWS_CLIPBOARD_EXE_NAME, WINDOWS_DIR } from '../utils/constants';\nimport { fileURLToPath } from 'url';\n\ntype ClipboardCallback = (content: string) => void;\ntype ClipboardReader = () => Promise<string>;\n\n// Path to the directory of the current module (e.g., /path/to/relaycode/dist)\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n// Path to the root of the relaycode package\nconst packageRoot = path.join(moduleDir, '..');\n// Path to the clipboard executable within the package\nconst sourceExePath = path.join(packageRoot, FALLBACKS_DIR, WINDOWS_DIR, WINDOWS_CLIPBOARD_EXE_NAME);\n\n\nconst checkLinuxClipboardDependencies = async () => {\n  if (process.platform === 'linux') {\n      logger.debug('Checking for clipboard dependencies on Linux (xsel or xclip)...');\n      try {\n          // Using `command -v` is more portable than `which`. Redirect stdout/stderr to keep it clean.\n          const { exitCode } = await executeShellCommand('command -v xsel >/dev/null 2>&1 || command -v xclip >/dev/null 2>&1');\n          if (exitCode !== 0) {\n              logger.error('-----------------------------------------------------------------------');\n              logger.error('ACTION REQUIRED: Clipboard support on Linux requires `xsel` or `xclip`.');\n              logger.error('Please install one of these tools to enable clipboard monitoring.');\n              logger.error('Example on Debian/Ubuntu: sudo apt install xsel');\n              logger.error('Example on Fedora/CentOS: sudo dnf install xsel');\n              logger.error('Example on Arch Linux:    sudo pacman -S xsel');\n              logger.error('-----------------------------------------------------------------------');\n          } else {\n              logger.debug('Linux clipboard dependency check passed.');\n          }\n      } catch (error) {\n          logger.warn(`An error occurred while checking for clipboard dependencies: ${getErrorMessage(error)}`);\n      }\n  }\n};\n\nconst WINDOWS_FALLBACK_DIR = path.join(process.cwd(), FALLBACKS_DIR, WINDOWS_DIR);\nconst WINDOWS_CLIPBOARD_PATH = path.join(WINDOWS_FALLBACK_DIR, WINDOWS_CLIPBOARD_EXE_NAME);\n\n// Direct Windows clipboard reader that uses the executable directly\nconst createDirectWindowsClipboardReader = (): ClipboardReader => {\n  return () => new Promise((resolve) => {\n    try {\n      if (!fs.existsSync(WINDOWS_CLIPBOARD_PATH)) {\n        logger.error('Windows clipboard executable not found. Cannot watch clipboard on Windows.');\n        // Resolve with empty string to avoid stopping the watcher loop, but log an error.\n        return resolve('');\n      }\n      \n      const command = `\"${WINDOWS_CLIPBOARD_PATH}\" --paste`;\n      \n      exec(command, { encoding: 'utf8' }, (error: ExecException | null, stdout: string, stderr: string) => {\n        if (error) {\n          // It's common for the clipboard executable to fail if the clipboard is empty\n          // or contains non-text data (e.g., an image). We can treat this as \"no content\".\n          // We don't log this as an error to avoid spamming the console during normal use.\n          logger.debug(`Windows clipboard read command failed (this is often normal): ${stderr.trim()}`);\n          resolve('');\n        } else {\n          resolve(stdout);\n        }\n      });\n    } catch (syncError) {\n      // Catch synchronous errors during setup (e.g., path issues).\n      logger.error(`A synchronous error occurred while setting up clipboard reader: ${getErrorMessage(syncError)}`);\n      resolve('');\n    }\n  });\n};\n\n// Check if the clipboard executable exists and fix path issues on Windows\nconst ensureClipboardExecutable = () => {\n  if (process.platform === 'win32') {\n    try {\n      // Create fallbacks directory in the current project if it doesn't exist\n      if (!fs.existsSync(WINDOWS_FALLBACK_DIR)) {\n        fs.mkdirSync(WINDOWS_FALLBACK_DIR, { recursive: true });\n      }\n      \n      if (fs.existsSync(sourceExePath)) {\n        let shouldCopy = true;\n        if (fs.existsSync(WINDOWS_CLIPBOARD_PATH)) {\n          // If the file exists, check if the size is the same.\n          // This is a simple way to check if it's the same file.\n          if (fs.statSync(sourceExePath).size === fs.statSync(WINDOWS_CLIPBOARD_PATH).size) {\n            shouldCopy = false;\n          }\n        }\n        \n        if (shouldCopy) {\n          fs.copyFileSync(sourceExePath, WINDOWS_CLIPBOARD_PATH);\n          logger.info('Copied Windows clipboard executable to local fallbacks directory');\n        }\n      } else {\n        logger.error(`Windows clipboard executable not found in package at: ${sourceExePath}`);\n      }\n    } catch (error) {\n      logger.warn('Error ensuring clipboard executable: ' + getErrorMessage(error));\n    }\n  }\n};\n\nexport const createClipboardWatcher = (\n  pollInterval: number,\n  callback: ClipboardCallback,\n  reader?: ClipboardReader,\n) => {\n  // Ensure clipboard executable exists before starting\n  ensureClipboardExecutable();\n  // Check for Linux dependencies. This is fire-and-forget.\n  checkLinuxClipboardDependencies();\n  \n  // On Windows, use the direct Windows reader\n  // Otherwise use the provided reader or clipboardy\n  const clipboardReader = process.platform === 'win32' ? \n    createDirectWindowsClipboardReader() : \n    reader || clipboardy.read;\n  \n  let lastContent = '';\n  let intervalId: NodeJS.Timeout | null = null;\n\n  const checkClipboard = async () => {\n    try {\n      const content = await clipboardReader();\n      if (content && content !== lastContent) {\n        lastContent = content;\n        callback(content);\n      }\n    } catch (error) {\n      // It's common for clipboard access to fail occasionally (e.g., on VM focus change)\n      // So we log a warning but don't stop the watcher.\n      logger.warn('Could not read from clipboard: ' + getErrorMessage(error));\n    }\n  };\n\n  const start = () => {\n    if (intervalId) {\n      return;\n    }\n    logger.info(`Starting clipboard watcher (polling every ${pollInterval}ms)`);\n    // Immediately check once, then start the interval\n    checkClipboard();\n    intervalId = setInterval(checkClipboard, pollInterval);\n  };\n\n  const stop = () => {\n    if (intervalId) {\n      clearInterval(intervalId);\n      intervalId = null;\n      logger.info('Clipboard watcher stopped.');\n    }\n  };\n\n  start();\n  \n  return { stop };\n};"]}