fffiloni commited on
Commit
d0be82c
·
verified ·
1 Parent(s): c7ea0c0

Upload 7 files

Browse files
Files changed (2) hide show
  1. web/static/app.css +95 -0
  2. web/static/app.js +27 -9
web/static/app.css CHANGED
@@ -2261,3 +2261,98 @@ strong,p,h1,h2,h3,h4,span,a,button,div,li{overflow-wrap:break-word;word-break:no
2261
  .model-prescan-card.running #scanModel{padding:7px 10px!important;font-size:11.5px!important;border-radius:12px!important}
2262
  .model-prescan-card.error #scanModel{border-color:rgba(244,63,94,.18)!important;background:linear-gradient(180deg,#fff,#fff7f7)!important}
2263
  @media(prefers-reduced-motion:reduce){.prescan-spinner{animation:none!important}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2261
  .model-prescan-card.running #scanModel{padding:7px 10px!important;font-size:11.5px!important;border-radius:12px!important}
2262
  .model-prescan-card.error #scanModel{border-color:rgba(244,63,94,.18)!important;background:linear-gradient(180deg,#fff,#fff7f7)!important}
2263
  @media(prefers-reduced-motion:reduce){.prescan-spinner{animation:none!important}}
2264
+
2265
+ /* v186: Eval Archive breathing room + less redundant Model pre-scan summary */
2266
+ .eval-archive-panel{
2267
+ padding:16px!important;
2268
+ display:grid!important;
2269
+ gap:10px!important;
2270
+ }
2271
+ .eval-archive-title-row{
2272
+ margin-bottom:2px!important;
2273
+ align-items:flex-start!important;
2274
+ }
2275
+ .eval-archive-title-row .badge{
2276
+ align-self:start!important;
2277
+ margin-top:0!important;
2278
+ }
2279
+ .eval-archive-summary{
2280
+ margin:0!important;
2281
+ max-width:100%!important;
2282
+ line-height:1.35!important;
2283
+ }
2284
+ .eval-archive-actions{
2285
+ margin-top:8px!important;
2286
+ padding-top:12px!important;
2287
+ border-top:1px solid rgba(226,232,240,.72)!important;
2288
+ gap:10px!important;
2289
+ }
2290
+ .eval-archive-panel.on .eval-archive-actions{border-top-color:rgba(34,197,94,.14)!important}
2291
+ .eval-archive-actions button{
2292
+ min-height:36px!important;
2293
+ padding:8px 12px!important;
2294
+ }
2295
+
2296
+ .model-prescan-card{
2297
+ gap:9px!important;
2298
+ }
2299
+ .model-prescan-card.success{
2300
+ padding:13px!important;
2301
+ }
2302
+ .model-prescan-card.success>p{
2303
+ max-width:52ch!important;
2304
+ }
2305
+ .prescan-compact-grid{
2306
+ grid-template-columns:repeat(3,minmax(0,1fr))!important;
2307
+ gap:6px!important;
2308
+ }
2309
+ .prescan-chip{
2310
+ padding:7px 8px!important;
2311
+ border-radius:13px!important;
2312
+ }
2313
+ .prescan-chip i{
2314
+ width:21px!important;
2315
+ height:21px!important;
2316
+ font-size:11px!important;
2317
+ }
2318
+ .prescan-chip em{font-size:8px!important}
2319
+ .prescan-chip strong{font-size:11px!important}
2320
+ .prescan-decision-line{
2321
+ display:flex!important;
2322
+ align-items:flex-start!important;
2323
+ gap:8px!important;
2324
+ padding:8px 10px!important;
2325
+ border-radius:14px!important;
2326
+ border:1px solid rgba(226,232,240,.84)!important;
2327
+ background:rgba(255,255,255,.78)!important;
2328
+ color:#475569!important;
2329
+ font-size:11.25px!important;
2330
+ line-height:1.25!important;
2331
+ min-width:0!important;
2332
+ }
2333
+ .prescan-decision-line b{
2334
+ flex:0 0 auto!important;
2335
+ color:#0f172a!important;
2336
+ font-size:10px!important;
2337
+ text-transform:uppercase!important;
2338
+ letter-spacing:.12em!important;
2339
+ }
2340
+ .prescan-decision-line span{
2341
+ min-width:0!important;
2342
+ overflow:hidden!important;
2343
+ text-overflow:ellipsis!important;
2344
+ display:-webkit-box!important;
2345
+ -webkit-line-clamp:2!important;
2346
+ -webkit-box-orient:vertical!important;
2347
+ }
2348
+ .prescan-decision-line.success{border-color:rgba(34,197,94,.18)!important;background:rgba(240,253,244,.55)!important}
2349
+ .prescan-decision-line.warn{border-color:rgba(245,158,11,.20)!important;background:rgba(255,251,235,.62)!important}
2350
+ .prescan-decision-line.error{border-color:rgba(244,63,94,.18)!important;background:rgba(255,241,242,.62)!important}
2351
+ .prescan-decision-line.running{border-color:rgba(37,99,235,.16)!important;background:rgba(239,246,255,.58)!important}
2352
+ .model-prescan-card.success .prescan-pill-row .prescan-pill.good{display:none!important}
2353
+ .model-prescan-card.success .model-prescan-signals{gap:7px!important}
2354
+ .model-prescan-card.success #scanModel{margin-top:1px!important}
2355
+ @media(max-width:720px){
2356
+ .eval-archive-actions{padding-top:10px!important}
2357
+ .prescan-decision-line{display:grid!important;gap:4px!important}
2358
+ }
web/static/app.js CHANGED
@@ -323,11 +323,13 @@ function renderModelPreScan(scan=null){
323
  setText('modelPreScanTitle',`${labelMap[verdict]||labelMap.caution}${scoreText}`);
324
  setText('modelPreScanSummary',scan.summary||'Model metadata scan completed.');
325
  if(badge){badge.textContent=labelMap[verdict]||verdict;badge.className='badge '+cls}
326
- const good=(scan.good_signals||[]).slice(0,4);
327
- const risk=(scan.risk_signals||[]).slice(0,4);
 
 
328
  const outputType=outputTypeFromModelScan(scan);
329
- const recs=[...(scan.recommendations||[]).slice(0,2)];
330
- if(outputType&&!recs.some(x=>String(x).toLowerCase().includes('expected output')))recs.unshift(`Expected output: ${outputType}`);
331
  if(signals){
332
  const metaCards=[
333
  outputType?['↳','Output',outputType,verdict==='safe']:null,
@@ -335,14 +337,20 @@ function renderModelPreScan(scan=null){
335
  scan.library_name?['◎','Library',scan.library_name,false]:null,
336
  ].filter(Boolean).slice(0,3);
337
  const compactMeta=metaCards.length?`<div class="prescan-meta prescan-compact-grid">${metaCards.map(([icon,k,v,isGood])=>`<span class="prescan-chip ${isGood?'good':''}"><i>${escapeHtml(icon)}</i><em>${escapeHtml(k)}</em><strong>${escapeHtml(String(v))}</strong></span>`).join('')}</div>`:'';
338
- const goodPills=good.length?`<div class="prescan-pill-row">${good.map(x=>`<span class="prescan-pill good"><b class="prescan-icon">✓</b>${escapeHtml(x)}</span>`).join('')}</div>`:'';
 
 
 
 
 
 
 
339
  const riskPills=risk.length?`<div class="prescan-pill-row">${risk.map(x=>`<span class="prescan-pill risk"><b class="prescan-icon">!</b>${escapeHtml(x)}</span>`).join('')}</div>`:'';
340
  const runningPills=verdict==='scanning'?'<div class="prescan-pill-row"><span class="prescan-pill running"><b class="prescan-icon prescan-spinner">◌</b>Reading model card</span><span class="prescan-pill running"><b class="prescan-icon">◇</b>Checking metadata</span></div>':'';
341
  const errorPill=verdict==='error'?`<div class="prescan-pill-row"><span class="prescan-pill risk"><b class="prescan-icon">!</b>${escapeHtml(scan.error||'The scan could not complete. Try again.')}</span></div>`:'';
342
- const recLine=recs.length?`<div class="prescan-recommendation-line ${cls}"><b>Recommendation</b><span>${escapeHtml(recs[0])}${recs.length>1?` · ${escapeHtml(recs.slice(1).join(' · '))}`:''}</span></div>`:'';
343
- const emptyHint=(!compactMeta&&!goodPills&&!riskPills&&!runningPills&&!errorPill&&!recLine)?'<div class="prescan-pill-row"><span class="prescan-pill"><b class="prescan-icon">◇</b>No extra metadata found.</span></div>':'';
344
  signals.hidden=false;
345
- signals.innerHTML=`${compactMeta}${runningPills}${goodPills}${riskPills}${errorPill}${recLine}${emptyHint}`;
346
  }
347
  if(ackWrap)ackWrap.hidden=!(verdict==='risky');
348
  }
@@ -419,7 +427,17 @@ function startPolling(runId,options={}){
419
  }
420
  async function bootstrapRunRecovery(){return restoreActiveRun()}
421
  async function restoreActiveRun(){try{const resumable=await apiGet(`/api/runs/resumable?bucket_name=${encodeURIComponent(state.bucketName)}`);if(resumable?.run?.run_id){state.runId=resumable.run.run_id;if(resumable.bucket_source)state.bucketSource=resumable.bucket_source;setBuildModeInspecting(state.runId);if(resumable.view)renderRunViewModel(resumable.view,{progress:0,events:[]});setQuickLinks(resumable.view?.links||{},resumable.view||{});startPolling(state.runId);return true}}catch(e){console.warn('resumable lookup failed',e)}try{const raw=localStorage.getItem('asf.activeRun');if(!raw)return false;const saved=JSON.parse(raw);if(saved?.bucketName)state.bucketName=saved.bucketName;if(saved?.runId){state.runId=saved.runId;setText('detailRunId',saved.runId);setQuickLinks(saved.links||{},{});setBuildModeInspecting(saved.runId);startPolling(saved.runId);return true}}catch(_){}return false}
422
- async function loadAppInfo(){setOperation('Checking sign-in and run storage…','loading');setBucketFeedback('checking','Checking private bucket access…');try{const me=await apiGet('/api/me');state.user=me;renderAnonymousEvalStatus(me);setText('userChip','@'+me.username);const userChip=$('userChip');if(userChip)userChip.href=`https://huggingface.co/${me.username}`;const logout=$('logoutLink');if(logout){logout.hidden=false;logout.href=me.logout_url||'/logout'}state.bucketSource=me.username+'/'+state.bucketName;setText('bucketInlineLabel',state.bucketSource);renderAuthWarnings(me);renderBillingPanel(me);loadBillingStatus().catch(()=>{});await checkBucket(false);await loadRuns(true);clearSavedRun();if(!state.bucketReady)setOperation('Create your private run bucket before launching builds.','warning');else setOperation('')}catch(e){state.user=null;renderAnonymousEvalStatus(null);setText('userChip','Sign in');const userChip=$('userChip');if(userChip)userChip.href='/oauth/huggingface/login';const logout=$('logoutLink');if(logout)logout.hidden=true;renderSignedOut();renderBillingPanel(null);setBucketReady(false,'Sign in with Hugging Face first.');showMessage('Please sign in with Hugging Face, then refresh this page.',true)}}
 
 
 
 
 
 
 
 
 
 
423
  function renderSignedOut(){const auth=$('authPanel');if(!auth)return;auth.hidden=false;auth.className='auth-panel warning';auth.innerHTML='<strong>Sign in required</strong><p>Use Hugging Face OAuth before launching Jobs or reading your Bucket.</p><a class="link-btn" href="/oauth/huggingface/login">Sign in with Hugging Face ↗</a>'}
424
  function renderAuthWarnings(me){const auth=$('authPanel');if(!auth)return;const missing=me.missing_scopes||[];const warnings=me.warnings||[];if(!missing.length&&!warnings.length){auth.hidden=true;auth.innerHTML='';return}auth.hidden=false;auth.className='auth-panel warning';auth.innerHTML=`<strong>OAuth session warning</strong><p>${escapeHtml([...warnings,missing.length?'Missing scopes: '+missing.join(', '):''].filter(Boolean).join(' • '))}</p><a class="link-btn" href="/oauth/huggingface/login">Refresh sign-in ↗</a>`}
425
  function renderBillingPanel(info){
 
323
  setText('modelPreScanTitle',`${labelMap[verdict]||labelMap.caution}${scoreText}`);
324
  setText('modelPreScanSummary',scan.summary||'Model metadata scan completed.');
325
  if(badge){badge.textContent=labelMap[verdict]||verdict;badge.className='badge '+cls}
326
+ const allGood=(scan.good_signals||[]).filter(Boolean);
327
+ const good=allGood.slice(0,2);
328
+ const allRisk=(scan.risk_signals||[]).filter(Boolean);
329
+ const risk=allRisk.slice(0,3);
330
  const outputType=outputTypeFromModelScan(scan);
331
+ const recommendations=(scan.recommendations||[]).filter(Boolean);
332
+ const primaryRecommendation=recommendations.find(x=>!String(x).toLowerCase().startsWith('expected output'))||recommendations[0]||'';
333
  if(signals){
334
  const metaCards=[
335
  outputType?['↳','Output',outputType,verdict==='safe']:null,
 
337
  scan.library_name?['◎','Library',scan.library_name,false]:null,
338
  ].filter(Boolean).slice(0,3);
339
  const compactMeta=metaCards.length?`<div class="prescan-meta prescan-compact-grid">${metaCards.map(([icon,k,v,isGood])=>`<span class="prescan-chip ${isGood?'good':''}"><i>${escapeHtml(icon)}</i><em>${escapeHtml(k)}</em><strong>${escapeHtml(String(v))}</strong></span>`).join('')}</div>`:'';
340
+ const signalSummaryParts=[];
341
+ if(allGood.length)signalSummaryParts.push(`${allGood.length} check${allGood.length>1?'s':''} passed`);
342
+ if(allRisk.length)signalSummaryParts.push(`${allRisk.length} risk signal${allRisk.length>1?'s':''}`);
343
+ else if(verdict!=='scanning'&&verdict!=='error')signalSummaryParts.push('No risk signals');
344
+ if(primaryRecommendation)signalSummaryParts.push(primaryRecommendation);
345
+ const summaryTitle=[...allGood,...allRisk,...recommendations].filter(Boolean).join('\n');
346
+ const signalSummary=signalSummaryParts.length?`<div class="prescan-decision-line ${cls}" title="${escapeHtml(summaryTitle)}"><b>${verdict==='safe'?'Ready':verdict==='caution'?'Review':verdict==='risky'?'Risk':verdict==='unsupported'?'Unsupported':verdict==='scanning'?'Scanning':'Issue'}</b><span>${escapeHtml(signalSummaryParts.join(' · '))}</span></div>`:'';
347
+ const goodPreview=(verdict!=='safe'&&good.length)?`<div class="prescan-pill-row">${good.map(x=>`<span class="prescan-pill good"><b class="prescan-icon">✓</b>${escapeHtml(x)}</span>`).join('')}</div>`:'';
348
  const riskPills=risk.length?`<div class="prescan-pill-row">${risk.map(x=>`<span class="prescan-pill risk"><b class="prescan-icon">!</b>${escapeHtml(x)}</span>`).join('')}</div>`:'';
349
  const runningPills=verdict==='scanning'?'<div class="prescan-pill-row"><span class="prescan-pill running"><b class="prescan-icon prescan-spinner">◌</b>Reading model card</span><span class="prescan-pill running"><b class="prescan-icon">◇</b>Checking metadata</span></div>':'';
350
  const errorPill=verdict==='error'?`<div class="prescan-pill-row"><span class="prescan-pill risk"><b class="prescan-icon">!</b>${escapeHtml(scan.error||'The scan could not complete. Try again.')}</span></div>`:'';
351
+ const emptyHint=(!compactMeta&&!signalSummary&&!goodPreview&&!riskPills&&!runningPills&&!errorPill)?'<div class="prescan-pill-row"><span class="prescan-pill"><b class="prescan-icon"></b>No extra metadata found.</span></div>':'';
 
352
  signals.hidden=false;
353
+ signals.innerHTML=`${compactMeta}${runningPills}${signalSummary}${goodPreview}${riskPills}${errorPill}${emptyHint}`;
354
  }
355
  if(ackWrap)ackWrap.hidden=!(verdict==='risky');
356
  }
 
427
  }
428
  async function bootstrapRunRecovery(){return restoreActiveRun()}
429
  async function restoreActiveRun(){try{const resumable=await apiGet(`/api/runs/resumable?bucket_name=${encodeURIComponent(state.bucketName)}`);if(resumable?.run?.run_id){state.runId=resumable.run.run_id;if(resumable.bucket_source)state.bucketSource=resumable.bucket_source;setBuildModeInspecting(state.runId);if(resumable.view)renderRunViewModel(resumable.view,{progress:0,events:[]});setQuickLinks(resumable.view?.links||{},resumable.view||{});startPolling(state.runId);return true}}catch(e){console.warn('resumable lookup failed',e)}try{const raw=localStorage.getItem('asf.activeRun');if(!raw)return false;const saved=JSON.parse(raw);if(saved?.bucketName)state.bucketName=saved.bucketName;if(saved?.runId){state.runId=saved.runId;setText('detailRunId',saved.runId);setQuickLinks(saved.links||{},{});setBuildModeInspecting(saved.runId);startPolling(saved.runId);return true}}catch(_){}return false}
430
+ async function refreshAnonymousEvalStatus(){
431
+ try{
432
+ const anonymous_eval=await apiGet('/api/eval-archive/status');
433
+ renderAnonymousEvalStatus({anonymous_eval});
434
+ return anonymous_eval;
435
+ }catch(e){
436
+ renderAnonymousEvalStatus({anonymous_eval:{enabled:false,reason:'status_unavailable',managed_by:'instance owner'}});
437
+ return null;
438
+ }
439
+ }
440
+ async function loadAppInfo(){setOperation('Checking sign-in and run storage…','loading');setBucketFeedback('checking','Checking private bucket access…');try{const me=await apiGet('/api/me');state.user=me;renderAnonymousEvalStatus(me);setText('userChip','@'+me.username);const userChip=$('userChip');if(userChip)userChip.href=`https://huggingface.co/${me.username}`;const logout=$('logoutLink');if(logout){logout.hidden=false;logout.href=me.logout_url||'/logout'}state.bucketSource=me.username+'/'+state.bucketName;setText('bucketInlineLabel',state.bucketSource);renderAuthWarnings(me);renderBillingPanel(me);loadBillingStatus().catch(()=>{});await checkBucket(false);await loadRuns(true);clearSavedRun();if(!state.bucketReady)setOperation('Create your private run bucket before launching builds.','warning');else setOperation('')}catch(e){state.user=null;await refreshAnonymousEvalStatus();setText('userChip','Sign in');const userChip=$('userChip');if(userChip)userChip.href='/oauth/huggingface/login';const logout=$('logoutLink');if(logout)logout.hidden=true;renderSignedOut();renderBillingPanel(null);setBucketReady(false,'Sign in with Hugging Face first.');showMessage('Please sign in with Hugging Face, then refresh this page.',true)}}
441
  function renderSignedOut(){const auth=$('authPanel');if(!auth)return;auth.hidden=false;auth.className='auth-panel warning';auth.innerHTML='<strong>Sign in required</strong><p>Use Hugging Face OAuth before launching Jobs or reading your Bucket.</p><a class="link-btn" href="/oauth/huggingface/login">Sign in with Hugging Face ↗</a>'}
442
  function renderAuthWarnings(me){const auth=$('authPanel');if(!auth)return;const missing=me.missing_scopes||[];const warnings=me.warnings||[];if(!missing.length&&!warnings.length){auth.hidden=true;auth.innerHTML='';return}auth.hidden=false;auth.className='auth-panel warning';auth.innerHTML=`<strong>OAuth session warning</strong><p>${escapeHtml([...warnings,missing.length?'Missing scopes: '+missing.join(', '):''].filter(Boolean).join(' • '))}</p><a class="link-btn" href="/oauth/huggingface/login">Refresh sign-in ↗</a>`}
443
  function renderBillingPanel(info){