@xopcai/xopc 0.0.16 → 0.0.18

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.
Files changed (36) hide show
  1. package/dist/extensions/feishu/src/transport/client/client.js +1 -1
  2. package/dist/extensions/feishu/src/transport/client/client.js.map +1 -1
  3. package/dist/extensions/feishu/src/transport/webhook/monitor.js +1 -1
  4. package/dist/extensions/feishu/src/transport/webhook/monitor.js.map +1 -1
  5. package/dist/extensions/telegram/xopc.extension.json +1 -1
  6. package/dist/gateway/static/root/assets/{agents-Dy5cGVVQ.js → agents-D1c5jt8x.js} +2 -2
  7. package/dist/gateway/static/root/assets/{agents-Dy5cGVVQ.js.map → agents-D1c5jt8x.js.map} +1 -1
  8. package/dist/gateway/static/root/assets/{apps-page-BOpDR0Lz.js → apps-page-bi53w_qy.js} +2 -2
  9. package/dist/gateway/static/root/assets/{apps-page-BOpDR0Lz.js.map → apps-page-bi53w_qy.js.map} +1 -1
  10. package/dist/gateway/static/root/assets/{channels-settings-CrCesccB.js → channels-settings-CPWWa4rf.js} +2 -2
  11. package/dist/gateway/static/root/assets/{channels-settings-CrCesccB.js.map → channels-settings-CPWWa4rf.js.map} +1 -1
  12. package/dist/gateway/static/root/assets/{cron-page-B_XY0gPt.js → cron-page-CFuU6V8l.js} +2 -2
  13. package/dist/gateway/static/root/assets/{cron-page-B_XY0gPt.js.map → cron-page-CFuU6V8l.js.map} +1 -1
  14. package/dist/gateway/static/root/assets/{cron-utils-BYdnLwhl.js → cron-utils-D7qRCgCo.js} +2 -2
  15. package/dist/gateway/static/root/assets/{cron-utils-BYdnLwhl.js.map → cron-utils-D7qRCgCo.js.map} +1 -1
  16. package/dist/gateway/static/root/assets/{dist-DvaA5uNp.js → dist-CS--Aojm.js} +2 -2
  17. package/dist/gateway/static/root/assets/{dist-DvaA5uNp.js.map → dist-CS--Aojm.js.map} +1 -1
  18. package/dist/gateway/static/root/assets/{extension-debug-page-CPSk7gFW.js → extension-debug-page-DkaqKijm.js} +2 -2
  19. package/dist/gateway/static/root/assets/{extension-debug-page-CPSk7gFW.js.map → extension-debug-page-DkaqKijm.js.map} +1 -1
  20. package/dist/gateway/static/root/assets/{extension-page-COdbk9I6.js → extension-page-5WNq5ZxE.js} +2 -2
  21. package/dist/gateway/static/root/assets/{extension-page-COdbk9I6.js.map → extension-page-5WNq5ZxE.js.map} +1 -1
  22. package/dist/gateway/static/root/assets/{extension-settings-page-BlEz2Ily.js → extension-settings-page-BM4emw9B.js} +2 -2
  23. package/dist/gateway/static/root/assets/{extension-settings-page-BlEz2Ily.js.map → extension-settings-page-BM4emw9B.js.map} +1 -1
  24. package/dist/gateway/static/root/assets/{index-tm9ZY35l.js → index-DJnBAhem.js} +4 -4
  25. package/dist/gateway/static/root/assets/{index-tm9ZY35l.js.map → index-DJnBAhem.js.map} +1 -1
  26. package/dist/gateway/static/root/assets/{logs-page-LSa0jmLO.js → logs-page-Du6UoHCK.js} +2 -2
  27. package/dist/gateway/static/root/assets/{logs-page-LSa0jmLO.js.map → logs-page-Du6UoHCK.js.map} +1 -1
  28. package/dist/gateway/static/root/assets/{sessions-page-cn2fi_V3.js → sessions-page-CzTpNrb3.js} +2 -2
  29. package/dist/gateway/static/root/assets/{sessions-page-cn2fi_V3.js.map → sessions-page-CzTpNrb3.js.map} +1 -1
  30. package/dist/gateway/static/root/assets/{settings-page-CyHd5szQ.js → settings-page-jqrVlTkQ.js} +2 -2
  31. package/dist/gateway/static/root/assets/{settings-page-CyHd5szQ.js.map → settings-page-jqrVlTkQ.js.map} +1 -1
  32. package/dist/gateway/static/root/assets/{skills-page-irjxwW9u.js → skills-page-Dg_Uk_jM.js} +2 -2
  33. package/dist/gateway/static/root/assets/{skills-page-irjxwW9u.js.map → skills-page-Dg_Uk_jM.js.map} +1 -1
  34. package/dist/gateway/static/root/index.html +1 -1
  35. package/dist/package.js +1 -1
  36. package/package.json +2 -1
