document.addEventListener('DOMContentLoaded', function () { var state = { items: [], workspaceId: null, loading: false, error: '', openId: null, }; var list = document.getElementById('stream-sessions-list'); var summary = document.getElementById('stream-sessions-summary'); var refreshButton = document.getElementById('stream-sessions-refresh'); var statusFilter = document.getElementById('stream-sessions-status'); var modeFilter = document.getElementById('stream-sessions-mode'); function tKey(key, vars) { if (!window.t) return key; return t(key, vars); } function currentWorkspaceId() { var workspace = window.getCurrentWorkspace ? window.getCurrentWorkspace() : null; return workspace ? workspace.id : null; } function formatJson(value) { if (value === null || value === undefined) return ''; if (typeof value === 'string') return value; return JSON.stringify(value, null, 2); } function formatDateTime(value) { if (!value) return '—'; return new Date(value).toLocaleString(); } function renderEmpty(title, body) { list.innerHTML = '
' + title + '
' + body + '
'; } function render() { summary.textContent = tKey('stream_sessions.summary', { count: state.items.length }); if (state.loading && state.items.length === 0) { renderEmpty(tKey('stream_sessions.loading.title'), tKey('stream_sessions.loading.body')); return; } if (state.error) { renderEmpty(tKey('stream_sessions.error.title'), state.error); return; } if (!state.items.length) { renderEmpty(tKey('stream_sessions.empty.title'), tKey('stream_sessions.empty.body')); return; } list.innerHTML = state.items.map(function(item) { var open = state.openId === item.id; var statusLabel = tKey('stream_sessions.status.' + item.status); return [ '
', '
', '
', '
' + item.id + '
', '
' + tKey('stream_sessions.operation', { operation: item.operation_id }) + '
', '
', ' ' + statusLabel + '', ' ' + item.mode + '', ' ' + item.protocol + '', '
', '
', '
', item.status === 'created' || item.status === 'running' ? ' ' : '', ' ', '
', '
', '
', '
' + tKey('stream_sessions.meta.created') + '
' + formatDateTime(item.created_at) + '
', '
' + tKey('stream_sessions.meta.last_poll') + '
' + formatDateTime(item.last_poll_at) + '
', '
' + tKey('stream_sessions.meta.expires') + '
' + formatDateTime(item.expires_at) + '
', '
' + tKey('stream_sessions.meta.agent') + '
' + (item.agent_id || '—') + '
', '
', open ? '
' + tKey('stream_sessions.cursor') + '
' + formatJson(item.cursor) + '
' : '', '
' ].join(''); }).join(''); list.querySelectorAll('[data-action="toggle"]').forEach(function(button) { button.addEventListener('click', function () { var sessionId = this.getAttribute('data-session-id'); state.openId = state.openId === sessionId ? null : sessionId; if (state.openId) { void loadDetail(sessionId); } else { render(); } }); }); list.querySelectorAll('[data-action="stop"]').forEach(function(button) { button.addEventListener('click', async function () { try { var sessionId = this.getAttribute('data-session-id'); await window.CrankApi.stopStreamSession(state.workspaceId, sessionId); if (window.CrankUi) { window.CrankUi.success(tKey('stream_sessions.toast.stop.body'), tKey('stream_sessions.toast.stop.title')); } await load(); } catch (error) { if (window.CrankUi) { window.CrankUi.error(error.message || tKey('stream_sessions.toast.stop_error.body'), tKey('stream_sessions.toast.stop_error.title')); } } }); }); } async function loadDetail(sessionId) { var detail = await window.CrankApi.getStreamSession(state.workspaceId, sessionId); state.items = state.items.map(function(item) { return item.id === sessionId ? detail : item; }); render(); } async function load() { state.workspaceId = currentWorkspaceId(); if (!state.workspaceId) { state.items = []; state.error = tKey('stream_sessions.error.workspace'); render(); return; } state.loading = true; state.error = ''; render(); try { var response = await window.CrankApi.listStreamSessions(state.workspaceId, { status: statusFilter.value || null, mode: modeFilter.value || null, page: 1, page_size: 50, }); state.items = response.items || []; } catch (error) { state.error = error.message || tKey('stream_sessions.error.load'); } finally { state.loading = false; render(); } } refreshButton.addEventListener('click', load); statusFilter.addEventListener('change', load); modeFilter.addEventListener('change', load); document.addEventListener('workspace:changed', load); void load(); });