@tonyclaw/llm-inspector 1.9.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{index-DyKLPMPn.js → index-DIlrtHTN.js} +3 -3
- package/.output/public/assets/{main-Cu0oTDfX.js → main-BBNeb1MO.js} +1 -1
- package/.output/server/_ssr/{index-COIATcfa.mjs → index-DF6r7JcS.mjs} +13 -5
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-CwmgKXBJ.mjs → router-Bf2efXht.mjs} +64 -14
- package/.output/server/{_tanstack-start-manifest_v-C7hQOzvX.mjs → _tanstack-start-manifest_v-C_8VdUUj.mjs} +1 -1
- package/.output/server/index.mjs +23 -23
- package/package.json +1 -1
- package/src/components/proxy-viewer/StreamingChunkSequence.tsx +12 -3
- package/src/proxy/logIndex.ts +30 -9
- package/src/proxy/logger.ts +21 -7
- package/src/proxy/store.ts +9 -5
- package/src/routes/api/health.ts +4 -0
|
@@ -14,4 +14,4 @@ Error generating stack: `+l.message+`
|
|
|
14
14
|
`)}else{const p=o.indexOf(`
|
|
15
15
|
`);if(p>=0){const v=o.slice(0,p).trim();o=o.slice(p+1),v.length>0&&(h=JSON.parse(v),f=!0)}}}return(async()=>{try{for(;;){const{value:y,done:m}=await r.read();y&&(o+=y);const p=o.lastIndexOf(`
|
|
16
16
|
`);if(p>=0){const v=o.slice(0,p);o=o.slice(p+1);const S=v.split(`
|
|
17
|
-
`).filter(Boolean);for(const _ of S)try{u(JSON.parse(_))}catch(R){i?.(`Invalid JSON line: ${_}`,R)}}if(m)break}}catch(y){i?.("Stream processing error:",y)}})(),u(h)}async function dR({jsonStream:a,onMessage:u,onError:i}){const r=a.getReader(),{value:o,done:f}=await r.read();if(f||!o)throw new Error("Stream ended before first object");const h=JSON.parse(o);return(async()=>{try{for(;;){const{value:y,done:m}=await r.read();if(m)break;if(y)try{u(JSON.parse(y))}catch(p){i?.(`Invalid JSON: ${y}`,p)}}}catch(y){i?.("Stream processing error:",y)}})(),u(h)}function hR(a){const u="/_serverFn/"+a;return Object.assign((...o)=>{const f=vg()?.serverFns?.fetch;return rR(u,o,f??fetch)},{url:u,serverFnMeta:{id:a},[Zo]:!0})}const mR={key:"$TSS/serverfn",test:a=>typeof a!="function"||!(Zo in a)?!1:!!a[Zo],toSerializable:({serverFnMeta:a})=>({functionId:a.id}),fromSerializable:({functionId:a})=>hR(a)};var lp=cg();const Eg=0,Rg=1,Tg=2,ip=3;var up=Object.prototype.hasOwnProperty;function Ko(a,u){var i,r;if(a===u)return!0;if(a&&u&&(i=a.constructor)===u.constructor){if(i===Date)return a.getTime()===u.getTime();if(i===RegExp)return a.toString()===u.toString();if(i===Array){if((r=a.length)===u.length)for(;r--&&Ko(a[r],u[r]););return r===-1}if(!i||typeof a=="object"){r=0;for(i in a)if(up.call(a,i)&&++r&&!up.call(u,i)||!(i in u)||!Ko(a[i],u[i]))return!1;return Object.keys(u).length===r}}return a!==a&&u!==u}const Bn=new WeakMap,Hn=()=>{},ge=Hn(),Xs=Object,_t=a=>a===ge,sn=a=>typeof a=="function",Gn=(a,u)=>({...a,...u}),Ag=a=>sn(a.then),No={},As={},pf="undefined",lu=typeof window!=pf,Jo=typeof document!=pf,yR=lu&&"Deno"in window,pR=()=>lu&&typeof window.requestAnimationFrame!=pf,Og=(a,u)=>{const i=Bn.get(a);return[()=>!_t(u)&&a.get(u)||No,r=>{if(!_t(u)){const o=a.get(u);u in As||(As[u]=o),i[5](u,Gn(o,r),o||No)}},i[6],()=>!_t(u)&&u in As?As[u]:!_t(u)&&a.get(u)||No]};let ko=!0;const gR=()=>ko,[Fo,Po]=lu&&window.addEventListener?[window.addEventListener.bind(window),window.removeEventListener.bind(window)]:[Hn,Hn],vR=()=>{const a=Jo&&document.visibilityState;return _t(a)||a!=="hidden"},SR=a=>(Jo&&document.addEventListener("visibilitychange",a),Fo("focus",a),()=>{Jo&&document.removeEventListener("visibilitychange",a),Po("focus",a)}),bR=a=>{const u=()=>{ko=!0,a()},i=()=>{ko=!1};return Fo("online",u),Fo("offline",i),()=>{Po("online",u),Po("offline",i)}},_R={isOnline:gR,isVisible:vR},ER={initFocus:SR,initReconnect:bR},sp=!qn.useId,Fl=!lu||yR,RR=a=>pR()?window.requestAnimationFrame(a):setTimeout(a,1),Ds=Fl?$.useEffect:$.useLayoutEffect,Uo=typeof navigator<"u"&&navigator.connection,rp=!Fl&&Uo&&(["slow-2g","2g"].includes(Uo.effectiveType)||Uo.saveData),Os=new WeakMap,TR=a=>Xs.prototype.toString.call(a),Bo=(a,u)=>a===`[object ${u}]`;let AR=0;const Wo=a=>{const u=typeof a,i=TR(a),r=Bo(i,"Date"),o=Bo(i,"RegExp"),f=Bo(i,"Object");let h,y;if(Xs(a)===a&&!r&&!o){if(h=Os.get(a),h)return h;if(h=++AR+"~",Os.set(a,h),Array.isArray(a)){for(h="@",y=0;y<a.length;y++)h+=Wo(a[y])+",";Os.set(a,h)}if(f){h="#";const m=Xs.keys(a).sort();for(;!_t(y=m.pop());)_t(a[y])||(h+=y+":"+Wo(a[y])+",");Os.set(a,h)}}else h=r?a.toJSON():u=="symbol"?a.toString():u=="string"?JSON.stringify(a):""+a;return h},gf=a=>{if(sn(a))try{a=a()}catch{a=""}const u=a;return a=typeof a=="string"?a:(Array.isArray(a)?a.length:a)?Wo(a):"",[a,u]};let OR=0;const $o=()=>++OR;async function wg(...a){const[u,i,r,o]=a,f=Gn({populateCache:!0,throwOnError:!0},typeof o=="boolean"?{revalidate:o}:o||{});let h=f.populateCache;const y=f.rollbackOnError;let m=f.optimisticData;const p=_=>typeof y=="function"?y(_):y!==!1,v=f.throwOnError;if(sn(i)){const _=i,R=[],z=u.keys();for(const A of z)!/^\$(inf|sub)\$/.test(A)&&_(u.get(A)._k)&&R.push(A);return Promise.all(R.map(S))}return S(i);async function S(_){const[R]=gf(_);if(!R)return;const[z,A]=Og(u,R),[x,Y,B,Z]=Bn.get(u),H=()=>{const it=x[R];return(sn(f.revalidate)?f.revalidate(z().data,_):f.revalidate!==!1)&&(delete B[R],delete Z[R],it&&it[0])?it[0](Tg).then(()=>z().data):z().data};if(a.length<3)return H();let k=r,I,Q=!1;const X=$o();Y[R]=[X,0];const K=!_t(m),rt=z(),nt=rt.data,lt=rt._c,ht=_t(lt)?nt:lt;if(K&&(m=sn(m)?m(ht,nt):m,A({data:m,_c:ht})),sn(k))try{k=k(ht)}catch(it){I=it,Q=!0}if(k&&Ag(k))if(k=await k.catch(it=>{I=it,Q=!0}),X!==Y[R][0]){if(Q)throw I;return k}else Q&&K&&p(I)&&(h=!0,A({data:ht,_c:ge}));if(h&&!Q)if(sn(h)){const it=h(k,ht);A({data:it,error:ge,_c:ge})}else A({data:k,error:ge,_c:ge});if(Y[R][1]=$o(),Promise.resolve(H()).then(()=>{A({_c:ge})}),Q){if(v)throw I;return}return k}}const cp=(a,u)=>{for(const i in a)a[i][0]&&a[i][0](u)},Mg=(a,u)=>{if(!Bn.has(a)){const i=Gn(ER,u),r=Object.create(null),o=wg.bind(ge,a);let f=Hn;const h=Object.create(null),y=(v,S)=>{const _=h[v]||[];return h[v]=_,_.push(S),()=>_.splice(_.indexOf(S),1)},m=(v,S,_)=>{a.set(v,S);const R=h[v];if(R)for(const z of R)z(S,_)},p=()=>{if(!Bn.has(a)&&(Bn.set(a,[r,Object.create(null),Object.create(null),Object.create(null),o,m,y]),!Fl)){const v=i.initFocus(setTimeout.bind(ge,cp.bind(ge,r,Eg))),S=i.initReconnect(setTimeout.bind(ge,cp.bind(ge,r,Rg)));f=()=>{v&&v(),S&&S(),Bn.delete(a)}}};return p(),[a,o,p,f]}return[a,Bn.get(a)[4]]},wR=(a,u,i,r,o)=>{const f=i.errorRetryCount,h=o.retryCount,y=~~((Math.random()+.5)*(1<<(h<8?h:8)))*i.errorRetryInterval;!_t(f)&&h>f||setTimeout(r,y,o)},MR=Ko,[vf,xR]=Mg(new Map),xg=Gn({onLoadingSlow:Hn,onSuccess:Hn,onError:Hn,onErrorRetry:wR,onDiscarded:Hn,revalidateOnFocus:!0,revalidateOnReconnect:!0,revalidateIfStale:!0,shouldRetryOnError:!0,errorRetryInterval:rp?1e4:5e3,focusThrottleInterval:5*1e3,dedupingInterval:2*1e3,loadingTimeout:rp?5e3:3e3,compare:MR,isPaused:()=>!1,cache:vf,mutate:xR,fallback:{}},_R),zg=(a,u)=>{const i=Gn(a,u);if(u){const{use:r,fallback:o}=a,{use:f,fallback:h}=u;r&&f&&(i.use=r.concat(f)),o&&h&&(i.fallback=Gn(o,h))}return i},Io=$.createContext({}),zR=a=>{const{value:u}=a,i=$.useContext(Io),r=sn(u),o=$.useMemo(()=>r?u(i):u,[r,i,u]),f=$.useMemo(()=>r?o:zg(i,o),[r,i,o]),h=o&&o.provider,y=$.useRef(ge);h&&!y.current&&(y.current=Mg(h(f.cache||vf),o));const m=y.current;return m&&(f.cache=m[0],f.mutate=m[1]),Ds(()=>{if(m)return m[2]&&m[2](),m[3]},[]),$.createElement(Io.Provider,Gn(a,{value:f}))},CR="$inf$",Cg=lu&&window.__SWR_DEVTOOLS_USE__,DR=Cg?window.__SWR_DEVTOOLS_USE__:[],LR=()=>{Cg&&(window.__SWR_DEVTOOLS_REACT__=qn)},NR=a=>sn(a[1])?[a[0],a[1],a[2]||{}]:[a[0],null,(a[1]===null?a[2]:a[1])||{}],UR=()=>{const a=$.useContext(Io);return $.useMemo(()=>Gn(xg,a),[a])},BR=a=>(u,i,r)=>a(u,i&&((...f)=>{const[h]=gf(u),[,,,y]=Bn.get(vf);if(h.startsWith(CR))return i(...f);const m=y[h];return _t(m)?i(...f):(delete y[h],m)}),r),jR=DR.concat(BR),HR=a=>function(...i){const r=UR(),[o,f,h]=NR(i),y=zg(r,h);let m=a;const{use:p}=y,v=(p||[]).concat(jR);for(let S=v.length;S--;)m=v[S](m);return m(o,f||y.fetcher||null,y)},qR=(a,u,i)=>{const r=u[a]||(u[a]=[]);return r.push(i),()=>{const o=r.indexOf(i);o>=0&&(r[o]=r[r.length-1],r.pop())}};LR();const jo=qn.use||(a=>{switch(a.status){case"pending":throw a;case"fulfilled":return a.value;case"rejected":throw a.reason;default:throw a.status="pending",a.then(u=>{a.status="fulfilled",a.value=u},u=>{a.status="rejected",a.reason=u}),a}}),Ho={dedupe:!0},op=Promise.resolve(ge),VR=()=>Hn,YR=(a,u,i)=>{const{cache:r,compare:o,suspense:f,fallbackData:h,revalidateOnMount:y,revalidateIfStale:m,refreshInterval:p,refreshWhenHidden:v,refreshWhenOffline:S,keepPreviousData:_,strictServerPrefetchWarning:R}=i,[z,A,x,Y]=Bn.get(r),[B,Z]=gf(a),H=$.useRef(!1),k=$.useRef(!1),I=$.useRef(B),Q=$.useRef(u),X=$.useRef(i),K=()=>X.current,rt=()=>K().isVisible()&&K().isOnline(),[nt,lt,ht,it]=Og(r,B),jt=$.useRef({}).current,N=_t(h)?_t(i.fallback)?ge:i.fallback[B]:h,F=(Et,Lt)=>{for(const At in jt){const qt=At;if(qt==="data"){if(!o(Et[qt],Lt[qt])&&(!_t(Et[qt])||!o(ot,Lt[qt])))return!1}else if(Lt[qt]!==Et[qt])return!1}return!0},ut=!H.current,Tt=$.useMemo(()=>{const Et=nt(),Lt=it(),At=Jt=>{const Vt=Gn(Jt);return delete Vt._k,(()=>{if(!B||!u||K().isPaused())return!1;if(ut&&!_t(y))return y;const xt=_t(N)?Vt.data:N;return _t(xt)||m})()?{isValidating:!0,isLoading:!0,...Vt}:Vt},qt=At(Et),ve=Et===Lt?qt:At(Lt);let oe=qt;return[()=>{const Jt=At(nt());return F(Jt,oe)?(oe.data=Jt.data,oe.isLoading=Jt.isLoading,oe.isValidating=Jt.isValidating,oe.error=Jt.error,oe):(oe=Jt,Jt)},()=>ve]},[r,B]),pt=lp.useSyncExternalStore($.useCallback(Et=>ht(B,(Lt,At)=>{F(At,Lt)||Et()}),[r,B]),Tt[0],Tt[1]),w=z[B]&&z[B].length>0,q=pt.data,J=_t(q)?N&&Ag(N)?jo(N):N:q,P=pt.error,ct=$.useRef(J),ot=_?_t(q)?_t(ct.current)?J:ct.current:q:J,ft=B&&_t(J),Xt=$.useRef(null);!Fl&&lp.useSyncExternalStore(VR,()=>(Xt.current=!1,Xt),()=>(Xt.current=!0,Xt));const Ht=Xt.current;R&&Ht&&!f&&ft&&console.warn(`Missing pre-initiated data for serialized key "${B}" during server-side rendering. Data fetching should be initiated on the server and provided to SWR via fallback data. You can set "strictServerPrefetchWarning: false" to disable this warning.`);const De=!B||!u||K().isPaused()||w&&!_t(P)?!1:ut&&!_t(y)?y:f?_t(J)?!1:m:_t(J)||m,Xe=ut&&De,Qn=_t(pt.isValidating)?Xe:pt.isValidating,Ta=_t(pt.isLoading)?Xe:pt.isLoading,_e=$.useCallback(async Et=>{const Lt=Q.current;if(!B||!Lt||k.current||K().isPaused())return!1;let At,qt,ve=!0;const oe=Et||{},Jt=!x[B]||!oe.dedupe,Vt=()=>sp?!k.current&&B===I.current&&H.current:B===I.current,yn={isValidating:!1,isLoading:!1},xt=()=>{lt(yn)},$t=()=>{const fe=x[B];fe&&fe[1]===qt&&delete x[B]},ae={isValidating:!0};_t(nt().data)&&(ae.isLoading=!0);try{if(Jt&&(lt(ae),i.loadingTimeout&&_t(nt().data)&&setTimeout(()=>{ve&&Vt()&&K().onLoadingSlow(B,i)},i.loadingTimeout),x[B]=[Lt(Z),$o()]),[At,qt]=x[B],At=await At,Jt&&setTimeout($t,i.dedupingInterval),!x[B]||x[B][1]!==qt)return Jt&&Vt()&&K().onDiscarded(B),!1;yn.error=ge;const fe=A[B];if(!_t(fe)&&(qt<=fe[0]||qt<=fe[1]||fe[1]===0))return xt(),Jt&&Vt()&&K().onDiscarded(B),!1;const Qe=nt().data;yn.data=o(Qe,At)?Qe:At,Jt&&Vt()&&K().onSuccess(At,B,i)}catch(fe){$t();const Qe=K(),{shouldRetryOnError:Wl}=Qe;Qe.isPaused()||(yn.error=fe,Jt&&Vt()&&(Qe.onError(fe,B,Qe),(Wl===!0||sn(Wl)&&Wl(fe))&&(!K().revalidateOnFocus||!K().revalidateOnReconnect||rt())&&Qe.onErrorRetry(fe,B,Qe,$s=>{const pn=z[B];pn&&pn[0]&&pn[0](ip,$s)},{retryCount:(oe.retryCount||0)+1,dedupe:!0})))}return ve=!1,xt(),!0},[B,r]),mn=$.useCallback((...Et)=>wg(r,I.current,...Et),[]);if(Ds(()=>{Q.current=u,X.current=i,_t(q)||(ct.current=q)}),Ds(()=>{if(!B)return;const Et=_e.bind(ge,Ho);let Lt=0;K().revalidateOnFocus&&(Lt=Date.now()+K().focusThrottleInterval);const qt=qR(B,z,(ve,oe={})=>{if(ve==Eg){const Jt=Date.now();K().revalidateOnFocus&&Jt>Lt&&rt()&&(Lt=Jt+K().focusThrottleInterval,Et())}else if(ve==Rg)K().revalidateOnReconnect&&rt()&&Et();else{if(ve==Tg)return _e();if(ve==ip)return _e(oe)}});return k.current=!1,I.current=B,H.current=!0,lt({_k:Z}),De&&(x[B]||(_t(J)||Fl?Et():RR(Et))),()=>{k.current=!0,qt()}},[B]),Ds(()=>{let Et;function Lt(){const qt=sn(p)?p(nt().data):p;qt&&Et!==-1&&(Et=setTimeout(At,qt))}function At(){!nt().error&&(v||K().isVisible())&&(S||K().isOnline())?_e(Ho).then(Lt):Lt()}return Lt(),()=>{Et&&(clearTimeout(Et),Et=-1)}},[p,v,S,B]),$.useDebugValue(ot),f){if(!sp&&Fl&&ft)throw new Error("Fallback data is required when using Suspense in SSR.");ft&&(Q.current=u,X.current=i,k.current=!1);const Et=Y[B],Lt=!_t(Et)&&ft?mn(Et):op;if(jo(Lt),!_t(P)&&ft)throw P;const At=ft?_e(Ho):op;!_t(ot)&&ft&&(At.status="fulfilled",At.value=!0),jo(At)}return{mutate:mn,get data(){return jt.data=!0,ot},get error(){return jt.error=!0,P},get isValidating(){return jt.isValidating=!0,Qn},get isLoading(){return jt.isLoading=!0,Ta}}},GR=Xs.defineProperty(zR,"defaultValue",{value:xg}),oT=HR(YR),XR="/assets/index-DdJSLfxK.css",Dg=DE({head:()=>({meta:[{charSet:"utf-8"},{name:"viewport",content:"width=device-width, initial-scale=1"},{title:"llm-inspector"}],links:[{rel:"stylesheet",href:XR}]}),component:QR});function QR(){return W.jsx(ZR,{children:W.jsx(yg,{})})}function ZR({children:a}){return W.jsxs("html",{lang:"en",className:"dark",children:[W.jsx("head",{children:W.jsx(kE,{})}),W.jsxs("body",{children:[W.jsx(GR,{value:{revalidateOnFocus:!1,revalidateIfStale:!1},children:a}),W.jsx(FE,{})]})]})}const KR="modulepreload",JR=function(a){return"/"+a},fp={},kR=function(u,i,r){let o=Promise.resolve();if(i&&i.length>0){let m=function(p){return Promise.all(p.map(v=>Promise.resolve(v).then(S=>({status:"fulfilled",value:S}),S=>({status:"rejected",reason:S}))))};document.getElementsByTagName("link");const h=document.querySelector("meta[property=csp-nonce]"),y=h?.nonce||h?.getAttribute("nonce");o=m(i.map(p=>{if(p=JR(p),p in fp)return;fp[p]=!0;const v=p.endsWith(".css"),S=v?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${p}"]${S}`))return;const _=document.createElement("link");if(_.rel=v?"stylesheet":KR,v||(_.as="script"),_.crossOrigin="",_.href=p,y&&_.setAttribute("nonce",y),document.head.appendChild(_),v)return new Promise((R,z)=>{_.addEventListener("load",R),_.addEventListener("error",()=>z(new Error(`Unable to preload CSS for ${p}`)))})}))}function f(h){const y=new Event("vite:preloadError",{cancelable:!0});if(y.payload=h,window.dispatchEvent(y),!y.defaultPrevented)throw h}return o.then(h=>{for(const y of h||[])y.status==="rejected"&&f(y.reason);return u().catch(f)})},FR=()=>kR(()=>import("./index-DyKLPMPn.js"),[]),PR=Qo("/")({component:LE(FR,"component")}),WR=PR.update({id:"/",path:"/",getParentRoute:()=>Dg}),$R={IndexRoute:WR},IR=Dg._addFileChildren($R);function tT(){return YE({routeTree:IR,scrollRestoration:!1})}async function eT(){const a=await tT();let u;return u=[],window.__TSS_START_OPTIONS__={serializationAdapters:u},u.push(mR),a.options.serializationAdapters&&u.push(...a.options.serializationAdapters),a.update({basepath:"",serializationAdapters:u}),a.state.matches.length||await WE(a),a}async function nT(){const a=await eT();return window.$_TSR?.h(),a}let qo;function aT(){return qo||(qo=nT()),W.jsx(rE,{promise:qo,children:a=>W.jsx(QE,{router:a})})}$.startTransition(()=>{iS.hydrateRoot(document,W.jsx($.StrictMode,{children:W.jsx(aT,{})}))});export{qn as R,fg as a,I0 as b,lT as c,rT as d,dp as g,W as j,$ as r,oT as u};
|
|
17
|
+
`).filter(Boolean);for(const _ of S)try{u(JSON.parse(_))}catch(R){i?.(`Invalid JSON line: ${_}`,R)}}if(m)break}}catch(y){i?.("Stream processing error:",y)}})(),u(h)}async function dR({jsonStream:a,onMessage:u,onError:i}){const r=a.getReader(),{value:o,done:f}=await r.read();if(f||!o)throw new Error("Stream ended before first object");const h=JSON.parse(o);return(async()=>{try{for(;;){const{value:y,done:m}=await r.read();if(m)break;if(y)try{u(JSON.parse(y))}catch(p){i?.(`Invalid JSON: ${y}`,p)}}}catch(y){i?.("Stream processing error:",y)}})(),u(h)}function hR(a){const u="/_serverFn/"+a;return Object.assign((...o)=>{const f=vg()?.serverFns?.fetch;return rR(u,o,f??fetch)},{url:u,serverFnMeta:{id:a},[Zo]:!0})}const mR={key:"$TSS/serverfn",test:a=>typeof a!="function"||!(Zo in a)?!1:!!a[Zo],toSerializable:({serverFnMeta:a})=>({functionId:a.id}),fromSerializable:({functionId:a})=>hR(a)};var lp=cg();const Eg=0,Rg=1,Tg=2,ip=3;var up=Object.prototype.hasOwnProperty;function Ko(a,u){var i,r;if(a===u)return!0;if(a&&u&&(i=a.constructor)===u.constructor){if(i===Date)return a.getTime()===u.getTime();if(i===RegExp)return a.toString()===u.toString();if(i===Array){if((r=a.length)===u.length)for(;r--&&Ko(a[r],u[r]););return r===-1}if(!i||typeof a=="object"){r=0;for(i in a)if(up.call(a,i)&&++r&&!up.call(u,i)||!(i in u)||!Ko(a[i],u[i]))return!1;return Object.keys(u).length===r}}return a!==a&&u!==u}const Bn=new WeakMap,Hn=()=>{},ge=Hn(),Xs=Object,_t=a=>a===ge,sn=a=>typeof a=="function",Gn=(a,u)=>({...a,...u}),Ag=a=>sn(a.then),No={},As={},pf="undefined",lu=typeof window!=pf,Jo=typeof document!=pf,yR=lu&&"Deno"in window,pR=()=>lu&&typeof window.requestAnimationFrame!=pf,Og=(a,u)=>{const i=Bn.get(a);return[()=>!_t(u)&&a.get(u)||No,r=>{if(!_t(u)){const o=a.get(u);u in As||(As[u]=o),i[5](u,Gn(o,r),o||No)}},i[6],()=>!_t(u)&&u in As?As[u]:!_t(u)&&a.get(u)||No]};let ko=!0;const gR=()=>ko,[Fo,Po]=lu&&window.addEventListener?[window.addEventListener.bind(window),window.removeEventListener.bind(window)]:[Hn,Hn],vR=()=>{const a=Jo&&document.visibilityState;return _t(a)||a!=="hidden"},SR=a=>(Jo&&document.addEventListener("visibilitychange",a),Fo("focus",a),()=>{Jo&&document.removeEventListener("visibilitychange",a),Po("focus",a)}),bR=a=>{const u=()=>{ko=!0,a()},i=()=>{ko=!1};return Fo("online",u),Fo("offline",i),()=>{Po("online",u),Po("offline",i)}},_R={isOnline:gR,isVisible:vR},ER={initFocus:SR,initReconnect:bR},sp=!qn.useId,Fl=!lu||yR,RR=a=>pR()?window.requestAnimationFrame(a):setTimeout(a,1),Ds=Fl?$.useEffect:$.useLayoutEffect,Uo=typeof navigator<"u"&&navigator.connection,rp=!Fl&&Uo&&(["slow-2g","2g"].includes(Uo.effectiveType)||Uo.saveData),Os=new WeakMap,TR=a=>Xs.prototype.toString.call(a),Bo=(a,u)=>a===`[object ${u}]`;let AR=0;const Wo=a=>{const u=typeof a,i=TR(a),r=Bo(i,"Date"),o=Bo(i,"RegExp"),f=Bo(i,"Object");let h,y;if(Xs(a)===a&&!r&&!o){if(h=Os.get(a),h)return h;if(h=++AR+"~",Os.set(a,h),Array.isArray(a)){for(h="@",y=0;y<a.length;y++)h+=Wo(a[y])+",";Os.set(a,h)}if(f){h="#";const m=Xs.keys(a).sort();for(;!_t(y=m.pop());)_t(a[y])||(h+=y+":"+Wo(a[y])+",");Os.set(a,h)}}else h=r?a.toJSON():u=="symbol"?a.toString():u=="string"?JSON.stringify(a):""+a;return h},gf=a=>{if(sn(a))try{a=a()}catch{a=""}const u=a;return a=typeof a=="string"?a:(Array.isArray(a)?a.length:a)?Wo(a):"",[a,u]};let OR=0;const $o=()=>++OR;async function wg(...a){const[u,i,r,o]=a,f=Gn({populateCache:!0,throwOnError:!0},typeof o=="boolean"?{revalidate:o}:o||{});let h=f.populateCache;const y=f.rollbackOnError;let m=f.optimisticData;const p=_=>typeof y=="function"?y(_):y!==!1,v=f.throwOnError;if(sn(i)){const _=i,R=[],z=u.keys();for(const A of z)!/^\$(inf|sub)\$/.test(A)&&_(u.get(A)._k)&&R.push(A);return Promise.all(R.map(S))}return S(i);async function S(_){const[R]=gf(_);if(!R)return;const[z,A]=Og(u,R),[x,Y,B,Z]=Bn.get(u),H=()=>{const it=x[R];return(sn(f.revalidate)?f.revalidate(z().data,_):f.revalidate!==!1)&&(delete B[R],delete Z[R],it&&it[0])?it[0](Tg).then(()=>z().data):z().data};if(a.length<3)return H();let k=r,I,Q=!1;const X=$o();Y[R]=[X,0];const K=!_t(m),rt=z(),nt=rt.data,lt=rt._c,ht=_t(lt)?nt:lt;if(K&&(m=sn(m)?m(ht,nt):m,A({data:m,_c:ht})),sn(k))try{k=k(ht)}catch(it){I=it,Q=!0}if(k&&Ag(k))if(k=await k.catch(it=>{I=it,Q=!0}),X!==Y[R][0]){if(Q)throw I;return k}else Q&&K&&p(I)&&(h=!0,A({data:ht,_c:ge}));if(h&&!Q)if(sn(h)){const it=h(k,ht);A({data:it,error:ge,_c:ge})}else A({data:k,error:ge,_c:ge});if(Y[R][1]=$o(),Promise.resolve(H()).then(()=>{A({_c:ge})}),Q){if(v)throw I;return}return k}}const cp=(a,u)=>{for(const i in a)a[i][0]&&a[i][0](u)},Mg=(a,u)=>{if(!Bn.has(a)){const i=Gn(ER,u),r=Object.create(null),o=wg.bind(ge,a);let f=Hn;const h=Object.create(null),y=(v,S)=>{const _=h[v]||[];return h[v]=_,_.push(S),()=>_.splice(_.indexOf(S),1)},m=(v,S,_)=>{a.set(v,S);const R=h[v];if(R)for(const z of R)z(S,_)},p=()=>{if(!Bn.has(a)&&(Bn.set(a,[r,Object.create(null),Object.create(null),Object.create(null),o,m,y]),!Fl)){const v=i.initFocus(setTimeout.bind(ge,cp.bind(ge,r,Eg))),S=i.initReconnect(setTimeout.bind(ge,cp.bind(ge,r,Rg)));f=()=>{v&&v(),S&&S(),Bn.delete(a)}}};return p(),[a,o,p,f]}return[a,Bn.get(a)[4]]},wR=(a,u,i,r,o)=>{const f=i.errorRetryCount,h=o.retryCount,y=~~((Math.random()+.5)*(1<<(h<8?h:8)))*i.errorRetryInterval;!_t(f)&&h>f||setTimeout(r,y,o)},MR=Ko,[vf,xR]=Mg(new Map),xg=Gn({onLoadingSlow:Hn,onSuccess:Hn,onError:Hn,onErrorRetry:wR,onDiscarded:Hn,revalidateOnFocus:!0,revalidateOnReconnect:!0,revalidateIfStale:!0,shouldRetryOnError:!0,errorRetryInterval:rp?1e4:5e3,focusThrottleInterval:5*1e3,dedupingInterval:2*1e3,loadingTimeout:rp?5e3:3e3,compare:MR,isPaused:()=>!1,cache:vf,mutate:xR,fallback:{}},_R),zg=(a,u)=>{const i=Gn(a,u);if(u){const{use:r,fallback:o}=a,{use:f,fallback:h}=u;r&&f&&(i.use=r.concat(f)),o&&h&&(i.fallback=Gn(o,h))}return i},Io=$.createContext({}),zR=a=>{const{value:u}=a,i=$.useContext(Io),r=sn(u),o=$.useMemo(()=>r?u(i):u,[r,i,u]),f=$.useMemo(()=>r?o:zg(i,o),[r,i,o]),h=o&&o.provider,y=$.useRef(ge);h&&!y.current&&(y.current=Mg(h(f.cache||vf),o));const m=y.current;return m&&(f.cache=m[0],f.mutate=m[1]),Ds(()=>{if(m)return m[2]&&m[2](),m[3]},[]),$.createElement(Io.Provider,Gn(a,{value:f}))},CR="$inf$",Cg=lu&&window.__SWR_DEVTOOLS_USE__,DR=Cg?window.__SWR_DEVTOOLS_USE__:[],LR=()=>{Cg&&(window.__SWR_DEVTOOLS_REACT__=qn)},NR=a=>sn(a[1])?[a[0],a[1],a[2]||{}]:[a[0],null,(a[1]===null?a[2]:a[1])||{}],UR=()=>{const a=$.useContext(Io);return $.useMemo(()=>Gn(xg,a),[a])},BR=a=>(u,i,r)=>a(u,i&&((...f)=>{const[h]=gf(u),[,,,y]=Bn.get(vf);if(h.startsWith(CR))return i(...f);const m=y[h];return _t(m)?i(...f):(delete y[h],m)}),r),jR=DR.concat(BR),HR=a=>function(...i){const r=UR(),[o,f,h]=NR(i),y=zg(r,h);let m=a;const{use:p}=y,v=(p||[]).concat(jR);for(let S=v.length;S--;)m=v[S](m);return m(o,f||y.fetcher||null,y)},qR=(a,u,i)=>{const r=u[a]||(u[a]=[]);return r.push(i),()=>{const o=r.indexOf(i);o>=0&&(r[o]=r[r.length-1],r.pop())}};LR();const jo=qn.use||(a=>{switch(a.status){case"pending":throw a;case"fulfilled":return a.value;case"rejected":throw a.reason;default:throw a.status="pending",a.then(u=>{a.status="fulfilled",a.value=u},u=>{a.status="rejected",a.reason=u}),a}}),Ho={dedupe:!0},op=Promise.resolve(ge),VR=()=>Hn,YR=(a,u,i)=>{const{cache:r,compare:o,suspense:f,fallbackData:h,revalidateOnMount:y,revalidateIfStale:m,refreshInterval:p,refreshWhenHidden:v,refreshWhenOffline:S,keepPreviousData:_,strictServerPrefetchWarning:R}=i,[z,A,x,Y]=Bn.get(r),[B,Z]=gf(a),H=$.useRef(!1),k=$.useRef(!1),I=$.useRef(B),Q=$.useRef(u),X=$.useRef(i),K=()=>X.current,rt=()=>K().isVisible()&&K().isOnline(),[nt,lt,ht,it]=Og(r,B),jt=$.useRef({}).current,N=_t(h)?_t(i.fallback)?ge:i.fallback[B]:h,F=(Et,Lt)=>{for(const At in jt){const qt=At;if(qt==="data"){if(!o(Et[qt],Lt[qt])&&(!_t(Et[qt])||!o(ot,Lt[qt])))return!1}else if(Lt[qt]!==Et[qt])return!1}return!0},ut=!H.current,Tt=$.useMemo(()=>{const Et=nt(),Lt=it(),At=Jt=>{const Vt=Gn(Jt);return delete Vt._k,(()=>{if(!B||!u||K().isPaused())return!1;if(ut&&!_t(y))return y;const xt=_t(N)?Vt.data:N;return _t(xt)||m})()?{isValidating:!0,isLoading:!0,...Vt}:Vt},qt=At(Et),ve=Et===Lt?qt:At(Lt);let oe=qt;return[()=>{const Jt=At(nt());return F(Jt,oe)?(oe.data=Jt.data,oe.isLoading=Jt.isLoading,oe.isValidating=Jt.isValidating,oe.error=Jt.error,oe):(oe=Jt,Jt)},()=>ve]},[r,B]),pt=lp.useSyncExternalStore($.useCallback(Et=>ht(B,(Lt,At)=>{F(At,Lt)||Et()}),[r,B]),Tt[0],Tt[1]),w=z[B]&&z[B].length>0,q=pt.data,J=_t(q)?N&&Ag(N)?jo(N):N:q,P=pt.error,ct=$.useRef(J),ot=_?_t(q)?_t(ct.current)?J:ct.current:q:J,ft=B&&_t(J),Xt=$.useRef(null);!Fl&&lp.useSyncExternalStore(VR,()=>(Xt.current=!1,Xt),()=>(Xt.current=!0,Xt));const Ht=Xt.current;R&&Ht&&!f&&ft&&console.warn(`Missing pre-initiated data for serialized key "${B}" during server-side rendering. Data fetching should be initiated on the server and provided to SWR via fallback data. You can set "strictServerPrefetchWarning: false" to disable this warning.`);const De=!B||!u||K().isPaused()||w&&!_t(P)?!1:ut&&!_t(y)?y:f?_t(J)?!1:m:_t(J)||m,Xe=ut&&De,Qn=_t(pt.isValidating)?Xe:pt.isValidating,Ta=_t(pt.isLoading)?Xe:pt.isLoading,_e=$.useCallback(async Et=>{const Lt=Q.current;if(!B||!Lt||k.current||K().isPaused())return!1;let At,qt,ve=!0;const oe=Et||{},Jt=!x[B]||!oe.dedupe,Vt=()=>sp?!k.current&&B===I.current&&H.current:B===I.current,yn={isValidating:!1,isLoading:!1},xt=()=>{lt(yn)},$t=()=>{const fe=x[B];fe&&fe[1]===qt&&delete x[B]},ae={isValidating:!0};_t(nt().data)&&(ae.isLoading=!0);try{if(Jt&&(lt(ae),i.loadingTimeout&&_t(nt().data)&&setTimeout(()=>{ve&&Vt()&&K().onLoadingSlow(B,i)},i.loadingTimeout),x[B]=[Lt(Z),$o()]),[At,qt]=x[B],At=await At,Jt&&setTimeout($t,i.dedupingInterval),!x[B]||x[B][1]!==qt)return Jt&&Vt()&&K().onDiscarded(B),!1;yn.error=ge;const fe=A[B];if(!_t(fe)&&(qt<=fe[0]||qt<=fe[1]||fe[1]===0))return xt(),Jt&&Vt()&&K().onDiscarded(B),!1;const Qe=nt().data;yn.data=o(Qe,At)?Qe:At,Jt&&Vt()&&K().onSuccess(At,B,i)}catch(fe){$t();const Qe=K(),{shouldRetryOnError:Wl}=Qe;Qe.isPaused()||(yn.error=fe,Jt&&Vt()&&(Qe.onError(fe,B,Qe),(Wl===!0||sn(Wl)&&Wl(fe))&&(!K().revalidateOnFocus||!K().revalidateOnReconnect||rt())&&Qe.onErrorRetry(fe,B,Qe,$s=>{const pn=z[B];pn&&pn[0]&&pn[0](ip,$s)},{retryCount:(oe.retryCount||0)+1,dedupe:!0})))}return ve=!1,xt(),!0},[B,r]),mn=$.useCallback((...Et)=>wg(r,I.current,...Et),[]);if(Ds(()=>{Q.current=u,X.current=i,_t(q)||(ct.current=q)}),Ds(()=>{if(!B)return;const Et=_e.bind(ge,Ho);let Lt=0;K().revalidateOnFocus&&(Lt=Date.now()+K().focusThrottleInterval);const qt=qR(B,z,(ve,oe={})=>{if(ve==Eg){const Jt=Date.now();K().revalidateOnFocus&&Jt>Lt&&rt()&&(Lt=Jt+K().focusThrottleInterval,Et())}else if(ve==Rg)K().revalidateOnReconnect&&rt()&&Et();else{if(ve==Tg)return _e();if(ve==ip)return _e(oe)}});return k.current=!1,I.current=B,H.current=!0,lt({_k:Z}),De&&(x[B]||(_t(J)||Fl?Et():RR(Et))),()=>{k.current=!0,qt()}},[B]),Ds(()=>{let Et;function Lt(){const qt=sn(p)?p(nt().data):p;qt&&Et!==-1&&(Et=setTimeout(At,qt))}function At(){!nt().error&&(v||K().isVisible())&&(S||K().isOnline())?_e(Ho).then(Lt):Lt()}return Lt(),()=>{Et&&(clearTimeout(Et),Et=-1)}},[p,v,S,B]),$.useDebugValue(ot),f){if(!sp&&Fl&&ft)throw new Error("Fallback data is required when using Suspense in SSR.");ft&&(Q.current=u,X.current=i,k.current=!1);const Et=Y[B],Lt=!_t(Et)&&ft?mn(Et):op;if(jo(Lt),!_t(P)&&ft)throw P;const At=ft?_e(Ho):op;!_t(ot)&&ft&&(At.status="fulfilled",At.value=!0),jo(At)}return{mutate:mn,get data(){return jt.data=!0,ot},get error(){return jt.error=!0,P},get isValidating(){return jt.isValidating=!0,Qn},get isLoading(){return jt.isLoading=!0,Ta}}},GR=Xs.defineProperty(zR,"defaultValue",{value:xg}),oT=HR(YR),XR="/assets/index-DdJSLfxK.css",Dg=DE({head:()=>({meta:[{charSet:"utf-8"},{name:"viewport",content:"width=device-width, initial-scale=1"},{title:"llm-inspector"}],links:[{rel:"stylesheet",href:XR}]}),component:QR});function QR(){return W.jsx(ZR,{children:W.jsx(yg,{})})}function ZR({children:a}){return W.jsxs("html",{lang:"en",className:"dark",children:[W.jsx("head",{children:W.jsx(kE,{})}),W.jsxs("body",{children:[W.jsx(GR,{value:{revalidateOnFocus:!1,revalidateIfStale:!1},children:a}),W.jsx(FE,{})]})]})}const KR="modulepreload",JR=function(a){return"/"+a},fp={},kR=function(u,i,r){let o=Promise.resolve();if(i&&i.length>0){let m=function(p){return Promise.all(p.map(v=>Promise.resolve(v).then(S=>({status:"fulfilled",value:S}),S=>({status:"rejected",reason:S}))))};document.getElementsByTagName("link");const h=document.querySelector("meta[property=csp-nonce]"),y=h?.nonce||h?.getAttribute("nonce");o=m(i.map(p=>{if(p=JR(p),p in fp)return;fp[p]=!0;const v=p.endsWith(".css"),S=v?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${p}"]${S}`))return;const _=document.createElement("link");if(_.rel=v?"stylesheet":KR,v||(_.as="script"),_.crossOrigin="",_.href=p,y&&_.setAttribute("nonce",y),document.head.appendChild(_),v)return new Promise((R,z)=>{_.addEventListener("load",R),_.addEventListener("error",()=>z(new Error(`Unable to preload CSS for ${p}`)))})}))}function f(h){const y=new Event("vite:preloadError",{cancelable:!0});if(y.payload=h,window.dispatchEvent(y),!y.defaultPrevented)throw h}return o.then(h=>{for(const y of h||[])y.status==="rejected"&&f(y.reason);return u().catch(f)})},FR=()=>kR(()=>import("./index-DIlrtHTN.js"),[]),PR=Qo("/")({component:LE(FR,"component")}),WR=PR.update({id:"/",path:"/",getParentRoute:()=>Dg}),$R={IndexRoute:WR},IR=Dg._addFileChildren($R);function tT(){return YE({routeTree:IR,scrollRestoration:!1})}async function eT(){const a=await tT();let u;return u=[],window.__TSS_START_OPTIONS__={serializationAdapters:u},u.push(mR),a.options.serializationAdapters&&u.push(...a.options.serializationAdapters),a.update({basepath:"",serializationAdapters:u}),a.state.matches.length||await WE(a),a}async function nT(){const a=await eT();return window.$_TSR?.h(),a}let qo;function aT(){return qo||(qo=nT()),W.jsx(rE,{promise:qo,children:a=>W.jsx(QE,{router:a})})}$.startTransition(()=>{iS.hydrateRoot(document,W.jsx($.StrictMode,{children:W.jsx(aT,{})}))});export{qn as R,fg as a,I0 as b,lT as c,rT as d,dp as g,W as j,$ as r,oT as u};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
-
import { C as CapturedLogSchema, a as parseRequest, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-
|
|
2
|
+
import { C as CapturedLogSchema, a as parseRequest, p as parseOpenAIResponse, I as InspectorResponseSchema } from "./router-Bf2efXht.mjs";
|
|
3
3
|
import { u as useVirtualizer } from "../_libs/tanstack__react-virtual.mjs";
|
|
4
4
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
@@ -199,7 +199,7 @@ async function exportLogsAsZip(logs) {
|
|
|
199
199
|
document.body.removeChild(anchor);
|
|
200
200
|
URL.revokeObjectURL(url);
|
|
201
201
|
}
|
|
202
|
-
const version = "1.9.
|
|
202
|
+
const version = "1.9.2";
|
|
203
203
|
const packageJson = {
|
|
204
204
|
version
|
|
205
205
|
};
|
|
@@ -1726,6 +1726,7 @@ function StreamingChunkSequence({
|
|
|
1726
1726
|
const [expandedIndices, setExpandedIndices] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
1727
1727
|
reactExports.useEffect(() => {
|
|
1728
1728
|
if (!containerExpanded || chunkState.status !== "idle") return;
|
|
1729
|
+
let cancelled = false;
|
|
1729
1730
|
setChunkState({ status: "loading" });
|
|
1730
1731
|
fetch(`/api/logs/${logId}/chunks`).then((res) => {
|
|
1731
1732
|
if (!res.ok) {
|
|
@@ -1733,11 +1734,18 @@ function StreamingChunkSequence({
|
|
|
1733
1734
|
}
|
|
1734
1735
|
return res.json();
|
|
1735
1736
|
}).then((data) => {
|
|
1736
|
-
|
|
1737
|
+
if (!cancelled) {
|
|
1738
|
+
setChunkState({ status: "success", chunks: data.chunks });
|
|
1739
|
+
}
|
|
1737
1740
|
}).catch(() => {
|
|
1738
|
-
|
|
1741
|
+
if (!cancelled) {
|
|
1742
|
+
setChunkState({ status: "error", message: "Chunk data unavailable" });
|
|
1743
|
+
}
|
|
1739
1744
|
});
|
|
1740
|
-
|
|
1745
|
+
return () => {
|
|
1746
|
+
cancelled = true;
|
|
1747
|
+
};
|
|
1748
|
+
}, [containerExpanded, logId]);
|
|
1741
1749
|
const groups = reactExports.useMemo(() => {
|
|
1742
1750
|
if (chunkState.status !== "success") return [];
|
|
1743
1751
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -197,7 +197,7 @@ function getResponse() {
|
|
|
197
197
|
return event.res;
|
|
198
198
|
}
|
|
199
199
|
async function getStartManifest(matchedRoutes) {
|
|
200
|
-
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-
|
|
200
|
+
const { tsrStartManifest } = await import("../_tanstack-start-manifest_v-C_8VdUUj.mjs");
|
|
201
201
|
const startManifest = tsrStartManifest();
|
|
202
202
|
const rootRoute = startManifest.routes[rootRouteId] = startManifest.routes[rootRouteId] || {};
|
|
203
203
|
rootRoute.assets = rootRoute.assets || [];
|
|
@@ -766,7 +766,7 @@ let entriesPromise;
|
|
|
766
766
|
let baseManifestPromise;
|
|
767
767
|
let cachedFinalManifestPromise;
|
|
768
768
|
async function loadEntries() {
|
|
769
|
-
const routerEntry = await import("./router-
|
|
769
|
+
const routerEntry = await import("./router-Bf2efXht.mjs").then((n) => n.r);
|
|
770
770
|
const startEntry = await import("./start-HYkvq4Ni.mjs");
|
|
771
771
|
return { startEntry, routerEntry };
|
|
772
772
|
}
|
|
@@ -3,7 +3,7 @@ import { j as jsxRuntimeExports } from "../_libs/react.mjs";
|
|
|
3
3
|
import { S as SWRConfig } from "../_libs/swr.mjs";
|
|
4
4
|
import { mkdirSync, writeFileSync, renameSync, copyFileSync, unlinkSync, existsSync, readFileSync } from "node:fs";
|
|
5
5
|
import path, { join, isAbsolute, dirname } from "node:path";
|
|
6
|
-
import { mkdir, appendFile, readFile, writeFile } from "node:fs/promises";
|
|
6
|
+
import { mkdir, appendFile, readdir, stat, unlink, readFile, writeFile } from "node:fs/promises";
|
|
7
7
|
import { C as Conf } from "../_libs/conf.mjs";
|
|
8
8
|
import { randomUUID } from "crypto";
|
|
9
9
|
import { exec } from "node:child_process";
|
|
@@ -68,12 +68,12 @@ function RootDocument({ children }) {
|
|
|
68
68
|
] })
|
|
69
69
|
] });
|
|
70
70
|
}
|
|
71
|
-
const $$splitComponentImporter = () => import("./index-
|
|
71
|
+
const $$splitComponentImporter = () => import("./index-DF6r7JcS.mjs");
|
|
72
72
|
const Route$f = createFileRoute("/")({
|
|
73
73
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
74
74
|
});
|
|
75
75
|
const LOG_DIR_ENV = process.env["LOG_DIR"];
|
|
76
|
-
Number(process.env["LOG_RETENTION_DAYS"] ?? "7");
|
|
76
|
+
const RETENTION_DAYS = Number(process.env["LOG_RETENTION_DAYS"] ?? "7");
|
|
77
77
|
const LOG_FILE_ENV = process.env["LLM_INSPECTOR_LOG_FILE"];
|
|
78
78
|
function getUserDataDir() {
|
|
79
79
|
if (process.platform === "win32") {
|
|
@@ -106,7 +106,33 @@ function getInspectorLogPath() {
|
|
|
106
106
|
const base = getUserDataDir();
|
|
107
107
|
return path.join(base, ".llm-inspector", "logs", "inspector.log");
|
|
108
108
|
}
|
|
109
|
+
async function initLogger() {
|
|
110
|
+
const dir = resolveLogDir();
|
|
111
|
+
const retentionMs = RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
112
|
+
const cutoff = Date.now() - retentionMs;
|
|
113
|
+
try {
|
|
114
|
+
const entries = await readdir(dir);
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
if (!entry.endsWith(".jsonl")) continue;
|
|
117
|
+
const fullPath = path.join(dir, entry);
|
|
118
|
+
try {
|
|
119
|
+
const s = await stat(fullPath);
|
|
120
|
+
if (s.mtimeMs < cutoff) {
|
|
121
|
+
await unlink(fullPath);
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.error("[logger] Failed to initialize log directory:", err);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let loggerInitialized = false;
|
|
109
131
|
async function writeAppLog(message) {
|
|
132
|
+
if (!loggerInitialized) {
|
|
133
|
+
loggerInitialized = true;
|
|
134
|
+
void initLogger();
|
|
135
|
+
}
|
|
110
136
|
try {
|
|
111
137
|
const logPath = getInspectorLogPath();
|
|
112
138
|
const logDirPath = path.dirname(logPath);
|
|
@@ -114,7 +140,8 @@ async function writeAppLog(message) {
|
|
|
114
140
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
115
141
|
await appendFile(logPath, `[${timestamp}] ${message}
|
|
116
142
|
`, "utf-8");
|
|
117
|
-
} catch {
|
|
143
|
+
} catch (err) {
|
|
144
|
+
console.error(`[logger] Failed to write to ${getInspectorLogPath()}:`, err);
|
|
118
145
|
}
|
|
119
146
|
}
|
|
120
147
|
const logger = {
|
|
@@ -149,7 +176,8 @@ async function flushWriteBuffer() {
|
|
|
149
176
|
const filePath = getLogFilePath();
|
|
150
177
|
await mkdir(path.dirname(filePath), { recursive: true });
|
|
151
178
|
await appendFile(filePath, toWrite, "utf-8");
|
|
152
|
-
} catch {
|
|
179
|
+
} catch (err) {
|
|
180
|
+
console.error("[logger] Failed to flush write buffer:", err);
|
|
153
181
|
} finally {
|
|
154
182
|
isFlushing = false;
|
|
155
183
|
}
|
|
@@ -251,12 +279,30 @@ async function findInIndex(id) {
|
|
|
251
279
|
const index = await loadIndex();
|
|
252
280
|
return index.entries[id] ?? null;
|
|
253
281
|
}
|
|
254
|
-
let
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
282
|
+
let idGenerationPromise = null;
|
|
283
|
+
let releaseLock = null;
|
|
284
|
+
async function acquireLock() {
|
|
285
|
+
if (releaseLock === null) {
|
|
286
|
+
idGenerationPromise = new Promise((resolve) => {
|
|
287
|
+
releaseLock = resolve;
|
|
288
|
+
});
|
|
289
|
+
} else {
|
|
290
|
+
await idGenerationPromise;
|
|
291
|
+
idGenerationPromise = new Promise((resolve) => {
|
|
292
|
+
releaseLock = resolve;
|
|
293
|
+
});
|
|
258
294
|
}
|
|
259
|
-
|
|
295
|
+
}
|
|
296
|
+
function releaseLockFn() {
|
|
297
|
+
if (releaseLock) {
|
|
298
|
+
const resolve = releaseLock;
|
|
299
|
+
releaseLock = null;
|
|
300
|
+
idGenerationPromise = null;
|
|
301
|
+
resolve();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
async function getNextLogId() {
|
|
305
|
+
await acquireLock();
|
|
260
306
|
try {
|
|
261
307
|
const index = await loadIndex();
|
|
262
308
|
const nextId = index.maxId + 1;
|
|
@@ -264,7 +310,7 @@ async function getNextLogId() {
|
|
|
264
310
|
cachedIndex = index;
|
|
265
311
|
return nextId;
|
|
266
312
|
} finally {
|
|
267
|
-
|
|
313
|
+
releaseLockFn();
|
|
268
314
|
}
|
|
269
315
|
}
|
|
270
316
|
function getCurrentLogFile() {
|
|
@@ -877,8 +923,7 @@ async function getLogById(id) {
|
|
|
877
923
|
return null;
|
|
878
924
|
}
|
|
879
925
|
function getFilteredLogs(sessionId, model) {
|
|
880
|
-
|
|
881
|
-
return cachedLogs.filter((l) => {
|
|
926
|
+
return [...memoryCache.values()].filter((l) => {
|
|
882
927
|
if (sessionId !== void 0 && l.sessionId !== sessionId) return false;
|
|
883
928
|
if (model !== void 0 && l.model !== model) return false;
|
|
884
929
|
return true;
|
|
@@ -915,13 +960,17 @@ function onLogUpdate(handler) {
|
|
|
915
960
|
};
|
|
916
961
|
}
|
|
917
962
|
function emitLogUpdate(log) {
|
|
963
|
+
const failedHandlers = [];
|
|
918
964
|
for (const handler of sseHandlers) {
|
|
919
965
|
try {
|
|
920
966
|
handler(log);
|
|
921
967
|
} catch {
|
|
922
|
-
|
|
968
|
+
failedHandlers.push(handler);
|
|
923
969
|
}
|
|
924
970
|
}
|
|
971
|
+
for (const handler of failedHandlers) {
|
|
972
|
+
sseHandlers.delete(handler);
|
|
973
|
+
}
|
|
925
974
|
}
|
|
926
975
|
const DEFAULT_UPSTREAM$1 = "https://api.anthropic.com";
|
|
927
976
|
const DEFAULT_OPENAI_UPSTREAM$1 = "https://api.openai.com/v1";
|
|
@@ -2204,6 +2253,7 @@ const Route$a = createFileRoute("/api/logs")({
|
|
|
2204
2253
|
}
|
|
2205
2254
|
}
|
|
2206
2255
|
});
|
|
2256
|
+
logger.debug("Health endpoint loaded");
|
|
2207
2257
|
const Route$9 = createFileRoute("/api/health")({
|
|
2208
2258
|
server: {
|
|
2209
2259
|
handlers: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/health", "/api/logs", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/api/config/paths"], "preloads": ["/assets/main-
|
|
1
|
+
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/__root.tsx", "children": ["/", "/api/health", "/api/logs", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/api/config/paths"], "preloads": ["/assets/main-BBNeb1MO.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-DIlrtHTN.js"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/models": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/proxy/$.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/config.paths.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.import.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/llm-inspector/src/routes/api/providers.$providerId.test.ts" } }, "clientEntry": "/assets/main-BBNeb1MO.js" });
|
|
2
2
|
export {
|
|
3
3
|
tsrStartManifest
|
|
4
4
|
};
|
package/.output/server/index.mjs
CHANGED
|
@@ -100,51 +100,51 @@ const assets = {
|
|
|
100
100
|
"/assets/alibaba-TTwafVwX.svg": {
|
|
101
101
|
"type": "image/svg+xml",
|
|
102
102
|
"etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
|
|
103
|
-
"mtime": "2026-06-
|
|
103
|
+
"mtime": "2026-06-04T06:47:15.495Z",
|
|
104
104
|
"size": 5915,
|
|
105
105
|
"path": "../public/assets/alibaba-TTwafVwX.svg"
|
|
106
106
|
},
|
|
107
|
+
"/assets/zhipuai-BPNAnxo-.svg": {
|
|
108
|
+
"type": "image/svg+xml",
|
|
109
|
+
"etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
|
|
110
|
+
"mtime": "2026-06-04T06:47:15.493Z",
|
|
111
|
+
"size": 11256,
|
|
112
|
+
"path": "../public/assets/zhipuai-BPNAnxo-.svg"
|
|
113
|
+
},
|
|
107
114
|
"/assets/index-DdJSLfxK.css": {
|
|
108
115
|
"type": "text/css; charset=utf-8",
|
|
109
116
|
"etag": '"10da0-LYeZ5d/vwqh4bAnuP/9hr6Wka6g"',
|
|
110
|
-
"mtime": "2026-06-
|
|
117
|
+
"mtime": "2026-06-04T06:47:15.496Z",
|
|
111
118
|
"size": 69024,
|
|
112
119
|
"path": "../public/assets/index-DdJSLfxK.css"
|
|
113
120
|
},
|
|
114
121
|
"/assets/minimax-BPMzvuL-.jpeg": {
|
|
115
122
|
"type": "image/jpeg",
|
|
116
123
|
"etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
|
|
117
|
-
"mtime": "2026-06-
|
|
124
|
+
"mtime": "2026-06-04T06:47:15.496Z",
|
|
118
125
|
"size": 6918,
|
|
119
126
|
"path": "../public/assets/minimax-BPMzvuL-.jpeg"
|
|
120
127
|
},
|
|
121
|
-
"/assets/zhipuai-BPNAnxo-.svg": {
|
|
122
|
-
"type": "image/svg+xml",
|
|
123
|
-
"etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
|
|
124
|
-
"mtime": "2026-06-04T03:52:13.283Z",
|
|
125
|
-
"size": 11256,
|
|
126
|
-
"path": "../public/assets/zhipuai-BPNAnxo-.svg"
|
|
127
|
-
},
|
|
128
|
-
"/assets/main-Cu0oTDfX.js": {
|
|
129
|
-
"type": "text/javascript; charset=utf-8",
|
|
130
|
-
"etag": '"50591-/K5L0AnXTcumA7dHm7kmA5HXlCE"',
|
|
131
|
-
"mtime": "2026-06-04T03:52:13.283Z",
|
|
132
|
-
"size": 329105,
|
|
133
|
-
"path": "../public/assets/main-Cu0oTDfX.js"
|
|
134
|
-
},
|
|
135
128
|
"/assets/qwen-CONDcHqt.png": {
|
|
136
129
|
"type": "image/png",
|
|
137
130
|
"etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
|
|
138
|
-
"mtime": "2026-06-
|
|
131
|
+
"mtime": "2026-06-04T06:47:15.496Z",
|
|
139
132
|
"size": 357059,
|
|
140
133
|
"path": "../public/assets/qwen-CONDcHqt.png"
|
|
141
134
|
},
|
|
142
|
-
"/assets/
|
|
135
|
+
"/assets/main-BBNeb1MO.js": {
|
|
136
|
+
"type": "text/javascript; charset=utf-8",
|
|
137
|
+
"etag": '"50591-TWIKovzRSQ6vEjzm8WrlemKulhw"',
|
|
138
|
+
"mtime": "2026-06-04T06:47:15.496Z",
|
|
139
|
+
"size": 329105,
|
|
140
|
+
"path": "../public/assets/main-BBNeb1MO.js"
|
|
141
|
+
},
|
|
142
|
+
"/assets/index-DIlrtHTN.js": {
|
|
143
143
|
"type": "text/javascript; charset=utf-8",
|
|
144
|
-
"etag": '"
|
|
145
|
-
"mtime": "2026-06-
|
|
146
|
-
"size":
|
|
147
|
-
"path": "../public/assets/index-
|
|
144
|
+
"etag": '"84a50-FOfNe2UFxoEIdVhEMki5m2aYqKs"',
|
|
145
|
+
"mtime": "2026-06-04T06:47:15.496Z",
|
|
146
|
+
"size": 543312,
|
|
147
|
+
"path": "../public/assets/index-DIlrtHTN.js"
|
|
148
148
|
}
|
|
149
149
|
};
|
|
150
150
|
function readAsset(id) {
|
package/package.json
CHANGED
|
@@ -31,6 +31,7 @@ export function StreamingChunkSequence({
|
|
|
31
31
|
useEffect(() => {
|
|
32
32
|
if (!containerExpanded || chunkState.status !== "idle") return;
|
|
33
33
|
|
|
34
|
+
let cancelled = false;
|
|
34
35
|
setChunkState({ status: "loading" });
|
|
35
36
|
|
|
36
37
|
fetch(`/api/logs/${logId}/chunks`)
|
|
@@ -41,12 +42,20 @@ export function StreamingChunkSequence({
|
|
|
41
42
|
return res.json();
|
|
42
43
|
})
|
|
43
44
|
.then((data: { chunks: StreamingChunk[]; truncated?: boolean }) => {
|
|
44
|
-
|
|
45
|
+
if (!cancelled) {
|
|
46
|
+
setChunkState({ status: "success", chunks: data.chunks });
|
|
47
|
+
}
|
|
45
48
|
})
|
|
46
49
|
.catch(() => {
|
|
47
|
-
|
|
50
|
+
if (!cancelled) {
|
|
51
|
+
setChunkState({ status: "error", message: "Chunk data unavailable" });
|
|
52
|
+
}
|
|
48
53
|
});
|
|
49
|
-
|
|
54
|
+
|
|
55
|
+
return () => {
|
|
56
|
+
cancelled = true;
|
|
57
|
+
};
|
|
58
|
+
}, [containerExpanded, logId]);
|
|
50
59
|
|
|
51
60
|
const groups = useMemo<ChunkGroup[]>(() => {
|
|
52
61
|
if (chunkState.status !== "success") return [];
|
package/src/proxy/logIndex.ts
CHANGED
|
@@ -201,16 +201,37 @@ export async function rebuildIndex(): Promise<LogIndex> {
|
|
|
201
201
|
return newIndex;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
//
|
|
205
|
-
|
|
204
|
+
// Async mutex for atomic ID generation to prevent race conditions
|
|
205
|
+
// Uses a promise queue instead of busy-waiting
|
|
206
|
+
let idGenerationPromise: Promise<void> | null = null;
|
|
207
|
+
let releaseLock: (() => void) | null = null;
|
|
208
|
+
|
|
209
|
+
async function acquireLock(): Promise<void> {
|
|
210
|
+
if (releaseLock === null) {
|
|
211
|
+
idGenerationPromise = new Promise<void>((resolve) => {
|
|
212
|
+
releaseLock = resolve;
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
// Wait for the previous lock to be released
|
|
216
|
+
await idGenerationPromise;
|
|
217
|
+
// After waiting, we need to create a new promise for the next waiter
|
|
218
|
+
idGenerationPromise = new Promise<void>((resolve) => {
|
|
219
|
+
releaseLock = resolve;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
206
223
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
224
|
+
function releaseLockFn(): void {
|
|
225
|
+
if (releaseLock) {
|
|
226
|
+
const resolve = releaseLock;
|
|
227
|
+
releaseLock = null;
|
|
228
|
+
idGenerationPromise = null;
|
|
229
|
+
resolve();
|
|
212
230
|
}
|
|
213
|
-
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export async function getNextLogId(): Promise<number> {
|
|
234
|
+
await acquireLock();
|
|
214
235
|
try {
|
|
215
236
|
const index = await loadIndex();
|
|
216
237
|
const nextId = index.maxId + 1;
|
|
@@ -219,7 +240,7 @@ export async function getNextLogId(): Promise<number> {
|
|
|
219
240
|
cachedIndex = index;
|
|
220
241
|
return nextId;
|
|
221
242
|
} finally {
|
|
222
|
-
|
|
243
|
+
releaseLockFn();
|
|
223
244
|
}
|
|
224
245
|
}
|
|
225
246
|
|
package/src/proxy/logger.ts
CHANGED
|
@@ -60,24 +60,36 @@ export async function initLogger(): Promise<void> {
|
|
|
60
60
|
await unlink(fullPath);
|
|
61
61
|
}
|
|
62
62
|
} catch {
|
|
63
|
-
// Skip files that can't be stat
|
|
63
|
+
// Skip files that can't be stat - not critical
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
} catch {
|
|
67
|
-
//
|
|
66
|
+
} catch (err) {
|
|
67
|
+
// Log directory initialization errors but don't fail startup
|
|
68
|
+
// eslint-disable-next-line no-console
|
|
69
|
+
console.error("[logger] Failed to initialize log directory:", err);
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
// File-based logger for application logs (not log entries)
|
|
74
|
+
let loggerInitialized = false;
|
|
75
|
+
|
|
72
76
|
async function writeAppLog(message: string): Promise<void> {
|
|
77
|
+
// Auto-initialize on first use if not already initialized
|
|
78
|
+
if (!loggerInitialized) {
|
|
79
|
+
loggerInitialized = true;
|
|
80
|
+
void initLogger();
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
try {
|
|
74
84
|
const logPath = getInspectorLogPath();
|
|
75
85
|
const logDirPath = path.dirname(logPath);
|
|
76
86
|
await mkdir(logDirPath, { recursive: true });
|
|
77
87
|
const timestamp = new Date().toISOString();
|
|
78
88
|
await appendFile(logPath, `[${timestamp}] ${message}\n`, "utf-8");
|
|
79
|
-
} catch {
|
|
80
|
-
//
|
|
89
|
+
} catch (err) {
|
|
90
|
+
// Log to stderr since file logging failed
|
|
91
|
+
// eslint-disable-next-line no-console
|
|
92
|
+
console.error(`[logger] Failed to write to ${getInspectorLogPath()}:`, err);
|
|
81
93
|
}
|
|
82
94
|
}
|
|
83
95
|
|
|
@@ -119,8 +131,10 @@ async function flushWriteBuffer(): Promise<void> {
|
|
|
119
131
|
const filePath = getLogFilePath();
|
|
120
132
|
await mkdir(path.dirname(filePath), { recursive: true });
|
|
121
133
|
await appendFile(filePath, toWrite, "utf-8");
|
|
122
|
-
} catch {
|
|
123
|
-
//
|
|
134
|
+
} catch (err) {
|
|
135
|
+
// Log write buffer errors but don't throw to prevent cascading failures
|
|
136
|
+
// eslint-disable-next-line no-console
|
|
137
|
+
console.error("[logger] Failed to flush write buffer:", err);
|
|
124
138
|
} finally {
|
|
125
139
|
isFlushing = false;
|
|
126
140
|
}
|
package/src/proxy/store.ts
CHANGED
|
@@ -266,9 +266,8 @@ export async function getLogById(id: number): Promise<CapturedLog | null> {
|
|
|
266
266
|
|
|
267
267
|
export function getFilteredLogs(sessionId?: string, model?: string): CapturedLog[] {
|
|
268
268
|
// Cache maintains insertion order (sorted by ID since logs are added in ID order)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return cachedLogs.filter((l) => {
|
|
269
|
+
// Use spread instead of Array.from for slightly better performance
|
|
270
|
+
return [...memoryCache.values()].filter((l) => {
|
|
272
271
|
if (sessionId !== undefined && l.sessionId !== sessionId) return false;
|
|
273
272
|
if (model !== undefined && l.model !== model) return false;
|
|
274
273
|
return true;
|
|
@@ -385,12 +384,17 @@ export function onLogUpdate(handler: LogUpdateHandler): () => void {
|
|
|
385
384
|
}
|
|
386
385
|
|
|
387
386
|
export function emitLogUpdate(log: CapturedLog): void {
|
|
387
|
+
const failedHandlers: LogUpdateHandler[] = [];
|
|
388
388
|
for (const handler of sseHandlers) {
|
|
389
389
|
try {
|
|
390
390
|
handler(log);
|
|
391
391
|
} catch {
|
|
392
|
-
//
|
|
393
|
-
|
|
392
|
+
// Collect failed handlers to remove after iteration
|
|
393
|
+
failedHandlers.push(handler);
|
|
394
394
|
}
|
|
395
395
|
}
|
|
396
|
+
// Remove failed handlers after iteration to avoid Set mutation during for...of
|
|
397
|
+
for (const handler of failedHandlers) {
|
|
398
|
+
sseHandlers.delete(handler);
|
|
399
|
+
}
|
|
396
400
|
}
|
package/src/routes/api/health.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
+
import { logger } from "../../proxy/logger";
|
|
3
|
+
|
|
4
|
+
// Trigger logger auto-initialization when this module loads
|
|
5
|
+
logger.debug("Health endpoint loaded");
|
|
2
6
|
|
|
3
7
|
export const Route = createFileRoute("/api/health")({
|
|
4
8
|
server: {
|