From 344b4b845c1e5bf428d3c08511d79aa7b8a35326 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sun, 17 May 2026 16:50:56 -0700 Subject: [PATCH] admin: E6 Calibration tab + D23 server-rendered SVG + TD2 contrast bump (T15) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the v0.36.0.0 admin SPA Calibration tab. Per the design review, the approved variant-B (Linear calm clarity) layout: single-column flow, generous whitespace, ONE big sparkline as hero, then patterns, then domain bars, then abandoned threads. D23 server-rendered SVG architecture: src/core/calibration/svg-renderer.ts — pure functions. data → SVG string. No DOM, no React, no chart library dep. Inlines the admin design tokens (#0a0a0f bg, #3b82f6 accent, etc.) so the SVG is visually consistent with the rest of the admin SPA. Four chart renderers: - renderBrierTrend({ series }) — sparkline w/ baseline reference at 0.25 (always-50% baseline) - renderDomainBars({ bars }) — horizontal accuracy bars per domain - renderAbandonedThreadsCard(threads) — D30/TD4 'revisit now' link per row, points at /admin/calibration/revisit/ - renderPatternStatementsCard(statements) — D29/TD3 clickable drill-down links per row, point at /admin/calibration/pattern/ XSS posture: all caller-controlled strings pass through escapeXml(). Numeric inputs are .toFixed()-coerced. Admin SPA renders via dangerouslySetInnerHTML inside a TrustedSVG wrapper component; endpoint is gated by requireAdmin middleware. /admin/api/calibration/profile — returns the active profile row as JSON. /admin/api/calibration/charts/:type — returns image/svg+xml markup for type ∈ {brier-trend, domain-bars, pattern-statements, abandoned-threads}. Cache-Control: private, max-age=60. brier-trend currently renders a single-point series from the active profile (the time-series view across calibration_profiles.generated_at history is a v0.37 follow-up once we have multiple snapshots). abandoned-threads pulls the top 5 abandoned rows via the same SQL the doctor check uses. CalibrationPage React component (admin/src/pages/Calibration.tsx): Fetches profile + 4 charts. Loading / error / cold-brain states all handled. Layout includes the audit annotations (partial-grade badge, voice-gate-fell-back-to-template badge) per the approved mockup. TrustedSVG wrapper isolates the dangerouslySetInnerHTML to the SVG surface only. App.tsx nav: added 'calibration' page route + sidebar nav item, hash routing extended to support #calibration. TD2 contrast bump: admin/src/index.css --text-muted: #555 → #777. Old value was contrast 4.0 on the #0a0a0f bg — below WCAG AA 4.5 for body text. New value is ~5.5, passes AA. Improvement is global across Dashboard, Agents, RequestLog, and the new Calibration tab — single-line CSS change with ~10x the impact. admin/dist/ rebuilt via `bun run build` (vite). 36 modules transformed. Tests: 19 cases in test/svg-renderer.test.ts. escapeXml (1): canonical entities. renderBrierTrend (6): empty state, polyline for 2+ points, clamp beyond yMax, design tokens inlined, XSS safety on date strings, text-anchor end on right label. renderDomainBars (4): empty state, label/accuracy/n rendering, out-of-range accuracy clamp, XSS safety on labels. renderAbandonedThreadsCard (4): empty state, row rendering with revisit link, claim truncation at 70 chars, custom revisitHref override. renderPatternStatementsCard (4): empty state, anchor count matches statement count, XSS safety, custom drillHref override. Co-Authored-By: Claude Opus 4.7 (1M context) --- admin/dist/assets/index-CDv6_ml5.js | 56 ---- admin/dist/assets/index-CWq369vO.js | 56 ++++ ...{index-BOifXQpQ.css => index-GxkWX7v3.css} | 2 +- admin/dist/index.html | 4 +- admin/src/App.tsx | 8 +- admin/src/api.ts | 16 ++ admin/src/index.css | 5 +- admin/src/pages/Calibration.tsx | 174 ++++++++++++ src/commands/serve-http.ts | 91 +++++++ src/core/calibration/svg-renderer.ts | 247 ++++++++++++++++++ test/svg-renderer.test.ts | 211 +++++++++++++++ 11 files changed, 808 insertions(+), 62 deletions(-) delete mode 100644 admin/dist/assets/index-CDv6_ml5.js create mode 100644 admin/dist/assets/index-CWq369vO.js rename admin/dist/assets/{index-BOifXQpQ.css => index-GxkWX7v3.css} (98%) create mode 100644 admin/src/pages/Calibration.tsx create mode 100644 src/core/calibration/svg-renderer.ts create mode 100644 test/svg-renderer.test.ts diff --git a/admin/dist/assets/index-CDv6_ml5.js b/admin/dist/assets/index-CDv6_ml5.js deleted file mode 100644 index 3994ff46a..000000000 --- a/admin/dist/assets/index-CDv6_ml5.js +++ /dev/null @@ -1,56 +0,0 @@ -(function(){const H=document.createElement("link").relList;if(H&&H.supports&&H.supports("modulepreload"))return;for(const O of document.querySelectorAll('link[rel="modulepreload"]'))r(O);new MutationObserver(O=>{for(const G of O)if(G.type==="childList")for(const U of G.addedNodes)U.tagName==="LINK"&&U.rel==="modulepreload"&&r(U)}).observe(document,{childList:!0,subtree:!0});function D(O){const G={};return O.integrity&&(G.integrity=O.integrity),O.referrerPolicy&&(G.referrerPolicy=O.referrerPolicy),O.crossOrigin==="use-credentials"?G.credentials="include":O.crossOrigin==="anonymous"?G.credentials="omit":G.credentials="same-origin",G}function r(O){if(O.ep)return;O.ep=!0;const G=D(O);fetch(O.href,G)}})();function Or(m){return m&&m.__esModule&&Object.prototype.hasOwnProperty.call(m,"default")?m.default:m}var cf={exports:{}},Tu={};/** - * @license React - * react-jsx-runtime.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var vr;function Pm(){if(vr)return Tu;vr=1;var m=Symbol.for("react.transitional.element"),H=Symbol.for("react.fragment");function D(r,O,G){var U=null;if(G!==void 0&&(U=""+G),O.key!==void 0&&(U=""+O.key),"key"in O){G={};for(var w in O)w!=="key"&&(G[w]=O[w])}else G=O;return O=G.ref,{$$typeof:m,type:r,key:U,ref:O!==void 0?O:null,props:G}}return Tu.Fragment=H,Tu.jsx=D,Tu.jsxs=D,Tu}var gr;function ly(){return gr||(gr=1,cf.exports=Pm()),cf.exports}var f=ly(),ff={exports:{}},L={};/** - * @license React - * react.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Sr;function ty(){if(Sr)return L;Sr=1;var m=Symbol.for("react.transitional.element"),H=Symbol.for("react.portal"),D=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),G=Symbol.for("react.consumer"),U=Symbol.for("react.context"),w=Symbol.for("react.forward_ref"),M=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),R=Symbol.for("react.lazy"),x=Symbol.for("react.activity"),_=Symbol.iterator;function F(d){return d===null||typeof d!="object"?null:(d=_&&d[_]||d["@@iterator"],typeof d=="function"?d:null)}var Z={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},al=Object.assign,ll={};function pl(d,E,N){this.props=d,this.context=E,this.refs=ll,this.updater=N||Z}pl.prototype.isReactComponent={},pl.prototype.setState=function(d,E){if(typeof d!="object"&&typeof d!="function"&&d!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,d,E,"setState")},pl.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function Ml(){}Ml.prototype=pl.prototype;function Gl(d,E,N){this.props=d,this.context=E,this.refs=ll,this.updater=N||Z}var st=Gl.prototype=new Ml;st.constructor=Gl,al(st,pl.prototype),st.isPureReactComponent=!0;var xt=Array.isArray;function Ll(){}var tl={H:null,A:null,T:null,S:null},Vl=Object.prototype.hasOwnProperty;function jt(d,E,N){var B=N.ref;return{$$typeof:m,type:d,key:E,ref:B!==void 0?B:null,props:N}}function Le(d,E){return jt(d.type,E,d.props)}function Ot(d){return typeof d=="object"&&d!==null&&d.$$typeof===m}function Kl(d){var E={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(N){return E[N]})}var Ae=/\/+/g;function Ut(d,E){return typeof d=="object"&&d!==null&&d.key!=null?Kl(""+d.key):E.toString(36)}function pt(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(Ll,Ll):(d.status="pending",d.then(function(E){d.status==="pending"&&(d.status="fulfilled",d.value=E)},function(E){d.status==="pending"&&(d.status="rejected",d.reason=E)})),d.status){case"fulfilled":return d.value;case"rejected":throw d.reason}}throw d}function T(d,E,N,B,V){var k=typeof d;(k==="undefined"||k==="boolean")&&(d=null);var fl=!1;if(d===null)fl=!0;else switch(k){case"bigint":case"string":case"number":fl=!0;break;case"object":switch(d.$$typeof){case m:case H:fl=!0;break;case R:return fl=d._init,T(fl(d._payload),E,N,B,V)}}if(fl)return V=V(d),fl=B===""?"."+Ut(d,0):B,xt(V)?(N="",fl!=null&&(N=fl.replace(Ae,"$&/")+"/"),T(V,E,N,"",function(Oa){return Oa})):V!=null&&(Ot(V)&&(V=Le(V,N+(V.key==null||d&&d.key===V.key?"":(""+V.key).replace(Ae,"$&/")+"/")+fl)),E.push(V)),1;fl=0;var Ql=B===""?".":B+":";if(xt(d))for(var Al=0;Al>>1,yl=T[dl];if(0>>1;dlO(N,Q))BO(V,N)?(T[dl]=V,T[B]=Q,dl=B):(T[dl]=N,T[E]=Q,dl=E);else if(BO(V,Q))T[dl]=V,T[B]=Q,dl=B;else break l}}return j}function O(T,j){var Q=T.sortIndex-j.sortIndex;return Q!==0?Q:T.id-j.id}if(m.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var G=performance;m.unstable_now=function(){return G.now()}}else{var U=Date,w=U.now();m.unstable_now=function(){return U.now()-w}}var M=[],p=[],R=1,x=null,_=3,F=!1,Z=!1,al=!1,ll=!1,pl=typeof setTimeout=="function"?setTimeout:null,Ml=typeof clearTimeout=="function"?clearTimeout:null,Gl=typeof setImmediate<"u"?setImmediate:null;function st(T){for(var j=D(p);j!==null;){if(j.callback===null)r(p);else if(j.startTime<=T)r(p),j.sortIndex=j.expirationTime,H(M,j);else break;j=D(p)}}function xt(T){if(al=!1,st(T),!Z)if(D(M)!==null)Z=!0,Ll||(Ll=!0,Kl());else{var j=D(p);j!==null&&pt(xt,j.startTime-T)}}var Ll=!1,tl=-1,Vl=5,jt=-1;function Le(){return ll?!0:!(m.unstable_now()-jtT&&Le());){var dl=x.callback;if(typeof dl=="function"){x.callback=null,_=x.priorityLevel;var yl=dl(x.expirationTime<=T);if(T=m.unstable_now(),typeof yl=="function"){x.callback=yl,st(T),j=!0;break t}x===D(M)&&r(M),st(T)}else r(M);x=D(M)}if(x!==null)j=!0;else{var d=D(p);d!==null&&pt(xt,d.startTime-T),j=!1}}break l}finally{x=null,_=Q,F=!1}j=void 0}}finally{j?Kl():Ll=!1}}}var Kl;if(typeof Gl=="function")Kl=function(){Gl(Ot)};else if(typeof MessageChannel<"u"){var Ae=new MessageChannel,Ut=Ae.port2;Ae.port1.onmessage=Ot,Kl=function(){Ut.postMessage(null)}}else Kl=function(){pl(Ot,0)};function pt(T,j){tl=pl(function(){T(m.unstable_now())},j)}m.unstable_IdlePriority=5,m.unstable_ImmediatePriority=1,m.unstable_LowPriority=4,m.unstable_NormalPriority=3,m.unstable_Profiling=null,m.unstable_UserBlockingPriority=2,m.unstable_cancelCallback=function(T){T.callback=null},m.unstable_forceFrameRate=function(T){0>T||125dl?(T.sortIndex=Q,H(p,T),D(M)===null&&T===D(p)&&(al?(Ml(tl),tl=-1):al=!0,pt(xt,Q-dl))):(T.sortIndex=yl,H(M,T),Z||F||(Z=!0,Ll||(Ll=!0,Kl()))),T},m.unstable_shouldYield=Le,m.unstable_wrapCallback=function(T){var j=_;return function(){var Q=_;_=j;try{return T.apply(this,arguments)}finally{_=Q}}}})(df)),df}var Tr;function ay(){return Tr||(Tr=1,of.exports=ey()),of.exports}var rf={exports:{}},Xl={};/** - * @license React - * react-dom.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var zr;function uy(){if(zr)return Xl;zr=1;var m=hf();function H(M){var p="https://react.dev/errors/"+M;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(m)}catch(H){console.error(H)}}return m(),rf.exports=uy(),rf.exports}/** - * @license React - * react-dom-client.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Er;function iy(){if(Er)return zu;Er=1;var m=ay(),H=hf(),D=ny();function r(l){var t="https://react.dev/errors/"+l;if(1yl||(l.current=dl[yl],dl[yl]=null,yl--)}function N(l,t){yl++,dl[yl]=l.current,l.current=t}var B=d(null),V=d(null),k=d(null),fl=d(null);function Ql(l,t){switch(N(k,t),N(V,l),N(B,null),t.nodeType){case 9:case 11:l=(l=t.documentElement)&&(l=l.namespaceURI)?Gd(l):0;break;default:if(l=t.tagName,t=t.namespaceURI)t=Gd(t),l=Xd(t,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}E(B),N(B,l)}function Al(){E(B),E(V),E(k)}function Oa(l){l.memoizedState!==null&&N(fl,l);var t=B.current,e=Xd(t,l.type);t!==e&&(N(V,l),N(B,e))}function Au(l){V.current===l&&(E(B),E(V)),fl.current===l&&(E(fl),gu._currentValue=Q)}var Zn,mf;function Ee(l){if(Zn===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Zn=t&&t[1]||"",mf=-1)":-1u||s[a]!==v[u]){var b=` -`+s[a].replace(" at new "," at ");return l.displayName&&b.includes("")&&(b=b.replace("",l.displayName)),b}while(1<=a&&0<=u);break}}}finally{Ln=!1,Error.prepareStackTrace=e}return(e=l?l.displayName||l.name:"")?Ee(e):""}function Mr(l,t){switch(l.tag){case 26:case 27:case 5:return Ee(l.type);case 16:return Ee("Lazy");case 13:return l.child!==t&&t!==null?Ee("Suspense Fallback"):Ee("Suspense");case 19:return Ee("SuspenseList");case 0:case 15:return Vn(l.type,!1);case 11:return Vn(l.type.render,!1);case 1:return Vn(l.type,!0);case 31:return Ee("Activity");default:return""}}function yf(l){try{var t="",e=null;do t+=Mr(l,e),e=l,l=l.return;while(l);return t}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}var Kn=Object.prototype.hasOwnProperty,Jn=m.unstable_scheduleCallback,wn=m.unstable_cancelCallback,Dr=m.unstable_shouldYield,Cr=m.unstable_requestPaint,Pl=m.unstable_now,Ur=m.unstable_getCurrentPriorityLevel,vf=m.unstable_ImmediatePriority,gf=m.unstable_UserBlockingPriority,Eu=m.unstable_NormalPriority,Rr=m.unstable_LowPriority,Sf=m.unstable_IdlePriority,Hr=m.log,Br=m.unstable_setDisableYieldValue,Na=null,lt=null;function It(l){if(typeof Hr=="function"&&Br(l),lt&&typeof lt.setStrictMode=="function")try{lt.setStrictMode(Na,l)}catch{}}var tt=Math.clz32?Math.clz32:Gr,qr=Math.log,Yr=Math.LN2;function Gr(l){return l>>>=0,l===0?32:31-(qr(l)/Yr|0)|0}var _u=256,xu=262144,ju=4194304;function _e(l){var t=l&42;if(t!==0)return t;switch(l&-l){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return l&261888;case 262144:case 524288:case 1048576:case 2097152:return l&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return l&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return l}}function Ou(l,t,e){var a=l.pendingLanes;if(a===0)return 0;var u=0,n=l.suspendedLanes,i=l.pingedLanes;l=l.warmLanes;var c=a&134217727;return c!==0?(a=c&~n,a!==0?u=_e(a):(i&=c,i!==0?u=_e(i):e||(e=c&~l,e!==0&&(u=_e(e))))):(c=a&~n,c!==0?u=_e(c):i!==0?u=_e(i):e||(e=a&~l,e!==0&&(u=_e(e)))),u===0?0:t!==0&&t!==u&&(t&n)===0&&(n=u&-u,e=t&-t,n>=e||n===32&&(e&4194048)!==0)?t:u}function Ma(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function Xr(l,t){switch(l){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function bf(){var l=ju;return ju<<=1,(ju&62914560)===0&&(ju=4194304),l}function kn(l){for(var t=[],e=0;31>e;e++)t.push(l);return t}function Da(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Qr(l,t,e,a,u,n){var i=l.pendingLanes;l.pendingLanes=e,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=e,l.entangledLanes&=e,l.errorRecoveryDisabledLanes&=e,l.shellSuspendCounter=0;var c=l.entanglements,s=l.expirationTimes,v=l.hiddenUpdates;for(e=i&~e;0"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var wr=/[\n"\\]/g;function dt(l){return l.replace(wr,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function li(l,t,e,a,u,n,i,c){l.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?l.type=i:l.removeAttribute("type"),t!=null?i==="number"?(t===0&&l.value===""||l.value!=t)&&(l.value=""+ot(t)):l.value!==""+ot(t)&&(l.value=""+ot(t)):i!=="submit"&&i!=="reset"||l.removeAttribute("value"),t!=null?ti(l,i,ot(t)):e!=null?ti(l,i,ot(e)):a!=null&&l.removeAttribute("value"),u==null&&n!=null&&(l.defaultChecked=!!n),u!=null&&(l.checked=u&&typeof u!="function"&&typeof u!="symbol"),c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.name=""+ot(c):l.removeAttribute("name")}function Cf(l,t,e,a,u,n,i,c){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(l.type=n),t!=null||e!=null){if(!(n!=="submit"&&n!=="reset"||t!=null)){Pn(l);return}e=e!=null?""+ot(e):"",t=t!=null?""+ot(t):e,c||t===l.value||(l.value=t),l.defaultValue=t}a=a??u,a=typeof a!="function"&&typeof a!="symbol"&&!!a,l.checked=c?l.checked:!!a,l.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(l.name=i),Pn(l)}function ti(l,t,e){t==="number"&&Du(l.ownerDocument)===l||l.defaultValue===""+e||(l.defaultValue=""+e)}function $e(l,t,e,a){if(l=l.options,t){t={};for(var u=0;u"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),ii=!1;if(Bt)try{var Ha={};Object.defineProperty(Ha,"passive",{get:function(){ii=!0}}),window.addEventListener("test",Ha,Ha),window.removeEventListener("test",Ha,Ha)}catch{ii=!1}var le=null,ci=null,Uu=null;function Gf(){if(Uu)return Uu;var l,t=ci,e=t.length,a,u="value"in le?le.value:le.textContent,n=u.length;for(l=0;l=Ya),Kf=" ",Jf=!1;function wf(l,t){switch(l){case"keyup":return Th.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function kf(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var Pe=!1;function Ah(l,t){switch(l){case"compositionend":return kf(t);case"keypress":return t.which!==32?null:(Jf=!0,Kf);case"textInput":return l=t.data,l===Kf&&Jf?null:l;default:return null}}function Eh(l,t){if(Pe)return l==="compositionend"||!ri&&wf(l,t)?(l=Gf(),Uu=ci=le=null,Pe=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:e,offset:t-l};l=a}l:{for(;e;){if(e.nextSibling){e=e.nextSibling;break l}e=e.parentNode}e=void 0}e=es(e)}}function us(l,t){return l&&t?l===t?!0:l&&l.nodeType===3?!1:t&&t.nodeType===3?us(l,t.parentNode):"contains"in l?l.contains(t):l.compareDocumentPosition?!!(l.compareDocumentPosition(t)&16):!1:!1}function ns(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var t=Du(l.document);t instanceof l.HTMLIFrameElement;){try{var e=typeof t.contentWindow.location.href=="string"}catch{e=!1}if(e)l=t.contentWindow;else break;t=Du(l.document)}return t}function yi(l){var t=l&&l.nodeName&&l.nodeName.toLowerCase();return t&&(t==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||t==="textarea"||l.contentEditable==="true")}var Ch=Bt&&"documentMode"in document&&11>=document.documentMode,la=null,vi=null,Za=null,gi=!1;function is(l,t,e){var a=e.window===e?e.document:e.nodeType===9?e:e.ownerDocument;gi||la==null||la!==Du(a)||(a=la,"selectionStart"in a&&yi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Za&&Qa(Za,a)||(Za=a,a=jn(vi,"onSelect"),0>=i,u-=i,Nt=1<<32-tt(t)+u|e<J?(P=q,q=null):P=q.sibling;var il=g(h,q,y[J],z);if(il===null){q===null&&(q=P);break}l&&q&&il.alternate===null&&t(h,q),o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il,q=P}if(J===y.length)return e(h,q),el&&Yt(h,J),Y;if(q===null){for(;JJ?(P=q,q=null):P=q.sibling;var ze=g(h,q,il.value,z);if(ze===null){q===null&&(q=P);break}l&&q&&ze.alternate===null&&t(h,q),o=n(ze,o,J),nl===null?Y=ze:nl.sibling=ze,nl=ze,q=P}if(il.done)return e(h,q),el&&Yt(h,J),Y;if(q===null){for(;!il.done;J++,il=y.next())il=A(h,il.value,z),il!==null&&(o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il);return el&&Yt(h,J),Y}for(q=a(q);!il.done;J++,il=y.next())il=S(q,h,J,il.value,z),il!==null&&(l&&il.alternate!==null&&q.delete(il.key===null?J:il.key),o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il);return l&&q.forEach(function(Im){return t(h,Im)}),el&&Yt(h,J),Y}function ml(h,o,y,z){if(typeof y=="object"&&y!==null&&y.type===al&&y.key===null&&(y=y.props.children),typeof y=="object"&&y!==null){switch(y.$$typeof){case F:l:{for(var Y=y.key;o!==null;){if(o.key===Y){if(Y=y.type,Y===al){if(o.tag===7){e(h,o.sibling),z=u(o,y.props.children),z.return=h,h=z;break l}}else if(o.elementType===Y||typeof Y=="object"&&Y!==null&&Y.$$typeof===Vl&&Be(Y)===o.type){e(h,o.sibling),z=u(o,y.props),ka(z,y),z.return=h,h=z;break l}e(h,o);break}else t(h,o);o=o.sibling}y.type===al?(z=De(y.props.children,h.mode,z,y.key),z.return=h,h=z):(z=Lu(y.type,y.key,y.props,null,h.mode,z),ka(z,y),z.return=h,h=z)}return i(h);case Z:l:{for(Y=y.key;o!==null;){if(o.key===Y)if(o.tag===4&&o.stateNode.containerInfo===y.containerInfo&&o.stateNode.implementation===y.implementation){e(h,o.sibling),z=u(o,y.children||[]),z.return=h,h=z;break l}else{e(h,o);break}else t(h,o);o=o.sibling}z=Ei(y,h.mode,z),z.return=h,h=z}return i(h);case Vl:return y=Be(y),ml(h,o,y,z)}if(pt(y))return C(h,o,y,z);if(Kl(y)){if(Y=Kl(y),typeof Y!="function")throw Error(r(150));return y=Y.call(y),X(h,o,y,z)}if(typeof y.then=="function")return ml(h,o,Wu(y),z);if(y.$$typeof===Gl)return ml(h,o,Ju(h,y),z);Fu(h,y)}return typeof y=="string"&&y!==""||typeof y=="number"||typeof y=="bigint"?(y=""+y,o!==null&&o.tag===6?(e(h,o.sibling),z=u(o,y),z.return=h,h=z):(e(h,o),z=Ai(y,h.mode,z),z.return=h,h=z),i(h)):e(h,o)}return function(h,o,y,z){try{wa=0;var Y=ml(h,o,y,z);return da=null,Y}catch(q){if(q===oa||q===ku)throw q;var nl=at(29,q,null,h.mode);return nl.lanes=z,nl.return=h,nl}finally{}}}var Ye=Ns(!0),Ms=Ns(!1),ne=!1;function Bi(l){l.updateQueue={baseState:l.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function qi(l,t){l=l.updateQueue,t.updateQueue===l&&(t.updateQueue={baseState:l.baseState,firstBaseUpdate:l.firstBaseUpdate,lastBaseUpdate:l.lastBaseUpdate,shared:l.shared,callbacks:null})}function ie(l){return{lane:l,tag:0,payload:null,callback:null,next:null}}function ce(l,t,e){var a=l.updateQueue;if(a===null)return null;if(a=a.shared,(cl&2)!==0){var u=a.pending;return u===null?t.next=t:(t.next=u.next,u.next=t),a.pending=t,t=Zu(l),hs(l,null,e),t}return Qu(l,a,t,e),Zu(l)}function $a(l,t,e){if(t=t.updateQueue,t!==null&&(t=t.shared,(e&4194048)!==0)){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,Tf(l,e)}}function Yi(l,t){var e=l.updateQueue,a=l.alternate;if(a!==null&&(a=a.updateQueue,e===a)){var u=null,n=null;if(e=e.firstBaseUpdate,e!==null){do{var i={lane:e.lane,tag:e.tag,payload:e.payload,callback:null,next:null};n===null?u=n=i:n=n.next=i,e=e.next}while(e!==null);n===null?u=n=t:n=n.next=t}else u=n=t;e={baseState:a.baseState,firstBaseUpdate:u,lastBaseUpdate:n,shared:a.shared,callbacks:a.callbacks},l.updateQueue=e;return}l=e.lastBaseUpdate,l===null?e.firstBaseUpdate=t:l.next=t,e.lastBaseUpdate=t}var Gi=!1;function Wa(){if(Gi){var l=sa;if(l!==null)throw l}}function Fa(l,t,e,a){Gi=!1;var u=l.updateQueue;ne=!1;var n=u.firstBaseUpdate,i=u.lastBaseUpdate,c=u.shared.pending;if(c!==null){u.shared.pending=null;var s=c,v=s.next;s.next=null,i===null?n=v:i.next=v,i=s;var b=l.alternate;b!==null&&(b=b.updateQueue,c=b.lastBaseUpdate,c!==i&&(c===null?b.firstBaseUpdate=v:c.next=v,b.lastBaseUpdate=s))}if(n!==null){var A=u.baseState;i=0,b=v=s=null,c=n;do{var g=c.lane&-536870913,S=g!==c.lane;if(S?(I&g)===g:(a&g)===g){g!==0&&g===fa&&(Gi=!0),b!==null&&(b=b.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});l:{var C=l,X=c;g=t;var ml=e;switch(X.tag){case 1:if(C=X.payload,typeof C=="function"){A=C.call(ml,A,g);break l}A=C;break l;case 3:C.flags=C.flags&-65537|128;case 0:if(C=X.payload,g=typeof C=="function"?C.call(ml,A,g):C,g==null)break l;A=x({},A,g);break l;case 2:ne=!0}}g=c.callback,g!==null&&(l.flags|=64,S&&(l.flags|=8192),S=u.callbacks,S===null?u.callbacks=[g]:S.push(g))}else S={lane:g,tag:c.tag,payload:c.payload,callback:c.callback,next:null},b===null?(v=b=S,s=A):b=b.next=S,i|=g;if(c=c.next,c===null){if(c=u.shared.pending,c===null)break;S=c,c=S.next,S.next=null,u.lastBaseUpdate=S,u.shared.pending=null}}while(!0);b===null&&(s=A),u.baseState=s,u.firstBaseUpdate=v,u.lastBaseUpdate=b,n===null&&(u.shared.lanes=0),re|=i,l.lanes=i,l.memoizedState=A}}function Ds(l,t){if(typeof l!="function")throw Error(r(191,l));l.call(t)}function Cs(l,t){var e=l.callbacks;if(e!==null)for(l.callbacks=null,l=0;ln?n:8;var i=T.T,c={};T.T=c,uc(l,!1,t,e);try{var s=u(),v=T.S;if(v!==null&&v(c,s),s!==null&&typeof s=="object"&&typeof s.then=="function"){var b=Qh(s,a);lu(l,t,b,ft(l))}else lu(l,t,a,ft(l))}catch(A){lu(l,t,{then:function(){},status:"rejected",reason:A},ft())}finally{j.p=n,i!==null&&c.types!==null&&(i.types=c.types),T.T=i}}function wh(){}function ec(l,t,e,a){if(l.tag!==5)throw Error(r(476));var u=oo(l).queue;so(l,u,t,Q,e===null?wh:function(){return ro(l),e(a)})}function oo(l){var t=l.memoizedState;if(t!==null)return t;t={memoizedState:Q,baseState:Q,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:Q},next:null};var e={};return t.next={memoizedState:e,baseState:e,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:e},next:null},l.memoizedState=t,l=l.alternate,l!==null&&(l.memoizedState=t),t}function ro(l){var t=oo(l);t.next===null&&(t=l.alternate.memoizedState),lu(l,t.next.queue,{},ft())}function ac(){return Bl(gu)}function ho(){return _l().memoizedState}function mo(){return _l().memoizedState}function kh(l){for(var t=l.return;t!==null;){switch(t.tag){case 24:case 3:var e=ft();l=ie(e);var a=ce(t,l,e);a!==null&&(Il(a,t,e),$a(a,t,e)),t={cache:Ci()},l.payload=t;return}t=t.return}}function $h(l,t,e){var a=ft();e={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null},fn(l)?vo(t,e):(e=Ti(l,t,e,a),e!==null&&(Il(e,l,a),go(e,t,a)))}function yo(l,t,e){var a=ft();lu(l,t,e,a)}function lu(l,t,e,a){var u={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null};if(fn(l))vo(t,u);else{var n=l.alternate;if(l.lanes===0&&(n===null||n.lanes===0)&&(n=t.lastRenderedReducer,n!==null))try{var i=t.lastRenderedState,c=n(i,e);if(u.hasEagerState=!0,u.eagerState=c,et(c,i))return Qu(l,t,u,0),vl===null&&Xu(),!1}catch{}finally{}if(e=Ti(l,t,u,a),e!==null)return Il(e,l,a),go(e,t,a),!0}return!1}function uc(l,t,e,a){if(a={lane:2,revertLane:Bc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},fn(l)){if(t)throw Error(r(479))}else t=Ti(l,e,a,2),t!==null&&Il(t,l,2)}function fn(l){var t=l.alternate;return l===K||t!==null&&t===K}function vo(l,t){ha=ln=!0;var e=l.pending;e===null?t.next=t:(t.next=e.next,e.next=t),l.pending=t}function go(l,t,e){if((e&4194048)!==0){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,Tf(l,e)}}var tu={readContext:Bl,use:an,useCallback:Tl,useContext:Tl,useEffect:Tl,useImperativeHandle:Tl,useLayoutEffect:Tl,useInsertionEffect:Tl,useMemo:Tl,useReducer:Tl,useRef:Tl,useState:Tl,useDebugValue:Tl,useDeferredValue:Tl,useTransition:Tl,useSyncExternalStore:Tl,useId:Tl,useHostTransitionStatus:Tl,useFormState:Tl,useActionState:Tl,useOptimistic:Tl,useMemoCache:Tl,useCacheRefresh:Tl};tu.useEffectEvent=Tl;var So={readContext:Bl,use:an,useCallback:function(l,t){return Zl().memoizedState=[l,t===void 0?null:t],l},useContext:Bl,useEffect:lo,useImperativeHandle:function(l,t,e){e=e!=null?e.concat([l]):null,nn(4194308,4,uo.bind(null,t,l),e)},useLayoutEffect:function(l,t){return nn(4194308,4,l,t)},useInsertionEffect:function(l,t){nn(4,2,l,t)},useMemo:function(l,t){var e=Zl();t=t===void 0?null:t;var a=l();if(Ge){It(!0);try{l()}finally{It(!1)}}return e.memoizedState=[a,t],a},useReducer:function(l,t,e){var a=Zl();if(e!==void 0){var u=e(t);if(Ge){It(!0);try{e(t)}finally{It(!1)}}}else u=t;return a.memoizedState=a.baseState=u,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:u},a.queue=l,l=l.dispatch=$h.bind(null,K,l),[a.memoizedState,l]},useRef:function(l){var t=Zl();return l={current:l},t.memoizedState=l},useState:function(l){l=Fi(l);var t=l.queue,e=yo.bind(null,K,t);return t.dispatch=e,[l.memoizedState,e]},useDebugValue:lc,useDeferredValue:function(l,t){var e=Zl();return tc(e,l,t)},useTransition:function(){var l=Fi(!1);return l=so.bind(null,K,l.queue,!0,!1),Zl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,t,e){var a=K,u=Zl();if(el){if(e===void 0)throw Error(r(407));e=e()}else{if(e=t(),vl===null)throw Error(r(349));(I&127)!==0||Ys(a,t,e)}u.memoizedState=e;var n={value:e,getSnapshot:t};return u.queue=n,lo(Xs.bind(null,a,n,l),[l]),a.flags|=2048,ya(9,{destroy:void 0},Gs.bind(null,a,n,e,t),null),e},useId:function(){var l=Zl(),t=vl.identifierPrefix;if(el){var e=Mt,a=Nt;e=(a&~(1<<32-tt(a)-1)).toString(32)+e,t="_"+t+"R_"+e,e=tn++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?n.multiple=!0:a.size&&(n.size=a.size);break;default:n=typeof a.is=="string"?i.createElement(u,{is:a.is}):i.createElement(u)}}n[Rl]=t,n[Jl]=a;l:for(i=t.child;i!==null;){if(i.tag===5||i.tag===6)n.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===t)break l;for(;i.sibling===null;){if(i.return===null||i.return===t)break l;i=i.return}i.sibling.return=i.return,i=i.sibling}t.stateNode=n;l:switch(Yl(n,u,a),u){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break l;case"img":a=!0;break l;default:a=!1}a&&Vt(t)}}return Sl(t),Sc(t,t.type,l===null?null:l.memoizedProps,t.pendingProps,e),null;case 6:if(l&&t.stateNode!=null)l.memoizedProps!==a&&Vt(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(l=k.current,ia(t)){if(l=t.stateNode,e=t.memoizedProps,a=null,u=Hl,u!==null)switch(u.tag){case 27:case 5:a=u.memoizedProps}l[Rl]=t,l=!!(l.nodeValue===e||a!==null&&a.suppressHydrationWarning===!0||qd(l.nodeValue,e)),l||ae(t,!0)}else l=On(l).createTextNode(a),l[Rl]=t,t.stateNode=l}return Sl(t),null;case 31:if(e=t.memoizedState,l===null||l.memoizedState!==null){if(a=ia(t),e!==null){if(l===null){if(!a)throw Error(r(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(r(557));l[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),l=!1}else e=Oi(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=e),l=!0;if(!l)return t.flags&256?(nt(t),t):(nt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Sl(t),null;case 13:if(a=t.memoizedState,l===null||l.memoizedState!==null&&l.memoizedState.dehydrated!==null){if(u=ia(t),a!==null&&a.dehydrated!==null){if(l===null){if(!u)throw Error(r(318));if(u=t.memoizedState,u=u!==null?u.dehydrated:null,!u)throw Error(r(317));u[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),u=!1}else u=Oi(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=u),u=!0;if(!u)return t.flags&256?(nt(t),t):(nt(t),null)}return nt(t),(t.flags&128)!==0?(t.lanes=e,t):(e=a!==null,l=l!==null&&l.memoizedState!==null,e&&(a=t.child,u=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(u=a.alternate.memoizedState.cachePool.pool),n=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(n=a.memoizedState.cachePool.pool),n!==u&&(a.flags|=2048)),e!==l&&e&&(t.child.flags|=8192),hn(t,t.updateQueue),Sl(t),null);case 4:return Al(),l===null&&Xc(t.stateNode.containerInfo),Sl(t),null;case 10:return Xt(t.type),Sl(t),null;case 19:if(E(El),a=t.memoizedState,a===null)return Sl(t),null;if(u=(t.flags&128)!==0,n=a.rendering,n===null)if(u)au(a,!1);else{if(zl!==0||l!==null&&(l.flags&128)!==0)for(l=t.child;l!==null;){if(n=Pu(l),n!==null){for(t.flags|=128,au(a,!1),l=n.updateQueue,t.updateQueue=l,hn(t,l),t.subtreeFlags=0,l=e,e=t.child;e!==null;)ms(e,l),e=e.sibling;return N(El,El.current&1|2),el&&Yt(t,a.treeForkCount),t.child}l=l.sibling}a.tail!==null&&Pl()>Sn&&(t.flags|=128,u=!0,au(a,!1),t.lanes=4194304)}else{if(!u)if(l=Pu(n),l!==null){if(t.flags|=128,u=!0,l=l.updateQueue,t.updateQueue=l,hn(t,l),au(a,!0),a.tail===null&&a.tailMode==="hidden"&&!n.alternate&&!el)return Sl(t),null}else 2*Pl()-a.renderingStartTime>Sn&&e!==536870912&&(t.flags|=128,u=!0,au(a,!1),t.lanes=4194304);a.isBackwards?(n.sibling=t.child,t.child=n):(l=a.last,l!==null?l.sibling=n:t.child=n,a.last=n)}return a.tail!==null?(l=a.tail,a.rendering=l,a.tail=l.sibling,a.renderingStartTime=Pl(),l.sibling=null,e=El.current,N(El,u?e&1|2:e&1),el&&Yt(t,a.treeForkCount),l):(Sl(t),null);case 22:case 23:return nt(t),Qi(),a=t.memoizedState!==null,l!==null?l.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(e&536870912)!==0&&(t.flags&128)===0&&(Sl(t),t.subtreeFlags&6&&(t.flags|=8192)):Sl(t),e=t.updateQueue,e!==null&&hn(t,e.retryQueue),e=null,l!==null&&l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(e=l.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==e&&(t.flags|=2048),l!==null&&E(He),null;case 24:return e=null,l!==null&&(e=l.memoizedState.cache),t.memoizedState.cache!==e&&(t.flags|=2048),Xt(xl),Sl(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function lm(l,t){switch(xi(t),t.tag){case 1:return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 3:return Xt(xl),Al(),l=t.flags,(l&65536)!==0&&(l&128)===0?(t.flags=l&-65537|128,t):null;case 26:case 27:case 5:return Au(t),null;case 31:if(t.memoizedState!==null){if(nt(t),t.alternate===null)throw Error(r(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 13:if(nt(t),l=t.memoizedState,l!==null&&l.dehydrated!==null){if(t.alternate===null)throw Error(r(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 19:return E(El),null;case 4:return Al(),null;case 10:return Xt(t.type),null;case 22:case 23:return nt(t),Qi(),l!==null&&E(He),l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 24:return Xt(xl),null;case 25:return null;default:return null}}function Zo(l,t){switch(xi(t),t.tag){case 3:Xt(xl),Al();break;case 26:case 27:case 5:Au(t);break;case 4:Al();break;case 31:t.memoizedState!==null&&nt(t);break;case 13:nt(t);break;case 19:E(El);break;case 10:Xt(t.type);break;case 22:case 23:nt(t),Qi(),l!==null&&E(He);break;case 24:Xt(xl)}}function uu(l,t){try{var e=t.updateQueue,a=e!==null?e.lastEffect:null;if(a!==null){var u=a.next;e=u;do{if((e.tag&l)===l){a=void 0;var n=e.create,i=e.inst;a=n(),i.destroy=a}e=e.next}while(e!==u)}}catch(c){ol(t,t.return,c)}}function oe(l,t,e){try{var a=t.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var n=u.next;a=n;do{if((a.tag&l)===l){var i=a.inst,c=i.destroy;if(c!==void 0){i.destroy=void 0,u=t;var s=e,v=c;try{v()}catch(b){ol(u,s,b)}}}a=a.next}while(a!==n)}}catch(b){ol(t,t.return,b)}}function Lo(l){var t=l.updateQueue;if(t!==null){var e=l.stateNode;try{Cs(t,e)}catch(a){ol(l,l.return,a)}}}function Vo(l,t,e){e.props=Xe(l.type,l.memoizedProps),e.state=l.memoizedState;try{e.componentWillUnmount()}catch(a){ol(l,t,a)}}function nu(l,t){try{var e=l.ref;if(e!==null){switch(l.tag){case 26:case 27:case 5:var a=l.stateNode;break;case 30:a=l.stateNode;break;default:a=l.stateNode}typeof e=="function"?l.refCleanup=e(a):e.current=a}}catch(u){ol(l,t,u)}}function Dt(l,t){var e=l.ref,a=l.refCleanup;if(e!==null)if(typeof a=="function")try{a()}catch(u){ol(l,t,u)}finally{l.refCleanup=null,l=l.alternate,l!=null&&(l.refCleanup=null)}else if(typeof e=="function")try{e(null)}catch(u){ol(l,t,u)}else e.current=null}function Ko(l){var t=l.type,e=l.memoizedProps,a=l.stateNode;try{l:switch(t){case"button":case"input":case"select":case"textarea":e.autoFocus&&a.focus();break l;case"img":e.src?a.src=e.src:e.srcSet&&(a.srcset=e.srcSet)}}catch(u){ol(l,l.return,u)}}function bc(l,t,e){try{var a=l.stateNode;zm(a,l.type,e,t),a[Jl]=t}catch(u){ol(l,l.return,u)}}function Jo(l){return l.tag===5||l.tag===3||l.tag===26||l.tag===27&&ge(l.type)||l.tag===4}function pc(l){l:for(;;){for(;l.sibling===null;){if(l.return===null||Jo(l.return))return null;l=l.return}for(l.sibling.return=l.return,l=l.sibling;l.tag!==5&&l.tag!==6&&l.tag!==18;){if(l.tag===27&&ge(l.type)||l.flags&2||l.child===null||l.tag===4)continue l;l.child.return=l,l=l.child}if(!(l.flags&2))return l.stateNode}}function Tc(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?(e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e).insertBefore(l,t):(t=e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e,t.appendChild(l),e=e._reactRootContainer,e!=null||t.onclick!==null||(t.onclick=Ht));else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode,t=null),l=l.child,l!==null))for(Tc(l,t,e),l=l.sibling;l!==null;)Tc(l,t,e),l=l.sibling}function mn(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?e.insertBefore(l,t):e.appendChild(l);else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode),l=l.child,l!==null))for(mn(l,t,e),l=l.sibling;l!==null;)mn(l,t,e),l=l.sibling}function wo(l){var t=l.stateNode,e=l.memoizedProps;try{for(var a=l.type,u=t.attributes;u.length;)t.removeAttributeNode(u[0]);Yl(t,a,e),t[Rl]=l,t[Jl]=e}catch(n){ol(l,l.return,n)}}var Kt=!1,Nl=!1,zc=!1,ko=typeof WeakSet=="function"?WeakSet:Set,Ul=null;function tm(l,t){if(l=l.containerInfo,Lc=Hn,l=ns(l),yi(l)){if("selectionStart"in l)var e={start:l.selectionStart,end:l.selectionEnd};else l:{e=(e=l.ownerDocument)&&e.defaultView||window;var a=e.getSelection&&e.getSelection();if(a&&a.rangeCount!==0){e=a.anchorNode;var u=a.anchorOffset,n=a.focusNode;a=a.focusOffset;try{e.nodeType,n.nodeType}catch{e=null;break l}var i=0,c=-1,s=-1,v=0,b=0,A=l,g=null;t:for(;;){for(var S;A!==e||u!==0&&A.nodeType!==3||(c=i+u),A!==n||a!==0&&A.nodeType!==3||(s=i+a),A.nodeType===3&&(i+=A.nodeValue.length),(S=A.firstChild)!==null;)g=A,A=S;for(;;){if(A===l)break t;if(g===e&&++v===u&&(c=i),g===n&&++b===a&&(s=i),(S=A.nextSibling)!==null)break;A=g,g=A.parentNode}A=S}e=c===-1||s===-1?null:{start:c,end:s}}else e=null}e=e||{start:0,end:0}}else e=null;for(Vc={focusedElem:l,selectionRange:e},Hn=!1,Ul=t;Ul!==null;)if(t=Ul,l=t.child,(t.subtreeFlags&1028)!==0&&l!==null)l.return=t,Ul=l;else for(;Ul!==null;){switch(t=Ul,n=t.alternate,l=t.flags,t.tag){case 0:if((l&4)!==0&&(l=t.updateQueue,l=l!==null?l.events:null,l!==null))for(e=0;e title"))),Yl(n,a,e),n[Rl]=l,Cl(n),a=n;break l;case"link":var i=lr("link","href",u).get(a+(e.href||""));if(i){for(var c=0;cml&&(i=ml,ml=X,X=i);var h=as(c,X),o=as(c,ml);if(h&&o&&(S.rangeCount!==1||S.anchorNode!==h.node||S.anchorOffset!==h.offset||S.focusNode!==o.node||S.focusOffset!==o.offset)){var y=A.createRange();y.setStart(h.node,h.offset),S.removeAllRanges(),X>ml?(S.addRange(y),S.extend(o.node,o.offset)):(y.setEnd(o.node,o.offset),S.addRange(y))}}}}for(A=[],S=c;S=S.parentNode;)S.nodeType===1&&A.push({element:S,left:S.scrollLeft,top:S.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;ce?32:e,T.T=null,e=Nc,Nc=null;var n=me,i=Wt;if(Dl=0,pa=me=null,Wt=0,(cl&6)!==0)throw Error(r(331));var c=cl;if(cl|=4,nd(n.current),ed(n,n.current,i,e),cl=c,du(0,!1),lt&&typeof lt.onPostCommitFiberRoot=="function")try{lt.onPostCommitFiberRoot(Na,n)}catch{}return!0}finally{j.p=u,T.T=a,Ad(l,t)}}function _d(l,t,e){t=ht(e,t),t=fc(l.stateNode,t,2),l=ce(l,t,2),l!==null&&(Da(l,2),Ct(l))}function ol(l,t,e){if(l.tag===3)_d(l,l,e);else for(;t!==null;){if(t.tag===3){_d(t,l,e);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(he===null||!he.has(a))){l=ht(e,l),e=xo(2),a=ce(t,e,2),a!==null&&(jo(e,a,t,l),Da(a,2),Ct(a));break}}t=t.return}}function Uc(l,t,e){var a=l.pingCache;if(a===null){a=l.pingCache=new um;var u=new Set;a.set(t,u)}else u=a.get(t),u===void 0&&(u=new Set,a.set(t,u));u.has(e)||(_c=!0,u.add(e),l=sm.bind(null,l,t,e),t.then(l,l))}function sm(l,t,e){var a=l.pingCache;a!==null&&a.delete(t),l.pingedLanes|=l.suspendedLanes&e,l.warmLanes&=~e,vl===l&&(I&e)===e&&(zl===4||zl===3&&(I&62914560)===I&&300>Pl()-gn?(cl&2)===0&&Ta(l,0):xc|=e,ba===I&&(ba=0)),Ct(l)}function xd(l,t){t===0&&(t=bf()),l=Me(l,t),l!==null&&(Da(l,t),Ct(l))}function om(l){var t=l.memoizedState,e=0;t!==null&&(e=t.retryLane),xd(l,e)}function dm(l,t){var e=0;switch(l.tag){case 31:case 13:var a=l.stateNode,u=l.memoizedState;u!==null&&(e=u.retryLane);break;case 19:a=l.stateNode;break;case 22:a=l.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),xd(l,e)}function rm(l,t){return Jn(l,t)}var En=null,Aa=null,Rc=!1,_n=!1,Hc=!1,ve=0;function Ct(l){l!==Aa&&l.next===null&&(Aa===null?En=Aa=l:Aa=Aa.next=l),_n=!0,Rc||(Rc=!0,mm())}function du(l,t){if(!Hc&&_n){Hc=!0;do for(var e=!1,a=En;a!==null;){if(l!==0){var u=a.pendingLanes;if(u===0)var n=0;else{var i=a.suspendedLanes,c=a.pingedLanes;n=(1<<31-tt(42|l)+1)-1,n&=u&~(i&~c),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(e=!0,Md(a,n))}else n=I,n=Ou(a,a===vl?n:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(n&3)===0||Ma(a,n)||(e=!0,Md(a,n));a=a.next}while(e);Hc=!1}}function hm(){jd()}function jd(){_n=Rc=!1;var l=0;ve!==0&&Em()&&(l=ve);for(var t=Pl(),e=null,a=En;a!==null;){var u=a.next,n=Od(a,t);n===0?(a.next=null,e===null?En=u:e.next=u,u===null&&(Aa=e)):(e=a,(l!==0||(n&3)!==0)&&(_n=!0)),a=u}Dl!==0&&Dl!==5||du(l),ve!==0&&(ve=0)}function Od(l,t){for(var e=l.suspendedLanes,a=l.pingedLanes,u=l.expirationTimes,n=l.pendingLanes&-62914561;0c)break;var b=s.transferSize,A=s.initiatorType;b&&Yd(A)&&(s=s.responseEnd,i+=b*(s"u"?null:document;function Wd(l,t,e){var a=Ea;if(a&&typeof t=="string"&&t){var u=dt(t);u='link[rel="'+l+'"][href="'+u+'"]',typeof e=="string"&&(u+='[crossorigin="'+e+'"]'),$d.has(u)||($d.add(u),l={rel:l,crossOrigin:e,href:t},a.querySelector(u)===null&&(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Um(l){Ft.D(l),Wd("dns-prefetch",l,null)}function Rm(l,t){Ft.C(l,t),Wd("preconnect",l,t)}function Hm(l,t,e){Ft.L(l,t,e);var a=Ea;if(a&&l&&t){var u='link[rel="preload"][as="'+dt(t)+'"]';t==="image"&&e&&e.imageSrcSet?(u+='[imagesrcset="'+dt(e.imageSrcSet)+'"]',typeof e.imageSizes=="string"&&(u+='[imagesizes="'+dt(e.imageSizes)+'"]')):u+='[href="'+dt(l)+'"]';var n=u;switch(t){case"style":n=_a(l);break;case"script":n=xa(l)}bt.has(n)||(l=x({rel:"preload",href:t==="image"&&e&&e.imageSrcSet?void 0:l,as:t},e),bt.set(n,l),a.querySelector(u)!==null||t==="style"&&a.querySelector(yu(n))||t==="script"&&a.querySelector(vu(n))||(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Bm(l,t){Ft.m(l,t);var e=Ea;if(e&&l){var a=t&&typeof t.as=="string"?t.as:"script",u='link[rel="modulepreload"][as="'+dt(a)+'"][href="'+dt(l)+'"]',n=u;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=xa(l)}if(!bt.has(n)&&(l=x({rel:"modulepreload",href:l},t),bt.set(n,l),e.querySelector(u)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(e.querySelector(vu(n)))return}a=e.createElement("link"),Yl(a,"link",l),Cl(a),e.head.appendChild(a)}}}function qm(l,t,e){Ft.S(l,t,e);var a=Ea;if(a&&l){var u=we(a).hoistableStyles,n=_a(l);t=t||"default";var i=u.get(n);if(!i){var c={loading:0,preload:null};if(i=a.querySelector(yu(n)))c.loading=5;else{l=x({rel:"stylesheet",href:l,"data-precedence":t},e),(e=bt.get(n))&&Fc(l,e);var s=i=a.createElement("link");Cl(s),Yl(s,"link",l),s._p=new Promise(function(v,b){s.onload=v,s.onerror=b}),s.addEventListener("load",function(){c.loading|=1}),s.addEventListener("error",function(){c.loading|=2}),c.loading|=4,Mn(i,t,a)}i={type:"stylesheet",instance:i,count:1,state:c},u.set(n,i)}}}function Ym(l,t){Ft.X(l,t);var e=Ea;if(e&&l){var a=we(e).hoistableScripts,u=xa(l),n=a.get(u);n||(n=e.querySelector(vu(u)),n||(l=x({src:l,async:!0},t),(t=bt.get(u))&&Ic(l,t),n=e.createElement("script"),Cl(n),Yl(n,"link",l),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Gm(l,t){Ft.M(l,t);var e=Ea;if(e&&l){var a=we(e).hoistableScripts,u=xa(l),n=a.get(u);n||(n=e.querySelector(vu(u)),n||(l=x({src:l,async:!0,type:"module"},t),(t=bt.get(u))&&Ic(l,t),n=e.createElement("script"),Cl(n),Yl(n,"link",l),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Fd(l,t,e,a){var u=(u=k.current)?Nn(u):null;if(!u)throw Error(r(446));switch(l){case"meta":case"title":return null;case"style":return typeof e.precedence=="string"&&typeof e.href=="string"?(t=_a(e.href),e=we(u).hoistableStyles,a=e.get(t),a||(a={type:"style",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(e.rel==="stylesheet"&&typeof e.href=="string"&&typeof e.precedence=="string"){l=_a(e.href);var n=we(u).hoistableStyles,i=n.get(l);if(i||(u=u.ownerDocument||u,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(l,i),(n=u.querySelector(yu(l)))&&!n._p&&(i.instance=n,i.state.loading=5),bt.has(l)||(e={rel:"preload",as:"style",href:e.href,crossOrigin:e.crossOrigin,integrity:e.integrity,media:e.media,hrefLang:e.hrefLang,referrerPolicy:e.referrerPolicy},bt.set(l,e),n||Xm(u,l,e,i.state))),t&&a===null)throw Error(r(528,""));return i}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=e.async,e=e.src,typeof e=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=xa(e),e=we(u).hoistableScripts,a=e.get(t),a||(a={type:"script",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,l))}}function _a(l){return'href="'+dt(l)+'"'}function yu(l){return'link[rel="stylesheet"]['+l+"]"}function Id(l){return x({},l,{"data-precedence":l.precedence,precedence:null})}function Xm(l,t,e,a){l.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=l.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Yl(t,"link",e),Cl(t),l.head.appendChild(t))}function xa(l){return'[src="'+dt(l)+'"]'}function vu(l){return"script[async]"+l}function Pd(l,t,e){if(t.count++,t.instance===null)switch(t.type){case"style":var a=l.querySelector('style[data-href~="'+dt(e.href)+'"]');if(a)return t.instance=a,Cl(a),a;var u=x({},e,{"data-href":e.href,"data-precedence":e.precedence,href:null,precedence:null});return a=(l.ownerDocument||l).createElement("style"),Cl(a),Yl(a,"style",u),Mn(a,e.precedence,l),t.instance=a;case"stylesheet":u=_a(e.href);var n=l.querySelector(yu(u));if(n)return t.state.loading|=4,t.instance=n,Cl(n),n;a=Id(e),(u=bt.get(u))&&Fc(a,u),n=(l.ownerDocument||l).createElement("link"),Cl(n);var i=n;return i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(n,"link",a),t.state.loading|=4,Mn(n,e.precedence,l),t.instance=n;case"script":return n=xa(e.src),(u=l.querySelector(vu(n)))?(t.instance=u,Cl(u),u):(a=e,(u=bt.get(n))&&(a=x({},e),Ic(a,u)),l=l.ownerDocument||l,u=l.createElement("script"),Cl(u),Yl(u,"link",a),l.head.appendChild(u),t.instance=u);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Mn(a,e.precedence,l));return t.instance}function Mn(l,t,e){for(var a=e.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),u=a.length?a[a.length-1]:null,n=u,i=0;i title"):null)}function Qm(l,t,e){if(e===1||t.itemProp!=null)return!1;switch(l){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return l=t.disabled,typeof t.precedence=="string"&&l==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function er(l){return!(l.type==="stylesheet"&&(l.state.loading&3)===0)}function Zm(l,t,e,a){if(e.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(e.state.loading&4)===0){if(e.instance===null){var u=_a(a.href),n=t.querySelector(yu(u));if(n){t=n._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(l.count++,l=Cn.bind(l),t.then(l,l)),e.state.loading|=4,e.instance=n,Cl(n);return}n=t.ownerDocument||t,a=Id(a),(u=bt.get(u))&&Fc(a,u),n=n.createElement("link"),Cl(n);var i=n;i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(n,"link",a),e.instance=n}l.stylesheets===null&&(l.stylesheets=new Map),l.stylesheets.set(e,t),(t=e.state.preload)&&(e.state.loading&3)===0&&(l.count++,e=Cn.bind(l),t.addEventListener("load",e),t.addEventListener("error",e))}}var Pc=0;function Lm(l,t){return l.stylesheets&&l.count===0&&Rn(l,l.stylesheets),0Pc?50:800)+t);return l.unsuspend=e,function(){l.unsuspend=null,clearTimeout(a),clearTimeout(u)}}:null}function Cn(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Rn(this,this.stylesheets);else if(this.unsuspend){var l=this.unsuspend;this.unsuspend=null,l()}}}var Un=null;function Rn(l,t){l.stylesheets=null,l.unsuspend!==null&&(l.count++,Un=new Map,t.forEach(Vm,l),Un=null,Cn.call(l))}function Vm(l,t){if(!(t.state.loading&4)){var e=Un.get(l);if(e)var a=e.get(null);else{e=new Map,Un.set(l,e);for(var u=l.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(m)}catch(H){console.error(H)}}return m(),sf.exports=iy(),sf.exports}var fy=cy();const sy=Or(fy),oy="";async function Et(m,H){const D=await fetch(`${oy}${m}`,{...H,credentials:"same-origin",headers:{"Content-Type":"application/json",...H==null?void 0:H.headers}});if(D.status===401)throw window.location.hash="#login",new Error("Unauthorized");if(!D.ok){const r=await D.json().catch(()=>({}));throw new Error(r.error||`HTTP ${D.status}`)}return D.json()}const _t={login:m=>Et("/admin/login",{method:"POST",body:JSON.stringify({token:m})}),signOutEverywhere:()=>Et("/admin/api/sign-out-everywhere",{method:"POST"}),stats:()=>Et("/admin/api/stats"),health:()=>Et("/admin/api/health-indicators"),agents:()=>Et("/admin/api/agents"),requests:(m=1,H="")=>Et(`/admin/api/requests?page=${m}${H}`),apiKeys:()=>Et("/admin/api/api-keys"),createApiKey:m=>Et("/admin/api/api-keys",{method:"POST",body:JSON.stringify({name:m})}),revokeApiKey:m=>Et("/admin/api/api-keys/revoke",{method:"POST",body:JSON.stringify({name:m})}),updateClientTtl:(m,H)=>Et("/admin/api/update-client-ttl",{method:"POST",body:JSON.stringify({clientId:m,tokenTtl:H})}),revokeClient:m=>Et("/admin/api/revoke-client",{method:"POST",body:JSON.stringify({clientId:m})})};function dy({onLogin:m}){const[H,D]=ul.useState(""),[r,O]=ul.useState(""),[G,U]=ul.useState(!1),w=async M=>{M.preventDefault(),O(""),U(!0);try{await _t.login(H),D(""),m()}catch{O("Invalid token.")}finally{U(!1)}};return f.jsx("div",{className:"login-page",children:f.jsxs("div",{className:"login-box",children:[f.jsx("div",{className:"login-logo",children:"GBrain"}),f.jsxs("div",{style:{background:"rgba(136, 170, 255, 0.08)",border:"1px solid rgba(136, 170, 255, 0.2)",borderRadius:8,padding:"14px 16px",marginBottom:20,fontSize:13,lineHeight:1.5,color:"var(--text-secondary)"},children:[f.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:"🔒 This is a protected dashboard"}),"Ask your AI agent for the admin login link:",f.jsx("div",{style:{background:"rgba(0,0,0,0.3)",borderRadius:6,padding:"8px 12px",marginTop:8,fontFamily:"var(--font-mono)",fontSize:12,color:"#88aaff",wordBreak:"break-all"},children:'"Give me the GBrain admin login link"'}),f.jsx("div",{style:{marginTop:8,fontSize:12,color:"var(--text-muted)"},children:"Each link is single-use. Your agent generates a fresh one each time."})]}),f.jsxs("details",{style:{marginBottom:16},children:[f.jsx("summary",{style:{cursor:"pointer",fontSize:13,color:"var(--text-muted)"},children:"Or paste bootstrap token manually"}),f.jsxs("form",{onSubmit:w,style:{marginTop:12},children:[f.jsx("div",{style:{marginBottom:12},children:f.jsx("input",{type:"password",placeholder:"Admin Token",value:H,onChange:M=>D(M.target.value)})}),f.jsx("button",{className:"btn btn-primary",style:{width:"100%"},disabled:G,children:G?"Authenticating...":"Submit"}),r&&f.jsx("div",{className:"login-error",children:r})]})]})]})})}function ry(){const[m,H]=ul.useState({connected_agents:0,requests_today:0,active_tokens:0}),[D,r]=ul.useState({expiring_soon:0,error_rate:"0%"}),[O,G]=ul.useState([]),[U,w]=ul.useState("connecting"),M=ul.useRef(null);ul.useEffect(()=>{_t.stats().then(H).catch(()=>{}),_t.health().then(r).catch(()=>{});const R=new EventSource("/admin/events");M.current=R,R.onopen=()=>w("connected"),R.onmessage=_=>{try{const F=JSON.parse(_.data);G(Z=>[F,...Z].slice(0,50))}catch{}},R.onerror=()=>{w("disconnected"),setTimeout(()=>{w("connecting"),R.close()},3e3)};const x=setInterval(()=>{_t.stats().then(H).catch(()=>{}),_t.health().then(r).catch(()=>{})},3e4);return()=>{R.close(),clearInterval(x)}},[]);const p=R=>{const x=Date.now()-new Date(R).getTime();return x<6e4?`${Math.floor(x/1e3)}s ago`:x<36e5?`${Math.floor(x/6e4)} min ago`:`${Math.floor(x/36e5)}h ago`};return f.jsxs(f.Fragment,{children:[f.jsx("h1",{className:"page-title",children:"Dashboard"}),f.jsxs("div",{style:{display:"flex",gap:24},children:[f.jsxs("div",{style:{flex:1},children:[f.jsxs("div",{className:"metrics",children:[f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.connected_agents}),f.jsx("div",{className:"metric-label",children:"Connected Agents"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.requests_today}),f.jsx("div",{className:"metric-label",children:"Requests Today"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.active_tokens}),f.jsx("div",{className:"metric-label",children:"Active Tokens"})]})]}),f.jsxs("h2",{className:"section-title",children:["Live Activity",f.jsx("span",{style:{marginLeft:8,fontSize:10,color:U==="connected"?"var(--success)":U==="connecting"?"var(--warning)":"var(--error)"},children:U==="connected"?"● connected":U==="connecting"?"● connecting...":"● disconnected"})]}),f.jsx("div",{className:"feed",children:O.length===0?f.jsx("div",{className:"feed-empty",children:U==="connected"?"No requests yet. Agents will appear when they connect.":"Connecting..."}):f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Time"})]})}),f.jsx("tbody",{children:O.map((R,x)=>f.jsxs("tr",{children:[f.jsx("td",{className:"mono",children:R.agent}),f.jsx("td",{className:"mono",children:R.operation}),f.jsx("td",{children:R.scopes.split(",").map(_=>f.jsx("span",{className:`badge badge-${_.trim()}`,style:{marginRight:4},children:_.trim()},_))}),f.jsxs("td",{className:"mono",children:[R.latency_ms," ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${R.status}`,children:R.status})}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:p(R.timestamp)})]},x))})]})})]}),f.jsxs("div",{style:{width:220},children:[f.jsx("h2",{className:"section-title",children:"Token Health"}),f.jsxs("div",{className:"health-panel",children:[f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--warning)"},children:"Expiring Soon"}),f.jsx("span",{className:"mono",children:D.expiring_soon})]}),f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--error)"},children:"Error Rate"}),f.jsx("span",{className:"mono",children:D.error_rate})]})]})]})]})]})}const xr=["admin","read","sources_admin","users_admin","write"];function hy(m){const H=Math.floor((Date.now()-m.getTime())/1e3);return H<60?"just now":H<3600?`${Math.floor(H/60)}m ago`:H<86400?`${Math.floor(H/3600)}h ago`:`${Math.floor(H/86400)}d ago`}function my(){const[m,H]=ul.useState([]),[D,r]=ul.useState(!0),[O,G]=ul.useState(!1),[U,w]=ul.useState(null),[M,p]=ul.useState(!1),[R,x]=ul.useState(null),[_,F]=ul.useState(null);ul.useEffect(()=>{Z()},[]);const Z=()=>{_t.agents().then(H).catch(()=>{})};return f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Agents"}),f.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[f.jsxs("label",{style:{fontSize:13,color:"var(--text-secondary)",display:"flex",alignItems:"center",gap:6,cursor:"pointer"},children:[f.jsx("input",{type:"checkbox",checked:D,onChange:al=>r(al.target.checked)})," Hide revoked"]}),f.jsx("button",{className:"btn btn-secondary",onClick:()=>p(!0),children:"+ API Key"}),f.jsx("button",{className:"btn btn-primary",onClick:()=>G(!0),children:"+ OAuth Client"})]})]}),(()=>{const al=m.filter(ll=>!D||ll.status!=="revoked");return m.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No agents registered. Register your first agent to get started."}):al.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:'All agents are revoked. Uncheck "Hide revoked" to view them.'}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Name"}),f.jsx("th",{children:"Type"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Requests"}),f.jsx("th",{children:"Last Used"})]})}),f.jsx("tbody",{children:al.map(ll=>f.jsxs("tr",{onClick:()=>F(ll),style:{cursor:"pointer"},children:[f.jsx("td",{style:{fontWeight:500},children:ll.name||ll.client_name}),f.jsx("td",{children:f.jsx("span",{className:`badge ${ll.auth_type==="oauth"?"badge-read":"badge-write"}`,style:{fontSize:11},children:ll.auth_type==="oauth"?"OAuth":"API Key"})}),f.jsx("td",{children:(ll.scope||"").split(" ").filter(Boolean).map(pl=>f.jsx("span",{className:`badge badge-${pl}`,style:{marginRight:4},children:pl},pl))}),f.jsx("td",{children:f.jsx("span",{className:`badge ${ll.status==="active"?"badge-success":"badge-danger"}`,children:ll.status})}),f.jsxs("td",{children:[f.jsx("span",{style:{fontWeight:500},children:ll.requests_today||0}),f.jsxs("span",{style:{color:"var(--text-muted)",fontSize:12},children:[" / ",ll.total_requests||0]})]}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:ll.last_used_at?hy(new Date(ll.last_used_at)):"Never"})]},ll.id))})]}),f.jsxs("div",{style:{color:"var(--text-muted)",fontSize:13,marginTop:12},children:[m.filter(ll=>ll.status==="active").length," active / ",m.length," total"]})]})})(),O&&f.jsx(gy,{onClose:()=>G(!1),onRegistered:al=>{G(!1),w(al),Z()}}),U&&f.jsx(Sy,{credentials:U,onClose:()=>w(null)}),_&&f.jsx(by,{agent:_,onClose:()=>F(null),onRevoked:Z}),M&&f.jsx(yy,{onClose:()=>p(!1),onCreated:al=>{p(!1),x(al),Z()}}),R&&f.jsx(vy,{token:R,onClose:()=>x(null)})]})}function yy({onClose:m,onCreated:H}){const[D,r]=ul.useState(""),[O,G]=ul.useState(!1),[U,w]=ul.useState(""),M=async p=>{if(p.preventDefault(),!D.trim()){w("Name required");return}G(!0);try{const R=await _t.createApiKey(D.trim());H({name:R.name,token:R.token})}catch(R){w(R instanceof Error?R.message:"Failed")}finally{G(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:m,children:f.jsxs("form",{className:"modal",onClick:p=>p.stopPropagation(),onSubmit:M,children:[f.jsx("div",{className:"modal-title",children:"Create API Key"}),f.jsx("p",{style:{color:"var(--text-secondary)",fontSize:13,marginBottom:16},children:"API keys use simple bearer token auth. They grant full read+write+admin access. For scoped access, use OAuth clients instead."}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Key Name"}),f.jsx("input",{placeholder:"e.g. claude-code-local",value:D,onChange:p=>r(p.target.value),autoFocus:!0})]}),U&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:U}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:m,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:O,children:O?"Creating...":"Create Key"})]})]})})}function vy({token:m,onClose:H}){const D=r=>navigator.clipboard.writeText(r);return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"API Key Created"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Name"}),f.jsx("div",{className:"code-block",children:f.jsx("span",{children:m.name})})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Bearer Token"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.token}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.token),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Usage"}),f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0,fontSize:12},children:`Authorization: Bearer ${m.token}`}),f.jsx("button",{className:"copy-btn",onClick:()=>D(`Authorization: Bearer ${m.token}`),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this token now. It will not be shown again."}),f.jsx("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:f.jsx("button",{className:"btn btn-primary",onClick:H,children:"Done"})})]})})}function gy({onClose:m,onRegistered:H}){const[D,r]=ul.useState(""),[O,G]=ul.useState(()=>Object.fromEntries(xr.map(Z=>[Z,Z==="read"]))),[U,w]=ul.useState("86400"),[M,p]=ul.useState(!1),[R,x]=ul.useState(""),_=[{label:"1 hour",value:"3600"},{label:"24 hours",value:"86400"},{label:"7 days",value:"604800"},{label:"30 days",value:"2592000"},{label:"1 year",value:"31536000"},{label:"No expiry",value:"0"}],F=async Z=>{if(Z.preventDefault(),!D.trim()){x("Name required");return}p(!0),x("");try{const al=Object.entries(O).filter(([,Ml])=>Ml).map(([Ml])=>Ml).join(" "),ll=await fetch("/admin/api/register-client",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D.trim(),scopes:al,tokenTtl:U==="0"?31536e4:Number(U)})});if(!ll.ok)throw new Error("Registration failed");const pl=await ll.json();H({clientId:pl.clientId,clientSecret:pl.clientSecret,name:D.trim()})}catch(al){x(al instanceof Error?al.message:"Registration failed")}finally{p(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:m,children:f.jsxs("form",{className:"modal",onClick:Z=>Z.stopPropagation(),onSubmit:F,children:[f.jsx("div",{className:"modal-title",children:"Register Agent"}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Agent Name"}),f.jsx("input",{placeholder:"e.g. perplexity-production",value:D,onChange:Z=>r(Z.target.value),autoFocus:!0})]}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Scopes"}),f.jsx("div",{className:"checkbox-group",children:xr.map(Z=>f.jsxs("label",{className:"checkbox-label",children:[f.jsx("input",{type:"checkbox",checked:O[Z],onChange:al=>G(ll=>({...ll,[Z]:al.target.checked}))}),Z]},Z))})]}),f.jsxs("div",{style:{marginBottom:20},children:[f.jsx("label",{children:"Token Lifetime"}),f.jsx("select",{value:U,onChange:Z=>w(Z.target.value),style:{width:"100%",background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"6px 10px",fontSize:14},children:_.map(Z=>f.jsx("option",{value:Z.value,children:Z.label},Z.value))})]}),R&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:R}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:m,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:M,children:M?"Registering...":"Register"})]})]})})}function Sy({credentials:m,onClose:H}){const D=O=>navigator.clipboard.writeText(O),r=()=>{const O=new Blob([JSON.stringify(m,null,2)],{type:"application/json"}),G=URL.createObjectURL(O),U=document.createElement("a");U.href=G,U.download=`${m.name}-credentials.json`,U.click(),URL.revokeObjectURL(G)};return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"Agent Registered"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client ID"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.clientId}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.clientId),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client Secret"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.clientSecret}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.clientSecret),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this secret now. It will not be shown again."}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:[f.jsx("button",{className:"btn btn-secondary",onClick:r,children:"Download as JSON"}),f.jsx("button",{className:"btn btn-primary",onClick:H,children:"Done"})]})]})})}function by({agent:m,onClose:H,onRevoked:D}){const[r,O]=ul.useState("claude-code"),G=x=>navigator.clipboard.writeText(x),U=window.location.origin,w=m.id||m.client_id||"",M=m.auth_type==="oauth",p=m.name||m.client_name||"unknown",R={"claude-code":M?["The user wants to connect GBrain MCP to your context. Here's how.","","# Step 1 — read the client secret from the operator without putting it in shell history.","# read -s suppresses the echo; export keeps it scoped to this shell session.",'read -rs -p "Client Secret: " GBRAIN_CS && echo',"","# Step 2 — mint a token and register GBrain in one go.",`claude mcp add --transport http gbrain ${U}/mcp \\`,` --header "Authorization: Bearer $(curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${w}' \\`,' --data-urlencode "client_secret=$GBRAIN_CS" \\',` -d 'scope=${m.scope||"read write"}' | jq -r .access_token)"`,"","# Step 3 — clear the secret from this shell.","unset GBRAIN_CS","",`The token will last ${m.token_ttl?m.token_ttl>=86400?Math.floor(m.token_ttl/86400)+" days":Math.floor(m.token_ttl/3600)+" hours":"1 hour (default)"}.`,"","─── Fallback: 2-step curl + paste ───","","If your shell doesn't support read -s, mint the token first, then paste:","",`curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${w}' \\`," -d 'client_secret=PASTE_YOUR_CLIENT_SECRET_HERE' \\",` -d 'scope=${m.scope||"read write"}' | jq -r .access_token`,"",`claude mcp add --transport http gbrain ${U}/mcp \\`,' --header "Authorization: Bearer PASTE_TOKEN_FROM_ABOVE"',"","# Then run: history -d $((HISTCMD-1)) # zsh: print -s -- '' && fc -p"].join(` -`):["The user wants to connect GBrain MCP to your context. Here's how.","","Run this command in terminal to register GBrain:","",`claude mcp add --transport http gbrain ${U}/mcp \\`,' --header "Authorization: Bearer PASTE_YOUR_API_KEY_HERE"',"",`Replace PASTE_YOUR_API_KEY_HERE with the API key shown when "${p}" was created.`,"API keys never expire."].join(` -`),chatgpt:["The user wants to connect GBrain MCP to ChatGPT.","","1. Open ChatGPT > Settings > Tools & Integrations > Add MCP Server","2. Enter this URL — ChatGPT will auto-discover the OAuth configuration:","",` ${U}/.well-known/oauth-authorization-server`,"","3. When prompted for credentials:",` Client ID: ${w}`," Client Secret: (the secret from agent registration)"," Grant Type: client_credentials",` Scope: ${m.scope||"read write"}`].join(` -`),"claude-cowork":["The user wants to connect GBrain MCP to Claude.ai.","","1. Open claude.ai > Settings > Connected Apps > Add MCP Server",`2. Server URL: ${U}/mcp`,"3. When prompted for auth:",` Token endpoint: ${U}/token`,` Client ID: ${w}`," Client Secret: (the secret from agent registration)",` Scope: ${m.scope||"read write"}`,"",`Discovery URL: ${U}/.well-known/oauth-authorization-server`].join(` -`),cursor:M?["The user wants to connect GBrain MCP to Cursor.","","Cursor supports OAuth for remote MCP. Add to .cursor/mcp.json:","","{",' "mcpServers": {',' "gbrain": {',` "url": "${U}/mcp",`,' "transport": "sse"'," }"," }","}","","Cursor will auto-discover OAuth via:",`${U}/.well-known/oauth-authorization-server`,"",`When prompted: Client ID ${w}, use the secret from registration.`].join(` -`):["The user wants to connect GBrain MCP to Cursor.","","Add to .cursor/mcp.json:","","{",' "mcpServers": {',' "gbrain": {',` "url": "${U}/mcp",`,' "transport": "sse",',' "headers": {',' "Authorization": "Bearer PASTE_YOUR_API_KEY_HERE"'," }"," }"," }","}","",`Replace PASTE_YOUR_API_KEY_HERE with the API key shown when "${p}" was created.`].join(` -`),perplexity:["The user wants to connect GBrain MCP to Perplexity.","","1. Go to Settings > Connectors > Add MCP",`2. Server URL: ${U}/mcp`,`3. Client ID: ${w}`,"4. Client Secret: (the secret from agent registration)"].join(` -`),json:JSON.stringify({server_url:U+"/mcp",token_url:U+"/token",discovery_url:U+"/.well-known/oauth-authorization-server",client_id:w,client_name:p,auth_type:m.auth_type,scope:m.scope},null,2)};return f.jsxs(f.Fragment,{children:[f.jsx("div",{className:"drawer-overlay",onClick:H}),f.jsxs("div",{className:"drawer",children:[f.jsx("button",{className:"drawer-close",onClick:H,children:"✕"}),f.jsx("div",{style:{fontSize:18,fontWeight:600,marginBottom:4},children:m.name||m.client_name}),f.jsx("span",{className:`badge ${m.status==="active"?"badge-success":"badge-danger"}`,children:m.status}),f.jsx("div",{className:"section-title",children:"Details"}),f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Client ID"}),f.jsxs("span",{className:"mono",children:[(m.id||m.id||m.client_id||"").substring(0,24),"..."]}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Scopes"}),f.jsx("span",{children:(m.scope||"").split(" ").filter(Boolean).map(x=>f.jsx("span",{className:`badge badge-${x}`,style:{marginRight:4},children:x},x))}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Registered"}),f.jsx("span",{children:new Date(m.created_at).toLocaleDateString()}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Token TTL"}),f.jsx("span",{children:m.token_ttl?m.token_ttl>=31536e3?"No expiry":m.token_ttl>=86400?`${Math.floor(m.token_ttl/86400)}d`:m.token_ttl>=3600?`${Math.floor(m.token_ttl/3600)}h`:`${m.token_ttl}s`:"1h (default)"})]}),f.jsx("div",{className:"section-title",children:"Config Export"}),f.jsxs("div",{className:"tabs",style:{flexWrap:"wrap"},children:[f.jsx("div",{className:`tab ${r==="claude-code"?"active":""}`,onClick:()=>O("claude-code"),children:"Claude Code"}),f.jsx("div",{className:`tab ${r==="chatgpt"?"active":""}`,onClick:()=>O("chatgpt"),children:"ChatGPT"}),f.jsx("div",{className:`tab ${r==="claude-cowork"?"active":""}`,onClick:()=>O("claude-cowork"),children:"Claude.ai"}),f.jsx("div",{className:`tab ${r==="cursor"?"active":""}`,onClick:()=>O("cursor"),children:"Cursor"}),f.jsx("div",{className:`tab ${r==="perplexity"?"active":""}`,onClick:()=>O("perplexity"),children:"Perplexity"}),f.jsx("div",{className:`tab ${r==="json"?"active":""}`,onClick:()=>O("json"),children:"JSON"})]}),(()=>{if(!M&&new Set(["chatgpt","claude-cowork","perplexity"]).has(r)){const _={chatgpt:"ChatGPT","claude-cowork":"Claude.ai",perplexity:"Perplexity"}[r]||r;return f.jsxs("div",{style:{background:"rgba(255, 200, 100, 0.08)",border:"1px solid rgba(255, 200, 100, 0.2)",borderRadius:8,padding:"14px 16px",marginTop:12,fontSize:13,lineHeight:1.6,color:"var(--text-secondary)"},children:[f.jsxs("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:[_," requires an OAuth client"]}),_," only supports OAuth 2.0 (client_credentials). API keys use raw bearer tokens, which ",_," does not accept. Register a separate OAuth client and use that to connect this AI."]})}return f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0},children:R[r]}),f.jsx("button",{className:"copy-btn",onClick:()=>G(R[r]),children:"Copy"})]})})(),f.jsxs("div",{style:{marginTop:32},children:[m.status==="active"&&f.jsx("button",{className:"btn btn-danger",onClick:async()=>{if(confirm(`Revoke ${m.name||m.client_name}? All active tokens will be invalidated.`))try{m.auth_type==="oauth"?await _t.revokeClient(m.id||m.client_id||""):await _t.revokeApiKey(m.name||""),D(),H()}catch(x){alert("Revoke failed: "+(x instanceof Error?x.message:"unknown error"))}},children:"Revoke Agent"}),m.status==="revoked"&&f.jsx("span",{style:{color:"var(--text-muted)",fontSize:13},children:"This agent has been revoked."})]})]})]})}function py(){const[m,H]=ul.useState({rows:[],total:0,page:1,pages:1}),[D,r]=ul.useState(1),[O,G]=ul.useState("all"),[U,w]=ul.useState(null);ul.useEffect(()=>{M(D)},[D,O]);const M=_=>{const F=O!=="all"?`&agent=${encodeURIComponent(O)}`:"";_t.requests(_,F).then(H).catch(()=>{})},p=_=>{const F=Date.now()-new Date(_).getTime();return F<6e4?`${Math.floor(F/1e3)}s ago`:F<36e5?`${Math.floor(F/6e4)} min ago`:F<864e5?`${Math.floor(F/36e5)}h ago`:new Date(_).toLocaleDateString()},R=_=>{if(!_)return null;const{query:F,slug:Z,partial:al,limit:ll,...pl}=_,Ml=[];return F&&Ml.push(`"${F}"`),Z&&Ml.push(Z),al&&Ml.push(`~${al}`),ll&&Ml.push(`limit=${ll}`),Object.keys(pl).length>0&&Ml.push(`+${Object.keys(pl).length} params`),Ml.join(" ")},x=new Map;return m.rows.forEach(_=>{_.token_name&&x.set(_.token_name,_.agent_name||_.token_name)}),f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Request Log"}),f.jsxs("select",{value:O,onChange:_=>{G(_.target.value),r(1)},style:{background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"4px 8px",fontSize:13},children:[f.jsx("option",{value:"all",children:"All agents"}),[...x.entries()].map(([_,F])=>f.jsx("option",{value:_,children:F},_))]})]}),m.rows.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No requests yet."}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Time"}),f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Params"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"})]})}),f.jsx("tbody",{children:m.rows.map(_=>f.jsxs(Nr.Fragment,{children:[f.jsxs("tr",{onClick:()=>w(U===_.id?null:_.id),style:{cursor:"pointer"},children:[f.jsx("td",{style:{color:"var(--text-secondary)",whiteSpace:"nowrap"},children:p(_.created_at)}),f.jsx("td",{children:f.jsx("a",{style:{color:"var(--text-link, #88aaff)",cursor:"pointer",textDecoration:"none",fontWeight:500},onClick:F=>{F.stopPropagation(),G(_.token_name),r(1)},children:_.agent_name||_.token_name})}),f.jsx("td",{className:"mono",children:_.operation}),f.jsx("td",{style:{color:"var(--text-secondary)",fontSize:12,maxWidth:200,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:R(_.params)}),f.jsxs("td",{className:"mono",children:[_.latency_ms,"ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${_.status}`,children:_.status})})]}),U===_.id&&f.jsx("tr",{children:f.jsx("td",{colSpan:6,style:{background:"var(--bg-secondary, #0f0f1a)",padding:16},children:f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Time"}),f.jsx("span",{children:new Date(_.created_at).toLocaleString()}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Agent"}),f.jsx("span",{className:"mono",children:_.token_name}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Operation"}),f.jsx("span",{className:"mono",children:_.operation}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Latency"}),f.jsxs("span",{children:[_.latency_ms,"ms"]}),_.params&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Params"}),f.jsx("pre",{className:"mono",style:{margin:0,whiteSpace:"pre-wrap",fontSize:12},children:JSON.stringify(_.params,null,2)})]}),_.error_message&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:"Error"}),f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:_.error_message})]})]})})})]},_.id))})]}),f.jsxs("div",{className:"pagination",children:[f.jsxs("span",{children:["Page ",m.page," of ",m.pages," (",m.total," total)"]}),f.jsxs("div",{style:{display:"flex",gap:8},children:[f.jsx("button",{disabled:m.page<=1,onClick:()=>r(_=>_-1),children:"Previous"}),f.jsx("button",{disabled:m.page>=m.pages,onClick:()=>r(_=>_+1),children:"Next"})]})]})]})]})}function jr(){const m=window.location.hash.replace("#","")||"dashboard";return["login","dashboard","agents","log"].includes(m)?m:"dashboard"}function Ty(){const[m,H]=ul.useState(jr);ul.useEffect(()=>{const O=()=>H(jr());return window.addEventListener("hashchange",O),()=>window.removeEventListener("hashchange",O)},[]);const D=O=>{window.location.hash=O,H(O)};if(m==="login")return f.jsx(dy,{onLogin:()=>D("dashboard")});const r=async()=>{if(confirm("Sign out every active admin session, including other browsers and tabs? Each one will need to re-authenticate via a fresh magic link.")){try{await _t.signOutEverywhere()}catch{}D("login")}};return f.jsxs("div",{className:"app",children:[f.jsxs("nav",{className:"sidebar",children:[f.jsx("div",{className:"sidebar-logo",children:"GBrain"}),f.jsxs("div",{className:"sidebar-nav",children:[f.jsx("a",{className:`nav-item ${m==="dashboard"?"active":""}`,onClick:()=>D("dashboard"),children:"Dashboard"}),f.jsx("a",{className:`nav-item ${m==="agents"?"active":""}`,onClick:()=>D("agents"),children:"Agents"}),f.jsx("a",{className:`nav-item ${m==="log"?"active":""}`,onClick:()=>D("log"),children:"Request Log"})]}),f.jsx("div",{style:{marginTop:"auto",padding:"16px 12px",borderTop:"1px solid var(--border)"},children:f.jsx("button",{onClick:r,style:{background:"transparent",border:"1px solid var(--border)",color:"var(--text-secondary)",padding:"6px 10px",borderRadius:6,fontSize:12,cursor:"pointer",width:"100%"},title:"Revoke every active admin session — every browser, every tab",children:"Sign out everywhere"})})]}),f.jsxs("main",{className:"main",children:[m==="dashboard"&&f.jsx(ry,{}),m==="agents"&&f.jsx(my,{}),m==="log"&&f.jsx(py,{})]})]})}sy.createRoot(document.getElementById("root")).render(f.jsx(Nr.StrictMode,{children:f.jsx(Ty,{})})); diff --git a/admin/dist/assets/index-CWq369vO.js b/admin/dist/assets/index-CWq369vO.js new file mode 100644 index 000000000..698ad7194 --- /dev/null +++ b/admin/dist/assets/index-CWq369vO.js @@ -0,0 +1,56 @@ +(function(){const N=document.createElement("link").relList;if(N&&N.supports&&N.supports("modulepreload"))return;for(const _ of document.querySelectorAll('link[rel="modulepreload"]'))h(_);new MutationObserver(_=>{for(const Y of _)if(Y.type==="childList")for(const U of Y.addedNodes)U.tagName==="LINK"&&U.rel==="modulepreload"&&h(U)}).observe(document,{childList:!0,subtree:!0});function M(_){const Y={};return _.integrity&&(Y.integrity=_.integrity),_.referrerPolicy&&(Y.referrerPolicy=_.referrerPolicy),_.crossOrigin==="use-credentials"?Y.credentials="include":_.crossOrigin==="anonymous"?Y.credentials="omit":Y.credentials="same-origin",Y}function h(_){if(_.ep)return;_.ep=!0;const Y=M(_);fetch(_.href,Y)}})();function Nr(d){return d&&d.__esModule&&Object.prototype.hasOwnProperty.call(d,"default")?d.default:d}var ff={exports:{}},zn={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var gr;function ty(){if(gr)return zn;gr=1;var d=Symbol.for("react.transitional.element"),N=Symbol.for("react.fragment");function M(h,_,Y){var U=null;if(Y!==void 0&&(U=""+Y),_.key!==void 0&&(U=""+_.key),"key"in _){Y={};for(var Z in _)Z!=="key"&&(Y[Z]=_[Z])}else Y=_;return _=Y.ref,{$$typeof:d,type:h,key:U,ref:_!==void 0?_:null,props:Y}}return zn.Fragment=N,zn.jsx=M,zn.jsxs=M,zn}var Sr;function ey(){return Sr||(Sr=1,ff.exports=ty()),ff.exports}var f=ey(),sf={exports:{}},V={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var br;function ay(){if(br)return V;br=1;var d=Symbol.for("react.transitional.element"),N=Symbol.for("react.portal"),M=Symbol.for("react.fragment"),h=Symbol.for("react.strict_mode"),_=Symbol.for("react.profiler"),Y=Symbol.for("react.consumer"),U=Symbol.for("react.context"),Z=Symbol.for("react.forward_ref"),O=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),H=Symbol.for("react.lazy"),j=Symbol.for("react.activity"),E=Symbol.iterator;function I(r){return r===null||typeof r!="object"?null:(r=E&&r[E]||r["@@iterator"],typeof r=="function"?r:null)}var L={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},nl=Object.assign,tl={};function pl(r,A,C){this.props=r,this.context=A,this.refs=tl,this.updater=C||L}pl.prototype.isReactComponent={},pl.prototype.setState=function(r,A){if(typeof r!="object"&&typeof r!="function"&&r!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,r,A,"setState")},pl.prototype.forceUpdate=function(r){this.updater.enqueueForceUpdate(this,r,"forceUpdate")};function Ml(){}Ml.prototype=pl.prototype;function Gl(r,A,C){this.props=r,this.context=A,this.refs=tl,this.updater=C||L}var ot=Gl.prototype=new Ml;ot.constructor=Gl,nl(ot,pl.prototype),ot.isPureReactComponent=!0;var _t=Array.isArray;function Ll(){}var el={H:null,A:null,T:null,S:null},Vl=Object.prototype.hasOwnProperty;function jt(r,A,C){var B=C.ref;return{$$typeof:d,type:r,key:A,ref:B!==void 0?B:null,props:C}}function Le(r,A){return jt(r.type,A,r.props)}function Ot(r){return typeof r=="object"&&r!==null&&r.$$typeof===d}function Kl(r){var A={"=":"=0",":":"=2"};return"$"+r.replace(/[=:]/g,function(C){return A[C]})}var xe=/\/+/g;function Ut(r,A){return typeof r=="object"&&r!==null&&r.key!=null?Kl(""+r.key):A.toString(36)}function zt(r){switch(r.status){case"fulfilled":return r.value;case"rejected":throw r.reason;default:switch(typeof r.status=="string"?r.then(Ll,Ll):(r.status="pending",r.then(function(A){r.status==="pending"&&(r.status="fulfilled",r.value=A)},function(A){r.status==="pending"&&(r.status="rejected",r.reason=A)})),r.status){case"fulfilled":return r.value;case"rejected":throw r.reason}}throw r}function T(r,A,C,B,K){var $=typeof r;($==="undefined"||$==="boolean")&&(r=null);var fl=!1;if(r===null)fl=!0;else switch($){case"bigint":case"string":case"number":fl=!0;break;case"object":switch(r.$$typeof){case d:case N:fl=!0;break;case H:return fl=r._init,T(fl(r._payload),A,C,B,K)}}if(fl)return K=K(r),fl=B===""?"."+Ut(r,0):B,_t(K)?(C="",fl!=null&&(C=fl.replace(xe,"$&/")+"/"),T(K,A,C,"",function(Oa){return Oa})):K!=null&&(Ot(K)&&(K=Le(K,C+(K.key==null||r&&r.key===K.key?"":(""+K.key).replace(xe,"$&/")+"/")+fl)),A.push(K)),1;fl=0;var Ql=B===""?".":B+":";if(_t(r))for(var xl=0;xl>>1,yl=T[dl];if(0<_(yl,D))T[dl]=D,T[Q]=yl,Q=dl;else break l}}function M(T){return T.length===0?null:T[0]}function h(T){if(T.length===0)return null;var D=T[0],Q=T.pop();if(Q!==D){T[0]=Q;l:for(var dl=0,yl=T.length,r=yl>>>1;dl_(C,Q))B_(K,C)?(T[dl]=K,T[B]=Q,dl=B):(T[dl]=C,T[A]=Q,dl=A);else if(B_(K,Q))T[dl]=K,T[B]=Q,dl=B;else break l}}return D}function _(T,D){var Q=T.sortIndex-D.sortIndex;return Q!==0?Q:T.id-D.id}if(d.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var Y=performance;d.unstable_now=function(){return Y.now()}}else{var U=Date,Z=U.now();d.unstable_now=function(){return U.now()-Z}}var O=[],p=[],H=1,j=null,E=3,I=!1,L=!1,nl=!1,tl=!1,pl=typeof setTimeout=="function"?setTimeout:null,Ml=typeof clearTimeout=="function"?clearTimeout:null,Gl=typeof setImmediate<"u"?setImmediate:null;function ot(T){for(var D=M(p);D!==null;){if(D.callback===null)h(p);else if(D.startTime<=T)h(p),D.sortIndex=D.expirationTime,N(O,D);else break;D=M(p)}}function _t(T){if(nl=!1,ot(T),!L)if(M(O)!==null)L=!0,Ll||(Ll=!0,Kl());else{var D=M(p);D!==null&&zt(_t,D.startTime-T)}}var Ll=!1,el=-1,Vl=5,jt=-1;function Le(){return tl?!0:!(d.unstable_now()-jtT&&Le());){var dl=j.callback;if(typeof dl=="function"){j.callback=null,E=j.priorityLevel;var yl=dl(j.expirationTime<=T);if(T=d.unstable_now(),typeof yl=="function"){j.callback=yl,ot(T),D=!0;break t}j===M(O)&&h(O),ot(T)}else h(O);j=M(O)}if(j!==null)D=!0;else{var r=M(p);r!==null&&zt(_t,r.startTime-T),D=!1}}break l}finally{j=null,E=Q,I=!1}D=void 0}}finally{D?Kl():Ll=!1}}}var Kl;if(typeof Gl=="function")Kl=function(){Gl(Ot)};else if(typeof MessageChannel<"u"){var xe=new MessageChannel,Ut=xe.port2;xe.port1.onmessage=Ot,Kl=function(){Ut.postMessage(null)}}else Kl=function(){pl(Ot,0)};function zt(T,D){el=pl(function(){T(d.unstable_now())},D)}d.unstable_IdlePriority=5,d.unstable_ImmediatePriority=1,d.unstable_LowPriority=4,d.unstable_NormalPriority=3,d.unstable_Profiling=null,d.unstable_UserBlockingPriority=2,d.unstable_cancelCallback=function(T){T.callback=null},d.unstable_forceFrameRate=function(T){0>T||125dl?(T.sortIndex=Q,N(p,T),M(O)===null&&T===M(p)&&(nl?(Ml(el),el=-1):nl=!0,zt(_t,Q-dl))):(T.sortIndex=yl,N(O,T),L||I||(L=!0,Ll||(Ll=!0,Kl()))),T},d.unstable_shouldYield=Le,d.unstable_wrapCallback=function(T){var D=E;return function(){var Q=E;E=D;try{return T.apply(this,arguments)}finally{E=Q}}}})(rf)),rf}var zr;function uy(){return zr||(zr=1,df.exports=ny()),df.exports}var hf={exports:{}},Xl={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var xr;function iy(){if(xr)return Xl;xr=1;var d=mf();function N(O){var p="https://react.dev/errors/"+O;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(d)}catch(N){console.error(N)}}return d(),hf.exports=iy(),hf.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Er;function fy(){if(Er)return xn;Er=1;var d=uy(),N=mf(),M=cy();function h(l){var t="https://react.dev/errors/"+l;if(1yl||(l.current=dl[yl],dl[yl]=null,yl--)}function C(l,t){yl++,dl[yl]=l.current,l.current=t}var B=r(null),K=r(null),$=r(null),fl=r(null);function Ql(l,t){switch(C($,t),C(K,l),C(B,null),t.nodeType){case 9:case 11:l=(l=t.documentElement)&&(l=l.namespaceURI)?Xd(l):0;break;default:if(l=t.tagName,t=t.namespaceURI)t=Xd(t),l=Qd(t,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}A(B),C(B,l)}function xl(){A(B),A(K),A($)}function Oa(l){l.memoizedState!==null&&C(fl,l);var t=B.current,e=Qd(t,l.type);t!==e&&(C(K,l),C(B,e))}function An(l){K.current===l&&(A(B),A(K)),fl.current===l&&(A(fl),Sn._currentValue=Q)}var Lu,yf;function Ae(l){if(Lu===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Lu=t&&t[1]||"",yf=-1)":-1n||s[a]!==v[n]){var b=` +`+s[a].replace(" at new "," at ");return l.displayName&&b.includes("")&&(b=b.replace("",l.displayName)),b}while(1<=a&&0<=n);break}}}finally{Vu=!1,Error.prepareStackTrace=e}return(e=l?l.displayName||l.name:"")?Ae(e):""}function Cr(l,t){switch(l.tag){case 26:case 27:case 5:return Ae(l.type);case 16:return Ae("Lazy");case 13:return l.child!==t&&t!==null?Ae("Suspense Fallback"):Ae("Suspense");case 19:return Ae("SuspenseList");case 0:case 15:return Ku(l.type,!1);case 11:return Ku(l.type.render,!1);case 1:return Ku(l.type,!0);case 31:return Ae("Activity");default:return""}}function vf(l){try{var t="",e=null;do t+=Cr(l,e),e=l,l=l.return;while(l);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var Ju=Object.prototype.hasOwnProperty,wu=d.unstable_scheduleCallback,ku=d.unstable_cancelCallback,Ur=d.unstable_shouldYield,Rr=d.unstable_requestPaint,Pl=d.unstable_now,Hr=d.unstable_getCurrentPriorityLevel,gf=d.unstable_ImmediatePriority,Sf=d.unstable_UserBlockingPriority,En=d.unstable_NormalPriority,Br=d.unstable_LowPriority,bf=d.unstable_IdlePriority,qr=d.log,Yr=d.unstable_setDisableYieldValue,Na=null,lt=null;function It(l){if(typeof qr=="function"&&Yr(l),lt&&typeof lt.setStrictMode=="function")try{lt.setStrictMode(Na,l)}catch{}}var tt=Math.clz32?Math.clz32:Qr,Gr=Math.log,Xr=Math.LN2;function Qr(l){return l>>>=0,l===0?32:31-(Gr(l)/Xr|0)|0}var _n=256,jn=262144,On=4194304;function Ee(l){var t=l&42;if(t!==0)return t;switch(l&-l){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return l&261888;case 262144:case 524288:case 1048576:case 2097152:return l&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return l&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return l}}function Nn(l,t,e){var a=l.pendingLanes;if(a===0)return 0;var n=0,u=l.suspendedLanes,i=l.pingedLanes;l=l.warmLanes;var c=a&134217727;return c!==0?(a=c&~u,a!==0?n=Ee(a):(i&=c,i!==0?n=Ee(i):e||(e=c&~l,e!==0&&(n=Ee(e))))):(c=a&~u,c!==0?n=Ee(c):i!==0?n=Ee(i):e||(e=a&~l,e!==0&&(n=Ee(e)))),n===0?0:t!==0&&t!==n&&(t&u)===0&&(u=n&-n,e=t&-t,u>=e||u===32&&(e&4194048)!==0)?t:n}function Ma(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function Zr(l,t){switch(l){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function pf(){var l=On;return On<<=1,(On&62914560)===0&&(On=4194304),l}function $u(l){for(var t=[],e=0;31>e;e++)t.push(l);return t}function Da(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Lr(l,t,e,a,n,u){var i=l.pendingLanes;l.pendingLanes=e,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=e,l.entangledLanes&=e,l.errorRecoveryDisabledLanes&=e,l.shellSuspendCounter=0;var c=l.entanglements,s=l.expirationTimes,v=l.hiddenUpdates;for(e=i&~e;0"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var $r=/[\n"\\]/g;function rt(l){return l.replace($r,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function ti(l,t,e,a,n,u,i,c){l.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?l.type=i:l.removeAttribute("type"),t!=null?i==="number"?(t===0&&l.value===""||l.value!=t)&&(l.value=""+dt(t)):l.value!==""+dt(t)&&(l.value=""+dt(t)):i!=="submit"&&i!=="reset"||l.removeAttribute("value"),t!=null?ei(l,i,dt(t)):e!=null?ei(l,i,dt(e)):a!=null&&l.removeAttribute("value"),n==null&&u!=null&&(l.defaultChecked=!!u),n!=null&&(l.checked=n&&typeof n!="function"&&typeof n!="symbol"),c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.name=""+dt(c):l.removeAttribute("name")}function Uf(l,t,e,a,n,u,i,c){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(l.type=u),t!=null||e!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){li(l);return}e=e!=null?""+dt(e):"",t=t!=null?""+dt(t):e,c||t===l.value||(l.value=t),l.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,l.checked=c?l.checked:!!a,l.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(l.name=i),li(l)}function ei(l,t,e){t==="number"&&Cn(l.ownerDocument)===l||l.defaultValue===""+e||(l.defaultValue=""+e)}function $e(l,t,e,a){if(l=l.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),ci=!1;if(Bt)try{var Ha={};Object.defineProperty(Ha,"passive",{get:function(){ci=!0}}),window.addEventListener("test",Ha,Ha),window.removeEventListener("test",Ha,Ha)}catch{ci=!1}var le=null,fi=null,Rn=null;function Xf(){if(Rn)return Rn;var l,t=fi,e=t.length,a,n="value"in le?le.value:le.textContent,u=n.length;for(l=0;l=Ya),Jf=" ",wf=!1;function kf(l,t){switch(l){case"keyup":return xh.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function $f(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var Pe=!1;function Eh(l,t){switch(l){case"compositionend":return $f(t);case"keypress":return t.which!==32?null:(wf=!0,Jf);case"textInput":return l=t.data,l===Jf&&wf?null:l;default:return null}}function _h(l,t){if(Pe)return l==="compositionend"||!hi&&kf(l,t)?(l=Xf(),Rn=fi=le=null,Pe=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:e,offset:t-l};l=a}l:{for(;e;){if(e.nextSibling){e=e.nextSibling;break l}e=e.parentNode}e=void 0}e=as(e)}}function us(l,t){return l&&t?l===t?!0:l&&l.nodeType===3?!1:t&&t.nodeType===3?us(l,t.parentNode):"contains"in l?l.contains(t):l.compareDocumentPosition?!!(l.compareDocumentPosition(t)&16):!1:!1}function is(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var t=Cn(l.document);t instanceof l.HTMLIFrameElement;){try{var e=typeof t.contentWindow.location.href=="string"}catch{e=!1}if(e)l=t.contentWindow;else break;t=Cn(l.document)}return t}function vi(l){var t=l&&l.nodeName&&l.nodeName.toLowerCase();return t&&(t==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||t==="textarea"||l.contentEditable==="true")}var Rh=Bt&&"documentMode"in document&&11>=document.documentMode,la=null,gi=null,Za=null,Si=!1;function cs(l,t,e){var a=e.window===e?e.document:e.nodeType===9?e:e.ownerDocument;Si||la==null||la!==Cn(a)||(a=la,"selectionStart"in a&&vi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Za&&Qa(Za,a)||(Za=a,a=ju(gi,"onSelect"),0>=i,n-=i,Nt=1<<32-tt(t)+n|e<w?(ll=q,q=null):ll=q.sibling;var il=g(m,q,y[w],z);if(il===null){q===null&&(q=ll);break}l&&q&&il.alternate===null&&t(m,q),o=u(il,o,w),ul===null?G=il:ul.sibling=il,ul=il,q=ll}if(w===y.length)return e(m,q),al&&Yt(m,w),G;if(q===null){for(;ww?(ll=q,q=null):ll=q.sibling;var ze=g(m,q,il.value,z);if(ze===null){q===null&&(q=ll);break}l&&q&&ze.alternate===null&&t(m,q),o=u(ze,o,w),ul===null?G=ze:ul.sibling=ze,ul=ze,q=ll}if(il.done)return e(m,q),al&&Yt(m,w),G;if(q===null){for(;!il.done;w++,il=y.next())il=x(m,il.value,z),il!==null&&(o=u(il,o,w),ul===null?G=il:ul.sibling=il,ul=il);return al&&Yt(m,w),G}for(q=a(q);!il.done;w++,il=y.next())il=S(q,m,w,il.value,z),il!==null&&(l&&il.alternate!==null&&q.delete(il.key===null?w:il.key),o=u(il,o,w),ul===null?G=il:ul.sibling=il,ul=il);return l&&q.forEach(function(ly){return t(m,ly)}),al&&Yt(m,w),G}function ml(m,o,y,z){if(typeof y=="object"&&y!==null&&y.type===nl&&y.key===null&&(y=y.props.children),typeof y=="object"&&y!==null){switch(y.$$typeof){case I:l:{for(var G=y.key;o!==null;){if(o.key===G){if(G=y.type,G===nl){if(o.tag===7){e(m,o.sibling),z=n(o,y.props.children),z.return=m,m=z;break l}}else if(o.elementType===G||typeof G=="object"&&G!==null&&G.$$typeof===Vl&&Be(G)===o.type){e(m,o.sibling),z=n(o,y.props),ka(z,y),z.return=m,m=z;break l}e(m,o);break}else t(m,o);o=o.sibling}y.type===nl?(z=De(y.props.children,m.mode,z,y.key),z.return=m,m=z):(z=Vn(y.type,y.key,y.props,null,m.mode,z),ka(z,y),z.return=m,m=z)}return i(m);case L:l:{for(G=y.key;o!==null;){if(o.key===G)if(o.tag===4&&o.stateNode.containerInfo===y.containerInfo&&o.stateNode.implementation===y.implementation){e(m,o.sibling),z=n(o,y.children||[]),z.return=m,m=z;break l}else{e(m,o);break}else t(m,o);o=o.sibling}z=Ei(y,m.mode,z),z.return=m,m=z}return i(m);case Vl:return y=Be(y),ml(m,o,y,z)}if(zt(y))return R(m,o,y,z);if(Kl(y)){if(G=Kl(y),typeof G!="function")throw Error(h(150));return y=G.call(y),X(m,o,y,z)}if(typeof y.then=="function")return ml(m,o,Fn(y),z);if(y.$$typeof===Gl)return ml(m,o,wn(m,y),z);In(m,y)}return typeof y=="string"&&y!==""||typeof y=="number"||typeof y=="bigint"?(y=""+y,o!==null&&o.tag===6?(e(m,o.sibling),z=n(o,y),z.return=m,m=z):(e(m,o),z=Ai(y,m.mode,z),z.return=m,m=z),i(m)):e(m,o)}return function(m,o,y,z){try{wa=0;var G=ml(m,o,y,z);return da=null,G}catch(q){if(q===oa||q===$n)throw q;var ul=at(29,q,null,m.mode);return ul.lanes=z,ul.return=m,ul}finally{}}}var Ye=Ms(!0),Ds=Ms(!1),ue=!1;function qi(l){l.updateQueue={baseState:l.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Yi(l,t){l=l.updateQueue,t.updateQueue===l&&(t.updateQueue={baseState:l.baseState,firstBaseUpdate:l.firstBaseUpdate,lastBaseUpdate:l.lastBaseUpdate,shared:l.shared,callbacks:null})}function ie(l){return{lane:l,tag:0,payload:null,callback:null,next:null}}function ce(l,t,e){var a=l.updateQueue;if(a===null)return null;if(a=a.shared,(cl&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=Ln(l),ms(l,null,e),t}return Zn(l,a,t,e),Ln(l)}function $a(l,t,e){if(t=t.updateQueue,t!==null&&(t=t.shared,(e&4194048)!==0)){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,zf(l,e)}}function Gi(l,t){var e=l.updateQueue,a=l.alternate;if(a!==null&&(a=a.updateQueue,e===a)){var n=null,u=null;if(e=e.firstBaseUpdate,e!==null){do{var i={lane:e.lane,tag:e.tag,payload:e.payload,callback:null,next:null};u===null?n=u=i:u=u.next=i,e=e.next}while(e!==null);u===null?n=u=t:u=u.next=t}else n=u=t;e={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},l.updateQueue=e;return}l=e.lastBaseUpdate,l===null?e.firstBaseUpdate=t:l.next=t,e.lastBaseUpdate=t}var Xi=!1;function Wa(){if(Xi){var l=sa;if(l!==null)throw l}}function Fa(l,t,e,a){Xi=!1;var n=l.updateQueue;ue=!1;var u=n.firstBaseUpdate,i=n.lastBaseUpdate,c=n.shared.pending;if(c!==null){n.shared.pending=null;var s=c,v=s.next;s.next=null,i===null?u=v:i.next=v,i=s;var b=l.alternate;b!==null&&(b=b.updateQueue,c=b.lastBaseUpdate,c!==i&&(c===null?b.firstBaseUpdate=v:c.next=v,b.lastBaseUpdate=s))}if(u!==null){var x=n.baseState;i=0,b=v=s=null,c=u;do{var g=c.lane&-536870913,S=g!==c.lane;if(S?(P&g)===g:(a&g)===g){g!==0&&g===fa&&(Xi=!0),b!==null&&(b=b.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});l:{var R=l,X=c;g=t;var ml=e;switch(X.tag){case 1:if(R=X.payload,typeof R=="function"){x=R.call(ml,x,g);break l}x=R;break l;case 3:R.flags=R.flags&-65537|128;case 0:if(R=X.payload,g=typeof R=="function"?R.call(ml,x,g):R,g==null)break l;x=j({},x,g);break l;case 2:ue=!0}}g=c.callback,g!==null&&(l.flags|=64,S&&(l.flags|=8192),S=n.callbacks,S===null?n.callbacks=[g]:S.push(g))}else S={lane:g,tag:c.tag,payload:c.payload,callback:c.callback,next:null},b===null?(v=b=S,s=x):b=b.next=S,i|=g;if(c=c.next,c===null){if(c=n.shared.pending,c===null)break;S=c,c=S.next,S.next=null,n.lastBaseUpdate=S,n.shared.pending=null}}while(!0);b===null&&(s=x),n.baseState=s,n.firstBaseUpdate=v,n.lastBaseUpdate=b,u===null&&(n.shared.lanes=0),re|=i,l.lanes=i,l.memoizedState=x}}function Cs(l,t){if(typeof l!="function")throw Error(h(191,l));l.call(t)}function Us(l,t){var e=l.callbacks;if(e!==null)for(l.callbacks=null,l=0;lu?u:8;var i=T.T,c={};T.T=c,uc(l,!1,t,e);try{var s=n(),v=T.S;if(v!==null&&v(c,s),s!==null&&typeof s=="object"&&typeof s.then=="function"){var b=Lh(s,a);ln(l,t,b,ft(l))}else ln(l,t,a,ft(l))}catch(x){ln(l,t,{then:function(){},status:"rejected",reason:x},ft())}finally{D.p=u,i!==null&&c.types!==null&&(i.types=c.types),T.T=i}}function $h(){}function ac(l,t,e,a){if(l.tag!==5)throw Error(h(476));var n=ro(l).queue;oo(l,n,t,Q,e===null?$h:function(){return ho(l),e(a)})}function ro(l){var t=l.memoizedState;if(t!==null)return t;t={memoizedState:Q,baseState:Q,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:Q},next:null};var e={};return t.next={memoizedState:e,baseState:e,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:e},next:null},l.memoizedState=t,l=l.alternate,l!==null&&(l.memoizedState=t),t}function ho(l){var t=ro(l);t.next===null&&(t=l.alternate.memoizedState),ln(l,t.next.queue,{},ft())}function nc(){return Bl(Sn)}function mo(){return El().memoizedState}function yo(){return El().memoizedState}function Wh(l){for(var t=l.return;t!==null;){switch(t.tag){case 24:case 3:var e=ft();l=ie(e);var a=ce(t,l,e);a!==null&&(Il(a,t,e),$a(a,t,e)),t={cache:Ui()},l.payload=t;return}t=t.return}}function Fh(l,t,e){var a=ft();e={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null},fu(l)?go(t,e):(e=zi(l,t,e,a),e!==null&&(Il(e,l,a),So(e,t,a)))}function vo(l,t,e){var a=ft();ln(l,t,e,a)}function ln(l,t,e,a){var n={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null};if(fu(l))go(t,n);else{var u=l.alternate;if(l.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var i=t.lastRenderedState,c=u(i,e);if(n.hasEagerState=!0,n.eagerState=c,et(c,i))return Zn(l,t,n,0),vl===null&&Qn(),!1}catch{}finally{}if(e=zi(l,t,n,a),e!==null)return Il(e,l,a),So(e,t,a),!0}return!1}function uc(l,t,e,a){if(a={lane:2,revertLane:qc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},fu(l)){if(t)throw Error(h(479))}else t=zi(l,e,a,2),t!==null&&Il(t,l,2)}function fu(l){var t=l.alternate;return l===J||t!==null&&t===J}function go(l,t){ha=tu=!0;var e=l.pending;e===null?t.next=t:(t.next=e.next,e.next=t),l.pending=t}function So(l,t,e){if((e&4194048)!==0){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,zf(l,e)}}var tn={readContext:Bl,use:nu,useCallback:Tl,useContext:Tl,useEffect:Tl,useImperativeHandle:Tl,useLayoutEffect:Tl,useInsertionEffect:Tl,useMemo:Tl,useReducer:Tl,useRef:Tl,useState:Tl,useDebugValue:Tl,useDeferredValue:Tl,useTransition:Tl,useSyncExternalStore:Tl,useId:Tl,useHostTransitionStatus:Tl,useFormState:Tl,useActionState:Tl,useOptimistic:Tl,useMemoCache:Tl,useCacheRefresh:Tl};tn.useEffectEvent=Tl;var bo={readContext:Bl,use:nu,useCallback:function(l,t){return Zl().memoizedState=[l,t===void 0?null:t],l},useContext:Bl,useEffect:to,useImperativeHandle:function(l,t,e){e=e!=null?e.concat([l]):null,iu(4194308,4,uo.bind(null,t,l),e)},useLayoutEffect:function(l,t){return iu(4194308,4,l,t)},useInsertionEffect:function(l,t){iu(4,2,l,t)},useMemo:function(l,t){var e=Zl();t=t===void 0?null:t;var a=l();if(Ge){It(!0);try{l()}finally{It(!1)}}return e.memoizedState=[a,t],a},useReducer:function(l,t,e){var a=Zl();if(e!==void 0){var n=e(t);if(Ge){It(!0);try{e(t)}finally{It(!1)}}}else n=t;return a.memoizedState=a.baseState=n,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:n},a.queue=l,l=l.dispatch=Fh.bind(null,J,l),[a.memoizedState,l]},useRef:function(l){var t=Zl();return l={current:l},t.memoizedState=l},useState:function(l){l=Ii(l);var t=l.queue,e=vo.bind(null,J,t);return t.dispatch=e,[l.memoizedState,e]},useDebugValue:tc,useDeferredValue:function(l,t){var e=Zl();return ec(e,l,t)},useTransition:function(){var l=Ii(!1);return l=oo.bind(null,J,l.queue,!0,!1),Zl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,t,e){var a=J,n=Zl();if(al){if(e===void 0)throw Error(h(407));e=e()}else{if(e=t(),vl===null)throw Error(h(349));(P&127)!==0||Gs(a,t,e)}n.memoizedState=e;var u={value:e,getSnapshot:t};return n.queue=u,to(Qs.bind(null,a,u,l),[l]),a.flags|=2048,ya(9,{destroy:void 0},Xs.bind(null,a,u,e,t),null),e},useId:function(){var l=Zl(),t=vl.identifierPrefix;if(al){var e=Mt,a=Nt;e=(a&~(1<<32-tt(a)-1)).toString(32)+e,t="_"+t+"R_"+e,e=eu++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?i.createElement(n,{is:a.is}):i.createElement(n)}}u[Rl]=t,u[Jl]=a;l:for(i=t.child;i!==null;){if(i.tag===5||i.tag===6)u.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===t)break l;for(;i.sibling===null;){if(i.return===null||i.return===t)break l;i=i.return}i.sibling.return=i.return,i=i.sibling}t.stateNode=u;l:switch(Yl(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break l;case"img":a=!0;break l;default:a=!1}a&&Vt(t)}}return Sl(t),bc(t,t.type,l===null?null:l.memoizedProps,t.pendingProps,e),null;case 6:if(l&&t.stateNode!=null)l.memoizedProps!==a&&Vt(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(h(166));if(l=$.current,ia(t)){if(l=t.stateNode,e=t.memoizedProps,a=null,n=Hl,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}l[Rl]=t,l=!!(l.nodeValue===e||a!==null&&a.suppressHydrationWarning===!0||Yd(l.nodeValue,e)),l||ae(t,!0)}else l=Ou(l).createTextNode(a),l[Rl]=t,t.stateNode=l}return Sl(t),null;case 31:if(e=t.memoizedState,l===null||l.memoizedState!==null){if(a=ia(t),e!==null){if(l===null){if(!a)throw Error(h(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(h(557));l[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),l=!1}else e=Ni(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=e),l=!0;if(!l)return t.flags&256?(ut(t),t):(ut(t),null);if((t.flags&128)!==0)throw Error(h(558))}return Sl(t),null;case 13:if(a=t.memoizedState,l===null||l.memoizedState!==null&&l.memoizedState.dehydrated!==null){if(n=ia(t),a!==null&&a.dehydrated!==null){if(l===null){if(!n)throw Error(h(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(h(317));n[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),n=!1}else n=Ni(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(ut(t),t):(ut(t),null)}return ut(t),(t.flags&128)!==0?(t.lanes=e,t):(e=a!==null,l=l!==null&&l.memoizedState!==null,e&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),e!==l&&e&&(t.child.flags|=8192),hu(t,t.updateQueue),Sl(t),null);case 4:return xl(),l===null&&Qc(t.stateNode.containerInfo),Sl(t),null;case 10:return Xt(t.type),Sl(t),null;case 19:if(A(Al),a=t.memoizedState,a===null)return Sl(t),null;if(n=(t.flags&128)!==0,u=a.rendering,u===null)if(n)an(a,!1);else{if(zl!==0||l!==null&&(l.flags&128)!==0)for(l=t.child;l!==null;){if(u=lu(l),u!==null){for(t.flags|=128,an(a,!1),l=u.updateQueue,t.updateQueue=l,hu(t,l),t.subtreeFlags=0,l=e,e=t.child;e!==null;)ys(e,l),e=e.sibling;return C(Al,Al.current&1|2),al&&Yt(t,a.treeForkCount),t.child}l=l.sibling}a.tail!==null&&Pl()>Su&&(t.flags|=128,n=!0,an(a,!1),t.lanes=4194304)}else{if(!n)if(l=lu(u),l!==null){if(t.flags|=128,n=!0,l=l.updateQueue,t.updateQueue=l,hu(t,l),an(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!al)return Sl(t),null}else 2*Pl()-a.renderingStartTime>Su&&e!==536870912&&(t.flags|=128,n=!0,an(a,!1),t.lanes=4194304);a.isBackwards?(u.sibling=t.child,t.child=u):(l=a.last,l!==null?l.sibling=u:t.child=u,a.last=u)}return a.tail!==null?(l=a.tail,a.rendering=l,a.tail=l.sibling,a.renderingStartTime=Pl(),l.sibling=null,e=Al.current,C(Al,n?e&1|2:e&1),al&&Yt(t,a.treeForkCount),l):(Sl(t),null);case 22:case 23:return ut(t),Zi(),a=t.memoizedState!==null,l!==null?l.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(e&536870912)!==0&&(t.flags&128)===0&&(Sl(t),t.subtreeFlags&6&&(t.flags|=8192)):Sl(t),e=t.updateQueue,e!==null&&hu(t,e.retryQueue),e=null,l!==null&&l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(e=l.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==e&&(t.flags|=2048),l!==null&&A(He),null;case 24:return e=null,l!==null&&(e=l.memoizedState.cache),t.memoizedState.cache!==e&&(t.flags|=2048),Xt(_l),Sl(t),null;case 25:return null;case 30:return null}throw Error(h(156,t.tag))}function em(l,t){switch(ji(t),t.tag){case 1:return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 3:return Xt(_l),xl(),l=t.flags,(l&65536)!==0&&(l&128)===0?(t.flags=l&-65537|128,t):null;case 26:case 27:case 5:return An(t),null;case 31:if(t.memoizedState!==null){if(ut(t),t.alternate===null)throw Error(h(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 13:if(ut(t),l=t.memoizedState,l!==null&&l.dehydrated!==null){if(t.alternate===null)throw Error(h(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 19:return A(Al),null;case 4:return xl(),null;case 10:return Xt(t.type),null;case 22:case 23:return ut(t),Zi(),l!==null&&A(He),l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 24:return Xt(_l),null;case 25:return null;default:return null}}function Lo(l,t){switch(ji(t),t.tag){case 3:Xt(_l),xl();break;case 26:case 27:case 5:An(t);break;case 4:xl();break;case 31:t.memoizedState!==null&&ut(t);break;case 13:ut(t);break;case 19:A(Al);break;case 10:Xt(t.type);break;case 22:case 23:ut(t),Zi(),l!==null&&A(He);break;case 24:Xt(_l)}}function nn(l,t){try{var e=t.updateQueue,a=e!==null?e.lastEffect:null;if(a!==null){var n=a.next;e=n;do{if((e.tag&l)===l){a=void 0;var u=e.create,i=e.inst;a=u(),i.destroy=a}e=e.next}while(e!==n)}}catch(c){ol(t,t.return,c)}}function oe(l,t,e){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&l)===l){var i=a.inst,c=i.destroy;if(c!==void 0){i.destroy=void 0,n=t;var s=e,v=c;try{v()}catch(b){ol(n,s,b)}}}a=a.next}while(a!==u)}}catch(b){ol(t,t.return,b)}}function Vo(l){var t=l.updateQueue;if(t!==null){var e=l.stateNode;try{Us(t,e)}catch(a){ol(l,l.return,a)}}}function Ko(l,t,e){e.props=Xe(l.type,l.memoizedProps),e.state=l.memoizedState;try{e.componentWillUnmount()}catch(a){ol(l,t,a)}}function un(l,t){try{var e=l.ref;if(e!==null){switch(l.tag){case 26:case 27:case 5:var a=l.stateNode;break;case 30:a=l.stateNode;break;default:a=l.stateNode}typeof e=="function"?l.refCleanup=e(a):e.current=a}}catch(n){ol(l,t,n)}}function Dt(l,t){var e=l.ref,a=l.refCleanup;if(e!==null)if(typeof a=="function")try{a()}catch(n){ol(l,t,n)}finally{l.refCleanup=null,l=l.alternate,l!=null&&(l.refCleanup=null)}else if(typeof e=="function")try{e(null)}catch(n){ol(l,t,n)}else e.current=null}function Jo(l){var t=l.type,e=l.memoizedProps,a=l.stateNode;try{l:switch(t){case"button":case"input":case"select":case"textarea":e.autoFocus&&a.focus();break l;case"img":e.src?a.src=e.src:e.srcSet&&(a.srcset=e.srcSet)}}catch(n){ol(l,l.return,n)}}function pc(l,t,e){try{var a=l.stateNode;Am(a,l.type,e,t),a[Jl]=t}catch(n){ol(l,l.return,n)}}function wo(l){return l.tag===5||l.tag===3||l.tag===26||l.tag===27&&ge(l.type)||l.tag===4}function Tc(l){l:for(;;){for(;l.sibling===null;){if(l.return===null||wo(l.return))return null;l=l.return}for(l.sibling.return=l.return,l=l.sibling;l.tag!==5&&l.tag!==6&&l.tag!==18;){if(l.tag===27&&ge(l.type)||l.flags&2||l.child===null||l.tag===4)continue l;l.child.return=l,l=l.child}if(!(l.flags&2))return l.stateNode}}function zc(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?(e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e).insertBefore(l,t):(t=e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e,t.appendChild(l),e=e._reactRootContainer,e!=null||t.onclick!==null||(t.onclick=Ht));else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode,t=null),l=l.child,l!==null))for(zc(l,t,e),l=l.sibling;l!==null;)zc(l,t,e),l=l.sibling}function mu(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?e.insertBefore(l,t):e.appendChild(l);else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode),l=l.child,l!==null))for(mu(l,t,e),l=l.sibling;l!==null;)mu(l,t,e),l=l.sibling}function ko(l){var t=l.stateNode,e=l.memoizedProps;try{for(var a=l.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);Yl(t,a,e),t[Rl]=l,t[Jl]=e}catch(u){ol(l,l.return,u)}}var Kt=!1,Nl=!1,xc=!1,$o=typeof WeakSet=="function"?WeakSet:Set,Ul=null;function am(l,t){if(l=l.containerInfo,Vc=Hu,l=is(l),vi(l)){if("selectionStart"in l)var e={start:l.selectionStart,end:l.selectionEnd};else l:{e=(e=l.ownerDocument)&&e.defaultView||window;var a=e.getSelection&&e.getSelection();if(a&&a.rangeCount!==0){e=a.anchorNode;var n=a.anchorOffset,u=a.focusNode;a=a.focusOffset;try{e.nodeType,u.nodeType}catch{e=null;break l}var i=0,c=-1,s=-1,v=0,b=0,x=l,g=null;t:for(;;){for(var S;x!==e||n!==0&&x.nodeType!==3||(c=i+n),x!==u||a!==0&&x.nodeType!==3||(s=i+a),x.nodeType===3&&(i+=x.nodeValue.length),(S=x.firstChild)!==null;)g=x,x=S;for(;;){if(x===l)break t;if(g===e&&++v===n&&(c=i),g===u&&++b===a&&(s=i),(S=x.nextSibling)!==null)break;x=g,g=x.parentNode}x=S}e=c===-1||s===-1?null:{start:c,end:s}}else e=null}e=e||{start:0,end:0}}else e=null;for(Kc={focusedElem:l,selectionRange:e},Hu=!1,Ul=t;Ul!==null;)if(t=Ul,l=t.child,(t.subtreeFlags&1028)!==0&&l!==null)l.return=t,Ul=l;else for(;Ul!==null;){switch(t=Ul,u=t.alternate,l=t.flags,t.tag){case 0:if((l&4)!==0&&(l=t.updateQueue,l=l!==null?l.events:null,l!==null))for(e=0;e title"))),Yl(u,a,e),u[Rl]=l,Cl(u),a=u;break l;case"link":var i=tr("link","href",n).get(a+(e.href||""));if(i){for(var c=0;cml&&(i=ml,ml=X,X=i);var m=ns(c,X),o=ns(c,ml);if(m&&o&&(S.rangeCount!==1||S.anchorNode!==m.node||S.anchorOffset!==m.offset||S.focusNode!==o.node||S.focusOffset!==o.offset)){var y=x.createRange();y.setStart(m.node,m.offset),S.removeAllRanges(),X>ml?(S.addRange(y),S.extend(o.node,o.offset)):(y.setEnd(o.node,o.offset),S.addRange(y))}}}}for(x=[],S=c;S=S.parentNode;)S.nodeType===1&&x.push({element:S,left:S.scrollLeft,top:S.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;ce?32:e,T.T=null,e=Mc,Mc=null;var u=me,i=Wt;if(Dl=0,pa=me=null,Wt=0,(cl&6)!==0)throw Error(h(331));var c=cl;if(cl|=4,id(u.current),ad(u,u.current,i,e),cl=c,rn(0,!1),lt&&typeof lt.onPostCommitFiberRoot=="function")try{lt.onPostCommitFiberRoot(Na,u)}catch{}return!0}finally{D.p=n,T.T=a,Ad(l,t)}}function _d(l,t,e){t=mt(e,t),t=sc(l.stateNode,t,2),l=ce(l,t,2),l!==null&&(Da(l,2),Ct(l))}function ol(l,t,e){if(l.tag===3)_d(l,l,e);else for(;t!==null;){if(t.tag===3){_d(t,l,e);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(he===null||!he.has(a))){l=mt(e,l),e=jo(2),a=ce(t,e,2),a!==null&&(Oo(e,a,t,l),Da(a,2),Ct(a));break}}t=t.return}}function Rc(l,t,e){var a=l.pingCache;if(a===null){a=l.pingCache=new im;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(e)||(_c=!0,n.add(e),l=dm.bind(null,l,t,e),t.then(l,l))}function dm(l,t,e){var a=l.pingCache;a!==null&&a.delete(t),l.pingedLanes|=l.suspendedLanes&e,l.warmLanes&=~e,vl===l&&(P&e)===e&&(zl===4||zl===3&&(P&62914560)===P&&300>Pl()-gu?(cl&2)===0&&Ta(l,0):jc|=e,ba===P&&(ba=0)),Ct(l)}function jd(l,t){t===0&&(t=pf()),l=Me(l,t),l!==null&&(Da(l,t),Ct(l))}function rm(l){var t=l.memoizedState,e=0;t!==null&&(e=t.retryLane),jd(l,e)}function hm(l,t){var e=0;switch(l.tag){case 31:case 13:var a=l.stateNode,n=l.memoizedState;n!==null&&(e=n.retryLane);break;case 19:a=l.stateNode;break;case 22:a=l.stateNode._retryCache;break;default:throw Error(h(314))}a!==null&&a.delete(t),jd(l,e)}function mm(l,t){return wu(l,t)}var Au=null,xa=null,Hc=!1,Eu=!1,Bc=!1,ve=0;function Ct(l){l!==xa&&l.next===null&&(xa===null?Au=xa=l:xa=xa.next=l),Eu=!0,Hc||(Hc=!0,vm())}function rn(l,t){if(!Bc&&Eu){Bc=!0;do for(var e=!1,a=Au;a!==null;){if(l!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var i=a.suspendedLanes,c=a.pingedLanes;u=(1<<31-tt(42|l)+1)-1,u&=n&~(i&~c),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(e=!0,Dd(a,u))}else u=P,u=Nn(a,a===vl?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Ma(a,u)||(e=!0,Dd(a,u));a=a.next}while(e);Bc=!1}}function ym(){Od()}function Od(){Eu=Hc=!1;var l=0;ve!==0&&_m()&&(l=ve);for(var t=Pl(),e=null,a=Au;a!==null;){var n=a.next,u=Nd(a,t);u===0?(a.next=null,e===null?Au=n:e.next=n,n===null&&(xa=e)):(e=a,(l!==0||(u&3)!==0)&&(Eu=!0)),a=n}Dl!==0&&Dl!==5||rn(l),ve!==0&&(ve=0)}function Nd(l,t){for(var e=l.suspendedLanes,a=l.pingedLanes,n=l.expirationTimes,u=l.pendingLanes&-62914561;0c)break;var b=s.transferSize,x=s.initiatorType;b&&Gd(x)&&(s=s.responseEnd,i+=b*(s"u"?null:document;function Fd(l,t,e){var a=Aa;if(a&&typeof t=="string"&&t){var n=rt(t);n='link[rel="'+l+'"][href="'+n+'"]',typeof e=="string"&&(n+='[crossorigin="'+e+'"]'),Wd.has(n)||(Wd.add(n),l={rel:l,crossOrigin:e,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Hm(l){Ft.D(l),Fd("dns-prefetch",l,null)}function Bm(l,t){Ft.C(l,t),Fd("preconnect",l,t)}function qm(l,t,e){Ft.L(l,t,e);var a=Aa;if(a&&l&&t){var n='link[rel="preload"][as="'+rt(t)+'"]';t==="image"&&e&&e.imageSrcSet?(n+='[imagesrcset="'+rt(e.imageSrcSet)+'"]',typeof e.imageSizes=="string"&&(n+='[imagesizes="'+rt(e.imageSizes)+'"]')):n+='[href="'+rt(l)+'"]';var u=n;switch(t){case"style":u=Ea(l);break;case"script":u=_a(l)}pt.has(u)||(l=j({rel:"preload",href:t==="image"&&e&&e.imageSrcSet?void 0:l,as:t},e),pt.set(u,l),a.querySelector(n)!==null||t==="style"&&a.querySelector(vn(u))||t==="script"&&a.querySelector(gn(u))||(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Ym(l,t){Ft.m(l,t);var e=Aa;if(e&&l){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+rt(a)+'"][href="'+rt(l)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=_a(l)}if(!pt.has(u)&&(l=j({rel:"modulepreload",href:l},t),pt.set(u,l),e.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(e.querySelector(gn(u)))return}a=e.createElement("link"),Yl(a,"link",l),Cl(a),e.head.appendChild(a)}}}function Gm(l,t,e){Ft.S(l,t,e);var a=Aa;if(a&&l){var n=we(a).hoistableStyles,u=Ea(l);t=t||"default";var i=n.get(u);if(!i){var c={loading:0,preload:null};if(i=a.querySelector(vn(u)))c.loading=5;else{l=j({rel:"stylesheet",href:l,"data-precedence":t},e),(e=pt.get(u))&&Ic(l,e);var s=i=a.createElement("link");Cl(s),Yl(s,"link",l),s._p=new Promise(function(v,b){s.onload=v,s.onerror=b}),s.addEventListener("load",function(){c.loading|=1}),s.addEventListener("error",function(){c.loading|=2}),c.loading|=4,Mu(i,t,a)}i={type:"stylesheet",instance:i,count:1,state:c},n.set(u,i)}}}function Xm(l,t){Ft.X(l,t);var e=Aa;if(e&&l){var a=we(e).hoistableScripts,n=_a(l),u=a.get(n);u||(u=e.querySelector(gn(n)),u||(l=j({src:l,async:!0},t),(t=pt.get(n))&&Pc(l,t),u=e.createElement("script"),Cl(u),Yl(u,"link",l),e.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Qm(l,t){Ft.M(l,t);var e=Aa;if(e&&l){var a=we(e).hoistableScripts,n=_a(l),u=a.get(n);u||(u=e.querySelector(gn(n)),u||(l=j({src:l,async:!0,type:"module"},t),(t=pt.get(n))&&Pc(l,t),u=e.createElement("script"),Cl(u),Yl(u,"link",l),e.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Id(l,t,e,a){var n=(n=$.current)?Nu(n):null;if(!n)throw Error(h(446));switch(l){case"meta":case"title":return null;case"style":return typeof e.precedence=="string"&&typeof e.href=="string"?(t=Ea(e.href),e=we(n).hoistableStyles,a=e.get(t),a||(a={type:"style",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(e.rel==="stylesheet"&&typeof e.href=="string"&&typeof e.precedence=="string"){l=Ea(e.href);var u=we(n).hoistableStyles,i=u.get(l);if(i||(n=n.ownerDocument||n,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(l,i),(u=n.querySelector(vn(l)))&&!u._p&&(i.instance=u,i.state.loading=5),pt.has(l)||(e={rel:"preload",as:"style",href:e.href,crossOrigin:e.crossOrigin,integrity:e.integrity,media:e.media,hrefLang:e.hrefLang,referrerPolicy:e.referrerPolicy},pt.set(l,e),u||Zm(n,l,e,i.state))),t&&a===null)throw Error(h(528,""));return i}if(t&&a!==null)throw Error(h(529,""));return null;case"script":return t=e.async,e=e.src,typeof e=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=_a(e),e=we(n).hoistableScripts,a=e.get(t),a||(a={type:"script",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(h(444,l))}}function Ea(l){return'href="'+rt(l)+'"'}function vn(l){return'link[rel="stylesheet"]['+l+"]"}function Pd(l){return j({},l,{"data-precedence":l.precedence,precedence:null})}function Zm(l,t,e,a){l.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=l.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Yl(t,"link",e),Cl(t),l.head.appendChild(t))}function _a(l){return'[src="'+rt(l)+'"]'}function gn(l){return"script[async]"+l}function lr(l,t,e){if(t.count++,t.instance===null)switch(t.type){case"style":var a=l.querySelector('style[data-href~="'+rt(e.href)+'"]');if(a)return t.instance=a,Cl(a),a;var n=j({},e,{"data-href":e.href,"data-precedence":e.precedence,href:null,precedence:null});return a=(l.ownerDocument||l).createElement("style"),Cl(a),Yl(a,"style",n),Mu(a,e.precedence,l),t.instance=a;case"stylesheet":n=Ea(e.href);var u=l.querySelector(vn(n));if(u)return t.state.loading|=4,t.instance=u,Cl(u),u;a=Pd(e),(n=pt.get(n))&&Ic(a,n),u=(l.ownerDocument||l).createElement("link"),Cl(u);var i=u;return i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(u,"link",a),t.state.loading|=4,Mu(u,e.precedence,l),t.instance=u;case"script":return u=_a(e.src),(n=l.querySelector(gn(u)))?(t.instance=n,Cl(n),n):(a=e,(n=pt.get(u))&&(a=j({},e),Pc(a,n)),l=l.ownerDocument||l,n=l.createElement("script"),Cl(n),Yl(n,"link",a),l.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(h(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Mu(a,e.precedence,l));return t.instance}function Mu(l,t,e){for(var a=e.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,i=0;i title"):null)}function Lm(l,t,e){if(e===1||t.itemProp!=null)return!1;switch(l){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return l=t.disabled,typeof t.precedence=="string"&&l==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function ar(l){return!(l.type==="stylesheet"&&(l.state.loading&3)===0)}function Vm(l,t,e,a){if(e.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(e.state.loading&4)===0){if(e.instance===null){var n=Ea(a.href),u=t.querySelector(vn(n));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(l.count++,l=Cu.bind(l),t.then(l,l)),e.state.loading|=4,e.instance=u,Cl(u);return}u=t.ownerDocument||t,a=Pd(a),(n=pt.get(n))&&Ic(a,n),u=u.createElement("link"),Cl(u);var i=u;i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(u,"link",a),e.instance=u}l.stylesheets===null&&(l.stylesheets=new Map),l.stylesheets.set(e,t),(t=e.state.preload)&&(e.state.loading&3)===0&&(l.count++,e=Cu.bind(l),t.addEventListener("load",e),t.addEventListener("error",e))}}var lf=0;function Km(l,t){return l.stylesheets&&l.count===0&&Ru(l,l.stylesheets),0lf?50:800)+t);return l.unsuspend=e,function(){l.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Cu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Ru(this,this.stylesheets);else if(this.unsuspend){var l=this.unsuspend;this.unsuspend=null,l()}}}var Uu=null;function Ru(l,t){l.stylesheets=null,l.unsuspend!==null&&(l.count++,Uu=new Map,t.forEach(Jm,l),Uu=null,Cu.call(l))}function Jm(l,t){if(!(t.state.loading&4)){var e=Uu.get(l);if(e)var a=e.get(null);else{e=new Map,Uu.set(l,e);for(var n=l.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(d)}catch(N){console.error(N)}}return d(),of.exports=fy(),of.exports}var oy=sy();const dy=Nr(oy),Dr="";async function Tt(d,N){const M=await fetch(`${Dr}${d}`,{...N,credentials:"same-origin",headers:{"Content-Type":"application/json",...N==null?void 0:N.headers}});if(M.status===401)throw window.location.hash="#login",new Error("Unauthorized");if(!M.ok){const h=await M.json().catch(()=>({}));throw new Error(h.error||`HTTP ${M.status}`)}return M.json()}async function ry(d){const N=await fetch(`${Dr}${d}`,{credentials:"same-origin"});if(N.status===401)throw window.location.hash="#login",new Error("Unauthorized");if(!N.ok)throw new Error(`HTTP ${N.status}`);return N.text()}const st={login:d=>Tt("/admin/login",{method:"POST",body:JSON.stringify({token:d})}),signOutEverywhere:()=>Tt("/admin/api/sign-out-everywhere",{method:"POST"}),stats:()=>Tt("/admin/api/stats"),health:()=>Tt("/admin/api/health-indicators"),agents:()=>Tt("/admin/api/agents"),requests:(d=1,N="")=>Tt(`/admin/api/requests?page=${d}${N}`),apiKeys:()=>Tt("/admin/api/api-keys"),createApiKey:d=>Tt("/admin/api/api-keys",{method:"POST",body:JSON.stringify({name:d})}),revokeApiKey:d=>Tt("/admin/api/api-keys/revoke",{method:"POST",body:JSON.stringify({name:d})}),updateClientTtl:(d,N)=>Tt("/admin/api/update-client-ttl",{method:"POST",body:JSON.stringify({clientId:d,tokenTtl:N})}),revokeClient:d=>Tt("/admin/api/revoke-client",{method:"POST",body:JSON.stringify({clientId:d})}),calibrationProfile:d=>Tt(`/admin/api/calibration/profile${d?`?holder=${encodeURIComponent(d)}`:""}`),calibrationChart:(d,N)=>ry(`/admin/api/calibration/charts/${encodeURIComponent(d)}${N?`?holder=${encodeURIComponent(N)}`:""}`)};function hy({onLogin:d}){const[N,M]=k.useState(""),[h,_]=k.useState(""),[Y,U]=k.useState(!1),Z=async O=>{O.preventDefault(),_(""),U(!0);try{await st.login(N),M(""),d()}catch{_("Invalid token.")}finally{U(!1)}};return f.jsx("div",{className:"login-page",children:f.jsxs("div",{className:"login-box",children:[f.jsx("div",{className:"login-logo",children:"GBrain"}),f.jsxs("div",{style:{background:"rgba(136, 170, 255, 0.08)",border:"1px solid rgba(136, 170, 255, 0.2)",borderRadius:8,padding:"14px 16px",marginBottom:20,fontSize:13,lineHeight:1.5,color:"var(--text-secondary)"},children:[f.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:"🔒 This is a protected dashboard"}),"Ask your AI agent for the admin login link:",f.jsx("div",{style:{background:"rgba(0,0,0,0.3)",borderRadius:6,padding:"8px 12px",marginTop:8,fontFamily:"var(--font-mono)",fontSize:12,color:"#88aaff",wordBreak:"break-all"},children:'"Give me the GBrain admin login link"'}),f.jsx("div",{style:{marginTop:8,fontSize:12,color:"var(--text-muted)"},children:"Each link is single-use. Your agent generates a fresh one each time."})]}),f.jsxs("details",{style:{marginBottom:16},children:[f.jsx("summary",{style:{cursor:"pointer",fontSize:13,color:"var(--text-muted)"},children:"Or paste bootstrap token manually"}),f.jsxs("form",{onSubmit:Z,style:{marginTop:12},children:[f.jsx("div",{style:{marginBottom:12},children:f.jsx("input",{type:"password",placeholder:"Admin Token",value:N,onChange:O=>M(O.target.value)})}),f.jsx("button",{className:"btn btn-primary",style:{width:"100%"},disabled:Y,children:Y?"Authenticating...":"Submit"}),h&&f.jsx("div",{className:"login-error",children:h})]})]})]})})}function my(){const[d,N]=k.useState({connected_agents:0,requests_today:0,active_tokens:0}),[M,h]=k.useState({expiring_soon:0,error_rate:"0%"}),[_,Y]=k.useState([]),[U,Z]=k.useState("connecting"),O=k.useRef(null);k.useEffect(()=>{st.stats().then(N).catch(()=>{}),st.health().then(h).catch(()=>{});const H=new EventSource("/admin/events");O.current=H,H.onopen=()=>Z("connected"),H.onmessage=E=>{try{const I=JSON.parse(E.data);Y(L=>[I,...L].slice(0,50))}catch{}},H.onerror=()=>{Z("disconnected"),setTimeout(()=>{Z("connecting"),H.close()},3e3)};const j=setInterval(()=>{st.stats().then(N).catch(()=>{}),st.health().then(h).catch(()=>{})},3e4);return()=>{H.close(),clearInterval(j)}},[]);const p=H=>{const j=Date.now()-new Date(H).getTime();return j<6e4?`${Math.floor(j/1e3)}s ago`:j<36e5?`${Math.floor(j/6e4)} min ago`:`${Math.floor(j/36e5)}h ago`};return f.jsxs(f.Fragment,{children:[f.jsx("h1",{className:"page-title",children:"Dashboard"}),f.jsxs("div",{style:{display:"flex",gap:24},children:[f.jsxs("div",{style:{flex:1},children:[f.jsxs("div",{className:"metrics",children:[f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:d.connected_agents}),f.jsx("div",{className:"metric-label",children:"Connected Agents"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:d.requests_today}),f.jsx("div",{className:"metric-label",children:"Requests Today"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:d.active_tokens}),f.jsx("div",{className:"metric-label",children:"Active Tokens"})]})]}),f.jsxs("h2",{className:"section-title",children:["Live Activity",f.jsx("span",{style:{marginLeft:8,fontSize:10,color:U==="connected"?"var(--success)":U==="connecting"?"var(--warning)":"var(--error)"},children:U==="connected"?"● connected":U==="connecting"?"● connecting...":"● disconnected"})]}),f.jsx("div",{className:"feed",children:_.length===0?f.jsx("div",{className:"feed-empty",children:U==="connected"?"No requests yet. Agents will appear when they connect.":"Connecting..."}):f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Time"})]})}),f.jsx("tbody",{children:_.map((H,j)=>f.jsxs("tr",{children:[f.jsx("td",{className:"mono",children:H.agent}),f.jsx("td",{className:"mono",children:H.operation}),f.jsx("td",{children:H.scopes.split(",").map(E=>f.jsx("span",{className:`badge badge-${E.trim()}`,style:{marginRight:4},children:E.trim()},E))}),f.jsxs("td",{className:"mono",children:[H.latency_ms," ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${H.status}`,children:H.status})}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:p(H.timestamp)})]},j))})]})})]}),f.jsxs("div",{style:{width:220},children:[f.jsx("h2",{className:"section-title",children:"Token Health"}),f.jsxs("div",{className:"health-panel",children:[f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--warning)"},children:"Expiring Soon"}),f.jsx("span",{className:"mono",children:M.expiring_soon})]}),f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--error)"},children:"Error Rate"}),f.jsx("span",{className:"mono",children:M.error_rate})]})]})]})]})]})}const jr=["admin","read","sources_admin","users_admin","write"];function yy(d){const N=Math.floor((Date.now()-d.getTime())/1e3);return N<60?"just now":N<3600?`${Math.floor(N/60)}m ago`:N<86400?`${Math.floor(N/3600)}h ago`:`${Math.floor(N/86400)}d ago`}function vy(){const[d,N]=k.useState([]),[M,h]=k.useState(!0),[_,Y]=k.useState(!1),[U,Z]=k.useState(null),[O,p]=k.useState(!1),[H,j]=k.useState(null),[E,I]=k.useState(null);k.useEffect(()=>{L()},[]);const L=()=>{st.agents().then(N).catch(()=>{})};return f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Agents"}),f.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[f.jsxs("label",{style:{fontSize:13,color:"var(--text-secondary)",display:"flex",alignItems:"center",gap:6,cursor:"pointer"},children:[f.jsx("input",{type:"checkbox",checked:M,onChange:nl=>h(nl.target.checked)})," Hide revoked"]}),f.jsx("button",{className:"btn btn-secondary",onClick:()=>p(!0),children:"+ API Key"}),f.jsx("button",{className:"btn btn-primary",onClick:()=>Y(!0),children:"+ OAuth Client"})]})]}),(()=>{const nl=d.filter(tl=>!M||tl.status!=="revoked");return d.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No agents registered. Register your first agent to get started."}):nl.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:'All agents are revoked. Uncheck "Hide revoked" to view them.'}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Name"}),f.jsx("th",{children:"Type"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Requests"}),f.jsx("th",{children:"Last Used"})]})}),f.jsx("tbody",{children:nl.map(tl=>f.jsxs("tr",{onClick:()=>I(tl),style:{cursor:"pointer"},children:[f.jsx("td",{style:{fontWeight:500},children:tl.name||tl.client_name}),f.jsx("td",{children:f.jsx("span",{className:`badge ${tl.auth_type==="oauth"?"badge-read":"badge-write"}`,style:{fontSize:11},children:tl.auth_type==="oauth"?"OAuth":"API Key"})}),f.jsx("td",{children:(tl.scope||"").split(" ").filter(Boolean).map(pl=>f.jsx("span",{className:`badge badge-${pl}`,style:{marginRight:4},children:pl},pl))}),f.jsx("td",{children:f.jsx("span",{className:`badge ${tl.status==="active"?"badge-success":"badge-danger"}`,children:tl.status})}),f.jsxs("td",{children:[f.jsx("span",{style:{fontWeight:500},children:tl.requests_today||0}),f.jsxs("span",{style:{color:"var(--text-muted)",fontSize:12},children:[" / ",tl.total_requests||0]})]}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:tl.last_used_at?yy(new Date(tl.last_used_at)):"Never"})]},tl.id))})]}),f.jsxs("div",{style:{color:"var(--text-muted)",fontSize:13,marginTop:12},children:[d.filter(tl=>tl.status==="active").length," active / ",d.length," total"]})]})})(),_&&f.jsx(by,{onClose:()=>Y(!1),onRegistered:nl=>{Y(!1),Z(nl),L()}}),U&&f.jsx(py,{credentials:U,onClose:()=>Z(null)}),E&&f.jsx(Ty,{agent:E,onClose:()=>I(null),onRevoked:L}),O&&f.jsx(gy,{onClose:()=>p(!1),onCreated:nl=>{p(!1),j(nl),L()}}),H&&f.jsx(Sy,{token:H,onClose:()=>j(null)})]})}function gy({onClose:d,onCreated:N}){const[M,h]=k.useState(""),[_,Y]=k.useState(!1),[U,Z]=k.useState(""),O=async p=>{if(p.preventDefault(),!M.trim()){Z("Name required");return}Y(!0);try{const H=await st.createApiKey(M.trim());N({name:H.name,token:H.token})}catch(H){Z(H instanceof Error?H.message:"Failed")}finally{Y(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:d,children:f.jsxs("form",{className:"modal",onClick:p=>p.stopPropagation(),onSubmit:O,children:[f.jsx("div",{className:"modal-title",children:"Create API Key"}),f.jsx("p",{style:{color:"var(--text-secondary)",fontSize:13,marginBottom:16},children:"API keys use simple bearer token auth. They grant full read+write+admin access. For scoped access, use OAuth clients instead."}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Key Name"}),f.jsx("input",{placeholder:"e.g. claude-code-local",value:M,onChange:p=>h(p.target.value),autoFocus:!0})]}),U&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:U}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:d,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:_,children:_?"Creating...":"Create Key"})]})]})})}function Sy({token:d,onClose:N}){const M=h=>navigator.clipboard.writeText(h);return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"API Key Created"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Name"}),f.jsx("div",{className:"code-block",children:f.jsx("span",{children:d.name})})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Bearer Token"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:d.token}),f.jsx("button",{className:"copy-btn",onClick:()=>M(d.token),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Usage"}),f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0,fontSize:12},children:`Authorization: Bearer ${d.token}`}),f.jsx("button",{className:"copy-btn",onClick:()=>M(`Authorization: Bearer ${d.token}`),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this token now. It will not be shown again."}),f.jsx("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:f.jsx("button",{className:"btn btn-primary",onClick:N,children:"Done"})})]})})}function by({onClose:d,onRegistered:N}){const[M,h]=k.useState(""),[_,Y]=k.useState(()=>Object.fromEntries(jr.map(L=>[L,L==="read"]))),[U,Z]=k.useState("86400"),[O,p]=k.useState(!1),[H,j]=k.useState(""),E=[{label:"1 hour",value:"3600"},{label:"24 hours",value:"86400"},{label:"7 days",value:"604800"},{label:"30 days",value:"2592000"},{label:"1 year",value:"31536000"},{label:"No expiry",value:"0"}],I=async L=>{if(L.preventDefault(),!M.trim()){j("Name required");return}p(!0),j("");try{const nl=Object.entries(_).filter(([,Ml])=>Ml).map(([Ml])=>Ml).join(" "),tl=await fetch("/admin/api/register-client",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:M.trim(),scopes:nl,tokenTtl:U==="0"?31536e4:Number(U)})});if(!tl.ok)throw new Error("Registration failed");const pl=await tl.json();N({clientId:pl.clientId,clientSecret:pl.clientSecret,name:M.trim()})}catch(nl){j(nl instanceof Error?nl.message:"Registration failed")}finally{p(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:d,children:f.jsxs("form",{className:"modal",onClick:L=>L.stopPropagation(),onSubmit:I,children:[f.jsx("div",{className:"modal-title",children:"Register Agent"}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Agent Name"}),f.jsx("input",{placeholder:"e.g. perplexity-production",value:M,onChange:L=>h(L.target.value),autoFocus:!0})]}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Scopes"}),f.jsx("div",{className:"checkbox-group",children:jr.map(L=>f.jsxs("label",{className:"checkbox-label",children:[f.jsx("input",{type:"checkbox",checked:_[L],onChange:nl=>Y(tl=>({...tl,[L]:nl.target.checked}))}),L]},L))})]}),f.jsxs("div",{style:{marginBottom:20},children:[f.jsx("label",{children:"Token Lifetime"}),f.jsx("select",{value:U,onChange:L=>Z(L.target.value),style:{width:"100%",background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"6px 10px",fontSize:14},children:E.map(L=>f.jsx("option",{value:L.value,children:L.label},L.value))})]}),H&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:H}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:d,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:O,children:O?"Registering...":"Register"})]})]})})}function py({credentials:d,onClose:N}){const M=_=>navigator.clipboard.writeText(_),h=()=>{const _=new Blob([JSON.stringify(d,null,2)],{type:"application/json"}),Y=URL.createObjectURL(_),U=document.createElement("a");U.href=Y,U.download=`${d.name}-credentials.json`,U.click(),URL.revokeObjectURL(Y)};return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"Agent Registered"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client ID"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:d.clientId}),f.jsx("button",{className:"copy-btn",onClick:()=>M(d.clientId),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client Secret"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:d.clientSecret}),f.jsx("button",{className:"copy-btn",onClick:()=>M(d.clientSecret),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this secret now. It will not be shown again."}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:[f.jsx("button",{className:"btn btn-secondary",onClick:h,children:"Download as JSON"}),f.jsx("button",{className:"btn btn-primary",onClick:N,children:"Done"})]})]})})}function Ty({agent:d,onClose:N,onRevoked:M}){const[h,_]=k.useState("claude-code"),Y=j=>navigator.clipboard.writeText(j),U=window.location.origin,Z=d.id||d.client_id||"",O=d.auth_type==="oauth",p=d.name||d.client_name||"unknown",H={"claude-code":O?["The user wants to connect GBrain MCP to your context. Here's how.","","# Step 1 — read the client secret from the operator without putting it in shell history.","# read -s suppresses the echo; export keeps it scoped to this shell session.",'read -rs -p "Client Secret: " GBRAIN_CS && echo',"","# Step 2 — mint a token and register GBrain in one go.",`claude mcp add --transport http gbrain ${U}/mcp \\`,` --header "Authorization: Bearer $(curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${Z}' \\`,' --data-urlencode "client_secret=$GBRAIN_CS" \\',` -d 'scope=${d.scope||"read write"}' | jq -r .access_token)"`,"","# Step 3 — clear the secret from this shell.","unset GBRAIN_CS","",`The token will last ${d.token_ttl?d.token_ttl>=86400?Math.floor(d.token_ttl/86400)+" days":Math.floor(d.token_ttl/3600)+" hours":"1 hour (default)"}.`,"","─── Fallback: 2-step curl + paste ───","","If your shell doesn't support read -s, mint the token first, then paste:","",`curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${Z}' \\`," -d 'client_secret=PASTE_YOUR_CLIENT_SECRET_HERE' \\",` -d 'scope=${d.scope||"read write"}' | jq -r .access_token`,"",`claude mcp add --transport http gbrain ${U}/mcp \\`,' --header "Authorization: Bearer PASTE_TOKEN_FROM_ABOVE"',"","# Then run: history -d $((HISTCMD-1)) # zsh: print -s -- '' && fc -p"].join(` +`):["The user wants to connect GBrain MCP to your context. Here's how.","","Run this command in terminal to register GBrain:","",`claude mcp add --transport http gbrain ${U}/mcp \\`,' --header "Authorization: Bearer PASTE_YOUR_API_KEY_HERE"',"",`Replace PASTE_YOUR_API_KEY_HERE with the API key shown when "${p}" was created.`,"API keys never expire."].join(` +`),chatgpt:["The user wants to connect GBrain MCP to ChatGPT.","","1. Open ChatGPT > Settings > Tools & Integrations > Add MCP Server","2. Enter this URL — ChatGPT will auto-discover the OAuth configuration:","",` ${U}/.well-known/oauth-authorization-server`,"","3. When prompted for credentials:",` Client ID: ${Z}`," Client Secret: (the secret from agent registration)"," Grant Type: client_credentials",` Scope: ${d.scope||"read write"}`].join(` +`),"claude-cowork":["The user wants to connect GBrain MCP to Claude.ai.","","1. Open claude.ai > Settings > Connected Apps > Add MCP Server",`2. Server URL: ${U}/mcp`,"3. When prompted for auth:",` Token endpoint: ${U}/token`,` Client ID: ${Z}`," Client Secret: (the secret from agent registration)",` Scope: ${d.scope||"read write"}`,"",`Discovery URL: ${U}/.well-known/oauth-authorization-server`].join(` +`),cursor:O?["The user wants to connect GBrain MCP to Cursor.","","Cursor supports OAuth for remote MCP. Add to .cursor/mcp.json:","","{",' "mcpServers": {',' "gbrain": {',` "url": "${U}/mcp",`,' "transport": "sse"'," }"," }","}","","Cursor will auto-discover OAuth via:",`${U}/.well-known/oauth-authorization-server`,"",`When prompted: Client ID ${Z}, use the secret from registration.`].join(` +`):["The user wants to connect GBrain MCP to Cursor.","","Add to .cursor/mcp.json:","","{",' "mcpServers": {',' "gbrain": {',` "url": "${U}/mcp",`,' "transport": "sse",',' "headers": {',' "Authorization": "Bearer PASTE_YOUR_API_KEY_HERE"'," }"," }"," }","}","",`Replace PASTE_YOUR_API_KEY_HERE with the API key shown when "${p}" was created.`].join(` +`),perplexity:["The user wants to connect GBrain MCP to Perplexity.","","1. Go to Settings > Connectors > Add MCP",`2. Server URL: ${U}/mcp`,`3. Client ID: ${Z}`,"4. Client Secret: (the secret from agent registration)"].join(` +`),json:JSON.stringify({server_url:U+"/mcp",token_url:U+"/token",discovery_url:U+"/.well-known/oauth-authorization-server",client_id:Z,client_name:p,auth_type:d.auth_type,scope:d.scope},null,2)};return f.jsxs(f.Fragment,{children:[f.jsx("div",{className:"drawer-overlay",onClick:N}),f.jsxs("div",{className:"drawer",children:[f.jsx("button",{className:"drawer-close",onClick:N,children:"✕"}),f.jsx("div",{style:{fontSize:18,fontWeight:600,marginBottom:4},children:d.name||d.client_name}),f.jsx("span",{className:`badge ${d.status==="active"?"badge-success":"badge-danger"}`,children:d.status}),f.jsx("div",{className:"section-title",children:"Details"}),f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Client ID"}),f.jsxs("span",{className:"mono",children:[(d.id||d.id||d.client_id||"").substring(0,24),"..."]}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Scopes"}),f.jsx("span",{children:(d.scope||"").split(" ").filter(Boolean).map(j=>f.jsx("span",{className:`badge badge-${j}`,style:{marginRight:4},children:j},j))}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Registered"}),f.jsx("span",{children:new Date(d.created_at).toLocaleDateString()}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Token TTL"}),f.jsx("span",{children:d.token_ttl?d.token_ttl>=31536e3?"No expiry":d.token_ttl>=86400?`${Math.floor(d.token_ttl/86400)}d`:d.token_ttl>=3600?`${Math.floor(d.token_ttl/3600)}h`:`${d.token_ttl}s`:"1h (default)"})]}),f.jsx("div",{className:"section-title",children:"Config Export"}),f.jsxs("div",{className:"tabs",style:{flexWrap:"wrap"},children:[f.jsx("div",{className:`tab ${h==="claude-code"?"active":""}`,onClick:()=>_("claude-code"),children:"Claude Code"}),f.jsx("div",{className:`tab ${h==="chatgpt"?"active":""}`,onClick:()=>_("chatgpt"),children:"ChatGPT"}),f.jsx("div",{className:`tab ${h==="claude-cowork"?"active":""}`,onClick:()=>_("claude-cowork"),children:"Claude.ai"}),f.jsx("div",{className:`tab ${h==="cursor"?"active":""}`,onClick:()=>_("cursor"),children:"Cursor"}),f.jsx("div",{className:`tab ${h==="perplexity"?"active":""}`,onClick:()=>_("perplexity"),children:"Perplexity"}),f.jsx("div",{className:`tab ${h==="json"?"active":""}`,onClick:()=>_("json"),children:"JSON"})]}),(()=>{if(!O&&new Set(["chatgpt","claude-cowork","perplexity"]).has(h)){const E={chatgpt:"ChatGPT","claude-cowork":"Claude.ai",perplexity:"Perplexity"}[h]||h;return f.jsxs("div",{style:{background:"rgba(255, 200, 100, 0.08)",border:"1px solid rgba(255, 200, 100, 0.2)",borderRadius:8,padding:"14px 16px",marginTop:12,fontSize:13,lineHeight:1.6,color:"var(--text-secondary)"},children:[f.jsxs("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:[E," requires an OAuth client"]}),E," only supports OAuth 2.0 (client_credentials). API keys use raw bearer tokens, which ",E," does not accept. Register a separate OAuth client and use that to connect this AI."]})}return f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0},children:H[h]}),f.jsx("button",{className:"copy-btn",onClick:()=>Y(H[h]),children:"Copy"})]})})(),f.jsxs("div",{style:{marginTop:32},children:[d.status==="active"&&f.jsx("button",{className:"btn btn-danger",onClick:async()=>{if(confirm(`Revoke ${d.name||d.client_name}? All active tokens will be invalidated.`))try{d.auth_type==="oauth"?await st.revokeClient(d.id||d.client_id||""):await st.revokeApiKey(d.name||""),M(),N()}catch(j){alert("Revoke failed: "+(j instanceof Error?j.message:"unknown error"))}},children:"Revoke Agent"}),d.status==="revoked"&&f.jsx("span",{style:{color:"var(--text-muted)",fontSize:13},children:"This agent has been revoked."})]})]})]})}function zy(){const[d,N]=k.useState({rows:[],total:0,page:1,pages:1}),[M,h]=k.useState(1),[_,Y]=k.useState("all"),[U,Z]=k.useState(null);k.useEffect(()=>{O(M)},[M,_]);const O=E=>{const I=_!=="all"?`&agent=${encodeURIComponent(_)}`:"";st.requests(E,I).then(N).catch(()=>{})},p=E=>{const I=Date.now()-new Date(E).getTime();return I<6e4?`${Math.floor(I/1e3)}s ago`:I<36e5?`${Math.floor(I/6e4)} min ago`:I<864e5?`${Math.floor(I/36e5)}h ago`:new Date(E).toLocaleDateString()},H=E=>{if(!E)return null;const{query:I,slug:L,partial:nl,limit:tl,...pl}=E,Ml=[];return I&&Ml.push(`"${I}"`),L&&Ml.push(L),nl&&Ml.push(`~${nl}`),tl&&Ml.push(`limit=${tl}`),Object.keys(pl).length>0&&Ml.push(`+${Object.keys(pl).length} params`),Ml.join(" ")},j=new Map;return d.rows.forEach(E=>{E.token_name&&j.set(E.token_name,E.agent_name||E.token_name)}),f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Request Log"}),f.jsxs("select",{value:_,onChange:E=>{Y(E.target.value),h(1)},style:{background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"4px 8px",fontSize:13},children:[f.jsx("option",{value:"all",children:"All agents"}),[...j.entries()].map(([E,I])=>f.jsx("option",{value:E,children:I},E))]})]}),d.rows.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No requests yet."}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Time"}),f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Params"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"})]})}),f.jsx("tbody",{children:d.rows.map(E=>f.jsxs(Mr.Fragment,{children:[f.jsxs("tr",{onClick:()=>Z(U===E.id?null:E.id),style:{cursor:"pointer"},children:[f.jsx("td",{style:{color:"var(--text-secondary)",whiteSpace:"nowrap"},children:p(E.created_at)}),f.jsx("td",{children:f.jsx("a",{style:{color:"var(--text-link, #88aaff)",cursor:"pointer",textDecoration:"none",fontWeight:500},onClick:I=>{I.stopPropagation(),Y(E.token_name),h(1)},children:E.agent_name||E.token_name})}),f.jsx("td",{className:"mono",children:E.operation}),f.jsx("td",{style:{color:"var(--text-secondary)",fontSize:12,maxWidth:200,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:H(E.params)}),f.jsxs("td",{className:"mono",children:[E.latency_ms,"ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${E.status}`,children:E.status})})]}),U===E.id&&f.jsx("tr",{children:f.jsx("td",{colSpan:6,style:{background:"var(--bg-secondary, #0f0f1a)",padding:16},children:f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Time"}),f.jsx("span",{children:new Date(E.created_at).toLocaleString()}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Agent"}),f.jsx("span",{className:"mono",children:E.token_name}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Operation"}),f.jsx("span",{className:"mono",children:E.operation}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Latency"}),f.jsxs("span",{children:[E.latency_ms,"ms"]}),E.params&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Params"}),f.jsx("pre",{className:"mono",style:{margin:0,whiteSpace:"pre-wrap",fontSize:12},children:JSON.stringify(E.params,null,2)})]}),E.error_message&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:"Error"}),f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:E.error_message})]})]})})})]},E.id))})]}),f.jsxs("div",{className:"pagination",children:[f.jsxs("span",{children:["Page ",d.page," of ",d.pages," (",d.total," total)"]}),f.jsxs("div",{style:{display:"flex",gap:8},children:[f.jsx("button",{disabled:d.page<=1,onClick:()=>h(E=>E-1),children:"Previous"}),f.jsx("button",{disabled:d.page>=d.pages,onClick:()=>h(E=>E+1),children:"Next"})]})]})]})]})}function xy({markup:d}){return f.jsx("div",{style:{width:"100%",overflow:"auto"},dangerouslySetInnerHTML:{__html:d}})}function Zu({type:d,ariaLabel:N}){const[M,h]=k.useState(""),[_,Y]=k.useState("");return k.useEffect(()=>{let U=!1;return st.calibrationChart(d).then(Z=>{U||h(Z)}).catch(Z=>{U||Y(Z.message??"fetch failed")}),()=>{U=!0}},[d]),_?f.jsxs("div",{style:{padding:16,color:"var(--error)"},role:"alert",children:[N,": ",_]}):M?f.jsx(xy,{markup:M}):f.jsxs("div",{style:{padding:16,color:"var(--text-muted)"},children:[N," loading..."]})}function Ay(){const[d,N]=k.useState(null),[M,h]=k.useState(!0),[_,Y]=k.useState("");if(k.useEffect(()=>{st.calibrationProfile().then(O=>{N(O),h(!1)}).catch(O=>{Y(O.message??"fetch failed"),h(!1)})},[]),M)return f.jsx("div",{style:{padding:24,color:"var(--text-secondary)"},children:"Loading calibration profile…"});if(_)return f.jsxs("div",{style:{padding:24,color:"var(--error)"},role:"alert",children:["Could not load calibration profile: ",_]});if(!d)return f.jsxs("div",{style:{padding:24,maxWidth:700},children:[f.jsx("h1",{style:{marginBottom:16},children:"Calibration"}),f.jsx("p",{style:{color:"var(--text-secondary)"},children:"No calibration profile yet. Builds after 5+ resolved takes."}),f.jsx("pre",{style:{background:"var(--bg-secondary)",padding:12,borderRadius:4,color:"var(--text-primary)",marginTop:12,fontFamily:"var(--font-mono)"},children:"gbrain dream --phase calibration_profile"})]});const U=new Date(d.generated_at),Z=Math.floor((Date.now()-U.getTime())/(1e3*60*60*24));return f.jsxs("div",{style:{padding:32,maxWidth:720},children:[f.jsx("h1",{style:{marginBottom:8},children:"Calibration"}),f.jsxs("div",{style:{color:"var(--text-muted)",fontSize:13,marginBottom:24},children:["Holder: ",d.holder," · ","Updated ",Z===0?"today":`${Z}d ago`,d.published&&" · published",d.grade_completion<.9&&` · ~${Math.round(d.grade_completion*100)}% graded`,!d.voice_gate_passed&&" · voice gate fell back to template"]}),f.jsx("section",{style:{marginBottom:32},children:f.jsx(Zu,{type:"brier-trend",ariaLabel:"Brier trend"})}),f.jsxs("section",{style:{marginBottom:32},children:[f.jsx("h2",{style:{fontSize:14,color:"var(--text-secondary)",marginBottom:12,fontWeight:400},children:"Pattern statements"}),f.jsx(Zu,{type:"pattern-statements",ariaLabel:"Pattern statements"})]}),f.jsx("section",{style:{marginBottom:32},children:f.jsx(Zu,{type:"domain-bars",ariaLabel:"Per-domain accuracy"})}),f.jsx("section",{style:{marginBottom:32},children:f.jsx(Zu,{type:"abandoned-threads",ariaLabel:"Abandoned threads"})}),d.active_bias_tags.length>0&&f.jsxs("section",{style:{marginBottom:32,color:"var(--text-muted)",fontSize:13},children:["Active bias tags: ",d.active_bias_tags.join(", ")]})]})}function Or(){const d=window.location.hash.replace("#","")||"dashboard";return["login","dashboard","agents","log","calibration"].includes(d)?d:"dashboard"}function Ey(){const[d,N]=k.useState(Or);k.useEffect(()=>{const _=()=>N(Or());return window.addEventListener("hashchange",_),()=>window.removeEventListener("hashchange",_)},[]);const M=_=>{window.location.hash=_,N(_)};if(d==="login")return f.jsx(hy,{onLogin:()=>M("dashboard")});const h=async()=>{if(confirm("Sign out every active admin session, including other browsers and tabs? Each one will need to re-authenticate via a fresh magic link.")){try{await st.signOutEverywhere()}catch{}M("login")}};return f.jsxs("div",{className:"app",children:[f.jsxs("nav",{className:"sidebar",children:[f.jsx("div",{className:"sidebar-logo",children:"GBrain"}),f.jsxs("div",{className:"sidebar-nav",children:[f.jsx("a",{className:`nav-item ${d==="dashboard"?"active":""}`,onClick:()=>M("dashboard"),children:"Dashboard"}),f.jsx("a",{className:`nav-item ${d==="agents"?"active":""}`,onClick:()=>M("agents"),children:"Agents"}),f.jsx("a",{className:`nav-item ${d==="log"?"active":""}`,onClick:()=>M("log"),children:"Request Log"}),f.jsx("a",{className:`nav-item ${d==="calibration"?"active":""}`,onClick:()=>M("calibration"),children:"Calibration"})]}),f.jsx("div",{style:{marginTop:"auto",padding:"16px 12px",borderTop:"1px solid var(--border)"},children:f.jsx("button",{onClick:h,style:{background:"transparent",border:"1px solid var(--border)",color:"var(--text-secondary)",padding:"6px 10px",borderRadius:6,fontSize:12,cursor:"pointer",width:"100%"},title:"Revoke every active admin session — every browser, every tab",children:"Sign out everywhere"})})]}),f.jsxs("main",{className:"main",children:[d==="dashboard"&&f.jsx(my,{}),d==="agents"&&f.jsx(vy,{}),d==="log"&&f.jsx(zy,{}),d==="calibration"&&f.jsx(Ay,{})]})]})}dy.createRoot(document.getElementById("root")).render(f.jsx(Mr.StrictMode,{children:f.jsx(Ey,{})})); diff --git a/admin/dist/assets/index-BOifXQpQ.css b/admin/dist/assets/index-GxkWX7v3.css similarity index 98% rename from admin/dist/assets/index-BOifXQpQ.css rename to admin/dist/assets/index-GxkWX7v3.css index c5068781d..32e5e375f 100644 --- a/admin/dist/assets/index-BOifXQpQ.css +++ b/admin/dist/assets/index-GxkWX7v3.css @@ -1 +1 @@ -:root{--bg-primary: #0a0a0f;--bg-secondary: #14141f;--bg-tertiary: #1e1e2e;--text-primary: #e0e0e0;--text-secondary: #888;--text-muted: #555;--accent: #3b82f6;--success: #22c55e;--warning: #f59e0b;--error: #ef4444;--font-mono: "JetBrains Mono", monospace;--font-sans: "Inter", system-ui, sans-serif}*{margin:0;padding:0;box-sizing:border-box}body{font-family:var(--font-sans);background:var(--bg-primary);color:var(--text-primary);font-size:14px;line-height:1.5}.app{display:flex;min-height:100vh}.sidebar{width:200px;background:var(--bg-secondary);border-right:1px solid #1e1e2e;padding:16px 0;flex-shrink:0;display:flex;flex-direction:column}.sidebar-logo{font-size:18px;font-weight:600;padding:0 16px 24px;color:var(--text-primary)}.sidebar-nav{display:flex;flex-direction:column;gap:2px}.nav-item{display:flex;align-items:center;gap:8px;padding:8px 16px;color:var(--text-secondary);text-decoration:none;font-size:13px;cursor:pointer;border-left:3px solid transparent;transition:all .15s}.nav-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.nav-item.active{border-left-color:var(--accent);background:var(--bg-tertiary);color:var(--text-primary)}.main{flex:1;padding:24px 32px;overflow-y:auto}.page-title{font-size:24px;font-weight:600;margin-bottom:24px}.metrics{display:flex;gap:16px;margin-bottom:24px}.metric{background:var(--bg-secondary);padding:16px 20px;border-radius:6px;min-width:140px}.metric-value{font-family:var(--font-mono);font-size:28px;font-weight:500}.metric-label{font-size:12px;color:var(--text-secondary);margin-top:4px}table{width:100%;border-collapse:collapse}th{text-align:left;font-size:11px;text-transform:uppercase;color:var(--text-muted);padding:8px 12px;font-weight:500;letter-spacing:.5px}td{padding:10px 12px;font-size:13px;border-top:1px solid #1a1a2a}tr:hover td{background:var(--bg-tertiary)}.badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:500}.badge-read{background:#3b82f626;color:var(--accent)}.badge-write{background:#f59e0b26;color:var(--warning)}.badge-admin{background:#ef444426;color:var(--error)}.badge-success{background:#22c55e26;color:var(--success)}.badge-error{background:#ef444426;color:var(--error)}.status-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}.status-active{background:var(--success)}.status-warning{background:var(--warning)}.status-inactive{background:var(--text-muted)}.btn{padding:8px 16px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:none;transition:all .15s}.btn-primary{background:var(--accent);color:#fff}.btn-primary:hover{background:#2563eb}.btn-secondary{background:transparent;color:var(--text-secondary);border:1px solid #333}.btn-secondary:hover{border-color:var(--text-secondary);color:var(--text-primary)}.btn-danger{background:transparent;color:var(--error);border:1px solid var(--error)}.btn-danger:hover{background:#ef44441a}input,select{background:var(--bg-primary);border:1px solid #333;color:var(--text-primary);padding:8px 12px;border-radius:6px;font-size:13px;font-family:var(--font-sans);width:100%}input:focus,select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px #3b82f633}input::placeholder{color:var(--text-muted)}label{display:block;font-size:13px;font-weight:500;margin-bottom:6px}.modal-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000b3;display:flex;align-items:center;justify-content:center;z-index:100}.modal{background:var(--bg-secondary);border-radius:8px;padding:24px;min-width:420px;max-width:520px}.modal-title{font-size:18px;font-weight:600;margin-bottom:20px}.drawer-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;z-index:90}.drawer{position:fixed;right:0;top:0;bottom:0;width:420px;background:var(--bg-secondary);border-left:1px solid var(--accent);padding:24px;z-index:91;overflow-y:auto}.drawer-close{position:absolute;top:16px;right:16px;background:none;border:none;color:var(--text-muted);font-size:18px;cursor:pointer}.section-title{font-size:11px;text-transform:uppercase;color:var(--text-muted);letter-spacing:.5px;margin:20px 0 12px;font-weight:500}.health-panel{background:var(--bg-secondary);border-radius:6px;padding:16px}.health-row{display:flex;justify-content:space-between;padding:6px 0;font-size:13px}.code-block{background:var(--bg-primary);border-radius:6px;padding:12px;font-family:var(--font-mono);font-size:12px;overflow-x:auto;position:relative}.code-block .copy-btn{position:absolute;top:8px;right:8px;background:var(--accent);color:#fff;border:none;padding:4px 10px;border-radius:4px;font-size:11px;cursor:pointer}.feed{max-height:400px;overflow-y:auto}.feed-empty{color:var(--text-muted);text-align:center;padding:32px;font-size:13px}.sparkline{display:inline-block;vertical-align:middle}.filter-bar{display:flex;gap:12px;margin-bottom:16px;align-items:center}.filter-bar select{width:auto;min-width:140px}.pagination{display:flex;justify-content:space-between;align-items:center;padding:12px 0;font-size:13px;color:var(--text-secondary)}.pagination button{background:var(--bg-secondary);border:1px solid #333;color:var(--text-primary);padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px}.pagination button:disabled{opacity:.3;cursor:default}.warning-bar{background:#f59e0b26;border:1px solid var(--warning);color:var(--warning);padding:10px 16px;border-radius:6px;font-size:13px;margin:12px 0}.checkbox-group{display:flex;gap:16px;flex-wrap:wrap}.checkbox-label{display:flex;align-items:center;gap:6px;font-size:13px;cursor:pointer}.tabs{display:flex;gap:0;margin-bottom:12px}.tab{padding:6px 12px;font-size:13px;color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent}.tab.active{color:var(--accent);border-bottom-color:var(--accent)}.login-page{display:flex;align-items:center;justify-content:center;min-height:100vh;background:var(--bg-primary)}.login-box{text-align:left;width:340px}.login-logo{font-size:32px;font-weight:600;margin-bottom:32px}.login-hint{color:var(--text-muted);font-size:12px;margin-top:12px}.login-error{color:var(--error);font-size:13px;margin-top:8px}.mono{font-family:var(--font-mono);font-size:12px}@media(max-width:768px){.sidebar{display:none}.main{padding:16px}.metrics{flex-wrap:wrap}.drawer{width:100%}} +:root{--bg-primary: #0a0a0f;--bg-secondary: #14141f;--bg-tertiary: #1e1e2e;--text-primary: #e0e0e0;--text-secondary: #888;--text-muted: #777;--accent: #3b82f6;--success: #22c55e;--warning: #f59e0b;--error: #ef4444;--font-mono: "JetBrains Mono", monospace;--font-sans: "Inter", system-ui, sans-serif}*{margin:0;padding:0;box-sizing:border-box}body{font-family:var(--font-sans);background:var(--bg-primary);color:var(--text-primary);font-size:14px;line-height:1.5}.app{display:flex;min-height:100vh}.sidebar{width:200px;background:var(--bg-secondary);border-right:1px solid #1e1e2e;padding:16px 0;flex-shrink:0;display:flex;flex-direction:column}.sidebar-logo{font-size:18px;font-weight:600;padding:0 16px 24px;color:var(--text-primary)}.sidebar-nav{display:flex;flex-direction:column;gap:2px}.nav-item{display:flex;align-items:center;gap:8px;padding:8px 16px;color:var(--text-secondary);text-decoration:none;font-size:13px;cursor:pointer;border-left:3px solid transparent;transition:all .15s}.nav-item:hover{background:var(--bg-tertiary);color:var(--text-primary)}.nav-item.active{border-left-color:var(--accent);background:var(--bg-tertiary);color:var(--text-primary)}.main{flex:1;padding:24px 32px;overflow-y:auto}.page-title{font-size:24px;font-weight:600;margin-bottom:24px}.metrics{display:flex;gap:16px;margin-bottom:24px}.metric{background:var(--bg-secondary);padding:16px 20px;border-radius:6px;min-width:140px}.metric-value{font-family:var(--font-mono);font-size:28px;font-weight:500}.metric-label{font-size:12px;color:var(--text-secondary);margin-top:4px}table{width:100%;border-collapse:collapse}th{text-align:left;font-size:11px;text-transform:uppercase;color:var(--text-muted);padding:8px 12px;font-weight:500;letter-spacing:.5px}td{padding:10px 12px;font-size:13px;border-top:1px solid #1a1a2a}tr:hover td{background:var(--bg-tertiary)}.badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:500}.badge-read{background:#3b82f626;color:var(--accent)}.badge-write{background:#f59e0b26;color:var(--warning)}.badge-admin{background:#ef444426;color:var(--error)}.badge-success{background:#22c55e26;color:var(--success)}.badge-error{background:#ef444426;color:var(--error)}.status-dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}.status-active{background:var(--success)}.status-warning{background:var(--warning)}.status-inactive{background:var(--text-muted)}.btn{padding:8px 16px;border-radius:6px;font-size:13px;font-weight:500;cursor:pointer;border:none;transition:all .15s}.btn-primary{background:var(--accent);color:#fff}.btn-primary:hover{background:#2563eb}.btn-secondary{background:transparent;color:var(--text-secondary);border:1px solid #333}.btn-secondary:hover{border-color:var(--text-secondary);color:var(--text-primary)}.btn-danger{background:transparent;color:var(--error);border:1px solid var(--error)}.btn-danger:hover{background:#ef44441a}input,select{background:var(--bg-primary);border:1px solid #333;color:var(--text-primary);padding:8px 12px;border-radius:6px;font-size:13px;font-family:var(--font-sans);width:100%}input:focus,select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px #3b82f633}input::placeholder{color:var(--text-muted)}label{display:block;font-size:13px;font-weight:500;margin-bottom:6px}.modal-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000b3;display:flex;align-items:center;justify-content:center;z-index:100}.modal{background:var(--bg-secondary);border-radius:8px;padding:24px;min-width:420px;max-width:520px}.modal-title{font-size:18px;font-weight:600;margin-bottom:20px}.drawer-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;z-index:90}.drawer{position:fixed;right:0;top:0;bottom:0;width:420px;background:var(--bg-secondary);border-left:1px solid var(--accent);padding:24px;z-index:91;overflow-y:auto}.drawer-close{position:absolute;top:16px;right:16px;background:none;border:none;color:var(--text-muted);font-size:18px;cursor:pointer}.section-title{font-size:11px;text-transform:uppercase;color:var(--text-muted);letter-spacing:.5px;margin:20px 0 12px;font-weight:500}.health-panel{background:var(--bg-secondary);border-radius:6px;padding:16px}.health-row{display:flex;justify-content:space-between;padding:6px 0;font-size:13px}.code-block{background:var(--bg-primary);border-radius:6px;padding:12px;font-family:var(--font-mono);font-size:12px;overflow-x:auto;position:relative}.code-block .copy-btn{position:absolute;top:8px;right:8px;background:var(--accent);color:#fff;border:none;padding:4px 10px;border-radius:4px;font-size:11px;cursor:pointer}.feed{max-height:400px;overflow-y:auto}.feed-empty{color:var(--text-muted);text-align:center;padding:32px;font-size:13px}.sparkline{display:inline-block;vertical-align:middle}.filter-bar{display:flex;gap:12px;margin-bottom:16px;align-items:center}.filter-bar select{width:auto;min-width:140px}.pagination{display:flex;justify-content:space-between;align-items:center;padding:12px 0;font-size:13px;color:var(--text-secondary)}.pagination button{background:var(--bg-secondary);border:1px solid #333;color:var(--text-primary);padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px}.pagination button:disabled{opacity:.3;cursor:default}.warning-bar{background:#f59e0b26;border:1px solid var(--warning);color:var(--warning);padding:10px 16px;border-radius:6px;font-size:13px;margin:12px 0}.checkbox-group{display:flex;gap:16px;flex-wrap:wrap}.checkbox-label{display:flex;align-items:center;gap:6px;font-size:13px;cursor:pointer}.tabs{display:flex;gap:0;margin-bottom:12px}.tab{padding:6px 12px;font-size:13px;color:var(--text-secondary);cursor:pointer;border-bottom:2px solid transparent}.tab.active{color:var(--accent);border-bottom-color:var(--accent)}.login-page{display:flex;align-items:center;justify-content:center;min-height:100vh;background:var(--bg-primary)}.login-box{text-align:left;width:340px}.login-logo{font-size:32px;font-weight:600;margin-bottom:32px}.login-hint{color:var(--text-muted);font-size:12px;margin-top:12px}.login-error{color:var(--error);font-size:13px;margin-top:8px}.mono{font-family:var(--font-mono);font-size:12px}@media(max-width:768px){.sidebar{display:none}.main{padding:16px}.metrics{flex-wrap:wrap}.drawer{width:100%}} diff --git a/admin/dist/index.html b/admin/dist/index.html index 2dd8be830..7e8440a2d 100644 --- a/admin/dist/index.html +++ b/admin/dist/index.html @@ -7,8 +7,8 @@ - - + +
diff --git a/admin/src/App.tsx b/admin/src/App.tsx index 67288d473..af80181a1 100644 --- a/admin/src/App.tsx +++ b/admin/src/App.tsx @@ -3,13 +3,14 @@ import { LoginPage } from './pages/Login'; import { DashboardPage } from './pages/Dashboard'; import { AgentsPage } from './pages/Agents'; import { RequestLogPage } from './pages/RequestLog'; +import { CalibrationPage } from './pages/Calibration'; import { api } from './api'; -type Page = 'login' | 'dashboard' | 'agents' | 'log'; +type Page = 'login' | 'dashboard' | 'agents' | 'log' | 'calibration'; function getPage(): Page { const hash = window.location.hash.replace('#', '') || 'dashboard'; - if (['login', 'dashboard', 'agents', 'log'].includes(hash)) return hash as Page; + if (['login', 'dashboard', 'agents', 'log', 'calibration'].includes(hash)) return hash as Page; return 'dashboard'; } @@ -54,6 +55,8 @@ export function App() { onClick={() => navigate('agents')}>Agents navigate('log')}>Request Log + navigate('calibration')}>Calibration
); diff --git a/admin/src/api.ts b/admin/src/api.ts index de08d59d9..8989b42c9 100644 --- a/admin/src/api.ts +++ b/admin/src/api.ts @@ -22,6 +22,17 @@ async function apiFetch(path: string, options?: RequestInit) { return res.json(); } +// v0.36.0.0 (T15 / E6) — SVG fetch (text/plain payload, NOT JSON). +async function apiFetchText(path: string) { + const res = await fetch(`${BASE}${path}`, { credentials: 'same-origin' }); + if (res.status === 401) { + window.location.hash = '#login'; + throw new Error('Unauthorized'); + } + if (!res.ok) throw new Error(`HTTP ${res.status}`); + return res.text(); +} + export const api = { login: (token: string) => apiFetch('/admin/login', { method: 'POST', body: JSON.stringify({ token }) }), signOutEverywhere: () => apiFetch('/admin/api/sign-out-everywhere', { method: 'POST' }), @@ -34,4 +45,9 @@ export const api = { revokeApiKey: (name: string) => apiFetch('/admin/api/api-keys/revoke', { method: 'POST', body: JSON.stringify({ name }) }), updateClientTtl: (clientId: string, tokenTtl: number | null) => apiFetch('/admin/api/update-client-ttl', { method: 'POST', body: JSON.stringify({ clientId, tokenTtl }) }), revokeClient: (clientId: string) => apiFetch('/admin/api/revoke-client', { method: 'POST', body: JSON.stringify({ clientId }) }), + // v0.36.0.0 (T15 / E6) — calibration endpoints. + calibrationProfile: (holder?: string) => + apiFetch(`/admin/api/calibration/profile${holder ? `?holder=${encodeURIComponent(holder)}` : ''}`), + calibrationChart: (type: string, holder?: string) => + apiFetchText(`/admin/api/calibration/charts/${encodeURIComponent(type)}${holder ? `?holder=${encodeURIComponent(holder)}` : ''}`), }; diff --git a/admin/src/index.css b/admin/src/index.css index aa385fe9d..19997874d 100644 --- a/admin/src/index.css +++ b/admin/src/index.css @@ -4,7 +4,10 @@ --bg-tertiary: #1e1e2e; --text-primary: #e0e0e0; --text-secondary: #888; - --text-muted: #555; + /* v0.36.0.0 TD2 — bumped from #555 (contrast 4.0 on #0a0a0f bg, below WCAG AA + 4.5 for body text) to #777 (contrast ~5.5, passes AA). Applies globally + to Dashboard, Agents, RequestLog, and the new Calibration tab. */ + --text-muted: #777; --accent: #3b82f6; --success: #22c55e; --warning: #f59e0b; diff --git a/admin/src/pages/Calibration.tsx b/admin/src/pages/Calibration.tsx new file mode 100644 index 000000000..27f15fefb --- /dev/null +++ b/admin/src/pages/Calibration.tsx @@ -0,0 +1,174 @@ +/** + * v0.36.0.0 (T15 / E6) — Calibration tab. + * + * Fetches the active calibration profile + 4 server-rendered SVG charts. + * Layout: Linear calm clarity (per D23 mockup variant-B) — single column, + * generous whitespace, ONE big sparkline as hero, then patterns, then + * domain bars, then abandoned threads. + * + * Per D23 — SVG markup comes from the server (image/svg+xml endpoint). + * Admin SPA renders inside a TrustedSVG wrapper that uses + * dangerouslySetInnerHTML. XSS posture: server-side escapeXml() on all + * caller-controlled strings + requireAdmin middleware on the endpoint. + */ + +import React, { useEffect, useState } from 'react'; +import { api } from '../api'; + +interface CalibrationProfileSummary { + holder: string; + source_id: string; + generated_at: string; + published: boolean; + total_resolved: number; + brier: number | null; + accuracy: number | null; + partial_rate: number | null; + grade_completion: number; + pattern_statements: string[]; + active_bias_tags: string[]; + voice_gate_passed: boolean; + voice_gate_attempts: number; +} + +interface ChartSvgProps { + type: string; + ariaLabel: string; +} + +function TrustedSVG({ markup }: { markup: string }) { + return ( +
+ ); +} + +function ChartSvg({ type, ariaLabel }: ChartSvgProps) { + const [markup, setMarkup] = useState(''); + const [error, setError] = useState(''); + + useEffect(() => { + let cancelled = false; + api + .calibrationChart(type) + .then(svg => { + if (!cancelled) setMarkup(svg); + }) + .catch(err => { + if (!cancelled) setError(err.message ?? 'fetch failed'); + }); + return () => { + cancelled = true; + }; + }, [type]); + + if (error) { + return ( +
+ {ariaLabel}: {error} +
+ ); + } + if (!markup) { + return
{ariaLabel} loading...
; + } + return ; +} + +export function CalibrationPage() { + const [profile, setProfile] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(''); + + useEffect(() => { + api + .calibrationProfile() + .then(p => { + setProfile(p); + setLoading(false); + }) + .catch(err => { + setError(err.message ?? 'fetch failed'); + setLoading(false); + }); + }, []); + + if (loading) { + return
Loading calibration profile…
; + } + if (error) { + return ( +
+ Could not load calibration profile: {error} +
+ ); + } + if (!profile) { + return ( +
+

Calibration

+

+ No calibration profile yet. Builds after 5+ resolved takes. +

+
+          gbrain dream --phase calibration_profile
+        
+
+ ); + } + + const generated = new Date(profile.generated_at); + const generatedAgo = Math.floor((Date.now() - generated.getTime()) / (1000 * 60 * 60 * 24)); + + return ( +
+

Calibration

+
+ Holder: {profile.holder} + {' · '} + Updated {generatedAgo === 0 ? 'today' : `${generatedAgo}d ago`} + {profile.published && ' · published'} + {profile.grade_completion < 0.9 && ` · ~${Math.round(profile.grade_completion * 100)}% graded`} + {!profile.voice_gate_passed && ' · voice gate fell back to template'} +
+ +
+ +
+ +
+

+ Pattern statements +

+ +
+ +
+ +
+ +
+ +
+ + {profile.active_bias_tags.length > 0 && ( +
+ Active bias tags: {profile.active_bias_tags.join(', ')} +
+ )} +
+ ); +} diff --git a/src/commands/serve-http.ts b/src/commands/serve-http.ts index db00d3540..b88c2a1a2 100644 --- a/src/commands/serve-http.ts +++ b/src/commands/serve-http.ts @@ -620,6 +620,97 @@ export async function runServeHttp(engine: BrainEngine, options: ServeHttpOption res.status(result.status).json(result.body); }); + // v0.36.0.0 (T15 / E6 / D23) — Calibration tab data endpoints. + // Server-rendered SVG charts; admin SPA renders via TrustedSVG wrapper. + app.get('/admin/api/calibration/profile', requireAdmin, async (req: Request, res: Response) => { + try { + const { getLatestProfile } = await import('./calibration.ts'); + const holder = (req.query.holder as string) || 'garry'; + const profile = await getLatestProfile(engine, { holder }); + res.json(profile); + } catch (err) { + res.status(500).json({ error: err instanceof Error ? err.message : 'unknown' }); + } + }); + + app.get('/admin/api/calibration/charts/:type', requireAdmin, async (req: Request, res: Response) => { + try { + const { getLatestProfile } = await import('./calibration.ts'); + const { + renderBrierTrend, + renderDomainBars, + renderAbandonedThreadsCard, + renderPatternStatementsCard, + } = await import('../core/calibration/svg-renderer.ts'); + const holder = (req.query.holder as string) || 'garry'; + const type = req.params.type; + const profile = await getLatestProfile(engine, { holder }); + + res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8'); + res.setHeader('Cache-Control', 'private, max-age=60'); + + if (type === 'brier-trend') { + // v0.36.0.0 ship state: 1-point series from the active profile. A + // proper 90-day time series will read from calibration_profiles + // generated_at history in v0.37 once we have multiple snapshots. + const series = profile?.brier !== null && profile?.brier !== undefined + ? [{ date: profile.generated_at.slice(0, 10), brier: profile.brier }] + : []; + return res.send(renderBrierTrend({ series })); + } + if (type === 'domain-bars') { + // v0.36.0.0 ship state: domain_scorecards JSONB is a placeholder + // (per-domain rendering comes when batchGetTakesScorecards lands in + // a follow-up). Render empty for now. + return res.send(renderDomainBars({ bars: [] })); + } + if (type === 'pattern-statements') { + return res.send( + renderPatternStatementsCard( + (profile?.pattern_statements ?? []).map((text: string) => ({ text })), + ), + ); + } + if (type === 'abandoned-threads') { + // v0.36.0.0 ship state: pull abandoned threads inline via a small + // SQL query (the doctor check counts them; this surfaces details). + const rows = await engine.executeRaw<{ + id: number; + page_slug: string; + claim: string; + weight: number; + since_date: string; + }>( + `SELECT id, page_slug, claim, weight, since_date + FROM takes + WHERE active = true AND resolved_at IS NULL AND superseded_by IS NULL + AND weight >= 0.7 + AND since_date::date < (now() - INTERVAL '12 months') + ORDER BY since_date ASC + LIMIT 5`, + ); + const now = new Date(); + const threads = rows.map(r => { + const since = new Date((r.since_date.length === 7 ? r.since_date + '-15' : r.since_date)); + const monthsSilent = Math.max(0, Math.floor((now.getTime() - since.getTime()) / (1000 * 60 * 60 * 24 * 30))); + return { + takeId: r.id, + pageSlug: r.page_slug, + claim: r.claim, + monthsSilent, + conviction: r.weight, + }; + }); + return res.send(renderAbandonedThreadsCard(threads)); + } + res.status(400).json({ error: 'unknown_chart_type', supported: ['brier-trend', 'domain-bars', 'pattern-statements', 'abandoned-threads'] }); + return; + } catch (err) { + res.status(500).json({ error: err instanceof Error ? err.message : 'unknown' }); + return; + } + }); + app.get('/admin/api/requests', requireAdmin, async (req: Request, res: Response) => { try { const page = parseInt(req.query.page as string) || 1; diff --git a/src/core/calibration/svg-renderer.ts b/src/core/calibration/svg-renderer.ts new file mode 100644 index 000000000..8e4721216 --- /dev/null +++ b/src/core/calibration/svg-renderer.ts @@ -0,0 +1,247 @@ +/** + * v0.36.0.0 (T15 / D23) — server-rendered SVG charts for the admin SPA. + * + * Pure functions: data → SVG string. No DOM, no React, no chart library. + * Admin tab fetches these endpoints and dangerouslySetInnerHTML's the + * markup inside a TrustedSVG wrapper. + * + * Why server-rendered SVG (per D23): + * - Chart logic stays close to the data math. + * - Zero new client-side chart-library dep. + * - SVG is accessible (text labels), scalable, copy-paste-friendly to + * PR descriptions and docs. + * - Sets the precedent for future admin charts (contradictions trend, + * takes scorecard, etc.). + * + * Design tokens inlined (must match admin/src/index.css): + * --bg-primary: #0a0a0f + * --bg-secondary: #14141f + * --text-primary: #e0e0e0 + * --text-secondary: #888 + * --text-muted: #777 (TD2 bump from #555 for AA contrast) + * --accent: #3b82f6 + * + * XSS posture: + * Output is generated server-side from typed inputs. Numeric inputs are + * coerced via `.toFixed(...)`. String inputs (pattern statements, abandoned + * thread claims) pass through `escapeXml()`. Admin SPA renders via a + * sandboxed
wrapper that's gated by + * requireAdmin middleware on the endpoint. + */ + +/** Min-safe XML attribute / text node escape. */ +export function escapeXml(s: string): string { + return s + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +const TOKEN = { + bgPrimary: '#0a0a0f', + bgSecondary: '#14141f', + textPrimary: '#e0e0e0', + textSecondary: '#888', + textMuted: '#777', // TD2 bump + accent: '#3b82f6', +} as const; + +// ─── Brier trend sparkline ────────────────────────────────────────── + +export interface BrierTrendPoint { + date: string; // ISO YYYY-MM-DD + brier: number; +} + +export interface BrierTrendOpts { + /** 7 / 30 / 90 / 365 day series, oldest → newest. */ + series: BrierTrendPoint[]; + /** Default 600 x 180 — sized for the admin SPA's single-column flow. */ + width?: number; + height?: number; +} + +export function renderBrierTrend(opts: BrierTrendOpts): string { + const w = opts.width ?? 600; + const h = opts.height ?? 180; + const padL = 40; + const padR = 16; + const padT = 20; + const padB = 28; + const plotW = w - padL - padR; + const plotH = h - padT - padB; + + if (opts.series.length === 0) { + return svgEmpty(w, h, 'No Brier-trend data yet (need 5+ resolved takes)'); + } + + // y-axis: Brier in [0, 0.4]. 0 = perfect; 0.25 = always-50% baseline. + const yMax = 0.4; + const xScale = (i: number): number => + padL + (opts.series.length === 1 ? plotW / 2 : (i / (opts.series.length - 1)) * plotW); + const yScale = (brier: number): number => padT + plotH - (Math.min(brier, yMax) / yMax) * plotH; + + const points = opts.series + .map((p, i) => `${xScale(i).toFixed(1)},${yScale(p.brier).toFixed(1)}`) + .join(' '); + + // Baseline reference line at Brier=0.25 (always-50%). + const baselineY = yScale(0.25).toFixed(1); + + const labels: string[] = []; + // X-axis: first + last date. + if (opts.series.length >= 2) { + const first = opts.series[0]!; + const last = opts.series[opts.series.length - 1]!; + labels.push( + `${escapeXml(first.date)}`, + `${escapeXml(last.date)}`, + ); + } + // Y-axis: 0.0 / 0.2 / 0.4 labels. + for (const y of [0, 0.2, 0.4]) { + labels.push( + `${y.toFixed(1)}`, + ); + } + + return ` + + Brier (lower is better) + + + ${labels.join('\n ')} +`; +} + +// ─── Per-domain accuracy bars ─────────────────────────────────────── + +export interface DomainBar { + /** Display label, e.g. "macro tech". */ + label: string; + /** accuracy in [0,1]. */ + accuracy: number; + /** Sample size for this domain. */ + n: number; +} + +export interface DomainBarsOpts { + bars: DomainBar[]; + width?: number; + /** Per-bar row height. Total height = bars.length * rowH + topPad. */ + rowHeight?: number; +} + +export function renderDomainBars(opts: DomainBarsOpts): string { + const w = opts.width ?? 600; + const rowH = opts.rowHeight ?? 28; + const padL = 140; + const padR = 50; + const padT = 24; + const h = padT + opts.bars.length * rowH + 12; + + if (opts.bars.length === 0) { + return svgEmpty(w, 60, 'No per-domain scorecard data yet'); + } + + const plotW = w - padL - padR; + const rows = opts.bars.map((bar, i) => { + const y = padT + i * rowH; + const barW = Math.max(0, Math.min(1, bar.accuracy)) * plotW; + const accPct = `${(bar.accuracy * 100).toFixed(0)}%`; + return ` + ${escapeXml(bar.label)} + + + ${accPct} · n=${bar.n}`; + }); + + return ` + + Per-domain accuracy${rows.join('')} +`; +} + +// ─── Abandoned threads card ───────────────────────────────────────── + +export interface AbandonedThread { + takeId: number; + pageSlug: string; + claim: string; + /** Months since last revisit. */ + monthsSilent: number; + conviction: number; + /** D30 (TD4) — revisit-now link target. Default: /admin/calibration/revisit/. */ + revisitHref?: string; +} + +export function renderAbandonedThreadsCard(threads: AbandonedThread[], width = 600): string { + const padT = 24; + const rowH = 44; + const h = padT + Math.max(threads.length, 1) * rowH + 12; + + if (threads.length === 0) { + return svgEmpty(width, 80, 'No abandoned high-conviction threads — clean slate'); + } + + const rows = threads.map((t, i) => { + const y = padT + i * rowH; + // Truncate claim for SVG layout — full claim shown in admin via tooltip + // (admin SPA renders the SVG, then layers HTML tooltips). Server side + // can't measure text width so we cap at 70 chars. + const claim = t.claim.length > 70 ? t.claim.slice(0, 70) + '…' : t.claim; + const meta = `conviction ${t.conviction.toFixed(2)} · ${t.monthsSilent} months silent`; + const href = t.revisitHref ?? `/admin/calibration/revisit/${t.takeId}`; + return ` + ${escapeXml(claim)} + ${escapeXml(meta)} + revisit now`; + }); + + return ` + + You committed to these and never revisited${rows.join('')} +`; +} + +// ─── Pattern statements card ──────────────────────────────────────── + +export interface PatternStatementsCardItem { + text: string; + /** D29 (TD3) — clickable drill-down. Default: /admin/calibration/pattern/. */ + drillHref?: string; +} + +export function renderPatternStatementsCard( + statements: PatternStatementsCardItem[], + width = 600, +): string { + const padT = 24; + const rowH = 36; + const h = padT + Math.max(statements.length, 1) * rowH + 12; + if (statements.length === 0) { + return svgEmpty(width, 60, 'No active patterns yet'); + } + const rows = statements.map((s, i) => { + const y = padT + i * rowH; + const txt = s.text.length > 90 ? s.text.slice(0, 90) + '…' : s.text; + const href = s.drillHref ?? `/admin/calibration/pattern/${i + 1}`; + return ` + ${escapeXml(txt)}`; + }); + return ` + + Active patterns (click to drill down)${rows.join('')} +`; +} + +// ─── helpers ──────────────────────────────────────────────────────── + +function svgEmpty(w: number, h: number, message: string): string { + return ` + + ${escapeXml(message)} +`; +} diff --git a/test/svg-renderer.test.ts b/test/svg-renderer.test.ts new file mode 100644 index 000000000..85dccce40 --- /dev/null +++ b/test/svg-renderer.test.ts @@ -0,0 +1,211 @@ +/** + * v0.36.0.0 (T15 / D23) — server-rendered SVG renderer tests. + * + * Pure functions, hermetic. No DOM, no JSDOM. Asserts structural + * properties of the emitted SVG markup. + */ + +import { describe, test, expect } from 'bun:test'; +import { + renderBrierTrend, + renderDomainBars, + renderAbandonedThreadsCard, + renderPatternStatementsCard, + escapeXml, +} from '../src/core/calibration/svg-renderer.ts'; + +describe('escapeXml', () => { + test('escapes the 5 mandatory entities', () => { + expect(escapeXml('')).toBe('<script>&"'</script>'); + }); +}); + +describe('renderBrierTrend', () => { + test('empty series → empty-state SVG with placeholder text', () => { + const out = renderBrierTrend({ series: [] }); + expect(out).toContain('No Brier-trend data yet'); + expect(out).toContain('=2 points', () => { + const out = renderBrierTrend({ + series: [ + { date: '2025-01-01', brier: 0.22 }, + { date: '2025-02-01', brier: 0.2 }, + { date: '2025-03-01', brier: 0.18 }, + ], + }); + expect(out).toContain(' { + const out = renderBrierTrend({ + series: [ + { date: '2025-01-01', brier: 0.9 }, + { date: '2025-02-01', brier: 0.1 }, + ], + }); + expect(out).toContain(' { + const out = renderBrierTrend({ series: [{ date: '2025-01-01', brier: 0.2 }] }); + expect(out).toContain('#0a0a0f'); // bg + expect(out).toContain('#3b82f6'); // accent + }); + + test('XSS-safe on attacker-controlled date strings', () => { + const out = renderBrierTrend({ + series: [ + { date: '', brier: 0.2 }, + { date: '2025-02-01', brier: 0.18 }, + ], + }); + expect(out).not.toContain('' }, + ]); + expect(out).not.toContain('