botmux 2.98.4-canary.2 → 2.99.0

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 (205) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/adapters/cli/genius.d.ts +4 -0
  4. package/dist/adapters/cli/genius.d.ts.map +1 -0
  5. package/dist/adapters/cli/genius.js +216 -0
  6. package/dist/adapters/cli/genius.js.map +1 -0
  7. package/dist/adapters/cli/registry.d.ts +2 -1
  8. package/dist/adapters/cli/registry.d.ts.map +1 -1
  9. package/dist/adapters/cli/registry.js +3 -1
  10. package/dist/adapters/cli/registry.js.map +1 -1
  11. package/dist/adapters/cli/types.d.ts +1 -1
  12. package/dist/adapters/cli/types.d.ts.map +1 -1
  13. package/dist/core/dashboard-rows.d.ts +1 -1
  14. package/dist/core/dashboard-rows.d.ts.map +1 -1
  15. package/dist/core/dashboard-rows.js +2 -1
  16. package/dist/core/dashboard-rows.js.map +1 -1
  17. package/dist/dashboard/session-card-model.d.ts +2 -2
  18. package/dist/dashboard/session-card-model.d.ts.map +1 -1
  19. package/dist/dashboard/session-card-model.js +5 -2
  20. package/dist/dashboard/session-card-model.js.map +1 -1
  21. package/dist/dashboard/web/app.d.ts.map +1 -1
  22. package/dist/dashboard/web/app.js +28 -63
  23. package/dist/dashboard/web/app.js.map +1 -1
  24. package/dist/dashboard/web/bot-defaults-page.d.ts +3 -0
  25. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -0
  26. package/dist/dashboard/web/bot-defaults-page.js +23 -0
  27. package/dist/dashboard/web/bot-defaults-page.js.map +1 -0
  28. package/dist/dashboard/web/bot-defaults.d.ts +2 -1
  29. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  30. package/dist/dashboard/web/bot-defaults.js +30 -30
  31. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  32. package/dist/dashboard/web/connectors-page.d.ts +14 -0
  33. package/dist/dashboard/web/connectors-page.d.ts.map +1 -0
  34. package/dist/dashboard/web/connectors-page.js +303 -0
  35. package/dist/dashboard/web/connectors-page.js.map +1 -0
  36. package/dist/dashboard/web/connectors.d.ts +1 -12
  37. package/dist/dashboard/web/connectors.d.ts.map +1 -1
  38. package/dist/dashboard/web/connectors.js +1 -325
  39. package/dist/dashboard/web/connectors.js.map +1 -1
  40. package/dist/dashboard/web/dashboard-routes.d.ts +14 -0
  41. package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -0
  42. package/dist/dashboard/web/dashboard-routes.js +176 -0
  43. package/dist/dashboard/web/dashboard-routes.js.map +1 -0
  44. package/dist/dashboard/web/groups-page.d.ts +3 -0
  45. package/dist/dashboard/web/groups-page.d.ts.map +1 -0
  46. package/dist/dashboard/web/groups-page.js +26 -0
  47. package/dist/dashboard/web/groups-page.js.map +1 -0
  48. package/dist/dashboard/web/groups.d.ts +1 -1
  49. package/dist/dashboard/web/groups.d.ts.map +1 -1
  50. package/dist/dashboard/web/groups.js +113 -52
  51. package/dist/dashboard/web/groups.js.map +1 -1
  52. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  53. package/dist/dashboard/web/i18n.js +18 -0
  54. package/dist/dashboard/web/i18n.js.map +1 -1
  55. package/dist/dashboard/web/insights-page.d.ts +3 -0
  56. package/dist/dashboard/web/insights-page.d.ts.map +1 -0
  57. package/dist/dashboard/web/insights-page.js +26 -0
  58. package/dist/dashboard/web/insights-page.js.map +1 -0
  59. package/dist/dashboard/web/insights.d.ts +18 -1
  60. package/dist/dashboard/web/insights.d.ts.map +1 -1
  61. package/dist/dashboard/web/insights.js +25 -61
  62. package/dist/dashboard/web/insights.js.map +1 -1
  63. package/dist/dashboard/web/office-page.d.ts +3 -0
  64. package/dist/dashboard/web/office-page.d.ts.map +1 -0
  65. package/dist/dashboard/web/office-page.js +149 -0
  66. package/dist/dashboard/web/office-page.js.map +1 -0
  67. package/dist/dashboard/web/office.d.ts +1 -1
  68. package/dist/dashboard/web/office.d.ts.map +1 -1
  69. package/dist/dashboard/web/office.js +1 -139
  70. package/dist/dashboard/web/office.js.map +1 -1
  71. package/dist/dashboard/web/overview-page.d.ts +3 -0
  72. package/dist/dashboard/web/overview-page.d.ts.map +1 -0
  73. package/dist/dashboard/web/overview-page.js +149 -0
  74. package/dist/dashboard/web/overview-page.js.map +1 -0
  75. package/dist/dashboard/web/overview.d.ts +2 -2
  76. package/dist/dashboard/web/overview.d.ts.map +1 -1
  77. package/dist/dashboard/web/overview.js +14 -3
  78. package/dist/dashboard/web/overview.js.map +1 -1
  79. package/dist/dashboard/web/react-hooks.d.ts +8 -0
  80. package/dist/dashboard/web/react-hooks.d.ts.map +1 -0
  81. package/dist/dashboard/web/react-hooks.js +43 -0
  82. package/dist/dashboard/web/react-hooks.js.map +1 -0
  83. package/dist/dashboard/web/react-mount.d.ts +4 -0
  84. package/dist/dashboard/web/react-mount.d.ts.map +1 -0
  85. package/dist/dashboard/web/react-mount.js +7 -0
  86. package/dist/dashboard/web/react-mount.js.map +1 -0
  87. package/dist/dashboard/web/roles-page.d.ts +4 -0
  88. package/dist/dashboard/web/roles-page.d.ts.map +1 -0
  89. package/dist/dashboard/web/roles-page.js +26 -0
  90. package/dist/dashboard/web/roles-page.js.map +1 -0
  91. package/dist/dashboard/web/roles.d.ts +1 -2
  92. package/dist/dashboard/web/roles.d.ts.map +1 -1
  93. package/dist/dashboard/web/roles.js +189 -135
  94. package/dist/dashboard/web/roles.js.map +1 -1
  95. package/dist/dashboard/web/route-lifecycle.d.ts +14 -0
  96. package/dist/dashboard/web/route-lifecycle.d.ts.map +1 -0
  97. package/dist/dashboard/web/route-lifecycle.js +29 -0
  98. package/dist/dashboard/web/route-lifecycle.js.map +1 -0
  99. package/dist/dashboard/web/schedules-page.d.ts +14 -0
  100. package/dist/dashboard/web/schedules-page.d.ts.map +1 -0
  101. package/dist/dashboard/web/schedules-page.js +84 -0
  102. package/dist/dashboard/web/schedules-page.js.map +1 -0
  103. package/dist/dashboard/web/schedules.d.ts +1 -1
  104. package/dist/dashboard/web/schedules.d.ts.map +1 -1
  105. package/dist/dashboard/web/schedules.js +1 -115
  106. package/dist/dashboard/web/schedules.js.map +1 -1
  107. package/dist/dashboard/web/sessions-page.d.ts +3 -0
  108. package/dist/dashboard/web/sessions-page.d.ts.map +1 -0
  109. package/dist/dashboard/web/sessions-page.js +28 -0
  110. package/dist/dashboard/web/sessions-page.js.map +1 -0
  111. package/dist/dashboard/web/sessions.d.ts +4 -1
  112. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  113. package/dist/dashboard/web/sessions.js +43 -10
  114. package/dist/dashboard/web/sessions.js.map +1 -1
  115. package/dist/dashboard/web/settings-page.d.ts +3 -0
  116. package/dist/dashboard/web/settings-page.d.ts.map +1 -0
  117. package/dist/dashboard/web/settings-page.js +387 -0
  118. package/dist/dashboard/web/settings-page.js.map +1 -0
  119. package/dist/dashboard/web/settings.d.ts +1 -1
  120. package/dist/dashboard/web/settings.d.ts.map +1 -1
  121. package/dist/dashboard/web/settings.js +1 -534
  122. package/dist/dashboard/web/settings.js.map +1 -1
  123. package/dist/dashboard/web/skills-page.d.ts +33 -0
  124. package/dist/dashboard/web/skills-page.d.ts.map +1 -0
  125. package/dist/dashboard/web/skills-page.js +515 -0
  126. package/dist/dashboard/web/skills-page.js.map +1 -0
  127. package/dist/dashboard/web/skills.d.ts +1 -1
  128. package/dist/dashboard/web/skills.d.ts.map +1 -1
  129. package/dist/dashboard/web/skills.js +1 -711
  130. package/dist/dashboard/web/skills.js.map +1 -1
  131. package/dist/dashboard/web/store.d.ts +9 -0
  132. package/dist/dashboard/web/store.d.ts.map +1 -1
  133. package/dist/dashboard/web/store.js +19 -2
  134. package/dist/dashboard/web/store.js.map +1 -1
  135. package/dist/dashboard/web/team-federation-page.d.ts +4 -0
  136. package/dist/dashboard/web/team-federation-page.d.ts.map +1 -0
  137. package/dist/dashboard/web/team-federation-page.js +47 -0
  138. package/dist/dashboard/web/team-federation-page.js.map +1 -0
  139. package/dist/dashboard/web/team-federation.d.ts +2 -2
  140. package/dist/dashboard/web/team-federation.d.ts.map +1 -1
  141. package/dist/dashboard/web/team-federation.js +104 -97
  142. package/dist/dashboard/web/team-federation.js.map +1 -1
  143. package/dist/dashboard/web/v3-page.d.ts +3 -0
  144. package/dist/dashboard/web/v3-page.d.ts.map +1 -0
  145. package/dist/dashboard/web/v3-page.js +27 -0
  146. package/dist/dashboard/web/v3-page.js.map +1 -0
  147. package/dist/dashboard/web/v3.d.ts +2 -1
  148. package/dist/dashboard/web/v3.d.ts.map +1 -1
  149. package/dist/dashboard/web/v3.js +18 -43
  150. package/dist/dashboard/web/v3.js.map +1 -1
  151. package/dist/dashboard/web/whiteboards-page.d.ts +3 -0
  152. package/dist/dashboard/web/whiteboards-page.d.ts.map +1 -0
  153. package/dist/dashboard/web/whiteboards-page.js +203 -0
  154. package/dist/dashboard/web/whiteboards-page.js.map +1 -0
  155. package/dist/dashboard/web/whiteboards.d.ts +1 -1
  156. package/dist/dashboard/web/whiteboards.d.ts.map +1 -1
  157. package/dist/dashboard/web/whiteboards.js +1 -275
  158. package/dist/dashboard/web/whiteboards.js.map +1 -1
  159. package/dist/dashboard-web/app.js +36 -2550
  160. package/dist/dashboard-web/chunks/bot-defaults-page-3EV7K6LJ.js +358 -0
  161. package/dist/dashboard-web/chunks/chunk-5E3MJJL4.js +1 -0
  162. package/dist/dashboard-web/chunks/chunk-76J7PNZI.js +1 -0
  163. package/dist/dashboard-web/chunks/chunk-7SZRL6FY.js +1 -0
  164. package/dist/dashboard-web/chunks/chunk-JTSE5VP6.js +54 -0
  165. package/dist/dashboard-web/chunks/chunk-JXLHRRJD.js +31 -0
  166. package/dist/dashboard-web/chunks/chunk-NASYW5FD.js +1 -0
  167. package/dist/dashboard-web/chunks/connectors-XPZKEHF6.js +1 -0
  168. package/dist/dashboard-web/chunks/groups-page-C54PVKYP.js +207 -0
  169. package/dist/dashboard-web/chunks/insights-page-BBQYR7WY.js +309 -0
  170. package/dist/dashboard-web/chunks/office-page-6DXYOG55.js +1 -0
  171. package/dist/dashboard-web/chunks/overview-page-5PJCAMID.js +1 -0
  172. package/dist/dashboard-web/chunks/roles-page-APUDLPVM.js +98 -0
  173. package/dist/dashboard-web/chunks/schedules-WG2UKHSO.js +1 -0
  174. package/dist/dashboard-web/chunks/sessions-page-F3U5NFPD.js +238 -0
  175. package/dist/dashboard-web/chunks/settings-page-OSBZNCXL.js +2 -0
  176. package/dist/dashboard-web/chunks/skills-page-Y3VUAOYG.js +2 -0
  177. package/dist/dashboard-web/chunks/team-federation-page-CRH3WZPH.js +10 -0
  178. package/dist/dashboard-web/chunks/v3-page-FVPUL665.js +149 -0
  179. package/dist/dashboard-web/chunks/whiteboards-page-HLCTYSSV.js +1 -0
  180. package/dist/dashboard-web/chunks/workflows-UB7OPYGI.js +184 -0
  181. package/dist/dashboard-web/index.html +1 -1
  182. package/dist/dashboard-web/style.css +82 -1
  183. package/dist/dashboard.js +5 -6
  184. package/dist/dashboard.js.map +1 -1
  185. package/dist/i18n/en.d.ts.map +1 -1
  186. package/dist/i18n/en.js +1 -0
  187. package/dist/i18n/en.js.map +1 -1
  188. package/dist/i18n/zh.d.ts.map +1 -1
  189. package/dist/i18n/zh.js +1 -0
  190. package/dist/i18n/zh.js.map +1 -1
  191. package/dist/im/lark/card-builder.d.ts.map +1 -1
  192. package/dist/im/lark/card-builder.js +1 -0
  193. package/dist/im/lark/card-builder.js.map +1 -1
  194. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  195. package/dist/im/lark/event-dispatcher.js +7 -0
  196. package/dist/im/lark/event-dispatcher.js.map +1 -1
  197. package/dist/im/lark/sessions-card.d.ts.map +1 -1
  198. package/dist/im/lark/sessions-card.js +4 -1
  199. package/dist/im/lark/sessions-card.js.map +1 -1
  200. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  201. package/dist/setup/bot-config-editor.js +16 -14
  202. package/dist/setup/bot-config-editor.js.map +1 -1
  203. package/dist/worker.js +1 -1
  204. package/dist/worker.js.map +1 -1
  205. package/package.json +8 -2
