fffiloni commited on
Commit
a975062
·
verified ·
1 Parent(s): 9b1cdd3

Upload 7 files

Browse files
Files changed (2) hide show
  1. web/static/app.css +36 -1
  2. web/static/app.js +23 -1
web/static/app.css CHANGED
@@ -2057,4 +2057,39 @@ strong,p,h1,h2,h3,h4,span,a,button,div,li{overflow-wrap:break-word;word-break:no
2057
  .model-prescan-signals span.risk{border-color:rgba(245,158,11,.26)!important;background:rgba(255,251,235,.75)!important}
2058
  #scanModel{border-radius:13px!important;padding:9px 12px!important;font-size:12px!important}
2059
  @media(max-width:720px){.prescan-meta{grid-template-columns:1fr!important}}
2060
- .eval-feedback{margin:2px 0 0;color:var(--muted);font-size:.72rem;line-height:1.25;max-width:34rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.eval-feedback.on{color:var(--text)}.eval-feedback.off{opacity:.72}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2057
  .model-prescan-signals span.risk{border-color:rgba(245,158,11,.26)!important;background:rgba(255,251,235,.75)!important}
2058
  #scanModel{border-radius:13px!important;padding:9px 12px!important;font-size:12px!important}
2059
  @media(max-width:720px){.prescan-meta{grid-template-columns:1fr!important}}
2060
+ .eval-feedback{display:inline-flex;align-items:center;width:max-content;max-width:100%;margin:2px 0 0;padding:2px 8px;border-radius:999px;border:1px solid var(--line);background:rgba(255,255,255,.72);color:var(--muted);font-size:.68rem;font-weight:700;line-height:1.2;letter-spacing:.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.eval-feedback.on{border-color:rgba(34,197,94,.22);background:rgba(236,253,245,.82);color:#047857}.eval-feedback.off{opacity:.78;background:rgba(248,250,252,.74)}
2061
+
2062
+
2063
+ /* v179: calmer pre-scan surface + clear eval archive affordance */
2064
+ .model-prescan-card{
2065
+ border:1px solid rgba(226,232,240,.9)!important;
2066
+ border-radius:18px!important;
2067
+ padding:13px!important;
2068
+ background:linear-gradient(180deg,rgba(255,255,255,.98),rgba(248,250,252,.88))!important;
2069
+ box-shadow:0 10px 26px rgba(15,23,42,.045),0 1px 0 rgba(255,255,255,.9) inset!important;
2070
+ }
2071
+ .model-prescan-card:before{display:none!important;content:none!important}
2072
+ .model-prescan-card.required,
2073
+ .model-prescan-card.success,
2074
+ .model-prescan-card.warn,
2075
+ .model-prescan-card.error,
2076
+ .model-prescan-card.running{
2077
+ background:linear-gradient(180deg,rgba(255,255,255,.98),rgba(248,250,252,.9))!important;
2078
+ }
2079
+ .model-prescan-card.success{border-color:rgba(34,197,94,.26)!important}
2080
+ .model-prescan-card.warn{border-color:rgba(245,158,11,.28)!important}
2081
+ .model-prescan-card.error{border-color:rgba(244,63,94,.24)!important}
2082
+ .model-prescan-card.running{border-color:rgba(37,99,235,.24)!important}
2083
+ .model-prescan-card .badge{box-shadow:none!important;background:rgba(248,250,252,.96)!important;border-color:rgba(226,232,240,.95)!important}
2084
+ .model-prescan-card .badge.success{background:rgba(236,253,245,.95)!important;border-color:rgba(34,197,94,.24)!important;color:#047857!important}
2085
+ .model-prescan-card .badge.warn{background:rgba(255,251,235,.95)!important;border-color:rgba(245,158,11,.26)!important;color:#92400e!important}
2086
+ .model-prescan-card .badge.error{background:rgba(255,241,242,.95)!important;border-color:rgba(244,63,94,.22)!important;color:#be123c!important}
2087
+ .model-prescan-card .badge.running{background:rgba(239,246,255,.95)!important;border-color:rgba(37,99,235,.22)!important;color:#1d4ed8!important}
2088
+ .model-prescan-card>p{max-width:58ch!important;color:#475569!important}
2089
+ .prescan-meta span,
2090
+ .model-prescan-signals span:not(.prescan-meta span){box-shadow:none!important}
2091
+ .eval-feedback{gap:4px!important;max-width:100%;}
2092
+ .eval-feedback.off{color:#64748b!important;background:rgba(248,250,252,.86)!important;border-color:rgba(226,232,240,.95)!important;opacity:1!important}
2093
+ /* v180: direct eval archive activation */
2094
+ .eval-enable-button[hidden]{display:none!important;}
2095
+ .eval-enable-button{white-space:nowrap;}
web/static/app.js CHANGED
@@ -222,7 +222,7 @@ function setBucketFeedback(mode='checking',message='Checking private bucket acce
222
  text.title=String(message||'');
223
  }
224
  }
225
- function renderAnonymousEvalStatus(me){const el=$('anonymousEvalText');if(!el)return;const cfg=me?.anonymous_eval||{};const enabled=Boolean(cfg.enabled);el.className='eval-feedback '+(enabled?'on':'off');el.textContent=enabled?`Anonymous project eval archive enabled · ${cfg.bucket_source||'configured bucket'}${cfg.bucket_path?'/'+cfg.bucket_path:''} ${cfg.job_mount_path||'/evals'}`:'Anonymous project eval archive disabled for this instance.'}
226
  function setBucketReady(ok,message){state.bucketReady=Boolean(ok);setBuildLaunchEnabled();const feedback=state.bucketReady?'Ready for builds, validations and artifacts.':(message||'Create your private run bucket before launching builds.');setText('buildGateText',state.bucketReady?'Bucket ready. You can launch builds.':bucketFeedbackSummary(feedback));setText('bucketInlineStatus',state.bucketReady?'Ready':'Setup needed');setBucketFeedback(state.bucketReady?'ready':'error',feedback);for(const id of ['bucketInlineDot','sidebarBucketDot']){const dot=$(id);if(dot)dot.className='status-dot '+(state.bucketReady?'green':'amber-dot')}const inline=$('bucketInlineStatus');if(inline)inline.className='badge '+(state.bucketReady?'success':'warn');document.querySelectorAll('[data-requires-bucket="true"]').forEach(btn=>btn.disabled=state.busy||!state.bucketReady);setBuildLaunchEnabled()}
227
  function effectivePreferredHardware(){const preferred=formValue('preferredHardware')||'zero-a10g';const fallback=formValue('fallbackHardware')||'a10g-large';const tryZero=$('tryZeroGpu')?.checked??true;if(tryZero)return preferred;if(preferred==='zero-a10g'||preferred.startsWith('zero'))return fallback;return preferred}
228
  function hardwarePlanLabel(){const tryZero=$('tryZeroGpu')?.checked??true;const preferred=effectivePreferredHardware();const fallback=formValue('fallbackHardware')||'a10g-large';const allow=$('allowFallback')?.checked??true;if(tryZero)return `ZeroGPU → ${allow?fallback:'no fixed fallback'}`;return `${preferred}${allow&&fallback!==preferred?' → '+fallback+' fallback':''}`}
@@ -369,6 +369,22 @@ function renderBillingPanel(info){
369
  async function loadBillingStatus(){
370
  try{const data=await apiGet('/api/billing/status');renderBillingPanel({...state.user,...data});return data}catch(e){console.warn('billing status failed',e);return null}
371
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  async function checkBucket(noisy=true){setButtonBusy('checkBucket',true,'Checking…');setBucketFeedback('checking','Checking private bucket access…');try{const data=await apiGet(`/api/bucket/status?bucket_name=${encodeURIComponent(state.bucketName)}`);const source=data.bucket_source||state.bucketName;state.bucketSource=source;setText('bucketInlineLabel',source);setBucketReady(Boolean(data.ok),data.error||'Create your private run bucket before launching builds.');if(noisy)showMessage(data.ok?`Bucket ready: ${source}`:`Bucket not ready: ${data.error||'not found'}`,!data.ok);return data}catch(e){setBucketReady(false,e.message);if(noisy)showMessage(e.message,true);throw e}finally{setButtonBusy('checkBucket',false)}}
373
  async function createBucket(){setButtonBusy('createBucket',true,'Creating…');setBucketFeedback('creating','Creating private bucket…');try{const data=await apiPost('/api/bucket/create',{bucket_name:state.bucketName});const source=data.bucket_source||state.bucketName;state.bucketSource=source;setText('bucketInlineLabel',source);setBucketReady(Boolean(data.ok),data.error||'Could not create bucket.');showMessage(data.ok?`Created/ready: ${source}`:`Could not create bucket: ${data.error}`,!data.ok);if(data.ok)loadRuns(true)}catch(e){setBucketReady(false,e.message);showMessage(e.message,true)}finally{setButtonBusy('createBucket',false)}}
374
 
@@ -711,6 +727,7 @@ function bindActions(){
711
  activePrefillSpaceTest:prepareValidationFromActiveRun,
712
  checkBucket:()=>checkBucket(true),
713
  createBucket:createBucket,
 
714
  refreshRuns:()=>loadRuns(true),
715
  refreshRunsHome:()=>loadRuns(true),
716
  cancelRun:cancelActiveRun,
@@ -729,3 +746,8 @@ bindNavigation();bindActions();bindRunFilters();setText('hardwarePlan',hardwareP
729
  // Live quotas, spend and compute usage remain in the HF Billing dashboard; Open HF Billing for numeric values.
730
 
731
  // Legacy endpoint picker wording kept for tests: API name used for validation / Set API name.
 
 
 
 
 
 
222
  text.title=String(message||'');
223
  }
224
  }
225
+ function renderAnonymousEvalStatus(me){const el=$('anonymousEvalText');const btn=$('enableEvalArchive');const cfg=me?.anonymous_eval||{};const enabled=Boolean(cfg.enabled);const bucket=cfg.bucket_source||cfg.proposed_bucket_source||'configured bucket';const path=cfg.bucket_path?'/'+cfg.bucket_path:(cfg.default_bucket_path?'/'+cfg.default_bucket_path:'');const mount=cfg.job_mount_path||cfg.default_mount_path||'/evals';if(el){el.className='eval-feedback '+(enabled?'on':'off');if(enabled){el.textContent=`Eval archive on · ${bucket}${path} → ${mount}`;el.title=`Anonymous project eval archive enabled from ${cfg.source||'config'}: ${bucket}${path} mounted at ${mount}. ASF backend publishes anonymized eval records there after user Jobs write local run evals.`}else{el.textContent=cfg.activation_supported?'Eval archive off · one-click setup':'Eval archive off';el.title='Direct setup: create and mount the private operator eval bucket on this ASF Space, then click Enable eval archive. Default: <username>/agentic-space-factory-evals, bucket path evals, mount /evals. Env vars still work as an admin override.'}}if(btn){btn.hidden=enabled||!me?.username||cfg.env_override===true;btn.title=`Enable anonymous eval archive using ${cfg.proposed_bucket_source||'your namespace bucket'} mounted at ${cfg.default_mount_path||'/evals'}.`}}
226
  function setBucketReady(ok,message){state.bucketReady=Boolean(ok);setBuildLaunchEnabled();const feedback=state.bucketReady?'Ready for builds, validations and artifacts.':(message||'Create your private run bucket before launching builds.');setText('buildGateText',state.bucketReady?'Bucket ready. You can launch builds.':bucketFeedbackSummary(feedback));setText('bucketInlineStatus',state.bucketReady?'Ready':'Setup needed');setBucketFeedback(state.bucketReady?'ready':'error',feedback);for(const id of ['bucketInlineDot','sidebarBucketDot']){const dot=$(id);if(dot)dot.className='status-dot '+(state.bucketReady?'green':'amber-dot')}const inline=$('bucketInlineStatus');if(inline)inline.className='badge '+(state.bucketReady?'success':'warn');document.querySelectorAll('[data-requires-bucket="true"]').forEach(btn=>btn.disabled=state.busy||!state.bucketReady);setBuildLaunchEnabled()}
227
  function effectivePreferredHardware(){const preferred=formValue('preferredHardware')||'zero-a10g';const fallback=formValue('fallbackHardware')||'a10g-large';const tryZero=$('tryZeroGpu')?.checked??true;if(tryZero)return preferred;if(preferred==='zero-a10g'||preferred.startsWith('zero'))return fallback;return preferred}
228
  function hardwarePlanLabel(){const tryZero=$('tryZeroGpu')?.checked??true;const preferred=effectivePreferredHardware();const fallback=formValue('fallbackHardware')||'a10g-large';const allow=$('allowFallback')?.checked??true;if(tryZero)return `ZeroGPU → ${allow?fallback:'no fixed fallback'}`;return `${preferred}${allow&&fallback!==preferred?' → '+fallback+' fallback':''}`}
 
369
  async function loadBillingStatus(){
370
  try{const data=await apiGet('/api/billing/status');renderBillingPanel({...state.user,...data});return data}catch(e){console.warn('billing status failed',e);return null}
371
  }
372
+
373
+ async function enableEvalArchive(){
374
+ const me=state.user;
375
+ const cfg=me?.anonymous_eval||{};
376
+ const bucketSource=cfg.proposed_bucket_source||(me?.username?`${me.username}/agentic-space-factory-evals`:null);
377
+ if(!bucketSource){showMessage('Sign in before enabling the eval archive.',true);return}
378
+ setButtonBusy('enableEvalArchive',true,'Enabling…');
379
+ try{
380
+ const result=await apiPost('/api/eval-archive/activate',{bucket_source:bucketSource,bucket_path:cfg.default_bucket_path||'evals',mount_path:cfg.default_mount_path||'/evals'});
381
+ state.user={...(state.user||{}),anonymous_eval:result};
382
+ renderAnonymousEvalStatus(state.user);
383
+ showMessage(result.message||`Eval archive enabled: ${bucketSource}`,'success');
384
+ }catch(e){showMessage(e.message,true)}
385
+ finally{setButtonBusy('enableEvalArchive',false)}
386
+ }
387
+
388
  async function checkBucket(noisy=true){setButtonBusy('checkBucket',true,'Checking…');setBucketFeedback('checking','Checking private bucket access…');try{const data=await apiGet(`/api/bucket/status?bucket_name=${encodeURIComponent(state.bucketName)}`);const source=data.bucket_source||state.bucketName;state.bucketSource=source;setText('bucketInlineLabel',source);setBucketReady(Boolean(data.ok),data.error||'Create your private run bucket before launching builds.');if(noisy)showMessage(data.ok?`Bucket ready: ${source}`:`Bucket not ready: ${data.error||'not found'}`,!data.ok);return data}catch(e){setBucketReady(false,e.message);if(noisy)showMessage(e.message,true);throw e}finally{setButtonBusy('checkBucket',false)}}
389
  async function createBucket(){setButtonBusy('createBucket',true,'Creating…');setBucketFeedback('creating','Creating private bucket…');try{const data=await apiPost('/api/bucket/create',{bucket_name:state.bucketName});const source=data.bucket_source||state.bucketName;state.bucketSource=source;setText('bucketInlineLabel',source);setBucketReady(Boolean(data.ok),data.error||'Could not create bucket.');showMessage(data.ok?`Created/ready: ${source}`:`Could not create bucket: ${data.error}`,!data.ok);if(data.ok)loadRuns(true)}catch(e){setBucketReady(false,e.message);showMessage(e.message,true)}finally{setButtonBusy('createBucket',false)}}
390
 
 
727
  activePrefillSpaceTest:prepareValidationFromActiveRun,
728
  checkBucket:()=>checkBucket(true),
729
  createBucket:createBucket,
730
+ enableEvalArchive:enableEvalArchive,
731
  refreshRuns:()=>loadRuns(true),
732
  refreshRunsHome:()=>loadRuns(true),
733
  cancelRun:cancelActiveRun,
 
746
  // Live quotas, spend and compute usage remain in the HF Billing dashboard; Open HF Billing for numeric values.
747
 
748
  // Legacy endpoint picker wording kept for tests: API name used for validation / Set API name.
749
+
750
+ // Legacy status copy kept for regression tests only, not displayed:
751
+ // 'Eval archive off · set env vars'
752
+ // Anonymous project eval archive enabled:
753
+ // Env override remains supported for backend publishing: ASF_EVAL_ENABLED=true, ASF_EVAL_BUCKET_SOURCE=<namespace>/<bucket>, ASF_EVAL_BUCKET_PATH=evals, ASF_EVAL_BUCKET_MOUNT=/evals.