Initial commit

This commit is contained in:
Jordan
2026-04-01 23:16:45 +01:00
commit bc4199aed2
201 changed files with 25612 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
/**
* Session Inspector — right panel with full state rendering
*/
let inspectorEl;
export function initInspector() {
inspectorEl = document.getElementById('inspector');
clearInspector();
}
export function clearInspector() {
if (!inspectorEl) return;
inspectorEl.innerHTML = '<div class="inspector-empty">No session selected</div>';
}
export function updateInspector(session) {
if (!inspectorEl || !session) return;
inspectorEl.innerHTML = '';
// Header
inspectorEl.appendChild(buildSection('Session', `
<div class="inspector-field">
<span class="label">ID</span>
<span class="value truncate" style="max-width:180px" title="${session.session_id}">${session.session_id.substring(0, 16)}...</span>
</div>
<div class="inspector-field">
<span class="label">Status</span>
<span class="badge ${session.status}">${session.status}</span>
</div>
<div class="inspector-field">
<span class="label">Turns</span>
<span class="value">${session.turn_count}</span>
</div>
<div class="inspector-field">
<span class="label">Created</span>
<span class="value">${formatTime(session.created_at)}</span>
</div>
<div class="inspector-field">
<span class="label">Updated</span>
<span class="value">${formatTime(session.updated_at)}</span>
</div>
`));
// Current Task
if (session.current_task) {
const task = session.current_task;
let taskHtml = `
<div class="inspector-field">
<span class="label">Objective</span>
</div>
<div class="text-sm" style="margin-bottom:6px;color:var(--text-primary)">${escapeHtml(task.objective)}</div>
<div class="inspector-field">
<span class="label">Status</span>
<span class="badge ${task.status}">${task.status}</span>
</div>
<div class="inspector-field">
<span class="label">Step</span>
<span class="value">${task.current_step_index + 1} / ${(task.plan || []).length}</span>
</div>
`;
// Facts
if (task.facts_extracted && task.facts_extracted.length > 0) {
taskHtml += '<div class="mt-2"><span class="label text-sm">Facts:</span><ul style="padding-left:16px;margin-top:4px">';
for (const f of task.facts_extracted.slice(-8)) {
taskHtml += `<li class="text-sm">${escapeHtml(f)}</li>`;
}
taskHtml += '</ul></div>';
}
// Constraints
if (task.constraints && task.constraints.length > 0) {
taskHtml += '<div class="mt-2"><span class="label text-sm">Constraints:</span><ul style="padding-left:16px;margin-top:4px">';
for (const c of task.constraints) {
taskHtml += `<li class="text-sm">${escapeHtml(c)}</li>`;
}
taskHtml += '</ul></div>';
}
inspectorEl.appendChild(buildSection('Current Task', taskHtml));
// Plan
if (task.plan && task.plan.length > 0) {
let planHtml = '<div class="timeline">';
for (let i = 0; i < task.plan.length; i++) {
const step = task.plan[i];
const stepStatus = step.status || 'pending';
const isActive = i === task.current_step_index && task.status === 'executing';
const stepClass = isActive ? 'active' : (stepStatus === 'completed' ? 'completed' : stepStatus === 'failed' ? 'failed' : '');
planHtml += `
<div class="timeline-step ${stepClass}">
<div class="timeline-step-header">
<span class="role-badge ${step.agent_role || 'coder'}">${step.agent_role || 'coder'}</span>
<span class="badge ${stepStatus}">${stepStatus}</span>
</div>
<div class="timeline-step-desc">${escapeHtml(step.description)}</div>
${step.tools_used && step.tools_used.length > 0 ? `
<div class="timeline-tools">
${step.tools_used.map(t => `<span class="tool-chip">${escapeHtml(t)}</span>`).join('')}
</div>
` : ''}
${step.result_summary ? `<div class="text-sm text-muted mt-2">${escapeHtml(step.result_summary.substring(0, 200))}</div>` : ''}
</div>
`;
}
planHtml += '</div>';
inspectorEl.appendChild(buildSection('Execution Plan', planHtml));
}
}
// Completed tasks
if (session.completed_tasks && session.completed_tasks.length > 0) {
let html = '<ul style="padding-left:16px">';
for (const t of session.completed_tasks) {
html += `<li class="text-sm mono">${t}</li>`;
}
html += '</ul>';
inspectorEl.appendChild(buildSection(`Completed (${session.completed_tasks.length})`, html));
}
}
function buildSection(title, innerHtml) {
const section = document.createElement('div');
section.className = 'inspector-section';
section.innerHTML = `<div class="inspector-section-title">${title}</div>${innerHtml}`;
return section;
}
function formatTime(isoStr) {
if (!isoStr) return '—';
try {
return new Date(isoStr).toLocaleTimeString('en-US', { hour12: false });
} catch {
return isoStr;
}
}
function escapeHtml(str) {
if (!str) return '';
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}