@@ -1,2 +1,2 @@
1
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{B as r,Bn as i,Bt as a,Dn as o,Er as s,H as ee,Kt as c,Mt as te,N as ne,Nt as re,Ot as ie,Rt as ae,V as oe,Vt as l,Wn as se,Wt as u,at as d,dn as ce,dr as le,dt as f,en as ue,ft as p,ln as de,lt as m,ot as h,rr as fe,rt as g,st as pe,ut as _,z as me}from"./index-tm9ZY35l.js";var v=e(t(),1);function he(e){let t=new URLSearchParams;if(!e)return``;e.level?.length&&t.set(`level`,e.level.join(`,`)),e.from&&t.set(`from`,e.from),e.to&&t.set(`to`,e.to),e.q&&t.set(`q`,e.q),e.module&&t.set(`module`,e.module),e.limit!=null&&t.set(`limit`,String(e.limit)),e.offset!=null&&t.set(`offset`,String(e.offset));let n=t.toString();return n?`?${n}`:``}async function y(e){return d(g(`/api/logs${he(e)}`))}async function b(){return(await d(g(`/api/logs/files`))).files??[]}async function ge(){return(await d(g(`/api/logs/modules`))).modules??[]}async function x(){return{byLevel:(await d(g(`/api/logs/stats`))).byLevel??{}}}async function _e(){return(await d(g(`/api/logs/dir`))).dir??``}var S=[`trace`,`debug`,`info`,`warn`,`error`,`fatal`],C=n(),w=50,ve=5e3,ye=new Set(S),be=[`error`,`fatal`],xe=[`warn`,`error`,`fatal`],T=[`info`,`warn`,`error`,`fatal`];function Se(e){if(!e)return new Set;let t=new Set;for(let n of e.split(`,`)){let e=n.trim();ye.has(e)&&t.add(e)}return t}function Ce(e,t){if(e.size!==t.size)return!1;for(let n of e)if(!t.has(n))return!1;return!0}function E(e,t){return e.size===t.length?t.every(t=>e.has(t)):!1}function D(e){return e.size===0?`all`:E(e,be)?`errors`:E(e,xe)?`warnPlus`:E(e,T)?`infoPlus`:e.size===S.length&&S.every(t=>e.has(t))?`verbose`:`custom`}function we(e){let t=D(e);return t===`custom`?`other`:t}function Te(e){switch(e){case`all`:return new Set;case`errors`:return new Set(be);case`warnPlus`:return new Set(xe);case`infoPlus`:return new Set(T);case`verbose`:return new Set(S)}}function Ee(e,t){return e.replace(/\{\{(\w+)\}\}/g,(e,n)=>String(t[n]??``))}function O(e){return String(e.module||e.prefix||e.service||e.extension||`—`)}function De(e){if(typeof e.message==`string`&&e.message)return e.message;try{return JSON.stringify(e)}catch{return``}}function Oe(e){try{return new Date(e).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}catch{return e}}function ke(e){try{return new Date(e).toLocaleString()}catch{return e}}function Ae(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function je(e){let t=e.trim();return t.length<=10?t:`${t.slice(0,8)}…`}function Me(e){return String(e).toLowerCase()}function Ne(e,t){let n=[];for(let r of S){let i=e[r]??0;i>0&&n.push(`${t[r]} ${i}`)}return n.join(` · `)}function k(){let e=a(te(e=>e.language)).logs,t=!!ie(e=>e.token),[n,d]=s(),g=n.get(`q`)??``,he=Se(n.get(`level`)),ye=n.get(`module`)??``,be=n.get(`from`)??``,xe=n.get(`to`)??``,T=n.get(`live`)===`1`,[E,D]=(0,v.useState)([]),[k,A]=(0,v.useState)(!1),[Fe,j]=(0,v.useState)(null),[Ie,M]=(0,v.useState)(!1),[N,P]=(0,v.useState)(g),[F,I]=(0,v.useState)(g.trim()),[L,R]=(0,v.useState)(he),[z,B]=(0,v.useState)(ye),[V,H]=(0,v.useState)(be),[U,W]=(0,v.useState)(xe),[Le,Re]=(0,v.useState)([]),[G,K]=(0,v.useState)([]),[q,J]=(0,v.useState)(null),[Y,ze]=(0,v.useState)(null),[Be,Ve]=(0,v.useState)(!1),[He,X]=(0,v.useState)(!1),[Ue,We]=(0,v.useState)(null),[Z,Ge]=(0,v.useState)(T),[Q,Ke]=(0,v.useState)(null),qe=(0,v.useMemo)(()=>we(L),[L]),Je=F.length>0||L.size>0||!!z||!!V||!!U,Ye=+(F.length>0)+ +(L.size>0)+ +!!z+(V||U?1:0);(0,v.useEffect)(()=>{let e=setTimeout(()=>I(N.trim()),300);return()=>clearTimeout(e)},[N]),(0,v.useEffect)(()=>{let e=n.get(`q`)??``,t=n.get(`module`)??``,r=n.get(`from`)??``,i=n.get(`to`)??``,a=n.get(`live`)===`1`,o=Se(n.get(`level`)),s=e.trim();P(t=>t===e?t:e),I(e=>e===s?e:s),R(e=>Ce(o,e)?e:o),B(e=>e===t?e:t),H(e=>e===r?e:r),W(e=>e===i?e:i),Ge(e=>e===a?e:a)},[n]),(0,v.useEffect)(()=>{let e=new URLSearchParams(n),t=F.trim();t?e.set(`q`,t):e.delete(`q`),L.size>0?e.set(`level`,Array.from(L).sort().join(`,`)):e.delete(`level`),z?e.set(`module`,z):e.delete(`module`),V?e.set(`from`,V):e.delete(`from`),U?e.set(`to`,U):e.delete(`to`),Z?e.set(`live`,`1`):e.delete(`live`),e.toString()!==n.toString()&&d(e,{replace:!0})},[Z,V,U,F,z,n,L,d]);let $=(0,v.useMemo)(()=>({q:F||void 0,level:L.size>0?Array.from(L):void 0,module:z||void 0,from:V||void 0,to:U||void 0,limit:w}),[F,L,z,V,U]);(0,v.useEffect)(()=>{if(!t)return;let n=!1;return(async()=>{A(!0),j(null),D([]);try{let e=await y({...$,offset:0});if(n)return;D(e.logs),M(e.logs.length===w)}catch(t){n||(j(t instanceof Error?t.message:e.loadError),D([]),M(!1))}finally{n||A(!1)}})(),()=>{n=!0}},[t,$,e.loadError]),(0,v.useEffect)(()=>{if(!t)return;let e=!1;return(async()=>{try{let[t,n,r]=await Promise.all([ge(),x(),b()]);e||(Re(t),J(n),K(r))}catch{}})(),()=>{e=!0}},[t]),(0,v.useEffect)(()=>{if(!t||!Be)return;let e=!1;return(async()=>{try{let[t,n]=await Promise.all([b(),_e()]);e||(K(t),We(n))}catch{e||K([])}})(),()=>{e=!0}},[t,Be]),(0,v.useEffect)(()=>{if(!Z||!t)return;let e=window.setInterval(()=>{(async()=>{try{let e=await y({...$,offset:0});D(e.logs),M(e.logs.length===w),J(await x())}catch{}})()},ve);return()=>clearInterval(e)},[Z,t,$]),(0,v.useEffect)(()=>{if(!Q)return;let e=window.setTimeout(()=>Ke(null),2e3);return()=>clearTimeout(e)},[Q]);let Xe=()=>{P(``),I(``),R(new Set),B(``),H(``),W(``)},Ze=e=>{if(e===`other`){X(!0);return}R(Te(e))},Qe=e=>{R(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},$e=()=>{k||!Ie||(async()=>{A(!0),j(null);try{let e=await y({...$,offset:E.length});D(t=>[...t,...e.logs]),M(e.logs.length===w)}catch(t){j(t instanceof Error?t.message:e.loadError)}finally{A(!1)}})()},et=()=>{(async()=>{A(!0),j(null);try{let e=await y({...$,offset:0});D(e.logs),M(e.logs.length===w);let[t,n]=await Promise.all([x(),b()]);J(t),K(n)}catch(t){j(t instanceof Error?t.message:e.loadError)}finally{A(!1)}})()},tt=q?Ne(q.byLevel??{},e.levelNames):``;return t?(0,C.jsxs)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-6`,children:[(0,C.jsxs)(`header`,{className:`flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between`,children:[(0,C.jsxs)(`div`,{className:`flex min-w-0 items-start gap-3`,children:[(0,C.jsx)(`div`,{className:`flex size-10 shrink-0 items-center justify-center rounded-xl border border-edge-subtle bg-surface-base dark:border-edge`,"aria-hidden":!0,children:(0,C.jsx)(ue,{className:`size-5 text-fg-muted`,strokeWidth:1.75})}),(0,C.jsxs)(`div`,{className:`min-w-0`,children:[(0,C.jsx)(`h1`,{className:`text-xl font-semibold tracking-tight text-fg`,children:e.title}),(0,C.jsx)(`p`,{className:`mt-0.5 text-sm leading-relaxed text-fg-muted`,children:e.subtitle})]})]}),(0,C.jsxs)(`div`,{className:`flex w-full shrink-0 flex-col gap-2 sm:w-auto sm:max-w-md sm:flex-row sm:items-center sm:justify-end`,children:[(0,C.jsx)(`div`,{className:`w-full sm:w-48`,children:(0,C.jsx)(ne,{"aria-label":e.refreshModeAria,value:Z?`live`:`paused`,onChange:e=>Ge(e===`live`),options:[{value:`paused`,label:e.refreshManual},{value:`live`,label:e.refreshLive}],buttonClassName:`h-8`})}),(0,C.jsxs)(`div`,{className:`flex items-center gap-1 self-end sm:self-center`,children:[(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0`,title:e.logFiles,"aria-label":e.logFiles,onClick:()=>Ve(!0),children:[(0,C.jsx)(i,{className:`size-4`,strokeWidth:1.75}),G.length>0?(0,C.jsx)(`span`,{className:`rounded-full bg-surface-hover px-1.5 text-xs text-fg-muted`,children:G.length}):null]}),(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0`,title:e.refresh,"aria-label":e.refresh,onClick:et,children:(0,C.jsx)(ce,{className:u(`size-4 transition-transform duration-150 ease-out motion-reduce:transition-none`,k&&`animate-spin motion-reduce:animate-none`),strokeWidth:1.75})})]})]})]}),Fe?(0,C.jsx)(`div`,{className:`rounded-xl border border-edge bg-surface-base px-3 py-2 text-sm text-fg dark:border-edge`,role:`alert`,children:Fe}):null,q&&tt?(0,C.jsx)(`div`,{className:`flex flex-wrap items-center gap-2`,children:(0,C.jsxs)(oe,{children:[(0,C.jsx)(ee,{asChild:!0,children:(0,C.jsxs)(`button`,{type:`button`,className:`max-w-full truncate rounded-lg border border-transparent px-1 py-0.5 text-left text-xs leading-5 text-fg-subtle transition-colors duration-150 ease-out hover:border-edge-subtle hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel dark:hover:border-edge`,children:[(0,C.jsx)(`span`,{className:`font-medium text-fg-muted`,children:e.statsRegion}),(0,C.jsx)(`span`,{className:`mx-1.5 text-fg-subtle`,children:`·`}),(0,C.jsx)(`span`,{className:`tabular-nums`,children:tt})]})}),(0,C.jsx)(r,{children:(0,C.jsxs)(me,{side:`bottom`,align:`start`,sideOffset:6,className:u(`z-50 w-[min(calc(100vw-2rem),20rem)] rounded-xl border border-edge bg-surface-panel p-3 shadow-popover outline-none`,`dark:border-edge`),children:[(0,C.jsx)(`p`,{className:`text-xs font-medium text-fg`,children:e.statsDetailTitle}),(0,C.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-fg-muted`,children:e.statsHint}),(0,C.jsx)(`ul`,{className:`mt-3 flex flex-col gap-1.5`,role:`list`,children:S.map(t=>{let n=q.byLevel?.[t]??0;return n===0?null:(0,C.jsxs)(`li`,{className:`flex items-center justify-between gap-2 rounded-md border border-edge-subtle bg-surface-base px-2 py-1 text-xs dark:border-edge`,children:[(0,C.jsx)(`span`,{className:`font-medium capitalize text-fg`,children:e.levelNames[t]}),(0,C.jsx)(`span`,{className:`tabular-nums text-fg-muted`,children:n})]},t)})})]})})]})}):null,(0,C.jsxs)(`section`,{className:`flex flex-col gap-3`,"aria-label":e.filters,children:[(0,C.jsx)(`div`,{className:`overflow-x-auto pb-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden`,children:(0,C.jsx)(`div`,{className:`min-w-[min(100%,36rem)]`,children:(0,C.jsx)(ne,{"aria-label":e.levelPresetAria,value:qe,onChange:Ze,options:[{value:`all`,label:e.presetAll},{value:`errors`,label:e.presetErrors},{value:`warnPlus`,label:e.presetWarnPlus},{value:`infoPlus`,label:e.presetInfoPlus},{value:`verbose`,label:e.presetVerbose},{value:`other`,label:e.presetOther}],buttonClassName:`h-8 px-1.5 text-[11px] sm:px-2 sm:text-xs`})})}),(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center`,children:[(0,C.jsxs)(`label`,{className:`relative min-w-0 flex-1 sm:min-w-[12rem]`,children:[(0,C.jsx)(`span`,{className:`sr-only`,children:e.searchPlaceholder}),(0,C.jsx)(de,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-subtle`,strokeWidth:1.75,"aria-hidden":!0}),(0,C.jsx)(`input`,{type:`search`,value:N,onChange:e=>P(e.target.value),placeholder:e.searchPlaceholder,autoComplete:`off`,spellCheck:!1,className:u(`h-10 w-full rounded-md border border-edge bg-surface-panel py-0 pl-10 pr-3 text-sm leading-5 text-fg placeholder:text-fg-subtle dark:border-edge`,re)})]}),(0,C.jsxs)(`select`,{id:`log-module`,value:z,onChange:e=>B(e.target.value),"aria-label":e.module,title:e.module,className:u(ae,`h-10 w-full min-w-0 rounded-md py-0 sm:w-[min(100%,14rem)] sm:shrink-0`),children:[(0,C.jsx)(`option`,{value:``,children:e.allModules}),Le.map(e=>(0,C.jsx)(`option`,{value:e,children:e},e))]}),(0,C.jsxs)(`div`,{className:`flex min-w-0 shrink-0 items-center gap-2`,children:[(0,C.jsxs)(l,{type:`button`,variant:`secondary`,className:`h-10 min-h-[44px] gap-2 rounded-md sm:min-h-10`,onClick:()=>X(!0),children:[(0,C.jsx)(o,{className:`size-4`,strokeWidth:1.75}),e.filtersMore,Ye>0?(0,C.jsx)(`span`,{className:`rounded-md bg-surface-hover px-1.5 text-xs tabular-nums text-fg-muted`,children:Ye}):null]}),Je?(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-10 min-h-[44px] gap-1 sm:min-h-10`,onClick:Xe,children:[(0,C.jsx)(c,{className:`size-4`,strokeWidth:1.75}),e.clear]}):null]})]}),Z?(0,C.jsx)(`p`,{className:`text-xs leading-5 text-fg-subtle`,children:e.liveHint}):null]}),k&&E.length===0?(0,C.jsx)(`div`,{className:`divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel dark:divide-edge dark:border-edge`,"aria-busy":`true`,children:Array.from({length:8}).map((e,t)=>(0,C.jsxs)(`div`,{className:`flex gap-3 px-3 py-2.5`,children:[(0,C.jsx)(`div`,{className:`h-4 w-16 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse`}),(0,C.jsx)(`div`,{className:`h-4 w-12 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse`}),(0,C.jsx)(`div`,{className:`h-4 w-20 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse`}),(0,C.jsx)(`div`,{className:`h-4 min-w-0 flex-1 bg-surface-hover motion-reduce:animate-none animate-pulse`})]},t))}):null,!k&&E.length===0?(0,C.jsxs)(`div`,{className:`flex flex-col items-center justify-center gap-2 rounded-xl border border-edge-subtle bg-surface-base py-16 text-center dark:border-edge`,children:[(0,C.jsx)(se,{className:`size-12 text-fg-subtle`,strokeWidth:1.5,"aria-hidden":!0}),(0,C.jsx)(`h2`,{className:`text-base font-semibold tracking-tight text-fg`,children:e.noLogs}),(0,C.jsx)(`p`,{className:`max-w-sm text-sm leading-relaxed text-fg-muted`,children:e.noLogsDescription}),(0,C.jsxs)(l,{type:`button`,variant:`secondary`,className:`mt-4 gap-2`,onClick:et,children:[(0,C.jsx)(ce,{className:`size-4`,strokeWidth:1.75}),e.refresh]})]}):null,E.length>0?(0,C.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,C.jsxs)(`p`,{className:`text-xs leading-5 text-fg-muted`,children:[Ee(e.showingCount,{count:String(E.length)}),Ie?(0,C.jsxs)(`span`,{className:`text-fg-subtle`,children:[` · `,e.moreAvailable]}):null]}),(0,C.jsx)(`ul`,{className:`divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel font-mono text-sm leading-6 dark:divide-edge dark:border-edge`,role:`list`,children:E.map((t,n)=>{let r=t.level??`info`,i=typeof t.requestId==`string`?t.requestId.trim():``;return(0,C.jsx)(`li`,{children:(0,C.jsxs)(`button`,{type:`button`,onClick:()=>ze(t),className:u(`flex w-full min-w-0 items-center gap-3 px-3 py-2.5 text-left transition-colors duration-150 ease-out`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`),children:[(0,C.jsx)(`span`,{className:`w-[5.25rem] shrink-0 tabular-nums text-fg-subtle`,children:Oe(t.timestamp)}),(0,C.jsx)(`span`,{className:`w-[4.5rem] shrink-0 truncate text-fg-muted`,title:r,children:Me(r)}),(0,C.jsx)(`span`,{className:`w-[4.5rem] shrink-0 truncate text-fg-subtle sm:w-[5.25rem]`,title:i?`${e.requestId}: ${i}`:void 0,children:i?je(i):`—`}),(0,C.jsx)(`span`,{className:`hidden max-w-[7rem] shrink-0 truncate text-fg-muted lg:inline`,title:O(t),children:O(t)}),(0,C.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg`,children:De(t)})]})},`${t.timestamp}-${n}`)})}),Ie?(0,C.jsx)(`div`,{className:`flex justify-center pt-1`,children:(0,C.jsxs)(l,{type:`button`,variant:`secondary`,className:`gap-2`,disabled:k,onClick:$e,children:[k?(0,C.jsx)(ce,{className:`size-4 animate-spin motion-reduce:animate-none`,strokeWidth:1.75}):(0,C.jsx)(le,{className:`size-4`,strokeWidth:1.75}),e.loadMore]})}):null]}):null,(0,C.jsx)(f,{open:He,onOpenChange:X,children:(0,C.jsxs)(_,{children:[(0,C.jsx)(m,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,C.jsxs)(pe,{className:u(`xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,90vh)] w-[min(100%-2rem,22rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),"aria-describedby":`log-filters-desc`,children:[(0,C.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,C.jsx)(p,{className:`text-base font-semibold tracking-tight text-fg`,children:e.filtersDialogTitle}),(0,C.jsx)(h,{asChild:!0,children:(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":e.close,children:(0,C.jsx)(c,{className:`size-5`,strokeWidth:1.75})})})]}),(0,C.jsx)(`div`,{id:`log-filters-desc`,className:`sr-only`,children:e.filtersDialogDesc}),(0,C.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-4`,children:[(0,C.jsx)(`p`,{className:`text-xs font-medium text-fg-muted`,children:e.timeRange}),(0,C.jsxs)(`div`,{className:`mt-2 flex flex-col gap-3`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`label`,{htmlFor:`log-from-d`,className:`mb-1 block text-xs text-fg-muted`,children:e.from}),(0,C.jsx)(`input`,{id:`log-from-d`,type:`datetime-local`,value:V,onChange:e=>H(e.target.value),className:`w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`label`,{htmlFor:`log-to-d`,className:`mb-1 block text-xs text-fg-muted`,children:e.to}),(0,C.jsx)(`input`,{id:`log-to-d`,type:`datetime-local`,value:U,onChange:e=>W(e.target.value),className:`w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge`})]})]}),(0,C.jsx)(`p`,{className:`mt-6 text-xs font-medium text-fg-muted`,children:e.levelCustom}),(0,C.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-fg-subtle`,children:e.levelCustomHint}),(0,C.jsx)(`div`,{className:`mt-3 flex flex-wrap gap-2`,role:`group`,"aria-label":e.level,children:S.map(t=>(0,C.jsx)(`button`,{type:`button`,className:u(`rounded-full border px-3 py-1.5 text-xs font-medium capitalize transition-[color,background-color,border-color] duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`,L.has(t)?`border-edge bg-surface-active text-fg dark:border-edge`:`border-edge-subtle bg-surface-base text-fg-muted hover:bg-surface-hover dark:border-edge`),onClick:()=>Qe(t),children:e.levelNames[t]},t))})]}),(0,C.jsx)(`div`,{className:`shrink-0 border-t border-edge-subtle px-4 py-3 dark:border-edge`,children:(0,C.jsx)(l,{type:`button`,className:`w-full rounded-xl`,onClick:()=>X(!1),children:e.filtersDone})})]})]})}),(0,C.jsx)(f,{open:Y!==null,onOpenChange:e=>!e&&ze(null),children:(0,C.jsxs)(_,{children:[(0,C.jsx)(m,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,C.jsxs)(pe,{className:u(`xopc-drawer-right fixed right-0 top-0 z-50 flex h-full w-full max-w-lg flex-col border-l border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),"aria-describedby":void 0,children:[(0,C.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,C.jsx)(p,{className:`text-base font-semibold tracking-tight text-fg`,children:e.details}),(0,C.jsxs)(`div`,{className:`flex min-w-0 items-center gap-1`,children:[Y?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-9 shrink-0 gap-1 px-2 text-xs`,onClick:()=>{let e=typeof Y.message==`string`?Y.message:``;navigator.clipboard.writeText(e).then(()=>Ke(`message`))},children:[(0,C.jsx)(fe,{className:`size-3.5 shrink-0`,strokeWidth:1.75}),(0,C.jsx)(`span`,{className:`hidden sm:inline`,children:Q===`message`?e.copied:e.copyMessage})]}),(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-9 shrink-0 gap-1 px-2 text-xs`,onClick:()=>{navigator.clipboard.writeText(JSON.stringify(Y,null,2)).then(()=>Ke(`json`))},children:[(0,C.jsx)(fe,{className:`size-3.5 shrink-0`,strokeWidth:1.75}),(0,C.jsx)(`span`,{className:`hidden sm:inline`,children:Q===`json`?e.copied:e.copyJson})]})]}):null,(0,C.jsx)(h,{asChild:!0,children:(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":e.close,children:(0,C.jsx)(c,{className:`size-5`,strokeWidth:1.75})})})]})]}),(0,C.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-4 font-mono text-sm leading-relaxed`,children:Y?(0,C.jsx)(Pe,{log:Y,labels:{time:e.time,level:e.level,module:e.module,message:e.message,metadata:e.metadata,requestId:e.requestId,sessionId:e.sessionId}}):null})]})]})}),(0,C.jsx)(f,{open:Be,onOpenChange:Ve,children:(0,C.jsxs)(_,{children:[(0,C.jsx)(m,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,C.jsxs)(pe,{className:u(`xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,85vh)] w-[min(100%-2rem,24rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),children:[(0,C.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,C.jsxs)(p,{className:`flex items-center gap-2 text-base font-semibold tracking-tight text-fg`,children:[(0,C.jsx)(i,{className:`size-4 text-fg-muted`,strokeWidth:1.75}),e.logFiles]}),(0,C.jsx)(h,{asChild:!0,children:(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":e.close,children:(0,C.jsx)(c,{className:`size-5`,strokeWidth:1.75})})})]}),(0,C.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-3`,children:G.length===0?(0,C.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e.filesEmpty}):(0,C.jsx)(`ul`,{className:`flex flex-col gap-2`,role:`list`,children:G.map(e=>(0,C.jsxs)(`li`,{className:`flex flex-col gap-1 rounded-lg border border-edge-subtle bg-surface-base px-3 py-2 dark:border-edge`,children:[(0,C.jsx)(`span`,{className:`break-all font-mono text-xs text-fg`,children:e.name}),(0,C.jsxs)(`span`,{className:`flex flex-wrap gap-x-2 text-xs text-fg-subtle`,children:[(0,C.jsx)(`span`,{children:Ae(e.size)}),(0,C.jsx)(`span`,{children:ke(e.modified)})]})]},e.name))})}),Ue?(0,C.jsxs)(`div`,{className:`shrink-0 border-t border-edge-subtle px-4 py-2 text-xs text-fg-subtle dark:border-edge`,children:[(0,C.jsxs)(`span`,{className:`font-medium text-fg-muted`,children:[e.logDir,`: `]}),(0,C.jsx)(`code`,{className:`break-all text-fg-subtle`,children:Ue})]}):null]})]})})]}):(0,C.jsx)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-10`,children:(0,C.jsxs)(`div`,{className:`flex items-start gap-3 rounded-2xl border border-edge-subtle bg-surface-base p-6 dark:border-edge`,children:[(0,C.jsx)(ue,{className:`mt-0.5 size-5 shrink-0 text-fg-subtle`,strokeWidth:1.75,"aria-hidden":!0}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`h1`,{className:`text-base font-semibold tracking-tight text-fg`,children:e.title}),(0,C.jsx)(`p`,{className:`mt-1 text-sm leading-relaxed text-fg-muted`,children:e.needToken})]})]})})}function Pe({log:e,labels:t}){let n=e.level??`info`,r=typeof e.requestId==`string`?e.requestId:``,i=typeof e.sessionId==`string`?e.sessionId:``;return(0,C.jsxs)(`div`,{className:`flex flex-col gap-8`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`span`,{className:`text-xs font-sans font-medium text-fg-muted`,children:t.message}),(0,C.jsx)(`pre`,{className:`mt-2 whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge`,children:e.message||`—`})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-[5.5rem_1fr] gap-x-3 gap-y-2 text-xs`,children:[(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.time}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:e.timestamp}),(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.level}),(0,C.jsx)(`span`,{className:`text-fg`,children:Me(n)}),(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.module}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:O(e)}),r?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.requestId}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:r})]}):null,i?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.sessionId}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:i})]}):null]}),e.meta&&Object.keys(e.meta).length>0?(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`span`,{className:`text-xs font-sans font-medium text-fg-muted`,children:t.metadata}),(0,C.jsx)(`pre`,{className:`mt-2 overflow-x-auto whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge`,children:JSON.stringify(e.meta,null,2)})]}):null]})}export{k as LogsPage};
2
- //# sourceMappingURL=logs-page-LSa0jmLO.js.map
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{B as r,Bn as i,Bt as a,Dn as o,Er as s,H as ee,Kt as c,Mt as te,N as ne,Nt as re,Ot as ie,Rt as ae,V as oe,Vt as l,Wn as se,Wt as u,at as d,dn as ce,dr as le,dt as f,en as ue,ft as p,ln as de,lt as m,ot as h,rr as fe,rt as g,st as pe,ut as _,z as me}from"./index-DJnBAhem.js";var v=e(t(),1);function he(e){let t=new URLSearchParams;if(!e)return``;e.level?.length&&t.set(`level`,e.level.join(`,`)),e.from&&t.set(`from`,e.from),e.to&&t.set(`to`,e.to),e.q&&t.set(`q`,e.q),e.module&&t.set(`module`,e.module),e.limit!=null&&t.set(`limit`,String(e.limit)),e.offset!=null&&t.set(`offset`,String(e.offset));let n=t.toString();return n?`?${n}`:``}async function y(e){return d(g(`/api/logs${he(e)}`))}async function b(){return(await d(g(`/api/logs/files`))).files??[]}async function ge(){return(await d(g(`/api/logs/modules`))).modules??[]}async function x(){return{byLevel:(await d(g(`/api/logs/stats`))).byLevel??{}}}async function _e(){return(await d(g(`/api/logs/dir`))).dir??``}var S=[`trace`,`debug`,`info`,`warn`,`error`,`fatal`],C=n(),w=50,ve=5e3,ye=new Set(S),be=[`error`,`fatal`],xe=[`warn`,`error`,`fatal`],T=[`info`,`warn`,`error`,`fatal`];function Se(e){if(!e)return new Set;let t=new Set;for(let n of e.split(`,`)){let e=n.trim();ye.has(e)&&t.add(e)}return t}function Ce(e,t){if(e.size!==t.size)return!1;for(let n of e)if(!t.has(n))return!1;return!0}function E(e,t){return e.size===t.length?t.every(t=>e.has(t)):!1}function D(e){return e.size===0?`all`:E(e,be)?`errors`:E(e,xe)?`warnPlus`:E(e,T)?`infoPlus`:e.size===S.length&&S.every(t=>e.has(t))?`verbose`:`custom`}function we(e){let t=D(e);return t===`custom`?`other`:t}function Te(e){switch(e){case`all`:return new Set;case`errors`:return new Set(be);case`warnPlus`:return new Set(xe);case`infoPlus`:return new Set(T);case`verbose`:return new Set(S)}}function Ee(e,t){return e.replace(/\{\{(\w+)\}\}/g,(e,n)=>String(t[n]??``))}function O(e){return String(e.module||e.prefix||e.service||e.extension||`—`)}function De(e){if(typeof e.message==`string`&&e.message)return e.message;try{return JSON.stringify(e)}catch{return``}}function Oe(e){try{return new Date(e).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}catch{return e}}function ke(e){try{return new Date(e).toLocaleString()}catch{return e}}function Ae(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function je(e){let t=e.trim();return t.length<=10?t:`${t.slice(0,8)}…`}function Me(e){return String(e).toLowerCase()}function Ne(e,t){let n=[];for(let r of S){let i=e[r]??0;i>0&&n.push(`${t[r]} ${i}`)}return n.join(` · `)}function k(){let e=a(te(e=>e.language)).logs,t=!!ie(e=>e.token),[n,d]=s(),g=n.get(`q`)??``,he=Se(n.get(`level`)),ye=n.get(`module`)??``,be=n.get(`from`)??``,xe=n.get(`to`)??``,T=n.get(`live`)===`1`,[E,D]=(0,v.useState)([]),[k,A]=(0,v.useState)(!1),[Fe,j]=(0,v.useState)(null),[Ie,M]=(0,v.useState)(!1),[N,P]=(0,v.useState)(g),[F,I]=(0,v.useState)(g.trim()),[L,R]=(0,v.useState)(he),[z,B]=(0,v.useState)(ye),[V,H]=(0,v.useState)(be),[U,W]=(0,v.useState)(xe),[Le,Re]=(0,v.useState)([]),[G,K]=(0,v.useState)([]),[q,J]=(0,v.useState)(null),[Y,ze]=(0,v.useState)(null),[Be,Ve]=(0,v.useState)(!1),[He,X]=(0,v.useState)(!1),[Ue,We]=(0,v.useState)(null),[Z,Ge]=(0,v.useState)(T),[Q,Ke]=(0,v.useState)(null),qe=(0,v.useMemo)(()=>we(L),[L]),Je=F.length>0||L.size>0||!!z||!!V||!!U,Ye=+(F.length>0)+ +(L.size>0)+ +!!z+(V||U?1:0);(0,v.useEffect)(()=>{let e=setTimeout(()=>I(N.trim()),300);return()=>clearTimeout(e)},[N]),(0,v.useEffect)(()=>{let e=n.get(`q`)??``,t=n.get(`module`)??``,r=n.get(`from`)??``,i=n.get(`to`)??``,a=n.get(`live`)===`1`,o=Se(n.get(`level`)),s=e.trim();P(t=>t===e?t:e),I(e=>e===s?e:s),R(e=>Ce(o,e)?e:o),B(e=>e===t?e:t),H(e=>e===r?e:r),W(e=>e===i?e:i),Ge(e=>e===a?e:a)},[n]),(0,v.useEffect)(()=>{let e=new URLSearchParams(n),t=F.trim();t?e.set(`q`,t):e.delete(`q`),L.size>0?e.set(`level`,Array.from(L).sort().join(`,`)):e.delete(`level`),z?e.set(`module`,z):e.delete(`module`),V?e.set(`from`,V):e.delete(`from`),U?e.set(`to`,U):e.delete(`to`),Z?e.set(`live`,`1`):e.delete(`live`),e.toString()!==n.toString()&&d(e,{replace:!0})},[Z,V,U,F,z,n,L,d]);let $=(0,v.useMemo)(()=>({q:F||void 0,level:L.size>0?Array.from(L):void 0,module:z||void 0,from:V||void 0,to:U||void 0,limit:w}),[F,L,z,V,U]);(0,v.useEffect)(()=>{if(!t)return;let n=!1;return(async()=>{A(!0),j(null),D([]);try{let e=await y({...$,offset:0});if(n)return;D(e.logs),M(e.logs.length===w)}catch(t){n||(j(t instanceof Error?t.message:e.loadError),D([]),M(!1))}finally{n||A(!1)}})(),()=>{n=!0}},[t,$,e.loadError]),(0,v.useEffect)(()=>{if(!t)return;let e=!1;return(async()=>{try{let[t,n,r]=await Promise.all([ge(),x(),b()]);e||(Re(t),J(n),K(r))}catch{}})(),()=>{e=!0}},[t]),(0,v.useEffect)(()=>{if(!t||!Be)return;let e=!1;return(async()=>{try{let[t,n]=await Promise.all([b(),_e()]);e||(K(t),We(n))}catch{e||K([])}})(),()=>{e=!0}},[t,Be]),(0,v.useEffect)(()=>{if(!Z||!t)return;let e=window.setInterval(()=>{(async()=>{try{let e=await y({...$,offset:0});D(e.logs),M(e.logs.length===w),J(await x())}catch{}})()},ve);return()=>clearInterval(e)},[Z,t,$]),(0,v.useEffect)(()=>{if(!Q)return;let e=window.setTimeout(()=>Ke(null),2e3);return()=>clearTimeout(e)},[Q]);let Xe=()=>{P(``),I(``),R(new Set),B(``),H(``),W(``)},Ze=e=>{if(e===`other`){X(!0);return}R(Te(e))},Qe=e=>{R(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},$e=()=>{k||!Ie||(async()=>{A(!0),j(null);try{let e=await y({...$,offset:E.length});D(t=>[...t,...e.logs]),M(e.logs.length===w)}catch(t){j(t instanceof Error?t.message:e.loadError)}finally{A(!1)}})()},et=()=>{(async()=>{A(!0),j(null);try{let e=await y({...$,offset:0});D(e.logs),M(e.logs.length===w);let[t,n]=await Promise.all([x(),b()]);J(t),K(n)}catch(t){j(t instanceof Error?t.message:e.loadError)}finally{A(!1)}})()},tt=q?Ne(q.byLevel??{},e.levelNames):``;return t?(0,C.jsxs)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-6`,children:[(0,C.jsxs)(`header`,{className:`flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between`,children:[(0,C.jsxs)(`div`,{className:`flex min-w-0 items-start gap-3`,children:[(0,C.jsx)(`div`,{className:`flex size-10 shrink-0 items-center justify-center rounded-xl border border-edge-subtle bg-surface-base dark:border-edge`,"aria-hidden":!0,children:(0,C.jsx)(ue,{className:`size-5 text-fg-muted`,strokeWidth:1.75})}),(0,C.jsxs)(`div`,{className:`min-w-0`,children:[(0,C.jsx)(`h1`,{className:`text-xl font-semibold tracking-tight text-fg`,children:e.title}),(0,C.jsx)(`p`,{className:`mt-0.5 text-sm leading-relaxed text-fg-muted`,children:e.subtitle})]})]}),(0,C.jsxs)(`div`,{className:`flex w-full shrink-0 flex-col gap-2 sm:w-auto sm:max-w-md sm:flex-row sm:items-center sm:justify-end`,children:[(0,C.jsx)(`div`,{className:`w-full sm:w-48`,children:(0,C.jsx)(ne,{"aria-label":e.refreshModeAria,value:Z?`live`:`paused`,onChange:e=>Ge(e===`live`),options:[{value:`paused`,label:e.refreshManual},{value:`live`,label:e.refreshLive}],buttonClassName:`h-8`})}),(0,C.jsxs)(`div`,{className:`flex items-center gap-1 self-end sm:self-center`,children:[(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0`,title:e.logFiles,"aria-label":e.logFiles,onClick:()=>Ve(!0),children:[(0,C.jsx)(i,{className:`size-4`,strokeWidth:1.75}),G.length>0?(0,C.jsx)(`span`,{className:`rounded-full bg-surface-hover px-1.5 text-xs text-fg-muted`,children:G.length}):null]}),(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0`,title:e.refresh,"aria-label":e.refresh,onClick:et,children:(0,C.jsx)(ce,{className:u(`size-4 transition-transform duration-150 ease-out motion-reduce:transition-none`,k&&`animate-spin motion-reduce:animate-none`),strokeWidth:1.75})})]})]})]}),Fe?(0,C.jsx)(`div`,{className:`rounded-xl border border-edge bg-surface-base px-3 py-2 text-sm text-fg dark:border-edge`,role:`alert`,children:Fe}):null,q&&tt?(0,C.jsx)(`div`,{className:`flex flex-wrap items-center gap-2`,children:(0,C.jsxs)(oe,{children:[(0,C.jsx)(ee,{asChild:!0,children:(0,C.jsxs)(`button`,{type:`button`,className:`max-w-full truncate rounded-lg border border-transparent px-1 py-0.5 text-left text-xs leading-5 text-fg-subtle transition-colors duration-150 ease-out hover:border-edge-subtle hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel dark:hover:border-edge`,children:[(0,C.jsx)(`span`,{className:`font-medium text-fg-muted`,children:e.statsRegion}),(0,C.jsx)(`span`,{className:`mx-1.5 text-fg-subtle`,children:`·`}),(0,C.jsx)(`span`,{className:`tabular-nums`,children:tt})]})}),(0,C.jsx)(r,{children:(0,C.jsxs)(me,{side:`bottom`,align:`start`,sideOffset:6,className:u(`z-50 w-[min(calc(100vw-2rem),20rem)] rounded-xl border border-edge bg-surface-panel p-3 shadow-popover outline-none`,`dark:border-edge`),children:[(0,C.jsx)(`p`,{className:`text-xs font-medium text-fg`,children:e.statsDetailTitle}),(0,C.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-fg-muted`,children:e.statsHint}),(0,C.jsx)(`ul`,{className:`mt-3 flex flex-col gap-1.5`,role:`list`,children:S.map(t=>{let n=q.byLevel?.[t]??0;return n===0?null:(0,C.jsxs)(`li`,{className:`flex items-center justify-between gap-2 rounded-md border border-edge-subtle bg-surface-base px-2 py-1 text-xs dark:border-edge`,children:[(0,C.jsx)(`span`,{className:`font-medium capitalize text-fg`,children:e.levelNames[t]}),(0,C.jsx)(`span`,{className:`tabular-nums text-fg-muted`,children:n})]},t)})})]})})]})}):null,(0,C.jsxs)(`section`,{className:`flex flex-col gap-3`,"aria-label":e.filters,children:[(0,C.jsx)(`div`,{className:`overflow-x-auto pb-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden`,children:(0,C.jsx)(`div`,{className:`min-w-[min(100%,36rem)]`,children:(0,C.jsx)(ne,{"aria-label":e.levelPresetAria,value:qe,onChange:Ze,options:[{value:`all`,label:e.presetAll},{value:`errors`,label:e.presetErrors},{value:`warnPlus`,label:e.presetWarnPlus},{value:`infoPlus`,label:e.presetInfoPlus},{value:`verbose`,label:e.presetVerbose},{value:`other`,label:e.presetOther}],buttonClassName:`h-8 px-1.5 text-[11px] sm:px-2 sm:text-xs`})})}),(0,C.jsxs)(`div`,{className:`flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center`,children:[(0,C.jsxs)(`label`,{className:`relative min-w-0 flex-1 sm:min-w-[12rem]`,children:[(0,C.jsx)(`span`,{className:`sr-only`,children:e.searchPlaceholder}),(0,C.jsx)(de,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-subtle`,strokeWidth:1.75,"aria-hidden":!0}),(0,C.jsx)(`input`,{type:`search`,value:N,onChange:e=>P(e.target.value),placeholder:e.searchPlaceholder,autoComplete:`off`,spellCheck:!1,className:u(`h-10 w-full rounded-md border border-edge bg-surface-panel py-0 pl-10 pr-3 text-sm leading-5 text-fg placeholder:text-fg-subtle dark:border-edge`,re)})]}),(0,C.jsxs)(`select`,{id:`log-module`,value:z,onChange:e=>B(e.target.value),"aria-label":e.module,title:e.module,className:u(ae,`h-10 w-full min-w-0 rounded-md py-0 sm:w-[min(100%,14rem)] sm:shrink-0`),children:[(0,C.jsx)(`option`,{value:``,children:e.allModules}),Le.map(e=>(0,C.jsx)(`option`,{value:e,children:e},e))]}),(0,C.jsxs)(`div`,{className:`flex min-w-0 shrink-0 items-center gap-2`,children:[(0,C.jsxs)(l,{type:`button`,variant:`secondary`,className:`h-10 min-h-[44px] gap-2 rounded-md sm:min-h-10`,onClick:()=>X(!0),children:[(0,C.jsx)(o,{className:`size-4`,strokeWidth:1.75}),e.filtersMore,Ye>0?(0,C.jsx)(`span`,{className:`rounded-md bg-surface-hover px-1.5 text-xs tabular-nums text-fg-muted`,children:Ye}):null]}),Je?(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-10 min-h-[44px] gap-1 sm:min-h-10`,onClick:Xe,children:[(0,C.jsx)(c,{className:`size-4`,strokeWidth:1.75}),e.clear]}):null]})]}),Z?(0,C.jsx)(`p`,{className:`text-xs leading-5 text-fg-subtle`,children:e.liveHint}):null]}),k&&E.length===0?(0,C.jsx)(`div`,{className:`divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel dark:divide-edge dark:border-edge`,"aria-busy":`true`,children:Array.from({length:8}).map((e,t)=>(0,C.jsxs)(`div`,{className:`flex gap-3 px-3 py-2.5`,children:[(0,C.jsx)(`div`,{className:`h-4 w-16 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse`}),(0,C.jsx)(`div`,{className:`h-4 w-12 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse`}),(0,C.jsx)(`div`,{className:`h-4 w-20 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse`}),(0,C.jsx)(`div`,{className:`h-4 min-w-0 flex-1 bg-surface-hover motion-reduce:animate-none animate-pulse`})]},t))}):null,!k&&E.length===0?(0,C.jsxs)(`div`,{className:`flex flex-col items-center justify-center gap-2 rounded-xl border border-edge-subtle bg-surface-base py-16 text-center dark:border-edge`,children:[(0,C.jsx)(se,{className:`size-12 text-fg-subtle`,strokeWidth:1.5,"aria-hidden":!0}),(0,C.jsx)(`h2`,{className:`text-base font-semibold tracking-tight text-fg`,children:e.noLogs}),(0,C.jsx)(`p`,{className:`max-w-sm text-sm leading-relaxed text-fg-muted`,children:e.noLogsDescription}),(0,C.jsxs)(l,{type:`button`,variant:`secondary`,className:`mt-4 gap-2`,onClick:et,children:[(0,C.jsx)(ce,{className:`size-4`,strokeWidth:1.75}),e.refresh]})]}):null,E.length>0?(0,C.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,C.jsxs)(`p`,{className:`text-xs leading-5 text-fg-muted`,children:[Ee(e.showingCount,{count:String(E.length)}),Ie?(0,C.jsxs)(`span`,{className:`text-fg-subtle`,children:[` · `,e.moreAvailable]}):null]}),(0,C.jsx)(`ul`,{className:`divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel font-mono text-sm leading-6 dark:divide-edge dark:border-edge`,role:`list`,children:E.map((t,n)=>{let r=t.level??`info`,i=typeof t.requestId==`string`?t.requestId.trim():``;return(0,C.jsx)(`li`,{children:(0,C.jsxs)(`button`,{type:`button`,onClick:()=>ze(t),className:u(`flex w-full min-w-0 items-center gap-3 px-3 py-2.5 text-left transition-colors duration-150 ease-out`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`),children:[(0,C.jsx)(`span`,{className:`w-[5.25rem] shrink-0 tabular-nums text-fg-subtle`,children:Oe(t.timestamp)}),(0,C.jsx)(`span`,{className:`w-[4.5rem] shrink-0 truncate text-fg-muted`,title:r,children:Me(r)}),(0,C.jsx)(`span`,{className:`w-[4.5rem] shrink-0 truncate text-fg-subtle sm:w-[5.25rem]`,title:i?`${e.requestId}: ${i}`:void 0,children:i?je(i):`—`}),(0,C.jsx)(`span`,{className:`hidden max-w-[7rem] shrink-0 truncate text-fg-muted lg:inline`,title:O(t),children:O(t)}),(0,C.jsx)(`span`,{className:`min-w-0 flex-1 truncate text-fg`,children:De(t)})]})},`${t.timestamp}-${n}`)})}),Ie?(0,C.jsx)(`div`,{className:`flex justify-center pt-1`,children:(0,C.jsxs)(l,{type:`button`,variant:`secondary`,className:`gap-2`,disabled:k,onClick:$e,children:[k?(0,C.jsx)(ce,{className:`size-4 animate-spin motion-reduce:animate-none`,strokeWidth:1.75}):(0,C.jsx)(le,{className:`size-4`,strokeWidth:1.75}),e.loadMore]})}):null]}):null,(0,C.jsx)(f,{open:He,onOpenChange:X,children:(0,C.jsxs)(_,{children:[(0,C.jsx)(m,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,C.jsxs)(pe,{className:u(`xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,90vh)] w-[min(100%-2rem,22rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),"aria-describedby":`log-filters-desc`,children:[(0,C.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,C.jsx)(p,{className:`text-base font-semibold tracking-tight text-fg`,children:e.filtersDialogTitle}),(0,C.jsx)(h,{asChild:!0,children:(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":e.close,children:(0,C.jsx)(c,{className:`size-5`,strokeWidth:1.75})})})]}),(0,C.jsx)(`div`,{id:`log-filters-desc`,className:`sr-only`,children:e.filtersDialogDesc}),(0,C.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-4`,children:[(0,C.jsx)(`p`,{className:`text-xs font-medium text-fg-muted`,children:e.timeRange}),(0,C.jsxs)(`div`,{className:`mt-2 flex flex-col gap-3`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`label`,{htmlFor:`log-from-d`,className:`mb-1 block text-xs text-fg-muted`,children:e.from}),(0,C.jsx)(`input`,{id:`log-from-d`,type:`datetime-local`,value:V,onChange:e=>H(e.target.value),className:`w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge`})]}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`label`,{htmlFor:`log-to-d`,className:`mb-1 block text-xs text-fg-muted`,children:e.to}),(0,C.jsx)(`input`,{id:`log-to-d`,type:`datetime-local`,value:U,onChange:e=>W(e.target.value),className:`w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge`})]})]}),(0,C.jsx)(`p`,{className:`mt-6 text-xs font-medium text-fg-muted`,children:e.levelCustom}),(0,C.jsx)(`p`,{className:`mt-1 text-xs leading-5 text-fg-subtle`,children:e.levelCustomHint}),(0,C.jsx)(`div`,{className:`mt-3 flex flex-wrap gap-2`,role:`group`,"aria-label":e.level,children:S.map(t=>(0,C.jsx)(`button`,{type:`button`,className:u(`rounded-full border px-3 py-1.5 text-xs font-medium capitalize transition-[color,background-color,border-color] duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`,L.has(t)?`border-edge bg-surface-active text-fg dark:border-edge`:`border-edge-subtle bg-surface-base text-fg-muted hover:bg-surface-hover dark:border-edge`),onClick:()=>Qe(t),children:e.levelNames[t]},t))})]}),(0,C.jsx)(`div`,{className:`shrink-0 border-t border-edge-subtle px-4 py-3 dark:border-edge`,children:(0,C.jsx)(l,{type:`button`,className:`w-full rounded-xl`,onClick:()=>X(!1),children:e.filtersDone})})]})]})}),(0,C.jsx)(f,{open:Y!==null,onOpenChange:e=>!e&&ze(null),children:(0,C.jsxs)(_,{children:[(0,C.jsx)(m,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,C.jsxs)(pe,{className:u(`xopc-drawer-right fixed right-0 top-0 z-50 flex h-full w-full max-w-lg flex-col border-l border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),"aria-describedby":void 0,children:[(0,C.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,C.jsx)(p,{className:`text-base font-semibold tracking-tight text-fg`,children:e.details}),(0,C.jsxs)(`div`,{className:`flex min-w-0 items-center gap-1`,children:[Y?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-9 shrink-0 gap-1 px-2 text-xs`,onClick:()=>{let e=typeof Y.message==`string`?Y.message:``;navigator.clipboard.writeText(e).then(()=>Ke(`message`))},children:[(0,C.jsx)(fe,{className:`size-3.5 shrink-0`,strokeWidth:1.75}),(0,C.jsx)(`span`,{className:`hidden sm:inline`,children:Q===`message`?e.copied:e.copyMessage})]}),(0,C.jsxs)(l,{type:`button`,variant:`ghost`,className:`h-9 shrink-0 gap-1 px-2 text-xs`,onClick:()=>{navigator.clipboard.writeText(JSON.stringify(Y,null,2)).then(()=>Ke(`json`))},children:[(0,C.jsx)(fe,{className:`size-3.5 shrink-0`,strokeWidth:1.75}),(0,C.jsx)(`span`,{className:`hidden sm:inline`,children:Q===`json`?e.copied:e.copyJson})]})]}):null,(0,C.jsx)(h,{asChild:!0,children:(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":e.close,children:(0,C.jsx)(c,{className:`size-5`,strokeWidth:1.75})})})]})]}),(0,C.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-4 font-mono text-sm leading-relaxed`,children:Y?(0,C.jsx)(Pe,{log:Y,labels:{time:e.time,level:e.level,module:e.module,message:e.message,metadata:e.metadata,requestId:e.requestId,sessionId:e.sessionId}}):null})]})]})}),(0,C.jsx)(f,{open:Be,onOpenChange:Ve,children:(0,C.jsxs)(_,{children:[(0,C.jsx)(m,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,C.jsxs)(pe,{className:u(`xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,85vh)] w-[min(100%-2rem,24rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),children:[(0,C.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,C.jsxs)(p,{className:`flex items-center gap-2 text-base font-semibold tracking-tight text-fg`,children:[(0,C.jsx)(i,{className:`size-4 text-fg-muted`,strokeWidth:1.75}),e.logFiles]}),(0,C.jsx)(h,{asChild:!0,children:(0,C.jsx)(l,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":e.close,children:(0,C.jsx)(c,{className:`size-5`,strokeWidth:1.75})})})]}),(0,C.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-3`,children:G.length===0?(0,C.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e.filesEmpty}):(0,C.jsx)(`ul`,{className:`flex flex-col gap-2`,role:`list`,children:G.map(e=>(0,C.jsxs)(`li`,{className:`flex flex-col gap-1 rounded-lg border border-edge-subtle bg-surface-base px-3 py-2 dark:border-edge`,children:[(0,C.jsx)(`span`,{className:`break-all font-mono text-xs text-fg`,children:e.name}),(0,C.jsxs)(`span`,{className:`flex flex-wrap gap-x-2 text-xs text-fg-subtle`,children:[(0,C.jsx)(`span`,{children:Ae(e.size)}),(0,C.jsx)(`span`,{children:ke(e.modified)})]})]},e.name))})}),Ue?(0,C.jsxs)(`div`,{className:`shrink-0 border-t border-edge-subtle px-4 py-2 text-xs text-fg-subtle dark:border-edge`,children:[(0,C.jsxs)(`span`,{className:`font-medium text-fg-muted`,children:[e.logDir,`: `]}),(0,C.jsx)(`code`,{className:`break-all text-fg-subtle`,children:Ue})]}):null]})]})})]}):(0,C.jsx)(`div`,{className:`mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-10`,children:(0,C.jsxs)(`div`,{className:`flex items-start gap-3 rounded-2xl border border-edge-subtle bg-surface-base p-6 dark:border-edge`,children:[(0,C.jsx)(ue,{className:`mt-0.5 size-5 shrink-0 text-fg-subtle`,strokeWidth:1.75,"aria-hidden":!0}),(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`h1`,{className:`text-base font-semibold tracking-tight text-fg`,children:e.title}),(0,C.jsx)(`p`,{className:`mt-1 text-sm leading-relaxed text-fg-muted`,children:e.needToken})]})]})})}function Pe({log:e,labels:t}){let n=e.level??`info`,r=typeof e.requestId==`string`?e.requestId:``,i=typeof e.sessionId==`string`?e.sessionId:``;return(0,C.jsxs)(`div`,{className:`flex flex-col gap-8`,children:[(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`span`,{className:`text-xs font-sans font-medium text-fg-muted`,children:t.message}),(0,C.jsx)(`pre`,{className:`mt-2 whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge`,children:e.message||`—`})]}),(0,C.jsxs)(`div`,{className:`grid grid-cols-[5.5rem_1fr] gap-x-3 gap-y-2 text-xs`,children:[(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.time}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:e.timestamp}),(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.level}),(0,C.jsx)(`span`,{className:`text-fg`,children:Me(n)}),(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.module}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:O(e)}),r?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.requestId}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:r})]}):null,i?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`span`,{className:`font-sans text-fg-muted`,children:t.sessionId}),(0,C.jsx)(`code`,{className:`break-all text-fg`,children:i})]}):null]}),e.meta&&Object.keys(e.meta).length>0?(0,C.jsxs)(`div`,{children:[(0,C.jsx)(`span`,{className:`text-xs font-sans font-medium text-fg-muted`,children:t.metadata}),(0,C.jsx)(`pre`,{className:`mt-2 overflow-x-auto whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge`,children:JSON.stringify(e.meta,null,2)})]}):null]})}export{k as LogsPage};
2
+ //# sourceMappingURL=logs-page-Du6UoHCK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logs-page-LSa0jmLO.js","names":[],"sources":["../../../../../web/src/features/logs/log-api.ts","../../../../../web/src/features/logs/log.types.ts","../../../../../web/src/features/logs/logs-page.tsx"],"sourcesContent":["import { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport type { LogEntry, LogFile, LogQuery, LogStats } from '@/features/logs/log.types';\n\nfunction buildQueryString(query?: LogQuery): string {\n const params = new URLSearchParams();\n if (!query) return '';\n if (query.level?.length) params.set('level', query.level.join(','));\n if (query.from) params.set('from', query.from);\n if (query.to) params.set('to', query.to);\n if (query.q) params.set('q', query.q);\n if (query.module) params.set('module', query.module);\n if (query.limit != null) params.set('limit', String(query.limit));\n if (query.offset != null) params.set('offset', String(query.offset));\n const qs = params.toString();\n return qs ? `?${qs}` : '';\n}\n\nexport async function queryLogs(query?: LogQuery): Promise<{ logs: LogEntry[]; count: number }> {\n return fetchJson<{ logs: LogEntry[]; count: number }>(apiUrl(`/api/logs${buildQueryString(query)}`));\n}\n\nexport async function getLogFiles(): Promise<LogFile[]> {\n const result = await fetchJson<{ files: LogFile[] }>(apiUrl('/api/logs/files'));\n return result.files ?? [];\n}\n\nexport async function getLogModules(): Promise<string[]> {\n const result = await fetchJson<{ modules: string[] }>(apiUrl('/api/logs/modules'));\n return result.modules ?? [];\n}\n\nexport async function getLogStats(): Promise<LogStats> {\n const raw = await fetchJson<Partial<LogStats>>(apiUrl('/api/logs/stats'));\n return { byLevel: raw.byLevel ?? {} };\n}\n\nexport async function getLogDir(): Promise<string> {\n const result = await fetchJson<{ dir: string }>(apiUrl('/api/logs/dir'));\n return result.dir ?? '';\n}\n","export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nexport const LOG_LEVELS: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n\nexport interface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n module?: string;\n prefix?: string;\n service?: string;\n extension?: string;\n requestId?: string;\n sessionId?: string;\n userId?: string;\n meta?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface LogQuery {\n level?: string[];\n from?: string;\n to?: string;\n q?: string;\n module?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface LogFile {\n name: string;\n size: number;\n modified: string;\n}\n\nexport interface LogStats {\n byLevel: Partial<Record<LogLevel | 'silent', number>>;\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport * as Popover from '@radix-ui/react-popover';\nimport {\n ChevronDown,\n ClipboardCopy,\n FileText,\n Folder,\n ListFilter,\n RefreshCw,\n Search,\n Terminal,\n X,\n} from 'lucide-react';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useSearchParams } from 'react-router-dom';\n\nimport { SlidingSegmented } from '@/components/ui/sliding-segmented';\nimport { Button } from '@/components/ui/button';\nimport { bareInputFocusClass, selectControlBaseClass } from '@/lib/form-field-width';\nimport { cn } from '@/lib/cn';\nimport {\n getLogDir,\n getLogFiles,\n getLogModules,\n getLogStats,\n queryLogs,\n} from '@/features/logs/log-api';\nimport type { LogEntry, LogFile, LogLevel } from '@/features/logs/log.types';\nimport { LOG_LEVELS } from '@/features/logs/log.types';\nimport { messages } from '@/i18n/messages';\nimport { useGatewayStore } from '@/stores/gateway-store';\nimport { useLocaleStore } from '@/stores/locale-store';\n\nconst PAGE_LIMIT = 50;\nconst REFRESH_MS = 5000;\nconst LOG_LEVEL_SET = new Set<LogLevel>(LOG_LEVELS);\n\ntype LevelPreset = 'all' | 'errors' | 'warnPlus' | 'infoPlus' | 'verbose' | 'custom';\ntype LevelSegmentValue = Exclude<LevelPreset, 'custom'> | 'other';\n\nconst PRESET_ERRORS: LogLevel[] = ['error', 'fatal'];\nconst PRESET_WARN_PLUS: LogLevel[] = ['warn', 'error', 'fatal'];\nconst PRESET_INFO_PLUS: LogLevel[] = ['info', 'warn', 'error', 'fatal'];\n\nfunction parseLogLevelsParam(raw: string | null): Set<LogLevel> {\n if (!raw) return new Set<LogLevel>();\n const out = new Set<LogLevel>();\n for (const part of raw.split(',')) {\n const level = part.trim() as LogLevel;\n if (LOG_LEVEL_SET.has(level)) out.add(level);\n }\n return out;\n}\n\nfunction isSameLogLevelSet(a: Set<LogLevel>, b: Set<LogLevel>): boolean {\n if (a.size !== b.size) return false;\n for (const level of a) {\n if (!b.has(level)) return false;\n }\n return true;\n}\n\nfunction setMatchesLevels(s: Set<LogLevel>, levels: readonly LogLevel[]): boolean {\n if (s.size !== levels.length) return false;\n return levels.every((l) => s.has(l));\n}\n\nfunction derivePreset(levels: Set<LogLevel>): LevelPreset {\n if (levels.size === 0) return 'all';\n if (setMatchesLevels(levels, PRESET_ERRORS)) return 'errors';\n if (setMatchesLevels(levels, PRESET_WARN_PLUS)) return 'warnPlus';\n if (setMatchesLevels(levels, PRESET_INFO_PLUS)) return 'infoPlus';\n if (levels.size === LOG_LEVELS.length && LOG_LEVELS.every((l) => levels.has(l))) return 'verbose';\n return 'custom';\n}\n\nfunction segmentValueFromLevels(levels: Set<LogLevel>): LevelSegmentValue {\n const p = derivePreset(levels);\n return p === 'custom' ? 'other' : p;\n}\n\nfunction levelsForPreset(preset: Exclude<LevelPreset, 'custom'>): Set<LogLevel> {\n switch (preset) {\n case 'all':\n return new Set();\n case 'errors':\n return new Set(PRESET_ERRORS);\n case 'warnPlus':\n return new Set(PRESET_WARN_PLUS);\n case 'infoPlus':\n return new Set(PRESET_INFO_PLUS);\n case 'verbose':\n return new Set(LOG_LEVELS);\n }\n}\n\nfunction interpolate(template: string, params: Record<string, string | number>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => String(params[key] ?? ''));\n}\n\nfunction moduleLabel(log: LogEntry): string {\n return String(log.module || log.prefix || log.service || log.extension || '—');\n}\n\nfunction messagePreview(log: LogEntry): string {\n if (typeof log.message === 'string' && log.message) return log.message;\n try {\n return JSON.stringify(log);\n } catch {\n return '';\n }\n}\n\nfunction formatTimeCompact(timestamp: string): string {\n try {\n const date = new Date(timestamp);\n return date.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n });\n } catch {\n return timestamp;\n }\n}\n\nfunction formatTimestampFull(timestamp: string): string {\n try {\n return new Date(timestamp).toLocaleString();\n } catch {\n return timestamp;\n }\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction requestIdPreview(id: string): string {\n const t = id.trim();\n if (t.length <= 10) return t;\n return `${t.slice(0, 8)}…`;\n}\n\nfunction levelLabel(level: string): string {\n return String(level).toLowerCase();\n}\n\nfunction formatStatsLine(\n byLevel: Partial<Record<LogLevel | 'silent', number>>,\n labels: Record<LogLevel, string>,\n): string {\n const parts: string[] = [];\n for (const lv of LOG_LEVELS) {\n const n = byLevel[lv] ?? 0;\n if (n > 0) parts.push(`${labels[lv]} ${n}`);\n }\n return parts.join(' · ');\n}\n\nexport function LogsPage() {\n const language = useLocaleStore((s) => s.language);\n const m = messages(language);\n const L = m.logs;\n const token = useGatewayStore((st) => st.token);\n const hasToken = Boolean(token);\n const [searchParams, setSearchParams] = useSearchParams();\n\n const initialSearch = searchParams.get('q') ?? '';\n const initialLevels = parseLogLevelsParam(searchParams.get('level'));\n const initialModule = searchParams.get('module') ?? '';\n const initialFrom = searchParams.get('from') ?? '';\n const initialTo = searchParams.get('to') ?? '';\n const initialAutoRefresh = searchParams.get('live') === '1';\n\n const [logs, setLogs] = useState<LogEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [hasMore, setHasMore] = useState(false);\n\n const [searchInput, setSearchInput] = useState(initialSearch);\n const [debouncedSearch, setDebouncedSearch] = useState(initialSearch.trim());\n const [selectedLevels, setSelectedLevels] = useState<Set<LogLevel>>(initialLevels);\n const [moduleFilter, setModuleFilter] = useState(initialModule);\n const [dateFrom, setDateFrom] = useState(initialFrom);\n const [dateTo, setDateTo] = useState(initialTo);\n\n const [modules, setModules] = useState<string[]>([]);\n const [files, setFiles] = useState<LogFile[]>([]);\n const [stats, setStats] = useState<Awaited<ReturnType<typeof getLogStats>> | null>(null);\n\n const [selectedLog, setSelectedLog] = useState<LogEntry | null>(null);\n const [filesOpen, setFilesOpen] = useState(false);\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [logDir, setLogDir] = useState<string | null>(null);\n const [autoRefresh, setAutoRefresh] = useState(initialAutoRefresh);\n const [copiedDetail, setCopiedDetail] = useState<'json' | 'message' | null>(null);\n\n const levelSegment = useMemo(() => segmentValueFromLevels(selectedLevels), [selectedLevels]);\n\n const hasActiveFilters =\n debouncedSearch.length > 0 ||\n selectedLevels.size > 0 ||\n Boolean(moduleFilter) ||\n Boolean(dateFrom) ||\n Boolean(dateTo);\n\n const activeFilterCount =\n (debouncedSearch.length > 0 ? 1 : 0) +\n (selectedLevels.size > 0 ? 1 : 0) +\n (moduleFilter ? 1 : 0) +\n (dateFrom || dateTo ? 1 : 0);\n\n useEffect(() => {\n const t = setTimeout(() => setDebouncedSearch(searchInput.trim()), 300);\n return () => clearTimeout(t);\n }, [searchInput]);\n\n useEffect(() => {\n const nextQ = searchParams.get('q') ?? '';\n const nextModule = searchParams.get('module') ?? '';\n const nextFrom = searchParams.get('from') ?? '';\n const nextTo = searchParams.get('to') ?? '';\n const nextAutoRefresh = searchParams.get('live') === '1';\n const nextLevels = parseLogLevelsParam(searchParams.get('level'));\n const nextDebouncedQ = nextQ.trim();\n\n setSearchInput((prev) => (prev === nextQ ? prev : nextQ));\n setDebouncedSearch((prev) => (prev === nextDebouncedQ ? prev : nextDebouncedQ));\n setSelectedLevels((prev) => (isSameLogLevelSet(nextLevels, prev) ? prev : nextLevels));\n setModuleFilter((prev) => (prev === nextModule ? prev : nextModule));\n setDateFrom((prev) => (prev === nextFrom ? prev : nextFrom));\n setDateTo((prev) => (prev === nextTo ? prev : nextTo));\n setAutoRefresh((prev) => (prev === nextAutoRefresh ? prev : nextAutoRefresh));\n }, [searchParams]);\n\n useEffect(() => {\n const params = new URLSearchParams(searchParams);\n const nextQ = debouncedSearch.trim();\n if (nextQ) params.set('q', nextQ);\n else params.delete('q');\n\n if (selectedLevels.size > 0) {\n params.set('level', Array.from(selectedLevels).sort().join(','));\n } else {\n params.delete('level');\n }\n\n if (moduleFilter) params.set('module', moduleFilter);\n else params.delete('module');\n if (dateFrom) params.set('from', dateFrom);\n else params.delete('from');\n if (dateTo) params.set('to', dateTo);\n else params.delete('to');\n if (autoRefresh) params.set('live', '1');\n else params.delete('live');\n\n const next = params.toString();\n if (next !== searchParams.toString()) {\n setSearchParams(params, { replace: true });\n }\n }, [\n autoRefresh,\n dateFrom,\n dateTo,\n debouncedSearch,\n moduleFilter,\n searchParams,\n selectedLevels,\n setSearchParams,\n ]);\n\n const queryParams = useMemo(\n () => ({\n q: debouncedSearch || undefined,\n level: selectedLevels.size > 0 ? Array.from(selectedLevels) : undefined,\n module: moduleFilter || undefined,\n from: dateFrom || undefined,\n to: dateTo || undefined,\n limit: PAGE_LIMIT,\n }),\n [debouncedSearch, selectedLevels, moduleFilter, dateFrom, dateTo],\n );\n\n useEffect(() => {\n if (!hasToken) return;\n let cancelled = false;\n (async () => {\n setLoading(true);\n setError(null);\n setLogs([]);\n try {\n const result = await queryLogs({ ...queryParams, offset: 0 });\n if (cancelled) return;\n setLogs(result.logs);\n setHasMore(result.logs.length === PAGE_LIMIT);\n } catch (e) {\n if (!cancelled) {\n setError(e instanceof Error ? e.message : L.loadError);\n setLogs([]);\n setHasMore(false);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [hasToken, queryParams, L.loadError]);\n\n useEffect(() => {\n if (!hasToken) return;\n let cancelled = false;\n (async () => {\n try {\n const [mods, st, fileList] = await Promise.all([getLogModules(), getLogStats(), getLogFiles()]);\n if (!cancelled) {\n setModules(mods);\n setStats(st);\n setFiles(fileList);\n }\n } catch {\n /* optional */\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [hasToken]);\n\n useEffect(() => {\n if (!hasToken || !filesOpen) return;\n let cancelled = false;\n (async () => {\n try {\n const [list, dir] = await Promise.all([getLogFiles(), getLogDir()]);\n if (!cancelled) {\n setFiles(list);\n setLogDir(dir);\n }\n } catch {\n if (!cancelled) setFiles([]);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [hasToken, filesOpen]);\n\n useEffect(() => {\n if (!autoRefresh || !hasToken) return;\n const id = window.setInterval(() => {\n void (async () => {\n try {\n const result = await queryLogs({ ...queryParams, offset: 0 });\n setLogs(result.logs);\n setHasMore(result.logs.length === PAGE_LIMIT);\n const st = await getLogStats();\n setStats(st);\n } catch {\n /* ignore */\n }\n })();\n }, REFRESH_MS);\n return () => clearInterval(id);\n }, [autoRefresh, hasToken, queryParams]);\n\n useEffect(() => {\n if (!copiedDetail) return;\n const t = window.setTimeout(() => setCopiedDetail(null), 2000);\n return () => clearTimeout(t);\n }, [copiedDetail]);\n\n const clearFilters = () => {\n setSearchInput('');\n setDebouncedSearch('');\n setSelectedLevels(new Set());\n setModuleFilter('');\n setDateFrom('');\n setDateTo('');\n };\n\n const handleLevelSegment = (value: LevelSegmentValue) => {\n if (value === 'other') {\n setFiltersOpen(true);\n return;\n }\n setSelectedLevels(levelsForPreset(value));\n };\n\n const toggleDialogLevel = (level: LogLevel) => {\n setSelectedLevels((prev) => {\n const next = new Set(prev);\n if (next.has(level)) next.delete(level);\n else next.add(level);\n return next;\n });\n };\n\n const handleLoadMore = () => {\n if (loading || !hasMore) return;\n void (async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await queryLogs({ ...queryParams, offset: logs.length });\n setLogs((prev) => [...prev, ...result.logs]);\n setHasMore(result.logs.length === PAGE_LIMIT);\n } catch (e) {\n setError(e instanceof Error ? e.message : L.loadError);\n } finally {\n setLoading(false);\n }\n })();\n };\n\n const refreshAll = () => {\n void (async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await queryLogs({ ...queryParams, offset: 0 });\n setLogs(result.logs);\n setHasMore(result.logs.length === PAGE_LIMIT);\n const [st, fileList] = await Promise.all([getLogStats(), getLogFiles()]);\n setStats(st);\n setFiles(fileList);\n } catch (e) {\n setError(e instanceof Error ? e.message : L.loadError);\n } finally {\n setLoading(false);\n }\n })();\n };\n\n const statsLine = stats ? formatStatsLine(stats.byLevel ?? {}, L.levelNames) : '';\n\n if (!hasToken) {\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-10\">\n <div className=\"flex items-start gap-3 rounded-2xl border border-edge-subtle bg-surface-base p-6 dark:border-edge\">\n <Terminal className=\"mt-0.5 size-5 shrink-0 text-fg-subtle\" strokeWidth={1.75} aria-hidden />\n <div>\n <h1 className=\"text-base font-semibold tracking-tight text-fg\">{L.title}</h1>\n <p className=\"mt-1 text-sm leading-relaxed text-fg-muted\">{L.needToken}</p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-6\">\n <header className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <div\n className=\"flex size-10 shrink-0 items-center justify-center rounded-xl border border-edge-subtle bg-surface-base dark:border-edge\"\n aria-hidden\n >\n <Terminal className=\"size-5 text-fg-muted\" strokeWidth={1.75} />\n </div>\n <div className=\"min-w-0\">\n <h1 className=\"text-xl font-semibold tracking-tight text-fg\">{L.title}</h1>\n <p className=\"mt-0.5 text-sm leading-relaxed text-fg-muted\">{L.subtitle}</p>\n </div>\n </div>\n <div className=\"flex w-full shrink-0 flex-col gap-2 sm:w-auto sm:max-w-md sm:flex-row sm:items-center sm:justify-end\">\n <div className=\"w-full sm:w-48\">\n <SlidingSegmented\n aria-label={L.refreshModeAria}\n value={autoRefresh ? 'live' : 'paused'}\n onChange={(v) => setAutoRefresh(v === 'live')}\n options={[\n { value: 'paused', label: L.refreshManual },\n { value: 'live', label: L.refreshLive },\n ]}\n buttonClassName=\"h-8\"\n />\n </div>\n <div className=\"flex items-center gap-1 self-end sm:self-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0\"\n title={L.logFiles}\n aria-label={L.logFiles}\n onClick={() => setFilesOpen(true)}\n >\n <Folder className=\"size-4\" strokeWidth={1.75} />\n {files.length > 0 ? (\n <span className=\"rounded-full bg-surface-hover px-1.5 text-xs text-fg-muted\">{files.length}</span>\n ) : null}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0\"\n title={L.refresh}\n aria-label={L.refresh}\n onClick={refreshAll}\n >\n <RefreshCw\n className={cn(\n 'size-4 transition-transform duration-150 ease-out motion-reduce:transition-none',\n loading && 'animate-spin motion-reduce:animate-none',\n )}\n strokeWidth={1.75}\n />\n </Button>\n </div>\n </div>\n </header>\n\n {error ? (\n <div\n className=\"rounded-xl border border-edge bg-surface-base px-3 py-2 text-sm text-fg dark:border-edge\"\n role=\"alert\"\n >\n {error}\n </div>\n ) : null}\n\n {stats && statsLine ? (\n <div className=\"flex flex-wrap items-center gap-2\">\n <Popover.Root>\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n className=\"max-w-full truncate rounded-lg border border-transparent px-1 py-0.5 text-left text-xs leading-5 text-fg-subtle transition-colors duration-150 ease-out hover:border-edge-subtle hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel dark:hover:border-edge\"\n >\n <span className=\"font-medium text-fg-muted\">{L.statsRegion}</span>\n <span className=\"mx-1.5 text-fg-subtle\">·</span>\n <span className=\"tabular-nums\">{statsLine}</span>\n </button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n side=\"bottom\"\n align=\"start\"\n sideOffset={6}\n className={cn(\n 'z-50 w-[min(calc(100vw-2rem),20rem)] rounded-xl border border-edge bg-surface-panel p-3 shadow-popover outline-none',\n 'dark:border-edge',\n )}\n >\n <p className=\"text-xs font-medium text-fg\">{L.statsDetailTitle}</p>\n <p className=\"mt-1 text-xs leading-5 text-fg-muted\">{L.statsHint}</p>\n <ul className=\"mt-3 flex flex-col gap-1.5\" role=\"list\">\n {LOG_LEVELS.map((lv) => {\n const n = stats.byLevel?.[lv] ?? 0;\n if (n === 0) return null;\n return (\n <li\n key={lv}\n className=\"flex items-center justify-between gap-2 rounded-md border border-edge-subtle bg-surface-base px-2 py-1 text-xs dark:border-edge\"\n >\n <span className=\"font-medium capitalize text-fg\">{L.levelNames[lv]}</span>\n <span className=\"tabular-nums text-fg-muted\">{n}</span>\n </li>\n );\n })}\n </ul>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n </div>\n ) : null}\n\n <section className=\"flex flex-col gap-3\" aria-label={L.filters}>\n <div className=\"overflow-x-auto pb-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n <div className=\"min-w-[min(100%,36rem)]\">\n <SlidingSegmented<LevelSegmentValue>\n aria-label={L.levelPresetAria}\n value={levelSegment}\n onChange={handleLevelSegment}\n options={[\n { value: 'all', label: L.presetAll },\n { value: 'errors', label: L.presetErrors },\n { value: 'warnPlus', label: L.presetWarnPlus },\n { value: 'infoPlus', label: L.presetInfoPlus },\n { value: 'verbose', label: L.presetVerbose },\n { value: 'other', label: L.presetOther },\n ]}\n buttonClassName=\"h-8 px-1.5 text-[11px] sm:px-2 sm:text-xs\"\n />\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center\">\n <label className=\"relative min-w-0 flex-1 sm:min-w-[12rem]\">\n <span className=\"sr-only\">{L.searchPlaceholder}</span>\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-subtle\"\n strokeWidth={1.75}\n aria-hidden\n />\n <input\n type=\"search\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n placeholder={L.searchPlaceholder}\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(\n 'h-10 w-full rounded-md border border-edge bg-surface-panel py-0 pl-10 pr-3 text-sm leading-5 text-fg placeholder:text-fg-subtle dark:border-edge',\n bareInputFocusClass,\n )}\n />\n </label>\n\n <select\n id=\"log-module\"\n value={moduleFilter}\n onChange={(e) => setModuleFilter(e.target.value)}\n aria-label={L.module}\n title={L.module}\n className={cn(\n selectControlBaseClass,\n 'h-10 w-full min-w-0 rounded-md py-0 sm:w-[min(100%,14rem)] sm:shrink-0',\n )}\n >\n <option value=\"\">{L.allModules}</option>\n {modules.map((mod) => (\n <option key={mod} value={mod}>\n {mod}\n </option>\n ))}\n </select>\n\n <div className=\"flex min-w-0 shrink-0 items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-10 min-h-[44px] gap-2 rounded-md sm:min-h-10\"\n onClick={() => setFiltersOpen(true)}\n >\n <ListFilter className=\"size-4\" strokeWidth={1.75} />\n {L.filtersMore}\n {activeFilterCount > 0 ? (\n <span className=\"rounded-md bg-surface-hover px-1.5 text-xs tabular-nums text-fg-muted\">\n {activeFilterCount}\n </span>\n ) : null}\n </Button>\n {hasActiveFilters ? (\n <Button type=\"button\" variant=\"ghost\" className=\"h-10 min-h-[44px] gap-1 sm:min-h-10\" onClick={clearFilters}>\n <X className=\"size-4\" strokeWidth={1.75} />\n {L.clear}\n </Button>\n ) : null}\n </div>\n </div>\n\n {autoRefresh ? <p className=\"text-xs leading-5 text-fg-subtle\">{L.liveHint}</p> : null}\n </section>\n\n {loading && logs.length === 0 ? (\n <div\n className=\"divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel dark:divide-edge dark:border-edge\"\n aria-busy=\"true\"\n >\n {Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"flex gap-3 px-3 py-2.5\">\n <div className=\"h-4 w-16 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n <div className=\"h-4 w-12 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n <div className=\"h-4 w-20 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n <div className=\"h-4 min-w-0 flex-1 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n </div>\n ))}\n </div>\n ) : null}\n\n {!loading && logs.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-2 rounded-xl border border-edge-subtle bg-surface-base py-16 text-center dark:border-edge\">\n <FileText className=\"size-12 text-fg-subtle\" strokeWidth={1.5} aria-hidden />\n <h2 className=\"text-base font-semibold tracking-tight text-fg\">{L.noLogs}</h2>\n <p className=\"max-w-sm text-sm leading-relaxed text-fg-muted\">{L.noLogsDescription}</p>\n <Button type=\"button\" variant=\"secondary\" className=\"mt-4 gap-2\" onClick={refreshAll}>\n <RefreshCw className=\"size-4\" strokeWidth={1.75} />\n {L.refresh}\n </Button>\n </div>\n ) : null}\n\n {logs.length > 0 ? (\n <div className=\"flex flex-col gap-2\">\n <p className=\"text-xs leading-5 text-fg-muted\">\n {interpolate(L.showingCount, { count: String(logs.length) })}\n {hasMore ? <span className=\"text-fg-subtle\"> · {L.moreAvailable}</span> : null}\n </p>\n <ul\n className=\"divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel font-mono text-sm leading-6 dark:divide-edge dark:border-edge\"\n role=\"list\"\n >\n {logs.map((log, idx) => {\n const lv = log.level ?? 'info';\n const rid = typeof log.requestId === 'string' ? log.requestId.trim() : '';\n return (\n <li key={`${log.timestamp}-${idx}`}>\n <button\n type=\"button\"\n onClick={() => setSelectedLog(log)}\n className={cn(\n 'flex w-full min-w-0 items-center gap-3 px-3 py-2.5 text-left transition-colors duration-150 ease-out',\n 'hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel',\n )}\n >\n <span className=\"w-[5.25rem] shrink-0 tabular-nums text-fg-subtle\">\n {formatTimeCompact(log.timestamp)}\n </span>\n <span className=\"w-[4.5rem] shrink-0 truncate text-fg-muted\" title={lv}>\n {levelLabel(lv)}\n </span>\n <span\n className=\"w-[4.5rem] shrink-0 truncate text-fg-subtle sm:w-[5.25rem]\"\n title={rid ? `${L.requestId}: ${rid}` : undefined}\n >\n {rid ? requestIdPreview(rid) : '—'}\n </span>\n <span\n className=\"hidden max-w-[7rem] shrink-0 truncate text-fg-muted lg:inline\"\n title={moduleLabel(log)}\n >\n {moduleLabel(log)}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-fg\">{messagePreview(log)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n {hasMore ? (\n <div className=\"flex justify-center pt-1\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"gap-2\"\n disabled={loading}\n onClick={handleLoadMore}\n >\n {loading ? (\n <RefreshCw className=\"size-4 animate-spin motion-reduce:animate-none\" strokeWidth={1.75} />\n ) : (\n <ChevronDown className=\"size-4\" strokeWidth={1.75} />\n )}\n {L.loadMore}\n </Button>\n </div>\n ) : null}\n </div>\n ) : null}\n\n <Dialog.Root open={filtersOpen} onOpenChange={setFiltersOpen}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-50 bg-scrim\" />\n <Dialog.Content\n className={cn(\n 'xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,90vh)] w-[min(100%-2rem,22rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none',\n 'dark:border-edge',\n )}\n aria-describedby=\"log-filters-desc\"\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge\">\n <Dialog.Title className=\"text-base font-semibold tracking-tight text-fg\">{L.filtersDialogTitle}</Dialog.Title>\n <Dialog.Close asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 shrink-0 p-0\" aria-label={L.close}>\n <X className=\"size-5\" strokeWidth={1.75} />\n </Button>\n </Dialog.Close>\n </div>\n <div id=\"log-filters-desc\" className=\"sr-only\">\n {L.filtersDialogDesc}\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-4 py-4\">\n <p className=\"text-xs font-medium text-fg-muted\">{L.timeRange}</p>\n <div className=\"mt-2 flex flex-col gap-3\">\n <div>\n <label htmlFor=\"log-from-d\" className=\"mb-1 block text-xs text-fg-muted\">\n {L.from}\n </label>\n <input\n id=\"log-from-d\"\n type=\"datetime-local\"\n value={dateFrom}\n onChange={(e) => setDateFrom(e.target.value)}\n className=\"w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge\"\n />\n </div>\n <div>\n <label htmlFor=\"log-to-d\" className=\"mb-1 block text-xs text-fg-muted\">\n {L.to}\n </label>\n <input\n id=\"log-to-d\"\n type=\"datetime-local\"\n value={dateTo}\n onChange={(e) => setDateTo(e.target.value)}\n className=\"w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge\"\n />\n </div>\n </div>\n <p className=\"mt-6 text-xs font-medium text-fg-muted\">{L.levelCustom}</p>\n <p className=\"mt-1 text-xs leading-5 text-fg-subtle\">{L.levelCustomHint}</p>\n <div className=\"mt-3 flex flex-wrap gap-2\" role=\"group\" aria-label={L.level}>\n {LOG_LEVELS.map((level) => {\n const active = selectedLevels.has(level);\n return (\n <button\n key={level}\n type=\"button\"\n className={cn(\n 'rounded-full border px-3 py-1.5 text-xs font-medium capitalize transition-[color,background-color,border-color] duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel',\n active\n ? 'border-edge bg-surface-active text-fg dark:border-edge'\n : 'border-edge-subtle bg-surface-base text-fg-muted hover:bg-surface-hover dark:border-edge',\n )}\n onClick={() => toggleDialogLevel(level)}\n >\n {L.levelNames[level]}\n </button>\n );\n })}\n </div>\n </div>\n <div className=\"shrink-0 border-t border-edge-subtle px-4 py-3 dark:border-edge\">\n <Button type=\"button\" className=\"w-full rounded-xl\" onClick={() => setFiltersOpen(false)}>\n {L.filtersDone}\n </Button>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n\n <Dialog.Root open={selectedLog !== null} onOpenChange={(o) => !o && setSelectedLog(null)}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-50 bg-scrim\" />\n <Dialog.Content\n className={cn(\n 'xopc-drawer-right fixed right-0 top-0 z-50 flex h-full w-full max-w-lg flex-col border-l border-edge bg-surface-panel shadow-popover outline-none',\n 'dark:border-edge',\n )}\n aria-describedby={undefined}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge\">\n <Dialog.Title className=\"text-base font-semibold tracking-tight text-fg\">{L.details}</Dialog.Title>\n <div className=\"flex min-w-0 items-center gap-1\">\n {selectedLog ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 shrink-0 gap-1 px-2 text-xs\"\n onClick={() => {\n const text = typeof selectedLog.message === 'string' ? selectedLog.message : '';\n void navigator.clipboard.writeText(text).then(() => setCopiedDetail('message'));\n }}\n >\n <ClipboardCopy className=\"size-3.5 shrink-0\" strokeWidth={1.75} />\n <span className=\"hidden sm:inline\">{copiedDetail === 'message' ? L.copied : L.copyMessage}</span>\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 shrink-0 gap-1 px-2 text-xs\"\n onClick={() => {\n void navigator.clipboard\n .writeText(JSON.stringify(selectedLog, null, 2))\n .then(() => setCopiedDetail('json'));\n }}\n >\n <ClipboardCopy className=\"size-3.5 shrink-0\" strokeWidth={1.75} />\n <span className=\"hidden sm:inline\">{copiedDetail === 'json' ? L.copied : L.copyJson}</span>\n </Button>\n </>\n ) : null}\n <Dialog.Close asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 shrink-0 p-0\" aria-label={L.close}>\n <X className=\"size-5\" strokeWidth={1.75} />\n </Button>\n </Dialog.Close>\n </div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-4 py-4 font-mono text-sm leading-relaxed\">\n {selectedLog ? (\n <LogDetailBody\n log={selectedLog}\n labels={{\n time: L.time,\n level: L.level,\n module: L.module,\n message: L.message,\n metadata: L.metadata,\n requestId: L.requestId,\n sessionId: L.sessionId,\n }}\n />\n ) : null}\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n\n <Dialog.Root open={filesOpen} onOpenChange={setFilesOpen}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-50 bg-scrim\" />\n <Dialog.Content\n className={cn(\n 'xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,85vh)] w-[min(100%-2rem,24rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none',\n 'dark:border-edge',\n )}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge\">\n <Dialog.Title className=\"flex items-center gap-2 text-base font-semibold tracking-tight text-fg\">\n <Folder className=\"size-4 text-fg-muted\" strokeWidth={1.75} />\n {L.logFiles}\n </Dialog.Title>\n <Dialog.Close asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 shrink-0 p-0\" aria-label={L.close}>\n <X className=\"size-5\" strokeWidth={1.75} />\n </Button>\n </Dialog.Close>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-4 py-3\">\n {files.length === 0 ? (\n <p className=\"text-sm text-fg-muted\">{L.filesEmpty}</p>\n ) : (\n <ul className=\"flex flex-col gap-2\" role=\"list\">\n {files.map((f) => (\n <li\n key={f.name}\n className=\"flex flex-col gap-1 rounded-lg border border-edge-subtle bg-surface-base px-3 py-2 dark:border-edge\"\n >\n <span className=\"break-all font-mono text-xs text-fg\">{f.name}</span>\n <span className=\"flex flex-wrap gap-x-2 text-xs text-fg-subtle\">\n <span>{formatFileSize(f.size)}</span>\n <span>{formatTimestampFull(f.modified)}</span>\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n {logDir ? (\n <div className=\"shrink-0 border-t border-edge-subtle px-4 py-2 text-xs text-fg-subtle dark:border-edge\">\n <span className=\"font-medium text-fg-muted\">{L.logDir}: </span>\n <code className=\"break-all text-fg-subtle\">{logDir}</code>\n </div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n </div>\n );\n}\n\nfunction LogDetailBody({\n log,\n labels,\n}: {\n log: LogEntry;\n labels: {\n time: string;\n level: string;\n module: string;\n message: string;\n metadata: string;\n requestId: string;\n sessionId: string;\n };\n}) {\n const lv = log.level ?? 'info';\n const rid = typeof log.requestId === 'string' ? log.requestId : '';\n const sid = typeof log.sessionId === 'string' ? log.sessionId : '';\n return (\n <div className=\"flex flex-col gap-8\">\n <div>\n <span className=\"text-xs font-sans font-medium text-fg-muted\">{labels.message}</span>\n <pre className=\"mt-2 whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge\">\n {log.message || '—'}\n </pre>\n </div>\n <div className=\"grid grid-cols-[5.5rem_1fr] gap-x-3 gap-y-2 text-xs\">\n <span className=\"font-sans text-fg-muted\">{labels.time}</span>\n <code className=\"break-all text-fg\">{log.timestamp}</code>\n <span className=\"font-sans text-fg-muted\">{labels.level}</span>\n <span className=\"text-fg\">{levelLabel(lv)}</span>\n <span className=\"font-sans text-fg-muted\">{labels.module}</span>\n <code className=\"break-all text-fg\">{moduleLabel(log)}</code>\n {rid ? (\n <>\n <span className=\"font-sans text-fg-muted\">{labels.requestId}</span>\n <code className=\"break-all text-fg\">{rid}</code>\n </>\n ) : null}\n {sid ? (\n <>\n <span className=\"font-sans text-fg-muted\">{labels.sessionId}</span>\n <code className=\"break-all text-fg\">{sid}</code>\n </>\n ) : null}\n </div>\n {log.meta && Object.keys(log.meta).length > 0 ? (\n <div>\n <span className=\"text-xs font-sans font-medium text-fg-muted\">{labels.metadata}</span>\n <pre className=\"mt-2 overflow-x-auto whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge\">\n {JSON.stringify(log.meta, null, 2)}\n </pre>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"logs-page-Du6UoHCK.js","names":[],"sources":["../../../../../web/src/features/logs/log-api.ts","../../../../../web/src/features/logs/log.types.ts","../../../../../web/src/features/logs/logs-page.tsx"],"sourcesContent":["import { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\n\nimport type { LogEntry, LogFile, LogQuery, LogStats } from '@/features/logs/log.types';\n\nfunction buildQueryString(query?: LogQuery): string {\n const params = new URLSearchParams();\n if (!query) return '';\n if (query.level?.length) params.set('level', query.level.join(','));\n if (query.from) params.set('from', query.from);\n if (query.to) params.set('to', query.to);\n if (query.q) params.set('q', query.q);\n if (query.module) params.set('module', query.module);\n if (query.limit != null) params.set('limit', String(query.limit));\n if (query.offset != null) params.set('offset', String(query.offset));\n const qs = params.toString();\n return qs ? `?${qs}` : '';\n}\n\nexport async function queryLogs(query?: LogQuery): Promise<{ logs: LogEntry[]; count: number }> {\n return fetchJson<{ logs: LogEntry[]; count: number }>(apiUrl(`/api/logs${buildQueryString(query)}`));\n}\n\nexport async function getLogFiles(): Promise<LogFile[]> {\n const result = await fetchJson<{ files: LogFile[] }>(apiUrl('/api/logs/files'));\n return result.files ?? [];\n}\n\nexport async function getLogModules(): Promise<string[]> {\n const result = await fetchJson<{ modules: string[] }>(apiUrl('/api/logs/modules'));\n return result.modules ?? [];\n}\n\nexport async function getLogStats(): Promise<LogStats> {\n const raw = await fetchJson<Partial<LogStats>>(apiUrl('/api/logs/stats'));\n return { byLevel: raw.byLevel ?? {} };\n}\n\nexport async function getLogDir(): Promise<string> {\n const result = await fetchJson<{ dir: string }>(apiUrl('/api/logs/dir'));\n return result.dir ?? '';\n}\n","export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\nexport const LOG_LEVELS: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n\nexport interface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n module?: string;\n prefix?: string;\n service?: string;\n extension?: string;\n requestId?: string;\n sessionId?: string;\n userId?: string;\n meta?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface LogQuery {\n level?: string[];\n from?: string;\n to?: string;\n q?: string;\n module?: string;\n limit?: number;\n offset?: number;\n}\n\nexport interface LogFile {\n name: string;\n size: number;\n modified: string;\n}\n\nexport interface LogStats {\n byLevel: Partial<Record<LogLevel | 'silent', number>>;\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport * as Popover from '@radix-ui/react-popover';\nimport {\n ChevronDown,\n ClipboardCopy,\n FileText,\n Folder,\n ListFilter,\n RefreshCw,\n Search,\n Terminal,\n X,\n} from 'lucide-react';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useSearchParams } from 'react-router-dom';\n\nimport { SlidingSegmented } from '@/components/ui/sliding-segmented';\nimport { Button } from '@/components/ui/button';\nimport { bareInputFocusClass, selectControlBaseClass } from '@/lib/form-field-width';\nimport { cn } from '@/lib/cn';\nimport {\n getLogDir,\n getLogFiles,\n getLogModules,\n getLogStats,\n queryLogs,\n} from '@/features/logs/log-api';\nimport type { LogEntry, LogFile, LogLevel } from '@/features/logs/log.types';\nimport { LOG_LEVELS } from '@/features/logs/log.types';\nimport { messages } from '@/i18n/messages';\nimport { useGatewayStore } from '@/stores/gateway-store';\nimport { useLocaleStore } from '@/stores/locale-store';\n\nconst PAGE_LIMIT = 50;\nconst REFRESH_MS = 5000;\nconst LOG_LEVEL_SET = new Set<LogLevel>(LOG_LEVELS);\n\ntype LevelPreset = 'all' | 'errors' | 'warnPlus' | 'infoPlus' | 'verbose' | 'custom';\ntype LevelSegmentValue = Exclude<LevelPreset, 'custom'> | 'other';\n\nconst PRESET_ERRORS: LogLevel[] = ['error', 'fatal'];\nconst PRESET_WARN_PLUS: LogLevel[] = ['warn', 'error', 'fatal'];\nconst PRESET_INFO_PLUS: LogLevel[] = ['info', 'warn', 'error', 'fatal'];\n\nfunction parseLogLevelsParam(raw: string | null): Set<LogLevel> {\n if (!raw) return new Set<LogLevel>();\n const out = new Set<LogLevel>();\n for (const part of raw.split(',')) {\n const level = part.trim() as LogLevel;\n if (LOG_LEVEL_SET.has(level)) out.add(level);\n }\n return out;\n}\n\nfunction isSameLogLevelSet(a: Set<LogLevel>, b: Set<LogLevel>): boolean {\n if (a.size !== b.size) return false;\n for (const level of a) {\n if (!b.has(level)) return false;\n }\n return true;\n}\n\nfunction setMatchesLevels(s: Set<LogLevel>, levels: readonly LogLevel[]): boolean {\n if (s.size !== levels.length) return false;\n return levels.every((l) => s.has(l));\n}\n\nfunction derivePreset(levels: Set<LogLevel>): LevelPreset {\n if (levels.size === 0) return 'all';\n if (setMatchesLevels(levels, PRESET_ERRORS)) return 'errors';\n if (setMatchesLevels(levels, PRESET_WARN_PLUS)) return 'warnPlus';\n if (setMatchesLevels(levels, PRESET_INFO_PLUS)) return 'infoPlus';\n if (levels.size === LOG_LEVELS.length && LOG_LEVELS.every((l) => levels.has(l))) return 'verbose';\n return 'custom';\n}\n\nfunction segmentValueFromLevels(levels: Set<LogLevel>): LevelSegmentValue {\n const p = derivePreset(levels);\n return p === 'custom' ? 'other' : p;\n}\n\nfunction levelsForPreset(preset: Exclude<LevelPreset, 'custom'>): Set<LogLevel> {\n switch (preset) {\n case 'all':\n return new Set();\n case 'errors':\n return new Set(PRESET_ERRORS);\n case 'warnPlus':\n return new Set(PRESET_WARN_PLUS);\n case 'infoPlus':\n return new Set(PRESET_INFO_PLUS);\n case 'verbose':\n return new Set(LOG_LEVELS);\n }\n}\n\nfunction interpolate(template: string, params: Record<string, string | number>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) => String(params[key] ?? ''));\n}\n\nfunction moduleLabel(log: LogEntry): string {\n return String(log.module || log.prefix || log.service || log.extension || '—');\n}\n\nfunction messagePreview(log: LogEntry): string {\n if (typeof log.message === 'string' && log.message) return log.message;\n try {\n return JSON.stringify(log);\n } catch {\n return '';\n }\n}\n\nfunction formatTimeCompact(timestamp: string): string {\n try {\n const date = new Date(timestamp);\n return date.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n });\n } catch {\n return timestamp;\n }\n}\n\nfunction formatTimestampFull(timestamp: string): string {\n try {\n return new Date(timestamp).toLocaleString();\n } catch {\n return timestamp;\n }\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction requestIdPreview(id: string): string {\n const t = id.trim();\n if (t.length <= 10) return t;\n return `${t.slice(0, 8)}…`;\n}\n\nfunction levelLabel(level: string): string {\n return String(level).toLowerCase();\n}\n\nfunction formatStatsLine(\n byLevel: Partial<Record<LogLevel | 'silent', number>>,\n labels: Record<LogLevel, string>,\n): string {\n const parts: string[] = [];\n for (const lv of LOG_LEVELS) {\n const n = byLevel[lv] ?? 0;\n if (n > 0) parts.push(`${labels[lv]} ${n}`);\n }\n return parts.join(' · ');\n}\n\nexport function LogsPage() {\n const language = useLocaleStore((s) => s.language);\n const m = messages(language);\n const L = m.logs;\n const token = useGatewayStore((st) => st.token);\n const hasToken = Boolean(token);\n const [searchParams, setSearchParams] = useSearchParams();\n\n const initialSearch = searchParams.get('q') ?? '';\n const initialLevels = parseLogLevelsParam(searchParams.get('level'));\n const initialModule = searchParams.get('module') ?? '';\n const initialFrom = searchParams.get('from') ?? '';\n const initialTo = searchParams.get('to') ?? '';\n const initialAutoRefresh = searchParams.get('live') === '1';\n\n const [logs, setLogs] = useState<LogEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [hasMore, setHasMore] = useState(false);\n\n const [searchInput, setSearchInput] = useState(initialSearch);\n const [debouncedSearch, setDebouncedSearch] = useState(initialSearch.trim());\n const [selectedLevels, setSelectedLevels] = useState<Set<LogLevel>>(initialLevels);\n const [moduleFilter, setModuleFilter] = useState(initialModule);\n const [dateFrom, setDateFrom] = useState(initialFrom);\n const [dateTo, setDateTo] = useState(initialTo);\n\n const [modules, setModules] = useState<string[]>([]);\n const [files, setFiles] = useState<LogFile[]>([]);\n const [stats, setStats] = useState<Awaited<ReturnType<typeof getLogStats>> | null>(null);\n\n const [selectedLog, setSelectedLog] = useState<LogEntry | null>(null);\n const [filesOpen, setFilesOpen] = useState(false);\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [logDir, setLogDir] = useState<string | null>(null);\n const [autoRefresh, setAutoRefresh] = useState(initialAutoRefresh);\n const [copiedDetail, setCopiedDetail] = useState<'json' | 'message' | null>(null);\n\n const levelSegment = useMemo(() => segmentValueFromLevels(selectedLevels), [selectedLevels]);\n\n const hasActiveFilters =\n debouncedSearch.length > 0 ||\n selectedLevels.size > 0 ||\n Boolean(moduleFilter) ||\n Boolean(dateFrom) ||\n Boolean(dateTo);\n\n const activeFilterCount =\n (debouncedSearch.length > 0 ? 1 : 0) +\n (selectedLevels.size > 0 ? 1 : 0) +\n (moduleFilter ? 1 : 0) +\n (dateFrom || dateTo ? 1 : 0);\n\n useEffect(() => {\n const t = setTimeout(() => setDebouncedSearch(searchInput.trim()), 300);\n return () => clearTimeout(t);\n }, [searchInput]);\n\n useEffect(() => {\n const nextQ = searchParams.get('q') ?? '';\n const nextModule = searchParams.get('module') ?? '';\n const nextFrom = searchParams.get('from') ?? '';\n const nextTo = searchParams.get('to') ?? '';\n const nextAutoRefresh = searchParams.get('live') === '1';\n const nextLevels = parseLogLevelsParam(searchParams.get('level'));\n const nextDebouncedQ = nextQ.trim();\n\n setSearchInput((prev) => (prev === nextQ ? prev : nextQ));\n setDebouncedSearch((prev) => (prev === nextDebouncedQ ? prev : nextDebouncedQ));\n setSelectedLevels((prev) => (isSameLogLevelSet(nextLevels, prev) ? prev : nextLevels));\n setModuleFilter((prev) => (prev === nextModule ? prev : nextModule));\n setDateFrom((prev) => (prev === nextFrom ? prev : nextFrom));\n setDateTo((prev) => (prev === nextTo ? prev : nextTo));\n setAutoRefresh((prev) => (prev === nextAutoRefresh ? prev : nextAutoRefresh));\n }, [searchParams]);\n\n useEffect(() => {\n const params = new URLSearchParams(searchParams);\n const nextQ = debouncedSearch.trim();\n if (nextQ) params.set('q', nextQ);\n else params.delete('q');\n\n if (selectedLevels.size > 0) {\n params.set('level', Array.from(selectedLevels).sort().join(','));\n } else {\n params.delete('level');\n }\n\n if (moduleFilter) params.set('module', moduleFilter);\n else params.delete('module');\n if (dateFrom) params.set('from', dateFrom);\n else params.delete('from');\n if (dateTo) params.set('to', dateTo);\n else params.delete('to');\n if (autoRefresh) params.set('live', '1');\n else params.delete('live');\n\n const next = params.toString();\n if (next !== searchParams.toString()) {\n setSearchParams(params, { replace: true });\n }\n }, [\n autoRefresh,\n dateFrom,\n dateTo,\n debouncedSearch,\n moduleFilter,\n searchParams,\n selectedLevels,\n setSearchParams,\n ]);\n\n const queryParams = useMemo(\n () => ({\n q: debouncedSearch || undefined,\n level: selectedLevels.size > 0 ? Array.from(selectedLevels) : undefined,\n module: moduleFilter || undefined,\n from: dateFrom || undefined,\n to: dateTo || undefined,\n limit: PAGE_LIMIT,\n }),\n [debouncedSearch, selectedLevels, moduleFilter, dateFrom, dateTo],\n );\n\n useEffect(() => {\n if (!hasToken) return;\n let cancelled = false;\n (async () => {\n setLoading(true);\n setError(null);\n setLogs([]);\n try {\n const result = await queryLogs({ ...queryParams, offset: 0 });\n if (cancelled) return;\n setLogs(result.logs);\n setHasMore(result.logs.length === PAGE_LIMIT);\n } catch (e) {\n if (!cancelled) {\n setError(e instanceof Error ? e.message : L.loadError);\n setLogs([]);\n setHasMore(false);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [hasToken, queryParams, L.loadError]);\n\n useEffect(() => {\n if (!hasToken) return;\n let cancelled = false;\n (async () => {\n try {\n const [mods, st, fileList] = await Promise.all([getLogModules(), getLogStats(), getLogFiles()]);\n if (!cancelled) {\n setModules(mods);\n setStats(st);\n setFiles(fileList);\n }\n } catch {\n /* optional */\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [hasToken]);\n\n useEffect(() => {\n if (!hasToken || !filesOpen) return;\n let cancelled = false;\n (async () => {\n try {\n const [list, dir] = await Promise.all([getLogFiles(), getLogDir()]);\n if (!cancelled) {\n setFiles(list);\n setLogDir(dir);\n }\n } catch {\n if (!cancelled) setFiles([]);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [hasToken, filesOpen]);\n\n useEffect(() => {\n if (!autoRefresh || !hasToken) return;\n const id = window.setInterval(() => {\n void (async () => {\n try {\n const result = await queryLogs({ ...queryParams, offset: 0 });\n setLogs(result.logs);\n setHasMore(result.logs.length === PAGE_LIMIT);\n const st = await getLogStats();\n setStats(st);\n } catch {\n /* ignore */\n }\n })();\n }, REFRESH_MS);\n return () => clearInterval(id);\n }, [autoRefresh, hasToken, queryParams]);\n\n useEffect(() => {\n if (!copiedDetail) return;\n const t = window.setTimeout(() => setCopiedDetail(null), 2000);\n return () => clearTimeout(t);\n }, [copiedDetail]);\n\n const clearFilters = () => {\n setSearchInput('');\n setDebouncedSearch('');\n setSelectedLevels(new Set());\n setModuleFilter('');\n setDateFrom('');\n setDateTo('');\n };\n\n const handleLevelSegment = (value: LevelSegmentValue) => {\n if (value === 'other') {\n setFiltersOpen(true);\n return;\n }\n setSelectedLevels(levelsForPreset(value));\n };\n\n const toggleDialogLevel = (level: LogLevel) => {\n setSelectedLevels((prev) => {\n const next = new Set(prev);\n if (next.has(level)) next.delete(level);\n else next.add(level);\n return next;\n });\n };\n\n const handleLoadMore = () => {\n if (loading || !hasMore) return;\n void (async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await queryLogs({ ...queryParams, offset: logs.length });\n setLogs((prev) => [...prev, ...result.logs]);\n setHasMore(result.logs.length === PAGE_LIMIT);\n } catch (e) {\n setError(e instanceof Error ? e.message : L.loadError);\n } finally {\n setLoading(false);\n }\n })();\n };\n\n const refreshAll = () => {\n void (async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await queryLogs({ ...queryParams, offset: 0 });\n setLogs(result.logs);\n setHasMore(result.logs.length === PAGE_LIMIT);\n const [st, fileList] = await Promise.all([getLogStats(), getLogFiles()]);\n setStats(st);\n setFiles(fileList);\n } catch (e) {\n setError(e instanceof Error ? e.message : L.loadError);\n } finally {\n setLoading(false);\n }\n })();\n };\n\n const statsLine = stats ? formatStatsLine(stats.byLevel ?? {}, L.levelNames) : '';\n\n if (!hasToken) {\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-3 px-4 py-10\">\n <div className=\"flex items-start gap-3 rounded-2xl border border-edge-subtle bg-surface-base p-6 dark:border-edge\">\n <Terminal className=\"mt-0.5 size-5 shrink-0 text-fg-subtle\" strokeWidth={1.75} aria-hidden />\n <div>\n <h1 className=\"text-base font-semibold tracking-tight text-fg\">{L.title}</h1>\n <p className=\"mt-1 text-sm leading-relaxed text-fg-muted\">{L.needToken}</p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"mx-auto flex w-full max-w-app-main flex-col gap-6 px-4 py-6\">\n <header className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <div\n className=\"flex size-10 shrink-0 items-center justify-center rounded-xl border border-edge-subtle bg-surface-base dark:border-edge\"\n aria-hidden\n >\n <Terminal className=\"size-5 text-fg-muted\" strokeWidth={1.75} />\n </div>\n <div className=\"min-w-0\">\n <h1 className=\"text-xl font-semibold tracking-tight text-fg\">{L.title}</h1>\n <p className=\"mt-0.5 text-sm leading-relaxed text-fg-muted\">{L.subtitle}</p>\n </div>\n </div>\n <div className=\"flex w-full shrink-0 flex-col gap-2 sm:w-auto sm:max-w-md sm:flex-row sm:items-center sm:justify-end\">\n <div className=\"w-full sm:w-48\">\n <SlidingSegmented\n aria-label={L.refreshModeAria}\n value={autoRefresh ? 'live' : 'paused'}\n onChange={(v) => setAutoRefresh(v === 'live')}\n options={[\n { value: 'paused', label: L.refreshManual },\n { value: 'live', label: L.refreshLive },\n ]}\n buttonClassName=\"h-8\"\n />\n </div>\n <div className=\"flex items-center gap-1 self-end sm:self-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0\"\n title={L.logFiles}\n aria-label={L.logFiles}\n onClick={() => setFilesOpen(true)}\n >\n <Folder className=\"size-4\" strokeWidth={1.75} />\n {files.length > 0 ? (\n <span className=\"rounded-full bg-surface-hover px-1.5 text-xs text-fg-muted\">{files.length}</span>\n ) : null}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 min-h-[44px] min-w-[44px] px-2 sm:min-h-9 sm:min-w-0\"\n title={L.refresh}\n aria-label={L.refresh}\n onClick={refreshAll}\n >\n <RefreshCw\n className={cn(\n 'size-4 transition-transform duration-150 ease-out motion-reduce:transition-none',\n loading && 'animate-spin motion-reduce:animate-none',\n )}\n strokeWidth={1.75}\n />\n </Button>\n </div>\n </div>\n </header>\n\n {error ? (\n <div\n className=\"rounded-xl border border-edge bg-surface-base px-3 py-2 text-sm text-fg dark:border-edge\"\n role=\"alert\"\n >\n {error}\n </div>\n ) : null}\n\n {stats && statsLine ? (\n <div className=\"flex flex-wrap items-center gap-2\">\n <Popover.Root>\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n className=\"max-w-full truncate rounded-lg border border-transparent px-1 py-0.5 text-left text-xs leading-5 text-fg-subtle transition-colors duration-150 ease-out hover:border-edge-subtle hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel dark:hover:border-edge\"\n >\n <span className=\"font-medium text-fg-muted\">{L.statsRegion}</span>\n <span className=\"mx-1.5 text-fg-subtle\">·</span>\n <span className=\"tabular-nums\">{statsLine}</span>\n </button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n side=\"bottom\"\n align=\"start\"\n sideOffset={6}\n className={cn(\n 'z-50 w-[min(calc(100vw-2rem),20rem)] rounded-xl border border-edge bg-surface-panel p-3 shadow-popover outline-none',\n 'dark:border-edge',\n )}\n >\n <p className=\"text-xs font-medium text-fg\">{L.statsDetailTitle}</p>\n <p className=\"mt-1 text-xs leading-5 text-fg-muted\">{L.statsHint}</p>\n <ul className=\"mt-3 flex flex-col gap-1.5\" role=\"list\">\n {LOG_LEVELS.map((lv) => {\n const n = stats.byLevel?.[lv] ?? 0;\n if (n === 0) return null;\n return (\n <li\n key={lv}\n className=\"flex items-center justify-between gap-2 rounded-md border border-edge-subtle bg-surface-base px-2 py-1 text-xs dark:border-edge\"\n >\n <span className=\"font-medium capitalize text-fg\">{L.levelNames[lv]}</span>\n <span className=\"tabular-nums text-fg-muted\">{n}</span>\n </li>\n );\n })}\n </ul>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n </div>\n ) : null}\n\n <section className=\"flex flex-col gap-3\" aria-label={L.filters}>\n <div className=\"overflow-x-auto pb-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\">\n <div className=\"min-w-[min(100%,36rem)]\">\n <SlidingSegmented<LevelSegmentValue>\n aria-label={L.levelPresetAria}\n value={levelSegment}\n onChange={handleLevelSegment}\n options={[\n { value: 'all', label: L.presetAll },\n { value: 'errors', label: L.presetErrors },\n { value: 'warnPlus', label: L.presetWarnPlus },\n { value: 'infoPlus', label: L.presetInfoPlus },\n { value: 'verbose', label: L.presetVerbose },\n { value: 'other', label: L.presetOther },\n ]}\n buttonClassName=\"h-8 px-1.5 text-[11px] sm:px-2 sm:text-xs\"\n />\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center\">\n <label className=\"relative min-w-0 flex-1 sm:min-w-[12rem]\">\n <span className=\"sr-only\">{L.searchPlaceholder}</span>\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-subtle\"\n strokeWidth={1.75}\n aria-hidden\n />\n <input\n type=\"search\"\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n placeholder={L.searchPlaceholder}\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(\n 'h-10 w-full rounded-md border border-edge bg-surface-panel py-0 pl-10 pr-3 text-sm leading-5 text-fg placeholder:text-fg-subtle dark:border-edge',\n bareInputFocusClass,\n )}\n />\n </label>\n\n <select\n id=\"log-module\"\n value={moduleFilter}\n onChange={(e) => setModuleFilter(e.target.value)}\n aria-label={L.module}\n title={L.module}\n className={cn(\n selectControlBaseClass,\n 'h-10 w-full min-w-0 rounded-md py-0 sm:w-[min(100%,14rem)] sm:shrink-0',\n )}\n >\n <option value=\"\">{L.allModules}</option>\n {modules.map((mod) => (\n <option key={mod} value={mod}>\n {mod}\n </option>\n ))}\n </select>\n\n <div className=\"flex min-w-0 shrink-0 items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-10 min-h-[44px] gap-2 rounded-md sm:min-h-10\"\n onClick={() => setFiltersOpen(true)}\n >\n <ListFilter className=\"size-4\" strokeWidth={1.75} />\n {L.filtersMore}\n {activeFilterCount > 0 ? (\n <span className=\"rounded-md bg-surface-hover px-1.5 text-xs tabular-nums text-fg-muted\">\n {activeFilterCount}\n </span>\n ) : null}\n </Button>\n {hasActiveFilters ? (\n <Button type=\"button\" variant=\"ghost\" className=\"h-10 min-h-[44px] gap-1 sm:min-h-10\" onClick={clearFilters}>\n <X className=\"size-4\" strokeWidth={1.75} />\n {L.clear}\n </Button>\n ) : null}\n </div>\n </div>\n\n {autoRefresh ? <p className=\"text-xs leading-5 text-fg-subtle\">{L.liveHint}</p> : null}\n </section>\n\n {loading && logs.length === 0 ? (\n <div\n className=\"divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel dark:divide-edge dark:border-edge\"\n aria-busy=\"true\"\n >\n {Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"flex gap-3 px-3 py-2.5\">\n <div className=\"h-4 w-16 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n <div className=\"h-4 w-12 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n <div className=\"h-4 w-20 shrink-0 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n <div className=\"h-4 min-w-0 flex-1 bg-surface-hover motion-reduce:animate-none animate-pulse\" />\n </div>\n ))}\n </div>\n ) : null}\n\n {!loading && logs.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-2 rounded-xl border border-edge-subtle bg-surface-base py-16 text-center dark:border-edge\">\n <FileText className=\"size-12 text-fg-subtle\" strokeWidth={1.5} aria-hidden />\n <h2 className=\"text-base font-semibold tracking-tight text-fg\">{L.noLogs}</h2>\n <p className=\"max-w-sm text-sm leading-relaxed text-fg-muted\">{L.noLogsDescription}</p>\n <Button type=\"button\" variant=\"secondary\" className=\"mt-4 gap-2\" onClick={refreshAll}>\n <RefreshCw className=\"size-4\" strokeWidth={1.75} />\n {L.refresh}\n </Button>\n </div>\n ) : null}\n\n {logs.length > 0 ? (\n <div className=\"flex flex-col gap-2\">\n <p className=\"text-xs leading-5 text-fg-muted\">\n {interpolate(L.showingCount, { count: String(logs.length) })}\n {hasMore ? <span className=\"text-fg-subtle\"> · {L.moreAvailable}</span> : null}\n </p>\n <ul\n className=\"divide-y divide-edge-subtle overflow-hidden rounded-xl border border-edge bg-surface-panel font-mono text-sm leading-6 dark:divide-edge dark:border-edge\"\n role=\"list\"\n >\n {logs.map((log, idx) => {\n const lv = log.level ?? 'info';\n const rid = typeof log.requestId === 'string' ? log.requestId.trim() : '';\n return (\n <li key={`${log.timestamp}-${idx}`}>\n <button\n type=\"button\"\n onClick={() => setSelectedLog(log)}\n className={cn(\n 'flex w-full min-w-0 items-center gap-3 px-3 py-2.5 text-left transition-colors duration-150 ease-out',\n 'hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel',\n )}\n >\n <span className=\"w-[5.25rem] shrink-0 tabular-nums text-fg-subtle\">\n {formatTimeCompact(log.timestamp)}\n </span>\n <span className=\"w-[4.5rem] shrink-0 truncate text-fg-muted\" title={lv}>\n {levelLabel(lv)}\n </span>\n <span\n className=\"w-[4.5rem] shrink-0 truncate text-fg-subtle sm:w-[5.25rem]\"\n title={rid ? `${L.requestId}: ${rid}` : undefined}\n >\n {rid ? requestIdPreview(rid) : '—'}\n </span>\n <span\n className=\"hidden max-w-[7rem] shrink-0 truncate text-fg-muted lg:inline\"\n title={moduleLabel(log)}\n >\n {moduleLabel(log)}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-fg\">{messagePreview(log)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n {hasMore ? (\n <div className=\"flex justify-center pt-1\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"gap-2\"\n disabled={loading}\n onClick={handleLoadMore}\n >\n {loading ? (\n <RefreshCw className=\"size-4 animate-spin motion-reduce:animate-none\" strokeWidth={1.75} />\n ) : (\n <ChevronDown className=\"size-4\" strokeWidth={1.75} />\n )}\n {L.loadMore}\n </Button>\n </div>\n ) : null}\n </div>\n ) : null}\n\n <Dialog.Root open={filtersOpen} onOpenChange={setFiltersOpen}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-50 bg-scrim\" />\n <Dialog.Content\n className={cn(\n 'xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,90vh)] w-[min(100%-2rem,22rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none',\n 'dark:border-edge',\n )}\n aria-describedby=\"log-filters-desc\"\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge\">\n <Dialog.Title className=\"text-base font-semibold tracking-tight text-fg\">{L.filtersDialogTitle}</Dialog.Title>\n <Dialog.Close asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 shrink-0 p-0\" aria-label={L.close}>\n <X className=\"size-5\" strokeWidth={1.75} />\n </Button>\n </Dialog.Close>\n </div>\n <div id=\"log-filters-desc\" className=\"sr-only\">\n {L.filtersDialogDesc}\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-4 py-4\">\n <p className=\"text-xs font-medium text-fg-muted\">{L.timeRange}</p>\n <div className=\"mt-2 flex flex-col gap-3\">\n <div>\n <label htmlFor=\"log-from-d\" className=\"mb-1 block text-xs text-fg-muted\">\n {L.from}\n </label>\n <input\n id=\"log-from-d\"\n type=\"datetime-local\"\n value={dateFrom}\n onChange={(e) => setDateFrom(e.target.value)}\n className=\"w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge\"\n />\n </div>\n <div>\n <label htmlFor=\"log-to-d\" className=\"mb-1 block text-xs text-fg-muted\">\n {L.to}\n </label>\n <input\n id=\"log-to-d\"\n type=\"datetime-local\"\n value={dateTo}\n onChange={(e) => setDateTo(e.target.value)}\n className=\"w-full rounded-xl border border-edge bg-surface-base px-2 py-2 text-sm text-fg dark:border-edge\"\n />\n </div>\n </div>\n <p className=\"mt-6 text-xs font-medium text-fg-muted\">{L.levelCustom}</p>\n <p className=\"mt-1 text-xs leading-5 text-fg-subtle\">{L.levelCustomHint}</p>\n <div className=\"mt-3 flex flex-wrap gap-2\" role=\"group\" aria-label={L.level}>\n {LOG_LEVELS.map((level) => {\n const active = selectedLevels.has(level);\n return (\n <button\n key={level}\n type=\"button\"\n className={cn(\n 'rounded-full border px-3 py-1.5 text-xs font-medium capitalize transition-[color,background-color,border-color] duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel',\n active\n ? 'border-edge bg-surface-active text-fg dark:border-edge'\n : 'border-edge-subtle bg-surface-base text-fg-muted hover:bg-surface-hover dark:border-edge',\n )}\n onClick={() => toggleDialogLevel(level)}\n >\n {L.levelNames[level]}\n </button>\n );\n })}\n </div>\n </div>\n <div className=\"shrink-0 border-t border-edge-subtle px-4 py-3 dark:border-edge\">\n <Button type=\"button\" className=\"w-full rounded-xl\" onClick={() => setFiltersOpen(false)}>\n {L.filtersDone}\n </Button>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n\n <Dialog.Root open={selectedLog !== null} onOpenChange={(o) => !o && setSelectedLog(null)}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-50 bg-scrim\" />\n <Dialog.Content\n className={cn(\n 'xopc-drawer-right fixed right-0 top-0 z-50 flex h-full w-full max-w-lg flex-col border-l border-edge bg-surface-panel shadow-popover outline-none',\n 'dark:border-edge',\n )}\n aria-describedby={undefined}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge\">\n <Dialog.Title className=\"text-base font-semibold tracking-tight text-fg\">{L.details}</Dialog.Title>\n <div className=\"flex min-w-0 items-center gap-1\">\n {selectedLog ? (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 shrink-0 gap-1 px-2 text-xs\"\n onClick={() => {\n const text = typeof selectedLog.message === 'string' ? selectedLog.message : '';\n void navigator.clipboard.writeText(text).then(() => setCopiedDetail('message'));\n }}\n >\n <ClipboardCopy className=\"size-3.5 shrink-0\" strokeWidth={1.75} />\n <span className=\"hidden sm:inline\">{copiedDetail === 'message' ? L.copied : L.copyMessage}</span>\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-9 shrink-0 gap-1 px-2 text-xs\"\n onClick={() => {\n void navigator.clipboard\n .writeText(JSON.stringify(selectedLog, null, 2))\n .then(() => setCopiedDetail('json'));\n }}\n >\n <ClipboardCopy className=\"size-3.5 shrink-0\" strokeWidth={1.75} />\n <span className=\"hidden sm:inline\">{copiedDetail === 'json' ? L.copied : L.copyJson}</span>\n </Button>\n </>\n ) : null}\n <Dialog.Close asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 shrink-0 p-0\" aria-label={L.close}>\n <X className=\"size-5\" strokeWidth={1.75} />\n </Button>\n </Dialog.Close>\n </div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-4 py-4 font-mono text-sm leading-relaxed\">\n {selectedLog ? (\n <LogDetailBody\n log={selectedLog}\n labels={{\n time: L.time,\n level: L.level,\n module: L.module,\n message: L.message,\n metadata: L.metadata,\n requestId: L.requestId,\n sessionId: L.sessionId,\n }}\n />\n ) : null}\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n\n <Dialog.Root open={filesOpen} onOpenChange={setFilesOpen}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-50 bg-scrim\" />\n <Dialog.Content\n className={cn(\n 'xopc-dialog-content fixed left-1/2 top-1/2 z-50 flex max-h-[min(32rem,85vh)] w-[min(100%-2rem,24rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border border-edge bg-surface-panel shadow-popover outline-none',\n 'dark:border-edge',\n )}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge\">\n <Dialog.Title className=\"flex items-center gap-2 text-base font-semibold tracking-tight text-fg\">\n <Folder className=\"size-4 text-fg-muted\" strokeWidth={1.75} />\n {L.logFiles}\n </Dialog.Title>\n <Dialog.Close asChild>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 shrink-0 p-0\" aria-label={L.close}>\n <X className=\"size-5\" strokeWidth={1.75} />\n </Button>\n </Dialog.Close>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-4 py-3\">\n {files.length === 0 ? (\n <p className=\"text-sm text-fg-muted\">{L.filesEmpty}</p>\n ) : (\n <ul className=\"flex flex-col gap-2\" role=\"list\">\n {files.map((f) => (\n <li\n key={f.name}\n className=\"flex flex-col gap-1 rounded-lg border border-edge-subtle bg-surface-base px-3 py-2 dark:border-edge\"\n >\n <span className=\"break-all font-mono text-xs text-fg\">{f.name}</span>\n <span className=\"flex flex-wrap gap-x-2 text-xs text-fg-subtle\">\n <span>{formatFileSize(f.size)}</span>\n <span>{formatTimestampFull(f.modified)}</span>\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n {logDir ? (\n <div className=\"shrink-0 border-t border-edge-subtle px-4 py-2 text-xs text-fg-subtle dark:border-edge\">\n <span className=\"font-medium text-fg-muted\">{L.logDir}: </span>\n <code className=\"break-all text-fg-subtle\">{logDir}</code>\n </div>\n ) : null}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n </div>\n );\n}\n\nfunction LogDetailBody({\n log,\n labels,\n}: {\n log: LogEntry;\n labels: {\n time: string;\n level: string;\n module: string;\n message: string;\n metadata: string;\n requestId: string;\n sessionId: string;\n };\n}) {\n const lv = log.level ?? 'info';\n const rid = typeof log.requestId === 'string' ? log.requestId : '';\n const sid = typeof log.sessionId === 'string' ? log.sessionId : '';\n return (\n <div className=\"flex flex-col gap-8\">\n <div>\n <span className=\"text-xs font-sans font-medium text-fg-muted\">{labels.message}</span>\n <pre className=\"mt-2 whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge\">\n {log.message || '—'}\n </pre>\n </div>\n <div className=\"grid grid-cols-[5.5rem_1fr] gap-x-3 gap-y-2 text-xs\">\n <span className=\"font-sans text-fg-muted\">{labels.time}</span>\n <code className=\"break-all text-fg\">{log.timestamp}</code>\n <span className=\"font-sans text-fg-muted\">{labels.level}</span>\n <span className=\"text-fg\">{levelLabel(lv)}</span>\n <span className=\"font-sans text-fg-muted\">{labels.module}</span>\n <code className=\"break-all text-fg\">{moduleLabel(log)}</code>\n {rid ? (\n <>\n <span className=\"font-sans text-fg-muted\">{labels.requestId}</span>\n <code className=\"break-all text-fg\">{rid}</code>\n </>\n ) : null}\n {sid ? (\n <>\n <span className=\"font-sans text-fg-muted\">{labels.sessionId}</span>\n <code className=\"break-all text-fg\">{sid}</code>\n </>\n ) : null}\n </div>\n {log.meta && Object.keys(log.meta).length > 0 ? (\n <div>\n <span className=\"text-xs font-sans font-medium text-fg-muted\">{labels.metadata}</span>\n <pre className=\"mt-2 overflow-x-auto whitespace-pre-wrap break-words border border-edge bg-surface-base p-3 text-xs leading-relaxed text-fg dark:border-edge\">\n {JSON.stringify(log.meta, null, 2)}\n </pre>\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{A as r,Bt as i,D as a,E as o,Er as s,F as c,Gt as l,I as ee,Kt as u,M as te,Mn as ne,Mt as re,Nn as ie,O as d,Ot as ae,Qt as f,Sn as p,T as oe,Vn as se,Vt as m,Wt as h,Zn as g,_n as _,dt as ce,ft as v,ir as le,j as ue,jn as de,k as y,ln as fe,lt as pe,ot as me,st as he,ut as ge,v as b,vn as _e,vr as ve,w as ye,y as x,yr as S}from"./index-tm9ZY35l.js";var C=e(t(),1),w=n();function T(e){let t=new Date(e),n=Math.floor((new Date().getTime()-t.getTime())/(1e3*60*60*24));return n===0?t.toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}):n===1?`Yesterday`:n<7?t.toLocaleDateString([],{weekday:`short`}):t.toLocaleDateString([],{month:`short`,day:`numeric`})}function E(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function be({session:e,variant:t,labels:n,onOpen:r,onAction:i}){let a=e.name?.trim()||n.unnamedSession,o=!!e.name?.trim(),s=e.status===`archived`,c=e.status===`pinned`;return(0,w.jsxs)(`div`,{role:`button`,tabIndex:0,className:h(`group flex min-w-0 w-full max-w-full cursor-pointer flex-col rounded-xl bg-surface-base text-left transition-colors duration-150 ease-out`,`hover:bg-surface-hover active:scale-[0.99]`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`,t===`list`&&`sm:flex-row sm:items-center sm:gap-4`),onClick:r,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),r())},children:[(0,w.jsxs)(`div`,{className:h(`flex min-w-0 items-start justify-between gap-2 bg-surface-hover/35 px-3 py-2 dark:bg-surface-hover/25`,t===`list`&&`sm:py-3`),children:[(0,w.jsx)(`div`,{className:`flex min-w-0 items-center gap-2`,children:(0,w.jsx)(`span`,{className:`truncate text-[11px] font-medium uppercase tracking-wide text-fg-subtle`,children:e.sourceChannel})}),(0,w.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5 text-xs text-fg-muted`,children:[c?(0,w.jsx)(_,{className:`size-3.5 text-accent-fg`,strokeWidth:1.75,"aria-hidden":!0}):null,(0,w.jsx)(`span`,{children:T(e.updatedAt)})]})]}),(0,w.jsxs)(`div`,{className:h(`min-w-0 flex-1 px-3 py-2`,t===`list`&&`sm:py-3`),children:[(0,w.jsx)(`div`,{className:`min-w-0 max-w-full truncate text-sm font-semibold text-fg`,title:a,children:a}),o?(0,w.jsx)(`div`,{className:`mt-0.5 min-w-0 max-w-full truncate font-mono text-[11px] text-fg-subtle`,title:e.key,children:e.key}):null,(0,w.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-3 text-xs text-fg-muted`,children:[(0,w.jsxs)(`span`,{className:`inline-flex items-center gap-1`,children:[(0,w.jsx)(p,{className:`size-3.5`,strokeWidth:1.75,"aria-hidden":!0}),e.messageCount]}),(0,w.jsxs)(`span`,{className:`inline-flex items-center gap-1`,children:[(0,w.jsx)(l,{className:`size-3.5`,strokeWidth:1.75,"aria-hidden":!0}),E(e.estimatedTokens)]})]}),e.tags.length>0?(0,w.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1`,children:[e.tags.slice(0,3).map(e=>(0,w.jsx)(`span`,{className:`max-w-full break-words rounded-md bg-surface-hover px-1.5 py-0.5 text-[11px] text-fg-muted`,children:e},e)),e.tags.length>3?(0,w.jsxs)(`span`,{className:`text-[11px] text-fg-disabled`,children:[`+`,e.tags.length-3]}):null]}):null]}),(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-0.5 border-t border-edge-subtle/80 bg-surface-hover/25 px-2 py-2 dark:border-edge-subtle`,onClick:e=>e.stopPropagation(),onKeyDown:e=>e.stopPropagation(),children:[(0,w.jsx)(`button`,{type:`button`,className:b,title:n.continueChat,"aria-label":n.continueChat,onClick:()=>i(`continue`),children:(0,w.jsx)(p,{className:`size-4`,strokeWidth:1.75})}),s?(0,w.jsx)(`button`,{type:`button`,className:b,title:n.unarchive,"aria-label":n.unarchive,onClick:()=>i(`unarchive`),children:(0,w.jsx)(S,{className:`size-4`,strokeWidth:1.75})}):(0,w.jsx)(`button`,{type:`button`,className:b,title:n.archive,"aria-label":n.archive,onClick:()=>i(`archive`),children:(0,w.jsx)(ve,{className:`size-4`,strokeWidth:1.75})}),c?(0,w.jsx)(`button`,{type:`button`,className:b,title:n.unpin,"aria-label":n.unpin,onClick:()=>i(`unpin`),children:(0,w.jsx)(_e,{className:`size-4`,strokeWidth:1.75})}):(0,w.jsx)(`button`,{type:`button`,className:b,title:n.pin,"aria-label":n.pin,onClick:()=>i(`pin`),children:(0,w.jsx)(_,{className:`size-4`,strokeWidth:1.75})}),(0,w.jsx)(`button`,{type:`button`,className:b,title:n.export,"aria-label":n.export,onClick:()=>i(`export`),children:(0,w.jsx)(g,{className:`size-4`,strokeWidth:1.75})}),(0,w.jsx)(`button`,{type:`button`,className:h(b,`text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-950/40`),title:n.delete,"aria-label":n.delete,onClick:()=>i(`delete`),children:(0,w.jsx)(f,{className:`size-4`,strokeWidth:1.75})})]})]})}function D(e){if(typeof e==`string`)return e.length>2e3?`${e.slice(0,2e3)}…`:e;try{let t=JSON.stringify(e,null,2);return t.length>2e3?`${t.slice(0,2e3)}…`:t}catch{return String(e)}}function xe({open:e,loading:t,session:n,labels:r,onClose:i,onArchive:a,onUnarchive:o,onPin:s,onUnpin:c,onExport:l,onDelete:ee}){let te=n?.status===`archived`,ne=n?.status===`pinned`;return(0,w.jsx)(ce,{open:e,onOpenChange:e=>!e&&i(),children:(0,w.jsxs)(ge,{children:[(0,w.jsx)(pe,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,w.jsxs)(he,{className:h(`xopc-drawer-right fixed right-0 top-0 z-50 flex h-full w-full max-w-lg flex-col border-l border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),"aria-describedby":void 0,children:[(0,w.jsxs)(`div`,{className:`flex min-w-0 shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,w.jsx)(v,{className:`min-w-0 flex-1 truncate text-base font-semibold tracking-tight text-fg`,children:n?.name?.trim()||r.unnamedSession}),(0,w.jsx)(me,{asChild:!0,children:(0,w.jsx)(m,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":r.close,children:(0,w.jsx)(u,{className:`size-5`,strokeWidth:1.75})})})]}),(0,w.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-3`,children:t?(0,w.jsx)(`p`,{className:`text-sm text-fg-muted`,children:r.detailLoading}):n?(0,w.jsxs)(w.Fragment,{children:[(0,w.jsxs)(`dl`,{className:`mb-4 grid gap-2 text-xs text-fg-muted`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`dt`,{className:`text-fg-disabled`,children:`Key`}),(0,w.jsx)(`dd`,{className:`mt-0.5 break-all font-mono text-fg`,children:n.key})]}),(0,w.jsx)(`div`,{className:`flex flex-wrap gap-4`,children:(0,w.jsxs)(`span`,{children:[n.messageCount,` msgs · `,n.estimatedTokens,` tok`]})})]}),(0,w.jsx)(`h3`,{className:`mb-2 text-xs font-medium uppercase tracking-wide text-fg-subtle`,children:r.detailMessages}),(0,w.jsx)(`ul`,{className:`space-y-3`,children:n.messages.map((e,t)=>(0,w.jsxs)(`li`,{className:`rounded-lg border border-edge-subtle bg-surface-hover/50 p-2 dark:border-edge`,children:[(0,w.jsx)(`div`,{className:`mb-1 text-[10px] font-medium uppercase text-fg-subtle`,children:e.role}),(0,w.jsx)(`pre`,{className:`max-h-40 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-fg-muted`,children:D(e.content)})]},`${e.timestamp??t}-${t}`))})]}):null}),(0,w.jsx)(`div`,{className:`shrink-0 border-t border-edge px-4 py-3 dark:border-edge`,children:(0,w.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:l,children:r.detailExport}),te?(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:o,children:r.unarchive}):(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:a,children:r.archive}),ne?(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:c,children:r.unpin}):(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:s,children:r.pin}),(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-950/40`,onClick:ee,children:r.delete})]})})]})]})})}var O=20;function k(e,t){return e.replace(/\{\{(\w+)\}\}/g,(e,n)=>String(t[n]??``))}var A=new Set([`all`,`active`,`pinned`,`archived`]),j=new Set([`grid`,`list`]);function M(){let e=i(re(e=>e.language)),t=e.sessions,n=!!ae(e=>e.token),[l,u]=s(),f=l.get(`q`)??``,p=l.get(`status`),g=l.get(`view`),me=l.get(`channel`)??``,b=A.has(p)?p:`all`,_e=j.has(g)?g:`grid`,[S,T]=(0,C.useState)(f),[E,D]=(0,C.useState)(f.trim()),[M,N]=(0,C.useState)(b),[P,F]=(0,C.useState)(_e),[I,L]=(0,C.useState)(me.trim()),[R,z]=(0,C.useState)([]),[B,V]=(0,C.useState)(!1),[Se,H]=(0,C.useState)(null),[U,Ce]=(0,C.useState)(!1),[W,G]=(0,C.useState)(null),[we,K]=(0,C.useState)(!1),[Te,Ee]=(0,C.useState)(!1),[q,J]=(0,C.useState)(null),[De,Y]=(0,C.useState)(!1),[X,Z]=(0,C.useState)(null);(0,C.useEffect)(()=>{let e=setTimeout(()=>D(S.trim()),300);return()=>clearTimeout(e)},[S]),(0,C.useEffect)(()=>{let e=l.get(`q`)??``,t=l.get(`status`),n=l.get(`view`),r=(l.get(`channel`)??``).trim(),i=A.has(t)?t:`all`,a=j.has(n)?n:`grid`,o=e.trim();T(t=>t===e?t:e),D(e=>e===o?e:o),N(e=>e===i?e:i),F(e=>e===a?e:a),L(e=>e===r?e:r)},[l]),(0,C.useEffect)(()=>{let e=new URLSearchParams(l),t=E.trim();t?e.set(`q`,t):e.delete(`q`),M===`all`?e.delete(`status`):e.set(`status`,M),P===`grid`?e.delete(`view`):e.set(`view`,P),I?e.set(`channel`,I):e.delete(`channel`),e.toString()!==l.toString()&&u(e,{replace:!0})},[E,l,u,M,P,I]),(0,C.useEffect)(()=>{if(!n)return;let e=!1;return(async()=>{V(!0),H(null);try{let t=await y({limit:O,offset:0,...E?{search:E}:{},...M===`all`?{}:{status:M},...I?{channel:I}:{}});if(e)return;z(t.items),Ce(t.hasMore)}catch(n){e||H(n instanceof Error?n.message:t.loadError)}finally{e||V(!1)}})(),()=>{e=!0}},[n,E,M,t.loadError]),(0,C.useEffect)(()=>{n&&d().then(G).catch(()=>{})},[n]),(0,C.useEffect)(()=>{if(!n)return;let e=e=>{let t=e.detail;!t?.key||t.name===void 0||(z(e=>e.map(e=>e.key===t.key?{...e,name:t.name}:e)),J(e=>e&&e.key===t.key?{...e,name:t.name}:e))};return window.addEventListener(`session-updated`,e),()=>{window.removeEventListener(`session-updated`,e)}},[n]);let Oe=(0,C.useCallback)(async()=>{if(!(!n||B||!U)){V(!0),H(null);try{let e=await y({limit:O,offset:R.length,...E?{search:E}:{},...M===`all`?{}:{status:M},...I?{channel:I}:{}});z(t=>[...t,...e.items]),Ce(e.hasMore)}catch(e){H(e instanceof Error?e.message:t.loadError)}finally{V(!1)}}},[n,B,U,R.length,E,M,I,t.loadError]),Q=(0,C.useCallback)((e,t)=>{z(n=>n.map(n=>n.key===e?{...n,status:t}:n)),J(n=>n&&n.key===e?{...n,status:t}:n)},[]),ke=(0,C.useCallback)(async e=>{K(!0),Ee(!0),J(null);try{J(await a(e))}catch{K(!1)}finally{Ee(!1)}},[]),Ae=e=>{ke(e)},$=async(e,t)=>{if(t===`continue`){window.dispatchEvent(new CustomEvent(`navigate-to-chat`,{detail:{sessionKey:e},bubbles:!0}));return}if(t===`delete`){Z(e),Y(!0);return}try{switch(t){case`archive`:await ye(e),Q(e,`archived`);break;case`unarchive`:await ue(e),Q(e,`active`);break;case`pin`:await r(e),Q(e,`pinned`);break;case`unpin`:await te(e),Q(e,`active`);break;case`export`:{let t=await o(e),n=new Blob([t],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=`session-${e.replace(/[^a-z0-9]/gi,`_`)}.json`,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r);break}default:break}d().then(G).catch(()=>{})}catch{}},je=async e=>{try{await oe(e),z(t=>t.filter(t=>t.key!==e)),J(t=>t?.key===e?null:t),q?.key===e&&K(!1),d().then(G).catch(()=>{})}catch{}},Me={continueChat:t.continueChat,archive:t.archive,unarchive:t.unarchive,pin:t.pin,unpin:t.unpin,export:t.export,delete:t.delete,unnamedSession:e.chat.newSession},Ne={close:t.close,detailLoading:t.detailLoading,detailMessages:t.detailMessages,detailExport:t.detailExport,archive:t.archive,unarchive:t.unarchive,pin:t.pin,unpin:t.unpin,delete:t.delete,unnamedSession:e.chat.newSession},Pe=[{key:`all`,label:t.filterAll,icon:ie},{key:`active`,label:t.filterActive,icon:le},{key:`pinned`,label:t.filterPinned,icon:_},{key:`archived`,label:t.filterArchived,icon:ve}],Fe=(()=>{let e=Object.entries(W?.byChannel??{}).sort((e,t)=>t[1]-e[1]).slice(0,6).map(([e])=>e);for(let t of[`telegram`,`weixin`,`feishu`])e.includes(t)||e.push(t);return e.slice(0,8)})();return n?(0,w.jsxs)(`div`,{className:`flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto overflow-x-hidden bg-surface-panel`,children:[(0,w.jsxs)(`div`,{className:`mx-auto flex w-full min-w-0 max-w-2xl flex-col gap-4 px-4 py-6 sm:px-6 lg:max-w-app-main lg:px-8`,children:[(0,w.jsxs)(`header`,{className:`flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between`,children:[(0,w.jsxs)(`h1`,{className:`flex items-center gap-2 text-xl font-semibold tracking-tight text-fg`,children:[(0,w.jsx)(se,{className:`size-5 shrink-0 text-fg-muted`,strokeWidth:1.75,"aria-hidden":!0}),t.title]}),(0,w.jsxs)(`div`,{className:`flex w-full min-w-0 items-center gap-2 rounded-xl bg-surface-base px-3 py-2 transition-colors sm:max-w-md dark:bg-surface-hover/40`,children:[(0,w.jsx)(fe,{className:`size-4 shrink-0 text-fg-disabled`,strokeWidth:1.75,"aria-hidden":!0}),(0,w.jsx)(`input`,{type:`search`,value:S,onChange:e=>T(e.target.value),placeholder:t.searchPlaceholder,className:`min-w-0 flex-1 border-0 bg-transparent text-sm text-fg placeholder:text-fg-disabled focus:outline-none focus:ring-0`})]})]}),(0,w.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Pe.map(({key:e,label:t,icon:n})=>(0,w.jsxs)(`button`,{type:`button`,"aria-pressed":M===e,onClick:()=>N(e),className:h(`inline-flex items-center gap-1.5 rounded-xl px-3 py-2 text-sm font-medium`,x.transition,x.focusRingPanel,M===e?`bg-accent-soft text-accent-fg`:`bg-surface-base text-fg-muted hover:bg-surface-hover hover:text-fg dark:bg-surface-hover/35`),children:[(0,w.jsx)(n,{className:`size-4`,strokeWidth:1.75,"aria-hidden":!0}),t]},e))}),(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,w.jsx)(`span`,{className:`text-xs font-medium text-fg-subtle`,children:t.filterChannelLabel}),(0,w.jsx)(`button`,{type:`button`,"aria-pressed":!I,onClick:()=>L(``),className:h(`inline-flex items-center rounded-xl px-3 py-2 text-sm font-medium`,x.transition,x.focusRingPanel,I?`bg-surface-base text-fg-muted hover:bg-surface-hover hover:text-fg dark:bg-surface-hover/35`:`bg-accent-soft text-accent-fg`),children:t.filterChannelAll}),Fe.map(e=>(0,w.jsxs)(`button`,{type:`button`,"aria-pressed":I===e,onClick:()=>L(e),className:h(`inline-flex items-center rounded-xl px-3 py-2 text-sm font-medium`,x.transition,x.focusRingPanel,I===e?`bg-accent-soft text-accent-fg`:`bg-surface-base text-fg-muted hover:bg-surface-hover hover:text-fg dark:bg-surface-hover/35`),children:[e,W?.byChannel?.[e]==null?null:(0,w.jsx)(`span`,{className:`ml-2 rounded-full bg-surface-hover px-2 py-0.5 text-[11px] text-fg-subtle`,children:W.byChannel[e]})]},e))]}),W?(0,w.jsx)(`div`,{className:`grid grid-cols-2 gap-3 sm:grid-cols-4`,children:[[W.totalSessions,t.totalSessions],[W.activeSessions,t.activeSessions],[W.pinnedSessions,t.pinnedSessions],[W.archivedSessions,t.archivedSessions]].map(([e,t])=>(0,w.jsxs)(`div`,{className:`rounded-xl bg-surface-base px-3 py-3 dark:bg-surface-hover/30`,children:[(0,w.jsx)(`div`,{className:`text-lg font-semibold tabular-nums text-fg`,children:e}),(0,w.jsx)(`div`,{className:`text-xs text-fg-muted`,children:t})]},t))}):null,Se?(0,w.jsx)(`div`,{className:`rounded-lg border border-edge bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-edge dark:bg-red-950/40 dark:text-red-300`,children:Se}):null,(0,w.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,w.jsx)(`p`,{className:`text-xs text-fg-muted`,children:k(t.sessionCount,{count:R.length})}),(0,w.jsxs)(`div`,{className:ee,role:`group`,"aria-label":t.layoutToggleGroup,children:[(0,w.jsx)(m,{type:`button`,variant:`segmented`,title:t.gridView,"aria-pressed":P===`grid`,onClick:()=>F(`grid`),className:h(c,`size-7 p-0`,P===`grid`&&`bg-surface-panel shadow-sm dark:bg-surface-panel dark:shadow-sm dark:ring-1 dark:ring-edge-strong/40`,P===`grid`&&`text-accent-fg`),children:(0,w.jsx)(ne,{className:`size-3.5`,strokeWidth:1.5})}),(0,w.jsx)(m,{type:`button`,variant:`segmented`,title:t.listView,"aria-pressed":P===`list`,onClick:()=>F(`list`),className:h(c,`size-9 p-0`,P===`list`&&`bg-surface-panel shadow-sm dark:bg-surface-panel dark:shadow-sm dark:ring-1 dark:ring-edge-strong/40`,P===`list`&&`text-accent-fg`),children:(0,w.jsx)(de,{className:`size-3.5`,strokeWidth:1.5})})]})]}),B&&R.length===0?(0,w.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3`,children:Array.from({length:6}).map((e,t)=>(0,w.jsx)(`div`,{className:`h-40 animate-pulse rounded-xl bg-surface-hover/60 dark:bg-surface-hover/40`},t))}):R.length===0?(0,w.jsxs)(`div`,{className:`flex flex-col items-center justify-center rounded-2xl bg-surface-base py-16 text-center dark:bg-surface-hover/25`,children:[(0,w.jsx)(se,{className:`mb-3 size-12 text-fg-disabled`,strokeWidth:1.25,"aria-hidden":!0}),(0,w.jsx)(`p`,{className:`text-base font-semibold text-fg`,children:t.noSessions}),(0,w.jsx)(`p`,{className:`mt-1 max-w-sm text-sm text-fg-muted`,children:t.noSessionsDescription}),(0,w.jsx)(m,{variant:`primary`,className:`mt-6`,onClick:()=>{window.dispatchEvent(new CustomEvent(`navigate-to-chat`,{detail:{sessionKey:``},bubbles:!0}))},children:t.startNewChat})]}):(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(`div`,{className:h(`grid min-w-0 gap-3`,P===`grid`?`sm:grid-cols-2 lg:grid-cols-3`:`grid-cols-1`),children:R.map(e=>(0,w.jsx)(be,{session:e,variant:P,labels:Me,onOpen:()=>Ae(e.key),onAction:t=>void $(e.key,t)},e.key))}),U?(0,w.jsx)(`div`,{className:`flex justify-center pt-2`,children:(0,w.jsx)(m,{type:`button`,variant:`secondary`,disabled:B,onClick:()=>void Oe(),children:t.loadMore})}):null]})]}),(0,w.jsx)(xe,{open:we,loading:Te,session:q,labels:Ne,onClose:()=>{K(!1),J(null)},onArchive:()=>q&&void $(q.key,`archive`),onUnarchive:()=>q&&void $(q.key,`unarchive`),onPin:()=>q&&void $(q.key,`pin`),onUnpin:()=>q&&void $(q.key,`unpin`),onExport:()=>q&&void $(q.key,`export`),onDelete:()=>q&&(Z(q.key),Y(!0))}),(0,w.jsx)(ce,{open:De,onOpenChange:Y,children:(0,w.jsxs)(ge,{children:[(0,w.jsx)(pe,{className:`xopc-dialog-overlay fixed inset-0 z-[60] bg-scrim`}),(0,w.jsxs)(he,{className:`xopc-dialog-content fixed left-1/2 top-1/2 z-[60] w-[min(100%-2rem,24rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl border border-edge bg-surface-panel p-4 shadow-popover dark:border-edge`,children:[(0,w.jsx)(v,{className:`text-base font-semibold text-fg`,children:t.deleteSessionTitle}),(0,w.jsx)(`p`,{className:`mt-2 text-sm text-fg-muted`,children:X?k(t.deleteSessionMessage,{name:R.find(e=>e.key===X)?.name?.trim()||e.chat.newSession}):``}),(0,w.jsxs)(`div`,{className:`mt-4 flex justify-end gap-2`,children:[(0,w.jsx)(m,{type:`button`,variant:`secondary`,onClick:()=>Y(!1),children:t.cancel}),(0,w.jsx)(m,{type:`button`,variant:`primary`,className:`bg-red-600 hover:bg-red-700`,onClick:()=>{X&&je(X),Y(!1),Z(null)},children:t.delete})]})]})]})})]}):(0,w.jsx)(`div`,{className:`mx-auto w-full max-w-2xl px-4 py-16 text-center text-sm text-fg-muted sm:px-8 lg:max-w-app-main`,children:t.needToken})}export{M as SessionsPage};
2
- //# sourceMappingURL=sessions-page-cn2fi_V3.js.map
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{A as r,Bt as i,D as a,E as o,Er as s,F as c,Gt as l,I as ee,Kt as u,M as te,Mn as ne,Mt as re,Nn as ie,O as d,Ot as ae,Qt as f,Sn as p,T as oe,Vn as se,Vt as m,Wt as h,Zn as g,_n as _,dt as ce,ft as v,ir as le,j as ue,jn as de,k as y,ln as fe,lt as pe,ot as me,st as he,ut as ge,v as b,vn as _e,vr as ve,w as ye,y as x,yr as S}from"./index-DJnBAhem.js";var C=e(t(),1),w=n();function T(e){let t=new Date(e),n=Math.floor((new Date().getTime()-t.getTime())/(1e3*60*60*24));return n===0?t.toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}):n===1?`Yesterday`:n<7?t.toLocaleDateString([],{weekday:`short`}):t.toLocaleDateString([],{month:`short`,day:`numeric`})}function E(e){return e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function be({session:e,variant:t,labels:n,onOpen:r,onAction:i}){let a=e.name?.trim()||n.unnamedSession,o=!!e.name?.trim(),s=e.status===`archived`,c=e.status===`pinned`;return(0,w.jsxs)(`div`,{role:`button`,tabIndex:0,className:h(`group flex min-w-0 w-full max-w-full cursor-pointer flex-col rounded-xl bg-surface-base text-left transition-colors duration-150 ease-out`,`hover:bg-surface-hover active:scale-[0.99]`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`,t===`list`&&`sm:flex-row sm:items-center sm:gap-4`),onClick:r,onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),r())},children:[(0,w.jsxs)(`div`,{className:h(`flex min-w-0 items-start justify-between gap-2 bg-surface-hover/35 px-3 py-2 dark:bg-surface-hover/25`,t===`list`&&`sm:py-3`),children:[(0,w.jsx)(`div`,{className:`flex min-w-0 items-center gap-2`,children:(0,w.jsx)(`span`,{className:`truncate text-[11px] font-medium uppercase tracking-wide text-fg-subtle`,children:e.sourceChannel})}),(0,w.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5 text-xs text-fg-muted`,children:[c?(0,w.jsx)(_,{className:`size-3.5 text-accent-fg`,strokeWidth:1.75,"aria-hidden":!0}):null,(0,w.jsx)(`span`,{children:T(e.updatedAt)})]})]}),(0,w.jsxs)(`div`,{className:h(`min-w-0 flex-1 px-3 py-2`,t===`list`&&`sm:py-3`),children:[(0,w.jsx)(`div`,{className:`min-w-0 max-w-full truncate text-sm font-semibold text-fg`,title:a,children:a}),o?(0,w.jsx)(`div`,{className:`mt-0.5 min-w-0 max-w-full truncate font-mono text-[11px] text-fg-subtle`,title:e.key,children:e.key}):null,(0,w.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-3 text-xs text-fg-muted`,children:[(0,w.jsxs)(`span`,{className:`inline-flex items-center gap-1`,children:[(0,w.jsx)(p,{className:`size-3.5`,strokeWidth:1.75,"aria-hidden":!0}),e.messageCount]}),(0,w.jsxs)(`span`,{className:`inline-flex items-center gap-1`,children:[(0,w.jsx)(l,{className:`size-3.5`,strokeWidth:1.75,"aria-hidden":!0}),E(e.estimatedTokens)]})]}),e.tags.length>0?(0,w.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1`,children:[e.tags.slice(0,3).map(e=>(0,w.jsx)(`span`,{className:`max-w-full break-words rounded-md bg-surface-hover px-1.5 py-0.5 text-[11px] text-fg-muted`,children:e},e)),e.tags.length>3?(0,w.jsxs)(`span`,{className:`text-[11px] text-fg-disabled`,children:[`+`,e.tags.length-3]}):null]}):null]}),(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-0.5 border-t border-edge-subtle/80 bg-surface-hover/25 px-2 py-2 dark:border-edge-subtle`,onClick:e=>e.stopPropagation(),onKeyDown:e=>e.stopPropagation(),children:[(0,w.jsx)(`button`,{type:`button`,className:b,title:n.continueChat,"aria-label":n.continueChat,onClick:()=>i(`continue`),children:(0,w.jsx)(p,{className:`size-4`,strokeWidth:1.75})}),s?(0,w.jsx)(`button`,{type:`button`,className:b,title:n.unarchive,"aria-label":n.unarchive,onClick:()=>i(`unarchive`),children:(0,w.jsx)(S,{className:`size-4`,strokeWidth:1.75})}):(0,w.jsx)(`button`,{type:`button`,className:b,title:n.archive,"aria-label":n.archive,onClick:()=>i(`archive`),children:(0,w.jsx)(ve,{className:`size-4`,strokeWidth:1.75})}),c?(0,w.jsx)(`button`,{type:`button`,className:b,title:n.unpin,"aria-label":n.unpin,onClick:()=>i(`unpin`),children:(0,w.jsx)(_e,{className:`size-4`,strokeWidth:1.75})}):(0,w.jsx)(`button`,{type:`button`,className:b,title:n.pin,"aria-label":n.pin,onClick:()=>i(`pin`),children:(0,w.jsx)(_,{className:`size-4`,strokeWidth:1.75})}),(0,w.jsx)(`button`,{type:`button`,className:b,title:n.export,"aria-label":n.export,onClick:()=>i(`export`),children:(0,w.jsx)(g,{className:`size-4`,strokeWidth:1.75})}),(0,w.jsx)(`button`,{type:`button`,className:h(b,`text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-950/40`),title:n.delete,"aria-label":n.delete,onClick:()=>i(`delete`),children:(0,w.jsx)(f,{className:`size-4`,strokeWidth:1.75})})]})]})}function D(e){if(typeof e==`string`)return e.length>2e3?`${e.slice(0,2e3)}…`:e;try{let t=JSON.stringify(e,null,2);return t.length>2e3?`${t.slice(0,2e3)}…`:t}catch{return String(e)}}function xe({open:e,loading:t,session:n,labels:r,onClose:i,onArchive:a,onUnarchive:o,onPin:s,onUnpin:c,onExport:l,onDelete:ee}){let te=n?.status===`archived`,ne=n?.status===`pinned`;return(0,w.jsx)(ce,{open:e,onOpenChange:e=>!e&&i(),children:(0,w.jsxs)(ge,{children:[(0,w.jsx)(pe,{className:`xopc-dialog-overlay fixed inset-0 z-50 bg-scrim`}),(0,w.jsxs)(he,{className:h(`xopc-drawer-right fixed right-0 top-0 z-50 flex h-full w-full max-w-lg flex-col border-l border-edge bg-surface-panel shadow-popover outline-none`,`dark:border-edge`),"aria-describedby":void 0,children:[(0,w.jsxs)(`div`,{className:`flex min-w-0 shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3 dark:border-edge`,children:[(0,w.jsx)(v,{className:`min-w-0 flex-1 truncate text-base font-semibold tracking-tight text-fg`,children:n?.name?.trim()||r.unnamedSession}),(0,w.jsx)(me,{asChild:!0,children:(0,w.jsx)(m,{type:`button`,variant:`ghost`,className:`h-9 w-9 shrink-0 p-0`,"aria-label":r.close,children:(0,w.jsx)(u,{className:`size-5`,strokeWidth:1.75})})})]}),(0,w.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 py-3`,children:t?(0,w.jsx)(`p`,{className:`text-sm text-fg-muted`,children:r.detailLoading}):n?(0,w.jsxs)(w.Fragment,{children:[(0,w.jsxs)(`dl`,{className:`mb-4 grid gap-2 text-xs text-fg-muted`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`dt`,{className:`text-fg-disabled`,children:`Key`}),(0,w.jsx)(`dd`,{className:`mt-0.5 break-all font-mono text-fg`,children:n.key})]}),(0,w.jsx)(`div`,{className:`flex flex-wrap gap-4`,children:(0,w.jsxs)(`span`,{children:[n.messageCount,` msgs · `,n.estimatedTokens,` tok`]})})]}),(0,w.jsx)(`h3`,{className:`mb-2 text-xs font-medium uppercase tracking-wide text-fg-subtle`,children:r.detailMessages}),(0,w.jsx)(`ul`,{className:`space-y-3`,children:n.messages.map((e,t)=>(0,w.jsxs)(`li`,{className:`rounded-lg border border-edge-subtle bg-surface-hover/50 p-2 dark:border-edge`,children:[(0,w.jsx)(`div`,{className:`mb-1 text-[10px] font-medium uppercase text-fg-subtle`,children:e.role}),(0,w.jsx)(`pre`,{className:`max-h-40 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-fg-muted`,children:D(e.content)})]},`${e.timestamp??t}-${t}`))})]}):null}),(0,w.jsx)(`div`,{className:`shrink-0 border-t border-edge px-4 py-3 dark:border-edge`,children:(0,w.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:l,children:r.detailExport}),te?(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:o,children:r.unarchive}):(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:a,children:r.archive}),ne?(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:c,children:r.unpin}):(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm`,onClick:s,children:r.pin}),(0,w.jsx)(m,{type:`button`,variant:`secondary`,className:`text-sm text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-950/40`,onClick:ee,children:r.delete})]})})]})]})})}var O=20;function k(e,t){return e.replace(/\{\{(\w+)\}\}/g,(e,n)=>String(t[n]??``))}var A=new Set([`all`,`active`,`pinned`,`archived`]),j=new Set([`grid`,`list`]);function M(){let e=i(re(e=>e.language)),t=e.sessions,n=!!ae(e=>e.token),[l,u]=s(),f=l.get(`q`)??``,p=l.get(`status`),g=l.get(`view`),me=l.get(`channel`)??``,b=A.has(p)?p:`all`,_e=j.has(g)?g:`grid`,[S,T]=(0,C.useState)(f),[E,D]=(0,C.useState)(f.trim()),[M,N]=(0,C.useState)(b),[P,F]=(0,C.useState)(_e),[I,L]=(0,C.useState)(me.trim()),[R,z]=(0,C.useState)([]),[B,V]=(0,C.useState)(!1),[Se,H]=(0,C.useState)(null),[U,Ce]=(0,C.useState)(!1),[W,G]=(0,C.useState)(null),[we,K]=(0,C.useState)(!1),[Te,Ee]=(0,C.useState)(!1),[q,J]=(0,C.useState)(null),[De,Y]=(0,C.useState)(!1),[X,Z]=(0,C.useState)(null);(0,C.useEffect)(()=>{let e=setTimeout(()=>D(S.trim()),300);return()=>clearTimeout(e)},[S]),(0,C.useEffect)(()=>{let e=l.get(`q`)??``,t=l.get(`status`),n=l.get(`view`),r=(l.get(`channel`)??``).trim(),i=A.has(t)?t:`all`,a=j.has(n)?n:`grid`,o=e.trim();T(t=>t===e?t:e),D(e=>e===o?e:o),N(e=>e===i?e:i),F(e=>e===a?e:a),L(e=>e===r?e:r)},[l]),(0,C.useEffect)(()=>{let e=new URLSearchParams(l),t=E.trim();t?e.set(`q`,t):e.delete(`q`),M===`all`?e.delete(`status`):e.set(`status`,M),P===`grid`?e.delete(`view`):e.set(`view`,P),I?e.set(`channel`,I):e.delete(`channel`),e.toString()!==l.toString()&&u(e,{replace:!0})},[E,l,u,M,P,I]),(0,C.useEffect)(()=>{if(!n)return;let e=!1;return(async()=>{V(!0),H(null);try{let t=await y({limit:O,offset:0,...E?{search:E}:{},...M===`all`?{}:{status:M},...I?{channel:I}:{}});if(e)return;z(t.items),Ce(t.hasMore)}catch(n){e||H(n instanceof Error?n.message:t.loadError)}finally{e||V(!1)}})(),()=>{e=!0}},[n,E,M,t.loadError]),(0,C.useEffect)(()=>{n&&d().then(G).catch(()=>{})},[n]),(0,C.useEffect)(()=>{if(!n)return;let e=e=>{let t=e.detail;!t?.key||t.name===void 0||(z(e=>e.map(e=>e.key===t.key?{...e,name:t.name}:e)),J(e=>e&&e.key===t.key?{...e,name:t.name}:e))};return window.addEventListener(`session-updated`,e),()=>{window.removeEventListener(`session-updated`,e)}},[n]);let Oe=(0,C.useCallback)(async()=>{if(!(!n||B||!U)){V(!0),H(null);try{let e=await y({limit:O,offset:R.length,...E?{search:E}:{},...M===`all`?{}:{status:M},...I?{channel:I}:{}});z(t=>[...t,...e.items]),Ce(e.hasMore)}catch(e){H(e instanceof Error?e.message:t.loadError)}finally{V(!1)}}},[n,B,U,R.length,E,M,I,t.loadError]),Q=(0,C.useCallback)((e,t)=>{z(n=>n.map(n=>n.key===e?{...n,status:t}:n)),J(n=>n&&n.key===e?{...n,status:t}:n)},[]),ke=(0,C.useCallback)(async e=>{K(!0),Ee(!0),J(null);try{J(await a(e))}catch{K(!1)}finally{Ee(!1)}},[]),Ae=e=>{ke(e)},$=async(e,t)=>{if(t===`continue`){window.dispatchEvent(new CustomEvent(`navigate-to-chat`,{detail:{sessionKey:e},bubbles:!0}));return}if(t===`delete`){Z(e),Y(!0);return}try{switch(t){case`archive`:await ye(e),Q(e,`archived`);break;case`unarchive`:await ue(e),Q(e,`active`);break;case`pin`:await r(e),Q(e,`pinned`);break;case`unpin`:await te(e),Q(e,`active`);break;case`export`:{let t=await o(e),n=new Blob([t],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=`session-${e.replace(/[^a-z0-9]/gi,`_`)}.json`,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r);break}default:break}d().then(G).catch(()=>{})}catch{}},je=async e=>{try{await oe(e),z(t=>t.filter(t=>t.key!==e)),J(t=>t?.key===e?null:t),q?.key===e&&K(!1),d().then(G).catch(()=>{})}catch{}},Me={continueChat:t.continueChat,archive:t.archive,unarchive:t.unarchive,pin:t.pin,unpin:t.unpin,export:t.export,delete:t.delete,unnamedSession:e.chat.newSession},Ne={close:t.close,detailLoading:t.detailLoading,detailMessages:t.detailMessages,detailExport:t.detailExport,archive:t.archive,unarchive:t.unarchive,pin:t.pin,unpin:t.unpin,delete:t.delete,unnamedSession:e.chat.newSession},Pe=[{key:`all`,label:t.filterAll,icon:ie},{key:`active`,label:t.filterActive,icon:le},{key:`pinned`,label:t.filterPinned,icon:_},{key:`archived`,label:t.filterArchived,icon:ve}],Fe=(()=>{let e=Object.entries(W?.byChannel??{}).sort((e,t)=>t[1]-e[1]).slice(0,6).map(([e])=>e);for(let t of[`telegram`,`weixin`,`feishu`])e.includes(t)||e.push(t);return e.slice(0,8)})();return n?(0,w.jsxs)(`div`,{className:`flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto overflow-x-hidden bg-surface-panel`,children:[(0,w.jsxs)(`div`,{className:`mx-auto flex w-full min-w-0 max-w-2xl flex-col gap-4 px-4 py-6 sm:px-6 lg:max-w-app-main lg:px-8`,children:[(0,w.jsxs)(`header`,{className:`flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between`,children:[(0,w.jsxs)(`h1`,{className:`flex items-center gap-2 text-xl font-semibold tracking-tight text-fg`,children:[(0,w.jsx)(se,{className:`size-5 shrink-0 text-fg-muted`,strokeWidth:1.75,"aria-hidden":!0}),t.title]}),(0,w.jsxs)(`div`,{className:`flex w-full min-w-0 items-center gap-2 rounded-xl bg-surface-base px-3 py-2 transition-colors sm:max-w-md dark:bg-surface-hover/40`,children:[(0,w.jsx)(fe,{className:`size-4 shrink-0 text-fg-disabled`,strokeWidth:1.75,"aria-hidden":!0}),(0,w.jsx)(`input`,{type:`search`,value:S,onChange:e=>T(e.target.value),placeholder:t.searchPlaceholder,className:`min-w-0 flex-1 border-0 bg-transparent text-sm text-fg placeholder:text-fg-disabled focus:outline-none focus:ring-0`})]})]}),(0,w.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Pe.map(({key:e,label:t,icon:n})=>(0,w.jsxs)(`button`,{type:`button`,"aria-pressed":M===e,onClick:()=>N(e),className:h(`inline-flex items-center gap-1.5 rounded-xl px-3 py-2 text-sm font-medium`,x.transition,x.focusRingPanel,M===e?`bg-accent-soft text-accent-fg`:`bg-surface-base text-fg-muted hover:bg-surface-hover hover:text-fg dark:bg-surface-hover/35`),children:[(0,w.jsx)(n,{className:`size-4`,strokeWidth:1.75,"aria-hidden":!0}),t]},e))}),(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,w.jsx)(`span`,{className:`text-xs font-medium text-fg-subtle`,children:t.filterChannelLabel}),(0,w.jsx)(`button`,{type:`button`,"aria-pressed":!I,onClick:()=>L(``),className:h(`inline-flex items-center rounded-xl px-3 py-2 text-sm font-medium`,x.transition,x.focusRingPanel,I?`bg-surface-base text-fg-muted hover:bg-surface-hover hover:text-fg dark:bg-surface-hover/35`:`bg-accent-soft text-accent-fg`),children:t.filterChannelAll}),Fe.map(e=>(0,w.jsxs)(`button`,{type:`button`,"aria-pressed":I===e,onClick:()=>L(e),className:h(`inline-flex items-center rounded-xl px-3 py-2 text-sm font-medium`,x.transition,x.focusRingPanel,I===e?`bg-accent-soft text-accent-fg`:`bg-surface-base text-fg-muted hover:bg-surface-hover hover:text-fg dark:bg-surface-hover/35`),children:[e,W?.byChannel?.[e]==null?null:(0,w.jsx)(`span`,{className:`ml-2 rounded-full bg-surface-hover px-2 py-0.5 text-[11px] text-fg-subtle`,children:W.byChannel[e]})]},e))]}),W?(0,w.jsx)(`div`,{className:`grid grid-cols-2 gap-3 sm:grid-cols-4`,children:[[W.totalSessions,t.totalSessions],[W.activeSessions,t.activeSessions],[W.pinnedSessions,t.pinnedSessions],[W.archivedSessions,t.archivedSessions]].map(([e,t])=>(0,w.jsxs)(`div`,{className:`rounded-xl bg-surface-base px-3 py-3 dark:bg-surface-hover/30`,children:[(0,w.jsx)(`div`,{className:`text-lg font-semibold tabular-nums text-fg`,children:e}),(0,w.jsx)(`div`,{className:`text-xs text-fg-muted`,children:t})]},t))}):null,Se?(0,w.jsx)(`div`,{className:`rounded-lg border border-edge bg-red-50 px-3 py-2 text-sm text-red-700 dark:border-edge dark:bg-red-950/40 dark:text-red-300`,children:Se}):null,(0,w.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,w.jsx)(`p`,{className:`text-xs text-fg-muted`,children:k(t.sessionCount,{count:R.length})}),(0,w.jsxs)(`div`,{className:ee,role:`group`,"aria-label":t.layoutToggleGroup,children:[(0,w.jsx)(m,{type:`button`,variant:`segmented`,title:t.gridView,"aria-pressed":P===`grid`,onClick:()=>F(`grid`),className:h(c,`size-7 p-0`,P===`grid`&&`bg-surface-panel shadow-sm dark:bg-surface-panel dark:shadow-sm dark:ring-1 dark:ring-edge-strong/40`,P===`grid`&&`text-accent-fg`),children:(0,w.jsx)(ne,{className:`size-3.5`,strokeWidth:1.5})}),(0,w.jsx)(m,{type:`button`,variant:`segmented`,title:t.listView,"aria-pressed":P===`list`,onClick:()=>F(`list`),className:h(c,`size-9 p-0`,P===`list`&&`bg-surface-panel shadow-sm dark:bg-surface-panel dark:shadow-sm dark:ring-1 dark:ring-edge-strong/40`,P===`list`&&`text-accent-fg`),children:(0,w.jsx)(de,{className:`size-3.5`,strokeWidth:1.5})})]})]}),B&&R.length===0?(0,w.jsx)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3`,children:Array.from({length:6}).map((e,t)=>(0,w.jsx)(`div`,{className:`h-40 animate-pulse rounded-xl bg-surface-hover/60 dark:bg-surface-hover/40`},t))}):R.length===0?(0,w.jsxs)(`div`,{className:`flex flex-col items-center justify-center rounded-2xl bg-surface-base py-16 text-center dark:bg-surface-hover/25`,children:[(0,w.jsx)(se,{className:`mb-3 size-12 text-fg-disabled`,strokeWidth:1.25,"aria-hidden":!0}),(0,w.jsx)(`p`,{className:`text-base font-semibold text-fg`,children:t.noSessions}),(0,w.jsx)(`p`,{className:`mt-1 max-w-sm text-sm text-fg-muted`,children:t.noSessionsDescription}),(0,w.jsx)(m,{variant:`primary`,className:`mt-6`,onClick:()=>{window.dispatchEvent(new CustomEvent(`navigate-to-chat`,{detail:{sessionKey:``},bubbles:!0}))},children:t.startNewChat})]}):(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)(`div`,{className:h(`grid min-w-0 gap-3`,P===`grid`?`sm:grid-cols-2 lg:grid-cols-3`:`grid-cols-1`),children:R.map(e=>(0,w.jsx)(be,{session:e,variant:P,labels:Me,onOpen:()=>Ae(e.key),onAction:t=>void $(e.key,t)},e.key))}),U?(0,w.jsx)(`div`,{className:`flex justify-center pt-2`,children:(0,w.jsx)(m,{type:`button`,variant:`secondary`,disabled:B,onClick:()=>void Oe(),children:t.loadMore})}):null]})]}),(0,w.jsx)(xe,{open:we,loading:Te,session:q,labels:Ne,onClose:()=>{K(!1),J(null)},onArchive:()=>q&&void $(q.key,`archive`),onUnarchive:()=>q&&void $(q.key,`unarchive`),onPin:()=>q&&void $(q.key,`pin`),onUnpin:()=>q&&void $(q.key,`unpin`),onExport:()=>q&&void $(q.key,`export`),onDelete:()=>q&&(Z(q.key),Y(!0))}),(0,w.jsx)(ce,{open:De,onOpenChange:Y,children:(0,w.jsxs)(ge,{children:[(0,w.jsx)(pe,{className:`xopc-dialog-overlay fixed inset-0 z-[60] bg-scrim`}),(0,w.jsxs)(he,{className:`xopc-dialog-content fixed left-1/2 top-1/2 z-[60] w-[min(100%-2rem,24rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl border border-edge bg-surface-panel p-4 shadow-popover dark:border-edge`,children:[(0,w.jsx)(v,{className:`text-base font-semibold text-fg`,children:t.deleteSessionTitle}),(0,w.jsx)(`p`,{className:`mt-2 text-sm text-fg-muted`,children:X?k(t.deleteSessionMessage,{name:R.find(e=>e.key===X)?.name?.trim()||e.chat.newSession}):``}),(0,w.jsxs)(`div`,{className:`mt-4 flex justify-end gap-2`,children:[(0,w.jsx)(m,{type:`button`,variant:`secondary`,onClick:()=>Y(!1),children:t.cancel}),(0,w.jsx)(m,{type:`button`,variant:`primary`,className:`bg-red-600 hover:bg-red-700`,onClick:()=>{X&&je(X),Y(!1),Z(null)},children:t.delete})]})]})]})})]}):(0,w.jsx)(`div`,{className:`mx-auto w-full max-w-2xl px-4 py-16 text-center text-sm text-fg-muted sm:px-8 lg:max-w-app-main`,children:t.needToken})}export{M as SessionsPage};
2
+ //# sourceMappingURL=sessions-page-CzTpNrb3.js.map