{"version":3,"sources":["../../src/commands/watch.ts"],"names":["watchCommand","options","cwd","clipboardWatcher","configWatcher","debounceTimer","startServices","config","logger","coreLogger","systemPromptPath","path","getStateDirectory","systemPrompt","fs","clipboardy","error","chalk","getErrorMessage","createBulkClipboardWatcher","contents","parsedResponses","content","parsedResponse","parseLLMResponse","block","processPatchesBulk","createClipboardWatcher","processPatch","handleConfigChange","newConfig","findConfig","initialConfig","loadConfigOrExit","configPath","findConfigPath","clipboardPollInterval"],"mappings":"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","file":"watch.cjs","sourcesContent":["import {\n  findConfig,\n  loadConfigOrExit,\n  findConfigPath,\n  getStateDirectory,\n} from '../core/config';\nimport { createClipboardWatcher, createBulkClipboardWatcher } from '../core/clipboard';\nimport chalk from 'chalk';\nimport {\n  parseLLMResponse,\n  type ParsedLLMResponse,\n  logger as coreLogger,\n} from 'relaycode-core';\nimport { processPatch, processPatchesBulk } from '../core/transaction';\nimport { logger, getErrorMessage } from '../utils/logger';\nimport { type Config } from 'relaycode-core';\nimport fs from 'fs';\nimport path from 'path';\nimport clipboardy from 'clipboardy';\n\n\nexport const watchCommand = async (options: { yes?: boolean } = {}, cwd: string = process.cwd()): Promise<{ stop: () => void }> => {\n  let clipboardWatcher: { stop: () => void } | null = null;\n  let configWatcher: fs.FSWatcher | null = null;\n  let debounceTimer: NodeJS.Timeout | null = null;\n\n  const startServices = async (config: Config) => {\n    // Stop existing watcher if it's running\n    if (clipboardWatcher) {\n      clipboardWatcher.stop();\n    }\n\n    logger.setLevel(config.core.logLevel);\n    if (config.core.logLevel === 'debug') {\n      coreLogger.setLevel('debug');\n    }\n    logger.debug(`Log level set to: ${config.core.logLevel}`);\n    logger.debug(`Preferred strategy set to: ${config.watcher.preferredStrategy}`);\n\n    const systemPromptPath = path.join(getStateDirectory(cwd), 'prompts', 'system-prompt.md');\n    try {\n      const systemPrompt = await fs.promises.readFile(systemPromptPath, 'utf-8');\n      await clipboardy.write(systemPrompt);\n      logger.success('✅ System prompt copied to clipboard.');\n      logger.info(\n        `Paste it into your LLM's \"System Prompt\" or \"Custom Instructions\" section.`\n      );\n    } catch (error) {\n      logger.error(\n        `Could not read or copy system prompt from ${chalk.cyan(systemPromptPath)}.`\n      );\n      logger.info(\n        `Please run ${chalk.magenta(\"'relay init'\")} to generate it, or create it manually.`\n      );\n      logger.debug(`Error details: ${getErrorMessage(error)}`);\n    }\n\n    // Use bulk clipboard watcher if bulk mode is enabled\n    if (config.watcher.enableBulkProcessing) {\n      clipboardWatcher = createBulkClipboardWatcher(\n        config.watcher.clipboardPollInterval,\n        async (contents) => {\n          logger.info(`Processing ${contents.length} clipboard items in bulk mode...`);\n\n          const parsedResponses: ParsedLLMResponse[] = [];\n          for (const content of contents) {\n            const parsedResponse = parseLLMResponse(content);\n            if (parsedResponse) {\n              if (parsedResponse.ignoredBlocks && parsedResponse.ignoredBlocks.length > 0) {\n                parsedResponse.ignoredBlocks.forEach(block => {\n                  logger.warn(`${chalk.yellow('⚠ Ignored block:')} ${block.reason}`);\n                });\n              }\n              // Only add responses that have operations to process\n              if (parsedResponse.operations.length > 0) {\n                parsedResponses.push(parsedResponse);\n              }\n            }\n          }\n\n          if (parsedResponses.length === 0) {\n            logger.warn('No operations to process from clipboard items.');\n            return;\n          }\n\n          await processPatchesBulk(config, parsedResponses, { cwd, notifyOnStart: true, yes: options.yes });\n          logger.info(chalk.gray(`\\n[relay] Watching for patches...`));\n        },\n        config.watcher.bulkSize || 5,\n        config.watcher.bulkTimeout || 30000\n      );\n    } else {\n      clipboardWatcher = createClipboardWatcher(config.watcher.clipboardPollInterval, async (content) => {\n        logger.debug('New clipboard content detected. Attempting to parse...');\n        const parsedResponse = parseLLMResponse(content);\n\n        if (!parsedResponse) {\n          logger.debug('Clipboard content is not a valid relaycode patch. Ignoring.');\n          return;\n        }\n        \n        // Check project ID before notifying and processing.\n        if (parsedResponse.control.projectId !== config.projectId) {\n          logger.debug(`Ignoring patch for different project (expected '${config.projectId}', got '${parsedResponse.control.projectId}').`);\n          return;\n        }\n\n        if (parsedResponse.ignoredBlocks && parsedResponse.ignoredBlocks.length > 0) {\n            parsedResponse.ignoredBlocks.forEach(block => {\n                logger.warn(`${chalk.yellow('⚠ Ignored block:')} ${block.reason}`);\n            });\n        }\n        if (parsedResponse.operations.length === 0) {\n            return; // Silently return, user has been notified of ignored blocks if any.\n        }\n\n        await processPatch(config, parsedResponse, { cwd, notifyOnStart: true, yes: options.yes });\n        logger.info(chalk.gray(`\\n[relay] Watching for patches...`));\n      });\n    }\n  };\n\n  const handleConfigChange = () => {\n    if (debounceTimer) clearTimeout(debounceTimer);\n    debounceTimer = setTimeout(async () => {\n      logger.info(`Configuration file change detected. Reloading...`);\n      try {\n        const newConfig = await findConfig(cwd);\n        if (newConfig) {\n          logger.success('Configuration reloaded. Restarting services...');\n          await startServices(newConfig);\n        } else {\n          logger.error(`Configuration file is invalid or has been deleted. Services paused.`);\n          if (clipboardWatcher) {\n            clipboardWatcher.stop();\n            clipboardWatcher = null;\n          }\n        }\n      } catch (error) {\n        logger.error(`Error reloading configuration: ${error instanceof Error ? error.message : String(error)}`);\n      }\n    }, 250);\n  };\n\n  // Initial startup\n  const initialConfig = await loadConfigOrExit(cwd);\n  const configPath = await findConfigPath(cwd);\n  \n  const { clipboardPollInterval } = initialConfig.watcher;\n  logger.info(\n    chalk.gray(\n      `[relay] Watching for patches... (project: ${initialConfig.projectId}, approval: ${initialConfig.patch.approvalMode}, poll: ${clipboardPollInterval}ms)`\n    )\n  );\n  \n  logger.success('Configuration loaded. Starting relaycode watch...');\n  await startServices(initialConfig);\n\n  // Watch for changes after initial setup\n  if (initialConfig.core.watchConfig && configPath) {\n    configWatcher = fs.watch(configPath, handleConfigChange);\n  } else {\n    logger.info('Configuration file watching is disabled. Changes to config will require a restart to take effect.');\n  }\n\n  const stopAll = () => {\n    if (clipboardWatcher) {\n      clipboardWatcher.stop();\n    }\n    if (configWatcher) {\n      configWatcher.close();\n      logger.info('Configuration file watcher stopped.');\n    }\n    if (debounceTimer) {\n      clearTimeout(debounceTimer);\n    }\n  };\n  return { stop: stopAll };\n};\n"]}