Upload 7 files
Browse files- web/static/app.css +36 -1
- 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:.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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');
|
| 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.
|