Fix two critical session issues in Claude Code IDE
Issue 1: Sessions history not showing in left sidebar - Converted loadChatHistoryOnLoad IIFE to named loadChatHistory() function - Added refresh calls in loadSessionMessages() after loading messages - Added guard to skip refresh if showing "Loading session..." state - Sidebar now properly shows all active sessions after attachment Issue 2: New chat session button fails with 'Failed to create session' - Changed startNewChat() to call loadChatHistory() instead of loadChatView() - Prevents triggering URL-based attachment logic that was causing confusion - Sidebar now refreshes correctly without getting stuck in loading state Also updated cache-bust version to force browser reload. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,16 +4,276 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Claude Code IDE</title>
|
||||
<link rel="stylesheet" href="/claude/css/style.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/ide.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/tag-renderer.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/preview-manager.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/chat-enhanced.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/terminal.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/monaco-editor.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/enhanced-chat-input.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/session-picker.css">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/approval-card.css">
|
||||
<meta http-equiv=1769027229"Cache-Control" content="no-cache, no-store, must-revalidate">
|
||||
<meta http-equiv=1769027229"Pragma" content="no-cache">
|
||||
<meta http-equiv=1769027229"Expires" content="0">
|
||||
|
||||
<!-- ============================================================
|
||||
PRELOAD: Extract Session ID from URL BEFORE any other JS runs
|
||||
This fixes race conditions where loadChatView() runs before ide.js
|
||||
============================================================ -->
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
// Extract session ID from route-based URL: /claude/ide/session/{sessionId}
|
||||
// This runs IMMEDIATELY, before any other scripts
|
||||
const pathname = window.location.pathname;
|
||||
const sessionMatch = pathname.match(/\/claude\/ide\/session\/([^\/]+)$/);
|
||||
|
||||
if (sessionMatch && sessionMatch[1]) {
|
||||
window.PRELOAD_SESSION_ID = sessionMatch[1];
|
||||
console.log('[PRELOAD] Session ID extracted from URL:', window.PRELOAD_SESSION_ID);
|
||||
console.log('[PRELOAD] Full URL:', window.location.href);
|
||||
if (window.traceExecution) {
|
||||
window.traceExecution('PRELOAD', 'Session ID extracted', { sessionId: sessionMatch[1], url: window.location.href });
|
||||
}
|
||||
} else {
|
||||
console.log('[PRELOAD] No session ID in URL pathname');
|
||||
if (window.traceExecution) {
|
||||
window.traceExecution('PRELOAD', 'No session ID in URL', { pathname: window.location.pathname });
|
||||
}
|
||||
}
|
||||
|
||||
// Also check for legacy query parameter
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const querySessionId = urlParams.get('session');
|
||||
if (querySessionId && !window.PRELOAD_SESSION_ID) {
|
||||
window.PRELOAD_SESSION_ID = querySessionId;
|
||||
console.log('[PRELOAD] Session ID from query param:', window.PRELOAD_SESSION_ID);
|
||||
if (window.traceExecution) {
|
||||
window.traceExecution('PRELOAD', 'Session ID from query param', { sessionId: querySessionId });
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- ============================================================
|
||||
REAL-TIME EXECUTION TRACER - For debugging session attachment
|
||||
============================================================ -->
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
window.EXECUTION_TRACE = [];
|
||||
const MAX_TRACE_ENTRIES = 100;
|
||||
|
||||
function trace(component, event, data) {
|
||||
const timestamp = new Date().toISOString().split('T')[1].slice(0, 12);
|
||||
const entry = {
|
||||
timestamp,
|
||||
component,
|
||||
event,
|
||||
data
|
||||
};
|
||||
|
||||
window.EXECUTION_TRACE.push(entry);
|
||||
|
||||
// Keep only recent entries
|
||||
if (window.EXECUTION_TRACE.length > MAX_TRACE_ENTRIES) {
|
||||
window.EXECUTION_TRACE.shift();
|
||||
}
|
||||
|
||||
// Log to console with color
|
||||
const colors = {
|
||||
'PRELOAD': '#00ff00',
|
||||
'Cache-Bust': '#ff00ff',
|
||||
'ide.js': '#00ffff',
|
||||
'session-picker': '#ffa500',
|
||||
'chat-functions': '#ffff00',
|
||||
'loadChatView': '#ff69b4',
|
||||
'attachToSession': '#00ff00',
|
||||
'switchView': '#87ceeb'
|
||||
};
|
||||
|
||||
const color = colors[component] || '#ffffff';
|
||||
console.log(
|
||||
`%c[${timestamp}] %c${component}%c: ${event}`,
|
||||
'color: #888',
|
||||
`color: ${color}; font-weight: bold`,
|
||||
'color: #ccc',
|
||||
data
|
||||
);
|
||||
|
||||
// Update trace panel if it exists
|
||||
updateTracePanel();
|
||||
}
|
||||
|
||||
function createTracePanel() {
|
||||
const panel = document.createElement('div');
|
||||
panel.id = 'execution-trace-panel';
|
||||
panel.innerHTML = `
|
||||
<div style="position: fixed; top: 10px; right: 10px; z-index: 99999; background: rgba(0,0,0,0.95); border: 2px solid #00ff00; border-radius: 8px; font-family: monospace; font-size: 11px; color: #00ff00; max-width: 400px; max-height: 300px; overflow: hidden;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; padding: 8px; border-bottom: 1px solid #00ff00; cursor: pointer;" onclick="toggleTracePanel()">
|
||||
<strong>🔍 EXECUTION TRACE</strong>
|
||||
<button id="trace-toggle" style="background: transparent; border: 1px solid #00ff00; color: #00ff00; cursor: pointer;">▼</button>
|
||||
</div>
|
||||
<div id="trace-content" style="padding: 8px; max-height: 250px; overflow-y: auto; font-size: 10px; line-height: 1.4;">
|
||||
<div style="color: #888;">Waiting for events...</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(panel);
|
||||
}
|
||||
|
||||
function updateTracePanel() {
|
||||
const content = document.getElementById('trace-content');
|
||||
if (!content) return;
|
||||
|
||||
if (window.EXECUTION_TRACE.length === 0) {
|
||||
content.innerHTML = '<div style="color: #888;">Waiting for events...</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const html = window.EXECUTION_TRACE.map(e => {
|
||||
const colors = {
|
||||
'PRELOAD': '#00ff00',
|
||||
'Cache-Bust': '#ff00ff',
|
||||
'ide.js': '#00ffff',
|
||||
'session-picker': '#ffa500',
|
||||
'chat-functions': '#ffff00',
|
||||
'sse-client': '#ff69b4',
|
||||
'loadChatView': '#ff69b4',
|
||||
'attachToSession': '#00ff00',
|
||||
'switchView': '#87ceeb'
|
||||
};
|
||||
const color = colors[e.component] || '#ffffff';
|
||||
return `<div style="margin-bottom: 2px;">
|
||||
<span style="color: #666;">[${e.timestamp}]</span>
|
||||
<span style="color: ${color}; font-weight: bold;">${e.component}</span>:
|
||||
<span style="color: #ccc;">${e.event}</span>
|
||||
${e.data ? `<span style="color: #666;">${JSON.stringify(e.data)}</span>` : ''}
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
content.innerHTML = html;
|
||||
content.scrollTop = content.scrollHeight;
|
||||
}
|
||||
|
||||
function toggleTracePanel() {
|
||||
const content = document.getElementById('trace-content');
|
||||
const toggle = document.getElementById('trace-toggle');
|
||||
if (content && toggle) {
|
||||
if (content.style.display === 'none') {
|
||||
content.style.display = 'block';
|
||||
toggle.textContent = '▼';
|
||||
} else {
|
||||
content.style.display = 'none';
|
||||
toggle.textContent = '▶';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize on DOM ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', createTracePanel);
|
||||
} else {
|
||||
createTracePanel();
|
||||
}
|
||||
|
||||
// Auto-upload trace every 10 seconds
|
||||
setInterval(() => {
|
||||
if (window.EXECUTION_TRACE.length > 0) {
|
||||
uploadTrace();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
// Function to upload trace to server
|
||||
async function uploadTrace() {
|
||||
try {
|
||||
const sessionId = window.PRELOAD_SESSION_ID || window.attachedSessionId || 'unknown';
|
||||
const response = await fetch('/claude/api/telemetry/trace', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
sessionId: sessionId,
|
||||
trace: window.EXECUTION_TRACE
|
||||
})
|
||||
});
|
||||
if (response.ok) {
|
||||
console.log('[TraceTelemetry] Trace uploaded successfully');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[TraceTelemetry] Failed to upload trace:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Export trace function and upload globally
|
||||
window.traceExecution = trace;
|
||||
window.uploadTrace = uploadTrace;
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- Cache-Busting Script - MUST run first -->
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
const EXPECTED_JS_VERSION = '1769082354552'; // Cache bust for sidebar refresh fix
|
||||
const CACHE_BUST_KEY = '_claude_cache_bust';
|
||||
|
||||
// Check if we need to force reload
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const forceReload = urlParams.get('_force') === 'true';
|
||||
|
||||
// Check if we just reloaded
|
||||
if (sessionStorage.getItem(CACHE_BUST_KEY)) {
|
||||
sessionStorage.removeItem(CACHE_BUST_KEY);
|
||||
console.log('[Cache-Bust] Fresh load confirmed');
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear all caches and reload
|
||||
async function forceFreshLoad() {
|
||||
console.log('[Cache-Bust] Forcing fresh load...');
|
||||
|
||||
// Clear caches API
|
||||
if ('caches' in window) {
|
||||
const cacheNames = await caches.keys();
|
||||
await Promise.all(cacheNames.map(name => caches.delete(name)));
|
||||
console.log('[Cache-Bust] Cleared', cacheNames.length, 'caches');
|
||||
}
|
||||
|
||||
// Unregister service workers
|
||||
if ('serviceWorker' in navigator) {
|
||||
const regs = await navigator.serviceWorker.getRegistrations();
|
||||
await Promise.all(regs.map(r => r.unregister()));
|
||||
console.log('[Cache-Bust] Unregistered', regs.length, 'service workers');
|
||||
}
|
||||
|
||||
// Mark that we're reloading
|
||||
sessionStorage.setItem(CACHE_BUST_KEY, 'true');
|
||||
|
||||
// Reload with cache busting
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('_t', Date.now().toString());
|
||||
url.searchParams.set('_v', EXPECTED_JS_VERSION);
|
||||
window.location.href = url.toString();
|
||||
}
|
||||
|
||||
// Detect if this is a stale cached page
|
||||
if (!forceReload) {
|
||||
// Check if page was loaded more than 5 minutes ago
|
||||
const loadTime = performance.timing.responseStart;
|
||||
const age = Date.now() - loadTime;
|
||||
|
||||
if (age > 300000) { // 5 minutes
|
||||
console.warn('[Cache-Bust] Page is stale, forcing reload...');
|
||||
forceFreshLoad();
|
||||
return;
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="/claude/css/style.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/ide.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/tag-renderer.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/preview-manager.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/chat-enhanced.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/terminal.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/monaco-editor.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/enhanced-chat-input.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/session-picker.css?v=1769027229">
|
||||
<link rel="stylesheet" href="/claude/claude-ide/components/approval-card.css?v=1769027229">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
|
||||
|
||||
<!-- Monaco Editor (VS Code Editor) - AMD Loader -->
|
||||
@@ -345,20 +605,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/claude/claude-ide/error-monitor.js"></script>
|
||||
<script src="/claude/claude-ide/semantic-validator.js"></script>
|
||||
<script src="/claude/claude-ide/components/approval-card.js"></script>
|
||||
<script src="/claude/claude-ide/command-tracker.js"></script>
|
||||
<script src="/claude/claude-ide/bug-tracker.js"></script>
|
||||
<script src="/claude/claude-ide/ide.js?v=2"></script>
|
||||
<script src="/claude/claude-ide/chat-functions.js"></script>
|
||||
<script src="/claude/claude-ide/tag-renderer.js"></script>
|
||||
<script src="/claude/claude-ide/preview-manager.js"></script>
|
||||
<script src="/claude/claude-ide/chat-enhanced.js"></script>
|
||||
<script src="/claude/claude-ide/terminal.js"></script>
|
||||
<script src="/claude/claude-ide/components/monaco-editor.js"></script>
|
||||
<script src="/claude/claude-ide/components/enhanced-chat-input.js"></script>
|
||||
<script src="/claude/claude-ide/components/session-picker.js"></script>
|
||||
<script src="/claude/claude-ide/error-monitor.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/semantic-validator.js?v1769082165881"></script>
|
||||
<!-- ============================================================
|
||||
HYBRID APPROACH: SSE Client for real-time session events
|
||||
============================================================ -->
|
||||
<script src="/claude/claude-ide/sse-client.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/components/approval-card.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/command-tracker.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/bug-tracker.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/ide.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/chat-functions.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/tag-renderer.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/preview-manager.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/chat-enhanced.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/terminal.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/components/monaco-editor.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/components/enhanced-chat-input.js?v1769082165881"></script>
|
||||
<script src="/claude/claude-ide/components/session-picker.js?v1769082165881"></script>
|
||||
|
||||
<!-- Debug Panel Toggle Script -->
|
||||
<script>
|
||||
@@ -465,5 +729,42 @@
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- SSE Event Handler Registration -->
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Register SSE event handlers after all scripts have loaded
|
||||
function registerSSEHandlers() {
|
||||
// Extract sessionId from URL path: /claude/ide/session/{sessionId}
|
||||
const pathMatch = window.location.pathname.match(/\/claude\/ide\/session\/([^/]+)$/);
|
||||
|
||||
if (pathMatch && pathMatch[1]) {
|
||||
const sessionId = decodeURIComponent(pathMatch[1]);
|
||||
|
||||
// Check if SSE client and handler function are available
|
||||
if (typeof window.sseClient === 'object' && typeof registerSSEEventHandlers === 'function') {
|
||||
console.log('[HTML-SSE] Registering SSE handlers for session:', sessionId);
|
||||
registerSSEEventHandlers(sessionId);
|
||||
} else {
|
||||
console.error('[HTML-SSE] SSE client or registerSSEEventHandlers not available', {
|
||||
sseClient: typeof window.sseClient,
|
||||
registerSSEEventHandlers: typeof registerSSEEventHandlers
|
||||
});
|
||||
// Retry after a delay
|
||||
setTimeout(registerSSEHandlers, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', registerSSEHandlers);
|
||||
} else {
|
||||
registerSSEHandlers();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user