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:
uroma
2026-01-22 11:46:31 +00:00
Unverified
parent 9ff98e975b
commit 3067c6bc24
4 changed files with 1031 additions and 127 deletions

View File

@@ -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>