Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Upload 7 files
Browse files- web/static/app.css +1 -0
- web/static/app.js +14 -5
- web/static/runs.js +20 -2
web/static/app.css
CHANGED
|
@@ -2599,6 +2599,7 @@ strong,p,h1,h2,h3,h4,span,a,button,div,li{overflow-wrap:break-word;word-break:no
|
|
| 2599 |
}
|
| 2600 |
|
| 2601 |
|
|
|
|
| 2602 |
/* v190.5 — Active Run timeline hotfix: horizontal canonical row + restored active pulse */
|
| 2603 |
@media (min-width:521px){
|
| 2604 |
.timeline.timeline-canonical{
|
|
|
|
| 2599 |
}
|
| 2600 |
|
| 2601 |
|
| 2602 |
+
/* v190.6 — Active Run timeline hotfix (carried forward from v190.5) */
|
| 2603 |
/* v190.5 — Active Run timeline hotfix: horizontal canonical row + restored active pulse */
|
| 2604 |
@media (min-width:521px){
|
| 2605 |
.timeline.timeline-canonical{
|
web/static/app.js
CHANGED
|
@@ -496,9 +496,12 @@ function parseJsonField(id,fallback){const raw=formValue(id);if(!raw)return fall
|
|
| 496 |
function prettyJson(value){return JSON.stringify(value,null,2)}
|
| 497 |
function validateValidationForm(){if(!formValue('validateSpace'))return'Enter the target Space ID to validate.';try{const args=parseJsonField('testArgs',[]);const kwargs=parseJsonField('testKwargs',{});if(!Array.isArray(args))return'Test args must be a JSON array because they are passed as positional arguments to gradio_client.predict(...).';if(!kwargs||Array.isArray(kwargs)||typeof kwargs!=='object')return'Test kwargs must be a JSON object because they are passed as keyword arguments.'}catch(e){return`Invalid JSON payload: ${e.message}`}return''}
|
| 498 |
function validationIsTerminalStatus(status){const canonical=String(status||'').toLowerCase();return ['full_inference_success','partial_validation','manual_hardware_required','failed','stale','stopped'].includes(canonical)}
|
|
|
|
| 499 |
function validationDetailRunId(detail={}){return detail.run_id||detail.summary?.run_id||detail.state?.run_id||detail.launch?.run_id||''}
|
| 500 |
-
function rememberTerminalValidation(detail={}){const runId=validationDetailRunId(detail)||state.validationRunId;const canonical=validationCanonicalStatus(detail);if(runId&&validationIsTerminalStatus(canonical))state.validationTerminalByRun[runId]={canonical,detail};return canonical}
|
| 501 |
-
function
|
|
|
|
|
|
|
| 502 |
function extractEffectiveValidationPayload(detail={}){const smoke=detail.generation_smoke||detail.summary?.generation_smoke||detail.state?.generation_smoke||{};const payload=detail.validation_payload||detail.tests?.validation_payload||detail.summary?.validation_payload||{};const args=firstArrayPath(detail.effective_args,smoke.effective_args,payload.effective_args,smoke.test_args,payload.test_args);const kwargs=firstObjectPath(detail.effective_kwargs,smoke.effective_kwargs,payload.effective_kwargs,smoke.test_kwargs,payload.test_kwargs);const source=detail.args_source||smoke.args_source||payload.args_source||'';return {args,kwargs,source,argsWereAutofilled:Boolean(detail.args_were_autofilled||smoke.args_were_autofilled||payload.args_were_autofilled||source==='gradio_schema_auto_fill')};}
|
| 503 |
function applyEffectiveValidationArgs(detail={}){const payload=extractEffectiveValidationPayload(detail);if(!payload.argsWereAutofilled||!Array.isArray(payload.args))return;if(state.validationArgsDirty)return;setInputValue('testArgs',prettyJson(payload.args));if(payload.kwargs&&typeof payload.kwargs==='object'&&!Array.isArray(payload.kwargs))setInputValue('testKwargs',prettyJson(payload.kwargs));const note=$('spaceTestArgsNote');if(note){note.hidden=false;note.textContent='Arguments filled from discovered Gradio schema.';} }
|
| 504 |
function setBuildModeNew(){const panel=$('buildModePanel');if(panel){panel.classList.remove('inspecting');panel.innerHTML='<strong>Preparing a new build</strong><p>This form launches new builds. Existing runs can be inspected in the Runs Explorer on the right.</p>'}const launch=$('launchResultPanel');if(launch)launch.hidden=true;const status=$('progressStatus');if(status){status.textContent='Idle';status.className='badge neutral'}setText('progressTitle','No run selected')}
|
|
@@ -732,6 +735,8 @@ function validationPrefillFromDetail(detail={}){
|
|
| 732 |
return {target,api,expected,args,kwargs};
|
| 733 |
}
|
| 734 |
function renderValidationStatus(data={}){
|
|
|
|
|
|
|
| 735 |
state.validationDetail=data||state.validationDetail;
|
| 736 |
const summary=data.summary||{};
|
| 737 |
const smoke=data.generation_smoke||data.summary?.generation_smoke||data.state?.generation_smoke||{};
|
|
@@ -753,7 +758,7 @@ function renderValidationStatus(data={}){
|
|
| 753 |
setText('validationStartedAt',formatTime(data.updated_at||summary.updated_at||data.state?.updated_at||data.created_at||summary.created_at||new Date().toISOString()));
|
| 754 |
const latency=firstPositiveNumber(smoke.latency_seconds,smoke.observed_latency_seconds,summary.latency_seconds,summary.observed_latency_seconds,data.latency_seconds,data.observed_latency_seconds);
|
| 755 |
setText('spaceTestLatency',latency?formatLatencySeconds(latency):(canonical==='running'?'—':'Not recorded'));
|
| 756 |
-
setText('spaceTestVerdict',badgeLabel(displayStatus));
|
| 757 |
const launchBtn=$('launchValidate');
|
| 758 |
if(launchBtn&&!launchBtn.classList.contains('is-busy'))launchBtn.textContent=runId&&runId!=='—'&&!isRunning?'Run validation again':'Launch validation';
|
| 759 |
if(launchBtn)launchBtn.disabled=state.busy||isRunning;
|
|
@@ -784,7 +789,9 @@ function renderValidationTimeline(detail={}){
|
|
| 784 |
}).join('')||'<div class="empty">No validation events yet.</div>';
|
| 785 |
}
|
| 786 |
function showValidationRunDetail(detail={}){
|
| 787 |
-
|
|
|
|
|
|
|
| 788 |
state.validationMode='view';
|
| 789 |
state.validationDetail=detail;
|
| 790 |
state.validationPrefillDraft=null;
|
|
@@ -805,7 +812,7 @@ async function refreshValidationProgress(pollToken=state.validationPollToken){
|
|
| 805 |
try{
|
| 806 |
const p=await apiGet(`/api/runs/${encodeURIComponent(requestedRunId)}/progress?bucket_name=${encodeURIComponent(state.bucketName)}&include_job_logs=1`);
|
| 807 |
if(pollToken!==state.validationPollToken||requestedRunId!==state.validationRunId)return;
|
| 808 |
-
if(shouldIgnoreValidationUpdate(p,requestedRunId))return;
|
| 809 |
state.validationPollErrors=0;
|
| 810 |
renderValidationStatus(p);
|
| 811 |
const canonical=validationCanonicalStatus(p);
|
|
@@ -818,6 +825,8 @@ async function refreshValidationProgress(pollToken=state.validationPollToken){
|
|
| 818 |
}
|
| 819 |
}
|
| 820 |
function startValidationPolling(runId){
|
|
|
|
|
|
|
| 821 |
stopValidationPolling();
|
| 822 |
state.validationMode='running';
|
| 823 |
state.validationRunId=runId;
|
|
|
|
| 496 |
function prettyJson(value){return JSON.stringify(value,null,2)}
|
| 497 |
function validateValidationForm(){if(!formValue('validateSpace'))return'Enter the target Space ID to validate.';try{const args=parseJsonField('testArgs',[]);const kwargs=parseJsonField('testKwargs',{});if(!Array.isArray(args))return'Test args must be a JSON array because they are passed as positional arguments to gradio_client.predict(...).';if(!kwargs||Array.isArray(kwargs)||typeof kwargs!=='object')return'Test kwargs must be a JSON object because they are passed as keyword arguments.'}catch(e){return`Invalid JSON payload: ${e.message}`}return''}
|
| 498 |
function validationIsTerminalStatus(status){const canonical=String(status||'').toLowerCase();return ['full_inference_success','partial_validation','manual_hardware_required','failed','stale','stopped'].includes(canonical)}
|
| 499 |
+
function validationIsNonTerminalStatus(status){const canonical=String(status||'').toLowerCase();return !canonical||['running','pending','waiting','started','queued','building','unknown'].includes(canonical)}
|
| 500 |
function validationDetailRunId(detail={}){return detail.run_id||detail.summary?.run_id||detail.state?.run_id||detail.launch?.run_id||''}
|
| 501 |
+
function rememberTerminalValidation(detail={}){const runId=validationDetailRunId(detail)||state.validationRunId;const canonical=validationCanonicalStatus(detail);if(runId&&validationIsTerminalStatus(canonical)){state.validationTerminalByRun=state.validationTerminalByRun||{};state.validationTerminalByRun[runId]={canonical,detail:{...detail,_terminalLocked:true}};}return canonical}
|
| 502 |
+
function terminalValidationForRun(runId=state.validationRunId){return runId&&state.validationTerminalByRun?state.validationTerminalByRun[runId]||null:null}
|
| 503 |
+
function mergeValidationWithTerminalLock(incoming={},runId=state.validationRunId){const terminal=terminalValidationForRun(runId);if(!terminal)return incoming;const incomingCanonical=validationCanonicalStatus(incoming);if(validationIsNonTerminalStatus(incomingCanonical)){return {...(terminal.detail||{}),_refreshing:true,_ignoredIncomingStatus:incomingCanonical};}return incoming;}
|
| 504 |
+
function shouldIgnoreValidationUpdate(incoming={},runId=state.validationRunId){const incomingCanonical=validationCanonicalStatus(incoming);const terminal=terminalValidationForRun(runId);if(terminal&&incomingCanonical==='running')return true;return Boolean(terminal&&validationIsNonTerminalStatus(incomingCanonical));}
|
| 505 |
function extractEffectiveValidationPayload(detail={}){const smoke=detail.generation_smoke||detail.summary?.generation_smoke||detail.state?.generation_smoke||{};const payload=detail.validation_payload||detail.tests?.validation_payload||detail.summary?.validation_payload||{};const args=firstArrayPath(detail.effective_args,smoke.effective_args,payload.effective_args,smoke.test_args,payload.test_args);const kwargs=firstObjectPath(detail.effective_kwargs,smoke.effective_kwargs,payload.effective_kwargs,smoke.test_kwargs,payload.test_kwargs);const source=detail.args_source||smoke.args_source||payload.args_source||'';return {args,kwargs,source,argsWereAutofilled:Boolean(detail.args_were_autofilled||smoke.args_were_autofilled||payload.args_were_autofilled||source==='gradio_schema_auto_fill')};}
|
| 506 |
function applyEffectiveValidationArgs(detail={}){const payload=extractEffectiveValidationPayload(detail);if(!payload.argsWereAutofilled||!Array.isArray(payload.args))return;if(state.validationArgsDirty)return;setInputValue('testArgs',prettyJson(payload.args));if(payload.kwargs&&typeof payload.kwargs==='object'&&!Array.isArray(payload.kwargs))setInputValue('testKwargs',prettyJson(payload.kwargs));const note=$('spaceTestArgsNote');if(note){note.hidden=false;note.textContent='Arguments filled from discovered Gradio schema.';} }
|
| 507 |
function setBuildModeNew(){const panel=$('buildModePanel');if(panel){panel.classList.remove('inspecting');panel.innerHTML='<strong>Preparing a new build</strong><p>This form launches new builds. Existing runs can be inspected in the Runs Explorer on the right.</p>'}const launch=$('launchResultPanel');if(launch)launch.hidden=true;const status=$('progressStatus');if(status){status.textContent='Idle';status.className='badge neutral'}setText('progressTitle','No run selected')}
|
|
|
|
| 735 |
return {target,api,expected,args,kwargs};
|
| 736 |
}
|
| 737 |
function renderValidationStatus(data={}){
|
| 738 |
+
const candidateRunId=validationDetailRunId(data)||state.validationRunId;
|
| 739 |
+
data=mergeValidationWithTerminalLock(data||state.validationDetail||{},candidateRunId);
|
| 740 |
state.validationDetail=data||state.validationDetail;
|
| 741 |
const summary=data.summary||{};
|
| 742 |
const smoke=data.generation_smoke||data.summary?.generation_smoke||data.state?.generation_smoke||{};
|
|
|
|
| 758 |
setText('validationStartedAt',formatTime(data.updated_at||summary.updated_at||data.state?.updated_at||data.created_at||summary.created_at||new Date().toISOString()));
|
| 759 |
const latency=firstPositiveNumber(smoke.latency_seconds,smoke.observed_latency_seconds,summary.latency_seconds,summary.observed_latency_seconds,data.latency_seconds,data.observed_latency_seconds);
|
| 760 |
setText('spaceTestLatency',latency?formatLatencySeconds(latency):(canonical==='running'?'—':'Not recorded'));
|
| 761 |
+
setText('spaceTestVerdict',data._refreshing?`${badgeLabel(displayStatus)} · Refreshing…`:badgeLabel(displayStatus));
|
| 762 |
const launchBtn=$('launchValidate');
|
| 763 |
if(launchBtn&&!launchBtn.classList.contains('is-busy'))launchBtn.textContent=runId&&runId!=='—'&&!isRunning?'Run validation again':'Launch validation';
|
| 764 |
if(launchBtn)launchBtn.disabled=state.busy||isRunning;
|
|
|
|
| 789 |
}).join('')||'<div class="empty">No validation events yet.</div>';
|
| 790 |
}
|
| 791 |
function showValidationRunDetail(detail={}){
|
| 792 |
+
const incomingRunId=detail.run_id||detail.summary?.run_id||state.validationRunId;
|
| 793 |
+
state.validationRunId=incomingRunId;
|
| 794 |
+
detail=mergeValidationWithTerminalLock(detail,incomingRunId);
|
| 795 |
state.validationMode='view';
|
| 796 |
state.validationDetail=detail;
|
| 797 |
state.validationPrefillDraft=null;
|
|
|
|
| 812 |
try{
|
| 813 |
const p=await apiGet(`/api/runs/${encodeURIComponent(requestedRunId)}/progress?bucket_name=${encodeURIComponent(state.bucketName)}&include_job_logs=1`);
|
| 814 |
if(pollToken!==state.validationPollToken||requestedRunId!==state.validationRunId)return;
|
| 815 |
+
if(shouldIgnoreValidationUpdate(p,requestedRunId)){const terminal=terminalValidationForRun(requestedRunId);if(terminal){renderValidationStatus({...terminal.detail,_refreshing:true});stopValidationPolling();loadRuns(false);}return;}
|
| 816 |
state.validationPollErrors=0;
|
| 817 |
renderValidationStatus(p);
|
| 818 |
const canonical=validationCanonicalStatus(p);
|
|
|
|
| 825 |
}
|
| 826 |
}
|
| 827 |
function startValidationPolling(runId){
|
| 828 |
+
const terminal=terminalValidationForRun(runId);
|
| 829 |
+
if(terminal){stopValidationPolling();state.validationMode='view';state.validationRunId=runId;renderValidationStatus({...terminal.detail,_refreshing:true});return;}
|
| 830 |
stopValidationPolling();
|
| 831 |
state.validationMode='running';
|
| 832 |
state.validationRunId=runId;
|
web/static/runs.js
CHANGED
|
@@ -8,8 +8,15 @@ function runValidationTerminalText(run={}){
|
|
| 8 |
run.generation_smoke?.status,run.summary?.smoke_status,run.smoke_status,run.details?.error,run.error,run.message
|
| 9 |
].map(x=>String(x||'').toLowerCase()).filter(Boolean).join(' ');
|
| 10 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
function runCanonicalStatus(run={}){
|
| 12 |
const validation=isValidationRunSummary(run);
|
|
|
|
|
|
|
| 13 |
const s=String(run.status||run.summary?.status||run.state?.status||'unknown').toLowerCase();
|
| 14 |
const gate=String(run.gate_status||run.inference_gate?.status||run.summary?.gate_status||'').toLowerCase();
|
| 15 |
const smoke=String(run.smoke_status||run.generation_smoke?.status||run.summary?.smoke_status||'').toLowerCase();
|
|
@@ -323,8 +330,19 @@ function bindRunRowEvents(root){
|
|
| 323 |
e.preventDefault();selectRun(row.dataset.run);
|
| 324 |
});
|
| 325 |
}
|
| 326 |
-
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))}
|
| 327 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
function cachedRunById(runId){
|
| 329 |
if(isRunLocallyDeleted(runId))return null;
|
| 330 |
return (state.runsCache||[]).find(r=>r.run_id===runId)||null;
|
|
|
|
| 8 |
run.generation_smoke?.status,run.summary?.smoke_status,run.smoke_status,run.details?.error,run.error,run.message
|
| 9 |
].map(x=>String(x||'').toLowerCase()).filter(Boolean).join(' ');
|
| 10 |
}
|
| 11 |
+
function validationLockedStatus(run={}){
|
| 12 |
+
const runId=run.run_id||run.summary?.run_id||run.state?.run_id||'';
|
| 13 |
+
const terminal=runId&&typeof state!=='undefined'&&state.validationTerminalByRun?state.validationTerminalByRun[runId]:null;
|
| 14 |
+
return terminal?.canonical||'';
|
| 15 |
+
}
|
| 16 |
function runCanonicalStatus(run={}){
|
| 17 |
const validation=isValidationRunSummary(run);
|
| 18 |
+
const locked=validation?validationLockedStatus(run):'';
|
| 19 |
+
if(locked)return locked;
|
| 20 |
const s=String(run.status||run.summary?.status||run.state?.status||'unknown').toLowerCase();
|
| 21 |
const gate=String(run.gate_status||run.inference_gate?.status||run.summary?.gate_status||'').toLowerCase();
|
| 22 |
const smoke=String(run.smoke_status||run.generation_smoke?.status||run.summary?.smoke_status||'').toLowerCase();
|
|
|
|
| 330 |
e.preventDefault();selectRun(row.dataset.run);
|
| 331 |
});
|
| 332 |
}
|
| 333 |
+
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,runCanonicalStatus(r),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))}
|
| 334 |
+
|
| 335 |
+
function mergeRunExplorerTerminalLocks(runs=[]){
|
| 336 |
+
if(typeof state==='undefined'||!state.validationTerminalByRun)return runs||[];
|
| 337 |
+
return (runs||[]).map(run=>{
|
| 338 |
+
const validation=isValidationRunSummary(run);
|
| 339 |
+
const runId=run.run_id||run.summary?.run_id||'';
|
| 340 |
+
const terminal=validation&&runId?state.validationTerminalByRun[runId]:null;
|
| 341 |
+
if(!terminal)return run;
|
| 342 |
+
return {...run,status:terminal.canonical,validation_status:terminal.canonical,result_status:terminal.canonical,summary:{...(run.summary||{}),status:terminal.canonical,validation_status:terminal.canonical,result_status:terminal.canonical}};
|
| 343 |
+
});
|
| 344 |
+
}
|
| 345 |
+
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(mergeRunExplorerTerminalLocks((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}
|
| 346 |
function cachedRunById(runId){
|
| 347 |
if(isRunLocallyDeleted(runId))return null;
|
| 348 |
return (state.runsCache||[]).find(r=>r.run_id===runId)||null;
|