No sessions yet.
';
- return;
- }
- els.sessionList.innerHTML = items.map((session) => `
-
- `).join('');
-}
-
-function appendTool(text) {
- const div = document.createElement('div');
- div.className = 'tool-entry';
- div.textContent = text;
- els.liveTools.prepend(div);
-}
-
-function appendError(text) {
- const div = document.createElement('div');
- div.className = 'error-entry';
- div.textContent = text;
- els.liveErrors.prepend(div);
-}
-
-function renderTimeline() {
- const activity = state.currentSession?.activity || [];
- if (!activity.length) {
- els.timeline.innerHTML = 'Choose a session to inspect prompts and stream history.
';
- return;
- }
- els.timeline.innerHTML = activity.slice().reverse().map((entry) => {
- let body = '';
- if (entry.type === 'prompt') body = entry.prompt;
- if (entry.type === 'result') body = entry.content;
- if (entry.type === 'error') body = entry.error;
- if (entry.type === 'event') {
- const event = entry.event || {};
- body = [event.type, event.name, event.content, event.input, event.output].filter(Boolean).join('\n');
- }
- return `
-
-
- ${escapeHTML(entry.type)}
- ${formatTime(entry.timestamp)}
-
- ${escapeHTML(body)}
-
- `;
- }).join('');
-}
-
-function resetLivePanels() {
- els.liveThinking.textContent = '';
- els.liveOutput.textContent = '';
- els.liveTools.innerHTML = '';
- els.liveErrors.innerHTML = '';
-}
-
-function renderSessionDetail() {
- const session = state.currentSession;
- if (!session) {
- els.sessionTitle.textContent = 'Select a session';
- els.sessionMeta.textContent = 'Active and historical session output appears here.';
- els.agentSelect.value = '';
- renderTimeline();
- resetLivePanels();
- return;
- }
- els.sessionTitle.textContent = session.id;
- els.sessionMeta.textContent = `${session.agent_name || 'claude'} · ${session.status || 'idle'} · last active ${formatTime(session.last_active)}`;
- if ([...els.agentSelect.options].some((opt) => opt.value === session.agent_name)) {
- els.agentSelect.value = session.agent_name;
- }
- renderTimeline();
- rebuildLivePanels(session.activity || []);
-}
-
-function rebuildLivePanels(activity) {
- resetLivePanels();
- for (const entry of activity) {
- if (entry.type === 'event' && entry.event) {
- applyEventToLive(entry.event);
- continue;
- }
- if (entry.type === 'result') {
- els.liveOutput.textContent = entry.content || '';
- continue;
- }
- if (entry.type === 'error') {
- appendError(entry.error || 'Unknown error');
- }
- }
-}
-
-function applyEventToLive(event) {
- switch (event.type) {
- case 'thinking_delta':
- case 'thinking_end':
- els.liveThinking.textContent = [els.liveThinking.textContent, event.content || ''].filter(Boolean).join('\n');
- break;
- case 'tool_start':
- appendTool(`start: ${event.name || 'tool'}`);
- break;
- case 'tool_input':
- appendTool(`input ${event.name || 'tool'}\n${event.input || ''}`);
- break;
- case 'tool_output':
- appendTool(`output ${event.name || 'tool'}\n${event.output || ''}`);
- break;
- case 'tool_end':
- appendTool(`end: ${event.name || 'tool'}`);
- break;
- case 'output_delta':
- case 'output_final':
- els.liveOutput.textContent = [els.liveOutput.textContent, event.content || ''].filter(Boolean).join('');
- break;
- case 'error':
- appendError(event.content || 'Unknown error');
- if ((event.content || '').toLowerCase().includes('permission')) {
- appendError('Permission request failed or was denied. Retry with a different approval mode if needed.');
- }
- break;
- }
-}
-
-function upsertSession(summary) {
- const idx = state.sessions.findIndex((item) => item.id === summary.id);
- if (idx === -1) state.sessions.push(summary);
- else state.sessions[idx] = summary;
- state.sessions.sort((a, b) => new Date(b.last_active) - new Date(a.last_active));
-}
-
-async function loadSession(sessionId) {
- state.selectedSessionId = sessionId;
- const session = await fetchJSON(`/api/sessions/${encodeURIComponent(sessionId)}`);
- state.currentSession = session;
- history.replaceState({}, '', `/sessions/${encodeURIComponent(sessionId)}`);
- renderSessions();
- renderSessionDetail();
-}
-
-async function bootstrap() {
- const [sessionsRes, agentsRes] = await Promise.all([fetchJSON('/api/sessions'), fetchJSON('/api/agents')]);
- state.sessions = sessionsRes.sessions || [];
- state.agents = agentsRes.agents || [];
- if (!state.agents.length) state.agents = ['claude', 'codex'];
- els.agentSelect.innerHTML = state.agents.map((agent) => `No sessions yet.
';
- return;
- }
- els.sessionList.innerHTML = items.map((session) => `
-
- `).join('');
-}
-
-function appendTool(text) {
- const div = document.createElement('div');
- div.className = 'tool-entry';
- div.textContent = text;
- els.liveTools.prepend(div);
-}
-
-function appendError(text) {
- const div = document.createElement('div');
- div.className = 'error-entry';
- div.textContent = text;
- els.liveErrors.prepend(div);
-}
-
-function renderTimeline() {
- const activity = state.currentSession?.activity || [];
- if (!activity.length) {
- els.timeline.innerHTML = 'Choose a session to inspect prompts and stream history.
';
- return;
- }
- els.timeline.innerHTML = activity.slice().reverse().map((entry) => {
- let body = '';
- if (entry.type === 'prompt') body = entry.prompt;
- if (entry.type === 'result') body = entry.content;
- if (entry.type === 'error') body = entry.error;
- if (entry.type === 'event') {
- const event = entry.event || {};
- body = [event.type, event.name, event.content, event.input, event.output].filter(Boolean).join('\n');
- }
- return `
-
-
- ${escapeHTML(entry.type)}
- ${formatTime(entry.timestamp)}
-
- ${escapeHTML(body)}
-
- `;
- }).join('');
-}
-
-function resetLivePanels() {
- els.liveThinking.textContent = '';
- els.liveOutput.textContent = '';
- els.liveTools.innerHTML = '';
- els.liveErrors.innerHTML = '';
-}
-
-function renderSessionDetail() {
- const session = state.currentSession;
- if (!session) {
- els.sessionTitle.textContent = 'Select a session';
- els.sessionMeta.textContent = 'Active and historical session output appears here.';
- els.agentSelect.value = '';
- renderTimeline();
- resetLivePanels();
- return;
- }
- els.sessionTitle.textContent = session.id;
- els.sessionMeta.textContent = `${session.agent_name || 'claude'} · ${session.status || 'idle'} · last active ${formatTime(session.last_active)}`;
- if ([...els.agentSelect.options].some((opt) => opt.value === session.agent_name)) {
- els.agentSelect.value = session.agent_name;
- }
- renderTimeline();
- rebuildLivePanels(session.activity || []);
-}
-
-function rebuildLivePanels(activity) {
- resetLivePanels();
- for (const entry of activity) {
- if (entry.type === 'event' && entry.event) {
- applyEventToLive(entry.event);
- continue;
- }
- if (entry.type === 'result') {
- els.liveOutput.textContent = entry.content || '';
- continue;
- }
- if (entry.type === 'error') {
- appendError(entry.error || 'Unknown error');
- }
- }
-}
-
-function applyEventToLive(event) {
- switch (event.type) {
- case 'thinking_delta':
- case 'thinking_end':
- els.liveThinking.textContent = [els.liveThinking.textContent, event.content || ''].filter(Boolean).join('\n');
- break;
- case 'tool_start':
- appendTool(`start: ${event.name || 'tool'}`);
- break;
- case 'tool_input':
- appendTool(`input ${event.name || 'tool'}\n${event.input || ''}`);
- break;
- case 'tool_output':
- appendTool(`output ${event.name || 'tool'}\n${event.output || ''}`);
- break;
- case 'tool_end':
- appendTool(`end: ${event.name || 'tool'}`);
- break;
- case 'output_delta':
- case 'output_final':
- els.liveOutput.textContent = [els.liveOutput.textContent, event.content || ''].filter(Boolean).join('');
- break;
- case 'error':
- appendError(event.content || 'Unknown error');
- if ((event.content || '').toLowerCase().includes('permission')) {
- appendError('Permission request failed or was denied. Retry with a different approval mode if needed.');
- }
- break;
- }
-}
-
-function upsertSession(summary) {
- const idx = state.sessions.findIndex((item) => item.id === summary.id);
- if (idx === -1) state.sessions.push(summary);
- else state.sessions[idx] = summary;
- state.sessions.sort((a, b) => new Date(b.last_active) - new Date(a.last_active));
-}
-
-async function loadSession(sessionId) {
- state.selectedSessionId = sessionId;
- const session = await fetchJSON(`/api/sessions/${encodeURIComponent(sessionId)}`);
- state.currentSession = session;
- history.replaceState({}, '', `/sessions/${encodeURIComponent(sessionId)}`);
- renderSessions();
- renderSessionDetail();
-}
-
-async function bootstrap() {
- const [sessionsRes, agentsRes] = await Promise.all([fetchJSON('/api/sessions'), fetchJSON('/api/agents')]);
- state.sessions = sessionsRes.sessions || [];
- state.agents = agentsRes.agents || [];
- if (!state.agents.length) state.agents = ['claude', 'codex'];
- els.agentSelect.innerHTML = state.agents.map((agent) => `