diff --git a/ccw/src/core/routes/codexlens-routes.ts b/ccw/src/core/routes/codexlens-routes.ts index e7738efc..738de5b7 100644 --- a/ccw/src/core/routes/codexlens-routes.ts +++ b/ccw/src/core/routes/codexlens-routes.ts @@ -1357,6 +1357,29 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise return { success: false, error: 'CodexLens not installed', status: 400 }; } + // Verify directory is indexed before starting watcher + try { + const statusResult = await executeCodexLens(['projects', 'list', '--json']); + if (statusResult.success && statusResult.stdout) { + const parsed = extractJSON(statusResult.stdout); + const projects = parsed.result || parsed || []; + const normalizedTarget = targetPath.toLowerCase().replace(/\\/g, '/'); + const isIndexed = Array.isArray(projects) && projects.some((p: { source_root: string }) => + p.source_root && p.source_root.toLowerCase().replace(/\\/g, '/') === normalizedTarget + ); + if (!isIndexed) { + return { + success: false, + error: `Directory is not indexed: ${targetPath}. Run 'codexlens init' first.`, + status: 400 + }; + } + } + } catch (err) { + console.warn('[CodexLens] Could not verify index status:', err); + // Continue anyway - watcher will fail with proper error if not indexed + } + // Spawn watch process using Python (no shell: true for security) // CodexLens is a Python package, must run via python -m codexlens const pythonPath = getVenvPythonPath(); diff --git a/ccw/src/templates/dashboard-js/views/codexlens-manager.js b/ccw/src/templates/dashboard-js/views/codexlens-manager.js index 144521d8..af7edc32 100644 --- a/ccw/src/templates/dashboard-js/views/codexlens-manager.js +++ b/ccw/src/templates/dashboard-js/views/codexlens-manager.js @@ -4558,11 +4558,25 @@ async function showWatcherControlModal() { try { showRefreshToast(t('codexlens.loadingWatcherStatus') || 'Loading watcher status...', 'info'); - // Fetch current watcher status - const response = await fetch('/api/codexlens/watch/status'); - const status = await response.json(); + // Fetch current watcher status and indexed projects in parallel + const [statusResponse, indexesResponse] = await Promise.all([ + fetch('/api/codexlens/watch/status'), + fetch('/api/codexlens/indexes') + ]); + const status = await statusResponse.json(); + const indexes = await indexesResponse.json(); - const modalHtml = buildWatcherControlContent(status); + // Get first indexed project path as default + let defaultPath = ''; + if (indexes.success && indexes.projects && indexes.projects.length > 0) { + // Sort by last_indexed desc and pick the most recent + const sorted = indexes.projects.sort((a, b) => + new Date(b.last_indexed || 0) - new Date(a.last_indexed || 0) + ); + defaultPath = sorted[0].source_root || ''; + } + + const modalHtml = buildWatcherControlContent(status, defaultPath); // Create and show modal const tempContainer = document.createElement('div'); @@ -4584,9 +4598,12 @@ async function showWatcherControlModal() { /** * Build File Watcher control modal content + * @param {Object} status - Watcher status + * @param {string} defaultPath - Default path from indexed projects */ -function buildWatcherControlContent(status) { +function buildWatcherControlContent(status, defaultPath) { const running = status.running || false; + defaultPath = defaultPath || ''; const rootPath = status.root_path || ''; const eventsProcessed = status.events_processed || 0; const uptimeSeconds = status.uptime_seconds || 0; @@ -4652,7 +4669,7 @@ function buildWatcherControlContent(status) { '
' + '
' + '' + - '' + '
' + '
' +