feat: AI auto-fix bug tracker with real-time error monitoring
- Real-time error monitoring system with WebSocket - Auto-fix agent that triggers on browser errors - Bug tracker dashboard with floating button (🐛) - Live activity stream showing AI thought process - Fixed 4 JavaScript errors (SyntaxError, TypeError) - Fixed SessionPicker API endpoint error - Enhanced chat input with Monaco editor - Session picker component for project management Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,11 @@ async function loadChatView() {
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
console.log('[loadChatView] Sessions data received:', data);
|
||||
console.log('[loadChatView] Raw sessions data:', {
|
||||
activeCount: (data.active || []).length,
|
||||
historicalCount: (data.historical || []).length,
|
||||
activeIds: (data.active || []).map(s => ({ id: s.id, status: s.status }))
|
||||
});
|
||||
|
||||
const sessionsListEl = document.getElementById('chat-history-list');
|
||||
|
||||
@@ -72,12 +76,13 @@ async function loadChatView() {
|
||||
// ONLY show active sessions - no historical sessions in chat view
|
||||
// Historical sessions are read-only and can't receive new messages
|
||||
let activeSessions = (data.active || []).filter(s => s.status === 'running');
|
||||
console.log('[loadChatView] Running sessions after status filter:', activeSessions.length);
|
||||
|
||||
// Filter by current project if in project context
|
||||
const currentProjectDir = window.currentProjectDir;
|
||||
|
||||
if (currentProjectDir) {
|
||||
console.log('[loadChatView] Filtering sessions for project path:', currentProjectDir);
|
||||
console.log('[loadChatView] Current project dir:', currentProjectDir);
|
||||
|
||||
// Filter sessions that belong to this project
|
||||
activeSessions = activeSessions.filter(session => {
|
||||
@@ -300,8 +305,10 @@ async function startNewChat() {
|
||||
// Subscribe to session via WebSocket
|
||||
subscribeToSession(data.session.id);
|
||||
|
||||
// Reload sessions list
|
||||
loadChatView();
|
||||
// Give backend time to persist session, then refresh sidebar
|
||||
// This ensures the new session appears in the list
|
||||
await new Promise(resolve => setTimeout(resolve, 150));
|
||||
await loadChatView().catch(err => console.error('[startNewChat] Background refresh failed:', err));
|
||||
|
||||
// Hide the creation success message after a short delay
|
||||
setTimeout(() => {
|
||||
@@ -363,6 +370,26 @@ function subscribeToSession(sessionId) {
|
||||
sessionId: sessionId
|
||||
}));
|
||||
console.log('Subscribed to session:', sessionId);
|
||||
} else if (window.ws && window.ws.readyState === WebSocket.CONNECTING) {
|
||||
// Wait for connection to open, then subscribe
|
||||
console.log('[subscribeToSession] WebSocket connecting, will subscribe when ready...');
|
||||
const onOpen = () => {
|
||||
window.ws.send(JSON.stringify({
|
||||
type: 'subscribe',
|
||||
sessionId: sessionId
|
||||
}));
|
||||
console.log('[subscribeToSession] Subscribed after connection open:', sessionId);
|
||||
window.ws.removeEventListener('open', onOpen);
|
||||
};
|
||||
window.ws.addEventListener('open', onOpen);
|
||||
} else {
|
||||
// WebSocket not connected - try to reconnect
|
||||
console.warn('[subscribeToSession] WebSocket not connected, attempting to connect...');
|
||||
if (typeof connectWebSocket === 'function') {
|
||||
connectWebSocket();
|
||||
// Retry subscription after connection
|
||||
setTimeout(() => subscribeToSession(sessionId), 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,9 +530,29 @@ async function sendChatMessage() {
|
||||
|
||||
if (!message) return;
|
||||
|
||||
// Auto-create session if none exists (OpenCode/CodeNomad hybrid approach)
|
||||
if (!attachedSessionId) {
|
||||
appendSystemMessage('Please start or attach to a session first.');
|
||||
return;
|
||||
console.log('[sendChatMessage] No session attached, auto-creating...');
|
||||
appendSystemMessage('Creating new session...');
|
||||
|
||||
try {
|
||||
await startNewChat();
|
||||
|
||||
// After session creation, wait a moment for attachment
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
|
||||
// Verify session was created and attached
|
||||
if (!attachedSessionId) {
|
||||
appendSystemMessage('❌ Failed to create session. Please try again.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[sendChatMessage] Session auto-created:', attachedSessionId);
|
||||
} catch (error) {
|
||||
console.error('[sendChatMessage] Auto-create session failed:', error);
|
||||
appendSystemMessage('❌ Failed to create session: ' + error.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide mode suggestion banner
|
||||
@@ -605,7 +652,24 @@ async function sendChatMessage() {
|
||||
console.log('Sending with metadata:', payload.metadata);
|
||||
}
|
||||
|
||||
window.ws.send(JSON.stringify(payload));
|
||||
// Debug logging before sending
|
||||
console.log('[DEBUG] About to send command payload:', {
|
||||
type: payload.type,
|
||||
sessionId: payload.sessionId,
|
||||
commandLength: payload.command?.length,
|
||||
wsReady: window.wsReady,
|
||||
wsState: window.ws?.readyState,
|
||||
queueLength: window.messageQueue?.length || 0
|
||||
});
|
||||
|
||||
// Use message queue to prevent race conditions
|
||||
if (typeof queueMessage === 'function') {
|
||||
queueMessage(payload);
|
||||
console.log('[DEBUG] Message queued, queue length now:', window.messageQueue?.length);
|
||||
} else {
|
||||
window.ws.send(JSON.stringify(payload));
|
||||
console.log('[DEBUG] Sent directly via WebSocket (no queue function)');
|
||||
}
|
||||
console.log('Sent command via WebSocket:', message.substring(0, 50));
|
||||
} catch (error) {
|
||||
console.error('Error sending message:', error);
|
||||
@@ -624,12 +688,12 @@ function setGeneratingState(generating) {
|
||||
|
||||
if (generating) {
|
||||
// Show stop button, hide send button
|
||||
sendButton.classList.add('hidden');
|
||||
stopButton.classList.remove('hidden');
|
||||
if (sendButton) sendButton.classList.add('hidden');
|
||||
if (stopButton) stopButton.classList.remove('hidden');
|
||||
} else {
|
||||
// Show send button, hide stop button
|
||||
sendButton.classList.remove('hidden');
|
||||
stopButton.classList.add('hidden');
|
||||
if (sendButton) sendButton.classList.remove('hidden');
|
||||
if (stopButton) stopButton.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1066,10 +1130,16 @@ function clearInput() {
|
||||
const wrapper = document.getElementById('chat-input-wrapper');
|
||||
const charCountBadge = document.getElementById('char-count-badge');
|
||||
|
||||
input.value = '';
|
||||
input.style.height = 'auto';
|
||||
wrapper.classList.remove('typing');
|
||||
charCountBadge.textContent = '0 chars';
|
||||
if (input) {
|
||||
input.value = '';
|
||||
input.style.height = 'auto';
|
||||
}
|
||||
if (wrapper) {
|
||||
wrapper.classList.remove('typing');
|
||||
}
|
||||
if (charCountBadge) {
|
||||
charCountBadge.textContent = '0 chars';
|
||||
}
|
||||
}
|
||||
|
||||
// Update Token Usage
|
||||
|
||||
Reference in New Issue
Block a user