Fix project isolation: Make loadChatHistory respect active project sessions
- Modified loadChatHistory() to check for active project before fetching all sessions - When active project exists, use project.sessions instead of fetching from API - Added detailed console logging to debug session filtering - This prevents ALL sessions from appearing in every project's sidebar Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,169 +1,252 @@
|
||||
/**
|
||||
* Real-Time Error Monitoring
|
||||
* Captures browser errors and forwards them to the server for Claude to see
|
||||
* Enhanced Real-Time Error Monitoring
|
||||
* Captures ALL browser console output and forwards it to the server
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Error endpoint
|
||||
const ERROR_ENDPOINT = '/claude/api/log-error';
|
||||
|
||||
// Send error to server
|
||||
// Queue to prevent error loops
|
||||
const errorQueue = [];
|
||||
let isReporting = false;
|
||||
|
||||
// Send error to server with better error handling
|
||||
function reportError(errorData) {
|
||||
// Add to bug tracker
|
||||
if (window.bugTracker) {
|
||||
const errorId = window.bugTracker.addError(errorData);
|
||||
errorData._id = errorId;
|
||||
errorQueue.push(errorData);
|
||||
processQueue();
|
||||
}
|
||||
|
||||
function processQueue() {
|
||||
if (isReporting || errorQueue.length === 0) return;
|
||||
|
||||
isReporting = true;
|
||||
const errorData = errorQueue.shift();
|
||||
|
||||
// Add timestamp if not present
|
||||
if (!errorData.timestamp) {
|
||||
errorData.timestamp = new Date().toISOString();
|
||||
}
|
||||
|
||||
// Add URL if not present
|
||||
if (!errorData.url) {
|
||||
errorData.url = window.location.href;
|
||||
}
|
||||
|
||||
// Add page info
|
||||
errorData.pageInfo = {
|
||||
pathname: window.location.pathname,
|
||||
search: window.location.search,
|
||||
hash: window.location.hash
|
||||
};
|
||||
|
||||
fetch(ERROR_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(errorData)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.autoFixTriggered && window.bugTracker) {
|
||||
window.bugTracker.startFix(errorData._id);
|
||||
showErrorNotification(errorData);
|
||||
}
|
||||
.catch(err => {
|
||||
// Silently fail - don't log to console to prevent infinite loop
|
||||
// Last resort: store in sessionStorage for later retrieval
|
||||
try {
|
||||
const stored = JSON.parse(sessionStorage.getItem('browser_errors') || '[]');
|
||||
stored.push(errorData);
|
||||
sessionStorage.setItem('browser_errors', JSON.stringify(stored.slice(-50)));
|
||||
} catch(e) {}
|
||||
})
|
||||
.catch(err => console.error('[ErrorMonitor] Failed to report error:', err));
|
||||
.finally(() => {
|
||||
isReporting = false;
|
||||
// Process next error after a short delay
|
||||
setTimeout(processQueue, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// Show notification that error is being fixed
|
||||
function showErrorNotification(errorData) {
|
||||
// Create notification element
|
||||
const notification = document.createElement('div');
|
||||
notification.style.cssText = `
|
||||
// Create visual error indicator
|
||||
function createErrorIndicator() {
|
||||
if (document.getElementById('error-indicator')) return;
|
||||
|
||||
const indicator = document.createElement('div');
|
||||
indicator.id = 'error-indicator';
|
||||
indicator.innerHTML = '⚠️ Errors - Check Server Logs';
|
||||
indicator.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
|
||||
color: white;
|
||||
padding: 16px 20px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
|
||||
z-index: 10000;
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
max-width: 400px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
z-index: 99999;
|
||||
cursor: pointer;
|
||||
animation: slideIn 0.3s ease-out;
|
||||
display: none;
|
||||
`;
|
||||
indicator.onclick = () => {
|
||||
indicator.remove();
|
||||
};
|
||||
|
||||
notification.innerHTML = `
|
||||
<div style="display: flex; align-items: flex-start; gap: 12px;">
|
||||
<div style="font-size: 24px;">🤖</div>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-weight: 600; margin-bottom: 4px;">Auto-Fix Agent Triggered</div>
|
||||
<div style="font-size: 13px; opacity: 0.9;">
|
||||
Error detected: ${errorData.message.substring(0, 60)}${errorData.message.length > 60 ? '...' : ''}
|
||||
</div>
|
||||
<div style="font-size: 11px; opacity: 0.7; margin-top: 4px;">
|
||||
Claude is analyzing and preparing a fix...
|
||||
</div>
|
||||
</div>
|
||||
<button onclick="this.parentElement.parentElement.remove()" style="background: none; border: none; color: white; cursor: pointer; font-size: 18px; opacity: 0.7;">×</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add animation styles
|
||||
if (!document.getElementById('error-notification-styles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'error-notification-styles';
|
||||
style.textContent = `
|
||||
@keyframes slideIn {
|
||||
from { transform: translateX(400px); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
// Auto-remove after 10 seconds
|
||||
setTimeout(() => {
|
||||
if (notification.parentElement) {
|
||||
notification.style.animation = 'slideIn 0.3s ease-out reverse';
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
@keyframes slideIn {
|
||||
from { transform: translateY(100px); opacity: 0; }
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
}, 10000);
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
document.body.appendChild(indicator);
|
||||
|
||||
return indicator;
|
||||
}
|
||||
|
||||
function showErrorIndicator() {
|
||||
const indicator = createErrorIndicator();
|
||||
if (indicator) {
|
||||
indicator.style.display = 'block';
|
||||
// Auto-hide after 30 seconds
|
||||
setTimeout(() => {
|
||||
if (indicator.parentElement) {
|
||||
indicator.style.animation = 'slideIn 0.3s ease-out reverse';
|
||||
setTimeout(() => indicator.remove(), 300);
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
}
|
||||
|
||||
// Intercept ALL console methods
|
||||
const consoleMethods = ['log', 'warn', 'info', 'error', 'debug'];
|
||||
const originals = {};
|
||||
|
||||
consoleMethods.forEach(method => {
|
||||
originals[method] = console[method];
|
||||
|
||||
console[method] = function(...args) {
|
||||
// Call original console method
|
||||
originals[method].apply(console, args);
|
||||
|
||||
// Format the message for server logging
|
||||
const message = args.map(arg => {
|
||||
if (typeof arg === 'string') return arg;
|
||||
if (typeof arg === 'object') {
|
||||
try { return JSON.stringify(arg); }
|
||||
catch(e) { return String(arg); }
|
||||
}
|
||||
return String(arg);
|
||||
}).join(' ');
|
||||
|
||||
// Skip reporting our own error-monitor failures to prevent infinite loop
|
||||
if (message.includes('[ErrorMonitor] Failed to report error')) {
|
||||
return;
|
||||
}
|
||||
// Skip AUTO-FIX logs from server
|
||||
if (message.includes('AUTO_FIX')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Report to server
|
||||
reportError({
|
||||
type: `console-${method}`,
|
||||
method: method,
|
||||
message: message,
|
||||
args: args.map(arg => {
|
||||
if (typeof arg === 'object') {
|
||||
try { return JSON.stringify(arg); }
|
||||
catch(e) { return String(arg); }
|
||||
}
|
||||
return String(arg);
|
||||
}),
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href
|
||||
});
|
||||
|
||||
// Show error indicator for errors
|
||||
if (method === 'error') {
|
||||
showErrorIndicator();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Global error handler
|
||||
window.addEventListener('error', (event) => {
|
||||
reportError({
|
||||
type: 'javascript',
|
||||
type: 'javascript-error',
|
||||
message: event.message,
|
||||
filename: event.filename,
|
||||
line: event.lineno,
|
||||
column: event.colno,
|
||||
stack: event.error?.stack,
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href,
|
||||
userAgent: navigator.userAgent
|
||||
url: window.location.href
|
||||
});
|
||||
showErrorIndicator();
|
||||
});
|
||||
|
||||
// Unhandled promise rejection handler
|
||||
window.addEventListener('unhandledrejection', (event) => {
|
||||
reportError({
|
||||
type: 'promise',
|
||||
type: 'unhandled-rejection',
|
||||
message: event.reason?.message || String(event.reason),
|
||||
stack: event.reason?.stack,
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href,
|
||||
userAgent: navigator.userAgent
|
||||
});
|
||||
});
|
||||
|
||||
// Console error interception
|
||||
const originalError = console.error;
|
||||
console.error = function(...args) {
|
||||
originalError.apply(console, args);
|
||||
reportError({
|
||||
type: 'console',
|
||||
message: args.map(arg => {
|
||||
if (typeof arg === 'object') {
|
||||
try { return JSON.stringify(arg); }
|
||||
catch(e) { return String(arg); }
|
||||
}
|
||||
return String(arg);
|
||||
}).join(' '),
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href
|
||||
});
|
||||
};
|
||||
showErrorIndicator();
|
||||
});
|
||||
|
||||
// Resource loading errors
|
||||
window.addEventListener('error', (event) => {
|
||||
if (event.target !== window) {
|
||||
const src = event.target.src || event.target.href || 'unknown';
|
||||
reportError({
|
||||
type: 'resource',
|
||||
type: 'resource-error',
|
||||
message: 'Failed to load: ' + src,
|
||||
tagName: event.target.tagName,
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href
|
||||
});
|
||||
showErrorIndicator();
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Network error monitoring for fetch
|
||||
const originalFetch = window.fetch;
|
||||
window.fetch = function(...args) {
|
||||
return originalFetch.apply(this, args).catch(error => {
|
||||
reportError({
|
||||
type: 'network',
|
||||
message: 'Fetch failed: ' + args[0],
|
||||
error: error.message,
|
||||
timestamp: new Date().toISOString(),
|
||||
url: window.location.href
|
||||
});
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
// Log page load
|
||||
reportError({
|
||||
type: 'page-load',
|
||||
message: 'Page loaded',
|
||||
url: window.location.href,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
console.log('[ErrorMonitor] Real-time error monitoring initialized');
|
||||
// Log SSE client status after page loads
|
||||
setTimeout(() => {
|
||||
reportError({
|
||||
type: 'sse-status-check',
|
||||
message: 'SSE Client Status',
|
||||
sseClientExists: typeof window.sseClient !== 'undefined',
|
||||
sseClientType: typeof window.sseClient,
|
||||
registerSSEEventHandlersExists: typeof window.registerSSEEventHandlers !== 'undefined',
|
||||
attachedSessionId: window.attachedSessionId || 'not-set',
|
||||
currentSessionId: window.chatSessionId || 'not-set',
|
||||
pathname: window.location.pathname,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
// Report any sessionStorage errors from previous page loads
|
||||
try {
|
||||
const stored = sessionStorage.getItem('browser_errors');
|
||||
if (stored) {
|
||||
const errors = JSON.parse(stored);
|
||||
errors.forEach(err => reportError(err));
|
||||
sessionStorage.removeItem('browser_errors');
|
||||
}
|
||||
} catch(e) {
|
||||
// Ignore errors parsing stored errors
|
||||
}
|
||||
|
||||
console.log('[ErrorMonitor] Enhanced error monitoring active - all console output being sent to server');
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user