community: remove premium protocols and streaming surface
This commit is contained in:
@@ -376,27 +376,6 @@
|
||||
getProtocolCapabilities: function(workspaceId) {
|
||||
return get('/workspaces/' + encodeURIComponent(workspaceId) + '/protocol-capabilities');
|
||||
},
|
||||
listStreamSessions: function(workspaceId, params) {
|
||||
return get('/workspaces/' + encodeURIComponent(workspaceId) + '/stream-sessions' + query(params));
|
||||
},
|
||||
getStreamSession: function(workspaceId, sessionId) {
|
||||
return get('/workspaces/' + encodeURIComponent(workspaceId) + '/stream-sessions/' + encodeURIComponent(sessionId));
|
||||
},
|
||||
stopStreamSession: function(workspaceId, sessionId) {
|
||||
return post('/workspaces/' + encodeURIComponent(workspaceId) + '/stream-sessions/' + encodeURIComponent(sessionId) + '/stop', {});
|
||||
},
|
||||
listAsyncJobs: function(workspaceId, params) {
|
||||
return get('/workspaces/' + encodeURIComponent(workspaceId) + '/async-jobs' + query(params));
|
||||
},
|
||||
getAsyncJob: function(workspaceId, jobId) {
|
||||
return get('/workspaces/' + encodeURIComponent(workspaceId) + '/async-jobs/' + encodeURIComponent(jobId));
|
||||
},
|
||||
cancelAsyncJob: function(workspaceId, jobId) {
|
||||
return post('/workspaces/' + encodeURIComponent(workspaceId) + '/async-jobs/' + encodeURIComponent(jobId) + '/cancel', {});
|
||||
},
|
||||
getAsyncJobResult: function(workspaceId, jobId) {
|
||||
return get('/workspaces/' + encodeURIComponent(workspaceId) + '/async-jobs/' + encodeURIComponent(jobId) + '/result');
|
||||
},
|
||||
getOperationUsage: function(workspaceId, operationId, params) {
|
||||
return get(
|
||||
'/workspaces/' + encodeURIComponent(workspaceId) + '/usage/operations/' + encodeURIComponent(operationId) + query(params)
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var state = {
|
||||
items: [],
|
||||
workspaceId: null,
|
||||
loading: false,
|
||||
error: '',
|
||||
openId: null,
|
||||
};
|
||||
|
||||
var list = document.getElementById('async-jobs-list');
|
||||
var summary = document.getElementById('async-jobs-summary');
|
||||
var refreshButton = document.getElementById('async-jobs-refresh');
|
||||
var statusFilter = document.getElementById('async-jobs-status');
|
||||
|
||||
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 element(tag, className, text) {
|
||||
var node = document.createElement(tag);
|
||||
if (className) node.className = className;
|
||||
if (text !== undefined && text !== null) node.textContent = text;
|
||||
return node;
|
||||
}
|
||||
|
||||
function renderEmpty(title, body) {
|
||||
list.innerHTML = '';
|
||||
var empty = element('div', 'empty-state');
|
||||
empty.appendChild(element('div', 'empty-state-title', title));
|
||||
empty.appendChild(element('div', 'empty-state-text', body));
|
||||
list.appendChild(empty);
|
||||
}
|
||||
|
||||
function appendMetaItem(parent, label, value) {
|
||||
var item = element('div', 'resource-meta-item');
|
||||
item.appendChild(element('div', 'resource-meta-label', label));
|
||||
item.appendChild(element('div', 'resource-meta-value', value));
|
||||
parent.appendChild(item);
|
||||
}
|
||||
|
||||
function appendDetailBlock(parent, title, value, dataResultFor) {
|
||||
var block = element('div', 'resource-detail-block');
|
||||
block.appendChild(element('div', 'resource-detail-title', title));
|
||||
var pre = element('pre', 'resource-detail-pre', value);
|
||||
if (dataResultFor) pre.setAttribute('data-result-for', dataResultFor);
|
||||
block.appendChild(pre);
|
||||
parent.appendChild(block);
|
||||
}
|
||||
|
||||
function renderJobCard(item) {
|
||||
var open = state.openId === item.id;
|
||||
var card = element('div', 'resource-card');
|
||||
card.setAttribute('data-job-id', item.id);
|
||||
|
||||
var header = element('div', 'resource-card-header');
|
||||
var headerMain = element('div');
|
||||
headerMain.appendChild(element('div', 'resource-card-title', item.id));
|
||||
headerMain.appendChild(element('div', 'resource-card-subtitle', tKey('async_jobs.operation', { operation: item.operation_id })));
|
||||
|
||||
var pillRow = element('div', 'resource-pill-row');
|
||||
pillRow.appendChild(
|
||||
element('span', 'resource-status-pill ' + String(item.status || '').toLowerCase(), tKey('async_jobs.status.' + item.status))
|
||||
);
|
||||
headerMain.appendChild(pillRow);
|
||||
header.appendChild(headerMain);
|
||||
|
||||
var actions = element('div', 'resource-card-actions');
|
||||
if (item.status === 'created' || item.status === 'running') {
|
||||
var cancelButton = element('button', 'btn-secondary', tKey('async_jobs.cancel'));
|
||||
cancelButton.setAttribute('data-action', 'cancel');
|
||||
cancelButton.setAttribute('data-job-id', item.id);
|
||||
actions.appendChild(cancelButton);
|
||||
}
|
||||
var toggleButton = element(
|
||||
'button',
|
||||
'btn-secondary',
|
||||
open ? tKey('async_jobs.hide_details') : tKey('async_jobs.show_details')
|
||||
);
|
||||
toggleButton.setAttribute('data-action', 'toggle');
|
||||
toggleButton.setAttribute('data-job-id', item.id);
|
||||
actions.appendChild(toggleButton);
|
||||
header.appendChild(actions);
|
||||
card.appendChild(header);
|
||||
|
||||
var metaGrid = element('div', 'resource-meta-grid');
|
||||
appendMetaItem(metaGrid, tKey('async_jobs.meta.created'), formatDateTime(item.created_at));
|
||||
appendMetaItem(metaGrid, tKey('async_jobs.meta.updated'), formatDateTime(item.updated_at));
|
||||
appendMetaItem(metaGrid, tKey('async_jobs.meta.finished'), formatDateTime(item.finished_at));
|
||||
appendMetaItem(metaGrid, tKey('async_jobs.meta.expires'), formatDateTime(item.expires_at));
|
||||
card.appendChild(metaGrid);
|
||||
|
||||
if (open) {
|
||||
appendDetailBlock(card, tKey('async_jobs.progress'), formatJson(item.progress));
|
||||
appendDetailBlock(card, tKey('async_jobs.error_preview'), formatJson(item.error));
|
||||
if (
|
||||
item.status === 'completed' ||
|
||||
item.status === 'failed' ||
|
||||
item.status === 'cancelled' ||
|
||||
item.status === 'expired'
|
||||
) {
|
||||
appendDetailBlock(card, tKey('async_jobs.result'), tKey('async_jobs.result_loading'), item.id);
|
||||
}
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
function render() {
|
||||
summary.textContent = tKey('async_jobs.summary', { count: state.items.length });
|
||||
|
||||
if (state.loading && state.items.length === 0) {
|
||||
renderEmpty(tKey('async_jobs.loading.title'), tKey('async_jobs.loading.body'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.error) {
|
||||
renderEmpty(tKey('async_jobs.error.title'), state.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.items.length) {
|
||||
renderEmpty(tKey('async_jobs.empty.title'), tKey('async_jobs.empty.body'));
|
||||
return;
|
||||
}
|
||||
|
||||
list.innerHTML = '';
|
||||
state.items.forEach(function(item) {
|
||||
list.appendChild(renderJobCard(item));
|
||||
});
|
||||
|
||||
list.querySelectorAll('[data-action="toggle"]').forEach(function(button) {
|
||||
button.addEventListener('click', function () {
|
||||
var jobId = this.getAttribute('data-job-id');
|
||||
state.openId = state.openId === jobId ? null : jobId;
|
||||
if (state.openId) {
|
||||
void loadDetail(jobId);
|
||||
} else {
|
||||
render();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
list.querySelectorAll('[data-action="cancel"]').forEach(function(button) {
|
||||
button.addEventListener('click', async function () {
|
||||
try {
|
||||
var jobId = this.getAttribute('data-job-id');
|
||||
await window.CrankApi.cancelAsyncJob(state.workspaceId, jobId);
|
||||
if (window.CrankUi) {
|
||||
window.CrankUi.success(tKey('async_jobs.toast.cancel.body'), tKey('async_jobs.toast.cancel.title'));
|
||||
}
|
||||
await load();
|
||||
} catch (error) {
|
||||
if (window.CrankUi) {
|
||||
window.CrankUi.error(error.message || tKey('async_jobs.toast.cancel_error.body'), tKey('async_jobs.toast.cancel_error.title'));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loadResult(jobId) {
|
||||
try {
|
||||
var result = await window.CrankApi.getAsyncJobResult(state.workspaceId, jobId);
|
||||
var node = document.querySelector('[data-result-for="' + jobId + '"]');
|
||||
if (node) node.textContent = formatJson(result);
|
||||
} catch (error) {
|
||||
var failedNode = document.querySelector('[data-result-for="' + jobId + '"]');
|
||||
if (failedNode) failedNode.textContent = error.message || tKey('async_jobs.result_error');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDetail(jobId) {
|
||||
var detail = await window.CrankApi.getAsyncJob(state.workspaceId, jobId);
|
||||
state.items = state.items.map(function(item) {
|
||||
return item.id === jobId ? detail : item;
|
||||
});
|
||||
render();
|
||||
if (detail.status === 'completed' || detail.status === 'failed' || detail.status === 'cancelled' || detail.status === 'expired') {
|
||||
await loadResult(jobId);
|
||||
}
|
||||
}
|
||||
|
||||
async function load() {
|
||||
state.workspaceId = currentWorkspaceId();
|
||||
if (!state.workspaceId) {
|
||||
state.items = [];
|
||||
state.error = tKey('async_jobs.error.workspace');
|
||||
render();
|
||||
return;
|
||||
}
|
||||
|
||||
state.loading = true;
|
||||
state.error = '';
|
||||
render();
|
||||
|
||||
try {
|
||||
var response = await window.CrankApi.listAsyncJobs(state.workspaceId, {
|
||||
status: statusFilter.value || null,
|
||||
page: 1,
|
||||
page_size: 50,
|
||||
});
|
||||
state.items = response.items || [];
|
||||
} catch (error) {
|
||||
state.error = error.message || tKey('async_jobs.error.load');
|
||||
} finally {
|
||||
state.loading = false;
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
refreshButton.addEventListener('click', load);
|
||||
statusFilter.addEventListener('change', load);
|
||||
document.addEventListener('workspace:changed', load);
|
||||
void load();
|
||||
});
|
||||
@@ -9,8 +9,6 @@
|
||||
secrets: '/secrets',
|
||||
logs: '/logs',
|
||||
usage: '/usage',
|
||||
streamSessions: '/stream-sessions',
|
||||
asyncJobs: '/async-jobs',
|
||||
settings: '/settings',
|
||||
workspaceSetup: '/workspace-setup',
|
||||
wizard: '/wizard/'
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
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 element(tag, className, text) {
|
||||
var node = document.createElement(tag);
|
||||
if (className) node.className = className;
|
||||
if (text !== undefined && text !== null) node.textContent = text;
|
||||
return node;
|
||||
}
|
||||
|
||||
function renderEmpty(title, body) {
|
||||
list.innerHTML = '';
|
||||
var empty = element('div', 'empty-state');
|
||||
empty.appendChild(element('div', 'empty-state-title', title));
|
||||
empty.appendChild(element('div', 'empty-state-text', body));
|
||||
list.appendChild(empty);
|
||||
}
|
||||
|
||||
function appendMetaItem(parent, label, value) {
|
||||
var item = element('div', 'resource-meta-item');
|
||||
item.appendChild(element('div', 'resource-meta-label', label));
|
||||
item.appendChild(element('div', 'resource-meta-value', value));
|
||||
parent.appendChild(item);
|
||||
}
|
||||
|
||||
function appendDetailBlock(parent, title, value) {
|
||||
var block = element('div', 'resource-detail-block');
|
||||
block.appendChild(element('div', 'resource-detail-title', title));
|
||||
block.appendChild(element('pre', 'resource-detail-pre', formatJson(value)));
|
||||
parent.appendChild(block);
|
||||
}
|
||||
|
||||
function renderSessionCard(item) {
|
||||
var open = state.openId === item.id;
|
||||
var card = element('div', 'resource-card');
|
||||
card.setAttribute('data-session-id', item.id);
|
||||
|
||||
var header = element('div', 'resource-card-header');
|
||||
var headerMain = element('div');
|
||||
headerMain.appendChild(element('div', 'resource-card-title', item.id));
|
||||
headerMain.appendChild(element('div', 'resource-card-subtitle', tKey('stream_sessions.operation', { operation: item.operation_id })));
|
||||
|
||||
var pillRow = element('div', 'resource-pill-row');
|
||||
var statusPill = element('span', 'resource-status-pill ' + String(item.status || '').toLowerCase(), tKey('stream_sessions.status.' + item.status));
|
||||
pillRow.appendChild(statusPill);
|
||||
pillRow.appendChild(element('span', 'resource-status-pill', item.mode));
|
||||
pillRow.appendChild(element('span', 'resource-status-pill', item.protocol));
|
||||
headerMain.appendChild(pillRow);
|
||||
header.appendChild(headerMain);
|
||||
|
||||
var actions = element('div', 'resource-card-actions');
|
||||
if (item.status === 'created' || item.status === 'running') {
|
||||
var stopButton = element('button', 'btn-secondary', tKey('stream_sessions.stop'));
|
||||
stopButton.setAttribute('data-action', 'stop');
|
||||
stopButton.setAttribute('data-session-id', item.id);
|
||||
actions.appendChild(stopButton);
|
||||
}
|
||||
var toggleButton = element(
|
||||
'button',
|
||||
'btn-secondary',
|
||||
open ? tKey('stream_sessions.hide_details') : tKey('stream_sessions.show_details')
|
||||
);
|
||||
toggleButton.setAttribute('data-action', 'toggle');
|
||||
toggleButton.setAttribute('data-session-id', item.id);
|
||||
actions.appendChild(toggleButton);
|
||||
header.appendChild(actions);
|
||||
card.appendChild(header);
|
||||
|
||||
var metaGrid = element('div', 'resource-meta-grid');
|
||||
appendMetaItem(metaGrid, tKey('stream_sessions.meta.created'), formatDateTime(item.created_at));
|
||||
appendMetaItem(metaGrid, tKey('stream_sessions.meta.last_poll'), formatDateTime(item.last_poll_at));
|
||||
appendMetaItem(metaGrid, tKey('stream_sessions.meta.expires'), formatDateTime(item.expires_at));
|
||||
appendMetaItem(metaGrid, tKey('stream_sessions.meta.agent'), item.agent_id || '—');
|
||||
card.appendChild(metaGrid);
|
||||
|
||||
if (open) {
|
||||
appendDetailBlock(card, tKey('stream_sessions.cursor'), item.cursor);
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
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.forEach(function(item) {
|
||||
list.appendChild(renderSessionCard(item));
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
Reference in New Issue
Block a user