Merge failure list rendering for any run with failures
All checks were successful
build-and-push / docker (push) Successful in 23s
All checks were successful
build-and-push / docker (push) Successful in 23s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
4036139901
1 changed files with 10 additions and 3 deletions
|
|
@ -1537,10 +1537,17 @@ async function refreshAiPanel() {
|
||||||
let status;
|
let status;
|
||||||
let runs;
|
let runs;
|
||||||
let detail = null;
|
let detail = null;
|
||||||
|
let details = {};
|
||||||
try {
|
try {
|
||||||
[status, runs] = await Promise.all([getJson('/api/ai/status'), getJson('/api/ai/runs')]);
|
[status, runs] = await Promise.all([getJson('/api/ai/status'), getJson('/api/ai/runs')]);
|
||||||
const focus = runs.find((r) => r.status === 'running') || runs[0];
|
const focus = runs.find((r) => r.status === 'running') || runs[0];
|
||||||
if (focus) detail = await getJson(`/api/ai/runs/${focus.id}`);
|
if (focus) detail = await getJson(`/api/ai/runs/${focus.id}`);
|
||||||
|
if (detail) details[detail.id] = detail;
|
||||||
|
// Runs that failed something need their detail too, or the list of failures
|
||||||
|
// has nothing to draw: without this only the newest run ever gets one.
|
||||||
|
for (const r of runs.slice(0, 5)) {
|
||||||
|
if (r.failed > 0 && !details[r.id]) details[r.id] = await getJson(`/api/ai/runs/${r.id}`);
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
aiPoll = setTimeout(refreshAiPanel, 5000);
|
aiPoll = setTimeout(refreshAiPanel, 5000);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1548,7 +1555,7 @@ async function refreshAiPanel() {
|
||||||
if (selectedScope !== 'ai' || !document.getElementById('aiRuns')) return;
|
if (selectedScope !== 'ai' || !document.getElementById('aiRuns')) return;
|
||||||
const running = runs.some((r) => r.status === 'running');
|
const running = runs.some((r) => r.status === 'running');
|
||||||
const changed = aiState.expectChange || (aiState.runs || []).some((r) => r.status === 'running');
|
const changed = aiState.expectChange || (aiState.runs || []).some((r) => r.status === 'running');
|
||||||
aiState = { ...aiState, status, runs, detail };
|
aiState = { ...aiState, status, runs, detail, details };
|
||||||
renderAiLive();
|
renderAiLive();
|
||||||
if (changed && !running) {
|
if (changed && !running) {
|
||||||
aiState.expectChange = false;
|
aiState.expectChange = false;
|
||||||
|
|
@ -1561,7 +1568,7 @@ async function refreshAiPanel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAiLive() {
|
function renderAiLive() {
|
||||||
const { status, runs = [], detail } = aiState;
|
const { status, runs = [], detail, details = {} } = aiState;
|
||||||
if (!status || !document.getElementById('aiRuns')) return;
|
if (!status || !document.getElementById('aiRuns')) return;
|
||||||
const c = status.config;
|
const c = status.config;
|
||||||
document.getElementById('aiSetup').innerHTML = status.problem
|
document.getElementById('aiSetup').innerHTML = status.problem
|
||||||
|
|
@ -1578,7 +1585,7 @@ function renderAiLive() {
|
||||||
start.disabled = Boolean(status.problem) || running;
|
start.disabled = Boolean(status.problem) || running;
|
||||||
start.title = running ? 'A run is going: wait for it, or stop it' : '';
|
start.title = running ? 'A run is going: wait for it, or stop it' : '';
|
||||||
document.getElementById('aiRuns').innerHTML = runs.length
|
document.getElementById('aiRuns').innerHTML = runs.length
|
||||||
? runs.slice(0, 5).map((r) => runHtml(r, detail && detail.id === r.id ? detail : null)).join('')
|
? runs.slice(0, 5).map((r) => runHtml(r, details[r.id] || (detail && detail.id === r.id ? detail : null))).join('')
|
||||||
: '<p class="form-hint">No runs yet.</p>';
|
: '<p class="form-hint">No runs yet.</p>';
|
||||||
const s = status.search;
|
const s = status.search;
|
||||||
document.getElementById('aiSearch').textContent = s.error
|
document.getElementById('aiSearch').textContent = s.error
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue