agent-relay-server 0.35.3 → 0.35.4

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 (46) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +1 -1
  3. package/public/assets/{activity-WjOShx3N.js → activity-CPuZGkeP.js} +2 -2
  4. package/public/assets/{activity-WjOShx3N.js.map → activity-CPuZGkeP.js.map} +1 -1
  5. package/public/assets/{agents-Cihuuoxa.js → agents-Bz4eJ4zH.js} +2 -2
  6. package/public/assets/{agents-Cihuuoxa.js.map → agents-Bz4eJ4zH.js.map} +1 -1
  7. package/public/assets/{analytics-B5_HS2Lt.js → analytics-inmkBD_j.js} +2 -2
  8. package/public/assets/{analytics-B5_HS2Lt.js.map → analytics-inmkBD_j.js.map} +1 -1
  9. package/public/assets/{automation-CoOe2nEA.js → automation-DRN2lcqQ.js} +2 -2
  10. package/public/assets/{automation-CoOe2nEA.js.map → automation-DRN2lcqQ.js.map} +1 -1
  11. package/public/assets/chat-Dn3TEhl0.js +2 -0
  12. package/public/assets/chat-Dn3TEhl0.js.map +1 -0
  13. package/public/assets/display-Bebqs1qu.js.map +1 -1
  14. package/public/assets/{formatted-body-impl-DhCblnWM.js → formatted-body-impl-DP9iZsd4.js} +2 -2
  15. package/public/assets/{formatted-body-impl-DhCblnWM.js.map → formatted-body-impl-DP9iZsd4.js.map} +1 -1
  16. package/public/assets/{index-CvSlyTSI.js → index-BL8r94_U.js} +5 -5
  17. package/public/assets/{index-CvSlyTSI.js.map → index-BL8r94_U.js.map} +1 -1
  18. package/public/assets/{maintenance-CUxxVXsc.js → maintenance-DtfpsMZa.js} +2 -2
  19. package/public/assets/{maintenance-CUxxVXsc.js.map → maintenance-DtfpsMZa.js.map} +1 -1
  20. package/public/assets/{managed-agents-VZEeMMSP.js → managed-agents-C5pzetBh.js} +2 -2
  21. package/public/assets/{managed-agents-VZEeMMSP.js.map → managed-agents-C5pzetBh.js.map} +1 -1
  22. package/public/assets/{markdown-preview-impl-Bbwmbxvn.js → markdown-preview-impl-4s9YDGM7.js} +2 -2
  23. package/public/assets/{markdown-preview-impl-Bbwmbxvn.js.map → markdown-preview-impl-4s9YDGM7.js.map} +1 -1
  24. package/public/assets/{memory-BQAC3YmR.js → memory-BWfDbph3.js} +2 -2
  25. package/public/assets/{memory-BQAC3YmR.js.map → memory-BWfDbph3.js.map} +1 -1
  26. package/public/assets/{messages-_sdHV42k.js → messages-C8cP25kp.js} +2 -2
  27. package/public/assets/{messages-_sdHV42k.js.map → messages-C8cP25kp.js.map} +1 -1
  28. package/public/assets/{orchestrators-BkHHgd83.js → orchestrators-Clu8MNKo.js} +2 -2
  29. package/public/assets/{orchestrators-BkHHgd83.js.map → orchestrators-Clu8MNKo.js.map} +1 -1
  30. package/public/assets/{overview-CYAHOUyA.js → overview-CXcGh2D6.js} +2 -2
  31. package/public/assets/{overview-CYAHOUyA.js.map → overview-CXcGh2D6.js.map} +1 -1
  32. package/public/assets/{pairs-BvMH1CS7.js → pairs-eOZl_lQn.js} +2 -2
  33. package/public/assets/{pairs-BvMH1CS7.js.map → pairs-eOZl_lQn.js.map} +1 -1
  34. package/public/assets/{security-Dsdr3lSX.js → security-CA03sHyP.js} +2 -2
  35. package/public/assets/{security-Dsdr3lSX.js.map → security-CA03sHyP.js.map} +1 -1
  36. package/public/assets/{settings-DlovIWdE.js → settings-KTOwGJiW.js} +2 -2
  37. package/public/assets/{settings-DlovIWdE.js.map → settings-KTOwGJiW.js.map} +1 -1
  38. package/public/assets/{tasks-Cgan8Oqb.js → tasks-D6jbr2y6.js} +2 -2
  39. package/public/assets/{tasks-Cgan8Oqb.js.map → tasks-D6jbr2y6.js.map} +1 -1
  40. package/public/assets/{terminal-viewer-impl-DVW-LRbz.js → terminal-viewer-impl-DFODXxpG.js} +2 -2
  41. package/public/assets/{terminal-viewer-impl-DVW-LRbz.js.map → terminal-viewer-impl-DFODXxpG.js.map} +1 -1
  42. package/public/assets/{work-queue-B4CifZKH.js → work-queue-BWWckTVy.js} +2 -2
  43. package/public/assets/{work-queue-B4CifZKH.js.map → work-queue-BWWckTVy.js.map} +1 -1
  44. package/public/index.html +1 -1
  45. package/public/assets/chat-0ZbxHlDu.js +0 -2
  46. package/public/assets/chat-0ZbxHlDu.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Dn as t,En as n,Gt as r,M as i,R as a,Vn as o,Zt as s,a as c,kn as l,p as u}from"./lucide-react-CD8Xl2U3.js";import{i as d,t as f}from"./store-CICRhg1m.js";import{m as p,z as m}from"./display-Bebqs1qu.js";import{t as h}from"./badge-t8zAwHW9.js";import{t as g}from"./button-DDA5P2YQ.js";import{s as _}from"./index-CvSlyTSI.js";var v=e(o(),1),y=l(),b={succeeded:`bg-emerald-500/10 text-emerald-400 border-emerald-500/30`,running:`bg-blue-500/10 text-blue-400 border-blue-500/30`,failed:`bg-red-500/10 text-red-400 border-red-500/30`,idle:`bg-zinc-500/10 text-zinc-400 border-zinc-500/30`,disabled:`bg-zinc-500/10 text-zinc-500 border-zinc-500/20`};function x(){let e=d(),t=f(e=>e.maintenanceJobs),n=f(e=>e.fetchMaintenanceJobs),r=f(e=>e.runMaintenanceJob),a=(0,v.useMemo)(()=>({failed:t.filter(e=>e.lastStatus===`failed`).length,running:t.filter(e=>e.running||e.lastStatus===`running`).length,dueSoon:t.filter(t=>t.nextRunAt&&t.nextRunAt<=e+300*1e3).length}),[t,e]);return(0,y.jsxs)(`div`,{className:`space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,y.jsx)(c,{className:`h-5 w-5 text-muted-foreground`}),(0,y.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Maintenance`}),(0,y.jsx)(h,{variant:`secondary`,children:t.length}),a.running>0&&(0,y.jsxs)(h,{className:`border border-blue-500/30 bg-blue-500/10 text-blue-400`,children:[a.running,` running`]}),a.failed>0&&(0,y.jsxs)(h,{variant:`destructive`,children:[a.failed,` failing`]}),a.dueSoon>0&&(0,y.jsxs)(h,{className:`border border-yellow-500/30 bg-yellow-500/10 text-yellow-400`,children:[a.dueSoon,` due soon`]})]}),(0,y.jsxs)(g,{size:`sm`,variant:`outline`,onClick:()=>void n(),children:[(0,y.jsx)(i,{className:`h-3.5 w-3.5`}),` Refresh`]})]}),(0,y.jsx)(_,{className:`h-[calc(100dvh-10rem)]`,children:t.length===0?(0,y.jsx)(`div`,{className:`rounded-md border border-border px-3 py-12 text-center text-sm text-muted-foreground`,children:`No maintenance jobs registered`}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`div`,{className:`hidden overflow-x-auto rounded-md border border-border md:block`,children:(0,y.jsxs)(`table`,{className:`w-full min-w-[980px] text-sm`,children:[(0,y.jsx)(`thead`,{className:`bg-muted/40 text-xs text-muted-foreground`,children:(0,y.jsxs)(`tr`,{children:[(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Job`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Status`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Last run`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Next run`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Duration`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Result`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-right font-medium`,children:`Action`})]})}),(0,y.jsx)(`tbody`,{children:t.map(t=>(0,y.jsx)(T,{job:t,now:e,onRun:()=>void r(t.id)},t.id))})]})}),(0,y.jsx)(`div`,{className:`space-y-3 md:hidden`,children:t.map(t=>(0,y.jsx)(w,{job:t,now:e,onRun:()=>void r(t.id)},t.id))})]})})]})}function S(e){return e.running?`running`:e.enabled?e.lastStatus:`disabled`}function C({status:e}){return(0,y.jsxs)(h,{variant:`outline`,className:t(`border`,b[e]||b.idle),children:[E(e),e]})}function w({job:e,now:t,onRun:n}){let r=S(e);return(0,y.jsxs)(`div`,{className:`rounded-md border border-border p-3`,children:[(0,y.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,y.jsxs)(`div`,{className:`min-w-0`,children:[(0,y.jsx)(`div`,{className:`font-medium`,children:e.title}),(0,y.jsx)(`div`,{className:`mt-0.5 text-xs text-muted-foreground`,children:e.description}),(0,y.jsx)(`div`,{className:`mt-1 font-mono text-[11px] text-muted-foreground/80`,children:e.id})]}),(0,y.jsx)(C,{status:r})]}),e.consecutiveFailures>0&&(0,y.jsxs)(`div`,{className:`mt-2 text-xs text-red-400`,children:[e.consecutiveFailures,` failure`,e.consecutiveFailures===1?``:`s`]}),(0,y.jsxs)(`dl`,{className:`mt-3 grid grid-cols-3 gap-2 text-xs`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`dt`,{className:`text-muted-foreground`,children:`Last run`}),(0,y.jsx)(`dd`,{children:e.lastRunAt?(0,y.jsx)(`span`,{title:p(e.lastRunAt),children:m(t,e.lastRunAt)}):`never`})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`dt`,{className:`text-muted-foreground`,children:`Next run`}),(0,y.jsx)(`dd`,{children:e.nextRunAt?(0,y.jsx)(`span`,{title:p(e.nextRunAt),children:O(t,e.nextRunAt)}):`-`})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`dt`,{className:`text-muted-foreground`,children:`Duration`}),(0,y.jsx)(`dd`,{children:e.lastDurationMs===void 0?`-`:`${e.lastDurationMs}ms`})]})]}),(0,y.jsxs)(`div`,{className:`mt-3`,children:[(0,y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Result`}),e.lastError?(0,y.jsx)(`div`,{className:`mt-0.5 text-xs text-red-400 line-clamp-3`,children:e.lastError}):(0,y.jsx)(`div`,{className:`mt-0.5 font-mono text-[11px] text-muted-foreground line-clamp-3`,children:D(e)})]}),(0,y.jsx)(`div`,{className:`mt-3 flex justify-end`,children:(0,y.jsxs)(g,{size:`sm`,variant:`outline`,disabled:!e.enabled||e.running,onClick:n,children:[(0,y.jsx)(a,{className:`h-3.5 w-3.5`}),` Run`]})})]})}function T({job:e,now:t,onRun:n}){let r=S(e);return(0,y.jsxs)(`tr`,{className:`border-t border-border align-top`,children:[(0,y.jsxs)(`td`,{className:`px-3 py-3`,children:[(0,y.jsx)(`div`,{className:`font-medium`,children:e.title}),(0,y.jsx)(`div`,{className:`mt-0.5 max-w-md text-xs text-muted-foreground`,children:e.description}),(0,y.jsx)(`div`,{className:`mt-1 font-mono text-[11px] text-muted-foreground/80`,children:e.id})]}),(0,y.jsxs)(`td`,{className:`px-3 py-3`,children:[(0,y.jsx)(C,{status:r}),e.consecutiveFailures>0&&(0,y.jsxs)(`div`,{className:`mt-1 text-xs text-red-400`,children:[e.consecutiveFailures,` failure`,e.consecutiveFailures===1?``:`s`]})]}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-xs text-muted-foreground`,children:e.lastRunAt?(0,y.jsx)(`span`,{title:p(e.lastRunAt),children:m(t,e.lastRunAt)}):`never`}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-xs text-muted-foreground`,children:e.nextRunAt?(0,y.jsx)(`span`,{title:p(e.nextRunAt),children:O(t,e.nextRunAt)}):`-`}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-xs text-muted-foreground`,children:e.lastDurationMs===void 0?`-`:`${e.lastDurationMs}ms`}),(0,y.jsx)(`td`,{className:`px-3 py-3`,children:e.lastError?(0,y.jsx)(`div`,{className:`max-w-sm text-xs text-red-400 line-clamp-3`,children:e.lastError}):(0,y.jsx)(`div`,{className:`max-w-sm font-mono text-[11px] text-muted-foreground line-clamp-3`,children:D(e)})}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-right`,children:(0,y.jsxs)(g,{size:`sm`,variant:`outline`,disabled:!e.enabled||e.running,onClick:n,children:[(0,y.jsx)(a,{className:`h-3.5 w-3.5`}),` Run`]})})]})}function E(e){return e===`succeeded`?(0,y.jsx)(s,{className:`mr-1 h-3 w-3`}):e===`running`?(0,y.jsx)(n,{className:`mr-1 h-3 w-3`}):e===`failed`?(0,y.jsx)(u,{className:`mr-1 h-3 w-3`}):(0,y.jsx)(r,{className:`mr-1 h-3 w-3`})}function D(e){if(!e.lastResult)return`-`;let t=Object.entries(e.lastResult).filter(([,e])=>Array.isArray(e)?e.length>0:e!=null&&e!==0).map(([e,t])=>`${e}: ${Array.isArray(t)?t.length:String(t)}`);return t.length?t.join(`, `):`no changes`}function O(e,t){if(t<=e)return`due now`;let n=Math.max(0,(t-e)/1e3);return n<60?`in ${Math.ceil(n)}s`:n<3600?`in ${Math.ceil(n/60)}m`:n<86400?`in ${Math.ceil(n/3600)}h`:`in ${Math.ceil(n/86400)}d`}export{x as MaintenanceView};
2
- //# sourceMappingURL=maintenance-CUxxVXsc.js.map
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{Dn as t,En as n,Gt as r,M as i,R as a,Vn as o,Zt as s,a as c,kn as l,p as u}from"./lucide-react-CD8Xl2U3.js";import{i as d,t as f}from"./store-CICRhg1m.js";import{m as p,z as m}from"./display-Bebqs1qu.js";import{t as h}from"./badge-t8zAwHW9.js";import{t as g}from"./button-DDA5P2YQ.js";import{s as _}from"./index-BL8r94_U.js";var v=e(o(),1),y=l(),b={succeeded:`bg-emerald-500/10 text-emerald-400 border-emerald-500/30`,running:`bg-blue-500/10 text-blue-400 border-blue-500/30`,failed:`bg-red-500/10 text-red-400 border-red-500/30`,idle:`bg-zinc-500/10 text-zinc-400 border-zinc-500/30`,disabled:`bg-zinc-500/10 text-zinc-500 border-zinc-500/20`};function x(){let e=d(),t=f(e=>e.maintenanceJobs),n=f(e=>e.fetchMaintenanceJobs),r=f(e=>e.runMaintenanceJob),a=(0,v.useMemo)(()=>({failed:t.filter(e=>e.lastStatus===`failed`).length,running:t.filter(e=>e.running||e.lastStatus===`running`).length,dueSoon:t.filter(t=>t.nextRunAt&&t.nextRunAt<=e+300*1e3).length}),[t,e]);return(0,y.jsxs)(`div`,{className:`space-y-4`,children:[(0,y.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,y.jsx)(c,{className:`h-5 w-5 text-muted-foreground`}),(0,y.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Maintenance`}),(0,y.jsx)(h,{variant:`secondary`,children:t.length}),a.running>0&&(0,y.jsxs)(h,{className:`border border-blue-500/30 bg-blue-500/10 text-blue-400`,children:[a.running,` running`]}),a.failed>0&&(0,y.jsxs)(h,{variant:`destructive`,children:[a.failed,` failing`]}),a.dueSoon>0&&(0,y.jsxs)(h,{className:`border border-yellow-500/30 bg-yellow-500/10 text-yellow-400`,children:[a.dueSoon,` due soon`]})]}),(0,y.jsxs)(g,{size:`sm`,variant:`outline`,onClick:()=>void n(),children:[(0,y.jsx)(i,{className:`h-3.5 w-3.5`}),` Refresh`]})]}),(0,y.jsx)(_,{className:`h-[calc(100dvh-10rem)]`,children:t.length===0?(0,y.jsx)(`div`,{className:`rounded-md border border-border px-3 py-12 text-center text-sm text-muted-foreground`,children:`No maintenance jobs registered`}):(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`div`,{className:`hidden overflow-x-auto rounded-md border border-border md:block`,children:(0,y.jsxs)(`table`,{className:`w-full min-w-[980px] text-sm`,children:[(0,y.jsx)(`thead`,{className:`bg-muted/40 text-xs text-muted-foreground`,children:(0,y.jsxs)(`tr`,{children:[(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Job`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Status`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Last run`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Next run`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Duration`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-left font-medium`,children:`Result`}),(0,y.jsx)(`th`,{className:`px-3 py-2 text-right font-medium`,children:`Action`})]})}),(0,y.jsx)(`tbody`,{children:t.map(t=>(0,y.jsx)(T,{job:t,now:e,onRun:()=>void r(t.id)},t.id))})]})}),(0,y.jsx)(`div`,{className:`space-y-3 md:hidden`,children:t.map(t=>(0,y.jsx)(w,{job:t,now:e,onRun:()=>void r(t.id)},t.id))})]})})]})}function S(e){return e.running?`running`:e.enabled?e.lastStatus:`disabled`}function C({status:e}){return(0,y.jsxs)(h,{variant:`outline`,className:t(`border`,b[e]||b.idle),children:[E(e),e]})}function w({job:e,now:t,onRun:n}){let r=S(e);return(0,y.jsxs)(`div`,{className:`rounded-md border border-border p-3`,children:[(0,y.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,y.jsxs)(`div`,{className:`min-w-0`,children:[(0,y.jsx)(`div`,{className:`font-medium`,children:e.title}),(0,y.jsx)(`div`,{className:`mt-0.5 text-xs text-muted-foreground`,children:e.description}),(0,y.jsx)(`div`,{className:`mt-1 font-mono text-[11px] text-muted-foreground/80`,children:e.id})]}),(0,y.jsx)(C,{status:r})]}),e.consecutiveFailures>0&&(0,y.jsxs)(`div`,{className:`mt-2 text-xs text-red-400`,children:[e.consecutiveFailures,` failure`,e.consecutiveFailures===1?``:`s`]}),(0,y.jsxs)(`dl`,{className:`mt-3 grid grid-cols-3 gap-2 text-xs`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`dt`,{className:`text-muted-foreground`,children:`Last run`}),(0,y.jsx)(`dd`,{children:e.lastRunAt?(0,y.jsx)(`span`,{title:p(e.lastRunAt),children:m(t,e.lastRunAt)}):`never`})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`dt`,{className:`text-muted-foreground`,children:`Next run`}),(0,y.jsx)(`dd`,{children:e.nextRunAt?(0,y.jsx)(`span`,{title:p(e.nextRunAt),children:O(t,e.nextRunAt)}):`-`})]}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`dt`,{className:`text-muted-foreground`,children:`Duration`}),(0,y.jsx)(`dd`,{children:e.lastDurationMs===void 0?`-`:`${e.lastDurationMs}ms`})]})]}),(0,y.jsxs)(`div`,{className:`mt-3`,children:[(0,y.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`Result`}),e.lastError?(0,y.jsx)(`div`,{className:`mt-0.5 text-xs text-red-400 line-clamp-3`,children:e.lastError}):(0,y.jsx)(`div`,{className:`mt-0.5 font-mono text-[11px] text-muted-foreground line-clamp-3`,children:D(e)})]}),(0,y.jsx)(`div`,{className:`mt-3 flex justify-end`,children:(0,y.jsxs)(g,{size:`sm`,variant:`outline`,disabled:!e.enabled||e.running,onClick:n,children:[(0,y.jsx)(a,{className:`h-3.5 w-3.5`}),` Run`]})})]})}function T({job:e,now:t,onRun:n}){let r=S(e);return(0,y.jsxs)(`tr`,{className:`border-t border-border align-top`,children:[(0,y.jsxs)(`td`,{className:`px-3 py-3`,children:[(0,y.jsx)(`div`,{className:`font-medium`,children:e.title}),(0,y.jsx)(`div`,{className:`mt-0.5 max-w-md text-xs text-muted-foreground`,children:e.description}),(0,y.jsx)(`div`,{className:`mt-1 font-mono text-[11px] text-muted-foreground/80`,children:e.id})]}),(0,y.jsxs)(`td`,{className:`px-3 py-3`,children:[(0,y.jsx)(C,{status:r}),e.consecutiveFailures>0&&(0,y.jsxs)(`div`,{className:`mt-1 text-xs text-red-400`,children:[e.consecutiveFailures,` failure`,e.consecutiveFailures===1?``:`s`]})]}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-xs text-muted-foreground`,children:e.lastRunAt?(0,y.jsx)(`span`,{title:p(e.lastRunAt),children:m(t,e.lastRunAt)}):`never`}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-xs text-muted-foreground`,children:e.nextRunAt?(0,y.jsx)(`span`,{title:p(e.nextRunAt),children:O(t,e.nextRunAt)}):`-`}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-xs text-muted-foreground`,children:e.lastDurationMs===void 0?`-`:`${e.lastDurationMs}ms`}),(0,y.jsx)(`td`,{className:`px-3 py-3`,children:e.lastError?(0,y.jsx)(`div`,{className:`max-w-sm text-xs text-red-400 line-clamp-3`,children:e.lastError}):(0,y.jsx)(`div`,{className:`max-w-sm font-mono text-[11px] text-muted-foreground line-clamp-3`,children:D(e)})}),(0,y.jsx)(`td`,{className:`px-3 py-3 text-right`,children:(0,y.jsxs)(g,{size:`sm`,variant:`outline`,disabled:!e.enabled||e.running,onClick:n,children:[(0,y.jsx)(a,{className:`h-3.5 w-3.5`}),` Run`]})})]})}function E(e){return e===`succeeded`?(0,y.jsx)(s,{className:`mr-1 h-3 w-3`}):e===`running`?(0,y.jsx)(n,{className:`mr-1 h-3 w-3`}):e===`failed`?(0,y.jsx)(u,{className:`mr-1 h-3 w-3`}):(0,y.jsx)(r,{className:`mr-1 h-3 w-3`})}function D(e){if(!e.lastResult)return`-`;let t=Object.entries(e.lastResult).filter(([,e])=>Array.isArray(e)?e.length>0:e!=null&&e!==0).map(([e,t])=>`${e}: ${Array.isArray(t)?t.length:String(t)}`);return t.length?t.join(`, `):`no changes`}function O(e,t){if(t<=e)return`due now`;let n=Math.max(0,(t-e)/1e3);return n<60?`in ${Math.ceil(n)}s`:n<3600?`in ${Math.ceil(n/60)}m`:n<86400?`in ${Math.ceil(n/3600)}h`:`in ${Math.ceil(n/86400)}d`}export{x as MaintenanceView};
2
+ //# sourceMappingURL=maintenance-DtfpsMZa.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"maintenance-CUxxVXsc.js","names":[],"sources":["../../dashboard/src/components/views/maintenance.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { Activity, AlertTriangle, CheckCircle2, Clock3, Play, RefreshCw, Wrench } from 'lucide-react'\nimport { useRelayStore, useNow } from '@/store'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { cn } from '@/lib/utils'\nimport { fmtTime, timeAgo } from '@/lib/display'\nimport type { MaintenanceJob } from '@/types'\n\nconst STATUS_CLASS: Record<string, string> = {\n succeeded: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30',\n running: 'bg-blue-500/10 text-blue-400 border-blue-500/30',\n failed: 'bg-red-500/10 text-red-400 border-red-500/30',\n idle: 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30',\n disabled: 'bg-zinc-500/10 text-zinc-500 border-zinc-500/20',\n}\n\nexport function MaintenanceView() {\n const now = useNow()\n const jobs = useRelayStore((s) => s.maintenanceJobs)\n const fetchMaintenanceJobs = useRelayStore((s) => s.fetchMaintenanceJobs)\n const runMaintenanceJob = useRelayStore((s) => s.runMaintenanceJob)\n\n const summary = useMemo(() => {\n const failed = jobs.filter((job) => job.lastStatus === 'failed').length\n const running = jobs.filter((job) => job.running || job.lastStatus === 'running').length\n const dueSoon = jobs.filter((job) => job.nextRunAt && job.nextRunAt <= now + 5 * 60 * 1000).length\n return { failed, running, dueSoon }\n }, [jobs, now])\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <Wrench className=\"h-5 w-5 text-muted-foreground\" />\n <h2 className=\"text-lg font-semibold\">Maintenance</h2>\n <Badge variant=\"secondary\">{jobs.length}</Badge>\n {summary.running > 0 && <Badge className=\"border border-blue-500/30 bg-blue-500/10 text-blue-400\">{summary.running} running</Badge>}\n {summary.failed > 0 && <Badge variant=\"destructive\">{summary.failed} failing</Badge>}\n {summary.dueSoon > 0 && <Badge className=\"border border-yellow-500/30 bg-yellow-500/10 text-yellow-400\">{summary.dueSoon} due soon</Badge>}\n </div>\n <Button size=\"sm\" variant=\"outline\" onClick={() => void fetchMaintenanceJobs()}>\n <RefreshCw className=\"h-3.5 w-3.5\" /> Refresh\n </Button>\n </div>\n\n <ScrollArea className=\"h-[calc(100dvh-10rem)]\">\n {jobs.length === 0 ? (\n <div className=\"rounded-md border border-border px-3 py-12 text-center text-sm text-muted-foreground\">No maintenance jobs registered</div>\n ) : (\n <>\n {/* Desktop / wide: full table */}\n <div className=\"hidden overflow-x-auto rounded-md border border-border md:block\">\n <table className=\"w-full min-w-[980px] text-sm\">\n <thead className=\"bg-muted/40 text-xs text-muted-foreground\">\n <tr>\n <th className=\"px-3 py-2 text-left font-medium\">Job</th>\n <th className=\"px-3 py-2 text-left font-medium\">Status</th>\n <th className=\"px-3 py-2 text-left font-medium\">Last run</th>\n <th className=\"px-3 py-2 text-left font-medium\">Next run</th>\n <th className=\"px-3 py-2 text-left font-medium\">Duration</th>\n <th className=\"px-3 py-2 text-left font-medium\">Result</th>\n <th className=\"px-3 py-2 text-right font-medium\">Action</th>\n </tr>\n </thead>\n <tbody>\n {jobs.map((job) => (\n <MaintenanceRow\n key={job.id}\n job={job}\n now={now}\n onRun={() => void runMaintenanceJob(job.id)}\n />\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile / narrow: stacked cards so every field is visible without horizontal scroll */}\n <div className=\"space-y-3 md:hidden\">\n {jobs.map((job) => (\n <MaintenanceCard\n key={job.id}\n job={job}\n now={now}\n onRun={() => void runMaintenanceJob(job.id)}\n />\n ))}\n </div>\n </>\n )}\n </ScrollArea>\n </div>\n )\n}\n\nfunction jobStatus(job: MaintenanceJob): string {\n return job.running ? 'running' : job.enabled ? job.lastStatus : 'disabled'\n}\n\nfunction StatusBadge({ status }: { status: string }) {\n return (\n <Badge variant=\"outline\" className={cn('border', STATUS_CLASS[status] || STATUS_CLASS.idle)}>\n {statusIcon(status)}\n {status}\n </Badge>\n )\n}\n\nfunction MaintenanceCard({ job, now, onRun }: { job: MaintenanceJob; now: number; onRun: () => void }) {\n const status = jobStatus(job)\n return (\n <div className=\"rounded-md border border-border p-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"font-medium\">{job.title}</div>\n <div className=\"mt-0.5 text-xs text-muted-foreground\">{job.description}</div>\n <div className=\"mt-1 font-mono text-[11px] text-muted-foreground/80\">{job.id}</div>\n </div>\n <StatusBadge status={status} />\n </div>\n\n {job.consecutiveFailures > 0 && (\n <div className=\"mt-2 text-xs text-red-400\">{job.consecutiveFailures} failure{job.consecutiveFailures === 1 ? '' : 's'}</div>\n )}\n\n <dl className=\"mt-3 grid grid-cols-3 gap-2 text-xs\">\n <div>\n <dt className=\"text-muted-foreground\">Last run</dt>\n <dd>{job.lastRunAt ? <span title={fmtTime(job.lastRunAt)}>{timeAgo(now, job.lastRunAt)}</span> : 'never'}</dd>\n </div>\n <div>\n <dt className=\"text-muted-foreground\">Next run</dt>\n <dd>{job.nextRunAt ? <span title={fmtTime(job.nextRunAt)}>{nextRunText(now, job.nextRunAt)}</span> : '-'}</dd>\n </div>\n <div>\n <dt className=\"text-muted-foreground\">Duration</dt>\n <dd>{job.lastDurationMs !== undefined ? `${job.lastDurationMs}ms` : '-'}</dd>\n </div>\n </dl>\n\n <div className=\"mt-3\">\n <div className=\"text-xs text-muted-foreground\">Result</div>\n {job.lastError ? (\n <div className=\"mt-0.5 text-xs text-red-400 line-clamp-3\">{job.lastError}</div>\n ) : (\n <div className=\"mt-0.5 font-mono text-[11px] text-muted-foreground line-clamp-3\">{resultSummary(job)}</div>\n )}\n </div>\n\n <div className=\"mt-3 flex justify-end\">\n <Button size=\"sm\" variant=\"outline\" disabled={!job.enabled || job.running} onClick={onRun}>\n <Play className=\"h-3.5 w-3.5\" /> Run\n </Button>\n </div>\n </div>\n )\n}\n\nfunction MaintenanceRow({ job, now, onRun }: { job: MaintenanceJob; now: number; onRun: () => void }) {\n const status = jobStatus(job)\n return (\n <tr className=\"border-t border-border align-top\">\n <td className=\"px-3 py-3\">\n <div className=\"font-medium\">{job.title}</div>\n <div className=\"mt-0.5 max-w-md text-xs text-muted-foreground\">{job.description}</div>\n <div className=\"mt-1 font-mono text-[11px] text-muted-foreground/80\">{job.id}</div>\n </td>\n <td className=\"px-3 py-3\">\n <StatusBadge status={status} />\n {job.consecutiveFailures > 0 && (\n <div className=\"mt-1 text-xs text-red-400\">{job.consecutiveFailures} failure{job.consecutiveFailures === 1 ? '' : 's'}</div>\n )}\n </td>\n <td className=\"px-3 py-3 text-xs text-muted-foreground\">\n {job.lastRunAt ? (\n <span title={fmtTime(job.lastRunAt)}>{timeAgo(now, job.lastRunAt)}</span>\n ) : 'never'}\n </td>\n <td className=\"px-3 py-3 text-xs text-muted-foreground\">\n {job.nextRunAt ? (\n <span title={fmtTime(job.nextRunAt)}>{nextRunText(now, job.nextRunAt)}</span>\n ) : '-'}\n </td>\n <td className=\"px-3 py-3 text-xs text-muted-foreground\">\n {job.lastDurationMs !== undefined ? `${job.lastDurationMs}ms` : '-'}\n </td>\n <td className=\"px-3 py-3\">\n {job.lastError ? (\n <div className=\"max-w-sm text-xs text-red-400 line-clamp-3\">{job.lastError}</div>\n ) : (\n <div className=\"max-w-sm font-mono text-[11px] text-muted-foreground line-clamp-3\">{resultSummary(job)}</div>\n )}\n </td>\n <td className=\"px-3 py-3 text-right\">\n <Button size=\"sm\" variant=\"outline\" disabled={!job.enabled || job.running} onClick={onRun}>\n <Play className=\"h-3.5 w-3.5\" /> Run\n </Button>\n </td>\n </tr>\n )\n}\n\nfunction statusIcon(status: string) {\n if (status === 'succeeded') return <CheckCircle2 className=\"mr-1 h-3 w-3\" />\n if (status === 'running') return <Activity className=\"mr-1 h-3 w-3\" />\n if (status === 'failed') return <AlertTriangle className=\"mr-1 h-3 w-3\" />\n return <Clock3 className=\"mr-1 h-3 w-3\" />\n}\n\nfunction resultSummary(job: MaintenanceJob): string {\n if (!job.lastResult) return '-'\n const entries = Object.entries(job.lastResult)\n .filter(([, value]) => Array.isArray(value) ? value.length > 0 : value !== undefined && value !== null && value !== 0)\n .map(([key, value]) => `${key}: ${Array.isArray(value) ? value.length : String(value)}`)\n return entries.length ? entries.join(', ') : 'no changes'\n}\n\nfunction nextRunText(now: number, nextRunAt: number): string {\n if (nextRunAt <= now) return 'due now'\n const diff = Math.max(0, (nextRunAt - now) / 1000)\n if (diff < 60) return `in ${Math.ceil(diff)}s`\n if (diff < 3600) return `in ${Math.ceil(diff / 60)}m`\n if (diff < 86400) return `in ${Math.ceil(diff / 3600)}h`\n return `in ${Math.ceil(diff / 86400)}d`\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"maintenance-DtfpsMZa.js","names":[],"sources":["../../dashboard/src/components/views/maintenance.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { Activity, AlertTriangle, CheckCircle2, Clock3, Play, RefreshCw, Wrench } from 'lucide-react'\nimport { useRelayStore, useNow } from '@/store'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { cn } from '@/lib/utils'\nimport { fmtTime, timeAgo } from '@/lib/display'\nimport type { MaintenanceJob } from '@/types'\n\nconst STATUS_CLASS: Record<string, string> = {\n succeeded: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/30',\n running: 'bg-blue-500/10 text-blue-400 border-blue-500/30',\n failed: 'bg-red-500/10 text-red-400 border-red-500/30',\n idle: 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30',\n disabled: 'bg-zinc-500/10 text-zinc-500 border-zinc-500/20',\n}\n\nexport function MaintenanceView() {\n const now = useNow()\n const jobs = useRelayStore((s) => s.maintenanceJobs)\n const fetchMaintenanceJobs = useRelayStore((s) => s.fetchMaintenanceJobs)\n const runMaintenanceJob = useRelayStore((s) => s.runMaintenanceJob)\n\n const summary = useMemo(() => {\n const failed = jobs.filter((job) => job.lastStatus === 'failed').length\n const running = jobs.filter((job) => job.running || job.lastStatus === 'running').length\n const dueSoon = jobs.filter((job) => job.nextRunAt && job.nextRunAt <= now + 5 * 60 * 1000).length\n return { failed, running, dueSoon }\n }, [jobs, now])\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <Wrench className=\"h-5 w-5 text-muted-foreground\" />\n <h2 className=\"text-lg font-semibold\">Maintenance</h2>\n <Badge variant=\"secondary\">{jobs.length}</Badge>\n {summary.running > 0 && <Badge className=\"border border-blue-500/30 bg-blue-500/10 text-blue-400\">{summary.running} running</Badge>}\n {summary.failed > 0 && <Badge variant=\"destructive\">{summary.failed} failing</Badge>}\n {summary.dueSoon > 0 && <Badge className=\"border border-yellow-500/30 bg-yellow-500/10 text-yellow-400\">{summary.dueSoon} due soon</Badge>}\n </div>\n <Button size=\"sm\" variant=\"outline\" onClick={() => void fetchMaintenanceJobs()}>\n <RefreshCw className=\"h-3.5 w-3.5\" /> Refresh\n </Button>\n </div>\n\n <ScrollArea className=\"h-[calc(100dvh-10rem)]\">\n {jobs.length === 0 ? (\n <div className=\"rounded-md border border-border px-3 py-12 text-center text-sm text-muted-foreground\">No maintenance jobs registered</div>\n ) : (\n <>\n {/* Desktop / wide: full table */}\n <div className=\"hidden overflow-x-auto rounded-md border border-border md:block\">\n <table className=\"w-full min-w-[980px] text-sm\">\n <thead className=\"bg-muted/40 text-xs text-muted-foreground\">\n <tr>\n <th className=\"px-3 py-2 text-left font-medium\">Job</th>\n <th className=\"px-3 py-2 text-left font-medium\">Status</th>\n <th className=\"px-3 py-2 text-left font-medium\">Last run</th>\n <th className=\"px-3 py-2 text-left font-medium\">Next run</th>\n <th className=\"px-3 py-2 text-left font-medium\">Duration</th>\n <th className=\"px-3 py-2 text-left font-medium\">Result</th>\n <th className=\"px-3 py-2 text-right font-medium\">Action</th>\n </tr>\n </thead>\n <tbody>\n {jobs.map((job) => (\n <MaintenanceRow\n key={job.id}\n job={job}\n now={now}\n onRun={() => void runMaintenanceJob(job.id)}\n />\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Mobile / narrow: stacked cards so every field is visible without horizontal scroll */}\n <div className=\"space-y-3 md:hidden\">\n {jobs.map((job) => (\n <MaintenanceCard\n key={job.id}\n job={job}\n now={now}\n onRun={() => void runMaintenanceJob(job.id)}\n />\n ))}\n </div>\n </>\n )}\n </ScrollArea>\n </div>\n )\n}\n\nfunction jobStatus(job: MaintenanceJob): string {\n return job.running ? 'running' : job.enabled ? job.lastStatus : 'disabled'\n}\n\nfunction StatusBadge({ status }: { status: string }) {\n return (\n <Badge variant=\"outline\" className={cn('border', STATUS_CLASS[status] || STATUS_CLASS.idle)}>\n {statusIcon(status)}\n {status}\n </Badge>\n )\n}\n\nfunction MaintenanceCard({ job, now, onRun }: { job: MaintenanceJob; now: number; onRun: () => void }) {\n const status = jobStatus(job)\n return (\n <div className=\"rounded-md border border-border p-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"font-medium\">{job.title}</div>\n <div className=\"mt-0.5 text-xs text-muted-foreground\">{job.description}</div>\n <div className=\"mt-1 font-mono text-[11px] text-muted-foreground/80\">{job.id}</div>\n </div>\n <StatusBadge status={status} />\n </div>\n\n {job.consecutiveFailures > 0 && (\n <div className=\"mt-2 text-xs text-red-400\">{job.consecutiveFailures} failure{job.consecutiveFailures === 1 ? '' : 's'}</div>\n )}\n\n <dl className=\"mt-3 grid grid-cols-3 gap-2 text-xs\">\n <div>\n <dt className=\"text-muted-foreground\">Last run</dt>\n <dd>{job.lastRunAt ? <span title={fmtTime(job.lastRunAt)}>{timeAgo(now, job.lastRunAt)}</span> : 'never'}</dd>\n </div>\n <div>\n <dt className=\"text-muted-foreground\">Next run</dt>\n <dd>{job.nextRunAt ? <span title={fmtTime(job.nextRunAt)}>{nextRunText(now, job.nextRunAt)}</span> : '-'}</dd>\n </div>\n <div>\n <dt className=\"text-muted-foreground\">Duration</dt>\n <dd>{job.lastDurationMs !== undefined ? `${job.lastDurationMs}ms` : '-'}</dd>\n </div>\n </dl>\n\n <div className=\"mt-3\">\n <div className=\"text-xs text-muted-foreground\">Result</div>\n {job.lastError ? (\n <div className=\"mt-0.5 text-xs text-red-400 line-clamp-3\">{job.lastError}</div>\n ) : (\n <div className=\"mt-0.5 font-mono text-[11px] text-muted-foreground line-clamp-3\">{resultSummary(job)}</div>\n )}\n </div>\n\n <div className=\"mt-3 flex justify-end\">\n <Button size=\"sm\" variant=\"outline\" disabled={!job.enabled || job.running} onClick={onRun}>\n <Play className=\"h-3.5 w-3.5\" /> Run\n </Button>\n </div>\n </div>\n )\n}\n\nfunction MaintenanceRow({ job, now, onRun }: { job: MaintenanceJob; now: number; onRun: () => void }) {\n const status = jobStatus(job)\n return (\n <tr className=\"border-t border-border align-top\">\n <td className=\"px-3 py-3\">\n <div className=\"font-medium\">{job.title}</div>\n <div className=\"mt-0.5 max-w-md text-xs text-muted-foreground\">{job.description}</div>\n <div className=\"mt-1 font-mono text-[11px] text-muted-foreground/80\">{job.id}</div>\n </td>\n <td className=\"px-3 py-3\">\n <StatusBadge status={status} />\n {job.consecutiveFailures > 0 && (\n <div className=\"mt-1 text-xs text-red-400\">{job.consecutiveFailures} failure{job.consecutiveFailures === 1 ? '' : 's'}</div>\n )}\n </td>\n <td className=\"px-3 py-3 text-xs text-muted-foreground\">\n {job.lastRunAt ? (\n <span title={fmtTime(job.lastRunAt)}>{timeAgo(now, job.lastRunAt)}</span>\n ) : 'never'}\n </td>\n <td className=\"px-3 py-3 text-xs text-muted-foreground\">\n {job.nextRunAt ? (\n <span title={fmtTime(job.nextRunAt)}>{nextRunText(now, job.nextRunAt)}</span>\n ) : '-'}\n </td>\n <td className=\"px-3 py-3 text-xs text-muted-foreground\">\n {job.lastDurationMs !== undefined ? `${job.lastDurationMs}ms` : '-'}\n </td>\n <td className=\"px-3 py-3\">\n {job.lastError ? (\n <div className=\"max-w-sm text-xs text-red-400 line-clamp-3\">{job.lastError}</div>\n ) : (\n <div className=\"max-w-sm font-mono text-[11px] text-muted-foreground line-clamp-3\">{resultSummary(job)}</div>\n )}\n </td>\n <td className=\"px-3 py-3 text-right\">\n <Button size=\"sm\" variant=\"outline\" disabled={!job.enabled || job.running} onClick={onRun}>\n <Play className=\"h-3.5 w-3.5\" /> Run\n </Button>\n </td>\n </tr>\n )\n}\n\nfunction statusIcon(status: string) {\n if (status === 'succeeded') return <CheckCircle2 className=\"mr-1 h-3 w-3\" />\n if (status === 'running') return <Activity className=\"mr-1 h-3 w-3\" />\n if (status === 'failed') return <AlertTriangle className=\"mr-1 h-3 w-3\" />\n return <Clock3 className=\"mr-1 h-3 w-3\" />\n}\n\nfunction resultSummary(job: MaintenanceJob): string {\n if (!job.lastResult) return '-'\n const entries = Object.entries(job.lastResult)\n .filter(([, value]) => Array.isArray(value) ? value.length > 0 : value !== undefined && value !== null && value !== 0)\n .map(([key, value]) => `${key}: ${Array.isArray(value) ? value.length : String(value)}`)\n return entries.length ? entries.join(', ') : 'no changes'\n}\n\nfunction nextRunText(now: number, nextRunAt: number): string {\n if (nextRunAt <= now) return 'due now'\n const diff = Math.max(0, (nextRunAt - now) / 1000)\n if (diff < 60) return `in ${Math.ceil(diff)}s`\n if (diff < 3600) return `in ${Math.ceil(diff / 60)}m`\n if (diff < 86400) return `in ${Math.ceil(diff / 3600)}h`\n return `in ${Math.ceil(diff / 86400)}d`\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Dn as t,I as n,R as r,Vn as i,g as a,k as o,kn as s,kt as c,m as l,y as u,z as d}from"./lucide-react-CD8Xl2U3.js";import{t as f}from"./store-CICRhg1m.js";import{m as p}from"./display-Bebqs1qu.js";import{t as m}from"./button-DDA5P2YQ.js";import{c as h,l as g}from"./index-CvSlyTSI.js";var _=e(i(),1),v=s(),y={running:`bg-emerald-500/15 text-emerald-400 border-emerald-500/30`,starting:`bg-blue-500/15 text-blue-400 border-blue-500/30`,stopping:`bg-yellow-500/15 text-yellow-400 border-yellow-500/30`,backoff:`bg-red-500/15 text-red-400 border-red-500/30`,stopped:`bg-muted text-muted-foreground border-border`};function b({status:e}){return(0,v.jsx)(`span`,{className:t(`inline-flex items-center rounded border px-2 py-0.5 text-xs font-medium`,y[e]),children:e})}function x(e,t){let n=t?.meta?.tmuxSession;return typeof n==`string`&&n.trim()?n:e.state.tmuxSession}function S(e,t){return x(e,t)?t?!!t.providerCapabilities?.terminal?.live?.read:e.policy.provider===`claude`:!1}function C(e,t){return S(e,t)?t?!!(t.providerCapabilities?.terminal?.live?.write||e.policy.provider===`claude`):e.policy.provider===`claude`:!1}function w(){let e=f(e=>e.managedPolicies),t=f(e=>e.agentsById),i=f(e=>e.fetchManagedPolicies),s=f(e=>e.apiCall),y=f(e=>e.openPolicyCreate),w=f(e=>e.openPolicyEdit),T=f(e=>e.deletePolicy),[E,D]=(0,_.useState)(null),[O,k]=(0,_.useState)(null);(0,_.useEffect)(()=>{i()},[]);async function A(e,t){await s(`POST`,`/spawn-policy/${encodeURIComponent(e)}/${t}`,{surface:{component:`managed-agents`}}),await i()}return(0,v.jsxs)(`div`,{className:`space-y-4`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,v.jsxs)(`div`,{children:[(0,v.jsx)(`h1`,{className:`text-2xl font-semibold`,children:`Managed Agents`}),(0,v.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Spawn policies, lifecycle state, and headless session logs.`})]}),(0,v.jsxs)(m,{onClick:y,size:`sm`,children:[(0,v.jsx)(n,{className:`h-4 w-4 mr-1`}),`Create Policy`]})]}),e.length===0&&(0,v.jsx)(`div`,{className:`rounded-md border border-border px-3 py-8 text-center text-sm text-muted-foreground`,children:`No managed agents configured`}),(0,v.jsx)(`div`,{className:`grid gap-3 sm:grid-cols-2 lg:grid-cols-3`,children:e.map(e=>{let n=e.state.agentId?t[e.state.agentId]:void 0,i=x(e,n);return(0,v.jsxs)(`div`,{className:`rounded-md border border-border bg-card p-3 space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,v.jsxs)(`div`,{className:`min-w-0`,children:[(0,v.jsx)(`div`,{className:`font-medium text-sm truncate`,children:e.policy.label||e.policy.name}),(0,v.jsxs)(`div`,{className:`text-xs text-muted-foreground truncate`,children:[e.policy.mode,` · `,e.policy.cwd]})]}),(0,v.jsx)(b,{status:e.state.status})]}),(0,v.jsxs)(`div`,{className:`grid grid-cols-2 gap-x-4 gap-y-1 text-xs`,children:[(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:`Provider`}),(0,v.jsx)(`div`,{children:e.policy.provider}),(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:`Agent`}),(0,v.jsx)(`div`,{className:`font-mono truncate`,children:e.state.agentId||`-`}),(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:`Restarts`}),(0,v.jsx)(`div`,{children:e.state.restartCount}),(e.state.backoffUntil||e.state.lastError)&&(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:e.state.backoffUntil?`Backoff`:`Error`}),(0,v.jsx)(`div`,{className:`truncate`,children:e.state.backoffUntil?p(e.state.backoffUntil):e.state.lastError})]})]}),(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-1 pt-1 border-t border-border`,children:[(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>A(e.policy.name,`start`),title:`Start`,children:(0,v.jsx)(r,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>A(e.policy.name,`stop`),title:`Stop`,children:(0,v.jsx)(u,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>A(e.policy.name,`restart`),title:`Restart`,children:(0,v.jsx)(o,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>D(e),disabled:!e.state.tmuxSession,title:`Logs`,children:(0,v.jsx)(c,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>i&&k({item:e,session:i}),disabled:!S(e,n),title:`Terminal`,children:(0,v.jsx)(a,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>w(e.policy),title:`Edit`,children:(0,v.jsx)(d,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>T(e.policy.name),title:`Delete`,children:(0,v.jsx)(l,{className:`h-3.5 w-3.5`})})]})]},e.policy.name)})}),E?.state.tmuxSession&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,v.jsxs)(`h2`,{className:`text-lg font-semibold`,children:[E.policy.name,` Logs`]}),(0,v.jsx)(m,{variant:`outline`,size:`sm`,onClick:()=>D(null),children:`Close`})]}),(0,v.jsx)(h,{orchestratorId:E.policy.orchestratorId,session:E.state.tmuxSession})]}),(0,v.jsx)(g,{open:!!O,onOpenChange:e=>{e||k(null)},orchestratorId:O?.item.policy.orchestratorId??``,session:O?.session??``,interactive:O?C(O.item,O.item.state.agentId?t[O.item.state.agentId]:void 0):!1})]})}export{w as ManagedAgentsView};
2
- //# sourceMappingURL=managed-agents-VZEeMMSP.js.map
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{Dn as t,I as n,R as r,Vn as i,g as a,k as o,kn as s,kt as c,m as l,y as u,z as d}from"./lucide-react-CD8Xl2U3.js";import{t as f}from"./store-CICRhg1m.js";import{m as p}from"./display-Bebqs1qu.js";import{t as m}from"./button-DDA5P2YQ.js";import{c as h,l as g}from"./index-BL8r94_U.js";var _=e(i(),1),v=s(),y={running:`bg-emerald-500/15 text-emerald-400 border-emerald-500/30`,starting:`bg-blue-500/15 text-blue-400 border-blue-500/30`,stopping:`bg-yellow-500/15 text-yellow-400 border-yellow-500/30`,backoff:`bg-red-500/15 text-red-400 border-red-500/30`,stopped:`bg-muted text-muted-foreground border-border`};function b({status:e}){return(0,v.jsx)(`span`,{className:t(`inline-flex items-center rounded border px-2 py-0.5 text-xs font-medium`,y[e]),children:e})}function x(e,t){let n=t?.meta?.tmuxSession;return typeof n==`string`&&n.trim()?n:e.state.tmuxSession}function S(e,t){return x(e,t)?t?!!t.providerCapabilities?.terminal?.live?.read:e.policy.provider===`claude`:!1}function C(e,t){return S(e,t)?t?!!(t.providerCapabilities?.terminal?.live?.write||e.policy.provider===`claude`):e.policy.provider===`claude`:!1}function w(){let e=f(e=>e.managedPolicies),t=f(e=>e.agentsById),i=f(e=>e.fetchManagedPolicies),s=f(e=>e.apiCall),y=f(e=>e.openPolicyCreate),w=f(e=>e.openPolicyEdit),T=f(e=>e.deletePolicy),[E,D]=(0,_.useState)(null),[O,k]=(0,_.useState)(null);(0,_.useEffect)(()=>{i()},[]);async function A(e,t){await s(`POST`,`/spawn-policy/${encodeURIComponent(e)}/${t}`,{surface:{component:`managed-agents`}}),await i()}return(0,v.jsxs)(`div`,{className:`space-y-4`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,v.jsxs)(`div`,{children:[(0,v.jsx)(`h1`,{className:`text-2xl font-semibold`,children:`Managed Agents`}),(0,v.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Spawn policies, lifecycle state, and headless session logs.`})]}),(0,v.jsxs)(m,{onClick:y,size:`sm`,children:[(0,v.jsx)(n,{className:`h-4 w-4 mr-1`}),`Create Policy`]})]}),e.length===0&&(0,v.jsx)(`div`,{className:`rounded-md border border-border px-3 py-8 text-center text-sm text-muted-foreground`,children:`No managed agents configured`}),(0,v.jsx)(`div`,{className:`grid gap-3 sm:grid-cols-2 lg:grid-cols-3`,children:e.map(e=>{let n=e.state.agentId?t[e.state.agentId]:void 0,i=x(e,n);return(0,v.jsxs)(`div`,{className:`rounded-md border border-border bg-card p-3 space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,v.jsxs)(`div`,{className:`min-w-0`,children:[(0,v.jsx)(`div`,{className:`font-medium text-sm truncate`,children:e.policy.label||e.policy.name}),(0,v.jsxs)(`div`,{className:`text-xs text-muted-foreground truncate`,children:[e.policy.mode,` · `,e.policy.cwd]})]}),(0,v.jsx)(b,{status:e.state.status})]}),(0,v.jsxs)(`div`,{className:`grid grid-cols-2 gap-x-4 gap-y-1 text-xs`,children:[(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:`Provider`}),(0,v.jsx)(`div`,{children:e.policy.provider}),(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:`Agent`}),(0,v.jsx)(`div`,{className:`font-mono truncate`,children:e.state.agentId||`-`}),(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:`Restarts`}),(0,v.jsx)(`div`,{children:e.state.restartCount}),(e.state.backoffUntil||e.state.lastError)&&(0,v.jsxs)(v.Fragment,{children:[(0,v.jsx)(`div`,{className:`text-muted-foreground`,children:e.state.backoffUntil?`Backoff`:`Error`}),(0,v.jsx)(`div`,{className:`truncate`,children:e.state.backoffUntil?p(e.state.backoffUntil):e.state.lastError})]})]}),(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-1 pt-1 border-t border-border`,children:[(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>A(e.policy.name,`start`),title:`Start`,children:(0,v.jsx)(r,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>A(e.policy.name,`stop`),title:`Stop`,children:(0,v.jsx)(u,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>A(e.policy.name,`restart`),title:`Restart`,children:(0,v.jsx)(o,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>D(e),disabled:!e.state.tmuxSession,title:`Logs`,children:(0,v.jsx)(c,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>i&&k({item:e,session:i}),disabled:!S(e,n),title:`Terminal`,children:(0,v.jsx)(a,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>w(e.policy),title:`Edit`,children:(0,v.jsx)(d,{className:`h-3.5 w-3.5`})}),(0,v.jsx)(m,{size:`icon`,variant:`outline`,className:`h-7 w-7`,onClick:()=>T(e.policy.name),title:`Delete`,children:(0,v.jsx)(l,{className:`h-3.5 w-3.5`})})]})]},e.policy.name)})}),E?.state.tmuxSession&&(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,v.jsxs)(`h2`,{className:`text-lg font-semibold`,children:[E.policy.name,` Logs`]}),(0,v.jsx)(m,{variant:`outline`,size:`sm`,onClick:()=>D(null),children:`Close`})]}),(0,v.jsx)(h,{orchestratorId:E.policy.orchestratorId,session:E.state.tmuxSession})]}),(0,v.jsx)(g,{open:!!O,onOpenChange:e=>{e||k(null)},orchestratorId:O?.item.policy.orchestratorId??``,session:O?.session??``,interactive:O?C(O.item,O.item.state.agentId?t[O.item.state.agentId]:void 0):!1})]})}export{w as ManagedAgentsView};
2
+ //# sourceMappingURL=managed-agents-C5pzetBh.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"managed-agents-VZEeMMSP.js","names":[],"sources":["../../dashboard/src/components/shared/health-badge.tsx","../../dashboard/src/components/views/managed-agents.tsx"],"sourcesContent":["import { cn } from '@/lib/utils'\nimport type { ManagedAgentLifecycleStatus } from '@/types'\n\nconst styles: Record<ManagedAgentLifecycleStatus, string> = {\n running: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30',\n starting: 'bg-blue-500/15 text-blue-400 border-blue-500/30',\n stopping: 'bg-yellow-500/15 text-yellow-400 border-yellow-500/30',\n backoff: 'bg-red-500/15 text-red-400 border-red-500/30',\n stopped: 'bg-muted text-muted-foreground border-border',\n}\n\nexport function HealthBadge({ status }: { status: ManagedAgentLifecycleStatus }) {\n return (\n <span className={cn('inline-flex items-center rounded border px-2 py-0.5 text-xs font-medium', styles[status])}>\n {status}\n </span>\n )\n}\n","import { useEffect, useState } from 'react'\nimport { FileText, Pencil, Play, Plus, RotateCw, Square, Terminal, Trash2 } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport { Button } from '@/components/ui/button'\nimport { HealthBadge } from '@/components/shared/health-badge'\nimport { LogViewer } from '@/components/shared/log-viewer'\nimport { TerminalDialog } from '@/components/shared/terminal-viewer'\nimport { fmtTime } from '@/lib/display'\nimport type { Agent, ManagedPolicyHealth } from '@/types'\n\nfunction terminalSessionFor(item: ManagedPolicyHealth, agent?: Agent): string | undefined {\n const agentSession = agent?.meta?.tmuxSession\n if (typeof agentSession === 'string' && agentSession.trim()) return agentSession\n return item.state.tmuxSession\n}\n\nfunction canReadTerminal(item: ManagedPolicyHealth, agent?: Agent): boolean {\n if (!terminalSessionFor(item, agent)) return false\n if (agent) return Boolean(agent.providerCapabilities?.terminal?.live?.read)\n return item.policy.provider === 'claude'\n}\n\nfunction canWriteTerminal(item: ManagedPolicyHealth, agent?: Agent): boolean {\n if (!canReadTerminal(item, agent)) return false\n if (agent) return Boolean(agent.providerCapabilities?.terminal?.live?.write || item.policy.provider === 'claude')\n return item.policy.provider === 'claude'\n}\n\nexport function ManagedAgentsView() {\n const policies = useRelayStore((s) => s.managedPolicies)\n const agentsById = useRelayStore((s) => s.agentsById)\n const fetchManagedPolicies = useRelayStore((s) => s.fetchManagedPolicies)\n const apiCall = useRelayStore((s) => s.apiCall)\n const openPolicyCreate = useRelayStore((s) => s.openPolicyCreate)\n const openPolicyEdit = useRelayStore((s) => s.openPolicyEdit)\n const deletePolicy = useRelayStore((s) => s.deletePolicy)\n const [logsFor, setLogsFor] = useState<ManagedPolicyHealth | null>(null)\n const [terminalFor, setTerminalFor] = useState<{ item: ManagedPolicyHealth; session: string } | null>(null)\n\n useEffect(() => {\n void fetchManagedPolicies()\n }, [])\n\n async function lifecycle(name: string, action: 'start' | 'stop' | 'restart') {\n await apiCall('POST', `/spawn-policy/${encodeURIComponent(name)}/${action}`, { surface: { component: 'managed-agents' } })\n await fetchManagedPolicies()\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Managed Agents</h1>\n <p className=\"text-sm text-muted-foreground\">Spawn policies, lifecycle state, and headless session logs.</p>\n </div>\n <Button onClick={openPolicyCreate} size=\"sm\">\n <Plus className=\"h-4 w-4 mr-1\" />\n Create Policy\n </Button>\n </div>\n\n {policies.length === 0 && (\n <div className=\"rounded-md border border-border px-3 py-8 text-center text-sm text-muted-foreground\">\n No managed agents configured\n </div>\n )}\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {policies.map((item) => {\n const agent = item.state.agentId ? agentsById[item.state.agentId] : undefined\n const terminalSession = terminalSessionFor(item, agent)\n return (\n <div key={item.policy.name} className=\"rounded-md border border-border bg-card p-3 space-y-2\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"font-medium text-sm truncate\">{item.policy.label || item.policy.name}</div>\n <div className=\"text-xs text-muted-foreground truncate\">{item.policy.mode} · {item.policy.cwd}</div>\n </div>\n <HealthBadge status={item.state.status} />\n </div>\n\n <div className=\"grid grid-cols-2 gap-x-4 gap-y-1 text-xs\">\n <div className=\"text-muted-foreground\">Provider</div>\n <div>{item.policy.provider}</div>\n <div className=\"text-muted-foreground\">Agent</div>\n <div className=\"font-mono truncate\">{item.state.agentId || '-'}</div>\n <div className=\"text-muted-foreground\">Restarts</div>\n <div>{item.state.restartCount}</div>\n {(item.state.backoffUntil || item.state.lastError) && (\n <>\n <div className=\"text-muted-foreground\">{item.state.backoffUntil ? 'Backoff' : 'Error'}</div>\n <div className=\"truncate\">{item.state.backoffUntil ? fmtTime(item.state.backoffUntil) : item.state.lastError}</div>\n </>\n )}\n </div>\n\n <div className=\"flex flex-wrap gap-1 pt-1 border-t border-border\">\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => lifecycle(item.policy.name, 'start')} title=\"Start\"><Play className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => lifecycle(item.policy.name, 'stop')} title=\"Stop\"><Square className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => lifecycle(item.policy.name, 'restart')} title=\"Restart\"><RotateCw className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => setLogsFor(item)} disabled={!item.state.tmuxSession} title=\"Logs\"><FileText className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => terminalSession && setTerminalFor({ item, session: terminalSession })} disabled={!canReadTerminal(item, agent)} title=\"Terminal\"><Terminal className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => openPolicyEdit(item.policy)} title=\"Edit\"><Pencil className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => deletePolicy(item.policy.name)} title=\"Delete\"><Trash2 className=\"h-3.5 w-3.5\" /></Button>\n </div>\n </div>\n )\n })}\n </div>\n\n {logsFor?.state.tmuxSession && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold\">{logsFor.policy.name} Logs</h2>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setLogsFor(null)}>Close</Button>\n </div>\n <LogViewer orchestratorId={logsFor.policy.orchestratorId} session={logsFor.state.tmuxSession} />\n </div>\n )}\n\n <TerminalDialog\n open={!!terminalFor}\n onOpenChange={(open) => { if (!open) setTerminalFor(null) }}\n orchestratorId={terminalFor?.item.policy.orchestratorId ?? ''}\n session={terminalFor?.session ?? ''}\n interactive={terminalFor ? canWriteTerminal(terminalFor.item, terminalFor.item.state.agentId ? agentsById[terminalFor.item.state.agentId] : undefined) : false}\n />\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"managed-agents-C5pzetBh.js","names":[],"sources":["../../dashboard/src/components/shared/health-badge.tsx","../../dashboard/src/components/views/managed-agents.tsx"],"sourcesContent":["import { cn } from '@/lib/utils'\nimport type { ManagedAgentLifecycleStatus } from '@/types'\n\nconst styles: Record<ManagedAgentLifecycleStatus, string> = {\n running: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30',\n starting: 'bg-blue-500/15 text-blue-400 border-blue-500/30',\n stopping: 'bg-yellow-500/15 text-yellow-400 border-yellow-500/30',\n backoff: 'bg-red-500/15 text-red-400 border-red-500/30',\n stopped: 'bg-muted text-muted-foreground border-border',\n}\n\nexport function HealthBadge({ status }: { status: ManagedAgentLifecycleStatus }) {\n return (\n <span className={cn('inline-flex items-center rounded border px-2 py-0.5 text-xs font-medium', styles[status])}>\n {status}\n </span>\n )\n}\n","import { useEffect, useState } from 'react'\nimport { FileText, Pencil, Play, Plus, RotateCw, Square, Terminal, Trash2 } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport { Button } from '@/components/ui/button'\nimport { HealthBadge } from '@/components/shared/health-badge'\nimport { LogViewer } from '@/components/shared/log-viewer'\nimport { TerminalDialog } from '@/components/shared/terminal-viewer'\nimport { fmtTime } from '@/lib/display'\nimport type { Agent, ManagedPolicyHealth } from '@/types'\n\nfunction terminalSessionFor(item: ManagedPolicyHealth, agent?: Agent): string | undefined {\n const agentSession = agent?.meta?.tmuxSession\n if (typeof agentSession === 'string' && agentSession.trim()) return agentSession\n return item.state.tmuxSession\n}\n\nfunction canReadTerminal(item: ManagedPolicyHealth, agent?: Agent): boolean {\n if (!terminalSessionFor(item, agent)) return false\n if (agent) return Boolean(agent.providerCapabilities?.terminal?.live?.read)\n return item.policy.provider === 'claude'\n}\n\nfunction canWriteTerminal(item: ManagedPolicyHealth, agent?: Agent): boolean {\n if (!canReadTerminal(item, agent)) return false\n if (agent) return Boolean(agent.providerCapabilities?.terminal?.live?.write || item.policy.provider === 'claude')\n return item.policy.provider === 'claude'\n}\n\nexport function ManagedAgentsView() {\n const policies = useRelayStore((s) => s.managedPolicies)\n const agentsById = useRelayStore((s) => s.agentsById)\n const fetchManagedPolicies = useRelayStore((s) => s.fetchManagedPolicies)\n const apiCall = useRelayStore((s) => s.apiCall)\n const openPolicyCreate = useRelayStore((s) => s.openPolicyCreate)\n const openPolicyEdit = useRelayStore((s) => s.openPolicyEdit)\n const deletePolicy = useRelayStore((s) => s.deletePolicy)\n const [logsFor, setLogsFor] = useState<ManagedPolicyHealth | null>(null)\n const [terminalFor, setTerminalFor] = useState<{ item: ManagedPolicyHealth; session: string } | null>(null)\n\n useEffect(() => {\n void fetchManagedPolicies()\n }, [])\n\n async function lifecycle(name: string, action: 'start' | 'stop' | 'restart') {\n await apiCall('POST', `/spawn-policy/${encodeURIComponent(name)}/${action}`, { surface: { component: 'managed-agents' } })\n await fetchManagedPolicies()\n }\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Managed Agents</h1>\n <p className=\"text-sm text-muted-foreground\">Spawn policies, lifecycle state, and headless session logs.</p>\n </div>\n <Button onClick={openPolicyCreate} size=\"sm\">\n <Plus className=\"h-4 w-4 mr-1\" />\n Create Policy\n </Button>\n </div>\n\n {policies.length === 0 && (\n <div className=\"rounded-md border border-border px-3 py-8 text-center text-sm text-muted-foreground\">\n No managed agents configured\n </div>\n )}\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {policies.map((item) => {\n const agent = item.state.agentId ? agentsById[item.state.agentId] : undefined\n const terminalSession = terminalSessionFor(item, agent)\n return (\n <div key={item.policy.name} className=\"rounded-md border border-border bg-card p-3 space-y-2\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <div className=\"font-medium text-sm truncate\">{item.policy.label || item.policy.name}</div>\n <div className=\"text-xs text-muted-foreground truncate\">{item.policy.mode} · {item.policy.cwd}</div>\n </div>\n <HealthBadge status={item.state.status} />\n </div>\n\n <div className=\"grid grid-cols-2 gap-x-4 gap-y-1 text-xs\">\n <div className=\"text-muted-foreground\">Provider</div>\n <div>{item.policy.provider}</div>\n <div className=\"text-muted-foreground\">Agent</div>\n <div className=\"font-mono truncate\">{item.state.agentId || '-'}</div>\n <div className=\"text-muted-foreground\">Restarts</div>\n <div>{item.state.restartCount}</div>\n {(item.state.backoffUntil || item.state.lastError) && (\n <>\n <div className=\"text-muted-foreground\">{item.state.backoffUntil ? 'Backoff' : 'Error'}</div>\n <div className=\"truncate\">{item.state.backoffUntil ? fmtTime(item.state.backoffUntil) : item.state.lastError}</div>\n </>\n )}\n </div>\n\n <div className=\"flex flex-wrap gap-1 pt-1 border-t border-border\">\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => lifecycle(item.policy.name, 'start')} title=\"Start\"><Play className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => lifecycle(item.policy.name, 'stop')} title=\"Stop\"><Square className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => lifecycle(item.policy.name, 'restart')} title=\"Restart\"><RotateCw className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => setLogsFor(item)} disabled={!item.state.tmuxSession} title=\"Logs\"><FileText className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => terminalSession && setTerminalFor({ item, session: terminalSession })} disabled={!canReadTerminal(item, agent)} title=\"Terminal\"><Terminal className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => openPolicyEdit(item.policy)} title=\"Edit\"><Pencil className=\"h-3.5 w-3.5\" /></Button>\n <Button size=\"icon\" variant=\"outline\" className=\"h-7 w-7\" onClick={() => deletePolicy(item.policy.name)} title=\"Delete\"><Trash2 className=\"h-3.5 w-3.5\" /></Button>\n </div>\n </div>\n )\n })}\n </div>\n\n {logsFor?.state.tmuxSession && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold\">{logsFor.policy.name} Logs</h2>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setLogsFor(null)}>Close</Button>\n </div>\n <LogViewer orchestratorId={logsFor.policy.orchestratorId} session={logsFor.state.tmuxSession} />\n </div>\n )}\n\n <TerminalDialog\n open={!!terminalFor}\n onOpenChange={(open) => { if (!open) setTerminalFor(null) }}\n orchestratorId={terminalFor?.item.policy.orchestratorId ?? ''}\n session={terminalFor?.session ?? ''}\n interactive={terminalFor ? canWriteTerminal(terminalFor.item, terminalFor.item.state.agentId ? agentsById[terminalFor.item.state.agentId] : undefined) : false}\n />\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{kn as e}from"./lucide-react-CD8Xl2U3.js";import{b as t,x as n}from"./index-CvSlyTSI.js";import{i as r,n as i,r as a,t as o}from"./lib-ZEIADKGq.js";var s=e(),c={...a,attributes:{...a.attributes,code:[...a.attributes?.code||[],[`className`,/^language-[\w-]+$/]]}};function l(e){return!e||!/^https?:\/\//i.test(e)?{}:{target:`_blank`,rel:`noreferrer`}}function u({content:e,path:a}){return(0,s.jsx)(`div`,{className:`markdown-preview max-w-none overflow-hidden p-4 text-sm leading-6`,children:(0,s.jsx)(r,{remarkPlugins:[o],rehypePlugins:[[i,c]],components:{a({href:e,children:t}){return(0,s.jsx)(`a`,{href:e,...l(e),children:t})},img({src:e,alt:n}){return e?(0,s.jsx)(t,{src:e,alt:n,className:`max-w-full`}):null},code({className:e,children:t,...r}){let i=/language-([\w-]+)/.exec(e||``),o=String(t).replace(/\n$/,``);return i?(0,s.jsx)(n,{content:o,path:`${a}.${i[1]}`,languageHint:i[1],compact:!0}):(0,s.jsx)(`code`,{className:e,...r,children:t})}},children:e})})}export{u as MarkdownPreview};
2
- //# sourceMappingURL=markdown-preview-impl-Bbwmbxvn.js.map
1
+ import{kn as e}from"./lucide-react-CD8Xl2U3.js";import{b as t,x as n}from"./index-BL8r94_U.js";import{i as r,n as i,r as a,t as o}from"./lib-ZEIADKGq.js";var s=e(),c={...a,attributes:{...a.attributes,code:[...a.attributes?.code||[],[`className`,/^language-[\w-]+$/]]}};function l(e){return!e||!/^https?:\/\//i.test(e)?{}:{target:`_blank`,rel:`noreferrer`}}function u({content:e,path:a}){return(0,s.jsx)(`div`,{className:`markdown-preview max-w-none overflow-hidden p-4 text-sm leading-6`,children:(0,s.jsx)(r,{remarkPlugins:[o],rehypePlugins:[[i,c]],components:{a({href:e,children:t}){return(0,s.jsx)(`a`,{href:e,...l(e),children:t})},img({src:e,alt:n}){return e?(0,s.jsx)(t,{src:e,alt:n,className:`max-w-full`}):null},code({className:e,children:t,...r}){let i=/language-([\w-]+)/.exec(e||``),o=String(t).replace(/\n$/,``);return i?(0,s.jsx)(n,{content:o,path:`${a}.${i[1]}`,languageHint:i[1],compact:!0}):(0,s.jsx)(`code`,{className:e,...r,children:t})}},children:e})})}export{u as MarkdownPreview};
2
+ //# sourceMappingURL=markdown-preview-impl-4s9YDGM7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-preview-impl-Bbwmbxvn.js","names":[],"sources":["../../dashboard/src/components/shared/markdown-preview-impl.tsx"],"sourcesContent":["import ReactMarkdown from 'react-markdown'\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\nimport remarkGfm from 'remark-gfm'\nimport { CodePreview } from './code-preview'\nimport { ZoomableImage } from './zoomable-image'\n\nconst markdownSchema = {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n code: [\n ...(defaultSchema.attributes?.code || []),\n ['className', /^language-[\\w-]+$/],\n ],\n },\n}\n\nfunction externalLinkProps(href?: string) {\n if (!href || !/^https?:\\/\\//i.test(href)) return {}\n return { target: '_blank', rel: 'noreferrer' }\n}\n\nexport interface MarkdownPreviewProps { content: string; path: string }\n\nexport function MarkdownPreview({ content, path }: MarkdownPreviewProps) {\n return (\n <div className=\"markdown-preview max-w-none overflow-hidden p-4 text-sm leading-6\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[[rehypeSanitize, markdownSchema]]}\n components={{\n a({ href, children }) {\n return (\n <a href={href} {...externalLinkProps(href)}>\n {children}\n </a>\n )\n },\n img({ src, alt }) {\n if (!src) return null\n return <ZoomableImage src={src} alt={alt} className=\"max-w-full\" />\n },\n code({ className, children, ...props }) {\n const match = /language-([\\w-]+)/.exec(className || '')\n const code = String(children).replace(/\\n$/, '')\n if (match) {\n return (\n <CodePreview\n content={code}\n path={`${path}.${match[1]}`}\n languageHint={match[1]}\n compact\n />\n )\n }\n return (\n <code className={className} {...props}>\n {children}\n </code>\n )\n },\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n )\n}\n"],"mappings":"oKAMM,EAAiB,CACrB,GAAG,EACH,WAAY,CACV,GAAG,EAAc,WACjB,KAAM,CACJ,GAAI,EAAc,YAAY,MAAQ,EAAE,CACxC,CAAC,YAAa,oBAAoB,CACnC,CACF,CACF,CAED,SAAS,EAAkB,EAAe,CAExC,MADI,CAAC,GAAQ,CAAC,gBAAgB,KAAK,EAAK,CAAS,EAAE,CAC5C,CAAE,OAAQ,SAAU,IAAK,aAAc,CAKhD,SAAgB,EAAgB,CAAE,UAAS,QAA8B,CACvE,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,8EACb,EAAA,EAAA,KAAC,EAAD,CACE,cAAe,CAAC,EAAU,CAC1B,cAAe,CAAC,CAAC,EAAgB,EAAe,CAAC,CACjD,WAAY,CACV,EAAE,CAAE,OAAM,YAAY,CACpB,OACE,EAAA,EAAA,KAAC,IAAD,CAAS,OAAM,GAAI,EAAkB,EAAK,CACvC,WACC,CAAA,EAGR,IAAI,CAAE,MAAK,OAAO,CAEhB,OADK,GACE,EAAA,EAAA,KAAC,EAAD,CAAoB,MAAU,MAAK,UAAU,aAAe,CAAA,CADlD,MAGnB,KAAK,CAAE,YAAW,WAAU,GAAG,GAAS,CACtC,IAAM,EAAQ,oBAAoB,KAAK,GAAa,GAAG,CACjD,EAAO,OAAO,EAAS,CAAC,QAAQ,MAAO,GAAG,CAWhD,OAVI,GAEA,EAAA,EAAA,KAAC,EAAD,CACE,QAAS,EACT,KAAM,GAAG,EAAK,GAAG,EAAM,KACvB,aAAc,EAAM,GACpB,QAAA,GACA,CAAA,EAIJ,EAAA,EAAA,KAAC,OAAD,CAAiB,YAAW,GAAI,EAC7B,WACI,CAAA,EAGZ,UAEA,EACa,CAAA,CACZ,CAAA"}
1
+ {"version":3,"file":"markdown-preview-impl-4s9YDGM7.js","names":[],"sources":["../../dashboard/src/components/shared/markdown-preview-impl.tsx"],"sourcesContent":["import ReactMarkdown from 'react-markdown'\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize'\nimport remarkGfm from 'remark-gfm'\nimport { CodePreview } from './code-preview'\nimport { ZoomableImage } from './zoomable-image'\n\nconst markdownSchema = {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n code: [\n ...(defaultSchema.attributes?.code || []),\n ['className', /^language-[\\w-]+$/],\n ],\n },\n}\n\nfunction externalLinkProps(href?: string) {\n if (!href || !/^https?:\\/\\//i.test(href)) return {}\n return { target: '_blank', rel: 'noreferrer' }\n}\n\nexport interface MarkdownPreviewProps { content: string; path: string }\n\nexport function MarkdownPreview({ content, path }: MarkdownPreviewProps) {\n return (\n <div className=\"markdown-preview max-w-none overflow-hidden p-4 text-sm leading-6\">\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[[rehypeSanitize, markdownSchema]]}\n components={{\n a({ href, children }) {\n return (\n <a href={href} {...externalLinkProps(href)}>\n {children}\n </a>\n )\n },\n img({ src, alt }) {\n if (!src) return null\n return <ZoomableImage src={src} alt={alt} className=\"max-w-full\" />\n },\n code({ className, children, ...props }) {\n const match = /language-([\\w-]+)/.exec(className || '')\n const code = String(children).replace(/\\n$/, '')\n if (match) {\n return (\n <CodePreview\n content={code}\n path={`${path}.${match[1]}`}\n languageHint={match[1]}\n compact\n />\n )\n }\n return (\n <code className={className} {...props}>\n {children}\n </code>\n )\n },\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n )\n}\n"],"mappings":"oKAMM,EAAiB,CACrB,GAAG,EACH,WAAY,CACV,GAAG,EAAc,WACjB,KAAM,CACJ,GAAI,EAAc,YAAY,MAAQ,EAAE,CACxC,CAAC,YAAa,oBAAoB,CACnC,CACF,CACF,CAED,SAAS,EAAkB,EAAe,CAExC,MADI,CAAC,GAAQ,CAAC,gBAAgB,KAAK,EAAK,CAAS,EAAE,CAC5C,CAAE,OAAQ,SAAU,IAAK,aAAc,CAKhD,SAAgB,EAAgB,CAAE,UAAS,QAA8B,CACvE,OACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,8EACb,EAAA,EAAA,KAAC,EAAD,CACE,cAAe,CAAC,EAAU,CAC1B,cAAe,CAAC,CAAC,EAAgB,EAAe,CAAC,CACjD,WAAY,CACV,EAAE,CAAE,OAAM,YAAY,CACpB,OACE,EAAA,EAAA,KAAC,IAAD,CAAS,OAAM,GAAI,EAAkB,EAAK,CACvC,WACC,CAAA,EAGR,IAAI,CAAE,MAAK,OAAO,CAEhB,OADK,GACE,EAAA,EAAA,KAAC,EAAD,CAAoB,MAAU,MAAK,UAAU,aAAe,CAAA,CADlD,MAGnB,KAAK,CAAE,YAAW,WAAU,GAAG,GAAS,CACtC,IAAM,EAAQ,oBAAoB,KAAK,GAAa,GAAG,CACjD,EAAO,OAAO,EAAS,CAAC,QAAQ,MAAO,GAAG,CAWhD,OAVI,GAEA,EAAA,EAAA,KAAC,EAAD,CACE,QAAS,EACT,KAAM,GAAG,EAAK,GAAG,EAAM,KACvB,aAAc,EAAM,GACpB,QAAA,GACA,CAAA,EAIJ,EAAA,EAAA,KAAC,OAAD,CAAiB,YAAW,GAAI,EAC7B,WACI,CAAA,EAGZ,UAEA,EACa,CAAA,CACZ,CAAA"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{B as t,D as n,E as r,I as ee,M as i,Rt as te,Vn as a,fn as ne,kn as o,m as re}from"./lucide-react-CD8Xl2U3.js";import{i as ie,t as s}from"./store-CICRhg1m.js";import{m as c,u as ae,z as l}from"./display-Bebqs1qu.js";import{t as u}from"./badge-t8zAwHW9.js";import{t as d}from"./button-DDA5P2YQ.js";import{t as f}from"./input-BW9UD3FM.js";import{D as oe,r as se,s as ce}from"./index-CvSlyTSI.js";import{i as p,n as m,r as h,t as g}from"./card-CggxP1h9.js";var _=e(a(),1),v=o(),y=[`organization`,`role`,`project`,`task`,`interaction`,`agent`],le=[`private`,`project`,`org`,`public`],ue=[`public`,`normal`,`sensitive`,`secret`],b=[`reported`,`inferred`,`verified`];function x(){return{type:`project`,scope:`default`,title:``,content:``,tags:``,visibility:`project`,sensitivity:`normal`,confidence:`reported`,relevanceScore:`0.7`}}function S(e){return{type:e.type,scope:e.scope,title:e.title,content:e.content,tags:e.tags.join(`, `),visibility:e.visibility,sensitivity:e.sensitivity,confidence:e.confidence,relevanceScore:String(e.relevanceScore)}}function C(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function de(e){let t={limit:100};e.type&&(t.type=e.type),e.scope.trim()&&(t.scope=e.scope.trim()),e.visibility&&(t.visibility=e.visibility);let n=C(e.tags);if(n.length&&(t.tags=n),e.minRelevance.trim()){let n=Number(e.minRelevance);Number.isFinite(n)&&(t.minRelevance=Math.max(0,Math.min(1,n)))}return t}function w(e){return e===`secret`?`bg-red-500/10 text-red-400 border-red-500/30`:e===`sensitive`?`bg-yellow-500/10 text-yellow-400 border-yellow-500/30`:e===`public`?`bg-blue-500/10 text-blue-400 border-blue-500/30`:`bg-zinc-500/10 text-zinc-400 border-zinc-500/30`}function T(e){return e>=.8?`text-emerald-400`:e>=.5?`text-yellow-400`:`text-zinc-400`}function fe(e){return e?Object.entries(e).map(([e,t])=>`${e}=${Array.isArray(t)?t.join(` `):String(t)}`).join(` `):`default`}function pe(e){return e.filter(e=>![`system`,`user`,`channel`].includes(e.kind||``))}function E(){let e=ie(),a=s(e=>e.agents),o=s(e=>e.memories),E=s(e=>e.memoryTotal),O=s(e=>e.memoryStats),k=s(e=>e.memoryBrokerInfo),A=s(e=>e.memoryFilters),j=s(e=>e.selectedMemoryId),he=s(e=>e.memoryLoading),M=s(e=>e.set),ge=s(e=>e.fetchMemories),N=s(e=>e.refreshMemory),P=s(e=>e.saveMemory),F=s(e=>e.deleteMemory),I=s(e=>e.injectMemory),L=o.find(e=>e.id===j),[R,z]=(0,_.useState)(`create`),[B,V]=(0,_.useState)(x),[H,U]=(0,_.useState)(``),[W,_e]=(0,_.useState)(`manual`),[G,ve]=(0,_.useState)(`1600`),[K,ye]=(0,_.useState)(`8`),[q,be]=(0,_.useState)(``),J=(0,_.useMemo)(()=>pe(a),[a]);(0,_.useEffect)(()=>{!H&&J[0]&&U(J[0].id)},[J,H]),(0,_.useEffect)(()=>{L&&R===`edit`&&V(S(L))},[L?.id,R]);let Y=(0,_.useMemo)(()=>{let e=A.search.trim().toLowerCase();return e?o.filter(t=>[t.id,t.type,t.scope,t.title,t.content,...t.tags].some(t=>String(t).toLowerCase().includes(e))):o},[o,A.search]);function X(e){M({memoryFilters:{...A,...e}})}async function Z(){let e=Number(B.relevanceScore),t={title:B.title.trim(),content:B.content.trim(),tags:C(B.tags),visibility:B.visibility,sensitivity:B.sensitivity,confidence:B.confidence,relevanceScore:Number.isFinite(e)?Math.max(0,Math.min(1,e)):.7};if(R===`edit`&&L){await P(t,L.id);return}await P({...t,type:B.type,scope:B.scope.trim()}),z(`create`),V(x())}async function Q(e){if(!H)return;let t=await I({agentId:H,memoryIds:e,query:e?.length?void 0:de(A),reason:W.trim()||`manual`,budget:{maxTokens:Math.max(200,Number(G)||1600),maxMemories:Math.max(1,Number(K)||8),priorityCutoff:3}});t?.command?.id&&be(t.command.id)}function xe(){z(`create`),V(x())}function Se(){L&&(z(`edit`),V(S(L)))}let Ce=B.title.trim()&&B.content.trim()&&(R===`edit`||B.scope.trim()),$=fe(k?.config);return(0,v.jsxs)(`div`,{className:`space-y-4`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-3 flex-wrap`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(ne,{className:`w-5 h-5 text-muted-foreground`}),(0,v.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Memory`}),(0,v.jsx)(u,{variant:`secondary`,children:O?.total??E}),k&&(0,v.jsx)(u,{className:k.external?`bg-blue-500/15 text-blue-400 border-blue-500/30`:`bg-emerald-500/15 text-emerald-400 border-emerald-500/30`,children:k.type})]}),(0,v.jsxs)(d,{size:`sm`,variant:`outline`,className:`gap-1.5`,onClick:()=>N(),children:[(0,v.jsx)(i,{className:`w-3.5 h-3.5 ${he?`animate-spin`:``}`}),`Refresh`]})]}),(0,v.jsxs)(`div`,{className:`grid gap-3 xl:grid-cols-[1.2fr_0.8fr]`,children:[(0,v.jsxs)(g,{children:[(0,v.jsx)(h,{className:`py-3 px-4`,children:(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,v.jsxs)(p,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(te,{className:`w-4 h-4 text-muted-foreground`}),`Broker`]}),k?.capabilities&&(0,v.jsx)(`div`,{className:`flex flex-wrap gap-1 justify-end`,children:Object.entries(k.capabilities).filter(([,e])=>!!e).map(([e])=>(0,v.jsx)(u,{variant:`outline`,className:`text-[10px] px-1.5 py-0`,children:e},e))})]})}),(0,v.jsxs)(m,{className:`px-4 pb-4 space-y-3`,children:[(0,v.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-5 gap-2`,children:[(0,v.jsx)(D,{label:`total`,value:O?.total??E}),(0,v.jsx)(D,{label:`project`,value:O?.byType?.project??0}),(0,v.jsx)(D,{label:`task`,value:O?.byType?.task??0}),(0,v.jsx)(D,{label:`agent`,value:O?.byType?.agent??0}),(0,v.jsx)(D,{label:`sensitive`,value:(O?.bySensitivity?.sensitive??0)+(O?.bySensitivity?.secret??0)})]}),(0,v.jsx)(`div`,{className:`font-mono text-xs text-muted-foreground truncate`,title:$,children:$})]})]}),(0,v.jsxs)(g,{children:[(0,v.jsx)(h,{className:`py-3 px-4`,children:(0,v.jsx)(p,{className:`text-sm font-medium`,children:`Inject`})}),(0,v.jsxs)(m,{className:`px-4 pb-4 space-y-2`,children:[(0,v.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-2`,children:[(0,v.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:H,onChange:e=>U(e.target.value),children:[(0,v.jsx)(`option`,{value:``,children:`Agent`}),J.map(e=>(0,v.jsx)(`option`,{value:e.id,children:ae(e)},e.id))]}),(0,v.jsx)(f,{value:W,onChange:e=>_e(e.target.value),placeholder:`reason`}),(0,v.jsx)(f,{value:G,onChange:e=>ve(e.target.value),inputMode:`numeric`,placeholder:`tokens`}),(0,v.jsx)(f,{value:K,onChange:e=>ye(e.target.value),inputMode:`numeric`,placeholder:`memories`})]}),(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,v.jsxs)(d,{size:`sm`,className:`gap-1.5`,disabled:!H||!L,onClick:()=>L&&Q([L.id]),children:[(0,v.jsx)(r,{className:`w-3.5 h-3.5`}),`Selected`]}),(0,v.jsxs)(d,{size:`sm`,variant:`outline`,className:`gap-1.5`,disabled:!H,onClick:()=>Q(),children:[(0,v.jsx)(n,{className:`w-3.5 h-3.5`}),`Filtered`]}),q&&(0,v.jsx)(u,{variant:`outline`,className:`font-mono text-[10px]`,children:q})]})]})]})]}),(0,v.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]`,children:[(0,v.jsxs)(`div`,{className:`space-y-3`,children:[(0,v.jsx)(g,{children:(0,v.jsx)(m,{className:`p-3`,children:(0,v.jsxs)(`div`,{className:`grid grid-cols-2 lg:grid-cols-6 gap-2`,children:[(0,v.jsx)(f,{className:`lg:col-span-2`,value:A.search,onChange:e=>X({search:e.target.value}),placeholder:`Search visible memories`}),(0,v.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:A.type,onChange:e=>X({type:e.target.value}),children:[(0,v.jsx)(`option`,{value:``,children:`All types`}),y.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))]}),(0,v.jsx)(f,{value:A.scope,onChange:e=>X({scope:e.target.value}),placeholder:`scope`}),(0,v.jsx)(f,{value:A.tags,onChange:e=>X({tags:e.target.value}),placeholder:`tags`}),(0,v.jsxs)(`div`,{className:`flex gap-2`,children:[(0,v.jsx)(f,{value:A.minRelevance,onChange:e=>X({minRelevance:e.target.value}),placeholder:`score`}),(0,v.jsx)(d,{size:`sm`,variant:`outline`,className:`h-8 px-2`,onClick:()=>ge(),children:(0,v.jsx)(n,{className:`w-4 h-4`})})]})]})})}),(0,v.jsx)(ce,{className:`h-[calc(100dvh-24rem)] min-h-[360px]`,children:(0,v.jsxs)(`div`,{className:`space-y-2 pr-2`,children:[Y.length===0&&(0,v.jsx)(`div`,{className:`text-center text-sm text-muted-foreground py-16`,children:`No memories`}),Y.map(t=>(0,v.jsx)(me,{memory:t,selected:t.id===j,now:e,onSelect:()=>M({selectedMemoryId:t.id})},t.id))]})})]}),(0,v.jsxs)(g,{children:[(0,v.jsx)(h,{className:`py-3 px-4`,children:(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,v.jsx)(p,{className:`text-sm font-medium`,children:R===`edit`?`Edit Memory`:`New Memory`}),(0,v.jsxs)(`div`,{className:`flex gap-1`,children:[(0,v.jsx)(d,{size:`sm`,variant:`ghost`,className:`h-7 px-2`,onClick:xe,title:`New memory`,children:(0,v.jsx)(ee,{className:`w-3.5 h-3.5`})}),(0,v.jsx)(d,{size:`sm`,variant:`ghost`,className:`h-7 px-2`,onClick:Se,disabled:!L,title:`Edit selected`,children:(0,v.jsx)(t,{className:`w-3.5 h-3.5`})}),(0,v.jsx)(d,{size:`sm`,variant:`ghost`,className:`h-7 px-2 text-red-400 hover:text-red-300`,disabled:!L,onClick:()=>L&&F(L.id),title:`Delete selected`,children:(0,v.jsx)(re,{className:`w-3.5 h-3.5`})})]})]})}),(0,v.jsxs)(m,{className:`px-4 pb-4 space-y-3`,children:[L&&(0,v.jsxs)(v.Fragment,{children:[(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-1`,children:[(0,v.jsx)(u,{variant:`secondary`,children:L.type}),(0,v.jsx)(u,{variant:`outline`,children:L.scope}),(0,v.jsx)(u,{className:w(L.sensitivity),children:L.sensitivity}),(0,v.jsx)(u,{variant:`outline`,className:T(L.relevanceScore),children:L.relevanceScore.toFixed(2)})]}),(0,v.jsxs)(`div`,{className:`text-xs text-muted-foreground`,title:c(L.updatedAt),children:[`updated `,l(e,L.updatedAt)]}),(0,v.jsx)(`p`,{className:`text-sm font-medium`,children:L.title}),(0,v.jsx)(`p`,{className:`text-xs text-muted-foreground whitespace-pre-wrap max-h-24 overflow-auto`,children:L.content})]}),(0,v.jsx)(oe,{})]}),(0,v.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,disabled:R===`edit`,value:B.type,onChange:e=>V({...B,type:e.target.value}),children:y.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(f,{disabled:R===`edit`,value:B.scope,onChange:e=>V({...B,scope:e.target.value}),placeholder:`scope`}),(0,v.jsx)(f,{className:`col-span-2`,value:B.title,onChange:e=>V({...B,title:e.target.value}),placeholder:`title`}),(0,v.jsx)(se,{className:`col-span-2 min-h-32`,value:B.content,onChange:e=>V({...B,content:e.target.value}),placeholder:`content`}),(0,v.jsx)(f,{className:`col-span-2`,value:B.tags,onChange:e=>V({...B,tags:e.target.value}),placeholder:`tags`}),(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:B.visibility,onChange:e=>V({...B,visibility:e.target.value}),children:le.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:B.sensitivity,onChange:e=>V({...B,sensitivity:e.target.value}),children:ue.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:B.confidence,onChange:e=>V({...B,confidence:e.target.value}),children:b.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(f,{value:B.relevanceScore,onChange:e=>V({...B,relevanceScore:e.target.value}),inputMode:`decimal`,placeholder:`score`})]}),(0,v.jsx)(d,{size:`sm`,className:`w-full`,disabled:!Ce,onClick:Z,children:R===`edit`?`Save memory`:`Create memory`})]})]})]})]})}function D({label:e,value:t}){return(0,v.jsxs)(`div`,{className:`rounded-md border border-border bg-muted/20 px-3 py-2`,children:[(0,v.jsx)(`div`,{className:`text-lg font-semibold tabular-nums`,children:t}),(0,v.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e})]})}function me({memory:e,selected:t,now:n,onSelect:r}){return(0,v.jsx)(`button`,{onClick:r,className:`w-full text-left rounded-md border p-3 transition-colors ${t?`border-primary bg-primary/5`:`border-border bg-card hover:border-zinc-600`}`,children:(0,v.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,v.jsxs)(`div`,{className:`min-w-0`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-1.5 flex-wrap`,children:[(0,v.jsx)(u,{variant:`secondary`,className:`text-[10px]`,children:e.type}),(0,v.jsx)(u,{variant:`outline`,className:`text-[10px] font-mono`,children:e.scope}),(0,v.jsx)(u,{className:`text-[10px] ${w(e.sensitivity)}`,children:e.sensitivity})]}),(0,v.jsx)(`div`,{className:`font-medium text-sm mt-2 truncate`,children:e.title}),(0,v.jsx)(`div`,{className:`text-xs text-muted-foreground line-clamp-2 mt-1`,children:e.content}),e.tags.length>0&&(0,v.jsx)(`div`,{className:`flex gap-1 flex-wrap mt-2`,children:e.tags.slice(0,8).map(e=>(0,v.jsxs)(u,{variant:`outline`,className:`text-[10px] text-zinc-400`,children:[`#`,e]},e))})]}),(0,v.jsxs)(`div`,{className:`text-right shrink-0 space-y-1`,children:[(0,v.jsx)(`div`,{className:`text-sm font-semibold tabular-nums ${T(e.relevanceScore)}`,children:e.relevanceScore.toFixed(2)}),(0,v.jsx)(`div`,{className:`text-[10px] text-muted-foreground`,title:c(e.updatedAt),children:l(n,e.updatedAt)}),e.accessCount>0&&(0,v.jsxs)(`div`,{className:`text-[10px] text-muted-foreground`,children:[e.accessCount,` hits`]})]})]})})}export{E as MemoryView};
2
- //# sourceMappingURL=memory-BQAC3YmR.js.map
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{B as t,D as n,E as r,I as ee,M as i,Rt as te,Vn as a,fn as ne,kn as o,m as re}from"./lucide-react-CD8Xl2U3.js";import{i as ie,t as s}from"./store-CICRhg1m.js";import{m as c,u as ae,z as l}from"./display-Bebqs1qu.js";import{t as u}from"./badge-t8zAwHW9.js";import{t as d}from"./button-DDA5P2YQ.js";import{t as f}from"./input-BW9UD3FM.js";import{D as oe,r as se,s as ce}from"./index-BL8r94_U.js";import{i as p,n as m,r as h,t as g}from"./card-CggxP1h9.js";var _=e(a(),1),v=o(),y=[`organization`,`role`,`project`,`task`,`interaction`,`agent`],le=[`private`,`project`,`org`,`public`],ue=[`public`,`normal`,`sensitive`,`secret`],b=[`reported`,`inferred`,`verified`];function x(){return{type:`project`,scope:`default`,title:``,content:``,tags:``,visibility:`project`,sensitivity:`normal`,confidence:`reported`,relevanceScore:`0.7`}}function S(e){return{type:e.type,scope:e.scope,title:e.title,content:e.content,tags:e.tags.join(`, `),visibility:e.visibility,sensitivity:e.sensitivity,confidence:e.confidence,relevanceScore:String(e.relevanceScore)}}function C(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function de(e){let t={limit:100};e.type&&(t.type=e.type),e.scope.trim()&&(t.scope=e.scope.trim()),e.visibility&&(t.visibility=e.visibility);let n=C(e.tags);if(n.length&&(t.tags=n),e.minRelevance.trim()){let n=Number(e.minRelevance);Number.isFinite(n)&&(t.minRelevance=Math.max(0,Math.min(1,n)))}return t}function w(e){return e===`secret`?`bg-red-500/10 text-red-400 border-red-500/30`:e===`sensitive`?`bg-yellow-500/10 text-yellow-400 border-yellow-500/30`:e===`public`?`bg-blue-500/10 text-blue-400 border-blue-500/30`:`bg-zinc-500/10 text-zinc-400 border-zinc-500/30`}function T(e){return e>=.8?`text-emerald-400`:e>=.5?`text-yellow-400`:`text-zinc-400`}function fe(e){return e?Object.entries(e).map(([e,t])=>`${e}=${Array.isArray(t)?t.join(` `):String(t)}`).join(` `):`default`}function pe(e){return e.filter(e=>![`system`,`user`,`channel`].includes(e.kind||``))}function E(){let e=ie(),a=s(e=>e.agents),o=s(e=>e.memories),E=s(e=>e.memoryTotal),O=s(e=>e.memoryStats),k=s(e=>e.memoryBrokerInfo),A=s(e=>e.memoryFilters),j=s(e=>e.selectedMemoryId),he=s(e=>e.memoryLoading),M=s(e=>e.set),ge=s(e=>e.fetchMemories),N=s(e=>e.refreshMemory),P=s(e=>e.saveMemory),F=s(e=>e.deleteMemory),I=s(e=>e.injectMemory),L=o.find(e=>e.id===j),[R,z]=(0,_.useState)(`create`),[B,V]=(0,_.useState)(x),[H,U]=(0,_.useState)(``),[W,_e]=(0,_.useState)(`manual`),[G,ve]=(0,_.useState)(`1600`),[K,ye]=(0,_.useState)(`8`),[q,be]=(0,_.useState)(``),J=(0,_.useMemo)(()=>pe(a),[a]);(0,_.useEffect)(()=>{!H&&J[0]&&U(J[0].id)},[J,H]),(0,_.useEffect)(()=>{L&&R===`edit`&&V(S(L))},[L?.id,R]);let Y=(0,_.useMemo)(()=>{let e=A.search.trim().toLowerCase();return e?o.filter(t=>[t.id,t.type,t.scope,t.title,t.content,...t.tags].some(t=>String(t).toLowerCase().includes(e))):o},[o,A.search]);function X(e){M({memoryFilters:{...A,...e}})}async function Z(){let e=Number(B.relevanceScore),t={title:B.title.trim(),content:B.content.trim(),tags:C(B.tags),visibility:B.visibility,sensitivity:B.sensitivity,confidence:B.confidence,relevanceScore:Number.isFinite(e)?Math.max(0,Math.min(1,e)):.7};if(R===`edit`&&L){await P(t,L.id);return}await P({...t,type:B.type,scope:B.scope.trim()}),z(`create`),V(x())}async function Q(e){if(!H)return;let t=await I({agentId:H,memoryIds:e,query:e?.length?void 0:de(A),reason:W.trim()||`manual`,budget:{maxTokens:Math.max(200,Number(G)||1600),maxMemories:Math.max(1,Number(K)||8),priorityCutoff:3}});t?.command?.id&&be(t.command.id)}function xe(){z(`create`),V(x())}function Se(){L&&(z(`edit`),V(S(L)))}let Ce=B.title.trim()&&B.content.trim()&&(R===`edit`||B.scope.trim()),$=fe(k?.config);return(0,v.jsxs)(`div`,{className:`space-y-4`,children:[(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-3 flex-wrap`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,v.jsx)(ne,{className:`w-5 h-5 text-muted-foreground`}),(0,v.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Memory`}),(0,v.jsx)(u,{variant:`secondary`,children:O?.total??E}),k&&(0,v.jsx)(u,{className:k.external?`bg-blue-500/15 text-blue-400 border-blue-500/30`:`bg-emerald-500/15 text-emerald-400 border-emerald-500/30`,children:k.type})]}),(0,v.jsxs)(d,{size:`sm`,variant:`outline`,className:`gap-1.5`,onClick:()=>N(),children:[(0,v.jsx)(i,{className:`w-3.5 h-3.5 ${he?`animate-spin`:``}`}),`Refresh`]})]}),(0,v.jsxs)(`div`,{className:`grid gap-3 xl:grid-cols-[1.2fr_0.8fr]`,children:[(0,v.jsxs)(g,{children:[(0,v.jsx)(h,{className:`py-3 px-4`,children:(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,v.jsxs)(p,{className:`text-sm font-medium flex items-center gap-2`,children:[(0,v.jsx)(te,{className:`w-4 h-4 text-muted-foreground`}),`Broker`]}),k?.capabilities&&(0,v.jsx)(`div`,{className:`flex flex-wrap gap-1 justify-end`,children:Object.entries(k.capabilities).filter(([,e])=>!!e).map(([e])=>(0,v.jsx)(u,{variant:`outline`,className:`text-[10px] px-1.5 py-0`,children:e},e))})]})}),(0,v.jsxs)(m,{className:`px-4 pb-4 space-y-3`,children:[(0,v.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-5 gap-2`,children:[(0,v.jsx)(D,{label:`total`,value:O?.total??E}),(0,v.jsx)(D,{label:`project`,value:O?.byType?.project??0}),(0,v.jsx)(D,{label:`task`,value:O?.byType?.task??0}),(0,v.jsx)(D,{label:`agent`,value:O?.byType?.agent??0}),(0,v.jsx)(D,{label:`sensitive`,value:(O?.bySensitivity?.sensitive??0)+(O?.bySensitivity?.secret??0)})]}),(0,v.jsx)(`div`,{className:`font-mono text-xs text-muted-foreground truncate`,title:$,children:$})]})]}),(0,v.jsxs)(g,{children:[(0,v.jsx)(h,{className:`py-3 px-4`,children:(0,v.jsx)(p,{className:`text-sm font-medium`,children:`Inject`})}),(0,v.jsxs)(m,{className:`px-4 pb-4 space-y-2`,children:[(0,v.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-2`,children:[(0,v.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:H,onChange:e=>U(e.target.value),children:[(0,v.jsx)(`option`,{value:``,children:`Agent`}),J.map(e=>(0,v.jsx)(`option`,{value:e.id,children:ae(e)},e.id))]}),(0,v.jsx)(f,{value:W,onChange:e=>_e(e.target.value),placeholder:`reason`}),(0,v.jsx)(f,{value:G,onChange:e=>ve(e.target.value),inputMode:`numeric`,placeholder:`tokens`}),(0,v.jsx)(f,{value:K,onChange:e=>ye(e.target.value),inputMode:`numeric`,placeholder:`memories`})]}),(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,v.jsxs)(d,{size:`sm`,className:`gap-1.5`,disabled:!H||!L,onClick:()=>L&&Q([L.id]),children:[(0,v.jsx)(r,{className:`w-3.5 h-3.5`}),`Selected`]}),(0,v.jsxs)(d,{size:`sm`,variant:`outline`,className:`gap-1.5`,disabled:!H,onClick:()=>Q(),children:[(0,v.jsx)(n,{className:`w-3.5 h-3.5`}),`Filtered`]}),q&&(0,v.jsx)(u,{variant:`outline`,className:`font-mono text-[10px]`,children:q})]})]})]})]}),(0,v.jsxs)(`div`,{className:`grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]`,children:[(0,v.jsxs)(`div`,{className:`space-y-3`,children:[(0,v.jsx)(g,{children:(0,v.jsx)(m,{className:`p-3`,children:(0,v.jsxs)(`div`,{className:`grid grid-cols-2 lg:grid-cols-6 gap-2`,children:[(0,v.jsx)(f,{className:`lg:col-span-2`,value:A.search,onChange:e=>X({search:e.target.value}),placeholder:`Search visible memories`}),(0,v.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:A.type,onChange:e=>X({type:e.target.value}),children:[(0,v.jsx)(`option`,{value:``,children:`All types`}),y.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))]}),(0,v.jsx)(f,{value:A.scope,onChange:e=>X({scope:e.target.value}),placeholder:`scope`}),(0,v.jsx)(f,{value:A.tags,onChange:e=>X({tags:e.target.value}),placeholder:`tags`}),(0,v.jsxs)(`div`,{className:`flex gap-2`,children:[(0,v.jsx)(f,{value:A.minRelevance,onChange:e=>X({minRelevance:e.target.value}),placeholder:`score`}),(0,v.jsx)(d,{size:`sm`,variant:`outline`,className:`h-8 px-2`,onClick:()=>ge(),children:(0,v.jsx)(n,{className:`w-4 h-4`})})]})]})})}),(0,v.jsx)(ce,{className:`h-[calc(100dvh-24rem)] min-h-[360px]`,children:(0,v.jsxs)(`div`,{className:`space-y-2 pr-2`,children:[Y.length===0&&(0,v.jsx)(`div`,{className:`text-center text-sm text-muted-foreground py-16`,children:`No memories`}),Y.map(t=>(0,v.jsx)(me,{memory:t,selected:t.id===j,now:e,onSelect:()=>M({selectedMemoryId:t.id})},t.id))]})})]}),(0,v.jsxs)(g,{children:[(0,v.jsx)(h,{className:`py-3 px-4`,children:(0,v.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,v.jsx)(p,{className:`text-sm font-medium`,children:R===`edit`?`Edit Memory`:`New Memory`}),(0,v.jsxs)(`div`,{className:`flex gap-1`,children:[(0,v.jsx)(d,{size:`sm`,variant:`ghost`,className:`h-7 px-2`,onClick:xe,title:`New memory`,children:(0,v.jsx)(ee,{className:`w-3.5 h-3.5`})}),(0,v.jsx)(d,{size:`sm`,variant:`ghost`,className:`h-7 px-2`,onClick:Se,disabled:!L,title:`Edit selected`,children:(0,v.jsx)(t,{className:`w-3.5 h-3.5`})}),(0,v.jsx)(d,{size:`sm`,variant:`ghost`,className:`h-7 px-2 text-red-400 hover:text-red-300`,disabled:!L,onClick:()=>L&&F(L.id),title:`Delete selected`,children:(0,v.jsx)(re,{className:`w-3.5 h-3.5`})})]})]})}),(0,v.jsxs)(m,{className:`px-4 pb-4 space-y-3`,children:[L&&(0,v.jsxs)(v.Fragment,{children:[(0,v.jsxs)(`div`,{className:`space-y-2`,children:[(0,v.jsxs)(`div`,{className:`flex flex-wrap gap-1`,children:[(0,v.jsx)(u,{variant:`secondary`,children:L.type}),(0,v.jsx)(u,{variant:`outline`,children:L.scope}),(0,v.jsx)(u,{className:w(L.sensitivity),children:L.sensitivity}),(0,v.jsx)(u,{variant:`outline`,className:T(L.relevanceScore),children:L.relevanceScore.toFixed(2)})]}),(0,v.jsxs)(`div`,{className:`text-xs text-muted-foreground`,title:c(L.updatedAt),children:[`updated `,l(e,L.updatedAt)]}),(0,v.jsx)(`p`,{className:`text-sm font-medium`,children:L.title}),(0,v.jsx)(`p`,{className:`text-xs text-muted-foreground whitespace-pre-wrap max-h-24 overflow-auto`,children:L.content})]}),(0,v.jsx)(oe,{})]}),(0,v.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,disabled:R===`edit`,value:B.type,onChange:e=>V({...B,type:e.target.value}),children:y.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(f,{disabled:R===`edit`,value:B.scope,onChange:e=>V({...B,scope:e.target.value}),placeholder:`scope`}),(0,v.jsx)(f,{className:`col-span-2`,value:B.title,onChange:e=>V({...B,title:e.target.value}),placeholder:`title`}),(0,v.jsx)(se,{className:`col-span-2 min-h-32`,value:B.content,onChange:e=>V({...B,content:e.target.value}),placeholder:`content`}),(0,v.jsx)(f,{className:`col-span-2`,value:B.tags,onChange:e=>V({...B,tags:e.target.value}),placeholder:`tags`}),(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:B.visibility,onChange:e=>V({...B,visibility:e.target.value}),children:le.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:B.sensitivity,onChange:e=>V({...B,sensitivity:e.target.value}),children:ue.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(`select`,{className:`rounded-md border border-input bg-background px-2 py-1.5 text-sm`,value:B.confidence,onChange:e=>V({...B,confidence:e.target.value}),children:b.map(e=>(0,v.jsx)(`option`,{value:e,children:e},e))}),(0,v.jsx)(f,{value:B.relevanceScore,onChange:e=>V({...B,relevanceScore:e.target.value}),inputMode:`decimal`,placeholder:`score`})]}),(0,v.jsx)(d,{size:`sm`,className:`w-full`,disabled:!Ce,onClick:Z,children:R===`edit`?`Save memory`:`Create memory`})]})]})]})]})}function D({label:e,value:t}){return(0,v.jsxs)(`div`,{className:`rounded-md border border-border bg-muted/20 px-3 py-2`,children:[(0,v.jsx)(`div`,{className:`text-lg font-semibold tabular-nums`,children:t}),(0,v.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e})]})}function me({memory:e,selected:t,now:n,onSelect:r}){return(0,v.jsx)(`button`,{onClick:r,className:`w-full text-left rounded-md border p-3 transition-colors ${t?`border-primary bg-primary/5`:`border-border bg-card hover:border-zinc-600`}`,children:(0,v.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,v.jsxs)(`div`,{className:`min-w-0`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-1.5 flex-wrap`,children:[(0,v.jsx)(u,{variant:`secondary`,className:`text-[10px]`,children:e.type}),(0,v.jsx)(u,{variant:`outline`,className:`text-[10px] font-mono`,children:e.scope}),(0,v.jsx)(u,{className:`text-[10px] ${w(e.sensitivity)}`,children:e.sensitivity})]}),(0,v.jsx)(`div`,{className:`font-medium text-sm mt-2 truncate`,children:e.title}),(0,v.jsx)(`div`,{className:`text-xs text-muted-foreground line-clamp-2 mt-1`,children:e.content}),e.tags.length>0&&(0,v.jsx)(`div`,{className:`flex gap-1 flex-wrap mt-2`,children:e.tags.slice(0,8).map(e=>(0,v.jsxs)(u,{variant:`outline`,className:`text-[10px] text-zinc-400`,children:[`#`,e]},e))})]}),(0,v.jsxs)(`div`,{className:`text-right shrink-0 space-y-1`,children:[(0,v.jsx)(`div`,{className:`text-sm font-semibold tabular-nums ${T(e.relevanceScore)}`,children:e.relevanceScore.toFixed(2)}),(0,v.jsx)(`div`,{className:`text-[10px] text-muted-foreground`,title:c(e.updatedAt),children:l(n,e.updatedAt)}),e.accessCount>0&&(0,v.jsxs)(`div`,{className:`text-[10px] text-muted-foreground`,children:[e.accessCount,` hits`]})]})]})})}export{E as MemoryView};
2
+ //# sourceMappingURL=memory-BWfDbph3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-BQAC3YmR.js","names":[],"sources":["../../dashboard/src/components/views/memory.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react'\nimport { useRelayStore, useNow } from '@/store'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { Separator } from '@/components/ui/separator'\nimport { BrainCircuit, Database, Edit3, Plus, RefreshCw, Search, Send, Trash2 } from 'lucide-react'\nimport { displayName, fmtTime, timeAgo } from '@/lib/display'\nimport type { Agent, CreateMemoryInput, Memory, MemoryFilterState, MemoryQuery, MemoryType, UpdateMemoryInput } from '@/types'\n\nconst MEMORY_TYPES: MemoryType[] = ['organization', 'role', 'project', 'task', 'interaction', 'agent']\nconst VISIBILITIES = ['private', 'project', 'org', 'public'] as const\nconst SENSITIVITIES = ['public', 'normal', 'sensitive', 'secret'] as const\nconst CONFIDENCES = ['reported', 'inferred', 'verified'] as const\n\ntype MemoryForm = {\n type: MemoryType\n scope: string\n title: string\n content: string\n tags: string\n visibility: (typeof VISIBILITIES)[number]\n sensitivity: (typeof SENSITIVITIES)[number]\n confidence: (typeof CONFIDENCES)[number]\n relevanceScore: string\n}\n\nfunction blankForm(): MemoryForm {\n return {\n type: 'project',\n scope: 'default',\n title: '',\n content: '',\n tags: '',\n visibility: 'project',\n sensitivity: 'normal',\n confidence: 'reported',\n relevanceScore: '0.7',\n }\n}\n\nfunction formFromMemory(memory: Memory): MemoryForm {\n return {\n type: memory.type,\n scope: memory.scope,\n title: memory.title,\n content: memory.content,\n tags: memory.tags.join(', '),\n visibility: memory.visibility,\n sensitivity: memory.sensitivity,\n confidence: memory.confidence,\n relevanceScore: String(memory.relevanceScore),\n }\n}\n\nfunction csv(value: string): string[] {\n return value.split(',').map((item) => item.trim()).filter(Boolean)\n}\n\nfunction queryFromFilters(filters: MemoryFilterState): MemoryQuery {\n const query: MemoryQuery = { limit: 100 }\n if (filters.type) query.type = filters.type as MemoryQuery['type']\n if (filters.scope.trim()) query.scope = filters.scope.trim()\n if (filters.visibility) query.visibility = filters.visibility as MemoryQuery['visibility']\n const tags = csv(filters.tags)\n if (tags.length) query.tags = tags\n if (filters.minRelevance.trim()) {\n const minRelevance = Number(filters.minRelevance)\n if (Number.isFinite(minRelevance)) query.minRelevance = Math.max(0, Math.min(1, minRelevance))\n }\n return query\n}\n\nfunction sensitivityClass(value: string) {\n if (value === 'secret') return 'bg-red-500/10 text-red-400 border-red-500/30'\n if (value === 'sensitive') return 'bg-yellow-500/10 text-yellow-400 border-yellow-500/30'\n if (value === 'public') return 'bg-blue-500/10 text-blue-400 border-blue-500/30'\n return 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30'\n}\n\nfunction scoreClass(score: number) {\n if (score >= 0.8) return 'text-emerald-400'\n if (score >= 0.5) return 'text-yellow-400'\n return 'text-zinc-400'\n}\n\nfunction compactConfig(config: Record<string, unknown> | undefined): string {\n if (!config) return 'default'\n return Object.entries(config)\n .map(([key, value]) => `${key}=${Array.isArray(value) ? value.join(' ') : String(value)}`)\n .join(' ')\n}\n\nfunction agentOptions(agents: Agent[]) {\n return agents.filter((agent) => !['system', 'user', 'channel'].includes(agent.kind || ''))\n}\n\nexport function MemoryView() {\n const now = useNow()\n const agents = useRelayStore((s) => s.agents)\n const memories = useRelayStore((s) => s.memories)\n const memoryTotal = useRelayStore((s) => s.memoryTotal)\n const memoryStats = useRelayStore((s) => s.memoryStats)\n const memoryBrokerInfo = useRelayStore((s) => s.memoryBrokerInfo)\n const memoryFilters = useRelayStore((s) => s.memoryFilters)\n const selectedMemoryId = useRelayStore((s) => s.selectedMemoryId)\n const memoryLoading = useRelayStore((s) => s.memoryLoading)\n const set = useRelayStore((s) => s.set)\n const fetchMemories = useRelayStore((s) => s.fetchMemories)\n const refreshMemory = useRelayStore((s) => s.refreshMemory)\n const saveMemory = useRelayStore((s) => s.saveMemory)\n const deleteMemory = useRelayStore((s) => s.deleteMemory)\n const injectMemory = useRelayStore((s) => s.injectMemory)\n\n const selectedMemory = memories.find((memory) => memory.id === selectedMemoryId)\n const [formMode, setFormMode] = useState<'create' | 'edit'>('create')\n const [form, setForm] = useState<MemoryForm>(blankForm)\n const [injectAgent, setInjectAgent] = useState('')\n const [injectReason, setInjectReason] = useState('manual')\n const [maxTokens, setMaxTokens] = useState('1600')\n const [maxMemories, setMaxMemories] = useState('8')\n const [lastCommand, setLastCommand] = useState('')\n\n const candidates = useMemo(() => agentOptions(agents), [agents])\n\n useEffect(() => {\n if (!injectAgent && candidates[0]) setInjectAgent(candidates[0].id)\n }, [candidates, injectAgent])\n\n useEffect(() => {\n if (selectedMemory && formMode === 'edit') setForm(formFromMemory(selectedMemory))\n }, [selectedMemory?.id, formMode])\n\n const visibleMemories = useMemo(() => {\n const needle = memoryFilters.search.trim().toLowerCase()\n if (!needle) return memories\n return memories.filter((memory) => [\n memory.id, memory.type, memory.scope, memory.title, memory.content, ...memory.tags,\n ].some((value) => String(value).toLowerCase().includes(needle)))\n }, [memories, memoryFilters.search])\n\n function updateFilter(partial: Partial<MemoryFilterState>) {\n set({ memoryFilters: { ...memoryFilters, ...partial } })\n }\n\n async function submitMemory() {\n const score = Number(form.relevanceScore)\n const common = {\n title: form.title.trim(),\n content: form.content.trim(),\n tags: csv(form.tags),\n visibility: form.visibility,\n sensitivity: form.sensitivity,\n confidence: form.confidence,\n relevanceScore: Number.isFinite(score) ? Math.max(0, Math.min(1, score)) : 0.7,\n }\n if (formMode === 'edit' && selectedMemory) {\n await saveMemory(common satisfies UpdateMemoryInput, selectedMemory.id)\n return\n }\n const input: CreateMemoryInput = {\n ...common,\n type: form.type,\n scope: form.scope.trim(),\n }\n await saveMemory(input)\n setFormMode('create')\n setForm(blankForm())\n }\n\n async function runInject(memoryIds?: string[]) {\n if (!injectAgent) return\n const result = await injectMemory({\n agentId: injectAgent,\n memoryIds,\n query: memoryIds?.length ? undefined : queryFromFilters(memoryFilters),\n reason: injectReason.trim() || 'manual',\n budget: {\n maxTokens: Math.max(200, Number(maxTokens) || 1600),\n maxMemories: Math.max(1, Number(maxMemories) || 8),\n priorityCutoff: 3,\n },\n })\n if (result?.command?.id) setLastCommand(result.command.id)\n }\n\n function startCreate() {\n setFormMode('create')\n setForm(blankForm())\n }\n\n function startEdit() {\n if (!selectedMemory) return\n setFormMode('edit')\n setForm(formFromMemory(selectedMemory))\n }\n\n const canSave = form.title.trim() && form.content.trim() && (formMode === 'edit' || form.scope.trim())\n const configText = compactConfig(memoryBrokerInfo?.config)\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3 flex-wrap\">\n <div className=\"flex items-center gap-2\">\n <BrainCircuit className=\"w-5 h-5 text-muted-foreground\" />\n <h2 className=\"text-lg font-semibold\">Memory</h2>\n <Badge variant=\"secondary\">{memoryStats?.total ?? memoryTotal}</Badge>\n {memoryBrokerInfo && (\n <Badge className={memoryBrokerInfo.external ? 'bg-blue-500/15 text-blue-400 border-blue-500/30' : 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30'}>\n {memoryBrokerInfo.type}\n </Badge>\n )}\n </div>\n <Button size=\"sm\" variant=\"outline\" className=\"gap-1.5\" onClick={() => refreshMemory()}>\n <RefreshCw className={`w-3.5 h-3.5 ${memoryLoading ? 'animate-spin' : ''}`} />\n Refresh\n </Button>\n </div>\n\n <div className=\"grid gap-3 xl:grid-cols-[1.2fr_0.8fr]\">\n <Card>\n <CardHeader className=\"py-3 px-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-sm font-medium flex items-center gap-2\">\n <Database className=\"w-4 h-4 text-muted-foreground\" />\n Broker\n </CardTitle>\n {memoryBrokerInfo?.capabilities && (\n <div className=\"flex flex-wrap gap-1 justify-end\">\n {Object.entries(memoryBrokerInfo.capabilities).filter(([, enabled]) => Boolean(enabled)).map(([key]) => (\n <Badge key={key} variant=\"outline\" className=\"text-[10px] px-1.5 py-0\">{key}</Badge>\n ))}\n </div>\n )}\n </div>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-3\">\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-2\">\n <Metric label=\"total\" value={memoryStats?.total ?? memoryTotal} />\n <Metric label=\"project\" value={memoryStats?.byType?.project ?? 0} />\n <Metric label=\"task\" value={memoryStats?.byType?.task ?? 0} />\n <Metric label=\"agent\" value={memoryStats?.byType?.agent ?? 0} />\n <Metric label=\"sensitive\" value={(memoryStats?.bySensitivity?.sensitive ?? 0) + (memoryStats?.bySensitivity?.secret ?? 0)} />\n </div>\n <div className=\"font-mono text-xs text-muted-foreground truncate\" title={configText}>{configText}</div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader className=\"py-3 px-4\">\n <CardTitle className=\"text-sm font-medium\">Inject</CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-2\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2\">\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={injectAgent} onChange={(e) => setInjectAgent(e.target.value)}>\n <option value=\"\">Agent</option>\n {candidates.map((agent) => <option key={agent.id} value={agent.id}>{displayName(agent)}</option>)}\n </select>\n <Input value={injectReason} onChange={(e) => setInjectReason(e.target.value)} placeholder=\"reason\" />\n <Input value={maxTokens} onChange={(e) => setMaxTokens(e.target.value)} inputMode=\"numeric\" placeholder=\"tokens\" />\n <Input value={maxMemories} onChange={(e) => setMaxMemories(e.target.value)} inputMode=\"numeric\" placeholder=\"memories\" />\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button size=\"sm\" className=\"gap-1.5\" disabled={!injectAgent || !selectedMemory} onClick={() => selectedMemory && runInject([selectedMemory.id])}>\n <Send className=\"w-3.5 h-3.5\" />\n Selected\n </Button>\n <Button size=\"sm\" variant=\"outline\" className=\"gap-1.5\" disabled={!injectAgent} onClick={() => runInject()}>\n <Search className=\"w-3.5 h-3.5\" />\n Filtered\n </Button>\n {lastCommand && <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{lastCommand}</Badge>}\n </div>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]\">\n <div className=\"space-y-3\">\n <Card>\n <CardContent className=\"p-3\">\n <div className=\"grid grid-cols-2 lg:grid-cols-6 gap-2\">\n <Input className=\"lg:col-span-2\" value={memoryFilters.search} onChange={(e) => updateFilter({ search: e.target.value })} placeholder=\"Search visible memories\" />\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={memoryFilters.type} onChange={(e) => updateFilter({ type: e.target.value })}>\n <option value=\"\">All types</option>\n {MEMORY_TYPES.map((type) => <option key={type} value={type}>{type}</option>)}\n </select>\n <Input value={memoryFilters.scope} onChange={(e) => updateFilter({ scope: e.target.value })} placeholder=\"scope\" />\n <Input value={memoryFilters.tags} onChange={(e) => updateFilter({ tags: e.target.value })} placeholder=\"tags\" />\n <div className=\"flex gap-2\">\n <Input value={memoryFilters.minRelevance} onChange={(e) => updateFilter({ minRelevance: e.target.value })} placeholder=\"score\" />\n <Button size=\"sm\" variant=\"outline\" className=\"h-8 px-2\" onClick={() => fetchMemories()}>\n <Search className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ScrollArea className=\"h-[calc(100dvh-24rem)] min-h-[360px]\">\n <div className=\"space-y-2 pr-2\">\n {visibleMemories.length === 0 && (\n <div className=\"text-center text-sm text-muted-foreground py-16\">No memories</div>\n )}\n {visibleMemories.map((memory) => (\n <MemoryRow\n key={memory.id}\n memory={memory}\n selected={memory.id === selectedMemoryId}\n now={now}\n onSelect={() => set({ selectedMemoryId: memory.id })}\n />\n ))}\n </div>\n </ScrollArea>\n </div>\n\n <Card>\n <CardHeader className=\"py-3 px-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-sm font-medium\">{formMode === 'edit' ? 'Edit Memory' : 'New Memory'}</CardTitle>\n <div className=\"flex gap-1\">\n <Button size=\"sm\" variant=\"ghost\" className=\"h-7 px-2\" onClick={startCreate} title=\"New memory\">\n <Plus className=\"w-3.5 h-3.5\" />\n </Button>\n <Button size=\"sm\" variant=\"ghost\" className=\"h-7 px-2\" onClick={startEdit} disabled={!selectedMemory} title=\"Edit selected\">\n <Edit3 className=\"w-3.5 h-3.5\" />\n </Button>\n <Button size=\"sm\" variant=\"ghost\" className=\"h-7 px-2 text-red-400 hover:text-red-300\" disabled={!selectedMemory} onClick={() => selectedMemory && deleteMemory(selectedMemory.id)} title=\"Delete selected\">\n <Trash2 className=\"w-3.5 h-3.5\" />\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-3\">\n {selectedMemory && (\n <>\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap gap-1\">\n <Badge variant=\"secondary\">{selectedMemory.type}</Badge>\n <Badge variant=\"outline\">{selectedMemory.scope}</Badge>\n <Badge className={sensitivityClass(selectedMemory.sensitivity)}>{selectedMemory.sensitivity}</Badge>\n <Badge variant=\"outline\" className={scoreClass(selectedMemory.relevanceScore)}>{selectedMemory.relevanceScore.toFixed(2)}</Badge>\n </div>\n <div className=\"text-xs text-muted-foreground\" title={fmtTime(selectedMemory.updatedAt)}>\n updated {timeAgo(now, selectedMemory.updatedAt)}\n </div>\n <p className=\"text-sm font-medium\">{selectedMemory.title}</p>\n <p className=\"text-xs text-muted-foreground whitespace-pre-wrap max-h-24 overflow-auto\">{selectedMemory.content}</p>\n </div>\n <Separator />\n </>\n )}\n\n <div className=\"grid grid-cols-2 gap-2\">\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" disabled={formMode === 'edit'} value={form.type} onChange={(e) => setForm({ ...form, type: e.target.value as MemoryType })}>\n {MEMORY_TYPES.map((type) => <option key={type} value={type}>{type}</option>)}\n </select>\n <Input disabled={formMode === 'edit'} value={form.scope} onChange={(e) => setForm({ ...form, scope: e.target.value })} placeholder=\"scope\" />\n <Input className=\"col-span-2\" value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })} placeholder=\"title\" />\n <Textarea className=\"col-span-2 min-h-32\" value={form.content} onChange={(e) => setForm({ ...form, content: e.target.value })} placeholder=\"content\" />\n <Input className=\"col-span-2\" value={form.tags} onChange={(e) => setForm({ ...form, tags: e.target.value })} placeholder=\"tags\" />\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={form.visibility} onChange={(e) => setForm({ ...form, visibility: e.target.value as MemoryForm['visibility'] })}>\n {VISIBILITIES.map((value) => <option key={value} value={value}>{value}</option>)}\n </select>\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={form.sensitivity} onChange={(e) => setForm({ ...form, sensitivity: e.target.value as MemoryForm['sensitivity'] })}>\n {SENSITIVITIES.map((value) => <option key={value} value={value}>{value}</option>)}\n </select>\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={form.confidence} onChange={(e) => setForm({ ...form, confidence: e.target.value as MemoryForm['confidence'] })}>\n {CONFIDENCES.map((value) => <option key={value} value={value}>{value}</option>)}\n </select>\n <Input value={form.relevanceScore} onChange={(e) => setForm({ ...form, relevanceScore: e.target.value })} inputMode=\"decimal\" placeholder=\"score\" />\n </div>\n <Button size=\"sm\" className=\"w-full\" disabled={!canSave} onClick={submitMemory}>\n {formMode === 'edit' ? 'Save memory' : 'Create memory'}\n </Button>\n </CardContent>\n </Card>\n </div>\n </div>\n )\n}\n\nfunction Metric({ label, value }: { label: string; value: number }) {\n return (\n <div className=\"rounded-md border border-border bg-muted/20 px-3 py-2\">\n <div className=\"text-lg font-semibold tabular-nums\">{value}</div>\n <div className=\"text-xs text-muted-foreground\">{label}</div>\n </div>\n )\n}\n\nfunction MemoryRow({ memory, selected, now, onSelect }: { memory: Memory; selected: boolean; now: number; onSelect: () => void }) {\n return (\n <button\n onClick={onSelect}\n className={`w-full text-left rounded-md border p-3 transition-colors ${selected ? 'border-primary bg-primary/5' : 'border-border bg-card hover:border-zinc-600'}`}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n <Badge variant=\"secondary\" className=\"text-[10px]\">{memory.type}</Badge>\n <Badge variant=\"outline\" className=\"text-[10px] font-mono\">{memory.scope}</Badge>\n <Badge className={`text-[10px] ${sensitivityClass(memory.sensitivity)}`}>{memory.sensitivity}</Badge>\n </div>\n <div className=\"font-medium text-sm mt-2 truncate\">{memory.title}</div>\n <div className=\"text-xs text-muted-foreground line-clamp-2 mt-1\">{memory.content}</div>\n {memory.tags.length > 0 && (\n <div className=\"flex gap-1 flex-wrap mt-2\">\n {memory.tags.slice(0, 8).map((tag) => <Badge key={tag} variant=\"outline\" className=\"text-[10px] text-zinc-400\">#{tag}</Badge>)}\n </div>\n )}\n </div>\n <div className=\"text-right shrink-0 space-y-1\">\n <div className={`text-sm font-semibold tabular-nums ${scoreClass(memory.relevanceScore)}`}>{memory.relevanceScore.toFixed(2)}</div>\n <div className=\"text-[10px] text-muted-foreground\" title={fmtTime(memory.updatedAt)}>{timeAgo(now, memory.updatedAt)}</div>\n {memory.accessCount > 0 && <div className=\"text-[10px] text-muted-foreground\">{memory.accessCount} hits</div>}\n </div>\n </div>\n </button>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory-BWfDbph3.js","names":[],"sources":["../../dashboard/src/components/views/memory.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react'\nimport { useRelayStore, useNow } from '@/store'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport { Separator } from '@/components/ui/separator'\nimport { BrainCircuit, Database, Edit3, Plus, RefreshCw, Search, Send, Trash2 } from 'lucide-react'\nimport { displayName, fmtTime, timeAgo } from '@/lib/display'\nimport type { Agent, CreateMemoryInput, Memory, MemoryFilterState, MemoryQuery, MemoryType, UpdateMemoryInput } from '@/types'\n\nconst MEMORY_TYPES: MemoryType[] = ['organization', 'role', 'project', 'task', 'interaction', 'agent']\nconst VISIBILITIES = ['private', 'project', 'org', 'public'] as const\nconst SENSITIVITIES = ['public', 'normal', 'sensitive', 'secret'] as const\nconst CONFIDENCES = ['reported', 'inferred', 'verified'] as const\n\ntype MemoryForm = {\n type: MemoryType\n scope: string\n title: string\n content: string\n tags: string\n visibility: (typeof VISIBILITIES)[number]\n sensitivity: (typeof SENSITIVITIES)[number]\n confidence: (typeof CONFIDENCES)[number]\n relevanceScore: string\n}\n\nfunction blankForm(): MemoryForm {\n return {\n type: 'project',\n scope: 'default',\n title: '',\n content: '',\n tags: '',\n visibility: 'project',\n sensitivity: 'normal',\n confidence: 'reported',\n relevanceScore: '0.7',\n }\n}\n\nfunction formFromMemory(memory: Memory): MemoryForm {\n return {\n type: memory.type,\n scope: memory.scope,\n title: memory.title,\n content: memory.content,\n tags: memory.tags.join(', '),\n visibility: memory.visibility,\n sensitivity: memory.sensitivity,\n confidence: memory.confidence,\n relevanceScore: String(memory.relevanceScore),\n }\n}\n\nfunction csv(value: string): string[] {\n return value.split(',').map((item) => item.trim()).filter(Boolean)\n}\n\nfunction queryFromFilters(filters: MemoryFilterState): MemoryQuery {\n const query: MemoryQuery = { limit: 100 }\n if (filters.type) query.type = filters.type as MemoryQuery['type']\n if (filters.scope.trim()) query.scope = filters.scope.trim()\n if (filters.visibility) query.visibility = filters.visibility as MemoryQuery['visibility']\n const tags = csv(filters.tags)\n if (tags.length) query.tags = tags\n if (filters.minRelevance.trim()) {\n const minRelevance = Number(filters.minRelevance)\n if (Number.isFinite(minRelevance)) query.minRelevance = Math.max(0, Math.min(1, minRelevance))\n }\n return query\n}\n\nfunction sensitivityClass(value: string) {\n if (value === 'secret') return 'bg-red-500/10 text-red-400 border-red-500/30'\n if (value === 'sensitive') return 'bg-yellow-500/10 text-yellow-400 border-yellow-500/30'\n if (value === 'public') return 'bg-blue-500/10 text-blue-400 border-blue-500/30'\n return 'bg-zinc-500/10 text-zinc-400 border-zinc-500/30'\n}\n\nfunction scoreClass(score: number) {\n if (score >= 0.8) return 'text-emerald-400'\n if (score >= 0.5) return 'text-yellow-400'\n return 'text-zinc-400'\n}\n\nfunction compactConfig(config: Record<string, unknown> | undefined): string {\n if (!config) return 'default'\n return Object.entries(config)\n .map(([key, value]) => `${key}=${Array.isArray(value) ? value.join(' ') : String(value)}`)\n .join(' ')\n}\n\nfunction agentOptions(agents: Agent[]) {\n return agents.filter((agent) => !['system', 'user', 'channel'].includes(agent.kind || ''))\n}\n\nexport function MemoryView() {\n const now = useNow()\n const agents = useRelayStore((s) => s.agents)\n const memories = useRelayStore((s) => s.memories)\n const memoryTotal = useRelayStore((s) => s.memoryTotal)\n const memoryStats = useRelayStore((s) => s.memoryStats)\n const memoryBrokerInfo = useRelayStore((s) => s.memoryBrokerInfo)\n const memoryFilters = useRelayStore((s) => s.memoryFilters)\n const selectedMemoryId = useRelayStore((s) => s.selectedMemoryId)\n const memoryLoading = useRelayStore((s) => s.memoryLoading)\n const set = useRelayStore((s) => s.set)\n const fetchMemories = useRelayStore((s) => s.fetchMemories)\n const refreshMemory = useRelayStore((s) => s.refreshMemory)\n const saveMemory = useRelayStore((s) => s.saveMemory)\n const deleteMemory = useRelayStore((s) => s.deleteMemory)\n const injectMemory = useRelayStore((s) => s.injectMemory)\n\n const selectedMemory = memories.find((memory) => memory.id === selectedMemoryId)\n const [formMode, setFormMode] = useState<'create' | 'edit'>('create')\n const [form, setForm] = useState<MemoryForm>(blankForm)\n const [injectAgent, setInjectAgent] = useState('')\n const [injectReason, setInjectReason] = useState('manual')\n const [maxTokens, setMaxTokens] = useState('1600')\n const [maxMemories, setMaxMemories] = useState('8')\n const [lastCommand, setLastCommand] = useState('')\n\n const candidates = useMemo(() => agentOptions(agents), [agents])\n\n useEffect(() => {\n if (!injectAgent && candidates[0]) setInjectAgent(candidates[0].id)\n }, [candidates, injectAgent])\n\n useEffect(() => {\n if (selectedMemory && formMode === 'edit') setForm(formFromMemory(selectedMemory))\n }, [selectedMemory?.id, formMode])\n\n const visibleMemories = useMemo(() => {\n const needle = memoryFilters.search.trim().toLowerCase()\n if (!needle) return memories\n return memories.filter((memory) => [\n memory.id, memory.type, memory.scope, memory.title, memory.content, ...memory.tags,\n ].some((value) => String(value).toLowerCase().includes(needle)))\n }, [memories, memoryFilters.search])\n\n function updateFilter(partial: Partial<MemoryFilterState>) {\n set({ memoryFilters: { ...memoryFilters, ...partial } })\n }\n\n async function submitMemory() {\n const score = Number(form.relevanceScore)\n const common = {\n title: form.title.trim(),\n content: form.content.trim(),\n tags: csv(form.tags),\n visibility: form.visibility,\n sensitivity: form.sensitivity,\n confidence: form.confidence,\n relevanceScore: Number.isFinite(score) ? Math.max(0, Math.min(1, score)) : 0.7,\n }\n if (formMode === 'edit' && selectedMemory) {\n await saveMemory(common satisfies UpdateMemoryInput, selectedMemory.id)\n return\n }\n const input: CreateMemoryInput = {\n ...common,\n type: form.type,\n scope: form.scope.trim(),\n }\n await saveMemory(input)\n setFormMode('create')\n setForm(blankForm())\n }\n\n async function runInject(memoryIds?: string[]) {\n if (!injectAgent) return\n const result = await injectMemory({\n agentId: injectAgent,\n memoryIds,\n query: memoryIds?.length ? undefined : queryFromFilters(memoryFilters),\n reason: injectReason.trim() || 'manual',\n budget: {\n maxTokens: Math.max(200, Number(maxTokens) || 1600),\n maxMemories: Math.max(1, Number(maxMemories) || 8),\n priorityCutoff: 3,\n },\n })\n if (result?.command?.id) setLastCommand(result.command.id)\n }\n\n function startCreate() {\n setFormMode('create')\n setForm(blankForm())\n }\n\n function startEdit() {\n if (!selectedMemory) return\n setFormMode('edit')\n setForm(formFromMemory(selectedMemory))\n }\n\n const canSave = form.title.trim() && form.content.trim() && (formMode === 'edit' || form.scope.trim())\n const configText = compactConfig(memoryBrokerInfo?.config)\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3 flex-wrap\">\n <div className=\"flex items-center gap-2\">\n <BrainCircuit className=\"w-5 h-5 text-muted-foreground\" />\n <h2 className=\"text-lg font-semibold\">Memory</h2>\n <Badge variant=\"secondary\">{memoryStats?.total ?? memoryTotal}</Badge>\n {memoryBrokerInfo && (\n <Badge className={memoryBrokerInfo.external ? 'bg-blue-500/15 text-blue-400 border-blue-500/30' : 'bg-emerald-500/15 text-emerald-400 border-emerald-500/30'}>\n {memoryBrokerInfo.type}\n </Badge>\n )}\n </div>\n <Button size=\"sm\" variant=\"outline\" className=\"gap-1.5\" onClick={() => refreshMemory()}>\n <RefreshCw className={`w-3.5 h-3.5 ${memoryLoading ? 'animate-spin' : ''}`} />\n Refresh\n </Button>\n </div>\n\n <div className=\"grid gap-3 xl:grid-cols-[1.2fr_0.8fr]\">\n <Card>\n <CardHeader className=\"py-3 px-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-sm font-medium flex items-center gap-2\">\n <Database className=\"w-4 h-4 text-muted-foreground\" />\n Broker\n </CardTitle>\n {memoryBrokerInfo?.capabilities && (\n <div className=\"flex flex-wrap gap-1 justify-end\">\n {Object.entries(memoryBrokerInfo.capabilities).filter(([, enabled]) => Boolean(enabled)).map(([key]) => (\n <Badge key={key} variant=\"outline\" className=\"text-[10px] px-1.5 py-0\">{key}</Badge>\n ))}\n </div>\n )}\n </div>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-3\">\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-2\">\n <Metric label=\"total\" value={memoryStats?.total ?? memoryTotal} />\n <Metric label=\"project\" value={memoryStats?.byType?.project ?? 0} />\n <Metric label=\"task\" value={memoryStats?.byType?.task ?? 0} />\n <Metric label=\"agent\" value={memoryStats?.byType?.agent ?? 0} />\n <Metric label=\"sensitive\" value={(memoryStats?.bySensitivity?.sensitive ?? 0) + (memoryStats?.bySensitivity?.secret ?? 0)} />\n </div>\n <div className=\"font-mono text-xs text-muted-foreground truncate\" title={configText}>{configText}</div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader className=\"py-3 px-4\">\n <CardTitle className=\"text-sm font-medium\">Inject</CardTitle>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-2\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2\">\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={injectAgent} onChange={(e) => setInjectAgent(e.target.value)}>\n <option value=\"\">Agent</option>\n {candidates.map((agent) => <option key={agent.id} value={agent.id}>{displayName(agent)}</option>)}\n </select>\n <Input value={injectReason} onChange={(e) => setInjectReason(e.target.value)} placeholder=\"reason\" />\n <Input value={maxTokens} onChange={(e) => setMaxTokens(e.target.value)} inputMode=\"numeric\" placeholder=\"tokens\" />\n <Input value={maxMemories} onChange={(e) => setMaxMemories(e.target.value)} inputMode=\"numeric\" placeholder=\"memories\" />\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button size=\"sm\" className=\"gap-1.5\" disabled={!injectAgent || !selectedMemory} onClick={() => selectedMemory && runInject([selectedMemory.id])}>\n <Send className=\"w-3.5 h-3.5\" />\n Selected\n </Button>\n <Button size=\"sm\" variant=\"outline\" className=\"gap-1.5\" disabled={!injectAgent} onClick={() => runInject()}>\n <Search className=\"w-3.5 h-3.5\" />\n Filtered\n </Button>\n {lastCommand && <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{lastCommand}</Badge>}\n </div>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid gap-4 xl:grid-cols-[minmax(0,1fr)_420px]\">\n <div className=\"space-y-3\">\n <Card>\n <CardContent className=\"p-3\">\n <div className=\"grid grid-cols-2 lg:grid-cols-6 gap-2\">\n <Input className=\"lg:col-span-2\" value={memoryFilters.search} onChange={(e) => updateFilter({ search: e.target.value })} placeholder=\"Search visible memories\" />\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={memoryFilters.type} onChange={(e) => updateFilter({ type: e.target.value })}>\n <option value=\"\">All types</option>\n {MEMORY_TYPES.map((type) => <option key={type} value={type}>{type}</option>)}\n </select>\n <Input value={memoryFilters.scope} onChange={(e) => updateFilter({ scope: e.target.value })} placeholder=\"scope\" />\n <Input value={memoryFilters.tags} onChange={(e) => updateFilter({ tags: e.target.value })} placeholder=\"tags\" />\n <div className=\"flex gap-2\">\n <Input value={memoryFilters.minRelevance} onChange={(e) => updateFilter({ minRelevance: e.target.value })} placeholder=\"score\" />\n <Button size=\"sm\" variant=\"outline\" className=\"h-8 px-2\" onClick={() => fetchMemories()}>\n <Search className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <ScrollArea className=\"h-[calc(100dvh-24rem)] min-h-[360px]\">\n <div className=\"space-y-2 pr-2\">\n {visibleMemories.length === 0 && (\n <div className=\"text-center text-sm text-muted-foreground py-16\">No memories</div>\n )}\n {visibleMemories.map((memory) => (\n <MemoryRow\n key={memory.id}\n memory={memory}\n selected={memory.id === selectedMemoryId}\n now={now}\n onSelect={() => set({ selectedMemoryId: memory.id })}\n />\n ))}\n </div>\n </ScrollArea>\n </div>\n\n <Card>\n <CardHeader className=\"py-3 px-4\">\n <div className=\"flex items-center justify-between gap-2\">\n <CardTitle className=\"text-sm font-medium\">{formMode === 'edit' ? 'Edit Memory' : 'New Memory'}</CardTitle>\n <div className=\"flex gap-1\">\n <Button size=\"sm\" variant=\"ghost\" className=\"h-7 px-2\" onClick={startCreate} title=\"New memory\">\n <Plus className=\"w-3.5 h-3.5\" />\n </Button>\n <Button size=\"sm\" variant=\"ghost\" className=\"h-7 px-2\" onClick={startEdit} disabled={!selectedMemory} title=\"Edit selected\">\n <Edit3 className=\"w-3.5 h-3.5\" />\n </Button>\n <Button size=\"sm\" variant=\"ghost\" className=\"h-7 px-2 text-red-400 hover:text-red-300\" disabled={!selectedMemory} onClick={() => selectedMemory && deleteMemory(selectedMemory.id)} title=\"Delete selected\">\n <Trash2 className=\"w-3.5 h-3.5\" />\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"px-4 pb-4 space-y-3\">\n {selectedMemory && (\n <>\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap gap-1\">\n <Badge variant=\"secondary\">{selectedMemory.type}</Badge>\n <Badge variant=\"outline\">{selectedMemory.scope}</Badge>\n <Badge className={sensitivityClass(selectedMemory.sensitivity)}>{selectedMemory.sensitivity}</Badge>\n <Badge variant=\"outline\" className={scoreClass(selectedMemory.relevanceScore)}>{selectedMemory.relevanceScore.toFixed(2)}</Badge>\n </div>\n <div className=\"text-xs text-muted-foreground\" title={fmtTime(selectedMemory.updatedAt)}>\n updated {timeAgo(now, selectedMemory.updatedAt)}\n </div>\n <p className=\"text-sm font-medium\">{selectedMemory.title}</p>\n <p className=\"text-xs text-muted-foreground whitespace-pre-wrap max-h-24 overflow-auto\">{selectedMemory.content}</p>\n </div>\n <Separator />\n </>\n )}\n\n <div className=\"grid grid-cols-2 gap-2\">\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" disabled={formMode === 'edit'} value={form.type} onChange={(e) => setForm({ ...form, type: e.target.value as MemoryType })}>\n {MEMORY_TYPES.map((type) => <option key={type} value={type}>{type}</option>)}\n </select>\n <Input disabled={formMode === 'edit'} value={form.scope} onChange={(e) => setForm({ ...form, scope: e.target.value })} placeholder=\"scope\" />\n <Input className=\"col-span-2\" value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })} placeholder=\"title\" />\n <Textarea className=\"col-span-2 min-h-32\" value={form.content} onChange={(e) => setForm({ ...form, content: e.target.value })} placeholder=\"content\" />\n <Input className=\"col-span-2\" value={form.tags} onChange={(e) => setForm({ ...form, tags: e.target.value })} placeholder=\"tags\" />\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={form.visibility} onChange={(e) => setForm({ ...form, visibility: e.target.value as MemoryForm['visibility'] })}>\n {VISIBILITIES.map((value) => <option key={value} value={value}>{value}</option>)}\n </select>\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={form.sensitivity} onChange={(e) => setForm({ ...form, sensitivity: e.target.value as MemoryForm['sensitivity'] })}>\n {SENSITIVITIES.map((value) => <option key={value} value={value}>{value}</option>)}\n </select>\n <select className=\"rounded-md border border-input bg-background px-2 py-1.5 text-sm\" value={form.confidence} onChange={(e) => setForm({ ...form, confidence: e.target.value as MemoryForm['confidence'] })}>\n {CONFIDENCES.map((value) => <option key={value} value={value}>{value}</option>)}\n </select>\n <Input value={form.relevanceScore} onChange={(e) => setForm({ ...form, relevanceScore: e.target.value })} inputMode=\"decimal\" placeholder=\"score\" />\n </div>\n <Button size=\"sm\" className=\"w-full\" disabled={!canSave} onClick={submitMemory}>\n {formMode === 'edit' ? 'Save memory' : 'Create memory'}\n </Button>\n </CardContent>\n </Card>\n </div>\n </div>\n )\n}\n\nfunction Metric({ label, value }: { label: string; value: number }) {\n return (\n <div className=\"rounded-md border border-border bg-muted/20 px-3 py-2\">\n <div className=\"text-lg font-semibold tabular-nums\">{value}</div>\n <div className=\"text-xs text-muted-foreground\">{label}</div>\n </div>\n )\n}\n\nfunction MemoryRow({ memory, selected, now, onSelect }: { memory: Memory; selected: boolean; now: number; onSelect: () => void }) {\n return (\n <button\n onClick={onSelect}\n className={`w-full text-left rounded-md border p-3 transition-colors ${selected ? 'border-primary bg-primary/5' : 'border-border bg-card hover:border-zinc-600'}`}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5 flex-wrap\">\n <Badge variant=\"secondary\" className=\"text-[10px]\">{memory.type}</Badge>\n <Badge variant=\"outline\" className=\"text-[10px] font-mono\">{memory.scope}</Badge>\n <Badge className={`text-[10px] ${sensitivityClass(memory.sensitivity)}`}>{memory.sensitivity}</Badge>\n </div>\n <div className=\"font-medium text-sm mt-2 truncate\">{memory.title}</div>\n <div className=\"text-xs text-muted-foreground line-clamp-2 mt-1\">{memory.content}</div>\n {memory.tags.length > 0 && (\n <div className=\"flex gap-1 flex-wrap mt-2\">\n {memory.tags.slice(0, 8).map((tag) => <Badge key={tag} variant=\"outline\" className=\"text-[10px] text-zinc-400\">#{tag}</Badge>)}\n </div>\n )}\n </div>\n <div className=\"text-right shrink-0 space-y-1\">\n <div className={`text-sm font-semibold tabular-nums ${scoreClass(memory.relevanceScore)}`}>{memory.relevanceScore.toFixed(2)}</div>\n <div className=\"text-[10px] text-muted-foreground\" title={fmtTime(memory.updatedAt)}>{timeAgo(now, memory.updatedAt)}</div>\n {memory.accessCount > 0 && <div className=\"text-[10px] text-muted-foreground\">{memory.accessCount} hits</div>}\n </div>\n </div>\n </button>\n )\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$ as t,A as n,Vn as r,Y as i,Zt as a,_n as o,_t as s,i as c,kn as l,m as u,p as d,z as f}from"./lucide-react-CD8Xl2U3.js";import{i as p,t as m}from"./store-CICRhg1m.js";import{d as h,m as g,u as _,w as v,z as y}from"./display-Bebqs1qu.js";import{t as b}from"./badge-t8zAwHW9.js";import{t as x}from"./button-DDA5P2YQ.js";import{L as S,M as C,t as w}from"./index-CvSlyTSI.js";import{n as T,t as E}from"./card-CggxP1h9.js";var D=e(r(),1),O=l();function k(e,t){if(t.startsWith(`/`))return t;let n=`${e.replace(/\/+$/,``)}/${t}`.split(`/`),r=[];for(let e of n)!e||e===`.`||(e===`..`?r.pop():r.push(e));return`/`+r.join(`/`)}function A(e){let t=e.replace(/\/+$/,``),n=t.lastIndexOf(`/`);return n>0?t.slice(0,n):`/`}function j(){let e=p(),n=m(e=>e.messages),r=m(e=>e.agentsById),a=m(e=>e.selectedAgent),o=m(e=>e.channelFilter),s=m(e=>e.tagFilter),l=m(e=>e.replyTo),u=m(e=>e.set),d=m(e=>e.openCompose),h=m(e=>e.startReply),g=m(e=>e.doClaim),v=m(e=>e.doDeliveryAction),y=m(e=>e.doDeleteMessage),w=m(e=>e.openThread),T=m(e=>e.cancelReply),E=C(),k=S(),A=(0,D.useMemo)(()=>{let e=[...n].sort((e,t)=>t.id-e.id);return a&&(e=e.filter(e=>e.from===a||e.to===a)),o&&(e=e.filter(e=>e.channel===o)),s&&(e=e.filter(e=>((r[e.from]||r[e.to])?.tags||[]).includes(s))),e},[n,a,o,s,r]),j=(0,D.useMemo)(()=>{let e=[],t=new Map;for(let n of A){let r=n.threadId??n.id;t.has(r)||t.set(r,[]),t.get(r).push(n),n.id===r&&e.push(n)}let n=new Set(e.map(e=>e.id));for(let t of A)!n.has(t.threadId??t.id)&&!e.find(e=>e.id===t.id)&&e.push(t);return e.sort((e,t)=>t.id-e.id),e.map(e=>({root:e,replies:(t.get(e.id)||[]).filter(t=>t.id!==e.id).sort((e,t)=>e.id-t.id)}))},[A]);function N(e){return r[e]?_(r[e]):e.slice(-10)}let P=(0,D.useMemo)(()=>[...new Set(n.map(e=>e.channel).filter(Boolean))],[n]);return(0,O.jsxs)(`div`,{className:`space-y-4`,children:[(0,O.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(t,{className:`w-5 h-5 text-muted-foreground`}),(0,O.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Messages`}),(0,O.jsx)(b,{variant:`secondary`,children:A.length})]}),(0,O.jsxs)(x,{size:`sm`,onClick:d,children:[(0,O.jsx)(f,{className:`w-4 h-4 mr-1`}),` Compose`]})]}),(0,O.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,O.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:a,onChange:e=>u({selectedAgent:e.target.value}),children:[(0,O.jsx)(`option`,{value:``,children:`All agents`}),E.map(e=>(0,O.jsx)(`option`,{value:e.id,children:_(e)},e.id))]}),(0,O.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:s,onChange:e=>u({tagFilter:e.target.value}),children:[(0,O.jsx)(`option`,{value:``,children:`All tags`}),k.map(e=>(0,O.jsxs)(`option`,{value:e,children:[`#`,e]},e))]}),(0,O.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:o,onChange:e=>u({channelFilter:e.target.value}),children:[(0,O.jsx)(`option`,{value:``,children:`All channels`}),P.map(e=>(0,O.jsx)(`option`,{value:e,children:e},e))]})]}),l&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md bg-blue-500/10 border border-blue-500/20 px-3 py-2 text-sm text-blue-300`,children:[(0,O.jsx)(i,{className:`w-4 h-4 shrink-0`}),(0,O.jsxs)(`span`,{children:[`Replying to message #`,l.id,` from `,(0,O.jsx)(`strong`,{children:N(l.from)})]}),(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`ml-auto h-6 px-1.5`,onClick:T,children:(0,O.jsx)(c,{className:`w-3.5 h-3.5`})})]}),(0,O.jsx)(`div`,{className:`h-[calc(100dvh-15rem)] overflow-y-auto`,children:(0,O.jsxs)(`div`,{className:`space-y-2 pr-2`,children:[j.length===0&&(0,O.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No messages`}),j.map(({root:t,replies:n})=>(0,O.jsxs)(`div`,{className:`space-y-1`,children:[(0,O.jsx)(M,{msg:t,now:e,agentLabel:N,agentsById:r,onReply:()=>h(t),onClaim:()=>g(t.id),onRetry:()=>v(t.id,`retry-now`),onMarkDead:()=>v(t.id,`mark-dead`,`Marked dead from dashboard`),onClear:()=>v(t.id,`clear`,`Cleared after manual handling`),onDelete:()=>y(t.id),onThread:t.threadId?()=>w(t.threadId):void 0,replyCount:n.length}),n.map(t=>(0,O.jsx)(`div`,{className:`ml-6`,children:(0,O.jsx)(M,{msg:t,now:e,agentLabel:N,agentsById:r,onReply:()=>h(t),onClaim:()=>g(t.id),onRetry:()=>v(t.id,`retry-now`),onMarkDead:()=>v(t.id,`mark-dead`,`Marked dead from dashboard`),onClear:()=>v(t.id,`clear`,`Cleared after manual handling`),onDelete:()=>y(t.id)})},t.id))]},t.id))]})})]})}function M({msg:e,now:t,agentLabel:r,agentsById:c,onReply:l,onClaim:d,onRetry:f,onMarkDead:p,onClear:_,onDelete:S,onThread:C,replyCount:j}){let[M,P]=(0,D.useState)(!1),F=v(e),I=m(e=>e.openFilesAt),L=e.deliveryStatus===`queued`||e.deliveryStatus===`failed`||e.deliveryStatus===`dead`||!!(e.deliveryLastError||e.deliveryPoisonReason),R=c[e.from===`user`?e.to:e.from];function z(e){return k((typeof R?.meta?.cwd==`string`?R.meta.cwd:``)||`/`,e)}function B(e,t){let n=z(e);I({path:A(n),selectedPath:n,line:t,overlay:!0})}return(0,O.jsx)(E,{className:`group relative`,children:(0,O.jsxs)(T,{className:`p-3`,children:[(0,O.jsxs)(`div`,{className:`min-w-0`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap text-xs text-muted-foreground mb-1`,children:[(0,O.jsx)(`span`,{className:`font-medium text-foreground`,children:r(e.from)}),(0,O.jsx)(`span`,{children:`→`}),(0,O.jsx)(`span`,{children:h(e.to,c)}),e.channel&&(0,O.jsxs)(b,{variant:`outline`,className:`text-xs px-1.5 py-0 gap-0.5`,children:[(0,O.jsx)(s,{className:`w-2.5 h-2.5`}),e.channel]}),e.claimedBy&&(0,O.jsxs)(b,{variant:`outline`,className:`text-xs px-1.5 py-0 text-emerald-400 border-emerald-500/30`,children:[(0,O.jsx)(a,{className:`w-2.5 h-2.5 mr-0.5`}),`claimed`]}),L&&(0,O.jsx)(N,{msg:e,now:t}),e.subject&&(0,O.jsx)(`span`,{className:`font-medium text-foreground`,children:e.subject}),(0,O.jsxs)(`span`,{className:`ml-auto shrink-0`,title:g(e.createdAt),children:[(0,O.jsxs)(`span`,{className:`opacity-40 mr-1`,children:[`#`,e.id]}),y(t,e.createdAt)]})]}),F&&(0,O.jsx)(`div`,{className:`cursor-pointer`,onClick:()=>P(e=>!e),children:(0,O.jsx)(w,{text:F,rawBody:e.body,className:`text-sm text-muted-foreground ${M?``:`max-h-[3.75rem] overflow-hidden`}`,onOpenPath:B,resolvePathTitle:(e,t)=>`${z(e)}${t?`:${t}`:``}`})})]}),(0,O.jsxs)(`div`,{className:`absolute top-2 right-2 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity bg-card rounded-md shadow-sm border border-border px-1 py-0.5`,children:[(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs`,onClick:l,title:`Reply`,children:(0,O.jsx)(i,{className:`w-3.5 h-3.5`})}),e.claimable&&!e.claimedBy&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-orange-400 hover:text-orange-300`,onClick:d,title:`Claim`,children:(0,O.jsx)(a,{className:`w-3.5 h-3.5`})}),L&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-blue-400 hover:text-blue-300`,onClick:f,title:`Retry delivery now`,children:(0,O.jsx)(n,{className:`w-3.5 h-3.5`})}),e.deliveryStatus!==`dead`&&L&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-red-400 hover:text-red-300`,onClick:p,title:`Mark dead`,children:(0,O.jsx)(o,{className:`w-3.5 h-3.5`})}),(e.deliveryStatus===`failed`||e.deliveryStatus===`dead`)&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-emerald-400 hover:text-emerald-300`,onClick:_,title:`Clear after manual handling`,children:(0,O.jsx)(a,{className:`w-3.5 h-3.5`})}),C&&(j??0)>0&&(0,O.jsxs)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs`,onClick:C,title:`Thread`,children:[`+`,j]}),(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-red-400 hover:text-red-300`,onClick:S,title:`Delete`,children:(0,O.jsx)(u,{className:`w-3.5 h-3.5`})})]})]})})}function N({msg:e,now:t}){let n=e.deliveryStatus||`pending`,r=e.deliveryPoisonReason||e.deliveryLastError||(e.deliveryNextRetryAt?`retry ${y(t,e.deliveryNextRetryAt)}`:void 0);return(0,O.jsxs)(b,{variant:`outline`,className:`text-xs px-1.5 py-0 ${n===`dead`?`text-red-300 border-red-500/30 bg-red-500/10`:n===`failed`?`text-amber-300 border-amber-500/30 bg-amber-500/10`:`text-blue-300 border-blue-500/30 bg-blue-500/10`}`,title:r||n,children:[(0,O.jsx)(d,{className:`w-2.5 h-2.5 mr-0.5`}),n,e.deliveryAttempts?` ${e.deliveryAttempts}x`:``]})}export{j as MessagesView};
2
- //# sourceMappingURL=messages-_sdHV42k.js.map
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{$ as t,A as n,Vn as r,Y as i,Zt as a,_n as o,_t as s,i as c,kn as l,m as u,p as d,z as f}from"./lucide-react-CD8Xl2U3.js";import{i as p,t as m}from"./store-CICRhg1m.js";import{d as h,m as g,u as _,w as v,z as y}from"./display-Bebqs1qu.js";import{t as b}from"./badge-t8zAwHW9.js";import{t as x}from"./button-DDA5P2YQ.js";import{L as S,M as C,t as w}from"./index-BL8r94_U.js";import{n as T,t as E}from"./card-CggxP1h9.js";var D=e(r(),1),O=l();function k(e,t){if(t.startsWith(`/`))return t;let n=`${e.replace(/\/+$/,``)}/${t}`.split(`/`),r=[];for(let e of n)!e||e===`.`||(e===`..`?r.pop():r.push(e));return`/`+r.join(`/`)}function A(e){let t=e.replace(/\/+$/,``),n=t.lastIndexOf(`/`);return n>0?t.slice(0,n):`/`}function j(){let e=p(),n=m(e=>e.messages),r=m(e=>e.agentsById),a=m(e=>e.selectedAgent),o=m(e=>e.channelFilter),s=m(e=>e.tagFilter),l=m(e=>e.replyTo),u=m(e=>e.set),d=m(e=>e.openCompose),h=m(e=>e.startReply),g=m(e=>e.doClaim),v=m(e=>e.doDeliveryAction),y=m(e=>e.doDeleteMessage),w=m(e=>e.openThread),T=m(e=>e.cancelReply),E=C(),k=S(),A=(0,D.useMemo)(()=>{let e=[...n].sort((e,t)=>t.id-e.id);return a&&(e=e.filter(e=>e.from===a||e.to===a)),o&&(e=e.filter(e=>e.channel===o)),s&&(e=e.filter(e=>((r[e.from]||r[e.to])?.tags||[]).includes(s))),e},[n,a,o,s,r]),j=(0,D.useMemo)(()=>{let e=[],t=new Map;for(let n of A){let r=n.threadId??n.id;t.has(r)||t.set(r,[]),t.get(r).push(n),n.id===r&&e.push(n)}let n=new Set(e.map(e=>e.id));for(let t of A)!n.has(t.threadId??t.id)&&!e.find(e=>e.id===t.id)&&e.push(t);return e.sort((e,t)=>t.id-e.id),e.map(e=>({root:e,replies:(t.get(e.id)||[]).filter(t=>t.id!==e.id).sort((e,t)=>e.id-t.id)}))},[A]);function N(e){return r[e]?_(r[e]):e.slice(-10)}let P=(0,D.useMemo)(()=>[...new Set(n.map(e=>e.channel).filter(Boolean))],[n]);return(0,O.jsxs)(`div`,{className:`space-y-4`,children:[(0,O.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(t,{className:`w-5 h-5 text-muted-foreground`}),(0,O.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Messages`}),(0,O.jsx)(b,{variant:`secondary`,children:A.length})]}),(0,O.jsxs)(x,{size:`sm`,onClick:d,children:[(0,O.jsx)(f,{className:`w-4 h-4 mr-1`}),` Compose`]})]}),(0,O.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,O.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:a,onChange:e=>u({selectedAgent:e.target.value}),children:[(0,O.jsx)(`option`,{value:``,children:`All agents`}),E.map(e=>(0,O.jsx)(`option`,{value:e.id,children:_(e)},e.id))]}),(0,O.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:s,onChange:e=>u({tagFilter:e.target.value}),children:[(0,O.jsx)(`option`,{value:``,children:`All tags`}),k.map(e=>(0,O.jsxs)(`option`,{value:e,children:[`#`,e]},e))]}),(0,O.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:o,onChange:e=>u({channelFilter:e.target.value}),children:[(0,O.jsx)(`option`,{value:``,children:`All channels`}),P.map(e=>(0,O.jsx)(`option`,{value:e,children:e},e))]})]}),l&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2 rounded-md bg-blue-500/10 border border-blue-500/20 px-3 py-2 text-sm text-blue-300`,children:[(0,O.jsx)(i,{className:`w-4 h-4 shrink-0`}),(0,O.jsxs)(`span`,{children:[`Replying to message #`,l.id,` from `,(0,O.jsx)(`strong`,{children:N(l.from)})]}),(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`ml-auto h-6 px-1.5`,onClick:T,children:(0,O.jsx)(c,{className:`w-3.5 h-3.5`})})]}),(0,O.jsx)(`div`,{className:`h-[calc(100dvh-15rem)] overflow-y-auto`,children:(0,O.jsxs)(`div`,{className:`space-y-2 pr-2`,children:[j.length===0&&(0,O.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No messages`}),j.map(({root:t,replies:n})=>(0,O.jsxs)(`div`,{className:`space-y-1`,children:[(0,O.jsx)(M,{msg:t,now:e,agentLabel:N,agentsById:r,onReply:()=>h(t),onClaim:()=>g(t.id),onRetry:()=>v(t.id,`retry-now`),onMarkDead:()=>v(t.id,`mark-dead`,`Marked dead from dashboard`),onClear:()=>v(t.id,`clear`,`Cleared after manual handling`),onDelete:()=>y(t.id),onThread:t.threadId?()=>w(t.threadId):void 0,replyCount:n.length}),n.map(t=>(0,O.jsx)(`div`,{className:`ml-6`,children:(0,O.jsx)(M,{msg:t,now:e,agentLabel:N,agentsById:r,onReply:()=>h(t),onClaim:()=>g(t.id),onRetry:()=>v(t.id,`retry-now`),onMarkDead:()=>v(t.id,`mark-dead`,`Marked dead from dashboard`),onClear:()=>v(t.id,`clear`,`Cleared after manual handling`),onDelete:()=>y(t.id)})},t.id))]},t.id))]})})]})}function M({msg:e,now:t,agentLabel:r,agentsById:c,onReply:l,onClaim:d,onRetry:f,onMarkDead:p,onClear:_,onDelete:S,onThread:C,replyCount:j}){let[M,P]=(0,D.useState)(!1),F=v(e),I=m(e=>e.openFilesAt),L=e.deliveryStatus===`queued`||e.deliveryStatus===`failed`||e.deliveryStatus===`dead`||!!(e.deliveryLastError||e.deliveryPoisonReason),R=c[e.from===`user`?e.to:e.from];function z(e){return k((typeof R?.meta?.cwd==`string`?R.meta.cwd:``)||`/`,e)}function B(e,t){let n=z(e);I({path:A(n),selectedPath:n,line:t,overlay:!0})}return(0,O.jsx)(E,{className:`group relative`,children:(0,O.jsxs)(T,{className:`p-3`,children:[(0,O.jsxs)(`div`,{className:`min-w-0`,children:[(0,O.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap text-xs text-muted-foreground mb-1`,children:[(0,O.jsx)(`span`,{className:`font-medium text-foreground`,children:r(e.from)}),(0,O.jsx)(`span`,{children:`→`}),(0,O.jsx)(`span`,{children:h(e.to,c)}),e.channel&&(0,O.jsxs)(b,{variant:`outline`,className:`text-xs px-1.5 py-0 gap-0.5`,children:[(0,O.jsx)(s,{className:`w-2.5 h-2.5`}),e.channel]}),e.claimedBy&&(0,O.jsxs)(b,{variant:`outline`,className:`text-xs px-1.5 py-0 text-emerald-400 border-emerald-500/30`,children:[(0,O.jsx)(a,{className:`w-2.5 h-2.5 mr-0.5`}),`claimed`]}),L&&(0,O.jsx)(N,{msg:e,now:t}),e.subject&&(0,O.jsx)(`span`,{className:`font-medium text-foreground`,children:e.subject}),(0,O.jsxs)(`span`,{className:`ml-auto shrink-0`,title:g(e.createdAt),children:[(0,O.jsxs)(`span`,{className:`opacity-40 mr-1`,children:[`#`,e.id]}),y(t,e.createdAt)]})]}),F&&(0,O.jsx)(`div`,{className:`cursor-pointer`,onClick:()=>P(e=>!e),children:(0,O.jsx)(w,{text:F,rawBody:e.body,className:`text-sm text-muted-foreground ${M?``:`max-h-[3.75rem] overflow-hidden`}`,onOpenPath:B,resolvePathTitle:(e,t)=>`${z(e)}${t?`:${t}`:``}`})})]}),(0,O.jsxs)(`div`,{className:`absolute top-2 right-2 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity bg-card rounded-md shadow-sm border border-border px-1 py-0.5`,children:[(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs`,onClick:l,title:`Reply`,children:(0,O.jsx)(i,{className:`w-3.5 h-3.5`})}),e.claimable&&!e.claimedBy&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-orange-400 hover:text-orange-300`,onClick:d,title:`Claim`,children:(0,O.jsx)(a,{className:`w-3.5 h-3.5`})}),L&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-blue-400 hover:text-blue-300`,onClick:f,title:`Retry delivery now`,children:(0,O.jsx)(n,{className:`w-3.5 h-3.5`})}),e.deliveryStatus!==`dead`&&L&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-red-400 hover:text-red-300`,onClick:p,title:`Mark dead`,children:(0,O.jsx)(o,{className:`w-3.5 h-3.5`})}),(e.deliveryStatus===`failed`||e.deliveryStatus===`dead`)&&(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-emerald-400 hover:text-emerald-300`,onClick:_,title:`Clear after manual handling`,children:(0,O.jsx)(a,{className:`w-3.5 h-3.5`})}),C&&(j??0)>0&&(0,O.jsxs)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs`,onClick:C,title:`Thread`,children:[`+`,j]}),(0,O.jsx)(x,{variant:`ghost`,size:`sm`,className:`h-7 px-2 text-xs text-red-400 hover:text-red-300`,onClick:S,title:`Delete`,children:(0,O.jsx)(u,{className:`w-3.5 h-3.5`})})]})]})})}function N({msg:e,now:t}){let n=e.deliveryStatus||`pending`,r=e.deliveryPoisonReason||e.deliveryLastError||(e.deliveryNextRetryAt?`retry ${y(t,e.deliveryNextRetryAt)}`:void 0);return(0,O.jsxs)(b,{variant:`outline`,className:`text-xs px-1.5 py-0 ${n===`dead`?`text-red-300 border-red-500/30 bg-red-500/10`:n===`failed`?`text-amber-300 border-amber-500/30 bg-amber-500/10`:`text-blue-300 border-blue-500/30 bg-blue-500/10`}`,title:r||n,children:[(0,O.jsx)(d,{className:`w-2.5 h-2.5 mr-0.5`}),n,e.deliveryAttempts?` ${e.deliveryAttempts}x`:``]})}export{j as MessagesView};
2
+ //# sourceMappingURL=messages-C8cP25kp.js.map