mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
feat: implement CodexLens watcher status handling and UI updates
This commit is contained in:
@@ -1374,6 +1374,19 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
|
|||||||
start_time: new Date()
|
start_time: new Date()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Capture stderr for error messages (capped at 4KB to prevent memory leak)
|
||||||
|
const MAX_STDERR_SIZE = 4096;
|
||||||
|
let stderrBuffer = '';
|
||||||
|
if (watcherProcess.stderr) {
|
||||||
|
watcherProcess.stderr.on('data', (data: Buffer) => {
|
||||||
|
stderrBuffer += data.toString();
|
||||||
|
// Cap buffer size to prevent memory leak in long-running watchers
|
||||||
|
if (stderrBuffer.length > MAX_STDERR_SIZE) {
|
||||||
|
stderrBuffer = stderrBuffer.slice(-MAX_STDERR_SIZE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Handle process output for event counting
|
// Handle process output for event counting
|
||||||
if (watcherProcess.stdout) {
|
if (watcherProcess.stdout) {
|
||||||
watcherProcess.stdout.on('data', (data: Buffer) => {
|
watcherProcess.stdout.on('data', (data: Buffer) => {
|
||||||
@@ -1386,11 +1399,38 @@ export async function handleCodexLensRoutes(ctx: RouteContext): Promise<boolean>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle spawn errors (e.g., ENOENT)
|
||||||
|
watcherProcess.on('error', (err: Error) => {
|
||||||
|
console.error(`[CodexLens] Watcher spawn error: ${err.message}`);
|
||||||
|
watcherStats.running = false;
|
||||||
|
watcherProcess = null;
|
||||||
|
broadcastToClients({
|
||||||
|
type: 'CODEXLENS_WATCHER_STATUS',
|
||||||
|
payload: { running: false, error: `Spawn error: ${err.message}` }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Handle process exit
|
// Handle process exit
|
||||||
watcherProcess.on('exit', (code: number) => {
|
watcherProcess.on('exit', (code: number) => {
|
||||||
watcherStats.running = false;
|
watcherStats.running = false;
|
||||||
watcherProcess = null;
|
watcherProcess = null;
|
||||||
console.log(`[CodexLens] Watcher exited with code ${code}`);
|
console.log(`[CodexLens] Watcher exited with code ${code}`);
|
||||||
|
|
||||||
|
// Broadcast error if exited with non-zero code
|
||||||
|
if (code !== 0) {
|
||||||
|
const errorMsg = stderrBuffer.trim() || `Exited with code ${code}`;
|
||||||
|
// Use stripAnsiCodes helper for consistent ANSI cleanup
|
||||||
|
const cleanError = stripAnsiCodes(errorMsg);
|
||||||
|
broadcastToClients({
|
||||||
|
type: 'CODEXLENS_WATCHER_STATUS',
|
||||||
|
payload: { running: false, error: cleanError }
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
broadcastToClients({
|
||||||
|
type: 'CODEXLENS_WATCHER_STATUS',
|
||||||
|
payload: { running: false }
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Broadcast watcher started
|
// Broadcast watcher started
|
||||||
|
|||||||
@@ -455,6 +455,23 @@ function handleNotification(data) {
|
|||||||
console.log('[CodexLens] Index progress:', payload.stage, payload.percent + '%');
|
console.log('[CodexLens] Index progress:', payload.stage, payload.percent + '%');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'CODEXLENS_WATCHER_STATUS':
|
||||||
|
// Handle CodexLens file watcher status updates
|
||||||
|
if (typeof handleWatcherStatusUpdate === 'function') {
|
||||||
|
handleWatcherStatusUpdate(payload);
|
||||||
|
}
|
||||||
|
if (payload.error) {
|
||||||
|
console.error('[CodexLens] Watcher error:', payload.error);
|
||||||
|
if (typeof showRefreshToast === 'function') {
|
||||||
|
showRefreshToast('Watcher error: ' + payload.error, 'error');
|
||||||
|
}
|
||||||
|
} else if (payload.running) {
|
||||||
|
console.log('[CodexLens] Watcher running:', payload.path);
|
||||||
|
} else {
|
||||||
|
console.log('[CodexLens] Watcher stopped');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log('[WS] Unknown notification type:', type);
|
console.log('[WS] Unknown notification type:', type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4783,3 +4783,33 @@ function closeWatcherModal() {
|
|||||||
var modal = document.getElementById('watcherControlModal');
|
var modal = document.getElementById('watcherControlModal');
|
||||||
if (modal) modal.remove();
|
if (modal) modal.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle watcher status update from WebSocket
|
||||||
|
* @param {Object} payload - { running: boolean, path?: string, error?: string }
|
||||||
|
*/
|
||||||
|
function handleWatcherStatusUpdate(payload) {
|
||||||
|
var toggle = document.getElementById('watcherToggle');
|
||||||
|
var statsDiv = document.getElementById('watcherStats');
|
||||||
|
var configDiv = document.getElementById('watcherStartConfig');
|
||||||
|
|
||||||
|
if (payload.error) {
|
||||||
|
// Watcher failed - update UI to show stopped state
|
||||||
|
if (toggle) toggle.checked = false;
|
||||||
|
if (statsDiv) statsDiv.style.display = 'none';
|
||||||
|
if (configDiv) configDiv.style.display = 'block';
|
||||||
|
stopWatcherStatusPolling();
|
||||||
|
} else if (payload.running) {
|
||||||
|
// Watcher started
|
||||||
|
if (toggle) toggle.checked = true;
|
||||||
|
if (statsDiv) statsDiv.style.display = 'block';
|
||||||
|
if (configDiv) configDiv.style.display = 'none';
|
||||||
|
startWatcherStatusPolling();
|
||||||
|
} else {
|
||||||
|
// Watcher stopped normally
|
||||||
|
if (toggle) toggle.checked = false;
|
||||||
|
if (statsDiv) statsDiv.style.display = 'none';
|
||||||
|
if (configDiv) configDiv.style.display = 'block';
|
||||||
|
stopWatcherStatusPolling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user