Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| function inferredOwnerFromBucket(bucket){return bucket?String(bucket).split('/')[0]:''} | |
| function inferredJobUrl(summary={}, detail={}){if(summary.job_url)return summary.job_url;const launch=detail.launch||{};const stateObj=detail.state||{};if(launch.job_url)return launch.job_url;if(stateObj.job_url)return stateObj.job_url;const jobId=summary.job_id||launch.job_id||stateObj.job_id;const owner=summary.created_by||summary.username||summary.owner||launch.created_by||launch.username||launch.owner||stateObj.created_by||stateObj.username||stateObj.owner||state.user?.username||inferredOwnerFromBucket(summary.bucket_source||detail.bucket_source||state.bucketSource);return jobId&&owner?`https://huggingface.co/jobs/${owner}/${jobId}`:''} | |
| function bucketRunFileUrl(bucket,runId,relPath=''){const rel=String(relPath||'').replace(/^\/+|\/+$/g,'');return bucket&&runId?`https://huggingface.co/buckets/${bucket}/tree/runs/${runId}${rel?`/${rel}`:''}`:''} | |
| function runCanonicalStatus(run={}){ | |
| const s=String(run.status||run.summary?.status||run.state?.status||'unknown').toLowerCase(); | |
| const gate=String(run.gate_status||run.inference_gate?.status||run.summary?.gate_status||'').toLowerCase(); | |
| const smoke=String(run.smoke_status||run.generation_smoke?.status||run.summary?.smoke_status||'').toLowerCase(); | |
| const text=[s,gate,smoke].filter(Boolean).join(' '); | |
| if(text.includes('stale'))return'stale'; | |
| if(text.includes('manual')||text.includes('hardware'))return'manual_hardware_required'; | |
| if(text.includes('technical_blocker')||text.includes('blocker')||text.includes('blocked'))return'technical_blocker'; | |
| if(text.includes('failed')||text.includes('failure')||text.includes('error')||text.includes('timeout'))return'failed'; | |
| if(text.includes('running')||text.includes('queued')||text.includes('pending')||text.includes('started')||text.includes('waiting')||text.includes('building'))return'running'; | |
| if(s==='full_inference_candidate_health_passed'||s==='health_only'||s==='partial'||s==='partial_validation'||s==='completed_with_warnings')return'partial_validation'; | |
| if(text.includes('success')||text.includes('succeed')||text.includes('passed')||['done','completed','full_inference_success','repair_success'].includes(s))return'full_inference_success'; | |
| if(text.includes('cancelled')||text.includes('canceled')||text.includes('stopped'))return'stopped'; | |
| return s||'unknown'; | |
| } | |
| function runMatchesStatus(run,status){const canon=runCanonicalStatus(run);if(!status||status==='all')return true;if(status==='failed')return canon==='failed';if(status==='running')return canon==='running';if(status==='full_inference_success')return canon==='full_inference_success';if(status==='partial_validation')return canon==='partial_validation';if(status==='manual_hardware_required')return canon==='manual_hardware_required';if(status==='technical_blocker')return canon==='technical_blocker';if(status==='stale')return canon==='stale';return canon===String(status).toLowerCase()} | |
| function runMatchesQuery(run,query){if(!query)return true;const haystack=[run.run_id,run.model_id,run.target_space,run.status,run.kind,run.selected_hardware].map(x=>String(x||'').toLowerCase()).join(' ');return haystack.includes(String(query).toLowerCase())} | |
| function runSortTimestamp(run={}){ | |
| const raw=run.updated_at||run.created_at||run.started_at||run.cancelled_at||''; | |
| const ts=Date.parse(raw); | |
| if(Number.isFinite(ts))return ts; | |
| const id=String(run.run_id||''); | |
| const m=id.match(/(\d{8})[-_]?(\d{6})/); | |
| if(m){ | |
| const d=m[1],t=m[2]; | |
| return Date.parse(`${d.slice(0,4)}-${d.slice(4,6)}-${d.slice(6,8)}T${t.slice(0,2)}:${t.slice(2,4)}:${t.slice(4,6)}Z`); | |
| } | |
| return 0; | |
| } | |
| function sortRunsNewestFirst(runs=[]){ | |
| return [...(runs||[])].sort((a,b)=>runSortTimestamp(b)-runSortTimestamp(a)||String(b.run_id||'').localeCompare(String(a.run_id||''))); | |
| } | |
| function filteredRuns(){return (state.runsCache||[]).filter(r=>runMatchesStatus(r,state.runStatusFilter||'all')&&runMatchesQuery(r,state.runSearch||''))} | |
| function renderRunStats(){const query=state.runSearch||'';const base=(state.runsCache||[]).filter(r=>runMatchesQuery(r,query));const counts={all:base.length,running:0,full_inference_success:0,partial_validation:0,manual_hardware_required:0,technical_blocker:0,failed:0,stale:0};for(const r of base){for(const key of Object.keys(counts)){if(key!=='all'&&runMatchesStatus(r,key))counts[key]+=1}}document.querySelectorAll('.filter[data-status]').forEach(btn=>{const status=btn.dataset.status||'all';const label={all:'All',running:'Running',full_inference_success:'Success',partial_validation:'Partial',manual_hardware_required:'Manual',failed:'Failed',technical_blocker:'Blockers',stale:'Stale'}[status]||status;const count=counts[status]??0;btn.innerHTML=`${escapeHtml(label)} <span>${count}</span>`;btn.classList.toggle('active',status===state.runStatusFilter)})} | |
| function runCardKind(run={}){return isValidationRunSummary(run)?'Test':'Build'} | |
| function runCompactStatusLabel(status){ | |
| const s=String(status||'unknown').toLowerCase(); | |
| if(s==='full_inference_candidate_health_passed'||s==='health_only'||s==='partial_validation'||s==='partial'||s==='completed_with_warnings')return 'Partial'; | |
| if(s.includes('success')||s.includes('succeed')||s.includes('passed')||s==='done'||s==='completed')return 'Success'; | |
| if(s.includes('running')||s.includes('queued')||s.includes('pending')||s.includes('building')||s.includes('waiting'))return 'Running'; | |
| if(s.includes('manual')||s.includes('hardware'))return 'Manual'; | |
| if(s.includes('stale'))return 'Stale'; | |
| if(s.includes('cancelled')||s.includes('canceled')||s.includes('stopped'))return 'Stopped'; | |
| if(s.includes('failed')||s.includes('error')||s.includes('technical')||s.includes('blocker'))return 'Failed'; | |
| return badgeLabel(status); | |
| } | |
| function runIsFinished(status){ | |
| const s=String(status||'').toLowerCase(); | |
| return Boolean(s&&( | |
| s.includes('success')||s.includes('succeed')||s.includes('failed')||s.includes('error')|| | |
| s.includes('manual')||s.includes('blocker')||s.includes('stale')|| | |
| s==='done'||s==='completed'||s==='cancelled'||s==='canceled'||s==='stopped'||s==='health_only'||s==='full_inference_candidate_health_passed'||s==='partial'||s==='partial_validation'||s==='completed_with_warnings' | |
| )); | |
| } | |
| function runHasValidationResult(detail={},summaryOverride={}){ | |
| const summary={...(detail.summary||{}),...(summaryOverride||{})}; | |
| const smoke=detail.generation_smoke||detail.tests?.generation_smoke||summary.generation_smoke||detail.state?.generation_smoke||{}; | |
| const gate=detail.inference_gate||summary.inference_gate||{}; | |
| const schema=detail.api_schema||detail.tests?.api_schema||summary.api_schema||{}; | |
| const events=Array.isArray(detail.events)?detail.events:(Array.isArray(summary.events)?summary.events:[]); | |
| const status=String(summary.status||detail.status||detail.state?.status||'').toLowerCase(); | |
| const terminalSuccess=runMatchesStatus({status},'full_inference_success'); | |
| return Boolean( | |
| Object.keys(smoke||{}).length|| | |
| Object.keys(gate||{}).length|| | |
| Object.keys(schema||{}).length|| | |
| summary.smoke_test_passed|| | |
| summary.health_passed|| | |
| summary.latency_seconds|| | |
| summary.observed_latency_seconds|| | |
| terminalSuccess|| | |
| events.some(e=>['generation_smoke','inference_gate','api_validation','repair_validation'].includes(String(e.step||''))&&['success','done','failed','warning'].includes(String(e.status||'').toLowerCase())) | |
| ); | |
| } | |
| function runImplementationMode(run={},detail={}){return firstNonEmpty(run.implementation_mode,run.summary?.implementation_mode,run.state?.implementation_mode,run.launch?.implementation_mode,detail.summary?.implementation_mode,detail.state?.implementation_mode,detail.launch?.implementation_mode)} | |
| function runRelativeTime(run={}){ | |
| const raw=run.updated_at||run.created_at||run.started_at||run.cancelled_at||''; | |
| const ts=Date.parse(raw); | |
| if(!Number.isFinite(ts))return runStatTime(run); | |
| const diff=Math.max(0,Date.now()-ts); | |
| const mins=Math.floor(diff/60000); | |
| if(mins<1)return'now'; | |
| if(mins<60)return`${mins}m ago`; | |
| const hrs=Math.floor(mins/60); | |
| if(hrs<24)return`${hrs}h ago`; | |
| const days=Math.floor(hrs/24); | |
| if(days<7)return`${days}d ago`; | |
| return formatTime(raw); | |
| } | |
| function runPrimaryTitle(run={}){ | |
| const validation=isValidationRunSummary(run); | |
| if(validation)return firstNonEmpty(run.target_space,run.space_id,run.run_id)||'Validation run'; | |
| return firstNonEmpty(run.model_id,run.target_space,run.run_id)||'Build run'; | |
| } | |
| function runSecondaryLine(run={}){ | |
| const validation=isValidationRunSummary(run); | |
| if(validation){ | |
| const parts=[firstNonEmpty(run.api_name,run.endpoint),runStatLatency(run),run.run_id].filter(Boolean); | |
| return parts.join(' β’ '); | |
| } | |
| const mode=runImplementationMode(run); | |
| const parts=[run.target_space,mode?'Goal: '+implementationModeLabel(mode,{short:true}):'',run.selected_hardware].filter(Boolean); | |
| return parts.join(' β’ '); | |
| } | |
| function runCardMeta(run={}){return runSecondaryLine(run)} | |
| function renderRunRows(runs,compact=false){ | |
| return (runs||[]).map(r=>{ | |
| const validation=isValidationRunSummary(r); | |
| const kind=runCardKind(r); | |
| const status=r.status||'unknown'; | |
| const tone=statusClass(status); | |
| const title=runPrimaryTitle(r); | |
| const secondary=runSecondaryLine(r)||r.run_id||'No metadata yet'; | |
| const time=runRelativeTime(r); | |
| const canDelete=runCanBeDeleted(status); | |
| return `<article class="run-row run-list-item ${validation?'validation-run':'build-run'}" role="button" tabindex="0" data-run="${escapeHtml(r.run_id)}" title="${validation?'Validation run':'Build run'}"> | |
| <span class="run-list-dot ${tone}" aria-hidden="true"></span> | |
| <div class="run-list-copy"> | |
| <div class="run-list-head"> | |
| <strong class="run-list-title" title="${escapeHtml(title)}">${escapeHtml(title)}</strong> | |
| <span class="run-list-kind ${validation?'validation':'build'}">${escapeHtml(kind)}</span> | |
| </div> | |
| <p class="run-list-sub" title="${escapeHtml(secondary)}">${escapeHtml(secondary)}</p> | |
| <p class="run-list-id" title="${escapeHtml(r.run_id)}">${escapeHtml(r.run_id)}</p> | |
| </div> | |
| <div class="run-list-status"> | |
| <em class="run-status-pill ${tone}" title="${escapeHtml(badgeLabel(status))}">${escapeHtml(runCompactStatusLabel(status))}</em> | |
| <time>${escapeHtml(time)}</time> | |
| </div> | |
| <button class="icon-btn danger run-delete-btn" type="button" data-run-delete="${escapeHtml(r.run_id)}" title="${canDelete?'Delete this finished run':'Delete becomes available after this run finishes'}" aria-label="Delete run ${escapeHtml(r.run_id)}" ${canDelete?'':'disabled aria-disabled="true"'}>Γ</button> | |
| </article>`; | |
| }).join('') | |
| } | |
| function bindRunPagination(root){ | |
| if(!root||root.dataset.boundPagination==='true')return; | |
| root.dataset.boundPagination='true'; | |
| root.addEventListener('click',e=>{ | |
| const btn=e.target.closest('[data-page-action]'); | |
| if(!btn||btn.disabled)return; | |
| state.runPage+=(btn.dataset.pageAction==='next'?1:-1); | |
| renderRunsFromCache(); | |
| }); | |
| } | |
| function renderRunPagination(total){ | |
| const root=$('runsPagination'); | |
| if(!root)return; | |
| bindRunPagination(root); | |
| const perPage=state.runsPerPage||5; | |
| const pages=Math.max(1,Math.ceil(total/perPage)); | |
| state.runPage=Math.min(Math.max(0,state.runPage||0),pages-1); | |
| if(total<=perPage){root.innerHTML='';return} | |
| root.innerHTML=`<button class="secondary small" data-page-action="prev" ${state.runPage<=0?'disabled':''}>βΉ</button><span>Page ${state.runPage+1} / ${pages}</span><button class="secondary small" data-page-action="next" ${state.runPage>=pages-1?'disabled':''}>βΊ</button>`; | |
| } | |
| function isValidationRunSummary(run={}){return isValidationRunDetail({summary:run,state:run,kind:run.kind,run_type:run.run_type})} | |
| function runStatTime(run={}){const raw=run.updated_at||run.created_at||run.started_at||run.cancelled_at||'';return raw?formatTime(raw):'β'} | |
| function runStatLatency(run={}){ | |
| const latency=run.latency_seconds||run.observed_latency_seconds||run.generation_smoke?.latency_seconds||run.generation_smoke?.observed_latency_seconds; | |
| return latency?fmtSeconds(Number(latency)):''; | |
| } | |
| function runStatLatencyValue(run={}){ | |
| const latency=run.latency_seconds||run.observed_latency_seconds||run.generation_smoke?.latency_seconds||run.generation_smoke?.observed_latency_seconds; | |
| const n=Number(latency); | |
| return Number.isFinite(n)&&n>0?n:null; | |
| } | |
| function percentile(values=[],p=0.5){ | |
| const nums=(values||[]).map(Number).filter(n=>Number.isFinite(n)).sort((a,b)=>a-b); | |
| if(!nums.length)return null; | |
| const idx=(nums.length-1)*p; | |
| const lo=Math.floor(idx),hi=Math.ceil(idx); | |
| if(lo===hi)return nums[lo]; | |
| return nums[lo]+(nums[hi]-nums[lo])*(idx-lo); | |
| } | |
| function pct(part,total){return total?`${Math.round((part/total)*100)}%`:'β'} | |
| function runStatsIssueCounts(runs=[]){ | |
| const counts={failed_builds:0,failed_validations:0,manual_hardware:0,pi_model_mismatch:0,stale:0}; | |
| for(const r of runs){ | |
| const validation=isValidationRunSummary(r); | |
| const status=String(r.status||'').toLowerCase(); | |
| const pi=r.pi_model_resolution||{}; | |
| if(runMatchesStatus(r,'failed')) validation?counts.failed_validations++:counts.failed_builds++; | |
| if(runMatchesStatus(r,'manual_hardware_required')) counts.manual_hardware++; | |
| if(pi.mismatch||status.includes('model_mismatch')) counts.pi_model_mismatch++; | |
| if(status.includes('stale')) counts.stale++; | |
| } | |
| return counts; | |
| } | |
| function runStatsCell(label,value,detail='',tone='neutral'){ | |
| return `<div class="run-stat-cell ${escapeHtml(tone)}"><span>${escapeHtml(label)}</span><strong>${escapeHtml(value)}</strong>${detail?`<em>${escapeHtml(detail)}</em>`:''}</div>`; | |
| } | |
| function renderRunAggregateStats(){ | |
| const root=$('runStatsList'); | |
| if(!root)return; | |
| const runs=state.runsCache||[]; | |
| const builds=runs.filter(r=>!isValidationRunSummary(r)); | |
| const validations=runs.filter(r=>isValidationRunSummary(r)); | |
| const running=runs.filter(r=>runMatchesStatus(r,'running')).length; | |
| const failed=runs.filter(r=>runMatchesStatus(r,'failed')).length; | |
| const terminalBuilds=builds.filter(r=>!runMatchesStatus(r,'running')); | |
| const terminalValidations=validations.filter(r=>!runMatchesStatus(r,'running')); | |
| const successBuilds=terminalBuilds.filter(r=>runMatchesStatus(r,'full_inference_success')).length; | |
| const passedValidations=terminalValidations.filter(r=>runMatchesStatus(r,'full_inference_success')).length; | |
| const latencies=validations.map(runStatLatencyValue).filter(v=>v!==null); | |
| const median=percentile(latencies,.5); | |
| const p95=percentile(latencies,.95); | |
| const issues=runStatsIssueCounts(runs); | |
| const issueTotal=Object.values(issues).reduce((a,b)=>a+b,0); | |
| const badge=$('runStatsBadge'); | |
| if(badge){ | |
| badge.textContent=runs.length?`${runs.length} indexed`:'No runs'; | |
| badge.className='badge '+(failed||issueTotal?'warn':running?'running':runs.length?'success':'neutral'); | |
| } | |
| if(!runs.length){ | |
| root.innerHTML='<div class="empty">No indexed runs yet. Launch a build or validation to populate stats.</div>'; | |
| return; | |
| } | |
| const issueItems=[ | |
| ['Failed builds',issues.failed_builds], | |
| ['Failed validations',issues.failed_validations], | |
| ['Manual hardware',issues.manual_hardware], | |
| ['Pi mismatch',issues.pi_model_mismatch], | |
| ['Stale runs',issues.stale], | |
| ].filter(([,count])=>count>0); | |
| root.innerHTML=` | |
| <div class="run-stats-grid"> | |
| ${runStatsCell('Total runs',String(runs.length),`${builds.length} builds Β· ${validations.length} validations`,'neutral')} | |
| ${runStatsCell('Status',`${running} running`,`${failed} failed` ,failed?'warn':running?'running':'success')} | |
| ${runStatsCell('Build success',pct(successBuilds,terminalBuilds.length),`${successBuilds}/${terminalBuilds.length} finished builds`,'success')} | |
| ${runStatsCell('Validation pass',pct(passedValidations,terminalValidations.length),`${passedValidations}/${terminalValidations.length} finished tests`,'success')} | |
| </div> | |
| <div class="run-stats-band"> | |
| <span>Test response time</span> | |
| <strong>${latencies.length?`Typical ${fmtSeconds(median)} Β· slowest recent ${fmtSeconds(p95)}`:'No completed Space Test yet'}</strong> | |
| </div> | |
| <div class="run-stats-band ${issueItems.length?'warn':'success'}"> | |
| <span>Things to review</span> | |
| <strong>${issueItems.length?issueItems.map(([label,count])=>`${count} ${label}`).join(' Β· '):'Nothing to review in indexed runs'}</strong> | |
| </div>`; | |
| } | |
| function rememberDeletedRun(runId){ | |
| if(!runId)return; | |
| state.deletedRuns=state.deletedRuns||{}; | |
| state.deletedRuns[runId]=Date.now(); | |
| } | |
| function isRunLocallyDeleted(runId){ | |
| if(!runId||!state.deletedRuns)return false; | |
| const ts=state.deletedRuns[runId]; | |
| if(!ts)return false; | |
| const ttl=10*60*1000; | |
| if(Date.now()-ts>ttl){delete state.deletedRuns[runId];return false;} | |
| return true; | |
| } | |
| function forgetRunEverywhere(runId){ | |
| if(!runId)return; | |
| if(state.runDetailCache)delete state.runDetailCache[runId]; | |
| if(state.runDetailRequests){ | |
| delete state.runDetailRequests[`${runId}:light`]; | |
| delete state.runDetailRequests[`${runId}:heavy`]; | |
| } | |
| if(state.documentCache)delete state.documentCache[runId]; | |
| if(state.latencyCache)delete state.latencyCache[runId]; | |
| state.runsCache=(state.runsCache||[]).filter(r=>r.run_id!==runId); | |
| document.querySelectorAll(`.run-row[data-run="${CSS.escape(runId)}"]`).forEach(row=>row.remove()); | |
| } | |
| function activeRunIds(){ | |
| return new Set((state.runsCache||[]).map(r=>r.run_id).filter(Boolean)); | |
| } | |
| function associatedSpaceFromDetail(detail={},summaryOverride={}){ | |
| const summary={...(detail.summary||{}),...(summaryOverride||{})}; | |
| const candidates=[summary.target_space,summary.target_space_id,detail.target_space,detail.target_space_id,detail.state?.target_space,detail.launch?.target_space,detail.links?.target_space]; | |
| for(const value of candidates){ | |
| const text=String(value||'').trim().replace('https://huggingface.co/spaces/','').replace(/^\/+|\/+$/g,''); | |
| if(text&&text.includes('/'))return text; | |
| } | |
| const urls=[summary.target_space_url,detail.target_space_url,detail.state?.target_space_url,detail.launch?.target_space_url,detail.links?.target_space_url]; | |
| for(const url of urls){ | |
| const text=String(url||''); | |
| const marker='huggingface.co/spaces/'; | |
| if(text.includes(marker))return text.split(marker,1)[1].split('?',1)[0].split('#',1)[0].replace(/^\/+|\/+$/g,''); | |
| } | |
| return ''; | |
| } | |
| function runCanOfferSpaceDeletion(kind,detail={},summary={}){ | |
| const normalizedKind=String(kind||summary.kind||detail.kind||detail.state?.kind||detail.launch?.kind||'').toLowerCase(); | |
| if(normalizedKind.includes('validation')||normalizedKind.includes('space_test'))return false; | |
| return Boolean(associatedSpaceFromDetail(detail,summary)); | |
| } | |
| function runCanBeDeleted(status){ | |
| const s=String(status||'').toLowerCase(); | |
| if(!s||s==='unknown')return true; | |
| return runIsFinished(s); | |
| } | |
| // v105 delegated row binding preserves v98 invariant: renderRunAggregateStats();document.querySelectorAll('.run-row[data-run]') | |
| function bindRunRowEvents(root){ | |
| if(!root||root.dataset.boundRuns==='true')return; | |
| root.dataset.boundRuns='true'; | |
| root.addEventListener('click',e=>{ | |
| const deleteBtn=e.target.closest('[data-run-delete]'); | |
| if(deleteBtn){e.preventDefault();e.stopPropagation();if(deleteBtn.disabled||deleteBtn.getAttribute('aria-disabled')==='true')return;const runId=deleteBtn.dataset.runDelete;const cached=cachedRunById(runId)||{};deleteRunById(runId,{kind:isValidationRunSummary(cached)?'validation':'active',detail:optimisticDetailFromSummary(cached),buttonId:null});return} | |
| const row=e.target.closest('.run-row[data-run]'); | |
| if(row)selectRun(row.dataset.run); | |
| }); | |
| root.addEventListener('keydown',e=>{ | |
| if(e.key!=='Enter'&&e.key!==' ')return; | |
| const row=e.target.closest('.run-row[data-run]'); | |
| if(!row||e.target.closest('[data-run-delete]'))return; | |
| e.preventDefault();selectRun(row.dataset.run); | |
| }); | |
| } | |
| function renderRunsFromCache(){state.runsCache=sortRunsNewestFirst(state.runsCache||[]);const runs=filteredRuns();const perPage=state.runsPerPage||5;state.runPage=Math.min(Math.max(0,state.runPage||0),Math.max(0,Math.ceil(runs.length/perPage)-1));const visible=runs.slice(state.runPage*perPage,state.runPage*perPage+perPage);const selectedId=state.centerTab==='validate'&&state.validationRunId?state.validationRunId:state.runId;const signature=JSON.stringify({ids:visible.map(r=>[r.run_id,r.status,r.updated_at,r.target_space,r.model_id,r.latency_seconds,r.observed_latency_seconds,r.recommended_zero_gpu_duration_seconds,r.recommended_zerogpu_duration_seconds]),filter:state.runStatusFilter,search:state.runSearch,page:state.runPage,selected:selectedId});for(const [id,compact] of [['runsTableHome',true],['runsTable',false]]){const root=$(id);if(!root)continue;bindRunRowEvents(root);if(root.dataset.signature!==signature){root.innerHTML=renderRunRows(visible,compact)||'<div class="empty">No runs match this filter.</div>';root.dataset.signature=signature}}renderRunStats();renderRunPagination(runs.length);renderRunAggregateStats();document.querySelectorAll('.run-row').forEach(row=>row.classList.toggle('selected',Boolean(selectedId)&&row.dataset.run===selectedId))} | |
| async function loadRuns(forceNetwork=false){const stale=Date.now()-(state.runsLastLoaded||0)>45000;const shouldFetch=forceNetwork||!state.runsCache.length||stale;if(!shouldFetch){renderRunsFromCache();return state.runsCache||[]}if(state.runsLoadPromise&&!forceNetwork)return state.runsLoadPromise;document.querySelectorAll('.runs-panel,.full-runs-panel').forEach(x=>x.classList.add('is-refreshing'));state.runsLoadPromise=apiGet(`/api/runs?limit=100&bucket_name=${encodeURIComponent(state.bucketName)}`).then(data=>{state.runsCache=sortRunsNewestFirst((data.runs||[]).filter(r=>!isRunLocallyDeleted(r.run_id)));state.runsLastLoaded=Date.now();if(data.bucket_source)state.bucketSource=data.bucket_source;renderRunsFromCache();return state.runsCache}).catch(e=>{for(const id of ['runsTable','runsTableHome']){const root=$(id);if(root)root.textContent='Could not load runs: '+e.message}if(forceNetwork)console.warn(e);return state.runsCache||[]}).finally(()=>{state.runsLoadPromise=null;document.querySelectorAll('.runs-panel,.full-runs-panel').forEach(x=>x.classList.remove('is-refreshing'))});return state.runsLoadPromise} | |
| function cachedRunById(runId){ | |
| if(isRunLocallyDeleted(runId))return null; | |
| return (state.runsCache||[]).find(r=>r.run_id===runId)||null; | |
| } | |
| function optimisticDetailFromSummary(summary={}){ | |
| if(!summary)return null; | |
| return { | |
| run_id:summary.run_id, | |
| bucket_source:summary.bucket_source||state.bucketSource, | |
| summary:{...summary,_optimistic:true}, | |
| state:{ | |
| status:summary.status, | |
| model_id:summary.model_id, | |
| target_space:summary.target_space, | |
| selected_hardware:summary.selected_hardware, | |
| job_id:summary.job_id, | |
| job_url:summary.job_url, | |
| kind:summary.kind, | |
| }, | |
| events:summary.events||[], | |
| report:'', | |
| files:summary.files||[], | |
| generation_smoke:summary.generation_smoke||{}, | |
| inference_gate:summary.inference_gate||{}, | |
| api_schema:summary.api_schema||{}, | |
| view:{ | |
| run_id:summary.run_id, | |
| header:{ | |
| title:summary.run_id||'Selected run', | |
| status:summary.status||'unknown', | |
| raw_status:summary.status||'unknown', | |
| model:summary.model_id||'β', | |
| space:summary.target_space||'β', | |
| }, | |
| links:{ | |
| job_url:summary.job_url||'', | |
| space_url:summary.target_space_url||'', | |
| artifacts_url:summary.artifacts_url||'', | |
| }, | |
| activity:[], | |
| }, | |
| }; | |
| } | |
| function upsertRunExplorerFromProgress(p={}){ | |
| const runId=p.run_id||p.summary?.run_id||state.runId; | |
| if(!runId||isRunLocallyDeleted(runId))return; | |
| const summary={ | |
| ...(cachedRunById(runId)||{}), | |
| ...(p.summary||{}), | |
| run_id:runId, | |
| status:p.view?.header?.status||p.status||p.state?.status||p.summary?.status, | |
| updated_at:p.state?.updated_at||p.summary?.updated_at||p.updated_at||new Date().toISOString(), | |
| model_id:p.summary?.model_id||p.state?.model_id||p.model_id, | |
| target_space:p.summary?.target_space||p.state?.target_space, | |
| target_space_url:p.summary?.target_space_url||p.links?.space_url||p.view?.links?.space_url, | |
| selected_hardware:p.summary?.selected_hardware||p.state?.selected_hardware, | |
| latency_seconds:p.summary?.latency_seconds||p.generation_smoke?.latency_seconds||p.state?.generation_smoke?.latency_seconds, | |
| observed_latency_seconds:p.summary?.observed_latency_seconds||p.generation_smoke?.observed_latency_seconds||p.generation_smoke?.latency_seconds, | |
| recommended_zero_gpu_duration_seconds:p.summary?.recommended_zero_gpu_duration_seconds||p.generation_smoke?.recommended_zero_gpu_duration_seconds||p.generation_smoke?.recommended_zerogpu_duration_seconds, | |
| recommended_zerogpu_duration_seconds:p.summary?.recommended_zerogpu_duration_seconds||p.generation_smoke?.recommended_zerogpu_duration_seconds||p.generation_smoke?.recommended_zero_gpu_duration_seconds, | |
| kind:p.summary?.kind||p.state?.kind||'universal_model_card_builder', | |
| bucket_source:p.bucket_source||p.summary?.bucket_source||state.bucketSource, | |
| }; | |
| state.runsCache=state.runsCache||[]; | |
| const idx=state.runsCache.findIndex(r=>r.run_id===runId); | |
| if(idx>=0)state.runsCache[idx]={...state.runsCache[idx],...summary}; | |
| else state.runsCache.unshift(summary); | |
| state.runsLastLoaded=Date.now(); | |
| renderRunsFromCache(); | |
| } | |
| function renderRunSelectionPreview(runId){ | |
| const cached=cachedRunById(runId); | |
| if(!cached)return; | |
| const detail=optimisticDetailFromSummary(cached); | |
| if(isValidationRunDetail(detail)){showValidationRunDetail(detail);return} | |
| switchCenterTab('active'); | |
| renderRunDetail(detail); | |
| setText('progressTitle',runId); | |
| setText('progressStatus',badgeLabel(cached.status||'loading')); | |
| const statusEl=$('progressStatus'); | |
| if(statusEl)statusEl.className='badge '+statusClass(cached.status||''); | |
| setText('currentStep','Loading run detailsβ¦'); | |
| setText('lastEvent','Fetching latest events and progressβ¦'); | |
| setText('progressPercent',cached.status&&String(cached.status).includes('success')?'100%':'β'); | |
| } | |
| function cachedRunDetail(runId,heavy=false){ | |
| const entry=state.runDetailCache?.[runId]; | |
| if(!entry)return null; | |
| const fresh=Date.now()-(entry.ts||0)<(state.runDetailCacheTtlMs||300000); | |
| if(!fresh)return null; | |
| if(heavy&&!entry.heavy)return null; | |
| return entry.detail||null; | |
| } | |
| function rememberRunDetail(runId,detail,heavy=false){ | |
| if(!runId||!detail)return; | |
| state.runDetailCache=state.runDetailCache||{}; | |
| const previous=state.runDetailCache[runId]||{}; | |
| state.runDetailCache[runId]={detail,heavy:Boolean(heavy||previous.heavy),ts:Date.now()}; | |
| } | |
| function fetchRunDetailOnce(runId,heavy=false){ | |
| state.runDetailRequests=state.runDetailRequests||{}; | |
| const key=`${runId}:${heavy?'heavy':'light'}`; | |
| if(state.runDetailRequests[key])return state.runDetailRequests[key]; | |
| const promise=apiGet(`/api/runs/${encodeURIComponent(runId)}?bucket_name=${encodeURIComponent(state.bucketName)}&include_heavy=${heavy?'true':'false'}`) | |
| .finally(()=>{delete state.runDetailRequests[key]}); | |
| state.runDetailRequests[key]=promise; | |
| return promise; | |
| } | |
| async function selectRun(runId){ | |
| // Keep the user on the current tab while refreshing the selected run panel. | |
| // Run selection must feel instant: render the best local data first, then hydrate. | |
| if(!runId)return; | |
| if(isRunLocallyDeleted(runId)){ | |
| forgetRunEverywhere(runId); | |
| renderRunsFromCache(); | |
| showMessage('This run was deleted and is no longer available.','warning'); | |
| return; | |
| } | |
| document.querySelectorAll('.run-row').forEach(row=>row.classList.toggle('selected',row.dataset.run===runId)); | |
| const cachedHeavy=cachedRunDetail(runId,true); | |
| const cachedLight=cachedRunDetail(runId,false); | |
| const localDetail=cachedHeavy||cachedLight||optimisticDetailFromSummary(cachedRunById(runId)); | |
| if(localDetail){ | |
| if(isValidationRunDetail(localDetail)){ | |
| showValidationRunDetail(localDetail); | |
| }else{ | |
| switchCenterTab('active'); | |
| setBuildModeInspecting(runId); | |
| renderRunDetail(localDetail); | |
| startPolling(runId,{deferFirstTick:true}); | |
| } | |
| }else{ | |
| renderRunSelectionPreview(runId); | |
| } | |
| // fetchRunDetailOnce wraps apiGet(`/api/runs/...?include_heavy=false|include_heavy=true) to dedupe duplicate clicks. | |
| try{ | |
| const detail=cachedLight||await fetchRunDetailOnce(runId,false); | |
| rememberRunDetail(runId,detail,false); | |
| if(detail.bucket_source)state.bucketSource=detail.bucket_source; | |
| if(isValidationRunDetail(detail)){ | |
| showValidationRunDetail(detail); | |
| if(!cachedHeavy){ | |
| fetchRunDetailOnce(runId,true).then(full=>{ | |
| rememberRunDetail(runId,full,true); | |
| if((state.validationRunId||'')===runId){if(full.bucket_source)state.bucketSource=full.bucket_source;showValidationRunDetail(full)} | |
| }).catch(e=>console.warn('heavy validation hydration failed',e)); | |
| } | |
| return; | |
| } | |
| switchCenterTab('active'); | |
| setBuildModeInspecting(runId); | |
| renderRunDetail(detail); | |
| startPolling(runId,{deferFirstTick:true}); | |
| if(!cachedHeavy){ | |
| fetchRunDetailOnce(runId,true).then(full=>{ | |
| rememberRunDetail(runId,full,true); | |
| if(state.runId===runId){if(full.bucket_source)state.bucketSource=full.bucket_source;renderRunDetail(full)} | |
| }).catch(e=>console.warn('heavy run hydration failed',e)); | |
| } | |
| }catch(e){ | |
| showMessage(`Could not load run details: ${e.message}`,'error'); | |
| const report=$('reportPreview');if(report)report.textContent='Could not load run details: '+e.message; | |
| } | |
| } | |
| function runDeletionContext(runId,options={}){ | |
| const kind=options.kind==='validation'?'validation':'active'; | |
| const explicit=options.detail||{}; | |
| const candidate=kind==='validation'?(explicit.run_id||explicit.summary?.run_id?explicit:state.validationDetail||{}):(explicit.run_id||explicit.summary?.run_id?explicit:state.selectedRunDetail||state.activeRunProgress||{}); | |
| const summary=candidate.summary||{}; | |
| const resolvedRunId=runId||summary.run_id||candidate.run_id||(kind==='validation'?state.validationRunId:state.runId); | |
| return {kind,runId:resolvedRunId,detail:candidate,summary}; | |
| } | |
| function clearDeletedRunState(runId,kind){ | |
| if(!runId)return; | |
| if(state.runId===runId){ | |
| if(state.poll){clearInterval(state.poll);state.poll=null} | |
| state.runId=null; | |
| state.activeRunProgress=null; | |
| state.selectedRunDetail=null; | |
| state.activeLinks={}; | |
| clearSavedRun(); | |
| resetRunDetails(); | |
| } | |
| if(state.validationRunId===runId||kind==='validation'){ | |
| if(state.validationRunId===runId)stopValidationPolling(); | |
| if(state.validationDetail?.run_id===runId||state.validationDetail?.summary?.run_id===runId||kind==='validation')state.validationDetail=null; | |
| if(state.validationRunId===runId)state.validationRunId=null; | |
| renderValidationStatus({status:'pending',run_id:'β',events:[]}); | |
| setText('spaceTestOutput','β'); | |
| setText('spaceTestLatency','β'); | |
| setText('spaceTestVerdict','pending'); | |
| const btn=$('deleteValidationRun');if(btn)btn.disabled=true; | |
| } | |
| if(state.selectedRunDetail?.run_id===runId||state.selectedRunDetail?.summary?.run_id===runId)state.selectedRunDetail=null; | |
| } | |
| function ensureDeleteRunDialog(){ | |
| let modal=$('deleteRunDialog'); | |
| if(modal)return modal; | |
| modal=document.createElement('div'); | |
| modal.id='deleteRunDialog'; | |
| modal.className='delete-run-modal'; | |
| modal.hidden=true; | |
| modal.innerHTML=`<div class="delete-run-backdrop" data-delete-cancel></div> | |
| <section class="delete-run-card" role="dialog" aria-modal="true" aria-labelledby="deleteRunTitle" aria-describedby="deleteRunBody"> | |
| <button class="delete-run-close" type="button" data-delete-cancel aria-label="Close">Γ</button> | |
| <div class="delete-run-icon" aria-hidden="true">β«</div> | |
| <div class="delete-run-copy"> | |
| <span class="delete-run-kicker" id="deleteRunKicker">Delete run</span> | |
| <h3 id="deleteRunTitle">Delete this run?</h3> | |
| <p id="deleteRunBody">This removes the run folder from your Hugging Face Storage Bucket.</p> | |
| </div> | |
| <div class="delete-run-meta" id="deleteRunMeta"></div> | |
| <label class="delete-space-option" id="deleteSpaceOption" hidden> | |
| <input type="checkbox" id="deleteAssociatedSpace" /> | |
| <span><strong>Also delete associated Space</strong><em id="deleteAssociatedSpaceLabel">β</em></span> | |
| </label> | |
| <div class="delete-run-warning" id="deleteRunWarning" hidden></div> | |
| <div class="delete-run-actions"> | |
| <button class="secondary" type="button" data-delete-cancel>Keep run</button> | |
| <button class="primary danger" type="button" data-delete-confirm>Delete run</button> | |
| </div> | |
| </section>`; | |
| document.body.appendChild(modal); | |
| return modal; | |
| } | |
| function confirmRunDeletion({runId,kind='active',status='',detail={}}={}){ | |
| if(state.deleteModalPromise&&state.deleteModalRunId===runId)return state.deleteModalPromise; | |
| if(state.deleteModalPromise)return state.deleteModalPromise; | |
| state.deleteModalRunId=runId; | |
| state.deleteModalPromise=new Promise(resolve=>{ | |
| const modal=ensureDeleteRunDialog(); | |
| const confirmBtn=modal.querySelector('[data-delete-confirm]'); | |
| const cancelEls=modal.querySelectorAll('[data-delete-cancel]'); | |
| const title=$('deleteRunTitle'); | |
| const body=$('deleteRunBody'); | |
| const kicker=$('deleteRunKicker'); | |
| const meta=$('deleteRunMeta'); | |
| const warning=$('deleteRunWarning'); | |
| const spaceOption=$('deleteSpaceOption'); | |
| const spaceCheckbox=$('deleteAssociatedSpace'); | |
| const spaceLabel=$('deleteAssociatedSpaceLabel'); | |
| const normalized=String(status||detail.status||detail.summary?.status||detail.state?.status||'unknown').toLowerCase(); | |
| const active=runMatchesStatus({status:normalized},'running'); | |
| const label=kind==='validation'?'validation run':'build run'; | |
| const associatedSpace=associatedSpaceFromDetail(detail,detail.summary||{}); | |
| const canDeleteSpace=runCanOfferSpaceDeletion(kind,detail,detail.summary||{}); | |
| kicker.textContent=kind==='validation'?'Space Test deletion':'Build run deletion'; | |
| title.textContent=`Delete this ${label}?`; | |
| body.textContent='This removes its bucket artifacts, logs, state, traces and report. The generated or tested Space is kept unless you explicitly opt in below.'; | |
| meta.innerHTML=`<span><strong>Run</strong><code>${escapeHtml(runId||'β')}</code></span><span><strong>Type</strong>${escapeHtml(kind==='validation'?'Space Test':'Build')}</span><span><strong>Status</strong>${escapeHtml(badgeLabel(normalized))}</span>${associatedSpace?`<span><strong>Space</strong><code>${escapeHtml(associatedSpace)}</code></span>`:''}`; | |
| if(spaceOption&&spaceCheckbox&&spaceLabel){ | |
| spaceCheckbox.checked=false; | |
| spaceOption.hidden=!canDeleteSpace; | |
| spaceLabel.textContent=associatedSpace||'No associated Space detected'; | |
| spaceCheckbox.onchange=()=>{confirmBtn.textContent=spaceCheckbox.checked?'Delete run and Space':(active?'Delete stored files':'Delete run');warning.hidden=false;warning.textContent=spaceCheckbox.checked?`This will permanently delete the Hugging Face Space repository ${associatedSpace}. This cannot be undone.`:(active?'This run still looks active. Deleting only removes stored run files; it does not cancel a running Job.':'Deletion is permanent for this run folder.');}; | |
| } | |
| warning.hidden=!active&&!canDeleteSpace; | |
| warning.textContent=active?'This run still looks active. Deleting only removes stored run files; it does not cancel a running Job.':(canDeleteSpace?'Optional Space deletion is destructive and cannot be undone.':'Deletion is permanent for this run folder.'); | |
| confirmBtn.textContent=active?'Delete stored files':'Delete run'; | |
| const previousFocus=document.activeElement; | |
| let done=false; | |
| const close=value=>{ | |
| if(done)return;done=true; | |
| modal.hidden=true; | |
| modal.classList.remove('is-open'); | |
| document.removeEventListener('keydown',onKey); | |
| cancelEls.forEach(el=>el.removeEventListener('click',onCancel)); | |
| confirmBtn.removeEventListener('click',onConfirm); | |
| if(spaceCheckbox)spaceCheckbox.onchange=null; | |
| try{previousFocus&&previousFocus.focus&&previousFocus.focus()}catch(_){} | |
| state.deleteModalPromise=null; | |
| state.deleteModalRunId=null; | |
| resolve(value); | |
| }; | |
| const onCancel=()=>close(false); | |
| const onConfirm=()=>close({deleteSpace:Boolean(spaceCheckbox&&spaceCheckbox.checked&&canDeleteSpace),associatedSpace}); | |
| const onKey=e=>{if(e.key==='Escape')close(false);if(e.key==='Enter'&&modal.classList.contains('is-open'))onConfirm()}; | |
| cancelEls.forEach(el=>el.addEventListener('click',onCancel)); | |
| confirmBtn.addEventListener('click',onConfirm); | |
| document.addEventListener('keydown',onKey); | |
| modal.hidden=false; | |
| requestAnimationFrame(()=>{modal.classList.add('is-open');confirmBtn.focus();}); | |
| }); | |
| return state.deleteModalPromise; | |
| } | |
| async function deleteRunById(runId,options={}){ | |
| const context=runDeletionContext(runId,options); | |
| runId=context.runId; | |
| if(!runId){showMessage(context.kind==='validation'?'Select a validation run before deleting it.':'Select a run before deleting it.','warning');return} | |
| if(state.deletingRuns&&state.deletingRuns[runId])return; | |
| const status=String(context.summary.status||context.detail.status||context.detail.state?.status||'').toLowerCase(); | |
| const confirmed=await confirmRunDeletion({runId,kind:context.kind,status,detail:context.detail}); | |
| if(!confirmed)return; | |
| const deleteSpace=typeof confirmed==='object'&&Boolean(confirmed.deleteSpace); | |
| if(state.deletingRuns&&state.deletingRuns[runId])return; | |
| state.deletingRuns=state.deletingRuns||{}; | |
| state.deletingRuns[runId]=true; | |
| const buttonId=options.buttonId===null?null:(options.buttonId||(context.kind==='validation'?'deleteValidationRun':'deleteActiveRun')); | |
| setButtonBusy(buttonId,true,'Deletingβ¦'); | |
| try{ | |
| const result=await apiDelete(`/api/runs/${encodeURIComponent(runId)}?bucket_name=${encodeURIComponent(state.bucketName)}`,deleteSpace?{delete_space:true}:{}); | |
| const suffix=deleteSpace?(result.space_deleted?' and associated Space':(result.space_delete_error?' but Space deletion failed':' and Space was already missing')):''; | |
| showMessage(`Deleted run ${runId}${suffix}`,'success'); | |
| rememberDeletedRun(runId); | |
| clearDeletedRunState(runId,context.kind); | |
| forgetRunEverywhere(runId); | |
| renderRunsFromCache(); | |
| await loadRuns(true); | |
| }catch(e){ | |
| showMessage(e.message,true); | |
| }finally{ | |
| if(state.deletingRuns)delete state.deletingRuns[runId]; | |
| setButtonBusy(buttonId,false); | |
| if(buttonId){ | |
| const btn=$(buttonId); | |
| const currentId=buttonId==='deleteActiveRun'?state.runId:state.validationRunId; | |
| if(btn)btn.disabled=!(currentId&¤tId===runId); | |
| } | |
| } | |
| } | |
| async function deleteSelectedRun(){return deleteRunById(null,{kind:'active',detail:state.selectedRunDetail||state.activeRunProgress||{}})} | |
| function defaultRunDocuments(detail={}){ | |
| const summary=detail.summary||{}; | |
| const runId=summary.run_id||detail.run_id||state.runId; | |
| const bucket=summary.bucket_source||detail.bucket_source||state.bucketSource; | |
| const rootUrl=runId&&bucket?artifactUrl(runId,bucket):''; | |
| const blob=rel=>runId&&bucket?`https://huggingface.co/buckets/${bucket}/tree/runs/${runId}/${rel}`:''; | |
| const tree=rel=>rootUrl?`${rootUrl}/${rel}`:''; | |
| return [ | |
| {id:'pi_raw_trace',label:'Pi RAW',subtitle:'Source folder',icon:'π§Ύ',present:false,url:blob('traces/raw/agent_trace.jsonl')||tree('traces/raw'),sensitivity:'raw'}, | |
| {id:'pi_redacted_trace',label:'Pi redacted',subtitle:'Source folder',icon:'π‘οΈ',present:false,url:blob('traces/redacted/agent_trace.jsonl')||tree('traces/redacted'),sensitivity:'safe'}, | |
| {id:'report',label:'Report',subtitle:'Source document',icon:'π',present:false,url:blob('report.md')}, | |
| {id:'smoke',label:'Smoke',subtitle:'Source JSON',icon:'β‘',present:false,url:blob('tests/generation_smoke.json')}, | |
| {id:'repair_decision',label:'Decision',subtitle:'Source JSON',icon:'β',present:false,url:blob('repair/REPAIR_DECISION.json')}, | |
| {id:'blockage',label:'Blockage',subtitle:'Source JSON',icon:'!',tone:'warn',present:false,url:blob('repair/BLOCKAGE.json')}, | |
| {id:'eval_publish',label:'Eval publish',subtitle:'Archive status',icon:'β',present:false,url:blob('eval_publish_status.json')}, | |
| {id:'space_logs',label:'Space logs',subtitle:'Build/runtime index',icon:'β',present:false,url:blob('logs/space_logs_index.json')}, | |
| ]; | |
| } | |
| function mergeStableRunDocuments(runId,docs=[]){ | |
| state.documentCache=state.documentCache||{}; | |
| const cached=Array.isArray(state.documentCache[runId])?state.documentCache[runId]:[]; | |
| const byId=new Map(cached.map(d=>[d.id,{...d}])); | |
| for(const doc of docs||[]){ | |
| const previous=byId.get(doc.id)||{}; | |
| byId.set(doc.id,{...previous,...doc,present:Boolean(doc.present||previous.present),url:doc.url||previous.url||''}); | |
| } | |
| return docs.map(doc=>byId.get(doc.id)||doc); | |
| } | |
| function deriveRunDocuments(detail={}){ | |
| const baseDocs=defaultRunDocuments(detail); | |
| const backendDocs=Array.isArray(detail.run_documents)?detail.run_documents:[]; | |
| const docs=backendDocs.length?baseDocs.map(base=>({...(base||{}),...(backendDocs.find(doc=>doc&&doc.id===base.id)||{})})).concat(backendDocs.filter(doc=>doc&&!baseDocs.some(base=>base.id===doc.id))):baseDocs; | |
| const files=Array.isArray(detail.files)?detail.files:[]; | |
| const manifestArtifacts=Array.isArray(detail.artifact_manifest?.artifacts)?detail.artifact_manifest.artifacts:[]; | |
| const manifestPaths=manifestArtifacts.filter(a=>a&&a.present!==false).map(a=>String(a.path||'')).filter(Boolean); | |
| const filePaths=new Set([...files.map(f=>String(f.path||'')),...manifestPaths]); | |
| const hasPrefix=prefix=>[...filePaths].some(path=>String(path||'').startsWith(prefix.replace(/\/$/,'')+'/')); | |
| const reportText=String(detail.report||''); | |
| const summary=detail.summary||{}; | |
| const blockers=detail.technical_blockers||{}; | |
| const status=String(summary.status||detail.state?.status||detail.status||'').toLowerCase(); | |
| const shouldShowBlockers=Boolean(Object.keys(blockers).length)||status.includes('manual')||status.includes('blocker')||status.includes('failed')||status.includes('error'); | |
| const byId=new Map(docs.map(d=>[d.id,{...d}])); | |
| const traceDocState=(prefix,doc)=>{ | |
| const folderPrefix=prefix.replace(/\/$/,'')+'/'; | |
| const hasContent=[...filePaths].some(path=>path.startsWith(folderPrefix)&&!path.endsWith('/')); | |
| const runId=summary.run_id||detail.run_id||state.runId; | |
| const bucket=summary.bucket_source||detail.bucket_source||state.bucketSource; | |
| const folderUrl=runId&&bucket?`https://huggingface.co/buckets/${bucket}/tree/runs/${runId}/${prefix.replace(/\/$/,'')}`:''; | |
| const existingUrl=String(doc.url||''); | |
| const existingIsFolder=existingUrl.endsWith(`/${prefix.replace(/\/$/,'')}`); | |
| return {present:Boolean(hasContent||doc.present),url:folderUrl||existingUrl}; | |
| }; | |
| const rawTrace=traceDocState('traces/raw',byId.get('pi_raw_trace')); | |
| byId.get('pi_raw_trace').present=rawTrace.present; | |
| byId.get('pi_raw_trace').url=rawTrace.url; | |
| const redactedTrace=traceDocState('traces/redacted',byId.get('pi_redacted_trace')); | |
| byId.get('pi_redacted_trace').present=redactedTrace.present; | |
| byId.get('pi_redacted_trace').url=redactedTrace.url; | |
| byId.get('report').present=Boolean((byId.get('report').present&&byId.get('report').url)||reportText.length||filePaths.has('report.md')); | |
| byId.get('smoke').present=Boolean((byId.get('smoke').present&&byId.get('smoke').url)||Object.keys(detail.generation_smoke||{}).length||(filePaths.has('tests/generation_smoke.json')||filePaths.has('generation_smoke.json'))); | |
| if(shouldShowBlockers&&!byId.has('blockers')){ | |
| const runId=summary.run_id||detail.run_id||state.runId; | |
| const bucket=summary.bucket_source||detail.bucket_source||state.bucketSource; | |
| byId.set('blockers',{id:'blockers',label:'Blockers',subtitle:'Source JSON',icon:'β οΈ',tone:'warn',present:Boolean(Object.keys(blockers).length||filePaths.has('generated/TECHNICAL_BLOCKERS.json')||filePaths.has('TECHNICAL_BLOCKERS.json')),url:runId&&bucket?`https://huggingface.co/buckets/${bucket}/tree/runs/${runId}/generated/TECHNICAL_BLOCKERS.json`:''}); | |
| } | |
| if(byId.has('repair_decision')){ | |
| byId.get('repair_decision').present=Boolean((byId.get('repair_decision').present&&byId.get('repair_decision').url)||nonEmptyObject(detail.repair_decision)||filePaths.has('repair/REPAIR_DECISION.json')); | |
| } | |
| if(byId.has('blockage')){ | |
| byId.get('blockage').present=Boolean((byId.get('blockage').present&&byId.get('blockage').url)||nonEmptyObject(detail.blockage)||filePaths.has('repair/BLOCKAGE.json')); | |
| } | |
| if(byId.has('eval_publish')){ | |
| const evalStatus=detail.eval_publish||detail.eval_publish_status||{}; | |
| byId.get('eval_publish').present=Boolean((byId.get('eval_publish').present&&byId.get('eval_publish').url)||nonEmptyObject(detail.eval_publish)||nonEmptyObject(detail.eval_publish_status)||filePaths.has('eval_publish_status.json')); | |
| if(nonEmptyObject(evalStatus)){ | |
| if(evalStatus.published===true)byId.get('eval_publish').tone='neutral'; | |
| else if(String(evalStatus.reason||'')==='record_not_ready')byId.get('eval_publish').tone='pending'; | |
| else if(evalStatus.attempted)byId.get('eval_publish').tone='warn'; | |
| } | |
| } | |
| if(byId.has('space_logs')){ | |
| const logIndex=detail.space_logs_index||detail.space_log_index||detail.logs_index||{}; | |
| const hasSpaceLogs=nonEmptyObject(logIndex)||filePaths.has('logs/space_logs_index.json')||filePaths.has('space_logs_index.json')||filePaths.has('logs/space_log_diagnostics.json')||filePaths.has('logs/space_runtime_snapshot.json'); | |
| byId.get('space_logs').present=Boolean((byId.get('space_logs').present&&byId.get('space_logs').url)||hasSpaceLogs); | |
| if(nonEmptyObject(logIndex)){ | |
| const quality=String(logIndex.log_quality||logIndex.quality||'').toLowerCase(); | |
| if(quality==='snapshot_only'||quality==='partial')byId.get('space_logs').tone='warn'; | |
| if(quality==='unavailable')byId.get('space_logs').tone='warn'; | |
| } | |
| } | |
| if(!byId.has('repair')&&hasPrefix('repair')){ | |
| const runId=summary.run_id||detail.run_id||state.runId; | |
| const bucket=summary.bucket_source||detail.bucket_source||state.bucketSource; | |
| byId.set('repair',{id:'repair',label:'Repair',subtitle:'Source folder',icon:'β¦',tone:status.includes('failed')?'warn':'neutral',present:true,url:runId&&bucket?`https://huggingface.co/buckets/${bucket}/tree/runs/${runId}/repair`:''}); | |
| } | |
| const order=['pi_raw_trace','pi_redacted_trace','repair_decision','repair','blockage','report','smoke','eval_publish','space_logs','blockers']; | |
| const runId=String(summary.run_id||detail.run_id||state.runId||''); | |
| const resolved=order.map(id=>byId.get(id)).filter(Boolean).filter(d=>{ | |
| if(['repair_decision','blockage','eval_publish','space_logs'].includes(d.id))return Boolean(d.present); | |
| if(d.id==='blockers')return shouldShowBlockers||d.present; | |
| return true; | |
| }); | |
| return runId?mergeStableRunDocuments(runId,resolved):resolved; | |
| } | |
| function renderRunDocuments(detail={}){ | |
| const root=$('runDocumentsDock'); | |
| if(!root)return; | |
| const runId=String(detail.run_id||detail.summary?.run_id||state.runId||''); | |
| state.documentCache=state.documentCache||{}; | |
| let docs=deriveRunDocuments(detail); | |
| const hasReady=docs.some(d=>d.present&&d.url); | |
| if(hasReady||!state.documentCache[runId])state.documentCache[runId]=mergeStableRunDocuments(runId,docs); | |
| docs=state.documentCache[runId]||docs; | |
| if(!docs.length){root.innerHTML='<div class="empty compact-empty loading-shimmer">Run documents are being indexedβ¦</div>';return;} | |
| const signature=JSON.stringify(docs.map(d=>[d.id,d.present,d.url,d.label,d.subtitle,d.tone])); | |
| if(root.dataset.signature===signature)return; | |
| root.dataset.signature=signature; | |
| root.innerHTML=docs.map(doc=>{ | |
| const present=Boolean(doc.present&&doc.url); | |
| const tag=present?'a':'span'; | |
| const attrs=present?`href="${escapeHtml(doc.url)}" target="_blank" rel="noreferrer"`:''; | |
| const title=present?`Open source: ${doc.label}`:`${doc.label} is not in the bucket yet`; | |
| const cls=['run-doc-btn',present?'ready':'pending',doc.sensitivity==='raw'?'raw':'',doc.sensitivity==='safe'?'safe':'',doc.tone==='warn'?'warn':''].filter(Boolean).join(' '); | |
| return `<${tag} class="${cls}" ${attrs} title="${escapeHtml(title)}" aria-disabled="${present?'false':'true'}"><span class="doc-icon" aria-hidden="true">${escapeHtml(doc.icon||'π')}</span><strong>${escapeHtml(doc.label)}</strong><em>${escapeHtml(present?doc.subtitle||'Open source':'Pending')}</em></${tag}>`; | |
| }).join(''); | |
| } | |
| function recoveryDecisionActionLabel(action){ | |
| const key=String(action||'').toLowerCase(); | |
| return { | |
| wait_for_logs:'Wait for logs', | |
| inspect_more_logs:'Inspect more logs', | |
| factory_rebuild_same_code:'Factory rebuild same code', | |
| patch_code:'Patch code', | |
| request_manual_hardware:'Request manual hardware', | |
| declare_technical_blocker:'Declare technical blocker' | |
| }[key]||badgeLabel(key||'pending'); | |
| } | |
| function recoveryStatusTone(action,status,detail={}){ | |
| const a=String(action||'').toLowerCase(); | |
| const s=String(status||'').toLowerCase(); | |
| const validated=Boolean(latestRecoveryEvent(detail,['repair_validation'])&&['success','done','passed'].includes(String(latestRecoveryEvent(detail,['repair_validation'])?.status||'').toLowerCase())); | |
| if(validated)return'success'; | |
| if(a.includes('blocker')||s.includes('failed')||s.includes('error'))return'error'; | |
| if(a.includes('manual'))return'warn'; | |
| if(a.includes('rebuild')||a.includes('wait')||a.includes('inspect'))return'running'; | |
| if(a.includes('patch'))return'warn'; | |
| return'neutral'; | |
| } | |
| function nonEmptyObject(value){ | |
| return Boolean(value&&typeof value==='object'&&!Array.isArray(value)&&Object.keys(value).length>0); | |
| } | |
| function runHasRecoverySignals(detail={}){ | |
| const files=Array.isArray(detail.files)?detail.files:[]; | |
| const events=Array.isArray(detail.events)?detail.events:([]); | |
| const runId=String(detail.run_id||detail.summary?.run_id||state.runId||''); | |
| const stableEvents=typeof mergeStableEvents==='function'?mergeStableEvents(runId,events):events; | |
| const decision=detail.repair_decision; | |
| const blockage=detail.blockage; | |
| const recoveryStepPattern=/^(failure_detected|failure_diagnosis|pi_diagnosis|repair_decision|wait_for_logs|factory_rebuild|repair|repair_diagnosis|repair_brief|repair_plan|repair_patch|repair_upload|repair_validation|technical_blocker|manual_hardware_required|failure)$/; | |
| return Boolean( | |
| nonEmptyObject(decision)|| | |
| nonEmptyObject(blockage)|| | |
| files.some(f=>String(f.path||'').startsWith('repair/'))|| | |
| stableEvents.some(e=>recoveryStepPattern.test(String(e.step||''))) | |
| ); | |
| } | |
| function latestRecoveryEvent(detail={},steps=[]){ | |
| const wanted=new Set(steps); | |
| const events=Array.isArray(detail.events)?detail.events:[]; | |
| const runId=String(detail.run_id||detail.summary?.run_id||state.runId||''); | |
| const stableEvents=typeof mergeStableEvents==='function'?mergeStableEvents(runId,events):events; | |
| for(const ev of [...stableEvents].reverse()){ | |
| if(wanted.has(String(ev.step||'')))return ev; | |
| } | |
| return null; | |
| } | |
| function recoverySourceDocuments(detail={}){ | |
| const docs=deriveRunDocuments(detail).filter(d=>d&&d.present&&d.url); | |
| const byId=new Map(docs.map(d=>[d.id,d])); | |
| const links=[]; | |
| const add=(id,label)=>{const d=byId.get(id);if(d&&d.url)links.push({label,url:d.url,tone:d.tone||'',sensitivity:d.sensitivity||''});}; | |
| add('repair_decision','Decision'); | |
| add('blockage','Blockage'); | |
| add('pi_redacted_trace','Pi trace'); | |
| add('pi_raw_trace','RAW trace'); | |
| return links.slice(0,4); | |
| } | |
| function recoveryPhaseLabel(detail={},decision={},blockage={}){ | |
| const summary=detail.summary||{}; | |
| const status=String(summary.status||detail.state?.status||detail.status||'').toLowerCase(); | |
| const terminalFailure=latestRecoveryEvent(detail,['failure']); | |
| if(nonEmptyObject(blockage)||status.includes('blocker')||status.includes('manual'))return'Final blocker'; | |
| if(decision.action&&TERMINAL_STATUSES.has(status))return'Final decision'; | |
| if(terminalFailure&&status.includes('fail')&&!decision.action)return'Recovery interrupted'; | |
| if(latestRecoveryEvent(detail,['repair_validation','generation_smoke','inference_gate']))return'Revalidating'; | |
| if(latestRecoveryEvent(detail,['repair_brief','repair_plan','repair_patch','repair_upload']))return'Repairing'; | |
| if(decision.action)return'Decision made'; | |
| return'Live diagnosis'; | |
| } | |
| function renderAgentRecovery(detail={}){ | |
| const card=$('agentRecoveryCard'); | |
| const body=$('agentRecoveryBody'); | |
| const badge=$('agentRecoveryBadge'); | |
| if(!card||!body)return; | |
| if(!runHasRecoverySignals(detail)){ | |
| card.hidden=true; | |
| body.innerHTML=''; | |
| if(badge){badge.textContent='Not needed';badge.className='badge neutral'} | |
| return; | |
| } | |
| card.hidden=false; | |
| const decision=detail.repair_decision||{}; | |
| const blockage=detail.blockage||{}; | |
| const summary=detail.summary||{}; | |
| const status=summary.status||detail.state?.status||detail.status||''; | |
| const failureEvent=latestRecoveryEvent(detail,['failure']); | |
| const action=decision.action||blockage.recommended_action||blockage.action||''; | |
| const normalizedAction=recoveryDecisionActionLabel(action||(failureEvent?'interrupted':'diagnosis')); | |
| const tone=failureEvent&&!decision.action?'error':recoveryStatusTone(action,status,detail); | |
| if(badge){badge.textContent=normalizedAction;badge.className='badge '+(tone==='success'?'success':tone==='error'?'error':tone==='warn'?'warn':tone==='running'?'running':'neutral')} | |
| const diagnosisEvent=latestRecoveryEvent(detail,['failure_diagnosis','pi_diagnosis','repair_decision']); | |
| const decisionEvent=latestRecoveryEvent(detail,['repair_decision']); | |
| const decisionMade=Boolean(decision.action||decisionEvent); | |
| const rebuildEvent=latestRecoveryEvent(detail,['wait_for_logs','factory_rebuild']); | |
| const patchEvent=latestRecoveryEvent(detail,['repair_brief','repair_plan','repair_patch','repair_upload','repair_validation']); | |
| const failureReason=failureEvent?(failureEvent.reason||failureEvent.error||failureEvent.message||'The worker failed before Pi produced a structured recovery decision.') : ''; | |
| const reason=decision.reason||blockage.reason||blockage.message||failureReason||diagnosisEvent?.message||'Pi diagnosis is coordinating the next recovery action from collected logs, status and validation evidence.'; | |
| const evidence=Array.isArray(decision.evidence)?decision.evidence:[]; | |
| const next=decision.next_step||blockage.suggested_next_step||blockage.next_step||''; | |
| const phase=recoveryPhaseLabel(detail,decision,blockage); | |
| const sourceDocs=recoverySourceDocuments(detail); | |
| const rows=[]; | |
| rows.push(`<div class="recovery-summary"><strong>${escapeHtml(phase)} Β· ${escapeHtml(normalizedAction)}</strong><p>${escapeHtml(shortText(reason,220))}</p></div>`); | |
| const interrupted=Boolean(failureEvent&&!decision.action); | |
| rows.push(`<div class="recovery-ladder" aria-label="Agent recovery phases"> | |
| <span class="${interrupted?'failed':(diagnosisEvent||decision.action?'done':'pending')}"><b>1</b><em>Diagnose</em></span> | |
| <span class="${decisionMade?'done':interrupted?'pending':'pending'}"><b>2</b><em>Decide</em></span> | |
| <span class="${rebuildEvent?'done':patchEvent?'done':decisionMade?'running':'pending'}"><b>3</b><em>${escapeHtml(action&&String(action).includes('rebuild')?'Rebuild':action&&String(action).includes('patch')?'Patch':'Act')}</em></span> | |
| <span class="${latestRecoveryEvent(detail,['repair_validation','generation_smoke','inference_gate'])?'done':failureEvent?'pending':'pending'}"><b>4</b><em>Revalidate</em></span> | |
| </div>`); | |
| const meta=[]; | |
| if(decision.failure_category||blockage.failure_category)meta.push(['Failure',decision.failure_category||blockage.failure_category]); | |
| if(decision.logs_quality||blockage.logs_quality)meta.push(['Logs',decision.logs_quality||blockage.logs_quality]); | |
| if(decision.confidence)meta.push(['Confidence',decision.confidence]); | |
| if(meta.length)rows.push(`<div class="recovery-meta">${meta.map(([k,v])=>`<div><span>${escapeHtml(k)}</span><strong>${escapeHtml(String(v))}</strong></div>`).join('')}</div>`); | |
| if(evidence.length)rows.push(`<ul class="recovery-evidence">${evidence.slice(0,3).map(x=>`<li>${escapeHtml(shortText(x,120))}</li>`).join('')}</ul>`); | |
| if(next)rows.push(`<p class="recovery-next"><strong>Next:</strong> ${escapeHtml(shortText(next,180))}</p>`); | |
| if(sourceDocs.length)rows.push(`<div class="recovery-docs"><span>Sources</span>${sourceDocs.map(d=>`<a href="${escapeHtml(d.url)}" target="_blank" rel="noreferrer" class="${escapeHtml(d.tone||d.sensitivity||'')}">${escapeHtml(d.label)}</a>`).join('')}</div>`); | |
| body.innerHTML=rows.join(''); | |
| } | |
| function renderActiveRunActions(summary={},detail={}){ | |
| const runId=summary.run_id||detail.run_id; | |
| const targetSpace=summary.target_space||detail.state?.target_space||detail.launch?.target_space||''; | |
| const bucket=summary.bucket_source||detail.bucket_source||state.bucketSource; | |
| const artifacts=summary.artifacts_url||(typeof artifactUrl==='function'?artifactUrl(runId,bucket):''); | |
| const jobUrl=inferredJobUrl(summary,detail); | |
| const status=summary.status||detail.status||detail.state?.status||''; | |
| const cancel=$('cancelRun'); | |
| if(cancel){ | |
| const terminal=typeof runIsFinished==='function'?runIsFinished(status):TERMINAL_STATUSES.has(String(status||'').toLowerCase()); | |
| cancel.hidden=Boolean(terminal); | |
| cancel.disabled=Boolean(terminal)||!runId; | |
| } | |
| const spaceUrl=summary.target_space_url||detail.links?.target_space_url||(targetSpace?`https://huggingface.co/spaces/${targetSpace}`:''); | |
| const ready=Boolean(spaceUrl)||(typeof runPassedSpaceCreation==='function'?runPassedSpaceCreation({summary,detail,events:detail.events||[]}):false); | |
| setLink('activeOpenJob',jobUrl); | |
| setLink('activeOpenSpace',ready?spaceUrl:''); | |
| setLink('activeOpenSettings',ready&&spaceUrl?spaceUrl+'/settings':''); | |
| setLink('activeOpenArtifacts',artifacts); | |
| const prefill=$('activePrefillSpaceTest'); | |
| if(prefill){ | |
| const canPrefill=Boolean(targetSpace); | |
| prefill.disabled=!canPrefill; | |
| prefill.title=canPrefill?'Prefill Space Test from this build':'Space Test prefill becomes available as soon as the target Space is known.'; | |
| prefill.onclick=canPrefill?prepareValidationFromActiveRun:null; | |
| } | |
| const del=$('deleteActiveRun'); | |
| if(del){ | |
| const canDelete=Boolean(runId&&runCanBeDeleted(status)); | |
| del.disabled=!canDelete; | |
| del.title=canDelete?'Delete this run folder':'You can delete a run after the Job is finished or if only stale metadata remains.'; | |
| del.onclick=canDelete?()=>deleteRunById(runId,{kind:'active',detail}):null; | |
| } | |
| } | |
| function renderSelectedLinks(summary={},detail={}){renderActiveRunActions(summary,detail)} | |
| function renderBlockers(detail={}){const root=$('selectedBlockers');if(!root)return;const detailRunId=detail.run_id||detail.summary?.run_id||detail.state?.run_id||'';if(detailRunId&&state.runId&&detailRunId!==state.runId){root.hidden=true;root.innerHTML='';return}const summary=detail.summary||{};const blockers=detail.technical_blockers||{};const manual=summary.manual_hardware_required||String(summary.status||'').includes('manual_hardware_required');const blockerItems=(Array.isArray(blockers.blockers)?blockers.blockers:[]).filter(b=>!['patch_code','repair_decision','repair','recovery'].includes(String(b.type||b.name||'').toLowerCase()));const piResolution=detail.pi_model_resolution||detail.state?.pi_model_resolution||summary.pi_model_resolution||{};const piMismatch=Boolean(piResolution.mismatch);if(!manual&&!blockerItems.length&&!piMismatch){root.hidden=true;root.innerHTML='';return}root.hidden=false;const parts=[];if(piMismatch){const requested=piResolution.requested_model||'β';const effective=piResolution.effective_model||'another model';parts.push(`<strong>Pi assistant model changed</strong><p>Requested ${escapeHtml(requested)}; traces show ${escapeHtml(effective)}. Likely Inference Providers routing/fallback.</p>`)}if(manual)parts.push('<strong>Manual hardware required</strong><p>Open Space settings, choose the recommended GPU, then run validation.</p>');for(const b of blockerItems.slice(0,4)){parts.push(`<strong>${escapeHtml(shortText(b.type||b.name||'Technical blocker',32))}</strong><p>${escapeHtml(shortText(b.claim||b.reason||b.message||'',120))}</p>`)}root.innerHTML=parts.join('')} | |
| function evalPublishHumanReason(reason){ | |
| const value=String(reason||'').toLowerCase(); | |
| const map={ | |
| eval_archive_disabled:'Eval archive is disabled for this instance.', | |
| eval_mount_missing:'Eval archive mount is missing on the ASF Space.', | |
| eval_mount_not_directory:'Eval archive mount exists but is not a directory.', | |
| record_not_ready:'Run-local eval_record.json is not ready yet.', | |
| invalid_record:'Run-local eval record is invalid.', | |
| run_not_terminal:'The run is not terminal yet; archive copy is waiting.', | |
| privacy_flags_rejected:'Privacy flags rejected the eval record.', | |
| already_published:'This eval record was already published.' | |
| }; | |
| return map[value]||String(reason||'Archive status unavailable.').replace(/_/g,' '); | |
| } | |
| function renderEvalArchiveStatus(detail={}){ | |
| const card=$('runEvalArchiveCard'); | |
| const body=$('evalArchiveBody'); | |
| const badge=$('evalArchiveBadge'); | |
| if(!card||!body)return; | |
| const status=detail.eval_publish||detail.eval_publish_status||{}; | |
| const hasStatus=status&&typeof status==='object'&&Object.keys(status).length>0; | |
| if(!hasStatus){card.hidden=true;body.innerHTML='';return;} | |
| card.hidden=false; | |
| const published=Boolean(status.published); | |
| const enabled=status.enabled!==false; | |
| const attempted=Boolean(status.attempted||status.checked_at||status.reason); | |
| const tone=published?'success':enabled?(attempted?'warn':'neutral'):'neutral'; | |
| const label=published?'Published':enabled?(attempted?'Not published':'Pending'):'Disabled'; | |
| if(badge){badge.textContent=label;badge.className='badge '+(tone==='success'?'success':tone==='warn'?'warn':'neutral')} | |
| const reason=published?'Eval record copied to the operator archive bucket.':evalPublishHumanReason(status.reason); | |
| const local=status.local_record_found===false?'missing':status.local_record_found===true?'written':'unknown'; | |
| const archivePath=status.archive_relative_path||status.archive_path||''; | |
| const rows=[ | |
| ['Local record',local], | |
| ['Backend copy',published?'published':attempted?'attempted':'not checked'], | |
| ['Mode',status.publish_mode||'backend'], | |
| ['Archive bucket',status.eval_bucket_source||'β'] | |
| ]; | |
| body.innerHTML=`<p>${escapeHtml(reason)}</p><div class="eval-archive-meta">${rows.map(([k,v])=>`<div><span>${escapeHtml(k)}</span><strong title="${escapeHtml(String(v))}">${escapeHtml(String(v||'β'))}</strong></div>`).join('')}</div>${archivePath?`<div class="eval-archive-path" title="${escapeHtml(String(archivePath))}">${escapeHtml(String(archivePath))}</div>`:''}`; | |
| } | |
| function renderRunDetail(detail){ | |
| state.selectedRunDetail=detail; | |
| const summary=detail.summary||{}; | |
| const smoke=detail.generation_smoke||{}; | |
| const files=detail.files||[]; | |
| const view=detail.view||{}; | |
| const header=view.header||{}; | |
| const runId=summary.run_id||detail.run_id; | |
| setText('selectedModelId',summary.model_id||header.model||'β'); | |
| setText('homeRunDetailStatus',header.status_label||summary.status||detail.status||'unknown'); | |
| setText('detailRunId',runId||'β'); | |
| setText('detailJobStatus',summary.status||detail.status||'β'); | |
| setText('detailGateStatus',(detail.inference_gate||{}).status||summary.status||'β'); | |
| setText('detailSpace',summary.target_space||detail.state?.target_space||'β'); | |
| const mode=runImplementationMode(summary,detail); | |
| setText('detailImplementationMode',mode?implementationModeLabel(mode):'β'); | |
| const modeEl=$('detailImplementationMode'); | |
| if(modeEl&&mode){modeEl.title=implementationModeDescription(mode)} | |
| setText('detailHardware',summary.selected_hardware||summary.hardware||detail.state?.selected_hardware||'β'); | |
| if(typeof renderActiveRunMeta==='function')renderActiveRunMeta({...detail,summary}); | |
| setText('detailTraces',summary._optimistic?'Loading detailsβ¦':(Array.isArray(detail.events)?String(detail.events.length)+' events':summary.traces_count||'β')); | |
| const validation=$('selectedValidation'); | |
| if(validation){validation.innerHTML=`<li><span>Health</span><strong>${summary.health_passed?'passed':'β'}</strong></li><li><span>Smoke test</span><strong>${summary.smoke_test_passed?'passed':(smoke.status||'β')}</strong></li><li><span>Latency</span><strong>${summary.latency_seconds?fmtSeconds(Math.round(summary.latency_seconds)):'β'}</strong></li>`} | |
| const artifactRoot=$('artifactList'); | |
| if(artifactRoot){const interesting=files.filter(f=>!/traces\//.test(f.path||'')).slice(0,18);artifactRoot.innerHTML=interesting.length?interesting.map(f=>`<a href="${escapeHtml(f.url)}" target="_blank"><span>${escapeHtml(f.path)}</span><em>${f.size?Math.round(Number(f.size)/1024)+' KB':''}</em></a>`).join(''):'No artifacts indexed yet.'} | |
| const reportText=(detail.report||'No report available.').slice(0,8000); | |
| const report=$('reportPreview'); | |
| if(report)report.textContent=reportText; | |
| setQuickLinks({job_url:inferredJobUrl(summary,detail),target_space_url:summary.target_space_url,target_space_settings_url:summary.target_space_url?summary.target_space_url+'/settings':'',artifacts_url:summary.artifacts_url,bucket_source:detail.bucket_source,run_id:runId},{summary,detail,events:detail.events||[]}); | |
| renderActiveRunActions({...summary,bucket_source:detail.bucket_source},detail); | |
| renderBlockers(detail); | |
| renderAgentRecovery(detail); | |
| renderEvalArchiveStatus(detail); | |
| renderRunDocuments(detail); | |
| renderMetrics({...detail,summary}); | |
| /* v71: avoid rendering stale view.pipeline before /progress returns canonical compact timeline. */ | |
| switchCenterTab('active'); | |
| } | |
| // Build run routing invariant: switchCenterTab('active');setBuildModeInspecting(runId);startPolling(runId) | |
| // Legacy route invariant: startPolling(runId);renderRunDetail(detail) | |
| // Legacy wording: Validation latency / Aggregated issues | |
| // Legacy invariant: state.runsCache=sortRunsNewestFirst(data.runs||[]) | |