// Simple client-side router const router = { currentRoute: '/', init() { // Handle browser back/forward window.addEventListener('popstate', () => { this.handleRoute(window.location.pathname); }); // Handle initial route this.handleRoute(window.location.pathname); }, navigate(path) { window.history.pushState({}, '', path); this.handleRoute(path); }, async handleRoute(path) { this.currentRoute = path; const container = document.getElementById('page-container'); if (path === '/' || path === '') { await this.renderHome(container); } else if (path.startsWith('/instance/')) { const id = path.split('/')[2]; await this.renderDetail(container, id); } else { container.innerHTML = components.error('Page not found'); } }, async renderHome(container) { container.innerHTML = components.spinner('Loading instances...'); try { const instances = await api.getInstances(); if (instances.length === 0) { container.innerHTML = components.emptyState( 'No running instances. Click "+ New Run" to start one.' ); return; } let html = '
'; for (const instance of instances) { // Use stats from API response const stats = instance.stats || { total_tokens: 0, tool_calls: 0, errors: 0, duration_secs: 0 }; html += components.instancePanel(instance, stats, instance.latest_message); } html += '
'; container.innerHTML = html; // Auto-refresh every 5 seconds setTimeout(() => { if (this.currentRoute === '/') { this.renderHome(container); } }, 5000); } catch (error) { container.innerHTML = components.error(error.message); } }, async renderDetail(container, id) { container.innerHTML = components.spinner('Loading instance details...'); try { const instance = await api.getInstance(id); const logs = await api.getInstanceLogs(id); // Build detail view HTML let html = `

${instance.workspace}

${components.statusBadge(instance.status)}
Tokens
${(instance.stats?.total_tokens || 0).toLocaleString()}
Tool Calls
${instance.stats?.tool_calls || 0}
Errors
${instance.stats?.errors || 0}
Duration
${Math.round((instance.stats?.duration_secs || 0) / 60)}m

Git Status

${components.gitStatus(instance.git_status)}

Project Files

${components.projectFiles(instance.project_files)}

Tool Calls

`; // Render tool calls if (logs && logs.tool_calls && logs.tool_calls.length > 0) { for (const toolCall of logs.tool_calls) { html += components.toolCall(toolCall); } } else { html += '

No tool calls yet

'; } html += `

Chat History

`; // Render messages from logs if (logs && logs.messages && logs.messages.length > 0) { for (const msg of logs.messages) { html += components.chatMessage(msg.content, msg.agent); } } else { html += '

No messages yet

'; } html += `
`; container.innerHTML = html; // Apply syntax highlighting document.querySelectorAll('pre code').forEach((block) => { hljs.highlightElement(block); }); // Auto-refresh every 3 seconds setTimeout(() => { if (this.currentRoute === `/instance/${id}`) { this.renderDetail(container, id); } }, 3000); } catch (error) { container.innerHTML = components.error(error.message); } } };