@@ -0,0 +1 @@
1
+ import{a as b,b as p,c as x}from"./chunk-JTSE5VP6.js";import{c as m}from"./chunk-7SZRL6FY.js";var i=m(b(),1);var e=m(x(),1),u=78222186;function y(t){return(t/1048576).toFixed(0)}function S(){let[t,n]=(0,i.useState)(null),[s,l]=(0,i.useState)(""),[c,f]=(0,i.useState)(!1),d=(0,i.useRef)(null),r=(0,i.useRef)(!1),h=()=>{d.current&&(clearTimeout(d.current),d.current=null)};async function g(){if(!r.current)try{let a=await fetch("/api/game/status");if(r.current)return;if(!a.ok){n({state:"absent",received:0,total:u});return}let o=await a.json();if(r.current)return;n(o),typeof o.proxy=="string"&&l(o.proxy),o.state==="downloading"&&(d.current=setTimeout(()=>{g()},700))}catch{r.current||(d.current=setTimeout(()=>{g()},1500))}}(0,i.useEffect)(()=>(r.current=!1,g(),()=>{r.current=!0,h()}),[]);async function v(){h(),f(!0),n({state:"downloading",received:0,total:u});try{let a=await fetch("/api/game/download",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({proxy:s.trim()})});if(r.current)return;if(!a.ok)throw new Error(`HTTP ${a.status}`);let o=await a.json();if(r.current)return;n(o),typeof o.proxy=="string"&&l(o.proxy),o.state==="downloading"&&(d.current=setTimeout(()=>{g()},700))}catch(a){if(r.current)return;n({state:"error",received:0,total:u,error:a instanceof Error?a.message:String(a)})}finally{r.current||f(!1)}}return t?.state==="ready"?(0,e.jsx)("iframe",{src:"/game/index.html",title:"HD2D Office",style:{flex:1,width:"100%",minHeight:0,border:"none",display:"block",background:"#0b0d12"},allow:"autoplay"}):(0,e.jsx)(w,{status:t??{state:"absent",received:0,total:u},proxy:s,starting:c,onProxyChange:l,onStart:()=>{v()}})}function w(t){let n=t.status.total||u,s=(0,i.useMemo)(()=>n?Math.min(100,Math.round(t.status.received/n*100)):0,[t.status.received,n]),l=t.status.state==="downloading",c=t.status.state==="error";return(0,e.jsxs)("div",{style:{margin:"auto",textAlign:"center",maxWidth:440,padding:32,color:"var(--fg,#e6e6e6)"},children:[(0,e.jsx)("div",{style:{fontSize:18,fontWeight:600,marginBottom:8},children:"HD2D \u529E\u516C\u5BA4"}),(0,e.jsxs)("div",{style:{fontSize:13,opacity:.7,lineHeight:1.7,marginBottom:20},children:["\u628A\u6BCF\u4E2A\u4F1A\u8BDD\u53D8\u6210\u529E\u516C\u5BA4\u91CC\u7684\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5B9E\u65F6\u6620\u5C04\u5C4F\u5E55\u72B6\u6001\u3002",(0,e.jsx)("br",{}),"\u9996\u6B21\u8FDB\u5165\u9700\u4E0B\u8F7D\u7EA6 ",y(n)," MB \u6E38\u620F\u8D44\u6E90\uFF08\u4EC5\u4E00\u6B21\uFF0C\u4E4B\u540E\u672C\u5730\u7F13\u5B58\uFF09\u3002"]}),c?(0,e.jsxs)("div",{style:{color:"#e06c75",fontSize:12,marginBottom:14},children:["\u4E0A\u6B21\u4E0B\u8F7D\u5931\u8D25\uFF1A",t.status.error??"\u672A\u77E5\u9519\u8BEF",(0,e.jsx)("br",{}),(0,e.jsx)("span",{style:{opacity:.7},children:"\u586B\u4EE3\u7406\u540E\u70B9\u91CD\u8BD5"})]}):null,l?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("div",{style:{background:"rgba(127,127,127,.2)",borderRadius:6,height:10,overflow:"hidden",marginBottom:10},children:(0,e.jsx)("div",{style:{height:"100%",width:`${s}%`,background:"#4a9eff",transition:"width .3s"}})}),(0,e.jsxs)("div",{style:{fontSize:12,opacity:.7},children:["\u4E0B\u8F7D\u4E2D... ",y(t.status.received)," / ",y(n)," MB\uFF08",s,"%\uFF09"]})]}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("input",{id:"hd2d-proxy",type:"text",value:t.proxy,onChange:f=>t.onProxyChange(f.currentTarget.value),placeholder:"HTTP \u4EE3\u7406\uFF08\u53EF\u9009\uFF0C\u5982 http://127.0.0.1:7890\uFF09",style:{width:"100%",boxSizing:"border-box",marginBottom:12,padding:"8px 10px",borderRadius:6,border:"1px solid rgba(127,127,127,.4)",background:"transparent",color:"inherit",fontSize:12}}),(0,e.jsx)("div",{style:{fontSize:11,opacity:.5,marginBottom:14,textAlign:"left"},children:"\u8FDE\u4E0D\u4E0A GitHub \u65F6\u586B\u4EE3\u7406\uFF08\u4EC5\u7528\u4E8E\u4E0B\u8F7D\u672C\u8D44\u6E90\uFF0C\u4F1A\u8BB0\u4F4F\uFF09\u3002\u7559\u7A7A\u8D70\u76F4\u8FDE/\u7CFB\u7EDF\u4EE3\u7406\u73AF\u5883\u53D8\u91CF\u3002"}),(0,e.jsxs)("button",{id:"hd2d-load",type:"button",disabled:t.starting,onClick:t.onStart,style:{cursor:t.starting?"default":"pointer",border:"none",borderRadius:8,padding:"10px 22px",fontSize:14,fontWeight:600,background:"#4a9eff",color:"#fff",opacity:t.starting?.7:1},children:[c?"\u91CD\u8BD5":"\u52A0\u8F7D\u529E\u516C\u5BA4","\uFF08\u7EA6 ",y(n)," MB\uFF09"]})]})]})}function T(t){let n={maxWidth:t.style.maxWidth,padding:t.style.padding,flex:t.style.flex,minHeight:t.style.minHeight,display:t.style.display};t.style.maxWidth="none",t.style.padding="0",t.style.flex="1 1 auto",t.style.minHeight="0",t.style.display="flex";let s=p(t,(0,e.jsx)(S,{}));return()=>{s(),t.style.maxWidth=n.maxWidth,t.style.padding=n.padding,t.style.flex=n.flex,t.style.minHeight=n.minHeight,t.style.display=n.display}}export{T as renderOfficePage};
@@ -0,0 +1 @@
1
+ import{a as _,b}from"./chunk-NASYW5FD.js";import"./chunk-76J7PNZI.js";import{o as y,p as N,r as I,s as L,t as S,u as M,v as w,x as u,y as m}from"./chunk-JXLHRRJD.js";import{a as j,b as C,c as D}from"./chunk-JTSE5VP6.js";import{c as k}from"./chunk-7SZRL6FY.js";var c=k(j(),1);var q={chats:[],bots:[]};async function B(){try{let t=await fetch("/api/groups");if(!t.ok)return;q=await t.json()}catch{}}var K=new Set(["working","analyzing","active","starting"]);function P(t){let a=new Map,l=s=>{let o=a.get(s);return o||(o={botName:s,larkAppId:s,cliId:"unknown",online:!1,sessions:[],active:[],busy:[],attention:[],lastActiveAt:0},a.set(s,o)),o};for(let s of q.bots??[]){let o=l(s.larkAppId??s.botName??"-");o.online=!0,s.botName&&(o.botName=s.botName),s.botAvatarUrl&&(o.botAvatarUrl=s.botAvatarUrl),s.cliId&&(o.cliId=s.cliId)}let r=[...t].sort((s,o)=>+(s.status==="closed")-+(o.status==="closed"));for(let s of r){let o=s.larkAppId??s.botName??"-";if(s.status==="closed"&&!a.has(o))continue;let i=l(o);s.botName&&(i.botName===i.larkAppId||!i.botName)&&(i.botName=s.botName),i.sessions.push(s),s.cliId&&i.cliId==="unknown"&&(i.cliId=s.cliId),i.lastActiveAt=Math.max(i.lastActiveAt,Number(s.lastMessageAt??0)),s.status!=="closed"&&(i.active.push(s),K.has(s.status)&&i.busy.push(s),u(s)&&i.attention.push(s))}for(let s of a.values())if(s.botName===s.larkAppId){let o=L(s.larkAppId);o&&(s.botName=o)}return[...a.values()].sort((s,o)=>{let i=d=>d.attention.length?0:d.busy.length?1:d.online||d.active.length?2:3;return i(s)!==i(o)?i(s)-i(o):o.lastActiveAt-s.lastActiveAt})}var e=k(D(),1),U=new Set(["working","analyzing","active","starting"]),X=new Set(["idle","dormant"]),O="botmux.overview.teamExpanded",F=230,z=13,E=2;function T(t){return(0,e.jsx)("span",{style:{display:"contents"},dangerouslySetInnerHTML:{__html:t.html}})}function J(){try{return window.localStorage.getItem(O)==="1"}catch{return!1}}function V(t){try{window.localStorage.setItem(O,t?"1":"0")}catch{}}function Q(t){return String(t??"unknown").toLowerCase().replace(/[^a-z0-9_-]/g,"-")}function Z(t,a){let l=String(t??"unknown"),r=`sessions.status.${l}`,s=a(r);return s===r?l:s}function ee(t){let a=t?.clientWidth??0;return a?Math.max(1,Math.floor((a+z)/(F+z)))*E:E*3}function te({card:t}){let a=b(),l=!t.online&&t.active.length===0,r=t.attention.length>0,s=t.busy.length>0,o=r?"warn":s?"busy":l?"off":"ok",i;if(r){let v=[...t.attention].sort((g,p)=>m(g)-m(p))[0];i=(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("b",{children:(w(v.title)||v.sessionId).slice(0,60)})," \xB7 ",u(v)??""]})}else if(s){let v=[...t.busy].sort((g,p)=>Number(p.lastMessageAt??0)-Number(g.lastMessageAt??0))[0];i=(0,e.jsx)("b",{children:(w(v.title)||v.sessionId).slice(0,60)})}else l?i=a("overview.botOffline"):i=a("overview.botIdle");let d=r?(0,e.jsx)("span",{className:"tag tag-warn",children:a("overview.botNeedsYou")}):s?(0,e.jsx)("span",{className:"tag tag-run",children:a("overview.botBusy",{count:t.busy.length})}):l?(0,e.jsx)("span",{className:"tag tag-off",children:a("overview.botOff")}):(0,e.jsx)("span",{className:"tag tag-ok",children:a("overview.botReady")});return(0,e.jsxs)("article",{className:`mate${r?" mate-attn":""}${l?" mate-off":""}`,children:[(0,e.jsxs)("div",{className:"mate-top",children:[(0,e.jsx)(T,{html:N({name:t.botName,larkAppId:t.larkAppId,avatarUrl:t.botAvatarUrl,dot:o})}),(0,e.jsxs)("div",{className:"mate-id",children:[(0,e.jsx)("b",{children:t.botName}),(0,e.jsx)("span",{className:"mate-role",children:t.cliId})]})]}),(0,e.jsx)("div",{className:"mate-task",children:i}),(0,e.jsxs)("div",{className:"mate-foot",children:[d,(0,e.jsx)("span",{children:t.lastActiveAt?a("overview.lastActive",{time:y(t.lastActiveAt)}):a("common.never")})]})]})}function se({session:t}){let a=b(),l=S(t);return(0,e.jsxs)("article",{className:"qcard","data-id":t.sessionId,children:[(0,e.jsx)(T,{html:N({name:l,larkAppId:t.larkAppId,size:"sm"})}),(0,e.jsxs)("div",{className:"qcard-tx",children:[(0,e.jsxs)("b",{children:[l," \xB7 ",(w(t.title)||t.sessionId).slice(0,56)]}),(0,e.jsxs)("span",{children:[u(t)??""," \xB7 ",y(m(t))]})]}),(0,e.jsx)("a",{className:"qcard-go",href:"#/sessions",children:a("strip.handle")})]})}function ne({session:t}){let a=b(),l=S(t),r=String(t.status??"unknown");return(0,e.jsxs)("li",{className:"sess-row",children:[(0,e.jsx)(T,{html:N({name:l,larkAppId:t.larkAppId,size:"sm"})}),(0,e.jsxs)("div",{className:"sess-tx",children:[(0,e.jsx)("b",{children:(w(t.title)||t.sessionId).slice(0,64)}),(0,e.jsxs)("span",{children:[l," \xB7 ",M(t)??t.cliId??"unknown"," \xB7 ",y(t.lastMessageAt)]})]}),(0,e.jsx)("span",{className:`status status-${Q(r)}`,children:Z(r,a)})]})}function ae({schedule:t}){let a=t.nextRunAt?new Date(t.nextRunAt).toLocaleString():"-";return(0,e.jsxs)("li",{className:"overview-list-row",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("strong",{children:t.name??t.id}),(0,e.jsxs)("span",{children:[S(t)," \xB7 ",t.parsed?.display??""]})]}),(0,e.jsx)("span",{children:a})]})}function ie({working:t,attention:a,idle:l}){let r=b(),s=t+a+l,o=s===0?"conic-gradient(var(--border) 0 360deg)":(()=>{let i=t/s*360,d=i+a/s*360;return`conic-gradient(var(--accent) 0 ${i}deg, var(--warning) ${i}deg ${d}deg, var(--success) ${d}deg 360deg)`})();return(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("div",{className:"donut-wrap",children:[(0,e.jsx)("div",{className:"donut",style:{background:o}}),(0,e.jsxs)("div",{className:"donut-center",children:[(0,e.jsx)("b",{children:s}),(0,e.jsx)("span",{children:r("overview.openSessions")})]})]}),(0,e.jsxs)("div",{className:"donut-legend",children:[(0,e.jsxs)("span",{children:[(0,e.jsx)("i",{style:{background:"var(--accent)"}}),r("overview.workingSessions")," ",t]}),(0,e.jsxs)("span",{children:[(0,e.jsx)("i",{style:{background:"var(--warning)"}}),r("overview.attention")," ",a]}),(0,e.jsxs)("span",{children:[(0,e.jsx)("i",{style:{background:"var(--success)"}}),r("sessions.board.idle")," ",l]})]})]})}function oe(){let t=b(),a=(0,c.useRef)(null),[l,r]=(0,c.useState)(J),[s,o]=(0,c.useState)(E*3),[i,d]=(0,c.useState)(0),{sessions:v,schedules:g}=_(n=>({sessions:[...n.sessions.values()],schedules:[...n.schedules.values()]}));(0,c.useEffect)(()=>{let n=()=>o(ee(a.current));return n(),window.addEventListener("resize",n),()=>window.removeEventListener("resize",n)},[]),(0,c.useEffect)(()=>{B().then(()=>d(n=>n+1)),I().then(()=>d(n=>n+1))},[]);let p=(0,c.useMemo)(()=>v.filter(n=>n.status!=="closed"),[v]),h=(0,c.useMemo)(()=>p.filter(n=>u(n)).sort((n,A)=>m(n)-m(A)),[p]),$=(0,c.useMemo)(()=>p.filter(n=>U.has(n.status)&&!u(n)),[p]),W=p.length-h.length-$.length,f=(0,c.useMemo)(()=>P(v),[v,i]),x=l?f:f.slice(0,s),Y=f.filter(n=>n.online||n.active.length>0).length,H=(0,c.useMemo)(()=>p.filter(n=>U.has(n.status)||X.has(n.status)).sort((n,A)=>Number(A.lastMessageAt??0)-Number(n.lastMessageAt??0)).slice(0,7),[p]),R=(0,c.useMemo)(()=>g.filter(n=>n.nextRunAt).sort((n,A)=>Date.parse(n.nextRunAt)-Date.parse(A.nextRunAt)).slice(0,5),[g]),G=()=>{r(n=>(V(!n),!n))};return(0,e.jsxs)("section",{className:"page hero-page",children:[(0,e.jsxs)("div",{className:"page-heading",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("p",{className:"eyebrow",children:t("app.subtitle")}),(0,e.jsx)("h1",{children:t("overview.title")}),(0,e.jsx)("p",{id:"overview-sub",children:t("overview.subtitle")})]}),(0,e.jsxs)("div",{className:"hero-pills",id:"overview-pills",children:[(0,e.jsxs)("span",{className:"pill",children:[t("overview.workingSessions")," ",(0,e.jsx)("b",{children:$.length})]}),(0,e.jsxs)("span",{className:`pill${h.length?" pill-hot":""}`,children:[t("overview.attention")," ",(0,e.jsx)("b",{children:h.length})]}),(0,e.jsxs)("span",{className:"pill",children:[t("overview.onlineBots")," ",(0,e.jsx)("b",{children:Y})]})]})]}),(0,e.jsxs)("div",{className:"sect-head",children:[(0,e.jsx)("h2",{children:t("overview.team")}),(0,e.jsx)("span",{children:t("overview.teamHint")}),(0,e.jsx)("a",{href:"#/bot-defaults",children:t("overview.viewAll")})]}),(0,e.jsx)("div",{className:"team-grid",id:"team-grid",ref:a,children:x.length?x.map(n=>(0,e.jsx)(te,{card:n},n.larkAppId??n.botName)):(0,e.jsx)("div",{className:"empty",children:t("overview.noSessions")})}),(0,e.jsx)("button",{type:"button",className:"team-toggle",id:"team-toggle",hidden:f.length<=s,onClick:G,children:l?t("overview.teamCollapse"):t("overview.teamExpand",{count:f.length})}),(0,e.jsxs)("div",{className:"sect-head",id:"attention-head",children:[(0,e.jsx)("h2",{children:t("overview.attention")}),(0,e.jsx)("span",{children:t("overview.attentionHint")})]}),(0,e.jsx)("div",{className:"qgrid",id:"attention-list",children:h.length?h.map(n=>(0,e.jsx)(se,{session:n},n.sessionId)):(0,e.jsx)("div",{className:"qcard qcard-empty",children:t("overview.noAttention")})}),(0,e.jsxs)("div",{className:"overview-cols",children:[(0,e.jsxs)("section",{className:"panel",children:[(0,e.jsxs)("header",{className:"panel-header",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("h2",{children:t("overview.activeSessions")}),(0,e.jsx)("p",{children:t("overview.activeSessionsHint")})]}),(0,e.jsx)("a",{className:"btn-link",href:"#/sessions",children:t("overview.viewAll")})]}),(0,e.jsx)("ul",{className:"overview-list",id:"recent-sessions",children:H.length?H.map(n=>(0,e.jsx)(ne,{session:n},n.sessionId)):(0,e.jsx)("li",{className:"empty",children:t("overview.noSessions")})})]}),(0,e.jsxs)("div",{className:"overview-side",children:[(0,e.jsxs)("section",{className:"panel",children:[(0,e.jsx)("header",{className:"panel-header",children:(0,e.jsxs)("div",{children:[(0,e.jsx)("h2",{children:t("overview.today")}),(0,e.jsx)("p",{children:t("overview.todayHint")})]})}),(0,e.jsx)("div",{className:"donut-row",id:"today-donut",children:(0,e.jsx)(ie,{working:$.length,attention:h.length,idle:Math.max(0,W)})})]}),(0,e.jsxs)("section",{className:"panel",children:[(0,e.jsxs)("header",{className:"panel-header",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("h2",{children:t("overview.nextSchedules")}),(0,e.jsx)("p",{children:t("schedules.subtitle")})]}),(0,e.jsx)("a",{className:"btn-link",href:"#/schedules",children:t("overview.viewAll")})]}),(0,e.jsx)("ul",{className:"overview-list",id:"next-schedules",children:R.length?R.map(n=>(0,e.jsx)(ae,{schedule:n},n.id)):(0,e.jsx)("li",{className:"empty",children:t("overview.noSchedules")})})]})]})]})]})}function be(t){return C(t,(0,e.jsx)(oe,{}))}export{be as renderOverviewPage};
@@ -0,0 +1,98 @@
1
+ import{a as le,b as se}from"./chunk-5E3MJJL4.js";import{b as ne}from"./chunk-NASYW5FD.js";import"./chunk-76J7PNZI.js";import{m as a,n as u,p as V,r as oe,w as O}from"./chunk-JXLHRRJD.js";import{a as Ie,b as F,c as re}from"./chunk-JTSE5VP6.js";import{c as D}from"./chunk-7SZRL6FY.js";var j=D(Ie(),1);var M=4096,be=/^[A-Za-z0-9._-]{1,64}$/,$=[],U=[],N=[],ue=[],Y=new Map,Z=new Map,Q=!1,_="groups",B=null,L=null,g="",R=new Set,y=null,E=null,w="",k=null,I=0,q=null;function m(e){return I===e}function z(e,t){let o=q,l=o?.generation??I,r=window.setTimeout(()=>{o?.timers.delete(r),m(l)&&e()},t);return o?.timers.add(r),r}function fe(e){return be.test(e)&&e!=="."&&e!==".."}function Ee(){let[,e=""]=location.hash.split("?");return new URLSearchParams(e).get("chatId")?.trim()||null}async function C(){let t=await(await fetch("/api/groups")).json();U=(t.bots??[]).map(o=>({larkAppId:o.larkAppId,botName:o.botName??o.larkAppId,botAvatarUrl:o.botAvatarUrl})),$=(t.chats??[]).map(o=>({chatId:o.chatId,name:o.name??o.chatId,memberBots:(o.memberBots??[]).map(l=>({larkAppId:l.larkAppId,botName:l.botName??l.larkAppId,inChat:l.inChat??!1,hasRole:l.hasRole??!1,oncallChat:l.oncallChat??null}))}))}async function G(){N=(await(await fetch("/api/role-profiles")).json()).profiles??[]}async function x(e){ue=(await(await fetch(`/api/role-profiles/${encodeURIComponent(e)}`)).json()).entries??[]}async function ee(e,t){return(await fetch(`/api/roles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).json()}function me(e,t){return`${e}\0${t}`}async function we(e=I){let t=await Promise.all(N.map(async r=>{try{let n=await(await fetch(`/api/role-profiles/${encodeURIComponent(r.profileId)}`)).json().catch(()=>({}));return[r.profileId,Array.isArray(n.entries)?n.entries:[]]}catch{return[r.profileId,[]]}}));if(!m(e))return!1;let o=new Map,l=new Set;return await Promise.all($.flatMap(r=>r.memberBots.filter(d=>d.inChat).map(async d=>{let n=me(d.larkAppId,r.chatId);if(!l.has(n)){l.add(n);try{let p=await ee(d.larkAppId,r.chatId),f=p.hasEffectiveRole??p.hasRole,v="effectiveContent"in p?p.effectiveContent:p.content;o.set(n,{content:f?String(v??""):null,source:p.effectiveSource??(p.hasRole?"chat":"none")})}catch{o.set(n,null)}}}))),m(e)?(Y=new Map(t),Z=o,!0):!1}async function T(e=I){try{if(!await we(e)||!m(e))return}catch{if(!m(e))return;Y=new Map,Z=new Map}Q=!0,P(document.getElementById("roles-search")?.value??"")}async function $e(e,t,o){return(await fetch(`/api/roles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({content:o})})).ok}async function Be(e,t){return(await fetch(`/api/roles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"DELETE"})).ok}async function Le(e,t){return(await fetch(`/api/role-profiles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).json()}async function Pe(e,t,o){return(await fetch(`/api/role-profiles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({content:o,allowEmpty:!0})})).ok}async function Te(e,t){return(await fetch(`/api/role-profiles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"DELETE"})).ok}function te(e){return new TextEncoder().encode(e).length}function ye(e){return e.memberBots.filter(t=>t.inChat&&t.hasRole).length}function ke(e){return e.memberBots.filter(t=>t.inChat).length}function J(e){return ue.find(t=>t.larkAppId===e)}function ie(e){_=e,document.getElementById("roles-by-group-view")?.toggleAttribute("hidden",e!=="groups"),document.getElementById("roles-profiles-view")?.toggleAttribute("hidden",e!=="profiles")}function Ce(e){if(!N.length||!Q)return"";let t=new Map;for(let r of e.memberBots)r.inChat&&t.set(r.larkAppId,Z.get(me(r.larkAppId,e.chatId))??null);if(!le(t))return"";let o=se(e.memberBots,N,Y,t)[0];if(!o)return`<div class="roles-profile-match muted">${a("groups.profileStatusUnmatched")}</div>`;let l=o.kind==="full"?"groups.profileStatusFullChat":"groups.profileStatusPartial";return`<div class="roles-profile-match ${o.kind}">
2
+ ${u(a(l,{name:o.profileId,matched:o.matched,total:o.total,chat:o.chatMatched}))}
3
+ </div>`}function P(e=""){let t=document.getElementById("roles-tree");if(!t)return;let o=e.toLowerCase(),l=$.filter(r=>{if(!o)return!0;let d=r.chatId.toLowerCase().includes(o)||(r.name??"").toLowerCase().includes(o),n=r.memberBots.some(p=>p.larkAppId.toLowerCase().includes(o)||(p.botName??"").toLowerCase().includes(o));return d||n});if(l.length===0){t.innerHTML=`<div class="roles-empty">${a("roles.noChats")}</div>`;return}t.innerHTML=l.map(r=>{let d=R.has(r.chatId),n=r.memberBots.filter(c=>c.inChat),p=d?"\u25BE":"\u25B8",f=ye(r),v=ke(r),i=d?n.map(c=>`
4
+ <div class="roles-bot-row ${B===r.chatId&&L===c.larkAppId?"selected":""}"
5
+ data-group-id="${u(r.chatId)}"
6
+ data-bot-id="${u(c.larkAppId)}">
7
+ <span class="roles-bot-indent"></span>
8
+ ${V({name:c.botName,larkAppId:c.larkAppId,size:"sm"})}
9
+ <div class="roles-bot-info">
10
+ <div class="roles-bot-name">${u(c.botName)}</div>
11
+ <div class="roles-bot-id">${u(c.larkAppId)}</div>
12
+ </div>
13
+ <span class="roles-badge ${c.hasRole?"has-role":"no-role"}">
14
+ ${c.hasRole?a("roles.configured"):a("roles.unconfigured")}
15
+ </span>
16
+ </div>`).join(""):"";return`
17
+ <div class="roles-group-section">
18
+ <div class="roles-group-row ${d?"expanded":""} ${B===r.chatId&&!L?"selected":""}"
19
+ data-group-id="${u(r.chatId)}">
20
+ <span class="roles-group-arrow">${p}</span>
21
+ <span class="roles-group-icon" aria-hidden="true"><svg viewBox="0 0 16 16"><circle cx="5.6" cy="5.8" r="2.4"/><path d="M1.8 13.2c.5-2.4 2-3.6 3.8-3.6s3.3 1.2 3.8 3.6"/><circle cx="11" cy="6.8" r="1.9"/><path d="M9.8 12.6c.4-1.7 1.5-2.6 2.8-2.6 1 0 1.9.5 2.4 1.6"/></svg></span>
22
+ <div class="roles-group-info">
23
+ <div class="roles-group-name">${u(r.name??r.chatId)}</div>
24
+ <div class="roles-group-meta">
25
+ ${f}/${v} ${a("roles.botsWithRoles")}
26
+ </div>
27
+ ${Ce(r)}
28
+ </div>
29
+ <span class="roles-group-chevron"></span>
30
+ </div>
31
+ <div class="roles-bot-list">${i}</div>
32
+ </div>`}).join(""),t.querySelectorAll(".roles-group-row").forEach(r=>{r.addEventListener("click",()=>{let d=r.dataset.groupId;d&&(R.has(d)?R.delete(d):R.add(d),P(document.getElementById("roles-search")?.value??""))})}),t.querySelectorAll(".roles-bot-row").forEach(r=>{r.addEventListener("click",d=>{d.stopPropagation();let n=r.dataset.groupId,p=r.dataset.botId;n&&p&&Re(n,p)})})}async function Re(e,t,o=I){B=e,L=t;let l=await ee(t,e);if(!m(o))return;let r=document.getElementById("roles-editor-empty"),d=document.getElementById("roles-editor-form"),n=document.getElementById("roles-editor-textarea"),p=document.getElementById("roles-editor-group-name"),f=document.getElementById("roles-editor-bot-name"),v=document.getElementById("roles-editor-chat-id");r&&(r.style.display="none"),d&&(d.style.display="");let i=$.find(b=>b.chatId===e),c=i?.memberBots.find(b=>b.larkAppId===t);p&&(p.textContent=i?.name??e),f&&(f.textContent=c?.botName??t),v&&(v.textContent=`${e} \xB7 ${t}`),g=l.content??"",n&&(n.value=g,n.focus()),W(),K(),P(document.getElementById("roles-search")?.value??"");let h=document.getElementById("roles-delete");h&&(h.style.display=l.hasRole?"":"none")}function W(){let e=document.getElementById("roles-editor-bytecount");if(!e)return;let t=te(g);e.textContent=`${t} / ${M} bytes`,e.className=`roles-bytecount ${t>3800?"warn":""} ${t>M?"over":""}`,Me(t)}function Me(e){let t=document.getElementById("roles-save");if(!t)return;let o=e??te(g);t.disabled=o>M||g.trim().length===0}function K(){let e=document.getElementById("roles-preview");e&&(g.trim()?e.innerHTML=`<strong>${a("roles.preview")}</strong><pre>${u(g)}</pre>`:e.innerHTML=`<small>${a("roles.previewEmpty")}</small>`)}function ae(){B=null,L=null,g="";let e=document.getElementById("roles-editor-empty"),t=document.getElementById("roles-editor-form"),o=document.getElementById("roles-editor-textarea"),l=document.getElementById("roles-delete");e&&(e.style.display=""),t&&(t.style.display="none"),o&&(o.value=""),l&&(l.style.display="none")}function A(e=""){let t=document.getElementById("roles-profile-list");if(!t)return;let o=e.toLowerCase(),l=N.filter(r=>!o||r.profileId.toLowerCase().includes(o));if(l.length===0){t.innerHTML=`<div class="roles-empty">${a("roles.profileEmpty")}</div>`;return}t.innerHTML=l.map(r=>{let d=y===r.profileId,n=(r.botEntries??[]).some(p=>p.hasEntry);return`
33
+ <div class="roles-profile-row ${d?"selected":""}" data-profile-id="${u(r.profileId)}">
34
+ <div class="roles-profile-row-main">
35
+ <div class="roles-profile-name">${u(r.profileId)}</div>
36
+ <div class="roles-group-meta">${r.entryCount} ${a("roles.profileEntries")}</div>
37
+ </div>
38
+ <span class="roles-badge ${n?"has-role":"no-role"}">${n?a("roles.configured"):a("roles.profileMissing")}</span>
39
+ </div>`}).join(""),t.querySelectorAll(".roles-profile-row").forEach(r=>{r.addEventListener("click",()=>{let d=r.dataset.profileId;d&&X(d)})})}async function X(e,t=I){fe(e.trim())&&(y=e.trim(),E=null,w="",k=k??$[0]?.chatId??null,await x(y),m(t)&&(A(document.getElementById("roles-profile-search")?.value??""),S()))}function S(){let e=document.getElementById("roles-profile-empty"),t=document.getElementById("roles-profile-detail");if(!e||!t)return;if(!y){e.style.display="",t.style.display="none",t.innerHTML="";return}e.style.display="none",t.style.display="";let o=U.find(r=>r.larkAppId===E),l=E?J(E):void 0;t.innerHTML=`
40
+ <div class="roles-profile-title">
41
+ <div>
42
+ <div class="roles-editor-breadcrumb">
43
+ <span>${u(y)}</span>
44
+ ${o?`<span class="roles-breadcrumb-sep">\u203A</span><span>${u(o.botName??o.larkAppId)}</span>`:""}
45
+ </div>
46
+ <div class="roles-editor-meta-line">${a("roles.profileRuntimeHint")}</div>
47
+ </div>
48
+ </div>
49
+ <div class="roles-profile-grid">
50
+ <div class="roles-profile-bots">
51
+ <div class="roles-profile-section-title">${a("roles.profileBots")}</div>
52
+ <div class="roles-profile-bot-list">
53
+ ${U.map(r=>{let d=!!J(r.larkAppId);return`
54
+ <div class="roles-bot-row roles-profile-bot-row ${E===r.larkAppId?"selected":""}" data-profile-bot-id="${u(r.larkAppId)}">
55
+ ${V({name:r.botName,larkAppId:r.larkAppId,size:"sm"})}
56
+ <div class="roles-bot-info">
57
+ <div class="roles-bot-name">${u(r.botName??r.larkAppId)}</div>
58
+ <div class="roles-bot-id">${u(r.larkAppId)}</div>
59
+ </div>
60
+ <span class="roles-badge ${d?"has-role":"no-role"}">${d?a("roles.configured"):a("roles.unconfigured")}</span>
61
+ </div>`}).join("")}
62
+ </div>
63
+ </div>
64
+ <div class="roles-profile-editor">
65
+ ${E?`
66
+ <textarea id="roles-profile-textarea" placeholder="${a("roles.profileEditorPlaceholder")}" rows="12">${u(w||l?.content||"")}</textarea>
67
+ <div class="roles-editor-footer">
68
+ <span id="roles-profile-bytecount" class="roles-bytecount"></span>
69
+ <div class="roles-editor-actions">
70
+ <button type="button" id="roles-profile-delete" class="danger" ${l?"":'style="display:none"'}>${a("roles.delete")}</button>
71
+ <button type="button" id="roles-profile-save" class="primary">${a("roles.saveEntry")}</button>
72
+ </div>
73
+ </div>
74
+ <div id="roles-profile-preview" class="roles-preview"></div>
75
+ `:`<div class="roles-editor-empty roles-profile-inline-empty">${a("roles.profileBotSelectHint")}</div>`}
76
+ </div>
77
+ </div>
78
+ <div class="roles-profile-apply">
79
+ <div class="roles-profile-section-title">${a("roles.applyToGroup")}</div>
80
+ <div class="roles-profile-apply-controls">
81
+ <select id="roles-profile-apply-group">
82
+ ${$.map(r=>`<option value="${u(r.chatId)}" ${k===r.chatId?"selected":""}>${u(r.name??r.chatId)}</option>`).join("")}
83
+ </select>
84
+ <label class="roles-profile-force"><input type="checkbox" id="roles-profile-apply-force"> ${a("roles.applyForce")}</label>
85
+ </div>
86
+ <div id="roles-profile-apply-bots"></div>
87
+ <div class="roles-editor-actions">
88
+ <button type="button" id="roles-profile-preview-apply">${a("roles.previewApply")}</button>
89
+ <button type="button" id="roles-profile-apply" class="primary">${a("roles.applyProfile")}</button>
90
+ </div>
91
+ <div id="roles-profile-apply-status" class="roles-profile-status"></div>
92
+ </div>
93
+ `,t.querySelectorAll(".roles-profile-bot-row").forEach(r=>{r.addEventListener("click",()=>{let d=r.dataset.profileBotId;d&&Ae(d)})}),ve(),He()}async function Ae(e,t=I){if(!y)return;E=e;let o=await Le(y,e);m(t)&&(w=o.content??"",await x(y),m(t)&&S())}function He(){let e=I,t=document.getElementById("roles-profile-textarea");t&&(w=t.value,de(),ce(),t.addEventListener("input",o=>{w=o.target.value,de(),ce()})),document.getElementById("roles-profile-save")?.addEventListener("click",async function(){if(!(!y||!E)){this.disabled=!0,this.textContent="...";try{let o=await Pe(y,E,w);if(!m(e)||(await G(),!m(e))||(await x(y),!m(e)))return;A(document.getElementById("roles-profile-search")?.value??""),T(e),S(),Ne(o?a("roles.saved"):a("roles.saveFailed"),!o)}finally{if(!m(e))return;this.disabled=!1,this.textContent=a("roles.saveEntry")}}}),document.getElementById("roles-profile-delete")?.addEventListener("click",async function(){if(!(!y||!E)&&confirm(a("roles.confirmDeleteProfileEntry"))){this.disabled=!0;try{if(await Te(y,E),!m(e)||(w="",await G(),!m(e))||(await x(y),!m(e)))return;A(document.getElementById("roles-profile-search")?.value??""),T(e),S()}finally{if(!m(e))return;this.disabled=!1}}}),document.getElementById("roles-profile-apply-group")?.addEventListener("change",o=>{k=o.target.value,ve()}),document.getElementById("roles-profile-preview-apply")?.addEventListener("click",()=>pe(!0,e)),document.getElementById("roles-profile-apply")?.addEventListener("click",()=>pe(!1,e))}function de(){let e=document.getElementById("roles-profile-bytecount"),t=document.getElementById("roles-profile-save");if(!e)return;let o=te(w);e.textContent=`${o} / ${M} bytes`,e.className=`roles-bytecount ${o>3800?"warn":""} ${o>M?"over":""}`,t&&(t.disabled=o>M||w.trim().length===0)}function ce(){let e=document.getElementById("roles-profile-preview");e&&(e.innerHTML=w.trim()?`<strong>${a("roles.preview")}</strong><pre>${u(w)}</pre>`:`<small>${a("roles.previewEmpty")}</small>`)}function ve(){let e=document.getElementById("roles-profile-apply-bots");if(!e)return;let t=k??$[0]?.chatId??"",o=$.find(r=>r.chatId===t),l=o?.memberBots.filter(r=>r.inChat)??[];if(!o||l.length===0){e.innerHTML=`<div class="roles-empty">${a("roles.noChats")}</div>`;return}e.innerHTML=l.map(r=>{let d=!!J(r.larkAppId);return`
94
+ <label class="checkbox-row roles-profile-apply-bot">
95
+ <input type="checkbox" name="profile-apply-bot" value="${u(r.larkAppId)}" ${d?"checked":""}>
96
+ <span>${u(r.botName??r.larkAppId)}</span>
97
+ <small>${d?a("roles.configured"):a("roles.profileMissing")}</small>
98
+ </label>`}).join("")}async function pe(e,t=I){let o=y;if(!o)return;let l=k??$[0]?.chatId;if(!l)return;let r=document.getElementById("roles-profile-apply-force")?.checked===!0,d=[...document.querySelectorAll("input[name=profile-apply-bot]:checked")].map(f=>f.value),n=document.getElementById("roles-profile-apply-status");if(d.length===0){n&&(n.textContent=a("roles.applyPickBots"));return}n&&(n.textContent="...");let p=await Promise.all(d.map(async f=>{let v=await fetch(`/api/role-profiles/${encodeURIComponent(o)}/apply`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({chatId:l,larkAppId:f,force:r,preview:e})}),i=await v.json().catch(()=>({}));return{larkAppId:f,ok:v.ok&&i.ok!==!1,status:v.status,error:i.error,wouldRefuse:i.wouldRefuse}}));if(m(t)&&(n&&(n.innerHTML=p.map(f=>{let v=U.find(h=>h.larkAppId===f.larkAppId),i=u(v?.botName??f.larkAppId),c=f.ok?e?f.wouldRefuse?a("roles.applyWouldRefuse"):a("roles.applyPreviewOk"):a("roles.applyOk"):`${a("roles.applyFailed")}: ${u(f.error??`HTTP ${f.status}`)}`;return`<div>${i}: ${c}</div>`}).join("")),!e)){if(await C(),!m(t))return;P(document.getElementById("roles-search")?.value??""),T(t)}}function Ne(e,t=!1){let o=document.querySelector("#roles-profile-detail .roles-editor-footer");if(!o)return;let l=document.createElement("span");l.className=`roles-saved-flash ${t?"roles-save-error":""}`,l.textContent=` ${e}`,o.appendChild(l),z(()=>l.remove(),t?3e3:2e3)}function he(e,t){let o=I+1;I=o;let l=new Set;q={generation:o,timers:l};let r=[],d=!1,n=()=>!d&&m(o),p=(i,c,h)=>{i&&(i.addEventListener(c,h),r.push(()=>i.removeEventListener(c,h)))};_=t,R.clear(),Q=!1,ae(),ie(_);let f=e.querySelector("#roles-tree"),v=e.querySelector("#roles-profile-list");return f&&(f.innerHTML=O()),v&&(v.innerHTML=O()),(async()=>{if(await C(),!!n()&&(await G(),!!n()&&(await oe(),!!n()))){if(t==="profiles"){let i=Ee();i&&$.some(c=>c.chatId===i)&&(k=i)}for(let i of $)ye(i)>0&&R.add(i.chatId);P(),A(),y&&await X(y,o),n()&&T(o)}})(),p(e.querySelector("#roles-search"),"input",i=>{n()&&P(i.target.value)}),p(e.querySelector("#roles-refresh"),"click",async()=>{if(n()&&(await C(),!!n()&&(P(document.getElementById("roles-search")?.value??""),T(o),B&&L))){let i=await ee(L,B);if(!n())return;let c=document.getElementById("roles-editor-textarea");c&&(c.value=i.content??""),g=i.content??"",W(),K();let h=document.getElementById("roles-delete");h&&(h.style.display=i.hasRole?"":"none")}}),p(e.querySelector("#roles-save"),"click",async i=>{if(!B||!L)return;let c=i.currentTarget;c.disabled=!0,c.textContent="...";try{let h=await $e(L,B,g);if(!n())return;if(h){if(await C(),!n())return;P(document.getElementById("roles-search")?.value??""),T(o);let b=document.getElementById("roles-delete");b&&(b.style.display="");let H=document.createElement("span");H.className="roles-saved-flash",H.textContent=` ${a("roles.saved")}`,document.querySelector(".roles-editor-footer")?.appendChild(H),z(()=>H.remove(),2e3)}else{let b=document.createElement("span");b.className="roles-saved-flash roles-save-error",b.textContent=g.trim().length===0?` ${a("roles.emptyError")}`:` ${a("roles.saveFailed")}`,document.querySelector(".roles-editor-footer")?.appendChild(b),z(()=>b.remove(),3e3)}}finally{if(!n())return;c.disabled=!1,c.textContent=a("roles.save")}}),p(e.querySelector("#roles-delete"),"click",async i=>{if(!B||!L||!confirm(a("roles.confirmDelete")))return;let c=i.currentTarget;c.disabled=!0,c.textContent="...";try{let h=await Be(L,B);if(!n())return;if(h){if(await C(),!n())return;ae(),P(document.getElementById("roles-search")?.value??""),T(o)}}finally{if(!n())return;c.disabled=!1,c.textContent=a("roles.delete")}}),p(e.querySelector("#roles-editor-textarea"),"input",i=>{n()&&(g=i.target.value,W(),K())}),p(e.querySelector("#roles-profile-search"),"input",i=>{n()&&A(i.target.value)}),p(e.querySelector("#roles-profile-refresh"),"click",async()=>{n()&&(await C(),n()&&(await G(),n()&&(T(o),y&&await x(y),n()&&(A(document.getElementById("roles-profile-search")?.value??""),S()))))}),p(e.querySelector("#roles-profile-select"),"click",async()=>{if(!n())return;let i=document.getElementById("roles-profile-id"),c=i?.value.trim();if(c){if(!fe(c)){i?.setCustomValidity(a("roles.profileIdInvalid")),i?.reportValidity();return}i?.setCustomValidity(""),await X(c,o),n()&&(location.hash.startsWith("#/roles/profile")?ie("profiles"):location.hash="#/roles/profile")}}),p(e.querySelector("#roles-profile-id"),"input",i=>{i.target.setCustomValidity("")}),()=>{d=!0,m(o)&&(I+=1);for(let i of r.splice(0))i();for(let i of l)window.clearTimeout(i);l.clear(),q?.generation===o&&(q=null)}}var s=D(re(),1);function ge(e){let t=ne(),o=(0,j.useRef)(null),l=e.tab==="profiles";return(0,j.useEffect)(()=>{if(o.current)return he(o.current,e.tab)},[e.tab]),(0,s.jsxs)("section",{className:"page roles-page",ref:o,children:[(0,s.jsx)("div",{className:"page-heading roles-heading",children:(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"eyebrow",children:t("nav.roles")}),(0,s.jsx)("h1",{children:t("roles.title")}),(0,s.jsx)("p",{children:t("roles.subtitle")})]})}),(0,s.jsxs)("nav",{className:"wf-subnav roles-subnav",children:[(0,s.jsx)("a",{href:"#/roles",className:l?void 0:"active",children:t("roles.tabGroups")}),(0,s.jsx)("a",{href:"#/roles/profile",className:l?"active":void 0,children:t("roles.tabProfiles")})]}),(0,s.jsxs)("div",{id:"roles-by-group-view",className:"roles-layout",hidden:l,children:[(0,s.jsxs)("div",{className:"roles-tree-panel",children:[(0,s.jsxs)("div",{className:"roles-tree-header",children:[(0,s.jsx)("input",{type:"search",id:"roles-search",placeholder:t("roles.search")}),(0,s.jsx)("button",{type:"button",id:"roles-refresh",children:t("roles.refresh")})]}),(0,s.jsx)("div",{id:"roles-tree",className:"roles-tree"})]}),(0,s.jsxs)("div",{className:"roles-editor-panel",children:[(0,s.jsx)("div",{id:"roles-editor-empty",className:"roles-editor-empty",children:t("roles.selectHint")}),(0,s.jsxs)("div",{id:"roles-editor-form",className:"roles-editor-form",style:{display:"none"},children:[(0,s.jsxs)("div",{className:"roles-editor-breadcrumb",children:[(0,s.jsx)("span",{id:"roles-editor-group-name"}),(0,s.jsx)("span",{className:"roles-breadcrumb-sep",children:"\u203A"}),(0,s.jsx)("span",{id:"roles-editor-bot-name"})]}),(0,s.jsx)("div",{className:"roles-editor-meta",children:(0,s.jsx)("span",{id:"roles-editor-chat-id",className:"roles-editor-meta-line"})}),(0,s.jsx)("textarea",{id:"roles-editor-textarea",placeholder:t("roles.editorPlaceholder"),rows:14}),(0,s.jsxs)("div",{className:"roles-editor-footer",children:[(0,s.jsx)("span",{id:"roles-editor-bytecount",className:"roles-bytecount"}),(0,s.jsxs)("div",{className:"roles-editor-actions",children:[(0,s.jsx)("button",{type:"button",id:"roles-delete",className:"danger",children:t("roles.delete")}),(0,s.jsx)("button",{type:"button",id:"roles-save",className:"primary",children:t("roles.save")})]})]}),(0,s.jsx)("div",{id:"roles-preview",className:"roles-preview"})]})]})]}),(0,s.jsxs)("div",{id:"roles-profiles-view",className:"roles-layout roles-profiles-layout",hidden:!l,children:[(0,s.jsxs)("div",{className:"roles-tree-panel",children:[(0,s.jsxs)("div",{className:"roles-tree-header roles-profile-create",children:[(0,s.jsx)("input",{type:"text",id:"roles-profile-id",placeholder:t("roles.profileIdPlaceholder"),maxLength:64}),(0,s.jsx)("button",{type:"button",id:"roles-profile-select",children:t("roles.openProfile")})]}),(0,s.jsxs)("div",{className:"roles-tree-header",children:[(0,s.jsx)("input",{type:"search",id:"roles-profile-search",placeholder:t("roles.profileSearch")}),(0,s.jsx)("button",{type:"button",id:"roles-profile-refresh",children:t("roles.refresh")})]}),(0,s.jsx)("div",{id:"roles-profile-list",className:"roles-tree"})]}),(0,s.jsxs)("div",{className:"roles-editor-panel",children:[(0,s.jsx)("div",{id:"roles-profile-empty",className:"roles-editor-empty",children:t("roles.profileSelectHint")}),(0,s.jsx)("div",{id:"roles-profile-detail",className:"roles-editor-form roles-profile-detail",style:{display:"none"}})]})]})]})}function Ve(e){return F(e,(0,s.jsx)(ge,{tab:"groups"}))}function Oe(e){return F(e,(0,s.jsx)(ge,{tab:"profiles"}))}export{Oe as renderRoleProfilesPage,Ve as renderRolesPage};
@@ -0,0 +1 @@
1
+ import{a as k,b as w}from"./chunk-NASYW5FD.js";import"./chunk-76J7PNZI.js";import"./chunk-JXLHRRJD.js";import{a as R,b as f,c as S}from"./chunk-JTSE5VP6.js";import{c as b}from"./chunk-7SZRL6FY.js";var c=b(R(),1);var e=b(S(),1);function y(t){if(!t)return"\u2014";try{return new Date(t).toLocaleString()}catch{return t}}function N(t,a){let i=a.q.toLowerCase();return t.filter(d=>!a.kind||d.parsed?.kind===a.kind).filter(d=>!a.enabledOnly||d.enabled).filter(d=>!i||JSON.stringify(d).toLowerCase().includes(i)).sort((d,r)=>{if(d.enabled!==r.enabled)return d.enabled?-1:1;let u=d.nextRunAt?Date.parse(d.nextRunAt):1/0,n=r.nextRunAt?Date.parse(r.nextRunAt):1/0;return u-n})}function x(t,a){return t.deliver==="new-topic"?`\u{1F195} ${a("schedules.deliveryNewTopic")}`:t.deliver==="local"?`\u{1F515} ${a("schedules.deliveryLocal")}`:a("schedules.deliveryOrigin")}function $(t){return t.repeat?`${t.repeat.completed}/${t.repeat.times??"\u221E"}`:"\u2014"}function C(){let t=w(),a=k(l=>[...l.schedules.values()]),[i,d]=(0,c.useState)({q:"",kind:"",enabledOnly:!1}),[r,u]=(0,c.useState)(null),n={name:t("schedules.name"),bot:t("schedules.bot"),schedule:t("schedules.schedule"),delivery:t("schedules.delivery"),next:t("schedules.next"),last:t("schedules.last"),repeat:t("schedules.repeat"),enabled:t("schedules.enabled"),actions:t("schedules.actions")},m=(0,c.useMemo)(()=>N(a,i),[a,i]);async function h(l,o){let g=`${l}:${o}`;u(g);try{let s=await fetch(`/api/schedules/${encodeURIComponent(l)}/${o}`,{method:"POST"}),v=await s.json().catch(()=>({}));(!s.ok||v.ok===!1)&&alert(`Failed: ${s.status} ${v?.error??""}`.trim())}catch(s){alert("Network error: "+s)}finally{u(s=>s===g?null:s)}}return(0,e.jsxs)("section",{className:"page schedules-page",children:[(0,e.jsx)("div",{className:"page-heading",children:(0,e.jsxs)("div",{children:[(0,e.jsx)("p",{className:"eyebrow",children:t("nav.schedules")}),(0,e.jsx)("h1",{children:t("schedules.title")}),(0,e.jsx)("p",{children:t("schedules.subtitle")})]})}),(0,e.jsxs)("form",{id:"sched-filters",className:"filters",children:[(0,e.jsx)("input",{type:"search",name:"q",placeholder:t("schedules.search"),value:i.q,onChange:l=>d(o=>({...o,q:l.currentTarget.value}))}),(0,e.jsxs)("select",{name:"kind",value:i.kind,onChange:l=>d(o=>({...o,kind:l.currentTarget.value})),children:[(0,e.jsx)("option",{value:"",children:t("schedules.anyKind")}),(0,e.jsx)("option",{value:"cron",children:"cron"}),(0,e.jsx)("option",{value:"interval",children:"interval"}),(0,e.jsx)("option",{value:"once",children:"once"})]}),(0,e.jsxs)("label",{children:[(0,e.jsx)("input",{type:"checkbox",name:"enabled",checked:i.enabledOnly,onChange:l=>d(o=>({...o,enabledOnly:l.currentTarget.checked}))})," ",t("schedules.enabledOnly")]})]}),(0,e.jsxs)("table",{className:"schedules-table",children:[(0,e.jsx)("thead",{children:(0,e.jsxs)("tr",{children:[(0,e.jsx)("th",{children:n.name}),(0,e.jsx)("th",{children:n.bot}),(0,e.jsx)("th",{children:n.schedule}),(0,e.jsx)("th",{children:n.delivery}),(0,e.jsx)("th",{children:n.next}),(0,e.jsx)("th",{children:n.last}),(0,e.jsx)("th",{children:n.repeat}),(0,e.jsx)("th",{children:n.enabled}),(0,e.jsx)("th",{children:n.actions})]})}),(0,e.jsx)("tbody",{id:"schedules-tbody",children:m.length===0?(0,e.jsx)("tr",{className:"schedule-empty-row",children:(0,e.jsx)("td",{colSpan:9,className:"empty",children:t("schedules.empty")})}):m.map(l=>(0,e.jsxs)("tr",{"data-id":l.id,children:[(0,e.jsx)("td",{"data-label":n.name,children:l.name??l.id}),(0,e.jsx)("td",{"data-label":n.bot,children:l.botName??l.larkAppId??"-"}),(0,e.jsx)("td",{"data-label":n.schedule,children:(0,e.jsx)("code",{children:l.parsed?.display??"?"})}),(0,e.jsx)("td",{"data-label":n.delivery,children:x(l,t)}),(0,e.jsx)("td",{"data-label":n.next,children:y(l.nextRunAt)}),(0,e.jsxs)("td",{"data-label":n.last,children:[y(l.lastRunAt)," ",l.lastStatus==="error"?"\u26A0\uFE0F":""]}),(0,e.jsx)("td",{"data-label":n.repeat,children:$(l)}),(0,e.jsx)("td",{"data-label":n.enabled,children:l.enabled?"\u2713":"\u2717"}),(0,e.jsx)("td",{className:"actions-cell","data-label":n.actions,children:(0,e.jsxs)("div",{className:"schedule-actions",children:[(0,e.jsx)(p,{op:"run",label:t("schedules.runNow"),pending:r===`${l.id}:run`,onClick:()=>{h(l.id,"run")}}),l.enabled?(0,e.jsx)(p,{op:"pause",label:t("schedules.pause"),pending:r===`${l.id}:pause`,onClick:()=>{h(l.id,"pause")}}):(0,e.jsx)(p,{op:"resume",label:t("schedules.resume"),pending:r===`${l.id}:resume`,onClick:()=>{h(l.id,"resume")}}),l.deliver==="local"?null:(0,e.jsx)(p,{op:"delivery",label:l.deliver==="new-topic"?t("schedules.useOrigin"):t("schedules.useNewTopic"),pending:r===`${l.id}:delivery`,onClick:()=>{h(l.id,"delivery")}})]})})]},l.id))})]})]})}function p(t){return(0,e.jsx)("button",{type:"button","data-op":t.op,disabled:t.pending,onClick:t.onClick,children:t.pending?"...":t.label})}function A(t){return f(t,(0,e.jsx)(C,{}))}export{N as filterSchedules,y as fmtScheduleDate,A as renderSchedulesPage};
@@ -0,0 +1,238 @@
1
+ import{b as Ut}from"./chunk-NASYW5FD.js";import{a as O}from"./chunk-76J7PNZI.js";import{b as Nt,c as Bt,d as Pt,e as Qe,f as Rt,g as et,h as qt,i as Dt,l as we,m as i,n as l,o as ue,p as ae,q as Ot,r as Kt,t as F,u as pe,v as j,y as Pe}from"./chunk-JXLHRRJD.js";import{a as xn,b as _t,c as jt}from"./chunk-JTSE5VP6.js";import{c as Ze}from"./chunk-7SZRL6FY.js";var De=Ze(xn(),1);var Re=[24,72,168],Nn=new Set(Re);function tt(o){let u=o==="7d"?168:Number(o);return!Number.isFinite(u)||!Nn.has(u)?null:u}function Bn(o){let u=Number(o);return Number.isFinite(u)&&u>0?u:null}function Pn(o,u=Date.now()){return u-o*60*60*1e3}function Rn(o,u,b=Date.now()){if(!o.sessionId||o.status!=="idle"||o.locked||o.pendingRepo||o.tuiPromptActive||o.agentAttention)return!1;let f=Bn(o.lastMessageAt);return f!==null&&f<Pn(u,b)}function Ft(o,u,b=Date.now()){return o.filter(f=>Rn(f,u,b))}var zt=["backlog","todo","in_progress","in_review","done"];function Wt(o){return typeof o=="string"&&zt.includes(o)?o:null}function Vt(o){if(o.status==="closed")return"done";let u=Wt(o.kanbanColumn);return u||(o.pendingRepo||o.tuiPromptActive||o.agentAttention||o.status==="limited"?"in_review":o.status==="starting"||o.status==="working"||o.status==="analyzing"||o.status==="active"?"in_progress":"todo")}var qn=1e15;function oe(o){if(typeof o.kanbanPosition=="number"&&Number.isFinite(o.kanbanPosition))return o.kanbanPosition;let u=typeof o.lastMessageAt=="number"&&Number.isFinite(o.lastMessageAt)?o.lastMessageAt:0;return qn-u}function nt(o,u){return o!==null&&u!==null?(o+u)/2:o!==null?o+1024:u!==null?u-1024:1024}function it(o){return typeof o=="number"&&Number.isFinite(o)?o:null}function Gt(o){let u=it(o);return u===null?"-":u.toLocaleString("en-US")}var en=["claude-code","seed","relay","codex","codex-app","cursor","gemini","opencode","mtr","hermes","mira","pi","copilot","aiden","coco","oh-my-pi","unknown"],Jt=[{id:"needs-you",labelKey:"sessions.board.needsYou",hintKey:"sessions.board.needsYouHint"},{id:"starting",labelKey:"sessions.board.starting",hintKey:"sessions.board.startingHint"},{id:"working",labelKey:"sessions.board.working",hintKey:"sessions.board.workingHint"},{id:"idle",labelKey:"sessions.board.idle",hintKey:"sessions.board.idleHint"}],Yt=[{id:"backlog",labelKey:"sessions.kanban.backlog"},{id:"todo",labelKey:"sessions.kanban.todo"},{id:"in_progress",labelKey:"sessions.kanban.inProgress"},{id:"in_review",labelKey:"sessions.kanban.inReview"},{id:"done",labelKey:"sessions.kanban.done"}],st=50;function Dn(o){let u=(b="")=>`<svg viewBox="0 0 14 14" aria-hidden="true"><circle cx="7" cy="7" r="5.4" fill="none" stroke="currentColor" stroke-width="1.6"${b}/>`;switch(o){case"backlog":return`${u(' stroke-dasharray="1.6 2.1"')}</svg>`;case"in_progress":return`${u()}<path d="M7,7 L7,3.6 A3.4,3.4 0 0 1 7,10.4 Z" fill="currentColor"/></svg>`;case"in_review":return`${u()}<path d="M7,7 L7,3.6 A3.4,3.4 0 1 1 3.6,7 Z" fill="currentColor"/></svg>`;case"done":return'<svg viewBox="0 0 14 14" aria-hidden="true"><circle cx="7" cy="7" r="6.2" fill="currentColor"/><path d="M4.4 7.2 6.2 9 9.7 5.4" fill="none" stroke="var(--surface)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>';default:return`${u()}</svg>`}}function qe(o){return String(o??"unknown").toLowerCase().replace(/[^a-z0-9_-]/g,"-")}var tn=["starting","working","idle","dormant","analyzing","active","limited","closed"];function Me(o){let u=String(o??"unknown"),b=`sessions.status.${u}`,f=i(b);return f===b?u:f}function Se(o){let u=String(o??"unknown");return`<span class="status status-${l(qe(u))}">${l(Me(u))}</span>`}function Xt(o){let u=String(o??"").trim();return u?u.replace(/\\/g,"/").split("/").filter(Boolean).at(-1)??u:"-"}function at(o){if(!o.webPort)return null;if(location.protocol==="https:")return o.proxyPort?`${location.origin}/s/${encodeURIComponent(o.sessionId)}`:null;let u=o.proxyPort??o.webPort,b=o.proxyPort?`/s/${encodeURIComponent(o.sessionId)}`:"";return`http://${location.hostname}:${u}${b}`}var C={pin:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 14.3s4.2-3.9 4.2-7.3A4.2 4.2 0 0 0 8 2.9a4.2 4.2 0 0 0-4.2 4.1C3.8 10.4 8 14.3 8 14.3z"/><circle cx="8" cy="6.9" r="1.5"/></svg>',openChat:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M9.4 2.8h3.8v3.8"/><path d="M13.2 2.8 7.3 8.7"/><path d="M11.5 9.3v2.9a1.2 1.2 0 0 1-1.2 1.2H3.8a1.2 1.2 0 0 1-1.2-1.2V5.7a1.2 1.2 0 0 1 1.2-1.2h2.9"/></svg>',details:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2.2" y="2.9" width="11.6" height="10.2" rx="1.8"/><path d="M9.9 2.9v10.2"/></svg>',terminal:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="1.7" y="2.7" width="12.6" height="10.6" rx="2"/><path d="M4.4 6.3 6.4 8.1 4.4 9.9"/><path d="M8.2 10.2h3.4"/></svg>',key:'<svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="6" cy="6.1" r="3"/><path d="M8.1 8.2 13 13.1"/><path d="M11.3 11.4 12.6 10.1"/><path d="M12.7 12.8 13.7 11.8"/></svg>',lock:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="3.2" y="7" width="9.6" height="6.2" rx="1.4"/><path d="M5.2 7V5.2a2.8 2.8 0 0 1 5.6 0V7"/></svg>',unlock:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="3.2" y="7" width="9.6" height="6.2" rx="1.4"/><path d="M5.2 7V5.2a2.8 2.8 0 0 1 5.2-1.4"/></svg>',close:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4.2 4.2 11.8 11.8"/><path d="M11.8 4.2 4.2 11.8"/></svg>',edit:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M10.7 3.3 12.7 5.3 6.3 11.7 3.7 12.3 4.3 9.7 10.7 3.3z"/></svg>',history:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M2.2 4.8a2 2 0 0 1 2-2h7.6a2 2 0 0 1 2 2v4.6a2 2 0 0 1-2 2H6.6l-2.9 2.4v-2.4h-.5a2 2 0 0 1-2-2z"/><path d="M5.2 6.2h5.6M5.2 8.4h3.6"/></svg>',restart:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M12.4 6.2a4.8 4.8 0 1 0 1.1 3.1"/><path d="M12.4 2.9v3.3H9.1"/></svg>',feishu:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M2.6 4.4C6.4 4 10.4 5.4 13.4 8.2 9.8 7 6.4 6.6 3.4 7.4"/><path d="M13.4 8.2C9.6 8.7 6 10 2.9 12 5.6 9 8.8 7.6 13.4 8.2"/></svg>'};function Te(o,u,b,f=""){return`<button type="button" class="card-act${f?" "+f:""}" data-action="${o}" title="${l(b)}" aria-label="${l(b)}">${u}</button>`}function Le(o){return o.locked?i("sessions.unlock"):i("sessions.lock")}function Ce(o){return o.locked?`<span class="session-lock-badge" title="${l(i("sessions.locked"))}">${l(i("sessions.locked"))}</span>`:""}function Zt(o){if(!o)return"";let u=`<a class="term-btn term-open" href="${l(o)}" target="_blank" rel="noopener" title="${l(i("sessions.openTerminal"))}" aria-label="${l(i("sessions.openTerminal"))}">${C.terminal}</a>`;if(!we.authed)return`<span class="term-pill solo">${u}</span>`;let b=`<button type="button" class="term-btn term-write" data-action="write-link" title="${l(i("sessions.writeLinkHint"))}" aria-label="${l(i("sessions.writeLink"))}">${C.key}</button>`;return`<span class="term-pill">${u}${b}</span>`}async function Qt(o,u){let b=window.open("about:blank","_blank");b&&(b.opener=null),u&&(u.disabled=!0);try{let f=await fetch(`/api/sessions/${encodeURIComponent(o.sessionId)}/write-link`),v=await f.json().catch(()=>({}));if(!f.ok||v?.ok===!1||!v?.url){b?.close(),f.status!==401&&alert(`${i("sessions.writeLinkFail")}: ${v?.error??f.status}`);return}b?b.location.href=v.url:window.open(v.url,"_blank","noopener")}catch(f){b?.close(),alert(`${i("sessions.writeLinkFail")}: ${f}`)}finally{u&&(u.disabled=!1)}}function On(o){return o.status==="closed"?null:o.pendingRepo||o.tuiPromptActive||o.agentAttention||o.status==="limited"?"needs-you":o.status==="starting"?"starting":o.status==="working"||o.status==="analyzing"||o.status==="active"?"working":(o.status==="dormant","idle")}function nn(){return`<details class="filter-cli">
2
+ <summary>${i("sessions.cli")} \xB7 <b id="cli-filter-count">${i("common.all")}</b></summary>
3
+ <div class="filter-cli-pop" role="group" aria-label="${i("sessions.cli")}">
4
+ ${en.map(o=>`
5
+ <label class="filter-check">
6
+ <input type="checkbox" name="cli" value="${l(o)}" checked>
7
+ <span>${l(o)}</span>
8
+ </label>
9
+ `).join("")}
10
+ </div>
11
+ </details>`}function Kn(o){let u=String(o.status??"unknown"),b=String(o.cliId??"unknown"),f=we.locale==="zh"?"\uFF1A":": ";return[i("sessions.restartConfirmIntro"),"",`${i("sessions.restartConfirmStatus")}${f}${Me(u)}`,`${i("sessions.restartConfirmCli")}${f}${b}`,"",i("sessions.restartConfirmQuestion")].join(`
12
+ `)}function ot(o){return o.status!=="closed"&&!o.adopt&&!o.pendingRepo}async function _n(){try{let o=await fetch("/api/groups");if(!o.ok)return[];let u=await o.json();return(Array.isArray(u?.bots)?u.bots:[]).filter(f=>f&&typeof f.larkAppId=="string").map(f=>({larkAppId:f.larkAppId,botName:typeof f.botName=="string"&&f.botName?f.botName:f.larkAppId}))}catch{return[]}}function jn(o){let u=o.map(b=>`
13
+ <label class="cs-bot"><input type="checkbox" name="bot" value="${l(b.larkAppId)}"> <span>${l(b.botName)}</span></label>`).join("");return`
14
+ <article class="cs-card">
15
+ <header><h3>${i("sessions.create.title")}</h3></header>
16
+ <form id="cs-form">
17
+ <label class="form-row">
18
+ <span>${i("sessions.create.content")}</span>
19
+ <textarea name="content" rows="5" placeholder="${l(i("sessions.create.contentPlaceholder"))}" required></textarea>
20
+ </label>
21
+ <fieldset class="cs-bots">
22
+ <legend>${i("sessions.create.bots")}</legend>
23
+ ${u||`<p class="cs-empty">${i("sessions.create.noBots")}</p>`}
24
+ </fieldset>
25
+ <fieldset class="cs-mode">
26
+ <legend>${i("sessions.create.mode")}</legend>
27
+ <label><input type="radio" name="mode" value="lead" checked> ${i("sessions.create.modeLead")}</label>
28
+ <label><input type="radio" name="mode" value="all"> ${i("sessions.create.modeAll")}</label>
29
+ <small>${i("sessions.create.modeHelp")}</small>
30
+ </fieldset>
31
+ <div class="cs-lead-row form-row" hidden>
32
+ <span>${i("sessions.create.lead")}</span>
33
+ <select name="lead"></select>
34
+ <small>${i("sessions.create.leadHelp")}</small>
35
+ </div>
36
+ <fieldset class="cs-column">
37
+ <legend>${i("sessions.create.column")}</legend>
38
+ <label><input type="radio" name="column" value="in_progress" checked> ${i("sessions.create.columnInProgress")}</label>
39
+ <label><input type="radio" name="column" value="backlog"> ${i("sessions.create.columnBacklog")}</label>
40
+ <small>${i("sessions.create.columnHelp")}</small>
41
+ </fieldset>
42
+ <details class="cs-advanced">
43
+ <summary>${i("sessions.create.advanced")}</summary>
44
+ <label class="form-row">
45
+ <span>${i("sessions.create.groupName")}</span>
46
+ <input type="text" name="name" maxlength="60" placeholder="${l(i("sessions.create.groupNamePlaceholder"))}">
47
+ </label>
48
+ <label class="form-row">
49
+ <span>${i("sessions.create.workingDir")}</span>
50
+ <input type="text" name="bindWorkingDir" placeholder="e.g. ~/projects/foo">
51
+ <small>${i("sessions.create.workingDirHelp")}</small>
52
+ </label>
53
+ </details>
54
+ <div class="actions cs-actions">
55
+ <button type="submit" class="primary">${i("sessions.create.submit")}</button>
56
+ <button type="button" id="cs-cancel">${i("sessions.create.cancel")}</button>
57
+ </div>
58
+ </form>
59
+ </article>`}function Un(o,u){u.onclick=async()=>{u.disabled=!0;try{let b=await _n();if(b.length===0){alert(i("sessions.create.noBots"));return}o.innerHTML=jn(b),o.showModal(),Fn(o,b)}finally{u.disabled=!1}}}function Fn(o,u){let b=o.querySelector("#cs-form"),f=o.querySelector(".cs-lead-row"),v=o.querySelector("select[name=lead]"),me=H=>u.find(R=>R.larkAppId===H)?.botName??H,ie=()=>Array.from(b.querySelectorAll("input[name=bot]:checked")).map(H=>H.value),W=()=>b.querySelector("input[name=mode]:checked")?.value??"all";function G(){let H=ie(),R=v.value;if(H.length===0){v.innerHTML=`<option value="" disabled selected>${l(i("sessions.create.leadPickFirst"))}</option>`,v.disabled=!0;return}v.disabled=!1,v.innerHTML=H.map(J=>`<option value="${l(J)}">${l(me(J))}</option>`).join(""),H.includes(R)&&(v.value=R)}function U(){W()==="lead"?(f.hidden=!1,G()):f.hidden=!0}b.querySelectorAll("input[name=mode]").forEach(H=>H.addEventListener("change",U)),b.querySelectorAll("input[name=bot]").forEach(H=>H.addEventListener("change",()=>{W()==="lead"&&G()})),U(),o.querySelector("#cs-cancel").onclick=()=>o.close(),b.onsubmit=async H=>{H.preventDefault();let R=new FormData(b),J=(R.get("content")??"").trim(),Q=ie(),be=W(),ee=R.get("column")??"in_progress",fe=(R.get("name")??"").trim(),q=(R.get("bindWorkingDir")??"").trim(),T=R.get("lead")??"";if(!J){alert(i("sessions.create.errContent"));return}if(Q.length===0){alert(i("sessions.create.errNoBot"));return}if(be==="lead"&&(!T||!Q.includes(T))){alert(i("sessions.create.errLead"));return}let $=b.querySelector("button[type=submit]");$&&($.disabled=!0,$.textContent=i("sessions.create.submitting"));try{let S=await fetch("/api/sessions/create",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({content:J,larkAppIds:Q,mode:be,column:ee,leadLarkAppId:be==="lead"?T:void 0,name:fe||void 0,bindWorkingDir:q||void 0})}),te=await S.json().catch(()=>null);S.ok&&te?.ok?zn(o,te):S.status!==401&&(alert(`${i("sessions.create.failed")}: ${te?.error??S.status}`),$&&($.disabled=!1,$.textContent=i("sessions.create.submit")))}catch(S){alert(`${i("sessions.create.failed")}: ${S}`),$&&($.disabled=!1,$.textContent=i("sessions.create.submit"))}}}function zn(o,u){let b=typeof u.shareLink=="string"&&u.shareLink?u.shareLink:"",f=Array.isArray(u.failed)?u.failed.length:0,v=Array.isArray(u.spawned)?u.spawned.length:0,me=u.column==="backlog"?i("sessions.create.doneBacklog"):i("sessions.create.doneInProgress"),ie=f>0?`<p class="cs-warn">${i("sessions.create.partialFail",{n:String(f)})}</p>`:"";o.innerHTML=`
60
+ <article class="cs-card">
61
+ <header><h3>${i("sessions.create.doneTitle")}</h3></header>
62
+ <p>${l(me)}\uFF08${v}\uFF09</p>
63
+ ${ie}
64
+ ${b?`<p><a href="${l(b)}" target="_blank" rel="noopener">${i("sessions.create.openChat")}</a></p>`:""}
65
+ <div class="actions"><button type="button" id="cs-done" class="primary">${i("sessions.create.close")}</button></div>
66
+ </article>`,o.querySelector("#cs-done").onclick=()=>o.close()}function sn(o){let u=o.querySelector("#sessions-table tbody"),b=o.querySelector("#filters"),f=o.querySelector("#drawer"),v=o.querySelector("#select-all"),me=o.querySelector("#bulk-bar"),ie=o.querySelector("#bulk-count"),W=o.querySelector("#bulk-lock"),G=o.querySelector("#bulk-unlock"),U=o.querySelector("#bulk-close"),H=o.querySelector("#bulk-clear"),R=o.querySelector("#idle-cleanup-bar"),J=o.querySelector("#idle-cleanup-threshold"),Q=o.querySelector("#idle-cleanup-run"),be=o.querySelector("#idle-cleanup-count"),ee=o.querySelector("#idle-cleanup-status"),fe=o.querySelector("#sessions-table"),q=o.querySelector("#sessions-board"),T=o.querySelector("#sessions-kanban"),$=o.querySelector("#term-modal"),S=o.querySelector("#history-modal"),te=o.querySelector("#kanban-groupby"),K=o.querySelector("#kanban-team"),rt=o.querySelector("#kanban-team-stats"),lt=o.querySelectorAll(".sessions-view-toggle [data-view]"),an=o.querySelector("#create-session-btn"),ct=o.querySelector("#create-session-modal");Un(ct,an);let w=new Set,ge="lastMessageAt",re="desc",E=Bt(window.localStorage),_=Pt(window.localStorage),Y=null,Oe="",Ke="",L="",dt=!1,ne=null,_e=!1,he=null,le=new Map,D=qt(window.localStorage),se=null,Ie=null,B=[],je=null,He=!1,Ue=!1,X=(()=>{try{return window.localStorage.getItem(et)??""}catch{return""}})(),Ee=!1,Ae=24;function ut(){return Ae}function on(e){return e===168?"7d":`${e}H`}function pt(e){let t=new Set;if(!e)return t;for(let a of e.groupChats)t.add(a);if(je)for(let[a,n]of je){if(t.has(a))continue;let s=!1;for(let r of e.botIds)if(n.botIds.has(r)){s=!0;break}if(s){for(let r of n.observedNames)if(e.botNames.has(r)){t.add(a);break}}}return t}function rn(){let e=ye();if(E==="kanban"&&D==="team"){let t=B.find(n=>n.key===X)??B[0],a=pt(t);return e.filter(n=>a.has(String(n.chatId)))}return e}function mt(){return Ft(rn(),ut())}function ln(){J.querySelectorAll("button[data-hours]").forEach(e=>{let t=tt(e.dataset.hours)===Ae;e.classList.toggle("active",t),e.setAttribute("aria-pressed",t?"true":"false")})}async function cn(){if(!(Ue||He)){Ue=!0;try{let[e,t,a]=await Promise.all([fetch("/api/team/hosted").then(r=>r.json()).catch(()=>null),fetch("/api/team/remote-roster").then(r=>r.json()).catch(()=>null),fetch("/api/groups").then(r=>r.json()).catch(()=>null)]);Array.isArray(a?.chats)&&(je=new Map(a.chats.map(r=>[String(r.chatId),{botIds:new Set((r.memberBots??[]).filter(c=>c.inChat).map(c=>String(c.larkAppId))),observedNames:new Set((r.observedBotNames??[]).map(c=>String(c)))}])));let n=r=>({ids:new Set(r.map(c=>String(c.larkAppId))),names:new Set(r.map(c=>String(c.name??"")).filter(Boolean))}),s=[];for(let r of e?.teams??[]){let{ids:c,names:d}=n(r.bots??[]);s.push({key:`local:${r.teamId}`,label:r.isDefault?i("team.myHostedTeam"):String(r.name??r.teamId),botIds:c,botNames:d,groupChats:new Set((r.groupChatIds??[]).map(m=>String(m)))})}for(let r of t?.memberships??[]){let{ids:c,names:d}=n(r.roster?.bots??[]);s.push({key:`${r.hubUrl}::${r.teamId}`,label:String(r.teamName??r.teamId??r.hubUrl),botIds:c,botNames:d,groupChats:new Set})}B=s}finally{He=!0,Ue=!1}B.length&&!B.some(e=>e.key===X)&&(X=B[0].key),delete K.dataset.loading,K.disabled=B.length===0,K.innerHTML=B.length?B.map(e=>`<option value="${l(e.key)}"${e.key===X?" selected":""}>${l(e.label)}</option>`).join(""):`<option value="">${l(i("sessions.kanban.noTeam"))}</option>`,L="",h()}}let A=null,ce="",bt=0,Fe=!1,ze=new Map;async function dn(e){let t=ce===e.key&&Date.now()-bt<3e4;if(!(Fe||t)){Fe=!0;try{let n=e.key.startsWith("local:")?`/api/team/board/local/${encodeURIComponent(e.key.slice(6))}`:`/api/team/remote-board?key=${encodeURIComponent(e.key)}`,s=await fetch(n),r=await s.json().catch(()=>({}));if(!s.ok||r?.ok===!1)return;let c=typeof r.deploymentId=="string"?r.deploymentId:null,d=[];ze=new Map;for(let m of Array.isArray(r.reports)?r.reports:[])if(!(c&&m.deploymentId===c))for(let g of Array.isArray(m.sessions)?m.sessions:[]){let M={...g,remoteDeployment:m.deploymentName||m.deploymentId};d.push(M),ze.set(String(g.sessionId),M)}A={board:r.board&&typeof r.board=="object"?r.board:{},remoteRows:d},ce=e.key,bt=Date.now(),L="",h()}catch{}finally{Fe=!1}}}async function un(e,t,a,n,s){try{let c=e.startsWith("local:")?await fetch(`/api/team/board/local/${encodeURIComponent(e.slice(6))}/move`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({sessionId:t,column:a,position:n})}):await fetch("/api/team/remote-board-move",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:e,sessionId:t,column:a,position:n})}),d=await c.json().catch(()=>({}));(!c.ok||d?.ok===!1)&&(A&&(s?A.board[t]=s:delete A.board[t]),L="",h(),c.status!==401&&alert(`${i("sessions.kanban.moveFail")}: ${d?.error??c.status}`))}catch(r){A&&(s?A.board[t]=s:delete A.board[t]),L="",h(),alert(`${i("sessions.kanban.moveFail")}: ${r}`)}}function ft(e,t,a){let n=B.find(r=>r.key===X)??B[0];if(!n)return;(!A||ce!==n.key)&&(A={board:{},remoteRows:A?.remoteRows??[]},ce=n.key);let s=A.board[e];A.board[e]={column:t,position:a},un(n.key,e,t,a,s)}function pn(){return _.map(e=>Jt.find(t=>t.id===e)).filter(e=>!!e)}function mn(e,t){let a=_.indexOf(e),n=a+t;if(a<0||n<0||n>=_.length)return;let s=[..._];s.splice(a,1),s.splice(n,0,e),_=s,Qe(window.localStorage,_),h()}function bn(e,t){if(e===t)return;let a=_.indexOf(e),n=_.indexOf(t);if(a<0||n<0)return;let s=[..._];s.splice(a,1),s.splice(n,0,e),_=s,Qe(window.localStorage,_),h()}function fn(e){let t=e.status==="closed",a=w.has(e.sessionId)?"checked":"";return`<tr data-id="${l(e.sessionId)}">
67
+ <td><input type="checkbox" class="row-select" ${a} ${t?"disabled":""}></td>
68
+ <td>${l(F(e))}</td>
69
+ <td><span class="badge cli-${qe(e.cliId)}">${l(e.cliId??"unknown")}</span></td>
70
+ <td>${Se(e.status)}${Ce(e)}</td>
71
+ <td class="token-cell">${Gt(e.tokenUsage?.in)}</td>
72
+ <td class="token-cell">${Gt(e.tokenUsage?.out)}</td>
73
+ <td title="${l(String(e.title??""))}">${l(j(e.title??"").slice(0,48))}</td>
74
+ <td title="${l(e.workingDir??"")}">${l((e.workingDir??"").slice(-34))}</td>
75
+ <td>${ue(e.spawnedAt)}</td>
76
+ <td>${ue(e.lastMessageAt)}</td>
77
+ <td>${e.adopt?'<span class="badge">adopt</span>':""}</td>
78
+ <td><button class="open" type="button">${i("sessions.details")}</button></td>
79
+ </tr>`}function gt(e){if(e.scope!=="chat"||!e.feishuChatLink)return null;let t=i("sessions.openChat");return`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(t)}" aria-label="${l(t)}">${C.feishu}</a>`}function ht(e){return e.agentAttention?.reason?e.agentAttention.reason:e.agentAttention?i("sessions.board.signalAgent"):e.pendingRepo?i("sessions.board.signalRepo"):e.tuiPromptActive?i("sessions.board.signalPrompt"):e.status==="limited"?i("sessions.board.signalLimited"):""}function gn(e){let t=w.has(e.sessionId),a=j(e.title)||e.sessionId,n=F(e),s=pe(e),r=at(e),c=ht(e),d=Xt(e.workingDir);return`<article class="session-card${t?" selected":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" aria-pressed="${t}">
80
+ <div class="session-card-top">
81
+ ${ae({name:n,larkAppId:e.larkAppId,size:"sm"})}
82
+ <div class="session-card-title">
83
+ <strong title="${l(String(e.title??a))}">${l(String(a).slice(0,72))}</strong>
84
+ <span>${l(n)} \xB7 ${l(s??e.cliId??"unknown")}</span>
85
+ </div>
86
+ <span class="session-card-status-group">
87
+ ${Se(e.status)}
88
+ ${Ce(e)}
89
+ </span>
90
+ </div>
91
+ ${d!=="-"||e.adopt?`<div class="session-card-meta">
92
+ ${d!=="-"?`<span title="${l(e.workingDir??"")}">${l(d)}</span>`:""}
93
+ ${e.adopt?'<span class="badge">adopt</span>':""}
94
+ </div>`:""}
95
+ <div class="session-card-time">
96
+ <span>${e.agentAttention?.at?`${l(i("sessions.board.waiting"))} ${ue(Pe(e))}`:`${l(i("sessions.last"))}: ${ue(e.lastMessageAt)}`}</span>
97
+ </div>
98
+ ${c?`<div class="session-signal" title="${l(c)}">${l(c)}</div>`:""}
99
+ <div class="session-card-actions">
100
+ ${gt(e)??Te("locate",C.pin,i("sessions.locate"))}
101
+ ${Te("details",C.details,i("sessions.details"))}
102
+ ${ot(e)?Te("restart",C.restart,i("sessions.restart")):""}
103
+ ${Zt(r)}
104
+ ${Te("lock",e.locked?C.unlock:C.lock,Le(e),e.locked?"locked":"")}
105
+ ${Te("close",C.close,i("sessions.close"),"danger")}
106
+ </div>
107
+ </article>`}function hn(e,t,a){let n=a==="needs-you"?Pe(e):Number(e.lastMessageAt??0),s=a==="needs-you"?Pe(t):Number(t.lastMessageAt??0);return n!==s?a==="needs-you"?n-s:s-n:String(e.title??e.sessionId).localeCompare(String(t.title??t.sessionId))}function yn(e){let t=new Map(Jt.map(s=>[s.id,[]]));for(let s of e){let r=On(s);r&&t.get(r).push(s)}let a=pn(),n=a.map((s,r)=>{let c=(t.get(s.id)??[]).sort((d,m)=>hn(d,m,s.id));return`<section class="session-board-column session-board-${s.id}" data-col="${s.id}">
108
+ <header draggable="true" title="${l(i("sessions.board.dragHint"))}">
109
+ <div>
110
+ <h2>${l(i(s.labelKey))}</h2>
111
+ <p>${l(i(s.hintKey))}</p>
112
+ </div>
113
+ <span class="session-board-head-right">
114
+ <span class="session-board-move">
115
+ <button type="button" data-move-col="${s.id}" data-dir="-1"
116
+ aria-label="${l(i("sessions.board.moveLeft"))}" ${r===0?"disabled":""}>\u2039</button>
117
+ <button type="button" data-move-col="${s.id}" data-dir="1"
118
+ aria-label="${l(i("sessions.board.moveRight"))}" ${r===a.length-1?"disabled":""}>\u203A</button>
119
+ </span>
120
+ <span class="session-board-count">${c.length}</span>
121
+ </span>
122
+ </header>
123
+ <div class="session-board-list">
124
+ ${c.length?c.map(gn).join(""):`<div class="session-board-empty">${i("sessions.board.emptyColumn")}</div>`}
125
+ </div>
126
+ </section>`}).join("");n!==Oe&&(Oe=n,q.innerHTML=n,q.classList.toggle("board-enter",!dt),dt=!0)}function yt(e){let t=j(e.title)||e.sessionId,a=F(e),n=pe(e),s=Xt(e.workingDir),r=ht(e),c=[n,s!=="-"?s:null].filter(Boolean).join(" \xB7 "),d=String(e.status??"unknown"),m=typeof e.remoteDeployment=="string"?e.remoteDeployment:"";return`<article class="kanban-card${m?" kanban-card-remote":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" tabindex="0" role="button" draggable="true">
127
+ <div class="kanban-card-top">
128
+ <span class="badge cli-${qe(e.cliId)}">${l(e.cliId??"unknown")}</span>
129
+ ${e.adopt?'<span class="badge">adopt</span>':""}
130
+ ${Ce(e)}
131
+ ${m?`<span class="badge kanban-remote-badge" title="${l(i("sessions.kanban.remoteHint",{name:m}))}">${l(m)}</span>`:""}
132
+ <span class="kanban-card-top-right">
133
+ <span class="kanban-card-dot" data-status="${l(qe(d))}" title="${l(Me(d))}"></span>
134
+ ${m?"":`<button type="button" class="card-act kanban-card-act" data-action="history" title="${l(i("sessions.history.title"))}" aria-label="${l(i("sessions.history.title"))}">${C.history}</button>
135
+ ${e.feishuChatLink?`<a class="card-act kanban-card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(i("sessions.kanban.openFeishu"))}" aria-label="${l(i("sessions.kanban.openFeishu"))}">${C.feishu}</a>`:""}
136
+ <button type="button" class="card-act kanban-card-act${e.locked?" locked":""}" data-action="lock" title="${l(Le(e))}" aria-label="${l(Le(e))}">${e.locked?C.unlock:C.lock}</button>
137
+ <button type="button" class="card-act kanban-card-act" data-action="details" title="${l(i("sessions.details"))}" aria-label="${l(i("sessions.details"))}">${C.details}</button>
138
+ ${ot(e)?`<button type="button" class="card-act kanban-card-act" data-action="restart" title="${l(i("sessions.restart"))}" aria-label="${l(i("sessions.restart"))}">${C.restart}</button>`:""}`}
139
+ </span>
140
+ </div>
141
+ <p class="kanban-card-title" title="${l(String(e.title??t))}">${l(String(t).slice(0,140))}</p>
142
+ ${c?`<p class="kanban-card-desc" title="${l(c)}">${l(c)}</p>`:""}
143
+ ${r?`<div class="session-signal" title="${l(r)}">${l(r)}</div>`:""}
144
+ <div class="kanban-card-foot">
145
+ <span class="kanban-card-owner">${ae({name:a,larkAppId:e.larkAppId,size:"sm"})}<span>${l(a)}</span></span>
146
+ <span class="kanban-card-updated">${l(i("sessions.kanban.updated",{time:ue(e.lastMessageAt)}))}</span>
147
+ </div>
148
+ </article>`}function kt(e){let t=[],a=new Map;for(let r of e){let c=String(r.chatId??r.sessionId),d=a.get(c);d||(d={chatId:c,rows:[]},a.set(c,d),t.push(d)),d.rows.push(r)}let n=[];return{html:t.map(r=>{if(n.push(...r.rows),r.rows.length<2)return yt(r.rows[0]);let c=pe(r.rows[0])??r.chatId;return`<div class="kanban-cluster" data-chat="${l(r.chatId)}">
149
+ <header draggable="true" title="${l(c)} \xB7 ${l(i("sessions.kanban.clusterDragHint"))}">
150
+ ${Ot({chatId:r.chatId,name:c,size:"sm"})}
151
+ <span class="kanban-cluster-name">${l(c)}</span>
152
+ <span class="kanban-cluster-count">${r.rows.length}</span>
153
+ </header>
154
+ ${r.rows.map(yt).join("")}
155
+ </div>`}).join(""),flat:n}}function kn(e){let t=new Map;for(let n of e){if(n.status==="closed")continue;let s=String(n.larkAppId||n.botName||"unknown"),r=t.get(s);r||(r={name:F(n),larkAppId:n.larkAppId,rows:[]},t.set(s,r)),r.rows.push(n)}let a=[...t.values()].sort((n,s)=>n.name.localeCompare(s.name));return a.length?a.map(n=>{let s=n.rows.sort((c,d)=>Number(d.lastMessageAt??0)-Number(c.lastMessageAt??0)),{html:r}=kt(s);return`<section class="kanban-column kanban-bot-col" data-bot="${l(n.larkAppId??n.name)}">
156
+ <header>
157
+ <span class="kanban-col-avatar">${ae({name:n.name,larkAppId:n.larkAppId,size:"sm"})}</span>
158
+ <h2>${l(n.name)}</h2>
159
+ <span class="kanban-col-count">${s.length}</span>
160
+ </header>
161
+ <div class="kanban-col-list">${r}</div>
162
+ </section>`}).join(""):`<div class="kanban-col-empty">${i("sessions.board.emptyColumn")}</div>`}function $t(e){let t=new Map(Yt.map(n=>[n.id,[]]));for(let n of e)t.get(Vt(n)).push(n);let a=Yt.map(n=>{let s=(t.get(n.id)??[]).sort((m,g)=>oe(m)-oe(g)),r=0;n.id==="done"&&s.length>st&&(r=s.length-st,s=s.slice(0,st));let{html:c,flat:d}=kt(s);return t.set(n.id,d),`<section class="kanban-column kanban-${n.id}" data-col="${n.id}">
163
+ <header>
164
+ <span class="kanban-col-icon">${Dn(n.id)}</span>
165
+ <h2>${l(i(n.labelKey))}</h2>
166
+ <span class="kanban-col-count">${s.length+r}</span>
167
+ </header>
168
+ <div class="kanban-col-list">
169
+ ${s.length?c:`<div class="kanban-col-empty">${i("sessions.board.emptyColumn")}</div>`}
170
+ ${r?`<div class="kanban-col-more">${l(i("sessions.kanban.moreHidden",{count:r}))}</div>`:""}
171
+ </div>
172
+ </section>`}).join("");return le=t,a}function $n(e){if(ne||se||_e)return;T.classList.toggle("kanban-mode-bot",D==="bot");let t;if(D==="bot")t=kn(e),le=new Map;else if(D==="team")if(!He)t=`<div class="kanban-loading">${i("sessions.kanban.teamLoading")}</div>`,le=new Map,K.dataset.loading||(K.dataset.loading="1",K.disabled=!0,K.innerHTML=`<option>${l(i("sessions.kanban.teamLoading"))}</option>`),cn();else{let n=B.find(g=>g.key===X)??B[0],s=pt(n),r=n?e.filter(g=>s.has(String(g.chatId))):[];n&&dn(n);let c=(ce===n?.key?A?.board:null)??{},d=(ce===n?.key?A?.remoteRows:null)??[],m=[...r,...d].map(g=>{let M=c[g.sessionId];return M?{...g,kanbanColumn:M.column,kanbanPosition:M.position}:g});rt.textContent=i("sessions.kanban.teamScope",{chats:s.size,sessions:m.length}),t=$t(m)}else t=$t(e);if(t===L)return;L=t;let a=new Map;T.querySelectorAll(".kanban-col-list").forEach(n=>{let s=n.closest(".kanban-column")?.dataset.col;s&&n.scrollTop&&a.set(s,n.scrollTop)}),T.innerHTML=t,a.size&&T.querySelectorAll(".kanban-col-list").forEach(n=>{let s=n.closest(".kanban-column")?.dataset.col,r=s?a.get(s):void 0;r&&(n.scrollTop=r)})}async function vt(e,t,a,n){try{let s=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/board`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({column:t,position:a})}),r=await s.json().catch(()=>({}));(!s.ok||r?.ok===!1)&&(e.kanbanColumn=n.column,e.kanbanPosition=n.position,L="",h(),s.status!==401&&alert(`${i("sessions.kanban.moveFail")}: ${r?.error??s.status}`))}catch(s){e.kanbanColumn=n.column,e.kanbanPosition=n.position,L="",h(),alert(`${i("sessions.kanban.moveFail")}: ${s}`)}}async function wt(e,t){let a=e.title;e.title=t,L="",h();try{let n=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/rename`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({title:t})}),s=await n.json().catch(()=>({}));(!n.ok||s?.ok===!1)&&(e.title=a,L="",h(),n.status!==401&&alert(`${i("sessions.kanban.renameFail")}: ${s?.error??n.status}`))}catch(n){e.title=a,L="",h(),alert(`${i("sessions.kanban.renameFail")}: ${n}`)}}function vn(e){if(e==null||e==="")return"";let t=Number(e),a=Number.isFinite(t)&&t>0?new Date(t):new Date(String(e));return Number.isNaN(a.getTime())?"":a.toLocaleString()}function wn(e,t,a){let n=t.senderType==="user",s=n?t.senderName||(a&&t.senderId===a?i("sessions.history.owner"):i("sessions.history.user")):F(e),r=vn(t.createTime),c=String(t.content??"").trim()||`[${t.msgType??"message"}]`,d=n?t.senderAvatar?`<img class="history-avatar-img" src="${l(String(t.senderAvatar))}" alt="" decoding="async" referrerpolicy="no-referrer">`:`<span class="history-avatar-user" aria-hidden="true">${l(String(s).slice(0,1))}</span>`:ae({name:F(e),larkAppId:e.larkAppId,size:"sm"});return`<div class="history-msg${n?" mine":""}">
173
+ ${d}
174
+ <div class="history-msg-main">
175
+ <div class="history-msg-meta"><span>${l(s)}</span><time>${l(r)}</time></div>
176
+ <div class="history-bubble">${l(c)}</div>
177
+ </div>
178
+ </div>`}async function St(e){let t=F(e);S.innerHTML=`<div class="term-modal-head">
179
+ <span class="term-modal-title">
180
+ ${ae({name:t,larkAppId:e.larkAppId,size:"sm"})}
181
+ <strong title="${l(String(e.title??""))}">${l((j(e.title)||e.sessionId).slice(0,60))}</strong>
182
+ <span class="history-scope-tag">${l(i("sessions.history.title"))}</span>
183
+ </span>
184
+ <span class="term-modal-actions">
185
+ <button type="button" id="history-close" class="card-act" title="${l(i("sessions.dismiss"))}" aria-label="${l(i("sessions.dismiss"))}">${C.close}</button>
186
+ </span>
187
+ </div>
188
+ <div class="history-body"><div class="term-modal-loading">${i("sessions.history.loading")}</div></div>`,S.showModal(),S.querySelector("#history-close").onclick=()=>S.close();try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/history?limit=80`),n=await a.json().catch(()=>({}));if(!S.open)return;let s=S.querySelector(".history-body");if(!a.ok||n?.ok===!1){let c=String(n?.error??a.status),d=c==="not_found_yet"||c==="not_found";s.innerHTML=`<div class="history-error">${l(i("sessions.history.fail"))}: ${l(c)}${d?`<br><span>${l(i("sessions.history.staleHint"))}</span>`:""}</div>`;return}let r=Array.isArray(n.messages)?n.messages:[];if(!r.length){s.innerHTML=`<div class="history-error">${i("sessions.history.empty")}</div>`;return}s.innerHTML=`<div class="history-list">${r.map(c=>wn(e,c,n.ownerOpenId)).join("")}</div>`,s.scrollTop=s.scrollHeight}catch(a){if(!S.open)return;let n=S.querySelector(".history-body");n&&(n.innerHTML=`<div class="history-error">${l(i("sessions.history.fail"))}: ${l(String(a))}</div>`)}}function Tt(e,t){let a=e.querySelector(".kanban-card-title");if(!a||e.querySelector(".kanban-rename-input"))return;_e=!0;let n=document.createElement("input");n.type="text",n.className="kanban-rename-input",n.maxLength=200,n.value=j(t.title)||"",a.replaceWith(n),n.focus(),n.select();let s=!1,r=c=>{if(s)return;s=!0,_e=!1;let d=n.value.trim();c&&d&&d!==(j(t.title)||"")?wt(t,d):(L="",h())};n.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Enter"?(c.preventDefault(),r(!0)):c.key==="Escape"&&(c.preventDefault(),r(!1))}),n.addEventListener("blur",()=>r(!0)),n.addEventListener("click",c=>c.stopPropagation())}function Lt(e,t){for(let a of e.querySelectorAll(".kanban-card:not(.dragging)")){if(a.closest(".kanban-cluster.dragging"))continue;let n=a.getBoundingClientRect();if(t<n.top+n.height/2)return a}return null}function Ct(){T.querySelectorAll(".drag-over, .dragging, .drop-before").forEach(e=>e.classList.remove("drag-over","dragging","drop-before"))}function Sn(e){let t=$.querySelector(".term-modal-name");if(!t||$.querySelector(".term-modal-name-input"))return;let a=document.createElement("input");a.type="text",a.className="term-modal-name-input",a.maxLength=200,a.value=j(e.title)||"",t.replaceWith(a);let n=()=>{let c=getComputedStyle(a),d=document.createElement("span");d.style.cssText="position:absolute;visibility:hidden;white-space:pre",d.style.fontSize=c.fontSize,d.style.fontFamily=c.fontFamily,d.style.fontWeight=c.fontWeight,d.style.letterSpacing=c.letterSpacing,d.textContent=a.value||" ",document.body.appendChild(d);let m=d.offsetWidth;d.remove();let g=Math.round(window.innerWidth*.6);a.style.width=`${Math.min(Math.max(m+22,80),g)}px`};n(),a.addEventListener("input",n),a.focus(),a.select();let s=!1,r=c=>{if(s)return;s=!0;let d=a.value.trim(),m=j(e.title)||"";if(c&&d&&d!==m){e.title=d;let g=document.createElement("strong");g.className="term-modal-name",g.title=d,g.textContent=d.slice(0,60),a.replaceWith(g),wt(e,d)}else{let g=document.createElement("strong");g.className="term-modal-name",g.title=String(e.title??m),g.textContent=m.slice(0,60),a.replaceWith(g)}};a.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Enter"?(c.preventDefault(),r(!0)):c.key==="Escape"&&(c.preventDefault(),r(!1))}),a.addEventListener("blur",()=>r(!0))}async function Mt(e){let t=at(e);if(!t){xe(e);return}let a=j(e.title)||e.sessionId,n=e.feishuChatLink?`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(i("sessions.kanban.openFeishu"))}" aria-label="${l(i("sessions.kanban.openFeishu"))}">${C.feishu}</a>`:"";$.innerHTML=`<div class="term-modal-head">
189
+ <span class="term-modal-title">
190
+ ${ae({name:F(e),larkAppId:e.larkAppId,size:"sm"})}
191
+ <strong class="term-modal-name" title="${l(String(e.title??a))}">${l(String(a).slice(0,60))}</strong>
192
+ <button type="button" id="term-modal-edit" class="card-act" title="${l(i("sessions.kanban.rename"))}" aria-label="${l(i("sessions.kanban.rename"))}">${C.edit}</button>
193
+ ${Se(e.status)}
194
+ </span>
195
+ <span class="term-modal-actions">
196
+ ${n}
197
+ <a id="term-modal-tab" class="card-act" href="${l(t)}" target="_blank" rel="noopener" title="${l(i("sessions.kanban.openTab"))}" aria-label="${l(i("sessions.kanban.openTab"))}">${C.terminal}</a>
198
+ <button type="button" id="term-modal-close" class="card-act" title="${l(i("sessions.dismiss"))}" aria-label="${l(i("sessions.dismiss"))}">${C.close}</button>
199
+ </span>
200
+ </div>
201
+ <div class="term-modal-body"><div class="term-modal-loading">${i("sessions.kanban.terminalLoading")}</div></div>`,$.showModal(),$.querySelector("#term-modal-close").onclick=()=>$.close(),$.querySelector("#term-modal-edit").onclick=()=>Sn(e);let s=t;if(we.authed)try{let d=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/write-link`),m=await d.json().catch(()=>({}));d.ok&&m?.ok!==!1&&m?.url&&(s=m.url)}catch{}if(!$.open)return;let r=$.querySelector(".term-modal-body");r.innerHTML=`<iframe class="term-modal-frame" src="${l(s)}" allow="clipboard-read; clipboard-write"></iframe>`;let c=$.querySelector("#term-modal-tab");c&&(c.href=s)}function ye(){let e=new FormData(b),t=(e.get("q")??"").toLowerCase(),a=e.getAll("cli"),n=a.length>0&&a.length<en.length,s=e.get("status"),r=e.get("adopt"),c=!!e.get("active"),d=E==="kanban",m=[...O.sessions.values()].filter(g=>!n||a.includes(g.cliId??"unknown")).filter(g=>!s||g.status===s).filter(g=>!r||r==="yes"==!!g.adopt).filter(g=>!c||d||g.status!=="closed").filter(g=>!t||JSON.stringify(g).toLowerCase().includes(t));return m.sort(Tn),m}function It(e,t){return t==="spawnedAt"||t==="lastMessageAt"?Number(e[t]??0):t==="tokenIn"?it(e.tokenUsage?.in)??-1:t==="tokenOut"?it(e.tokenUsage?.out)??-1:t==="adopt"?!!e.adopt:String(e[t]??"").toLowerCase()}function Tn(e,t){let a=It(e,ge),n=It(t,ge),s=0;return typeof a=="number"&&typeof n=="number"?s=a-n:typeof a=="boolean"&&typeof n=="boolean"?s=Number(a)-Number(n):s=String(a).localeCompare(String(n)),s===0&&(s=Number(e.lastMessageAt??0)-Number(t.lastMessageAt??0)),re==="asc"?s:-s}function Ln(){fe.querySelectorAll("th[data-sort]").forEach(e=>{let t=e.dataset.sort===ge;e.classList.toggle("sorted",t),e.setAttribute("aria-sort",t?re==="asc"?"ascending":"descending":"none");let a=e.dataset.label??e.textContent?.trim()??"";e.textContent=t?`${a} ${re==="asc"?"\u25B2":"\u25BC"}`:a})}function We(e){me.hidden=w.size===0,ie.textContent=i("sessions.selectedCount",{count:w.size});let t=[...w].map(s=>O.sessions.get(s)).filter(s=>!!s&&s.status!=="closed");W.disabled=!t.some(s=>!s.locked),G.disabled=!t.some(s=>!!s.locked);let a=e.filter(s=>s.status!=="closed");if(a.length===0){v.checked=!1,v.indeterminate=!1,v.disabled=!0;return}v.disabled=!1;let n=a.filter(s=>w.has(s.sessionId)).length;v.checked=n===a.length,v.indeterminate=n>0&&n<a.length}function Ve(){let e=mt().length;be.textContent=i("sessions.idleCleanupCount",{count:e}),Q.disabled=Ee||e===0,R.classList.toggle("is-empty",e===0),ln()}function Cn(){lt.forEach(e=>{let t=e.dataset.view===E;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))}),te.hidden=E!=="kanban",K.hidden=!(E==="kanban"&&D==="team"),rt.hidden=K.hidden||!He,te.querySelectorAll("[data-groupby]").forEach(e=>{let t=e.dataset.groupby===D;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))})}function Mn(){let e=b.querySelector("#cli-filter-count");if(!e)return;let t=[...b.querySelectorAll('input[name="cli"]')],a=t.filter(n=>n.checked).length;e.textContent=a===t.length?i("common.all"):`${a}/${t.length}`,e.classList.toggle("cli-filter-active",a!==t.length)}function h(){let e=ye();for(let n of[...w]){let s=O.sessions.get(n);(!s||s.status==="closed")&&w.delete(n)}let t=e.filter(n=>n.status!=="closed"),a=E==="table"?e:t;if(fe.hidden=E!=="table",q.hidden=E!=="board",T.hidden=E!=="kanban",E==="table"){let n=e.length?e.map(fn).join(""):`<tr><td colspan="12" class="empty">${i("sessions.empty")}</td></tr>`;n!==Ke&&(Ke=n,u.innerHTML=n)}else E==="kanban"?$n(e):yn(t);Cn(),Ln(),Mn(),We(a),Ve()}async function Ht(e,t){t&&(t.disabled=!0,t.textContent=i("sessions.locating"));try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/locate`,{method:"POST"}),n=await a.json();if(n.ok){if(!t)return;let s=30;t.textContent=i("sessions.cooldown",{seconds:s});let r=setInterval(()=>{s-=1,s<=0?(clearInterval(r),t.disabled=!1,t.textContent=i("sessions.locate")):t.textContent=i("sessions.cooldown",{seconds:s})},1e3)}else alert(`Locate failed: ${n.error??a.status}`),t&&(t.disabled=!1,t.textContent=i("sessions.locate"))}catch(a){alert(`Locate error: ${a}`),t&&(t.disabled=!1,t.textContent=i("sessions.locate"))}}async function Et(e,t){if(!confirm(i("sessions.closeConfirm")))return!1;t&&(t.disabled=!0);try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/close`,{method:"POST"}),n=await a.json().catch(()=>({}));return!a.ok||n?.ok===!1?(a.status!==401&&alert(`Close failed: ${n?.error??a.status}`),!1):!0}catch(a){return alert(`Close error: ${a}`),!1}finally{t&&(t.disabled=!1)}}function ke(){Oe="",Ke="",L=""}async function Ge(e,t,a){let n=!!e.locked;if(n===t)return!0;e.locked=t,ke(),h(),a&&(a.disabled=!0);try{let s=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:t})}),r=await s.json().catch(()=>({}));return!s.ok||r?.ok===!1?(e.locked=n,ke(),h(),s.status!==401&&alert(`${i("sessions.lockFailed")}: ${r?.error??s.status}`),!1):(e.locked=!!r.locked,ke(),h(),!0)}catch(s){return e.locked=n,ke(),h(),alert(`${i("sessions.lockFailed")}: ${s}`),!1}finally{a&&(a.disabled=!1)}}let Je=new Set;async function Ye(e,t){if(Je.has(e.sessionId)||!confirm(Kn(e)))return!1;t&&(t.disabled=!0);try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/restart`,{method:"POST"}),n=await a.json().catch(()=>({}));return!a.ok||n?.ok===!1?(a.status!==401&&alert(`${i("sessions.restartFailed")}: ${n?.error??a.status}`),!1):(Je.add(e.sessionId),setTimeout(()=>Je.delete(e.sessionId),5e3),!0)}catch(a){return alert(`${i("sessions.restartFailed")}: ${a}`),!1}finally{t&&(t.disabled=!1)}}function In(e){return e===void 0?"\u2014":e<1e3?`${e}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${Math.floor(e/6e4)}m${Math.round(e%6e4/1e3)}s`}function Hn(e){if(!e||e.status!=="ok"){let r=e?.error?.message?l(String(e.error.message)):l(String(e?.status??"error"));return`<p>${i("sessions.insightUnavailable")}: ${r}</p>`}let t=e.agg??{};if(!t.totalSpans)return`<p>${i("sessions.insightEmpty")}</p>`;let a="color:var(--muted,#8f959e)",n=[],s=[];if(e.meta?.asOf&&s.push(l(i("sessions.insightAsOf",{asOf:String(e.meta.asOf)}))),e.meta?.partial&&s.push(l(i("sessions.insightPartial"))),s.length&&n.push(`<p style="font-size:12px;${a}">${s.join(" \xB7 ")}</p>`),n.push(`<p>${l(i("sessions.insightMetrics",{total:String(t.totalSpans??0),failed:String(t.failedSpans??0),slow:String(t.slowSpans??0),rw:t.readWriteRatio===null||t.readWriteRatio===void 0?"\u2014":String(t.readWriteRatio),compactions:String(t.compactions??0)}))}</p>`),Array.isArray(e.suggestions)&&e.suggestions.length){let r=d=>d==="bad"?"\u{1F534}":d==="warn"?"\u{1F7E1}":"\u2139\uFE0F",c=e.suggestions.map(d=>`<li>${r(d.severity)} <b>${l(String(d.title??""))}</b> \u2014 ${l(String(d.action??""))}`+(Array.isArray(d.evidence)&&d.evidence.length?`<br><small style="${a}">${l(d.evidence.join("\uFF1B"))}</small>`:"")+"</li>").join("");n.push(`<details open><summary>${i("sessions.insightSuggestions")}</summary><ul style="padding-left:18px;margin:6px 0">${c}</ul></details>`)}if(Array.isArray(e.spans)&&e.spans.length){let r=m=>m==="error"?"\u{1F534}":m==="running"?"\u23F3":"\u2705",c=[...e.spans].sort((m,g)=>(m.relStartMs??0)-(g.relStartMs??0)).map(m=>{let g=[m.inputSummary,m.outputSummary].filter(Boolean).map(x=>l(String(x))).join(" \u2192 ");return`<tr${m.status==="error"?' style="color:var(--danger,#d33)"':""}><td>${r(m.status)}</td><td><code>${l(String(m.tool??""))}</code></td><td>${l(String(m.phase??""))}</td><td>${In(m.durationMs)}</td><td>#${l(String(m.turnIndex??0))}</td><td>${g}</td></tr>`}).join(""),d=e.meta?.capped?`<p style="font-size:12px;${a}">${l(i("sessions.insightCapped",{shown:String(e.meta.spansReturned??e.spans.length),total:String(e.meta.spansTotal??e.spans.length)}))}</p>`:"";n.push(`<details><summary>${i("sessions.insightSpans")} (${e.spans.length})</summary>${d}<div style="max-height:320px;overflow:auto"><table style="width:100%;font-size:12px"><tbody>${c}</tbody></table></div></details>`)}return n.join("")}function xe(e){let t=e.status==="closed",a=at(e);f.innerHTML=`<article>
202
+ <header>
203
+ <h3>${l(j(e.title)||e.sessionId)}</h3>
204
+ <span class="drawer-status-line">
205
+ ${Se(e.status)}
206
+ ${Ce(e)}
207
+ </span>
208
+ <p><code>${l(e.sessionId)}</code> <button data-copy="${l(e.sessionId)}">${i("sessions.copy")}</button></p>
209
+ </header>
210
+ <p><b>${i("sessions.bot")}:</b> ${l(F(e))} \xB7 <b>${i("sessions.cli")}:</b> ${l(e.cliId??"?")}</p>
211
+ ${pe(e)?`<p><b>${i("sessions.chat")}:</b> ${l(pe(e))}</p>`:""}
212
+ <p><b>chatId:</b> <code>${l(e.chatId??"")}</code> <button data-copy="${l(e.chatId??"")}">${i("sessions.copy")}</button></p>
213
+ <p><b>rootMessageId:</b> <code>${l(e.rootMessageId??"")}</code> <button data-copy="${l(e.rootMessageId??"")}">${i("sessions.copy")}</button></p>
214
+ ${e.threadId?`<p><b>threadId:</b> <code>${l(e.threadId)}</code></p>`:""}
215
+ <p><b>${i("sessions.workingDir")}:</b> ${l(e.workingDir??"-")}</p>
216
+ <div class="actions">
217
+ ${gt(e)??`<button id="locate-btn" type="button">${i("sessions.locate")}</button>`}
218
+ <button id="history-drawer-btn" type="button">${i("sessions.history.title")}</button>
219
+ ${Zt(a)}
220
+ ${ot(e)?`<button id="restart-btn" type="button">${i("sessions.restart")}</button>`:""}
221
+ ${t?"":`<button id="lock-btn" type="button">${l(Le(e))}</button>`}
222
+ ${e.queued&&!t?`<button id="start-btn" type="button" class="primary">${i("sessions.create.start")}</button>`:""}
223
+ ${t?`<button id="resume-btn" type="button" class="primary">${i("sessions.resume")}</button>`:""}
224
+ ${t?"":`<button id="close-btn" type="button" class="contrast">${i("sessions.close")}</button>`}
225
+ <button id="land-btn" type="button">${i("sessions.land")}</button>
226
+ ${we.authed?`<button id="insight-btn" type="button">${i("sessions.insight")}</button>`:""}
227
+ </div>
228
+ <div id="land-area"></div>
229
+ <div id="insight-area"></div>
230
+ <form method="dialog"><button>${i("sessions.dismiss")}</button></form>
231
+ </article>`,f.querySelectorAll("[data-copy]").forEach(y=>{y.onclick=()=>{navigator.clipboard.writeText(y.dataset.copy??""),y.textContent=i("sessions.copied"),setTimeout(()=>{y.textContent=i("sessions.copy")},800)}});let n=f.querySelector("#locate-btn");n&&(n.onclick=()=>{Ht(e,n)});let s=f.querySelector("#history-drawer-btn");s&&(s.onclick=()=>{St(e)});let r=f.querySelector(".term-write");r&&(r.onclick=()=>{Qt(e,r)});let c=f.querySelector("#resume-btn");c&&(c.onclick=async()=>{c.disabled=!0;try{let y=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/resume`,{method:"POST"}),k=await y.json().catch(()=>({}));if(!y.ok||k.ok===!1){alert(`${i("sessions.resumeFailed")}: ${k?.error??y.status}`),c.disabled=!1;return}f.close()}catch(y){alert(`${i("sessions.resumeFailed")}: ${y}`),c.disabled=!1}});let d=f.querySelector("#restart-btn");d&&(d.onclick=async()=>{await Ye(e,d)&&f.close()});let m=f.querySelector("#close-btn");m&&(m.onclick=async()=>{await Et(e,m)&&f.close()});let g=f.querySelector("#lock-btn");g&&(g.onclick=async()=>{let y=!e.locked;if(await Ge(e,y,g)){g.textContent=Le(e);let k=f.querySelector(".drawer-status-line");k&&(k.innerHTML=`${Se(e.status)}${Ce(e)}`)}});let M=f.querySelector("#start-btn");M&&(M.onclick=async()=>{M.disabled=!0;try{let y=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/start`,{method:"POST"}),k=await y.json().catch(()=>({}));if(!y.ok||k.ok===!1){y.status!==401&&alert(`${i("sessions.create.startFailed")}: ${k?.error??y.status}`),M.disabled=!1;return}f.close()}catch(y){alert(`${i("sessions.create.startFailed")}: ${y}`),M.disabled=!1}});let x=f.querySelector("#land-btn"),N=f.querySelector("#land-area");x&&N&&(x.onclick=async()=>{x.disabled=!0,N.innerHTML=`<p>${i("sessions.landLoading")}</p>`;try{let y=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-diff`),k=await y.json().catch(()=>({}));if(!k.ok){N.innerHTML=`<p>${i("sessions.landUnavailable")}: ${l(k.error??String(y.status))}</p>`,x.disabled=!1;return}if(k.empty){N.innerHTML=`<p>${i("sessions.landEmpty")}</p>`,x.disabled=!1;return}let V=String(k.patch??""),Ne=V.slice(0,2e4)+(V.length>2e4?`
232
+ \u2026(truncated)`:"");N.innerHTML=`
233
+ <p><b>${k.files}</b> files (+${k.insertions}/-${k.deletions}) \u2192 <code>${l(String(k.workingDir??""))}</code></p>
234
+ <pre style="max-height:320px;overflow:auto;white-space:pre-wrap">${l(Ne)}</pre>
235
+ <div class="actions">
236
+ <button id="land-apply" type="button" class="primary">${i("sessions.landApply")}</button>
237
+ <button id="land-discard" type="button" class="contrast">${i("sessions.landDiscard")}</button>
238
+ </div>`;let ve=N.querySelector("#land-apply"),Be=N.querySelector("#land-discard");ve.onclick=async()=>{ve.disabled=!0,Be.disabled=!0;let I=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/apply`,{method:"POST"}),Z=await I.json().catch(()=>({}));N.innerHTML=Z.ok?`<p>\u2705 ${i("sessions.landApplied")}: ${Z.files} files (+${Z.insertions}/-${Z.deletions}) \u2192 <code>${l(String(Z.workingDir??""))}</code></p>`:`<p>\u274C ${i("sessions.landFailed")}: ${l(Z.error??String(I.status))}</p>`},Be.onclick=async()=>{await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/discard`,{method:"POST"}),N.innerHTML=`<p>\u{1F5D1} ${i("sessions.landDiscarded")}</p>`}}catch(y){N.innerHTML=`<p>${i("sessions.landUnavailable")}: ${l(String(y))}</p>`,x.disabled=!1}});let de=f.querySelector("#insight-btn"),P=f.querySelector("#insight-area");de&&P&&(de.onclick=async()=>{de.disabled=!0,P.innerHTML=`<p>${i("sessions.insightLoading")}</p>`;try{let y=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/insight?detail=spans`),k=await y.json().catch(()=>({}));!k.ok||!k.report?P.innerHTML=`<p>${i("sessions.insightUnavailable")}: ${l(String(k.error??y.status))}</p>`:P.innerHTML=Hn(k.report)}catch(y){P.innerHTML=`<p>${i("sessions.insightUnavailable")}: ${l(String(y))}</p>`}de.disabled=!1}),f.showModal()}u.addEventListener("click",e=>{let t=e.target;if(t.classList.contains("row-select")){let r=t.closest("tr[data-id]");if(!r)return;t.checked?w.add(r.dataset.id):w.delete(r.dataset.id),We(ye());return}let a=t.closest("td");if(a&&a.querySelector(".row-select"))return;let n=t.closest("tr[data-id]");if(!n)return;let s=O.sessions.get(n.dataset.id);s&&xe(s)}),q.addEventListener("click",e=>{let t=e.target,a=t.closest("button[data-move-col]");if(a){mn(a.dataset.moveCol,Number(a.dataset.dir));return}let n=t.closest(".session-card[data-id]");if(!n)return;let s=O.sessions.get(n.dataset.id);if(!s)return;let r=t.closest("button[data-action]");if(r){let c=r.dataset.action;c==="details"?xe(s):c==="write-link"?Qt(s,r):c==="locate"?Ht(s,r):c==="restart"?Ye(s,r):c==="lock"?Ge(s,!s.locked,r):c==="close"&&Et(s,r).then(d=>{d&&(w.delete(s.sessionId),h())});return}t.closest("a, button, input, label")||(w.has(s.sessionId)?w.delete(s.sessionId):w.add(s.sessionId),n.classList.toggle("selected",w.has(s.sessionId)),n.setAttribute("aria-pressed",String(w.has(s.sessionId))),We(ye().filter(c=>c.status!=="closed")))}),q.addEventListener("dragstart",e=>{let a=e.target.closest(".session-board-column > header[draggable]")?.closest(".session-board-column");a?.dataset.col&&(Y=a.dataset.col,a.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",Y)))}),q.addEventListener("dragover",e=>{if(!Y)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".session-board-column");q.querySelectorAll(".drag-over").forEach(a=>a.classList.remove("drag-over")),t&&t.dataset.col!==Y&&t.classList.add("drag-over")}),q.addEventListener("drop",e=>{if(!Y)return;e.preventDefault();let t=e.target.closest(".session-board-column"),a=Y;Y=null,t?.dataset.col&&bn(a,t.dataset.col)}),q.addEventListener("dragend",()=>{Y=null,q.querySelectorAll(".drag-over, .dragging").forEach(e=>e.classList.remove("drag-over","dragging"))}),lt.forEach(e=>{e.addEventListener("click",()=>{let t=Nt(e.dataset.view)??"board";t!==E&&(E=t,Rt(window.localStorage,E),h())})}),te.querySelectorAll("[data-groupby]").forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.groupby,a=t==="bot"?"bot":t==="team"?"team":"flow";a!==D&&(D=a,Dt(window.localStorage,a),L="",h())})}),K.addEventListener("change",()=>{X=K.value;try{window.localStorage.setItem(et,X)}catch{}L="",h()});function $e(){he!==null&&(clearTimeout(he),he=null)}T.addEventListener("click",e=>{let t=e.target,a=t.closest(".kanban-card[data-id]");if(!a)return;let n=O.sessions.get(a.dataset.id);if(!n)return;let s=t.closest("button[data-action]");if(s){s.dataset.action==="details"?xe(n):s.dataset.action==="rename"?Tt(a,n):s.dataset.action==="history"?St(n):s.dataset.action==="restart"?Ye(n,s):s.dataset.action==="lock"&&Ge(n,!n.locked,s);return}t.closest("a, button, input, label")||($e(),he=setTimeout(()=>{he=null,Mt(n)},220))}),T.addEventListener("dblclick",e=>{let t=e.target,a=t.closest(".kanban-card-title"),n=t.closest(".kanban-card[data-id]");if(!a||!n)return;$e();let s=O.sessions.get(n.dataset.id);s&&Tt(n,s)}),T.addEventListener("keydown",e=>{if(e.key!=="Enter"&&e.key!==" ")return;let t=e.target;if(!t.classList?.contains("kanban-card"))return;e.preventDefault();let a=O.sessions.get(t.dataset.id);a&&Mt(a)}),T.addEventListener("dragstart",e=>{if(D==="bot")return;let t=e.target,a=t.closest(".kanban-cluster > header[draggable]");if(a){let s=a.closest(".kanban-cluster"),r=s.closest(".kanban-column")?.dataset.col;if(!s.dataset.chat||!r)return;$e(),se=s.dataset.chat,Ie=r,s.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",`cluster:${se}`));return}let n=t.closest(".kanban-card[data-id]");n&&($e(),ne=n.dataset.id,n.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",ne)))}),T.addEventListener("dragover",e=>{if(!ne&&!se)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".kanban-column");T.querySelectorAll(".drag-over").forEach(a=>a.classList.remove("drag-over")),T.querySelectorAll(".drop-before").forEach(a=>a.classList.remove("drop-before")),t&&(t.classList.add("drag-over"),Lt(t,e.clientY)?.classList.add("drop-before"))}),T.addEventListener("drop",e=>{let t=se,a=Ie,n=ne;if(!n&&!t)return;e.preventDefault(),ne=null,se=null,Ie=null,Ct();let s=e.target.closest(".kanban-column"),r=s?.dataset.col;if(!s||!r)return;let c=Lt(s,e.clientY);if(t&&a){let P=(le.get(a)??[]).filter(I=>String(I.chatId)===t).filter(I=>!(I.status==="closed"&&r!=="done"));if(!P.length)return;let y=new Set(P.map(I=>I.sessionId)),k=(le.get(r)??[]).filter(I=>!y.has(I.sessionId)),V=c?k.findIndex(I=>I.sessionId===c.dataset.id):k.length;V<0&&(V=k.length);let Ne=V>0?k[V-1]:null,ve=V<k.length?k[V]:null,Be=nt(Ne?oe(Ne):null,ve?oe(ve):null);P.forEach((I,Z)=>{let Xe=Be+Z*.001;if(D==="team")ft(String(I.sessionId),r,Xe);else{let An={column:I.kanbanColumn,position:I.kanbanPosition};I.kanbanColumn=r,I.kanbanPosition=Xe,vt(I,r,Xe,An)}}),L="",h();return}let d=O.sessions.get(n)??ze.get(n);if(!d||d.status==="closed"&&r!=="done")return;let m=(le.get(r)??[]).filter(P=>P.sessionId!==n),g=c?m.findIndex(P=>P.sessionId===c.dataset.id):m.length;g<0&&(g=m.length);let M=g>0?m[g-1]:null,x=g<m.length?m[g]:null,N=nt(M?oe(M):null,x?oe(x):null);if(D==="team"){ft(String(d.sessionId),r,N),L="",h();return}let de={column:d.kanbanColumn,position:d.kanbanPosition};d.kanbanColumn=r,d.kanbanPosition=N,L="",h(),vt(d,r,N,de)}),T.addEventListener("dragend",()=>{ne=null,se=null,Ie=null,Ct(),L="",h()}),$.addEventListener("click",e=>{e.target===$&&$.close()}),$.addEventListener("close",()=>{$.innerHTML=""}),S.addEventListener("click",e=>{e.target===S&&S.close()}),S.addEventListener("close",()=>{S.innerHTML=""}),v.addEventListener("change",()=>{let e=ye().filter(t=>t.status!=="closed");for(let t of e)v.checked?w.add(t.sessionId):w.delete(t.sessionId);h()}),H.addEventListener("click",()=>{w.clear(),h()}),U.addEventListener("click",async()=>{let e=[...w];if(e.length===0||!confirm(i("sessions.closeBulkConfirm",{count:e.length})))return;U.disabled=!0,H.disabled=!0;let t=U.textContent,a=0,n=0,s=[...e];U.textContent=`0/${e.length}`;async function r(){for(;s.length;){let c=s.shift();try{let d=await fetch(`/api/sessions/${encodeURIComponent(c)}/close`,{method:"POST"}),m=await d.json().catch(()=>({}));(!d.ok||m?.ok===!1)&&(n+=1)}catch{n+=1}finally{a+=1,U.textContent=`${a}/${e.length}`}}}await Promise.all(Array.from({length:Math.min(6,e.length)},()=>r())),U.textContent=t,U.disabled=!1,H.disabled=!1,w.clear(),h(),n>0&&alert(`Failed: ${n}/${e.length}`)});async function At(e){let t=[...w].map(m=>O.sessions.get(m)).filter(m=>!!m&&m.status!=="closed"&&!!m.locked!==e);if(t.length===0)return;W.disabled=!0,G.disabled=!0;let a=e?W.textContent:G.textContent,n=e?W:G,s=0,r=0,c=[...t];n.textContent=`0/${t.length}`;async function d(){for(;c.length;){let m=c.shift(),g=!!m.locked;try{let M=await fetch(`/api/sessions/${encodeURIComponent(m.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:e})}),x=await M.json().catch(()=>({}));!M.ok||x?.ok===!1?(r+=1,m.locked=g):m.locked=!!x.locked}catch{r+=1,m.locked=g}finally{s+=1,n.textContent=`${s}/${t.length}`}}}await Promise.all(Array.from({length:Math.min(6,t.length)},()=>d())),n.textContent=a,ke(),h(),r>0&&alert(`${i("sessions.lockFailed")}: ${r}/${t.length}`)}W.addEventListener("click",()=>{At(!0)}),G.addEventListener("click",()=>{At(!1)}),J.addEventListener("click",e=>{if(Ee)return;let t=e.target?.closest("button[data-hours]");if(!t)return;let a=tt(t.dataset.hours);!a||a===Ae||(Ae=a,ee.textContent="",Ve())}),Q.addEventListener("click",async()=>{let e=ut(),t=mt();if(t.length===0)return;let a=on(e);if(confirm(i("sessions.idleCleanupConfirm",{count:t.length,threshold:a}))){Ee=!0,Q.disabled=!0,ee.textContent=i("sessions.idleCleanupRunning");try{let n=await fetch("/api/sessions/cleanup-idle",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({olderThanHours:e,sessionIds:t.map(r=>r.sessionId)})}),s=await n.json().catch(()=>({}));if(!n.ok){n.status!==401&&alert(`${i("sessions.idleCleanupFailed")}: ${s?.error??n.status}`),ee.textContent="";return}for(let r of s?.results??[])r?.ok&&r?.sessionId&&w.delete(String(r.sessionId));ee.textContent=i("sessions.idleCleanupDone",{closed:Number(s?.closed??0),failed:Number(s?.failed??0)}),h()}catch(n){alert(`${i("sessions.idleCleanupFailed")}: ${n}`),ee.textContent=""}finally{Ee=!1,Ve()}}}),fe.querySelectorAll("th[data-sort]").forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.sort;ge===t?re=re==="asc"?"desc":"asc":(ge=t,re=t==="spawnedAt"||t==="lastMessageAt"?"desc":"asc"),h()})}),b.addEventListener("input",h);let En=O.on(h),xt=setInterval(()=>{if(!document.body.contains(T)){clearInterval(xt);return}E==="kanban"&&D==="team"&&(L="",h())},3e4);return h(),Kt().then(h),()=>{En(),clearInterval(xt),$e(),f.close(),$.close(),S.close(),ct.close()}}var p=Ze(jt(),1);function z(o){return(0,p.jsx)("th",{"data-sort":o.sort,"data-label":o.label,children:o.label})}function Wn(){let o=Ut(),u=(0,De.useRef)(null);return(0,De.useEffect)(()=>{if(u.current)return sn(u.current)},[]),(0,p.jsxs)("section",{className:"page",ref:u,children:[(0,p.jsxs)("div",{className:"page-heading",children:[(0,p.jsxs)("div",{children:[(0,p.jsx)("p",{className:"eyebrow",children:o("nav.sessions")}),(0,p.jsx)("h1",{children:o("sessions.title")}),(0,p.jsx)("p",{children:o("sessions.subtitle")})]}),(0,p.jsxs)("div",{className:"sessions-view-controls",children:[(0,p.jsxs)("button",{type:"button",id:"create-session-btn",className:"primary create-session-btn",children:["+ ",o("sessions.create.button")]}),(0,p.jsx)("span",{id:"kanban-team-stats",className:"kanban-team-stats",hidden:!0}),(0,p.jsx)("select",{id:"kanban-team",className:"kanban-team-select","aria-label":o("sessions.kanban.groupTeam"),hidden:!0}),(0,p.jsxs)("div",{className:"segmented kanban-groupby",id:"kanban-groupby",role:"group","aria-label":o("sessions.kanban.groupBy"),hidden:!0,children:[(0,p.jsx)("button",{type:"button","data-groupby":"flow",children:o("sessions.kanban.groupFlow")}),(0,p.jsx)("button",{type:"button","data-groupby":"team",children:o("sessions.kanban.groupTeam")}),(0,p.jsx)("button",{type:"button","data-groupby":"bot",children:o("sessions.kanban.groupBot")})]}),(0,p.jsxs)("div",{className:"segmented sessions-view-toggle",role:"group","aria-label":o("sessions.viewMode"),children:[(0,p.jsx)("button",{type:"button","data-view":"kanban",children:o("sessions.viewKanban")}),(0,p.jsx)("button",{type:"button","data-view":"board",children:o("sessions.viewBoard")}),(0,p.jsx)("button",{type:"button","data-view":"table",children:o("sessions.viewTable")})]})]})]}),(0,p.jsxs)("form",{id:"filters",className:"filters sessions-filters",children:[(0,p.jsx)("input",{type:"search",name:"q",placeholder:o("sessions.search")}),(0,p.jsxs)("select",{name:"status",children:[(0,p.jsx)("option",{value:"",children:o("sessions.anyStatus")}),tn.map(b=>(0,p.jsx)("option",{value:b,children:Me(b)},b))]}),(0,p.jsxs)("select",{name:"adopt",children:[(0,p.jsx)("option",{value:"",children:o("sessions.adoptAny")}),(0,p.jsx)("option",{value:"yes",children:o("sessions.adoptYes")}),(0,p.jsx)("option",{value:"no",children:o("sessions.adoptNo")})]}),(0,p.jsx)("span",{style:{display:"contents"},dangerouslySetInnerHTML:{__html:nn()}}),(0,p.jsxs)("label",{className:"filter-toggle",children:[(0,p.jsx)("input",{type:"checkbox",name:"active",defaultChecked:!0})," ",(0,p.jsx)("span",{children:o("sessions.activeOnly")})]})]}),(0,p.jsxs)("div",{id:"idle-cleanup-bar",className:"idle-cleanup-bar",children:[(0,p.jsxs)("div",{className:"idle-cleanup-summary",children:[(0,p.jsx)("span",{className:"idle-cleanup-dot","aria-hidden":"true"}),(0,p.jsx)("span",{id:"idle-cleanup-count",className:"idle-cleanup-count"})]}),(0,p.jsxs)("div",{className:"idle-cleanup-controls",children:[(0,p.jsx)("span",{className:"idle-cleanup-label",children:o("sessions.idleCleanupOlderThan")}),(0,p.jsx)("div",{id:"idle-cleanup-threshold",className:"idle-cleanup-thresholds",role:"group","aria-label":o("sessions.idleCleanupThreshold"),children:Re.map(b=>(0,p.jsx)("button",{type:"button","data-hours":b,"aria-pressed":b===24?"true":"false",children:b===168?"7d":`${b}H`},b))}),(0,p.jsx)("button",{type:"button",id:"idle-cleanup-run",className:"contrast idle-cleanup-run",children:o("sessions.idleCleanupRun")})]}),(0,p.jsx)("span",{id:"idle-cleanup-status",className:"idle-cleanup-status","aria-live":"polite"})]}),(0,p.jsxs)("div",{id:"bulk-bar",className:"bulk-bar",hidden:!0,children:[(0,p.jsx)("span",{id:"bulk-count"}),(0,p.jsx)("button",{type:"button",id:"bulk-lock",children:o("sessions.lockSelected")}),(0,p.jsx)("button",{type:"button",id:"bulk-unlock",children:o("sessions.unlockSelected")}),(0,p.jsx)("button",{type:"button",id:"bulk-close",className:"contrast",children:o("sessions.closeSelected")}),(0,p.jsx)("button",{type:"button",id:"bulk-clear",children:o("sessions.clearSelection")})]}),(0,p.jsxs)("table",{id:"sessions-table",children:[(0,p.jsx)("thead",{children:(0,p.jsxs)("tr",{children:[(0,p.jsx)("th",{children:(0,p.jsx)("input",{type:"checkbox",id:"select-all",title:o("sessions.activeOnly")})}),(0,p.jsx)(z,{sort:"botName",label:o("sessions.bot")}),(0,p.jsx)(z,{sort:"cliId",label:o("sessions.cli")}),(0,p.jsx)(z,{sort:"status",label:o("sessions.status")}),(0,p.jsx)(z,{sort:"tokenIn",label:o("sessions.tokenIn")}),(0,p.jsx)(z,{sort:"tokenOut",label:o("sessions.tokenOut")}),(0,p.jsx)(z,{sort:"title",label:o("sessions.titleCol")}),(0,p.jsx)(z,{sort:"workingDir",label:o("sessions.workingDir")}),(0,p.jsx)(z,{sort:"spawnedAt",label:o("sessions.created")}),(0,p.jsx)(z,{sort:"lastMessageAt",label:o("sessions.last")}),(0,p.jsx)(z,{sort:"adopt",label:o("sessions.adopt")}),(0,p.jsx)("th",{children:o("sessions.actions")})]})}),(0,p.jsx)("tbody",{})]}),(0,p.jsx)("div",{id:"sessions-board",className:"sessions-board",hidden:!0}),(0,p.jsx)("div",{id:"sessions-kanban",className:"sessions-kanban",hidden:!0}),(0,p.jsx)("dialog",{id:"drawer"}),(0,p.jsx)("dialog",{id:"term-modal",className:"term-modal"}),(0,p.jsx)("dialog",{id:"history-modal",className:"history-modal"}),(0,p.jsx)("dialog",{id:"create-session-modal",className:"create-session-modal"})]})}function rs(o){return _t(o,(0,p.jsx)(Wn,{}))}export{rs as renderSessionsPage};