mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 17:55:26 -04:00
Add Cookbook crash report copy action
This commit is contained in:
@@ -33,6 +33,74 @@ function _taskBadge(task) {
|
|||||||
return { text: _statusLabel(task.status, task.type), cls: 'cookbook-task-' + task.status };
|
return { text: _statusLabel(task.status, task.type), cls: 'cookbook-task-' + task.status };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _shouldOfferCrashReport(task) {
|
||||||
|
if (!task) return false;
|
||||||
|
if (task._unreachable && task.type === 'serve') return true;
|
||||||
|
return ['error', 'crashed', 'failed'].includes(task.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _redactCrashReportText(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
return String(text)
|
||||||
|
.replace(/\b(Bearer\s+)[A-Za-z0-9._~+/=-]{12,}/gi, '$1[redacted]')
|
||||||
|
.replace(/\b(hf_[A-Za-z0-9]{16,})\b/g, '[redacted-hf-token]')
|
||||||
|
.replace(/\b(sk-[A-Za-z0-9_-]{16,})\b/g, '[redacted-api-key]')
|
||||||
|
.replace(/\b(xox[baprs]-[A-Za-z0-9-]{16,})\b/g, '[redacted-slack-token]')
|
||||||
|
.replace(/\b(AIza[0-9A-Za-z_-]{20,})\b/g, '[redacted-google-key]')
|
||||||
|
.replace(/\b((?:HF_TOKEN|HUGGING_FACE_HUB_TOKEN|OPENAI_API_KEY|ANTHROPIC_API_KEY|BRAVE_API_KEY|TAVILY_API_KEY|SERPER_API_KEY|GOOGLE_API_KEY|API_KEY|TOKEN|PASSWORD)\s*=\s*)(['"]?)[^\s'"\\]+/gi, '$1$2[redacted]')
|
||||||
|
.replace(/\b(--(?:api-key|token|hf-token|password)\s+)([^\s]+)/gi, '$1[redacted]');
|
||||||
|
}
|
||||||
|
|
||||||
|
function _lastLines(text, count = 160) {
|
||||||
|
const clean = _redactCrashReportText(text || '').trimEnd();
|
||||||
|
if (!clean) return '(no captured output)';
|
||||||
|
return clean.split('\n').slice(-count).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function _codeFence(text) {
|
||||||
|
return String(text || '').replace(/```/g, '` ` `');
|
||||||
|
}
|
||||||
|
|
||||||
|
function _taskHostLabel(task) {
|
||||||
|
if (!task?.remoteHost) return 'local';
|
||||||
|
return task.remoteHost + (task.sshPort ? `:${task.sshPort}` : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function _taskPort(task) {
|
||||||
|
const cmd = task?.payload?._cmd || '';
|
||||||
|
const match = cmd.match(/--port\s+(\d+)/);
|
||||||
|
return match ? match[1] : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function _buildCrashReport(task, outputText) {
|
||||||
|
const capturedOutput = outputText || task?.output || '';
|
||||||
|
const cmd = _redactCrashReportText(task?.payload?._cmd || '');
|
||||||
|
const diag = _diagnose(capturedOutput);
|
||||||
|
const started = task?.ts ? new Date(task.ts).toISOString() : '';
|
||||||
|
const report = [
|
||||||
|
'## Odysseus Cookbook crash report',
|
||||||
|
'',
|
||||||
|
'Please review this report for secrets before posting it publicly.',
|
||||||
|
'',
|
||||||
|
'### Task',
|
||||||
|
`- ID: \`${task?.sessionId || task?.id || 'unknown'}\``,
|
||||||
|
`- Type: \`${task?.type || 'unknown'}\``,
|
||||||
|
`- Status: \`${task?._unreachable ? 'unreachable' : (task?.status || 'unknown')}\``,
|
||||||
|
`- Model/repo: \`${task?.payload?.repo_id || task?.name || 'unknown'}\``,
|
||||||
|
`- Host: \`${_taskHostLabel(task)}\``,
|
||||||
|
];
|
||||||
|
if (task?.platform) report.push(`- Platform: \`${task.platform}\``);
|
||||||
|
if (started) report.push(`- Started: \`${started}\``);
|
||||||
|
const port = _taskPort(task);
|
||||||
|
if (port) report.push(`- Port: \`${port}\``);
|
||||||
|
if (diag?.message) report.push(`- Diagnosis: ${diag.message}`);
|
||||||
|
if (cmd) {
|
||||||
|
report.push('', '### Command', '```bash', _codeFence(cmd), '```');
|
||||||
|
}
|
||||||
|
report.push('', '### Last captured output', '```text', _codeFence(_lastLines(capturedOutput)), '```');
|
||||||
|
return report.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
// Shared state/functions injected by init()
|
// Shared state/functions injected by init()
|
||||||
let _envState;
|
let _envState;
|
||||||
let _sshCmd;
|
let _sshCmd;
|
||||||
@@ -1660,6 +1728,13 @@ export function _renderRunningTab() {
|
|||||||
_copyText(tmuxAttach);
|
_copyText(tmuxAttach);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
if (_shouldOfferCrashReport(task)) {
|
||||||
|
items.push({ label: 'Copy crash report', action: 'copy-crash-report', custom: () => {
|
||||||
|
const out = (el.querySelector('.cookbook-output-pre')?.textContent || task.output || '');
|
||||||
|
_copyText(_buildCrashReport(task, out));
|
||||||
|
uiModule.showToast('Copied crash report');
|
||||||
|
}});
|
||||||
|
}
|
||||||
// Copy the last 50 lines of the task's output/log.
|
// Copy the last 50 lines of the task's output/log.
|
||||||
items.push({ label: 'Copy last 50 lines', action: 'copy-log', custom: () => {
|
items.push({ label: 'Copy last 50 lines', action: 'copy-log', custom: () => {
|
||||||
const out = (el.querySelector('.cookbook-output-pre')?.textContent || task.output || '');
|
const out = (el.querySelector('.cookbook-output-pre')?.textContent || task.output || '');
|
||||||
@@ -1683,6 +1758,7 @@ export function _renderRunningTab() {
|
|||||||
'register-endpoint': '<circle cx="12" cy="12" r="9"/><path d="M12 8v8M8 12h8"/>',
|
'register-endpoint': '<circle cx="12" cy="12" r="9"/><path d="M12 8v8M8 12h8"/>',
|
||||||
save: '<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><path d="M17 21v-8H7v8M7 3v5h8"/>',
|
save: '<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><path d="M17 21v-8H7v8M7 3v5h8"/>',
|
||||||
'copy-tmux': '<rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>',
|
'copy-tmux': '<rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>',
|
||||||
|
'copy-crash-report': '<path d="M10.3 2.3 1.8 17a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 2.3a2 2 0 0 0-3.4 0z"/><path d="M12 8v5M12 17h.01"/>',
|
||||||
'copy-log': '<rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>',
|
'copy-log': '<rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>',
|
||||||
kill: '<path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>',
|
kill: '<path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>',
|
||||||
cancel: '<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>',
|
cancel: '<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>',
|
||||||
|
|||||||
Reference in New Issue
Block a user