botmux 2.106.0 → 2.107.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 (182) hide show
  1. package/dist/bot-registry.d.ts +25 -0
  2. package/dist/bot-registry.d.ts.map +1 -1
  3. package/dist/bot-registry.js +6 -0
  4. package/dist/bot-registry.js.map +1 -1
  5. package/dist/core/command-handler.d.ts.map +1 -1
  6. package/dist/core/command-handler.js +5 -0
  7. package/dist/core/command-handler.js.map +1 -1
  8. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  9. package/dist/core/dashboard-ipc-server.js +27 -1
  10. package/dist/core/dashboard-ipc-server.js.map +1 -1
  11. package/dist/core/dashboard-rows.d.ts +6 -0
  12. package/dist/core/dashboard-rows.d.ts.map +1 -1
  13. package/dist/core/dashboard-rows.js +25 -0
  14. package/dist/core/dashboard-rows.js.map +1 -1
  15. package/dist/core/pending-response.d.ts +1 -0
  16. package/dist/core/pending-response.d.ts.map +1 -1
  17. package/dist/core/pending-response.js +1 -0
  18. package/dist/core/pending-response.js.map +1 -1
  19. package/dist/core/resource-monitor/attribution.d.ts +70 -0
  20. package/dist/core/resource-monitor/attribution.d.ts.map +1 -0
  21. package/dist/core/resource-monitor/attribution.js +222 -0
  22. package/dist/core/resource-monitor/attribution.js.map +1 -0
  23. package/dist/core/resource-monitor/procfs.d.ts +22 -0
  24. package/dist/core/resource-monitor/procfs.d.ts.map +1 -0
  25. package/dist/core/resource-monitor/procfs.js +134 -0
  26. package/dist/core/resource-monitor/procfs.js.map +1 -0
  27. package/dist/core/resource-monitor/ring-buffer.d.ts +15 -0
  28. package/dist/core/resource-monitor/ring-buffer.d.ts.map +1 -0
  29. package/dist/core/resource-monitor/ring-buffer.js +61 -0
  30. package/dist/core/resource-monitor/ring-buffer.js.map +1 -0
  31. package/dist/core/resource-monitor/runtime.d.ts +31 -0
  32. package/dist/core/resource-monitor/runtime.d.ts.map +1 -0
  33. package/dist/core/resource-monitor/runtime.js +92 -0
  34. package/dist/core/resource-monitor/runtime.js.map +1 -0
  35. package/dist/core/resource-monitor/top-selector.d.ts +18 -0
  36. package/dist/core/resource-monitor/top-selector.d.ts.map +1 -0
  37. package/dist/core/resource-monitor/top-selector.js +57 -0
  38. package/dist/core/resource-monitor/top-selector.js.map +1 -0
  39. package/dist/core/resource-monitor/types.d.ts +181 -0
  40. package/dist/core/resource-monitor/types.d.ts.map +1 -0
  41. package/dist/core/resource-monitor/types.js +2 -0
  42. package/dist/core/resource-monitor/types.js.map +1 -0
  43. package/dist/core/session-manager.d.ts +3 -1
  44. package/dist/core/session-manager.d.ts.map +1 -1
  45. package/dist/core/session-manager.js +31 -1
  46. package/dist/core/session-manager.js.map +1 -1
  47. package/dist/core/types.d.ts +1 -0
  48. package/dist/core/types.d.ts.map +1 -1
  49. package/dist/core/types.js.map +1 -1
  50. package/dist/daemon.d.ts +1 -1
  51. package/dist/daemon.d.ts.map +1 -1
  52. package/dist/daemon.js +44 -22
  53. package/dist/daemon.js.map +1 -1
  54. package/dist/dashboard/bot-payload.d.ts +1 -0
  55. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  56. package/dist/dashboard/bot-payload.js +1 -0
  57. package/dist/dashboard/bot-payload.js.map +1 -1
  58. package/dist/dashboard/resource-monitor-service.d.ts +56 -0
  59. package/dist/dashboard/resource-monitor-service.d.ts.map +1 -0
  60. package/dist/dashboard/resource-monitor-service.js +446 -0
  61. package/dist/dashboard/resource-monitor-service.js.map +1 -0
  62. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  63. package/dist/dashboard/web/bot-defaults.js +160 -1
  64. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  65. package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
  66. package/dist/dashboard/web/dashboard-routes.js +18 -0
  67. package/dist/dashboard/web/dashboard-routes.js.map +1 -1
  68. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  69. package/dist/dashboard/web/i18n.js +274 -2
  70. package/dist/dashboard/web/i18n.js.map +1 -1
  71. package/dist/dashboard/web/monitor-room-store.d.ts +20 -0
  72. package/dist/dashboard/web/monitor-room-store.d.ts.map +1 -0
  73. package/dist/dashboard/web/monitor-room-store.js +80 -0
  74. package/dist/dashboard/web/monitor-room-store.js.map +1 -0
  75. package/dist/dashboard/web/monitor-room.d.ts +31 -0
  76. package/dist/dashboard/web/monitor-room.d.ts.map +1 -0
  77. package/dist/dashboard/web/monitor-room.js +393 -0
  78. package/dist/dashboard/web/monitor-room.js.map +1 -0
  79. package/dist/dashboard/web/monitoring-page.d.ts +155 -0
  80. package/dist/dashboard/web/monitoring-page.d.ts.map +1 -0
  81. package/dist/dashboard/web/monitoring-page.js +189 -0
  82. package/dist/dashboard/web/monitoring-page.js.map +1 -0
  83. package/dist/dashboard/web/overview-page.d.ts.map +1 -1
  84. package/dist/dashboard/web/overview-page.js +108 -1
  85. package/dist/dashboard/web/overview-page.js.map +1 -1
  86. package/dist/dashboard/web/preferences.d.ts +3 -0
  87. package/dist/dashboard/web/preferences.d.ts.map +1 -1
  88. package/dist/dashboard/web/preferences.js +18 -0
  89. package/dist/dashboard/web/preferences.js.map +1 -1
  90. package/dist/dashboard/web/session-terminal.d.ts +7 -0
  91. package/dist/dashboard/web/session-terminal.d.ts.map +1 -0
  92. package/dist/dashboard/web/session-terminal.js +17 -0
  93. package/dist/dashboard/web/session-terminal.js.map +1 -0
  94. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  95. package/dist/dashboard/web/sessions-page.js +2 -1
  96. package/dist/dashboard/web/sessions-page.js.map +1 -1
  97. package/dist/dashboard/web/sessions.d.ts +4 -0
  98. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  99. package/dist/dashboard/web/sessions.js +98 -17
  100. package/dist/dashboard/web/sessions.js.map +1 -1
  101. package/dist/dashboard/web/skills-page.js +1 -1
  102. package/dist/dashboard/web/skills-page.js.map +1 -1
  103. package/dist/dashboard/web/substitute-targets.d.ts +30 -0
  104. package/dist/dashboard/web/substitute-targets.d.ts.map +1 -0
  105. package/dist/dashboard/web/substitute-targets.js +99 -0
  106. package/dist/dashboard/web/substitute-targets.js.map +1 -0
  107. package/dist/dashboard/web/ui.d.ts +1 -1
  108. package/dist/dashboard/web/ui.d.ts.map +1 -1
  109. package/dist/dashboard/web/ui.js +4 -1
  110. package/dist/dashboard/web/ui.js.map +1 -1
  111. package/dist/dashboard-web/app.js +3 -3
  112. package/dist/dashboard-web/chunks/bot-defaults-page-OCIHPGEU.js +438 -0
  113. package/dist/dashboard-web/chunks/chunk-3N2PPQVD.js +1 -0
  114. package/dist/dashboard-web/chunks/chunk-3UJYRR2Q.js +37 -0
  115. package/dist/dashboard-web/chunks/{chunk-VFCACTRF.js → chunk-PE6W3C2C.js} +1 -1
  116. package/dist/dashboard-web/chunks/chunk-QW54DWU3.js +325 -0
  117. package/dist/dashboard-web/chunks/{connectors-VDOAKUW3.js → connectors-IGETYWCP.js} +1 -1
  118. package/dist/dashboard-web/chunks/{groups-page-CX5AN4XG.js → groups-page-MYBS4ZYJ.js} +1 -1
  119. package/dist/dashboard-web/chunks/{insights-page-DOMRL4S6.js → insights-page-UPA32V2S.js} +1 -1
  120. package/dist/dashboard-web/chunks/monitor-room-RFX4HPS5.js +51 -0
  121. package/dist/dashboard-web/chunks/monitoring-page-7T3BESZ2.js +1 -0
  122. package/dist/dashboard-web/chunks/overview-page-LJSBCQW4.js +1 -0
  123. package/dist/dashboard-web/chunks/{roles-page-3FEAH6S4.js → roles-page-ESURTVQH.js} +1 -1
  124. package/dist/dashboard-web/chunks/{schedules-CTQEA7IE.js → schedules-LML2ISOT.js} +1 -1
  125. package/dist/dashboard-web/chunks/sessions-YB73XOTU.js +1 -0
  126. package/dist/dashboard-web/chunks/sessions-page-MCO5QR7Z.js +1 -0
  127. package/dist/dashboard-web/chunks/{settings-page-R23I3IZG.js → settings-page-OSDKNVS3.js} +1 -1
  128. package/dist/dashboard-web/chunks/skills-page-PXBZJ6P6.js +2 -0
  129. package/dist/dashboard-web/chunks/{team-federation-page-ZKL3YMGN.js → team-federation-page-TTPVHFPX.js} +1 -1
  130. package/dist/dashboard-web/chunks/{workflows-4BYQQBFP.js → workflows-FCPM4S4D.js} +1 -1
  131. package/dist/dashboard-web/index.html +2 -1
  132. package/dist/dashboard-web/style.css +818 -8
  133. package/dist/dashboard.js +37 -0
  134. package/dist/dashboard.js.map +1 -1
  135. package/dist/i18n/en.d.ts.map +1 -1
  136. package/dist/i18n/en.js +8 -0
  137. package/dist/i18n/en.js.map +1 -1
  138. package/dist/i18n/zh.d.ts.map +1 -1
  139. package/dist/i18n/zh.js +8 -0
  140. package/dist/i18n/zh.js.map +1 -1
  141. package/dist/im/lark/card-builder.d.ts.map +1 -1
  142. package/dist/im/lark/card-builder.js +18 -0
  143. package/dist/im/lark/card-builder.js.map +1 -1
  144. package/dist/im/lark/card-handler.d.ts.map +1 -1
  145. package/dist/im/lark/card-handler.js +12 -2
  146. package/dist/im/lark/card-handler.js.map +1 -1
  147. package/dist/im/lark/event-dispatcher.d.ts +3 -0
  148. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  149. package/dist/im/lark/event-dispatcher.js +59 -2
  150. package/dist/im/lark/event-dispatcher.js.map +1 -1
  151. package/dist/im/lark/message-parser.d.ts +35 -0
  152. package/dist/im/lark/message-parser.d.ts.map +1 -1
  153. package/dist/im/lark/message-parser.js +56 -0
  154. package/dist/im/lark/message-parser.js.map +1 -1
  155. package/dist/im/lark/substitute-command.d.ts +2 -0
  156. package/dist/im/lark/substitute-command.d.ts.map +1 -0
  157. package/dist/im/lark/substitute-command.js +51 -0
  158. package/dist/im/lark/substitute-command.js.map +1 -0
  159. package/dist/services/substitute-chat-toggle-store.d.ts +3 -0
  160. package/dist/services/substitute-chat-toggle-store.d.ts.map +1 -0
  161. package/dist/services/substitute-chat-toggle-store.js +58 -0
  162. package/dist/services/substitute-chat-toggle-store.js.map +1 -0
  163. package/dist/services/substitute-mode-normalize.d.ts +22 -0
  164. package/dist/services/substitute-mode-normalize.d.ts.map +1 -0
  165. package/dist/services/substitute-mode-normalize.js +56 -0
  166. package/dist/services/substitute-mode-normalize.js.map +1 -0
  167. package/dist/services/substitute-mode-store.d.ts +50 -0
  168. package/dist/services/substitute-mode-store.d.ts.map +1 -0
  169. package/dist/services/substitute-mode-store.js +115 -0
  170. package/dist/services/substitute-mode-store.js.map +1 -0
  171. package/dist/types.d.ts +14 -0
  172. package/dist/types.d.ts.map +1 -1
  173. package/dist/worker.js +20 -1
  174. package/dist/worker.js.map +1 -1
  175. package/package.json +1 -1
  176. package/dist/dashboard-web/chunks/bot-defaults-page-3OIY7N76.js +0 -409
  177. package/dist/dashboard-web/chunks/chunk-BNEXMNQD.js +0 -31
  178. package/dist/dashboard-web/chunks/chunk-DKKOGZCG.js +0 -317
  179. package/dist/dashboard-web/chunks/overview-page-AZBAXVZ7.js +0 -1
  180. package/dist/dashboard-web/chunks/sessions-LVZCXO2Z.js +0 -1
  181. package/dist/dashboard-web/chunks/sessions-page-NHBJDSBC.js +0 -1
  182. package/dist/dashboard-web/chunks/skills-page-VUG3EPWX.js +0 -2
@@ -1,317 +0,0 @@
1
- import{a as O}from"./chunk-LXIK7OUJ.js";import{b as Et,c as Ht,d as At,e as Je,f as xt,g as Ye,h as Bt,i as Rt,l as ve,m as s,n as l,o as de,p as se,q as Nt,r as Pt,t as j,u as ue,v as K,y as Be}from"./chunk-BNEXMNQD.js";var Dt=["backlog","todo","in_progress","in_review","done"];function Ot(i){return typeof i=="string"&&Dt.includes(i)?i:null}function _t(i){if(i.status==="closed")return"done";let u=Ot(i.kanbanColumn);return u||(i.pendingRepo||i.tuiPromptActive||i.agentAttention||i.status==="limited"?"in_review":i.status==="starting"||i.status==="working"||i.status==="analyzing"||i.status==="active"?"in_progress":"todo")}var Sn=1e15;function ae(i){if(typeof i.kanbanPosition=="number"&&Number.isFinite(i.kanbanPosition))return i.kanbanPosition;let u=typeof i.lastMessageAt=="number"&&Number.isFinite(i.lastMessageAt)?i.lastMessageAt:0;return Sn-u}function Xe(i,u){return i!==null&&u!==null?(i+u)/2:i!==null?i+1024:u!==null?u-1024:1024}var Ze=[24,72,168],Cn=new Set(Ze);function Qe(i){let u=i==="7d"?168:Number(i);return!Number.isFinite(u)||!Cn.has(u)?null:u}function Tn(i){let u=Number(i);return Number.isFinite(u)&&u>0?u:null}function Ln(i,u=Date.now()){return u-i*60*60*1e3}function In(i,u,b=Date.now()){if(!i.sessionId||i.status!=="idle"||i.locked||i.pendingRepo||i.tuiPromptActive||i.agentAttention)return!1;let m=Tn(i.lastMessageAt);return m!==null&&m<Ln(u,b)}function qt(i,u,b=Date.now()){return i.filter(m=>In(m,u,b))}var Kt={1:"claude-code",2:"aiden",3:"coco",4:"codex",5:"cursor",6:"gemini",7:"opencode",8:"antigravity",9:"mtr",10:"hermes",11:"codex-app",12:"mira",13:"seed",14:"traex",15:"pi",16:"copilot",17:"oh-my-pi",18:"relay",19:"mir",20:"kimi",21:"genius"},Gn=new Set(Object.values(Kt)),Mn={"claude-code":"Claude",aiden:"Aiden",coco:"CoCo",codex:"Codex",cursor:"Cursor",gemini:"Gemini",genius:"Genius",opencode:"OpenCode",antigravity:"Antigravity",mtr:"MTR",hermes:"Hermes","codex-app":"Codex App",mira:"Mira",seed:"Seed",traex:"TRAE",pi:"Pi",copilot:"Copilot","oh-my-pi":"Oh My Pi",relay:"Relay",mir:"Mir CLI",kimi:"Kimi"},Ut=Object.values(Kt).map(i=>({id:i,label:Mn[i]??i}));function F(i,u){return`<th data-sort="${i}" data-label="${l(u)}">${l(u)}</th>`}function st(i){return typeof i=="number"&&Number.isFinite(i)?i:null}function jt(i){let u=st(i);return u===null?"-":u.toLocaleString("en-US")}var Jt=[...Ut.map(i=>i.id),"unknown"],Ft=[{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"}],zt=[{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"}],et=50;function En(i){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(i){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 Re(i){return String(i??"unknown").toLowerCase().replace(/[^a-z0-9_-]/g,"-")}var Hn=["starting","working","idle","dormant","analyzing","active","limited","closed"];function Ne(i){let u=String(i??"unknown"),b=`sessions.status.${u}`,m=s(b);return m===b?u:m}function we(i){let u=String(i??"unknown");return`<span class="status status-${l(Re(u))}">${l(Ne(u))}</span>`}function Wt(i){let u=String(i??"").trim();return u?u.replace(/\\/g,"/").split("/").filter(Boolean).at(-1)??u:"-"}function tt(i){if(!i.webPort)return null;if(location.protocol==="https:")return i.proxyPort?`${location.origin}/s/${encodeURIComponent(i.sessionId)}`:null;let u=i.proxyPort??i.webPort,b=i.proxyPort?`/s/${encodeURIComponent(i.sessionId)}`:"";return`http://${location.hostname}:${u}${b}`}var T={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 Se(i,u,b,m=""){return`<button type="button" class="card-act${m?" "+m:""}" data-action="${i}" title="${l(b)}" aria-label="${l(b)}">${u}</button>`}function Ce(i){return i.locked?s("sessions.unlock"):s("sessions.lock")}function Te(i){return i.locked?`<span class="session-lock-badge" title="${l(s("sessions.locked"))}">${l(s("sessions.locked"))}</span>`:""}function Gt(i){if(!i)return"";let u=`<a class="term-btn term-open" href="${l(i)}" target="_blank" rel="noopener" title="${l(s("sessions.openTerminal"))}" aria-label="${l(s("sessions.openTerminal"))}">${T.terminal}</a>`;if(!ve.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(s("sessions.writeLinkHint"))}" aria-label="${l(s("sessions.writeLink"))}">${T.key}</button>`;return`<span class="term-pill">${u}${b}</span>`}async function Vt(i,u){let b=window.open("about:blank","_blank");b&&(b.opener=null),u&&(u.disabled=!0);try{let m=await fetch(`/api/sessions/${encodeURIComponent(i.sessionId)}/write-link`),$=await m.json().catch(()=>({}));if(!m.ok||$?.ok===!1||!$?.url){b?.close(),m.status!==401&&alert(`${s("sessions.writeLinkFail")}: ${$?.error??m.status}`);return}b?b.location.href=$.url:window.open($.url,"_blank","noopener")}catch(m){b?.close(),alert(`${s("sessions.writeLinkFail")}: ${m}`)}finally{u&&(u.disabled=!1)}}function An(i){return i.status==="closed"?null:i.pendingRepo||i.tuiPromptActive||i.agentAttention||i.status==="limited"?"needs-you":i.status==="starting"?"starting":i.status==="working"||i.status==="analyzing"||i.status==="active"?"working":(i.status==="dormant","idle")}function xn(){return`<details class="filter-cli">
2
- <summary>${s("sessions.cli")} \xB7 <b id="cli-filter-count">${s("common.all")}</b></summary>
3
- <div class="filter-cli-pop" role="group" aria-label="${s("sessions.cli")}">
4
- ${Jt.map(i=>`
5
- <label class="filter-check">
6
- <input type="checkbox" name="cli" value="${l(i)}" checked>
7
- <span>${l(i)}</span>
8
- </label>
9
- `).join("")}
10
- </div>
11
- </details>`}function Bn(i){let u=String(i.status??"unknown"),b=String(i.cliId??"unknown"),m=ve.locale==="zh"?"\uFF1A":": ";return[s("sessions.restartConfirmIntro"),"",`${s("sessions.restartConfirmStatus")}${m}${Ne(u)}`,`${s("sessions.restartConfirmCli")}${m}${b}`,"",s("sessions.restartConfirmQuestion")].join(`
12
- `)}function nt(i){return i.status!=="closed"&&!i.adopt&&!i.pendingRepo}function Rn(){return`<section class="page">
13
- <div class="page-heading">
14
- <div>
15
- <p class="eyebrow">${s("nav.sessions")}</p>
16
- <h1>${s("sessions.title")}</h1>
17
- <p>${s("sessions.subtitle")}</p>
18
- </div>
19
- <div class="sessions-view-controls">
20
- <span id="kanban-team-stats" class="kanban-team-stats" hidden></span>
21
- <select id="kanban-team" class="kanban-team-select" aria-label="${s("sessions.kanban.groupTeam")}" hidden></select>
22
- <div class="segmented kanban-groupby" id="kanban-groupby" role="group" aria-label="${s("sessions.kanban.groupBy")}" hidden>
23
- <button type="button" data-groupby="flow">${s("sessions.kanban.groupFlow")}</button>
24
- <button type="button" data-groupby="team">${s("sessions.kanban.groupTeam")}</button>
25
- <button type="button" data-groupby="bot">${s("sessions.kanban.groupBot")}</button>
26
- </div>
27
- <div class="segmented sessions-view-toggle" role="group" aria-label="${s("sessions.viewMode")}">
28
- <button type="button" data-view="kanban">${s("sessions.viewKanban")}</button>
29
- <button type="button" data-view="board">${s("sessions.viewBoard")}</button>
30
- <button type="button" data-view="table">${s("sessions.viewTable")}</button>
31
- </div>
32
- </div>
33
- </div>
34
- <form id="filters" class="filters sessions-filters">
35
- <input type="search" name="q" placeholder="${s("sessions.search")}" />
36
- <select name="status">
37
- <option value="">${s("sessions.anyStatus")}</option>
38
- ${Hn.map(i=>`<option value="${l(i)}">${l(Ne(i))}</option>`).join("")}
39
- </select>
40
- <select name="adopt">
41
- <option value="">${s("sessions.adoptAny")}</option>
42
- <option value="yes">${s("sessions.adoptYes")}</option>
43
- <option value="no">${s("sessions.adoptNo")}</option>
44
- </select>
45
- ${xn()}
46
- <label class="filter-toggle"><input type="checkbox" name="active" checked> <span>${s("sessions.activeOnly")}</span></label>
47
- </form>
48
- <div id="idle-cleanup-bar" class="idle-cleanup-bar">
49
- <div class="idle-cleanup-summary">
50
- <span class="idle-cleanup-dot" aria-hidden="true"></span>
51
- <span id="idle-cleanup-count" class="idle-cleanup-count"></span>
52
- </div>
53
- <div class="idle-cleanup-controls">
54
- <span class="idle-cleanup-label">${s("sessions.idleCleanupOlderThan")}</span>
55
- <div id="idle-cleanup-threshold" class="idle-cleanup-thresholds" role="group" aria-label="${s("sessions.idleCleanupThreshold")}">
56
- ${Ze.map(i=>`<button type="button" data-hours="${i}" aria-pressed="${i===24?"true":"false"}">${i===168?"7d":`${i}H`}</button>`).join("")}
57
- </div>
58
- <button type="button" id="idle-cleanup-run" class="contrast idle-cleanup-run">${s("sessions.idleCleanupRun")}</button>
59
- </div>
60
- <span id="idle-cleanup-status" class="idle-cleanup-status" aria-live="polite"></span>
61
- </div>
62
- <div id="bulk-bar" class="bulk-bar" hidden>
63
- <span id="bulk-count"></span>
64
- <button type="button" id="bulk-lock">${s("sessions.lockSelected")}</button>
65
- <button type="button" id="bulk-unlock">${s("sessions.unlockSelected")}</button>
66
- <button type="button" id="bulk-close" class="contrast">${s("sessions.closeSelected")}</button>
67
- <button type="button" id="bulk-clear">${s("sessions.clearSelection")}</button>
68
- </div>
69
- <table id="sessions-table">
70
- <thead><tr>
71
- <th><input type="checkbox" id="select-all" title="${s("sessions.activeOnly")}"></th>
72
- ${F("botName",s("sessions.bot"))}
73
- ${F("cliId",s("sessions.cli"))}
74
- ${F("status",s("sessions.status"))}
75
- ${F("tokenIn",s("sessions.tokenIn"))}
76
- ${F("tokenOut",s("sessions.tokenOut"))}
77
- ${F("title",s("sessions.titleCol"))}
78
- ${F("workingDir",s("sessions.workingDir"))}
79
- ${F("spawnedAt",s("sessions.created"))}
80
- ${F("lastMessageAt",s("sessions.last"))}
81
- ${F("adopt",s("sessions.adopt"))}
82
- <th>${s("sessions.actions")}</th>
83
- </tr></thead>
84
- <tbody></tbody>
85
- </table>
86
- <div id="sessions-board" class="sessions-board" hidden></div>
87
- <div id="sessions-kanban" class="sessions-kanban" hidden></div>
88
- <dialog id="drawer"></dialog>
89
- <dialog id="term-modal" class="term-modal"></dialog>
90
- <dialog id="history-modal" class="history-modal"></dialog>
91
- </section>`}async function Nn(){try{let i=await fetch("/api/groups");if(!i.ok)return[];let u=await i.json();return(Array.isArray(u?.bots)?u.bots:[]).filter(m=>m&&typeof m.larkAppId=="string").map(m=>({larkAppId:m.larkAppId,botName:typeof m.botName=="string"&&m.botName?m.botName:m.larkAppId}))}catch{return[]}}function Pn(i){let u=i.map(b=>`
92
- <label class="cs-bot"><input type="checkbox" name="bot" value="${l(b.larkAppId)}"> <span>${l(b.botName)}</span></label>`).join("");return`
93
- <article class="cs-card">
94
- <header><h3>${s("sessions.create.title")}</h3></header>
95
- <form id="cs-form">
96
- <label class="form-row">
97
- <span>${s("sessions.create.content")}</span>
98
- <textarea name="content" rows="5" placeholder="${l(s("sessions.create.contentPlaceholder"))}" required></textarea>
99
- </label>
100
- <fieldset class="cs-bots">
101
- <legend>${s("sessions.create.bots")}</legend>
102
- ${u||`<p class="cs-empty">${s("sessions.create.noBots")}</p>`}
103
- </fieldset>
104
- <fieldset class="cs-mode">
105
- <legend>${s("sessions.create.mode")}</legend>
106
- <label><input type="radio" name="mode" value="lead" checked> ${s("sessions.create.modeLead")}</label>
107
- <label><input type="radio" name="mode" value="all"> ${s("sessions.create.modeAll")}</label>
108
- <small>${s("sessions.create.modeHelp")}</small>
109
- </fieldset>
110
- <div class="cs-lead-row form-row" hidden>
111
- <span>${s("sessions.create.lead")}</span>
112
- <select name="lead"></select>
113
- <small>${s("sessions.create.leadHelp")}</small>
114
- </div>
115
- <fieldset class="cs-column">
116
- <legend>${s("sessions.create.column")}</legend>
117
- <label><input type="radio" name="column" value="in_progress" checked> ${s("sessions.create.columnInProgress")}</label>
118
- <label><input type="radio" name="column" value="backlog"> ${s("sessions.create.columnBacklog")}</label>
119
- <small>${s("sessions.create.columnHelp")}</small>
120
- </fieldset>
121
- <details class="cs-advanced">
122
- <summary>${s("sessions.create.advanced")}</summary>
123
- <label class="form-row">
124
- <span>${s("sessions.create.groupName")}</span>
125
- <input type="text" name="name" maxlength="60" placeholder="${l(s("sessions.create.groupNamePlaceholder"))}">
126
- </label>
127
- <label class="form-row">
128
- <span>${s("sessions.create.workingDir")}</span>
129
- <input type="text" name="bindWorkingDir" placeholder="e.g. ~/projects/foo">
130
- <small>${s("sessions.create.workingDirHelp")}</small>
131
- </label>
132
- </details>
133
- <div class="actions cs-actions">
134
- <button type="submit" class="primary">${s("sessions.create.submit")}</button>
135
- <button type="button" id="cs-cancel">${s("sessions.create.cancel")}</button>
136
- </div>
137
- </form>
138
- </article>`}async function ts(){let i=document.getElementById("create-session-modal");if(!i)return;let u=await Nn();if(u.length===0){alert(s("sessions.create.noBots"));return}i.innerHTML=Pn(u),i.showModal(),Dn(i,u)}function Dn(i,u){let b=i.querySelector("#cs-form"),m=i.querySelector(".cs-lead-row"),$=i.querySelector("select[name=lead]"),pe=M=>u.find(N=>N.larkAppId===M)?.botName??M,oe=()=>Array.from(b.querySelectorAll("input[name=bot]:checked")).map(M=>M.value),z=()=>b.querySelector("input[name=mode]:checked")?.value??"all";function G(){let M=oe(),N=$.value;if(M.length===0){$.innerHTML=`<option value="" disabled selected>${l(s("sessions.create.leadPickFirst"))}</option>`,$.disabled=!0;return}$.disabled=!1,$.innerHTML=M.map(V=>`<option value="${l(V)}">${l(pe(V))}</option>`).join(""),M.includes(N)&&($.value=N)}function U(){z()==="lead"?(m.hidden=!1,G()):m.hidden=!0}b.querySelectorAll("input[name=mode]").forEach(M=>M.addEventListener("change",U)),b.querySelectorAll("input[name=bot]").forEach(M=>M.addEventListener("change",()=>{z()==="lead"&&G()})),U(),i.querySelector("#cs-cancel").onclick=()=>i.close(),b.onsubmit=async M=>{M.preventDefault();let N=new FormData(b),V=(N.get("content")??"").trim(),Z=oe(),me=z(),Q=N.get("column")??"in_progress",fe=(N.get("name")??"").trim(),P=(N.get("bindWorkingDir")??"").trim(),S=N.get("lead")??"";if(!V){alert(s("sessions.create.errContent"));return}if(Z.length===0){alert(s("sessions.create.errNoBot"));return}if(me==="lead"&&(!S||!Z.includes(S))){alert(s("sessions.create.errLead"));return}let k=b.querySelector("button[type=submit]");k&&(k.disabled=!0,k.textContent=s("sessions.create.submitting"));try{let w=await fetch("/api/sessions/create",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({content:V,larkAppIds:Z,mode:me,column:Q,leadLarkAppId:me==="lead"?S:void 0,name:fe||void 0,bindWorkingDir:P||void 0})}),ee=await w.json().catch(()=>null);w.ok&&ee?.ok?On(i,ee):w.status!==401&&(alert(`${s("sessions.create.failed")}: ${ee?.error??w.status}`),k&&(k.disabled=!1,k.textContent=s("sessions.create.submit")))}catch(w){alert(`${s("sessions.create.failed")}: ${w}`),k&&(k.disabled=!1,k.textContent=s("sessions.create.submit"))}}}function On(i,u){let b=typeof u.shareLink=="string"&&u.shareLink?u.shareLink:"",m=Array.isArray(u.failed)?u.failed.length:0,$=Array.isArray(u.spawned)?u.spawned.length:0,pe=u.column==="backlog"?s("sessions.create.doneBacklog"):s("sessions.create.doneInProgress"),oe=m>0?`<p class="cs-warn">${s("sessions.create.partialFail",{n:String(m)})}</p>`:"";i.innerHTML=`
139
- <article class="cs-card">
140
- <header><h3>${s("sessions.create.doneTitle")}</h3></header>
141
- <p>${l(pe)}\uFF08${$}\uFF09</p>
142
- ${oe}
143
- ${b?`<p><a href="${l(b)}" target="_blank" rel="noopener">${s("sessions.create.openChat")}</a></p>`:""}
144
- <div class="actions"><button type="button" id="cs-done" class="primary">${s("sessions.create.close")}</button></div>
145
- </article>`,i.querySelector("#cs-done").onclick=()=>i.close()}function ns(i){return i.innerHTML=Rn(),_n(i)}function _n(i){let u=i.querySelector("#sessions-table tbody"),b=i.querySelector("#filters"),m=i.querySelector("#drawer"),$=i.querySelector("#select-all"),pe=i.querySelector("#bulk-bar"),oe=i.querySelector("#bulk-count"),z=i.querySelector("#bulk-lock"),G=i.querySelector("#bulk-unlock"),U=i.querySelector("#bulk-close"),M=i.querySelector("#bulk-clear"),N=i.querySelector("#idle-cleanup-bar"),V=i.querySelector("#idle-cleanup-threshold"),Z=i.querySelector("#idle-cleanup-run"),me=i.querySelector("#idle-cleanup-count"),Q=i.querySelector("#idle-cleanup-status"),fe=i.querySelector("#sessions-table"),P=i.querySelector("#sessions-board"),S=i.querySelector("#sessions-kanban"),k=i.querySelector("#term-modal"),w=i.querySelector("#history-modal"),ee=i.querySelector("#kanban-groupby"),_=i.querySelector("#kanban-team"),at=i.querySelector("#kanban-team-stats"),ot=i.querySelectorAll(".sessions-view-toggle [data-view]"),v=new Set,be="lastMessageAt",ie="desc",E=Ht(window.localStorage),q=At(window.localStorage),J=null,Pe="",De="",C="",it=!1,te=null,Oe=!1,ge=null,re=new Map,D=Bt(window.localStorage),ne=null,Le=null,B=[],_e=null,Ie=!1,qe=!1,Y=(()=>{try{return window.localStorage.getItem(Ye)??""}catch{return""}})(),Me=!1,Ee=24;function rt(){return Ee}function Yt(e){return e===168?"7d":`${e}H`}function lt(e){let t=new Set;if(!e)return t;for(let o of e.groupChats)t.add(o);if(_e)for(let[o,n]of _e){if(t.has(o))continue;let a=!1;for(let r of e.botIds)if(n.botIds.has(r)){a=!0;break}if(a){for(let r of n.observedNames)if(e.botNames.has(r)){t.add(o);break}}}return t}function Xt(){let e=he();if(E==="kanban"&&D==="team"){let t=B.find(n=>n.key===Y)??B[0],o=lt(t);return e.filter(n=>o.has(String(n.chatId)))}return e}function ct(){return qt(Xt(),rt())}function Zt(){V.querySelectorAll("button[data-hours]").forEach(e=>{let t=Qe(e.dataset.hours)===Ee;e.classList.toggle("active",t),e.setAttribute("aria-pressed",t?"true":"false")})}async function Qt(){if(!(qe||Ie)){qe=!0;try{let[e,t,o]=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(o?.chats)&&(_e=new Map(o.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))}),a=[];for(let r of e?.teams??[]){let{ids:c,names:d}=n(r.bots??[]);a.push({key:`local:${r.teamId}`,label:r.isDefault?s("team.myHostedTeam"):String(r.name??r.teamId),botIds:c,botNames:d,groupChats:new Set((r.groupChatIds??[]).map(p=>String(p)))})}for(let r of t?.memberships??[]){let{ids:c,names:d}=n(r.roster?.bots??[]);a.push({key:`${r.hubUrl}::${r.teamId}`,label:String(r.teamName??r.teamId??r.hubUrl),botIds:c,botNames:d,groupChats:new Set})}B=a}finally{Ie=!0,qe=!1}B.length&&!B.some(e=>e.key===Y)&&(Y=B[0].key),delete _.dataset.loading,_.disabled=B.length===0,_.innerHTML=B.length?B.map(e=>`<option value="${l(e.key)}"${e.key===Y?" selected":""}>${l(e.label)}</option>`).join(""):`<option value="">${l(s("sessions.kanban.noTeam"))}</option>`,C="",g()}}let H=null,le="",dt=0,Ke=!1,Ue=new Map;async function en(e){let t=le===e.key&&Date.now()-dt<3e4;if(!(Ke||t)){Ke=!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)}`,a=await fetch(n),r=await a.json().catch(()=>({}));if(!a.ok||r?.ok===!1)return;let c=typeof r.deploymentId=="string"?r.deploymentId:null,d=[];Ue=new Map;for(let p of Array.isArray(r.reports)?r.reports:[])if(!(c&&p.deploymentId===c))for(let f of Array.isArray(p.sessions)?p.sessions:[]){let L={...f,remoteDeployment:p.deploymentName||p.deploymentId};d.push(L),Ue.set(String(f.sessionId),L)}H={board:r.board&&typeof r.board=="object"?r.board:{},remoteRows:d},le=e.key,dt=Date.now(),C="",g()}catch{}finally{Ke=!1}}}async function tn(e,t,o,n,a){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:o,position:n})}):await fetch("/api/team/remote-board-move",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:e,sessionId:t,column:o,position:n})}),d=await c.json().catch(()=>({}));(!c.ok||d?.ok===!1)&&(H&&(a?H.board[t]=a:delete H.board[t]),C="",g(),c.status!==401&&alert(`${s("sessions.kanban.moveFail")}: ${d?.error??c.status}`))}catch(r){H&&(a?H.board[t]=a:delete H.board[t]),C="",g(),alert(`${s("sessions.kanban.moveFail")}: ${r}`)}}function ut(e,t,o){let n=B.find(r=>r.key===Y)??B[0];if(!n)return;(!H||le!==n.key)&&(H={board:{},remoteRows:H?.remoteRows??[]},le=n.key);let a=H.board[e];H.board[e]={column:t,position:o},tn(n.key,e,t,o,a)}function nn(){return q.map(e=>Ft.find(t=>t.id===e)).filter(e=>!!e)}function sn(e,t){let o=q.indexOf(e),n=o+t;if(o<0||n<0||n>=q.length)return;let a=[...q];a.splice(o,1),a.splice(n,0,e),q=a,Je(window.localStorage,q),g()}function an(e,t){if(e===t)return;let o=q.indexOf(e),n=q.indexOf(t);if(o<0||n<0)return;let a=[...q];a.splice(o,1),a.splice(n,0,e),q=a,Je(window.localStorage,q),g()}function on(e){let t=e.status==="closed",o=v.has(e.sessionId)?"checked":"";return`<tr data-id="${l(e.sessionId)}">
146
- <td><input type="checkbox" class="row-select" ${o} ${t?"disabled":""}></td>
147
- <td>${l(j(e))}</td>
148
- <td><span class="badge cli-${Re(e.cliId)}">${l(e.cliId??"unknown")}</span></td>
149
- <td>${we(e.status)}${Te(e)}</td>
150
- <td class="token-cell">${jt(e.tokenUsage?.in)}</td>
151
- <td class="token-cell">${jt(e.tokenUsage?.out)}</td>
152
- <td title="${l(String(e.title??""))}">${l(K(e.title??"").slice(0,48))}</td>
153
- <td title="${l(e.workingDir??"")}">${l((e.workingDir??"").slice(-34))}</td>
154
- <td>${de(e.spawnedAt)}</td>
155
- <td>${de(e.lastMessageAt)}</td>
156
- <td>${e.adopt?'<span class="badge">adopt</span>':""}</td>
157
- <td><button class="open" type="button">${s("sessions.details")}</button></td>
158
- </tr>`}function pt(e){if(e.scope!=="chat"||!e.feishuChatLink)return null;let t=s("sessions.openChat");return`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(t)}" aria-label="${l(t)}">${T.feishu}</a>`}function mt(e){return e.agentAttention?.reason?e.agentAttention.reason:e.agentAttention?s("sessions.board.signalAgent"):e.pendingRepo?s("sessions.board.signalRepo"):e.tuiPromptActive?s("sessions.board.signalPrompt"):e.status==="limited"?s("sessions.board.signalLimited"):""}function rn(e){let t=v.has(e.sessionId),o=K(e.title)||e.sessionId,n=j(e),a=ue(e),r=tt(e),c=mt(e),d=Wt(e.workingDir);return`<article class="session-card${t?" selected":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" aria-pressed="${t}">
159
- <div class="session-card-top">
160
- ${se({name:n,larkAppId:e.larkAppId,size:"sm"})}
161
- <div class="session-card-title">
162
- <strong title="${l(String(e.title??o))}">${l(String(o).slice(0,72))}</strong>
163
- <span>${l(n)} \xB7 ${l(a??e.cliId??"unknown")}</span>
164
- </div>
165
- <span class="session-card-status-group">
166
- ${we(e.status)}
167
- ${Te(e)}
168
- </span>
169
- </div>
170
- ${d!=="-"||e.adopt?`<div class="session-card-meta">
171
- ${d!=="-"?`<span title="${l(e.workingDir??"")}">${l(d)}</span>`:""}
172
- ${e.adopt?'<span class="badge">adopt</span>':""}
173
- </div>`:""}
174
- <div class="session-card-time">
175
- <span>${e.agentAttention?.at?`${l(s("sessions.board.waiting"))} ${de(Be(e))}`:`${l(s("sessions.last"))}: ${de(e.lastMessageAt)}`}</span>
176
- </div>
177
- ${c?`<div class="session-signal" title="${l(c)}">${l(c)}</div>`:""}
178
- <div class="session-card-actions">
179
- ${pt(e)??Se("locate",T.pin,s("sessions.locate"))}
180
- ${Se("details",T.details,s("sessions.details"))}
181
- ${nt(e)?Se("restart",T.restart,s("sessions.restart")):""}
182
- ${Gt(r)}
183
- ${Se("lock",e.locked?T.unlock:T.lock,Ce(e),e.locked?"locked":"")}
184
- ${Se("close",T.close,s("sessions.close"),"danger")}
185
- </div>
186
- </article>`}function ln(e,t,o){let n=o==="needs-you"?Be(e):Number(e.lastMessageAt??0),a=o==="needs-you"?Be(t):Number(t.lastMessageAt??0);return n!==a?o==="needs-you"?n-a:a-n:String(e.title??e.sessionId).localeCompare(String(t.title??t.sessionId))}function cn(e){let t=new Map(Ft.map(a=>[a.id,[]]));for(let a of e){let r=An(a);r&&t.get(r).push(a)}let o=nn(),n=o.map((a,r)=>{let c=(t.get(a.id)??[]).sort((d,p)=>ln(d,p,a.id));return`<section class="session-board-column session-board-${a.id}" data-col="${a.id}">
187
- <header draggable="true" title="${l(s("sessions.board.dragHint"))}">
188
- <div>
189
- <h2>${l(s(a.labelKey))}</h2>
190
- <p>${l(s(a.hintKey))}</p>
191
- </div>
192
- <span class="session-board-head-right">
193
- <span class="session-board-move">
194
- <button type="button" data-move-col="${a.id}" data-dir="-1"
195
- aria-label="${l(s("sessions.board.moveLeft"))}" ${r===0?"disabled":""}>\u2039</button>
196
- <button type="button" data-move-col="${a.id}" data-dir="1"
197
- aria-label="${l(s("sessions.board.moveRight"))}" ${r===o.length-1?"disabled":""}>\u203A</button>
198
- </span>
199
- <span class="session-board-count">${c.length}</span>
200
- </span>
201
- </header>
202
- <div class="session-board-list">
203
- ${c.length?c.map(rn).join(""):`<div class="session-board-empty">${s("sessions.board.emptyColumn")}</div>`}
204
- </div>
205
- </section>`}).join("");n!==Pe&&(Pe=n,P.innerHTML=n,P.classList.toggle("board-enter",!it),it=!0)}function ft(e){let t=K(e.title)||e.sessionId,o=j(e),n=ue(e),a=Wt(e.workingDir),r=mt(e),c=[n,a!=="-"?a:null].filter(Boolean).join(" \xB7 "),d=String(e.status??"unknown"),p=typeof e.remoteDeployment=="string"?e.remoteDeployment:"";return`<article class="kanban-card${p?" kanban-card-remote":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" tabindex="0" role="button" draggable="true">
206
- <div class="kanban-card-top">
207
- <span class="badge cli-${Re(e.cliId)}">${l(e.cliId??"unknown")}</span>
208
- ${e.adopt?'<span class="badge">adopt</span>':""}
209
- ${Te(e)}
210
- ${p?`<span class="badge kanban-remote-badge" title="${l(s("sessions.kanban.remoteHint",{name:p}))}">${l(p)}</span>`:""}
211
- <span class="kanban-card-top-right">
212
- <span class="kanban-card-dot" data-status="${l(Re(d))}" title="${l(Ne(d))}"></span>
213
- ${p?"":`<button type="button" class="card-act kanban-card-act" data-action="history" title="${l(s("sessions.history.title"))}" aria-label="${l(s("sessions.history.title"))}">${T.history}</button>
214
- ${e.feishuChatLink?`<a class="card-act kanban-card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(s("sessions.kanban.openFeishu"))}" aria-label="${l(s("sessions.kanban.openFeishu"))}">${T.feishu}</a>`:""}
215
- <button type="button" class="card-act kanban-card-act${e.locked?" locked":""}" data-action="lock" title="${l(Ce(e))}" aria-label="${l(Ce(e))}">${e.locked?T.unlock:T.lock}</button>
216
- <button type="button" class="card-act kanban-card-act" data-action="details" title="${l(s("sessions.details"))}" aria-label="${l(s("sessions.details"))}">${T.details}</button>
217
- ${nt(e)?`<button type="button" class="card-act kanban-card-act" data-action="restart" title="${l(s("sessions.restart"))}" aria-label="${l(s("sessions.restart"))}">${T.restart}</button>`:""}`}
218
- </span>
219
- </div>
220
- <p class="kanban-card-title" title="${l(String(e.title??t))}">${l(String(t).slice(0,140))}</p>
221
- ${c?`<p class="kanban-card-desc" title="${l(c)}">${l(c)}</p>`:""}
222
- ${r?`<div class="session-signal" title="${l(r)}">${l(r)}</div>`:""}
223
- <div class="kanban-card-foot">
224
- <span class="kanban-card-owner">${se({name:o,larkAppId:e.larkAppId,size:"sm"})}<span>${l(o)}</span></span>
225
- <span class="kanban-card-updated">${l(s("sessions.kanban.updated",{time:de(e.lastMessageAt)}))}</span>
226
- </div>
227
- </article>`}function bt(e){let t=[],o=new Map;for(let r of e){let c=String(r.chatId??r.sessionId),d=o.get(c);d||(d={chatId:c,rows:[]},o.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 ft(r.rows[0]);let c=ue(r.rows[0])??r.chatId;return`<div class="kanban-cluster" data-chat="${l(r.chatId)}">
228
- <header draggable="true" title="${l(c)} \xB7 ${l(s("sessions.kanban.clusterDragHint"))}">
229
- ${Nt({chatId:r.chatId,name:c,size:"sm"})}
230
- <span class="kanban-cluster-name">${l(c)}</span>
231
- <span class="kanban-cluster-count">${r.rows.length}</span>
232
- </header>
233
- ${r.rows.map(ft).join("")}
234
- </div>`}).join(""),flat:n}}function dn(e){let t=new Map;for(let n of e){if(n.status==="closed")continue;let a=String(n.larkAppId||n.botName||"unknown"),r=t.get(a);r||(r={name:j(n),larkAppId:n.larkAppId,rows:[]},t.set(a,r)),r.rows.push(n)}let o=[...t.values()].sort((n,a)=>n.name.localeCompare(a.name));return o.length?o.map(n=>{let a=n.rows.sort((c,d)=>Number(d.lastMessageAt??0)-Number(c.lastMessageAt??0)),{html:r}=bt(a);return`<section class="kanban-column kanban-bot-col" data-bot="${l(n.larkAppId??n.name)}">
235
- <header>
236
- <span class="kanban-col-avatar">${se({name:n.name,larkAppId:n.larkAppId,size:"sm"})}</span>
237
- <h2>${l(n.name)}</h2>
238
- <span class="kanban-col-count">${a.length}</span>
239
- </header>
240
- <div class="kanban-col-list">${r}</div>
241
- </section>`}).join(""):`<div class="kanban-col-empty">${s("sessions.board.emptyColumn")}</div>`}function gt(e){let t=new Map(zt.map(n=>[n.id,[]]));for(let n of e)t.get(_t(n)).push(n);let o=zt.map(n=>{let a=(t.get(n.id)??[]).sort((p,f)=>ae(p)-ae(f)),r=0;n.id==="done"&&a.length>et&&(r=a.length-et,a=a.slice(0,et));let{html:c,flat:d}=bt(a);return t.set(n.id,d),`<section class="kanban-column kanban-${n.id}" data-col="${n.id}">
242
- <header>
243
- <span class="kanban-col-icon">${En(n.id)}</span>
244
- <h2>${l(s(n.labelKey))}</h2>
245
- <span class="kanban-col-count">${a.length+r}</span>
246
- </header>
247
- <div class="kanban-col-list">
248
- ${a.length?c:`<div class="kanban-col-empty">${s("sessions.board.emptyColumn")}</div>`}
249
- ${r?`<div class="kanban-col-more">${l(s("sessions.kanban.moreHidden",{count:r}))}</div>`:""}
250
- </div>
251
- </section>`}).join("");return re=t,o}function un(e){if(te||ne||Oe)return;S.classList.toggle("kanban-mode-bot",D==="bot");let t;if(D==="bot")t=dn(e),re=new Map;else if(D==="team")if(!Ie)t=`<div class="kanban-loading">${s("sessions.kanban.teamLoading")}</div>`,re=new Map,_.dataset.loading||(_.dataset.loading="1",_.disabled=!0,_.innerHTML=`<option>${l(s("sessions.kanban.teamLoading"))}</option>`),Qt();else{let n=B.find(f=>f.key===Y)??B[0],a=lt(n),r=n?e.filter(f=>a.has(String(f.chatId))):[];n&&en(n);let c=(le===n?.key?H?.board:null)??{},d=(le===n?.key?H?.remoteRows:null)??[],p=[...r,...d].map(f=>{let L=c[f.sessionId];return L?{...f,kanbanColumn:L.column,kanbanPosition:L.position}:f});at.textContent=s("sessions.kanban.teamScope",{chats:a.size,sessions:p.length}),t=gt(p)}else t=gt(e);if(t===C)return;C=t;let o=new Map;S.querySelectorAll(".kanban-col-list").forEach(n=>{let a=n.closest(".kanban-column")?.dataset.col;a&&n.scrollTop&&o.set(a,n.scrollTop)}),S.innerHTML=t,o.size&&S.querySelectorAll(".kanban-col-list").forEach(n=>{let a=n.closest(".kanban-column")?.dataset.col,r=a?o.get(a):void 0;r&&(n.scrollTop=r)})}async function ht(e,t,o,n){try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/board`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({column:t,position:o})}),r=await a.json().catch(()=>({}));(!a.ok||r?.ok===!1)&&(e.kanbanColumn=n.column,e.kanbanPosition=n.position,C="",g(),a.status!==401&&alert(`${s("sessions.kanban.moveFail")}: ${r?.error??a.status}`))}catch(a){e.kanbanColumn=n.column,e.kanbanPosition=n.position,C="",g(),alert(`${s("sessions.kanban.moveFail")}: ${a}`)}}async function yt(e,t){let o=e.title;e.title=t,C="",g();try{let n=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/rename`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({title:t})}),a=await n.json().catch(()=>({}));(!n.ok||a?.ok===!1)&&(e.title=o,C="",g(),n.status!==401&&alert(`${s("sessions.kanban.renameFail")}: ${a?.error??n.status}`))}catch(n){e.title=o,C="",g(),alert(`${s("sessions.kanban.renameFail")}: ${n}`)}}function pn(e){if(e==null||e==="")return"";let t=Number(e),o=Number.isFinite(t)&&t>0?new Date(t):new Date(String(e));return Number.isNaN(o.getTime())?"":o.toLocaleString()}function mn(e,t,o){let n=t.senderType==="user",a=n?t.senderName||(o&&t.senderId===o?s("sessions.history.owner"):s("sessions.history.user")):j(e),r=pn(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(a).slice(0,1))}</span>`:se({name:j(e),larkAppId:e.larkAppId,size:"sm"});return`<div class="history-msg${n?" mine":""}">
252
- ${d}
253
- <div class="history-msg-main">
254
- <div class="history-msg-meta"><span>${l(a)}</span><time>${l(r)}</time></div>
255
- <div class="history-bubble">${l(c)}</div>
256
- </div>
257
- </div>`}async function kt(e){let t=j(e);w.innerHTML=`<div class="term-modal-head">
258
- <span class="term-modal-title">
259
- ${se({name:t,larkAppId:e.larkAppId,size:"sm"})}
260
- <strong title="${l(String(e.title??""))}">${l((K(e.title)||e.sessionId).slice(0,60))}</strong>
261
- <span class="history-scope-tag">${l(s("sessions.history.title"))}</span>
262
- </span>
263
- <span class="term-modal-actions">
264
- <button type="button" id="history-close" class="card-act" title="${l(s("sessions.dismiss"))}" aria-label="${l(s("sessions.dismiss"))}">${T.close}</button>
265
- </span>
266
- </div>
267
- <div class="history-body"><div class="term-modal-loading">${s("sessions.history.loading")}</div></div>`,w.showModal(),w.querySelector("#history-close").onclick=()=>w.close();try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/history?limit=80`),n=await o.json().catch(()=>({}));if(!w.open)return;let a=w.querySelector(".history-body");if(!o.ok||n?.ok===!1){let c=String(n?.error??o.status),d=c==="not_found_yet"||c==="not_found";a.innerHTML=`<div class="history-error">${l(s("sessions.history.fail"))}: ${l(c)}${d?`<br><span>${l(s("sessions.history.staleHint"))}</span>`:""}</div>`;return}let r=Array.isArray(n.messages)?n.messages:[];if(!r.length){a.innerHTML=`<div class="history-error">${s("sessions.history.empty")}</div>`;return}a.innerHTML=`<div class="history-list">${r.map(c=>mn(e,c,n.ownerOpenId)).join("")}</div>`,a.scrollTop=a.scrollHeight}catch(o){if(!w.open)return;let n=w.querySelector(".history-body");n&&(n.innerHTML=`<div class="history-error">${l(s("sessions.history.fail"))}: ${l(String(o))}</div>`)}}function $t(e,t){let o=e.querySelector(".kanban-card-title");if(!o||e.querySelector(".kanban-rename-input"))return;Oe=!0;let n=document.createElement("input");n.type="text",n.className="kanban-rename-input",n.maxLength=200,n.value=K(t.title)||"",o.replaceWith(n),n.focus(),n.select();let a=!1,r=c=>{if(a)return;a=!0,Oe=!1;let d=n.value.trim();c&&d&&d!==(K(t.title)||"")?yt(t,d):(C="",g())};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 vt(e,t){for(let o of e.querySelectorAll(".kanban-card:not(.dragging)")){if(o.closest(".kanban-cluster.dragging"))continue;let n=o.getBoundingClientRect();if(t<n.top+n.height/2)return o}return null}function wt(){S.querySelectorAll(".drag-over, .dragging, .drop-before").forEach(e=>e.classList.remove("drag-over","dragging","drop-before"))}function fn(e){let t=k.querySelector(".term-modal-name");if(!t||k.querySelector(".term-modal-name-input"))return;let o=document.createElement("input");o.type="text",o.className="term-modal-name-input",o.maxLength=200,o.value=K(e.title)||"",t.replaceWith(o);let n=()=>{let c=getComputedStyle(o),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=o.value||" ",document.body.appendChild(d);let p=d.offsetWidth;d.remove();let f=Math.round(window.innerWidth*.6);o.style.width=`${Math.min(Math.max(p+22,80),f)}px`};n(),o.addEventListener("input",n),o.focus(),o.select();let a=!1,r=c=>{if(a)return;a=!0;let d=o.value.trim(),p=K(e.title)||"";if(c&&d&&d!==p){e.title=d;let f=document.createElement("strong");f.className="term-modal-name",f.title=d,f.textContent=d.slice(0,60),o.replaceWith(f),yt(e,d)}else{let f=document.createElement("strong");f.className="term-modal-name",f.title=String(e.title??p),f.textContent=p.slice(0,60),o.replaceWith(f)}};o.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Enter"?(c.preventDefault(),r(!0)):c.key==="Escape"&&(c.preventDefault(),r(!1))}),o.addEventListener("blur",()=>r(!0))}async function St(e){let t=tt(e);if(!t){He(e);return}let o=K(e.title)||e.sessionId,n=e.feishuChatLink?`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(s("sessions.kanban.openFeishu"))}" aria-label="${l(s("sessions.kanban.openFeishu"))}">${T.feishu}</a>`:"";k.innerHTML=`<div class="term-modal-head">
268
- <span class="term-modal-title">
269
- ${se({name:j(e),larkAppId:e.larkAppId,size:"sm"})}
270
- <strong class="term-modal-name" title="${l(String(e.title??o))}">${l(String(o).slice(0,60))}</strong>
271
- <button type="button" id="term-modal-edit" class="card-act" title="${l(s("sessions.kanban.rename"))}" aria-label="${l(s("sessions.kanban.rename"))}">${T.edit}</button>
272
- ${we(e.status)}
273
- </span>
274
- <span class="term-modal-actions">
275
- ${n}
276
- <a id="term-modal-tab" class="card-act" href="${l(t)}" target="_blank" rel="noopener" title="${l(s("sessions.kanban.openTab"))}" aria-label="${l(s("sessions.kanban.openTab"))}">${T.terminal}</a>
277
- <button type="button" id="term-modal-close" class="card-act" title="${l(s("sessions.dismiss"))}" aria-label="${l(s("sessions.dismiss"))}">${T.close}</button>
278
- </span>
279
- </div>
280
- <div class="term-modal-body"><div class="term-modal-loading">${s("sessions.kanban.terminalLoading")}</div></div>`,k.showModal(),k.querySelector("#term-modal-close").onclick=()=>k.close(),k.querySelector("#term-modal-edit").onclick=()=>fn(e);let a=t;if(ve.authed)try{let d=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/write-link`),p=await d.json().catch(()=>({}));d.ok&&p?.ok!==!1&&p?.url&&(a=p.url)}catch{}if(!k.open)return;let r=k.querySelector(".term-modal-body");r.innerHTML=`<iframe class="term-modal-frame" src="${l(a)}" allow="clipboard-read; clipboard-write"></iframe>`;let c=k.querySelector("#term-modal-tab");c&&(c.href=a)}function he(){let e=new FormData(b),t=(e.get("q")??"").toLowerCase(),o=e.getAll("cli"),n=o.length>0&&o.length<Jt.length,a=e.get("status"),r=e.get("adopt"),c=!!e.get("active"),d=E==="kanban",p=[...O.sessions.values()].filter(f=>!n||o.includes(f.cliId??"unknown")).filter(f=>!a||f.status===a).filter(f=>!r||r==="yes"==!!f.adopt).filter(f=>!c||d||f.status!=="closed").filter(f=>!t||JSON.stringify(f).toLowerCase().includes(t));return p.sort(bn),p}function Ct(e,t){return t==="spawnedAt"||t==="lastMessageAt"?Number(e[t]??0):t==="tokenIn"?st(e.tokenUsage?.in)??-1:t==="tokenOut"?st(e.tokenUsage?.out)??-1:t==="adopt"?!!e.adopt:String(e[t]??"").toLowerCase()}function bn(e,t){let o=Ct(e,be),n=Ct(t,be),a=0;return typeof o=="number"&&typeof n=="number"?a=o-n:typeof o=="boolean"&&typeof n=="boolean"?a=Number(o)-Number(n):a=String(o).localeCompare(String(n)),a===0&&(a=Number(e.lastMessageAt??0)-Number(t.lastMessageAt??0)),ie==="asc"?a:-a}function gn(){fe.querySelectorAll("th[data-sort]").forEach(e=>{let t=e.dataset.sort===be;e.classList.toggle("sorted",t),e.setAttribute("aria-sort",t?ie==="asc"?"ascending":"descending":"none");let o=e.dataset.label??e.textContent?.trim()??"";e.textContent=t?`${o} ${ie==="asc"?"\u25B2":"\u25BC"}`:o})}function je(e){pe.hidden=v.size===0,oe.textContent=s("sessions.selectedCount",{count:v.size});let t=[...v].map(a=>O.sessions.get(a)).filter(a=>!!a&&a.status!=="closed");z.disabled=!t.some(a=>!a.locked),G.disabled=!t.some(a=>!!a.locked);let o=e.filter(a=>a.status!=="closed");if(o.length===0){$.checked=!1,$.indeterminate=!1,$.disabled=!0;return}$.disabled=!1;let n=o.filter(a=>v.has(a.sessionId)).length;$.checked=n===o.length,$.indeterminate=n>0&&n<o.length}function Fe(){let e=ct().length;me.textContent=s("sessions.idleCleanupCount",{count:e}),Z.disabled=Me||e===0,N.classList.toggle("is-empty",e===0),Zt()}function hn(){ot.forEach(e=>{let t=e.dataset.view===E;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))}),ee.hidden=E!=="kanban",_.hidden=!(E==="kanban"&&D==="team"),at.hidden=_.hidden||!Ie,ee.querySelectorAll("[data-groupby]").forEach(e=>{let t=e.dataset.groupby===D;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))})}function yn(){let e=b.querySelector("#cli-filter-count");if(!e)return;let t=[...b.querySelectorAll('input[name="cli"]')],o=t.filter(n=>n.checked).length;e.textContent=o===t.length?s("common.all"):`${o}/${t.length}`,e.classList.toggle("cli-filter-active",o!==t.length)}function g(){let e=he();for(let n of[...v]){let a=O.sessions.get(n);(!a||a.status==="closed")&&v.delete(n)}let t=e.filter(n=>n.status!=="closed"),o=E==="table"?e:t;if(fe.hidden=E!=="table",P.hidden=E!=="board",S.hidden=E!=="kanban",E==="table"){let n=e.length?e.map(on).join(""):`<tr><td colspan="12" class="empty">${s("sessions.empty")}</td></tr>`;n!==De&&(De=n,u.innerHTML=n)}else E==="kanban"?un(e):cn(t);hn(),gn(),yn(),je(o),Fe()}async function Tt(e,t){t&&(t.disabled=!0,t.textContent=s("sessions.locating"));try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/locate`,{method:"POST"}),n=await o.json();if(n.ok){if(!t)return;let a=30;t.textContent=s("sessions.cooldown",{seconds:a});let r=setInterval(()=>{a-=1,a<=0?(clearInterval(r),t.disabled=!1,t.textContent=s("sessions.locate")):t.textContent=s("sessions.cooldown",{seconds:a})},1e3)}else alert(`Locate failed: ${n.error??o.status}`),t&&(t.disabled=!1,t.textContent=s("sessions.locate"))}catch(o){alert(`Locate error: ${o}`),t&&(t.disabled=!1,t.textContent=s("sessions.locate"))}}async function Lt(e,t){if(!confirm(s("sessions.closeConfirm")))return!1;t&&(t.disabled=!0);try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/close`,{method:"POST"}),n=await o.json().catch(()=>({}));return!o.ok||n?.ok===!1?(o.status!==401&&alert(`Close failed: ${n?.error??o.status}`),!1):!0}catch(o){return alert(`Close error: ${o}`),!1}finally{t&&(t.disabled=!1)}}function ye(){Pe="",De="",C=""}async function ze(e,t,o){let n=!!e.locked;if(n===t)return!0;e.locked=t,ye(),g(),o&&(o.disabled=!0);try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:t})}),r=await a.json().catch(()=>({}));return!a.ok||r?.ok===!1?(e.locked=n,ye(),g(),a.status!==401&&alert(`${s("sessions.lockFailed")}: ${r?.error??a.status}`),!1):(e.locked=!!r.locked,ye(),g(),!0)}catch(a){return e.locked=n,ye(),g(),alert(`${s("sessions.lockFailed")}: ${a}`),!1}finally{o&&(o.disabled=!1)}}let We=new Set;async function Ge(e,t){if(We.has(e.sessionId)||!confirm(Bn(e)))return!1;t&&(t.disabled=!0);try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/restart`,{method:"POST"}),n=await o.json().catch(()=>({}));return!o.ok||n?.ok===!1?(o.status!==401&&alert(`${s("sessions.restartFailed")}: ${n?.error??o.status}`),!1):(We.add(e.sessionId),setTimeout(()=>We.delete(e.sessionId),5e3),!0)}catch(o){return alert(`${s("sessions.restartFailed")}: ${o}`),!1}finally{t&&(t.disabled=!1)}}function kn(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 $n(e){if(!e||e.status!=="ok"){let r=e?.error?.message?l(String(e.error.message)):l(String(e?.status??"error"));return`<p>${s("sessions.insightUnavailable")}: ${r}</p>`}let t=e.agg??{};if(!t.totalSpans)return`<p>${s("sessions.insightEmpty")}</p>`;let o="color:var(--muted,#8f959e)",n=[],a=[];if(e.meta?.asOf&&a.push(l(s("sessions.insightAsOf",{asOf:String(e.meta.asOf)}))),e.meta?.partial&&a.push(l(s("sessions.insightPartial"))),a.length&&n.push(`<p style="font-size:12px;${o}">${a.join(" \xB7 ")}</p>`),n.push(`<p>${l(s("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="${o}">${l(d.evidence.join("\uFF1B"))}</small>`:"")+"</li>").join("");n.push(`<details open><summary>${s("sessions.insightSuggestions")}</summary><ul style="padding-left:18px;margin:6px 0">${c}</ul></details>`)}if(Array.isArray(e.spans)&&e.spans.length){let r=p=>p==="error"?"\u{1F534}":p==="running"?"\u23F3":"\u2705",c=[...e.spans].sort((p,f)=>(p.relStartMs??0)-(f.relStartMs??0)).map(p=>{let f=[p.inputSummary,p.outputSummary].filter(Boolean).map(A=>l(String(A))).join(" \u2192 ");return`<tr${p.status==="error"?' style="color:var(--danger,#d33)"':""}><td>${r(p.status)}</td><td><code>${l(String(p.tool??""))}</code></td><td>${l(String(p.phase??""))}</td><td>${kn(p.durationMs)}</td><td>#${l(String(p.turnIndex??0))}</td><td>${f}</td></tr>`}).join(""),d=e.meta?.capped?`<p style="font-size:12px;${o}">${l(s("sessions.insightCapped",{shown:String(e.meta.spansReturned??e.spans.length),total:String(e.meta.spansTotal??e.spans.length)}))}</p>`:"";n.push(`<details><summary>${s("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 He(e){let t=e.status==="closed",o=tt(e);m.innerHTML=`<article>
281
- <header>
282
- <h3>${l(K(e.title)||e.sessionId)}</h3>
283
- <span class="drawer-status-line">
284
- ${we(e.status)}
285
- ${Te(e)}
286
- </span>
287
- <p><code>${l(e.sessionId)}</code> <button data-copy="${l(e.sessionId)}">${s("sessions.copy")}</button></p>
288
- </header>
289
- <p><b>${s("sessions.bot")}:</b> ${l(j(e))} \xB7 <b>${s("sessions.cli")}:</b> ${l(e.cliId??"?")}</p>
290
- ${ue(e)?`<p><b>${s("sessions.chat")}:</b> ${l(ue(e))}</p>`:""}
291
- <p><b>chatId:</b> <code>${l(e.chatId??"")}</code> <button data-copy="${l(e.chatId??"")}">${s("sessions.copy")}</button></p>
292
- <p><b>rootMessageId:</b> <code>${l(e.rootMessageId??"")}</code> <button data-copy="${l(e.rootMessageId??"")}">${s("sessions.copy")}</button></p>
293
- ${e.threadId?`<p><b>threadId:</b> <code>${l(e.threadId)}</code></p>`:""}
294
- <p><b>${s("sessions.workingDir")}:</b> ${l(e.workingDir??"-")}</p>
295
- <div class="actions">
296
- ${pt(e)??`<button id="locate-btn" type="button">${s("sessions.locate")}</button>`}
297
- <button id="history-drawer-btn" type="button">${s("sessions.history.title")}</button>
298
- ${Gt(o)}
299
- ${nt(e)?`<button id="restart-btn" type="button">${s("sessions.restart")}</button>`:""}
300
- ${t?"":`<button id="lock-btn" type="button">${l(Ce(e))}</button>`}
301
- ${e.queued&&!t?`<button id="start-btn" type="button" class="primary">${s("sessions.create.start")}</button>`:""}
302
- ${t?`<button id="resume-btn" type="button" class="primary">${s("sessions.resume")}</button>`:""}
303
- ${t?"":`<button id="close-btn" type="button" class="contrast">${s("sessions.close")}</button>`}
304
- <button id="land-btn" type="button">${s("sessions.land")}</button>
305
- ${ve.authed?`<button id="insight-btn" type="button">${s("sessions.insight")}</button>`:""}
306
- </div>
307
- <div id="land-area"></div>
308
- <div id="insight-area"></div>
309
- <form method="dialog"><button>${s("sessions.dismiss")}</button></form>
310
- </article>`,m.querySelectorAll("[data-copy]").forEach(h=>{h.onclick=()=>{navigator.clipboard.writeText(h.dataset.copy??""),h.textContent=s("sessions.copied"),setTimeout(()=>{h.textContent=s("sessions.copy")},800)}});let n=m.querySelector("#locate-btn");n&&(n.onclick=()=>{Tt(e,n)});let a=m.querySelector("#history-drawer-btn");a&&(a.onclick=()=>{kt(e)});let r=m.querySelector(".term-write");r&&(r.onclick=()=>{Vt(e,r)});let c=m.querySelector("#resume-btn");c&&(c.onclick=async()=>{c.disabled=!0;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/resume`,{method:"POST"}),y=await h.json().catch(()=>({}));if(!h.ok||y.ok===!1){alert(`${s("sessions.resumeFailed")}: ${y?.error??h.status}`),c.disabled=!1;return}m.close()}catch(h){alert(`${s("sessions.resumeFailed")}: ${h}`),c.disabled=!1}});let d=m.querySelector("#restart-btn");d&&(d.onclick=async()=>{await Ge(e,d)&&m.close()});let p=m.querySelector("#close-btn");p&&(p.onclick=async()=>{await Lt(e,p)&&m.close()});let f=m.querySelector("#lock-btn");f&&(f.onclick=async()=>{let h=!e.locked;if(await ze(e,h,f)){f.textContent=Ce(e);let y=m.querySelector(".drawer-status-line");y&&(y.innerHTML=`${we(e.status)}${Te(e)}`)}});let L=m.querySelector("#start-btn");L&&(L.onclick=async()=>{L.disabled=!0;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/start`,{method:"POST"}),y=await h.json().catch(()=>({}));if(!h.ok||y.ok===!1){h.status!==401&&alert(`${s("sessions.create.startFailed")}: ${y?.error??h.status}`),L.disabled=!1;return}m.close()}catch(h){alert(`${s("sessions.create.startFailed")}: ${h}`),L.disabled=!1}});let A=m.querySelector("#land-btn"),x=m.querySelector("#land-area");A&&x&&(A.onclick=async()=>{A.disabled=!0,x.innerHTML=`<p>${s("sessions.landLoading")}</p>`;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-diff`),y=await h.json().catch(()=>({}));if(!y.ok){x.innerHTML=`<p>${s("sessions.landUnavailable")}: ${l(y.error??String(h.status))}</p>`,A.disabled=!1;return}if(y.empty){x.innerHTML=`<p>${s("sessions.landEmpty")}</p>`,A.disabled=!1;return}let W=String(y.patch??""),Ae=W.slice(0,2e4)+(W.length>2e4?`
311
- \u2026(truncated)`:"");x.innerHTML=`
312
- <p><b>${y.files}</b> files (+${y.insertions}/-${y.deletions}) \u2192 <code>${l(String(y.workingDir??""))}</code></p>
313
- <pre style="max-height:320px;overflow:auto;white-space:pre-wrap">${l(Ae)}</pre>
314
- <div class="actions">
315
- <button id="land-apply" type="button" class="primary">${s("sessions.landApply")}</button>
316
- <button id="land-discard" type="button" class="contrast">${s("sessions.landDiscard")}</button>
317
- </div>`;let $e=x.querySelector("#land-apply"),xe=x.querySelector("#land-discard");$e.onclick=async()=>{$e.disabled=!0,xe.disabled=!0;let I=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/apply`,{method:"POST"}),X=await I.json().catch(()=>({}));x.innerHTML=X.ok?`<p>\u2705 ${s("sessions.landApplied")}: ${X.files} files (+${X.insertions}/-${X.deletions}) \u2192 <code>${l(String(X.workingDir??""))}</code></p>`:`<p>\u274C ${s("sessions.landFailed")}: ${l(X.error??String(I.status))}</p>`},xe.onclick=async()=>{await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/discard`,{method:"POST"}),x.innerHTML=`<p>\u{1F5D1} ${s("sessions.landDiscarded")}</p>`}}catch(h){x.innerHTML=`<p>${s("sessions.landUnavailable")}: ${l(String(h))}</p>`,A.disabled=!1}});let ce=m.querySelector("#insight-btn"),R=m.querySelector("#insight-area");ce&&R&&(ce.onclick=async()=>{ce.disabled=!0,R.innerHTML=`<p>${s("sessions.insightLoading")}</p>`;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/insight?detail=spans`),y=await h.json().catch(()=>({}));!y.ok||!y.report?R.innerHTML=`<p>${s("sessions.insightUnavailable")}: ${l(String(y.error??h.status))}</p>`:R.innerHTML=$n(y.report)}catch(h){R.innerHTML=`<p>${s("sessions.insightUnavailable")}: ${l(String(h))}</p>`}ce.disabled=!1}),m.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?v.add(r.dataset.id):v.delete(r.dataset.id),je(he());return}let o=t.closest("td");if(o&&o.querySelector(".row-select"))return;let n=t.closest("tr[data-id]");if(!n)return;let a=O.sessions.get(n.dataset.id);a&&He(a)}),P.addEventListener("click",e=>{let t=e.target,o=t.closest("button[data-move-col]");if(o){sn(o.dataset.moveCol,Number(o.dataset.dir));return}let n=t.closest(".session-card[data-id]");if(!n)return;let a=O.sessions.get(n.dataset.id);if(!a)return;let r=t.closest("button[data-action]");if(r){let c=r.dataset.action;c==="details"?He(a):c==="write-link"?Vt(a,r):c==="locate"?Tt(a,r):c==="restart"?Ge(a,r):c==="lock"?ze(a,!a.locked,r):c==="close"&&Lt(a,r).then(d=>{d&&(v.delete(a.sessionId),g())});return}t.closest("a, button, input, label")||(v.has(a.sessionId)?v.delete(a.sessionId):v.add(a.sessionId),n.classList.toggle("selected",v.has(a.sessionId)),n.setAttribute("aria-pressed",String(v.has(a.sessionId))),je(he().filter(c=>c.status!=="closed")))}),P.addEventListener("dragstart",e=>{let o=e.target.closest(".session-board-column > header[draggable]")?.closest(".session-board-column");o?.dataset.col&&(J=o.dataset.col,o.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",J)))}),P.addEventListener("dragover",e=>{if(!J)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".session-board-column");P.querySelectorAll(".drag-over").forEach(o=>o.classList.remove("drag-over")),t&&t.dataset.col!==J&&t.classList.add("drag-over")}),P.addEventListener("drop",e=>{if(!J)return;e.preventDefault();let t=e.target.closest(".session-board-column"),o=J;J=null,t?.dataset.col&&an(o,t.dataset.col)}),P.addEventListener("dragend",()=>{J=null,P.querySelectorAll(".drag-over, .dragging").forEach(e=>e.classList.remove("drag-over","dragging"))}),ot.forEach(e=>{e.addEventListener("click",()=>{let t=Et(e.dataset.view)??"board";t!==E&&(E=t,xt(window.localStorage,E),g())})}),ee.querySelectorAll("[data-groupby]").forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.groupby,o=t==="bot"?"bot":t==="team"?"team":"flow";o!==D&&(D=o,Rt(window.localStorage,o),C="",g())})}),_.addEventListener("change",()=>{Y=_.value;try{window.localStorage.setItem(Ye,Y)}catch{}C="",g()});function ke(){ge!==null&&(clearTimeout(ge),ge=null)}S.addEventListener("click",e=>{let t=e.target,o=t.closest(".kanban-card[data-id]");if(!o)return;let n=O.sessions.get(o.dataset.id);if(!n)return;let a=t.closest("button[data-action]");if(a){a.dataset.action==="details"?He(n):a.dataset.action==="rename"?$t(o,n):a.dataset.action==="history"?kt(n):a.dataset.action==="restart"?Ge(n,a):a.dataset.action==="lock"&&ze(n,!n.locked,a);return}t.closest("a, button, input, label")||(ke(),ge=setTimeout(()=>{ge=null,St(n)},220))}),S.addEventListener("dblclick",e=>{let t=e.target,o=t.closest(".kanban-card-title"),n=t.closest(".kanban-card[data-id]");if(!o||!n)return;ke();let a=O.sessions.get(n.dataset.id);a&&$t(n,a)}),S.addEventListener("keydown",e=>{if(e.key!=="Enter"&&e.key!==" ")return;let t=e.target;if(!t.classList?.contains("kanban-card"))return;e.preventDefault();let o=O.sessions.get(t.dataset.id);o&&St(o)}),S.addEventListener("dragstart",e=>{if(D==="bot")return;let t=e.target,o=t.closest(".kanban-cluster > header[draggable]");if(o){let a=o.closest(".kanban-cluster"),r=a.closest(".kanban-column")?.dataset.col;if(!a.dataset.chat||!r)return;ke(),ne=a.dataset.chat,Le=r,a.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",`cluster:${ne}`));return}let n=t.closest(".kanban-card[data-id]");n&&(ke(),te=n.dataset.id,n.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",te)))}),S.addEventListener("dragover",e=>{if(!te&&!ne)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".kanban-column");S.querySelectorAll(".drag-over").forEach(o=>o.classList.remove("drag-over")),S.querySelectorAll(".drop-before").forEach(o=>o.classList.remove("drop-before")),t&&(t.classList.add("drag-over"),vt(t,e.clientY)?.classList.add("drop-before"))}),S.addEventListener("drop",e=>{let t=ne,o=Le,n=te;if(!n&&!t)return;e.preventDefault(),te=null,ne=null,Le=null,wt();let a=e.target.closest(".kanban-column"),r=a?.dataset.col;if(!a||!r)return;let c=vt(a,e.clientY);if(t&&o){let R=(re.get(o)??[]).filter(I=>String(I.chatId)===t).filter(I=>!(I.status==="closed"&&r!=="done"));if(!R.length)return;let h=new Set(R.map(I=>I.sessionId)),y=(re.get(r)??[]).filter(I=>!h.has(I.sessionId)),W=c?y.findIndex(I=>I.sessionId===c.dataset.id):y.length;W<0&&(W=y.length);let Ae=W>0?y[W-1]:null,$e=W<y.length?y[W]:null,xe=Xe(Ae?ae(Ae):null,$e?ae($e):null);R.forEach((I,X)=>{let Ve=xe+X*.001;if(D==="team")ut(String(I.sessionId),r,Ve);else{let wn={column:I.kanbanColumn,position:I.kanbanPosition};I.kanbanColumn=r,I.kanbanPosition=Ve,ht(I,r,Ve,wn)}}),C="",g();return}let d=O.sessions.get(n)??Ue.get(n);if(!d||d.status==="closed"&&r!=="done")return;let p=(re.get(r)??[]).filter(R=>R.sessionId!==n),f=c?p.findIndex(R=>R.sessionId===c.dataset.id):p.length;f<0&&(f=p.length);let L=f>0?p[f-1]:null,A=f<p.length?p[f]:null,x=Xe(L?ae(L):null,A?ae(A):null);if(D==="team"){ut(String(d.sessionId),r,x),C="",g();return}let ce={column:d.kanbanColumn,position:d.kanbanPosition};d.kanbanColumn=r,d.kanbanPosition=x,C="",g(),ht(d,r,x,ce)}),S.addEventListener("dragend",()=>{te=null,ne=null,Le=null,wt(),C="",g()}),k.addEventListener("click",e=>{e.target===k&&k.close()}),k.addEventListener("close",()=>{k.innerHTML=""}),w.addEventListener("click",e=>{e.target===w&&w.close()}),w.addEventListener("close",()=>{w.innerHTML=""}),$.addEventListener("change",()=>{let e=he().filter(t=>t.status!=="closed");for(let t of e)$.checked?v.add(t.sessionId):v.delete(t.sessionId);g()}),M.addEventListener("click",()=>{v.clear(),g()}),U.addEventListener("click",async()=>{let e=[...v];if(e.length===0||!confirm(s("sessions.closeBulkConfirm",{count:e.length})))return;U.disabled=!0,M.disabled=!0;let t=U.textContent,o=0,n=0,a=[...e];U.textContent=`0/${e.length}`;async function r(){for(;a.length;){let c=a.shift();try{let d=await fetch(`/api/sessions/${encodeURIComponent(c)}/close`,{method:"POST"}),p=await d.json().catch(()=>({}));(!d.ok||p?.ok===!1)&&(n+=1)}catch{n+=1}finally{o+=1,U.textContent=`${o}/${e.length}`}}}await Promise.all(Array.from({length:Math.min(6,e.length)},()=>r())),U.textContent=t,U.disabled=!1,M.disabled=!1,v.clear(),g(),n>0&&alert(`Failed: ${n}/${e.length}`)});async function It(e){let t=[...v].map(p=>O.sessions.get(p)).filter(p=>!!p&&p.status!=="closed"&&!!p.locked!==e);if(t.length===0)return;z.disabled=!0,G.disabled=!0;let o=e?z.textContent:G.textContent,n=e?z:G,a=0,r=0,c=[...t];n.textContent=`0/${t.length}`;async function d(){for(;c.length;){let p=c.shift(),f=!!p.locked;try{let L=await fetch(`/api/sessions/${encodeURIComponent(p.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:e})}),A=await L.json().catch(()=>({}));!L.ok||A?.ok===!1?(r+=1,p.locked=f):p.locked=!!A.locked}catch{r+=1,p.locked=f}finally{a+=1,n.textContent=`${a}/${t.length}`}}}await Promise.all(Array.from({length:Math.min(6,t.length)},()=>d())),n.textContent=o,ye(),g(),r>0&&alert(`${s("sessions.lockFailed")}: ${r}/${t.length}`)}z.addEventListener("click",()=>{It(!0)}),G.addEventListener("click",()=>{It(!1)}),V.addEventListener("click",e=>{if(Me)return;let t=e.target?.closest("button[data-hours]");if(!t)return;let o=Qe(t.dataset.hours);!o||o===Ee||(Ee=o,Q.textContent="",Fe())}),Z.addEventListener("click",async()=>{let e=rt(),t=ct();if(t.length===0)return;let o=Yt(e);if(confirm(s("sessions.idleCleanupConfirm",{count:t.length,threshold:o}))){Me=!0,Z.disabled=!0,Q.textContent=s("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)})}),a=await n.json().catch(()=>({}));if(!n.ok){n.status!==401&&alert(`${s("sessions.idleCleanupFailed")}: ${a?.error??n.status}`),Q.textContent="";return}for(let r of a?.results??[])r?.ok&&r?.sessionId&&v.delete(String(r.sessionId));Q.textContent=s("sessions.idleCleanupDone",{closed:Number(a?.closed??0),failed:Number(a?.failed??0)}),g()}catch(n){alert(`${s("sessions.idleCleanupFailed")}: ${n}`),Q.textContent=""}finally{Me=!1,Fe()}}}),fe.querySelectorAll("th[data-sort]").forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.sort;be===t?ie=ie==="asc"?"desc":"asc":(be=t,ie=t==="spawnedAt"||t==="lastMessageAt"?"desc":"asc"),g()})}),b.addEventListener("input",g);let vn=O.on(g),Mt=setInterval(()=>{if(!document.body.contains(S)){clearInterval(Mt);return}E==="kanban"&&D==="team"&&(C="",g())},3e4);return g(),Pt().then(g),()=>{vn(),clearInterval(Mt),ke(),m.close(),k.close(),w.close()}}export{Ze as a,Hn as b,Ne as c,xn as d,Bn as e,nt as f,ts as g,ns as h,_n as i};
@@ -1 +0,0 @@
1
- import{a as q,b}from"./chunk-VFCACTRF.js";import"./chunk-LXIK7OUJ.js";import{o as N,p as S,r as M,s as C,t as $,u as E,v as w,x as p,y as m}from"./chunk-BNEXMNQD.js";import{a as j,b as D,c as _}from"./chunk-JTSE5VP6.js";import{c as I}from"./chunk-7SZRL6FY.js";var c=I(j(),1);var B={chats:[],bots:[]};async function P(){try{let t=await fetch("/api/groups");if(!t.ok)return;B=await t.json()}catch{}}var K=new Set(["working","analyzing","active","starting"]);function U(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 B.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),p(s)&&i.attention.push(s))}for(let s of a.values())if(s.botName===s.larkAppId){let o=C(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=I(_(),1),z=new Set(["working","analyzing","active","starting"]),X=new Set(["idle","dormant"]),W="botmux.overview.teamExpanded",F=230,O=13,T=2;function x(t){return(0,e.jsx)("span",{style:{display:"contents"},dangerouslySetInnerHTML:{__html:t.html}})}function J(){try{return window.localStorage.getItem(W)==="1"}catch{return!1}}function V(t){try{window.localStorage.setItem(W,t?"1":"0")}catch{}}function Q(t){return String(t??"unknown").toLowerCase().replace(/[^a-z0-9_-]/g,"-")}function ee(t,a){let l=String(t??"unknown"),r=`sessions.status.${l}`,s=a(r);return s===r?l:s}function te(t){let a=t?.clientWidth??0;return a?Math.max(1,Math.floor((a+O)/(F+O)))*T:T*3}function se({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,f)=>m(g)-m(f))[0];i=(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("b",{children:(w(v.title)||v.sessionId).slice(0,60)})," \xB7 ",p(v)??""]})}else if(s){let v=[...t.busy].sort((g,f)=>Number(f.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)(x,{html:S({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:N(t.lastActiveAt)}):a("common.never")})]})]})}function ne({session:t}){let a=b(),l=$(t);return(0,e.jsxs)("article",{className:"qcard","data-id":t.sessionId,children:[(0,e.jsx)(x,{html:S({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:[p(t)??""," \xB7 ",N(m(t))]})]}),(0,e.jsx)("a",{className:"qcard-go",href:"#/sessions",children:a("strip.handle")})]})}function ae({session:t}){let a=b(),l=$(t),r=String(t.status??"unknown");return(0,e.jsxs)("li",{className:"sess-row",children:[(0,e.jsx)(x,{html:S({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 ",E(t)??t.cliId??"unknown"," \xB7 ",N(t.lastMessageAt)]})]}),(0,e.jsx)("span",{className:`status status-${Q(r)}`,children:ee(r,a)})]})}function ie({schedule:t,timeZone:a}){let l=t.nextRunAt?new Date(t.nextRunAt).toLocaleString(void 0,a?{timeZone:a,timeZoneName:"short"}:void 0):"-";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:[$(t)," \xB7 ",t.parsed?.display??""]})]}),(0,e.jsx)("span",{children:l})]})}function oe({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 le(){let t=b(),a=(0,c.useRef)(null),[l,r]=(0,c.useState)(J),[s,o]=(0,c.useState)(T*3),[i,d]=(0,c.useState)(0),{sessions:v,schedules:g,scheduleTimeZone:f}=q(n=>({sessions:[...n.sessions.values()],schedules:[...n.schedules.values()],scheduleTimeZone:n.scheduleTimeZone}));(0,c.useEffect)(()=>{let n=()=>o(te(a.current));return n(),window.addEventListener("resize",n),()=>window.removeEventListener("resize",n)},[]),(0,c.useEffect)(()=>{P().then(()=>d(n=>n+1)),M().then(()=>d(n=>n+1))},[]);let u=(0,c.useMemo)(()=>v.filter(n=>n.status!=="closed"),[v]),h=(0,c.useMemo)(()=>u.filter(n=>p(n)).sort((n,y)=>m(n)-m(y)),[u]),k=(0,c.useMemo)(()=>u.filter(n=>z.has(n.status)&&!p(n)),[u]),Y=u.length-h.length-k.length,A=(0,c.useMemo)(()=>U(v),[v,i]),H=l?A:A.slice(0,s),G=A.filter(n=>n.online||n.active.length>0).length,R=(0,c.useMemo)(()=>u.filter(n=>z.has(n.status)||X.has(n.status)).sort((n,y)=>Number(y.lastMessageAt??0)-Number(n.lastMessageAt??0)).slice(0,7),[u]),L=(0,c.useMemo)(()=>g.filter(n=>n.nextRunAt).sort((n,y)=>Date.parse(n.nextRunAt)-Date.parse(y.nextRunAt)).slice(0,5),[g]),Z=()=>{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:k.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:G})]})]})]}),(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:H.length?H.map(n=>(0,e.jsx)(se,{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:A.length<=s,onClick:Z,children:l?t("overview.teamCollapse"):t("overview.teamExpand",{count:A.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)(ne,{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:R.length?R.map(n=>(0,e.jsx)(ae,{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)(oe,{working:k.length,attention:h.length,idle:Math.max(0,Y)})})]}),(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:L.length?L.map(n=>(0,e.jsx)(ie,{schedule:n,timeZone:f},n.id)):(0,e.jsx)("li",{className:"empty",children:t("overview.noSchedules")})})]})]})]})]})}function fe(t){return D(t,(0,e.jsx)(le,{}))}export{fe as renderOverviewPage};
@@ -1 +0,0 @@
1
- import{b as a,c as b,d as c,e as d,f as e,g as f,h as g,i as h}from"./chunk-DKKOGZCG.js";import"./chunk-LXIK7OUJ.js";import"./chunk-BNEXMNQD.js";import"./chunk-7SZRL6FY.js";export{a as SESSION_STATUS_OPTIONS,e as canRestartSession,f as openCreateSessionModal,c as renderCliFilterGroup,g as renderSessionsPage,d as restartConfirmMessage,b as sessionStatusText,h as wireSessionsPage};
@@ -1 +0,0 @@
1
- import{a as u,b,c as p,d as c,i as m}from"./chunk-DKKOGZCG.js";import{b as r}from"./chunk-VFCACTRF.js";import"./chunk-LXIK7OUJ.js";import"./chunk-BNEXMNQD.js";import{a as v,b as l,c as d}from"./chunk-JTSE5VP6.js";import{c as i}from"./chunk-7SZRL6FY.js";var n=i(v(),1);var s=i(d(),1);function t(e){return(0,s.jsx)("th",{"data-sort":e.sort,"data-label":e.label,children:e.label})}function g(){let e=r(),o=(0,n.useRef)(null);return(0,n.useEffect)(()=>{if(o.current)return m(o.current)},[]),(0,s.jsxs)("section",{className:"page",ref:o,children:[(0,s.jsxs)("div",{className:"page-heading",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"eyebrow",children:e("nav.sessions")}),(0,s.jsx)("h1",{children:e("sessions.title")}),(0,s.jsx)("p",{children:e("sessions.subtitle")})]}),(0,s.jsxs)("div",{className:"sessions-view-controls",children:[(0,s.jsx)("span",{id:"kanban-team-stats",className:"kanban-team-stats",hidden:!0}),(0,s.jsx)("select",{id:"kanban-team",className:"kanban-team-select","aria-label":e("sessions.kanban.groupTeam"),hidden:!0}),(0,s.jsxs)("div",{className:"segmented kanban-groupby",id:"kanban-groupby",role:"group","aria-label":e("sessions.kanban.groupBy"),hidden:!0,children:[(0,s.jsx)("button",{type:"button","data-groupby":"flow",children:e("sessions.kanban.groupFlow")}),(0,s.jsx)("button",{type:"button","data-groupby":"team",children:e("sessions.kanban.groupTeam")}),(0,s.jsx)("button",{type:"button","data-groupby":"bot",children:e("sessions.kanban.groupBot")})]}),(0,s.jsxs)("div",{className:"segmented sessions-view-toggle",role:"group","aria-label":e("sessions.viewMode"),children:[(0,s.jsx)("button",{type:"button","data-view":"kanban",children:e("sessions.viewKanban")}),(0,s.jsx)("button",{type:"button","data-view":"board",children:e("sessions.viewBoard")}),(0,s.jsx)("button",{type:"button","data-view":"table",children:e("sessions.viewTable")})]})]})]}),(0,s.jsxs)("form",{id:"filters",className:"filters sessions-filters",children:[(0,s.jsx)("input",{type:"search",name:"q",placeholder:e("sessions.search")}),(0,s.jsxs)("select",{name:"status",children:[(0,s.jsx)("option",{value:"",children:e("sessions.anyStatus")}),b.map(a=>(0,s.jsx)("option",{value:a,children:p(a)},a))]}),(0,s.jsxs)("select",{name:"adopt",children:[(0,s.jsx)("option",{value:"",children:e("sessions.adoptAny")}),(0,s.jsx)("option",{value:"yes",children:e("sessions.adoptYes")}),(0,s.jsx)("option",{value:"no",children:e("sessions.adoptNo")})]}),(0,s.jsx)("span",{style:{display:"contents"},dangerouslySetInnerHTML:{__html:c()}}),(0,s.jsxs)("label",{className:"filter-toggle",children:[(0,s.jsx)("input",{type:"checkbox",name:"active",defaultChecked:!0})," ",(0,s.jsx)("span",{children:e("sessions.activeOnly")})]})]}),(0,s.jsxs)("div",{id:"idle-cleanup-bar",className:"idle-cleanup-bar",children:[(0,s.jsxs)("div",{className:"idle-cleanup-summary",children:[(0,s.jsx)("span",{className:"idle-cleanup-dot","aria-hidden":"true"}),(0,s.jsx)("span",{id:"idle-cleanup-count",className:"idle-cleanup-count"})]}),(0,s.jsxs)("div",{className:"idle-cleanup-controls",children:[(0,s.jsx)("span",{className:"idle-cleanup-label",children:e("sessions.idleCleanupOlderThan")}),(0,s.jsx)("div",{id:"idle-cleanup-threshold",className:"idle-cleanup-thresholds",role:"group","aria-label":e("sessions.idleCleanupThreshold"),children:u.map(a=>(0,s.jsx)("button",{type:"button","data-hours":a,"aria-pressed":a===24?"true":"false",children:a===168?"7d":`${a}H`},a))}),(0,s.jsx)("button",{type:"button",id:"idle-cleanup-run",className:"contrast idle-cleanup-run",children:e("sessions.idleCleanupRun")})]}),(0,s.jsx)("span",{id:"idle-cleanup-status",className:"idle-cleanup-status","aria-live":"polite"})]}),(0,s.jsxs)("div",{id:"bulk-bar",className:"bulk-bar",hidden:!0,children:[(0,s.jsx)("span",{id:"bulk-count"}),(0,s.jsx)("button",{type:"button",id:"bulk-lock",children:e("sessions.lockSelected")}),(0,s.jsx)("button",{type:"button",id:"bulk-unlock",children:e("sessions.unlockSelected")}),(0,s.jsx)("button",{type:"button",id:"bulk-close",className:"contrast",children:e("sessions.closeSelected")}),(0,s.jsx)("button",{type:"button",id:"bulk-clear",children:e("sessions.clearSelection")})]}),(0,s.jsxs)("table",{id:"sessions-table",children:[(0,s.jsx)("thead",{children:(0,s.jsxs)("tr",{children:[(0,s.jsx)("th",{children:(0,s.jsx)("input",{type:"checkbox",id:"select-all",title:e("sessions.activeOnly")})}),(0,s.jsx)(t,{sort:"botName",label:e("sessions.bot")}),(0,s.jsx)(t,{sort:"cliId",label:e("sessions.cli")}),(0,s.jsx)(t,{sort:"status",label:e("sessions.status")}),(0,s.jsx)(t,{sort:"tokenIn",label:e("sessions.tokenIn")}),(0,s.jsx)(t,{sort:"tokenOut",label:e("sessions.tokenOut")}),(0,s.jsx)(t,{sort:"title",label:e("sessions.titleCol")}),(0,s.jsx)(t,{sort:"workingDir",label:e("sessions.workingDir")}),(0,s.jsx)(t,{sort:"spawnedAt",label:e("sessions.created")}),(0,s.jsx)(t,{sort:"lastMessageAt",label:e("sessions.last")}),(0,s.jsx)(t,{sort:"adopt",label:e("sessions.adopt")}),(0,s.jsx)("th",{children:e("sessions.actions")})]})}),(0,s.jsx)("tbody",{})]}),(0,s.jsx)("div",{id:"sessions-board",className:"sessions-board",hidden:!0}),(0,s.jsx)("div",{id:"sessions-kanban",className:"sessions-kanban",hidden:!0}),(0,s.jsx)("dialog",{id:"drawer"}),(0,s.jsx)("dialog",{id:"term-modal",className:"term-modal"}),(0,s.jsx)("dialog",{id:"history-modal",className:"history-modal"})]})}function f(e){return l(e,(0,s.jsx)(g,{}))}export{f as renderSessionsPage};
@@ -1,2 +0,0 @@
1
- import{b as G}from"./chunk-VFCACTRF.js";import"./chunk-LXIK7OUJ.js";import{p as Z,w as Nl}from"./chunk-BNEXMNQD.js";import{a as as,b as wl,c as Cl}from"./chunk-JTSE5VP6.js";import{c as Y}from"./chunk-7SZRL6FY.js";var a=Y(as(),1);var l=Y(Cl(),1),ns=2;function ll(e){let t=e.as??"span";return(0,l.jsx)(t,{style:{display:"contents"},dangerouslySetInnerHTML:{__html:e.html}})}function os(e,t){let n=String(e??"").replace(/\\/g,"/");return n.includes("/.codex/skills/")?t("skills.sourceCodex"):n.includes("/.claude/skills/")?t("skills.sourceClaude"):n.includes("/.trae/skills/")?t("skills.sourceTrae"):n.includes("/.cursor/skills/")?t("skills.sourceCursor"):n.includes("/.gemini/skills/")?t("skills.sourceGemini"):n.includes("/.config/opencode/skills/")?t("skills.sourceOpenCode"):null}function rs(e,t){let n=e.source??{};return n.type==="github"?`github:${n.owner}/${n.repo}/${n.path??""}`:n.type==="git"?`${n.url??"git"}#${n.path??""}`:n.type==="local-link"?os(n.path,t)??t("skills.sourceLocalLink"):n.type==="local-copy"?t("skills.sourceBotmuxCopy"):String(n.type??"unknown")}function q(e){return(e?.include??[]).filter(t=>t.startsWith("skill:")).map(t=>t.slice(6))}function cs(e){return q(e).length}function ds(e){return q(e).length>0}function U(e){return`${e.cliId}
2
- ${e.rootDir}`}function us(e){return e>=1600?4:e<=620?1:e<=980?2:3}async function h(e,t){let n=await fetch(e,{...t,headers:{"content-type":"application/json",...t.headers??{}}}),k=await n.json().catch(()=>({}));if(!n.ok||k.ok===!1){let f=new Error(k?.error??`HTTP ${n.status}`);throw f.status=n.status,f.body=k,f}return k}function Il(e){return`oncall-status${e?` ${e.ok?"hint-ok":"hint-warn-inline"}`:""}`}function ks(e){let t=G(),n=(0,a.useRef)(null),k=e.installCandidates??[],f=e.selectedInstallSkills??new Set,m=k.length>0&&k.every(r=>f.has(r.name)),C=e.installBusy||e.installDiscovering;return(0,a.useEffect)(()=>{let r=n.current;if(r)if(e.installSelectionOpen&&!r.open)try{r.showModal()}catch{}else!e.installSelectionOpen&&r.open&&r.close()},[e.installSelectionOpen,k.length]),(0,l.jsxs)("article",{className:"bd-card skills-install-panel",children:[(0,l.jsxs)("div",{className:"skills-install-title",children:[(0,l.jsx)("h3",{className:"bd-section-title",children:t("skills.install")}),(0,l.jsxs)("span",{className:"skills-help-tip",children:[(0,l.jsx)("button",{type:"button",className:"skills-help-button","aria-label":t("skills.installInfoLabel"),children:"?"}),(0,l.jsx)("span",{className:"skills-help-popover",role:"tooltip",children:t("skills.installInfo")})]})]}),(0,l.jsxs)("div",{className:"skills-install-grid",children:[(0,l.jsxs)("label",{className:"skills-source-label",children:[(0,l.jsx)("span",{children:t("skills.source")}),(0,l.jsx)("div",{className:"skills-source-control",children:(0,l.jsx)("input",{type:"text","data-install":"source","aria-label":t("skills.source"),placeholder:t("skills.sourcePlaceholder"),value:e.installSource,onChange:r=>e.onInstallSourceChange(r.currentTarget.value)})})]}),(0,l.jsxs)("div",{className:"bd-section-note skills-install-note",children:[(0,l.jsxs)("span",{children:[(0,l.jsx)("strong",{children:t("skills.sourceHelpRemoteLabel")}),t("skills.sourceHelpRemote")]}),(0,l.jsxs)("span",{children:[(0,l.jsx)("strong",{children:t("skills.sourceHelpLocalLabel")}),t("skills.sourceHelpLocal")]})]}),(0,l.jsxs)("div",{className:"skills-install-action-row",children:[(0,l.jsxs)("details",{className:"skills-advanced-options","data-skills-advanced":!0,open:!1,children:[(0,l.jsxs)("summary",{children:[(0,l.jsx)("span",{className:"skills-advanced-marker","aria-hidden":"true"}),(0,l.jsx)("span",{children:t("skills.advanced")})]}),(0,l.jsxs)("div",{className:"skills-advanced-fields",children:[(0,l.jsxs)("label",{className:"skills-install-field-wide",children:[(0,l.jsx)("span",{children:t("skills.path")}),(0,l.jsx)("input",{type:"text","data-install":"path",placeholder:t("skills.pathPlaceholder"),value:e.installPath,onChange:r=>e.onInstallPathChange(r.currentTarget.value)})]}),(0,l.jsxs)("label",{className:"skills-install-field-wide",children:[(0,l.jsx)("span",{children:t("skills.ref")}),(0,l.jsx)("input",{type:"text","data-install":"ref",placeholder:t("skills.refPlaceholder"),value:e.installRef,onChange:r=>e.onInstallRefChange(r.currentTarget.value)})]})]})]}),(0,l.jsx)("div",{className:"skills-install-actions",children:(0,l.jsx)("button",{type:"button",className:"primary","data-action":"install",disabled:C,onClick:()=>e.onInstall(),children:e.installDiscovering?t("skills.scanning"):e.installBusy?t("skills.jobRunning"):t("skills.installSubmit")})})]}),(0,l.jsxs)("div",{className:"skills-local-discovery-panel",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:t("skills.localDiscoverTitle")}),(0,l.jsx)("span",{children:t("skills.localDiscoverHelp")})]}),(0,l.jsx)("button",{type:"button","data-action":"open-native-skill-discovery",onClick:()=>e.onOpenNativeDiscovery(),children:t("skills.localDiscover")})]})]}),(0,l.jsx)("div",{className:"actions",children:(0,l.jsx)("span",{className:Il(e.installStatus),"data-skills-status":!0,children:e.installStatus?.text??""})}),(0,l.jsx)("dialog",{className:"skills-discovery-dialog skills-install-selection-dialog","data-install-selection-dialog":!0,ref:n,onClose:()=>e.onCloseInstallSelection?.(),children:(0,l.jsxs)("article",{children:[(0,l.jsxs)("header",{children:[(0,l.jsx)("h3",{children:t("skills.installSelectionTitle")}),(0,l.jsx)("p",{children:t("skills.installSelectionHelp",{count:k.length})})]}),(0,l.jsx)("div",{className:"skills-discovery-body skills-install-selection-body",children:(0,l.jsxs)("div",{className:"skills-candidate-list","data-install-candidates":!0,children:[(0,l.jsxs)("div",{className:"skills-candidate-list-head",children:[(0,l.jsx)("span",{children:t("skills.scanFound",{count:k.length})}),e.onSelectAllInstallSkills?(0,l.jsx)("button",{type:"button","data-action":"toggle-all-source-skills",disabled:e.installBusy,onClick:()=>e.onSelectAllInstallSkills?.(!m),children:t(m?"skills.discoverClearSelection":"skills.discoverSelectAll")}):null]}),k.map(r=>(0,l.jsxs)("label",{className:"skills-candidate-row",children:[(0,l.jsx)("input",{type:"checkbox",checked:f.has(r.name),disabled:e.installBusy,onChange:()=>e.onToggleInstallSkill?.(r.name)}),(0,l.jsxs)("span",{children:[(0,l.jsx)("strong",{children:r.name}),(0,l.jsxs)("small",{children:[r.path,r.description?` \xB7 ${r.description}`:""]})]})]},`${r.name}:${r.path}`))]})}),(0,l.jsxs)("footer",{className:"actions",children:[(0,l.jsx)("button",{type:"button","data-action":"close-install-selection",disabled:e.installBusy,onClick:()=>e.onCloseInstallSelection?.(),children:t("skills.installSelectionCancel")}),(0,l.jsx)("button",{type:"button",className:"primary","data-action":"confirm-install-selection",disabled:e.installBusy||f.size===0,onClick:()=>e.onConfirmInstallSelection?.(),children:e.installBusy?t("skills.jobRunning"):t("skills.installSelected")})]})]})})]})}function ps(){let e=G(),t=(0,a.useRef)(!0),n=(0,a.useRef)(new Set),k=(0,a.useRef)(null),f=(0,a.useRef)(null),[m,C]=(0,a.useState)([]),[r,I]=(0,a.useState)([]),[v,D]=(0,a.useState)([]),[b,g]=(0,a.useState)("off"),[P,u]=(0,a.useState)("auto"),[R,sl]=(0,a.useState)(null),[el,tl]=(0,a.useState)(!0),[Pl,Rl]=(0,a.useState)(()=>window.innerWidth),[J,$l]=(0,a.useState)(""),[il,Bl]=(0,a.useState)(""),[al,Tl]=(0,a.useState)(""),[Dl,y]=(0,a.useState)(null),[Al,nl]=(0,a.useState)(!1),[jl,ol]=(0,a.useState)(!1),[xl,A]=(0,a.useState)(!1),[rl,cl]=(0,a.useState)([]),[_,j]=(0,a.useState)(()=>new Set),[K,x]=(0,a.useState)(!1),[El,dl]=(0,a.useState)(!1),[z,Ml]=(0,a.useState)(null),[W,F]=(0,a.useState)(()=>new Set),[B,V]=(0,a.useState)(0),[ul,E]=(0,a.useState)(null),[kl,M]=(0,a.useState)(null),[Ll,pl]=(0,a.useState)(null),[Ol,ml]=(0,a.useState)({}),L=(0,a.useMemo)(()=>new Set(m.map(s=>s.name)),[m]),O=us(Pl)*ns,$=Math.max(1,Math.ceil(m.length/O)),Hl=m.slice(B*O,B*O+O),N=(0,a.useMemo)(()=>r.length===0?void 0:(z?r.find(i=>U(i)===z):void 0)??r.find(i=>i.skills.length>0)??r[0],[z,r]),Q=N?U(N):"",T=(0,a.useMemo)(()=>N?N.skills.filter(s=>!L.has(s.name)).map(s=>s.rootDir??s.source?.root??"").filter(Boolean):[],[N,L]),vl=T.length>0&&T.every(s=>W.has(s)),yl=(0,a.useCallback)(()=>{for(let s of n.current)window.clearTimeout(s);n.current.clear()},[]),Gl=(0,a.useCallback)(s=>new Promise(i=>{let o=window.setTimeout(()=>{n.current.delete(o),i()},s);n.current.add(o)}),[]),fl=(0,a.useCallback)(async()=>{let[s,i]=await Promise.all([fetch("/api/skills"),fetch("/api/bots")]),o=await s.json().catch(()=>({})),d=await i.json().catch(()=>({}));if(!s.ok){let c=o?.error??`skills HTTP ${s.status}`;throw new Error(c==="not_found_yet"||c==="not_found"?e("skills.apiUnavailable"):c)}if(!i.ok)throw new Error(d?.error??`bots HTTP ${i.status}`);return{skills:Array.isArray(o.skills)?o.skills:[],nativeSkillGroups:Array.isArray(o.nativeSkillGroups)?o.nativeSkillGroups:[],bots:Array.isArray(d.bots)?d.bots:[],trustProjectSkills:o.trustProjectSkills==="all"?"all":"off",delivery:o.delivery==="prompt"||o.delivery==="native"?o.delivery:"auto"}},[e]),w=(0,a.useCallback)(async()=>{tl(!0);try{let s=await fl();if(!t.current)return;C(s.skills),I(s.nativeSkillGroups),D(s.bots),g(s.trustProjectSkills),u(s.delivery),sl(null),F(i=>{let o=new Set,d=new Set(s.skills.map(c=>c.name));for(let c of s.nativeSkillGroups)for(let p of c.skills){let S=p.rootDir??p.source?.root??"";S&&!d.has(p.name)&&i.has(S)&&o.add(S)}return o})}catch(s){if(!t.current)return;sl(s?.message??String(s))}finally{t.current&&tl(!1)}},[fl]);(0,a.useEffect)(()=>{t.current=!0,w();let s=()=>Rl(window.innerWidth);return window.addEventListener("resize",s),()=>{t.current=!1,yl(),window.removeEventListener("resize",s)}},[yl,w]),(0,a.useEffect)(()=>{V(s=>Math.min(Math.max(0,s),$-1))},[$]),(0,a.useEffect)(()=>{let s=k.current;if(s)if(K&&!s.open)try{s.showModal()}catch{}else!K&&s.open&&s.close()},[K,Q]);async function gl(s,i,o=!0){let d=s;for(i({text:e("skills.jobRunning"),ok:!0});;){if(!t.current)return;if(d.status==="succeeded"){i({text:e("skills.saved"),ok:!0}),o&&await w();return}if(d.status==="failed")throw new Error(d.error??"job_failed");if(await Gl(800),!t.current)return;let c=await h(`/api/skills/jobs/${encodeURIComponent(d.id)}`,{method:"GET"});if(!t.current)return;d=c.job}}function Ul(s){return v.filter(i=>q(i.skills).includes(s)).map(i=>i.botName??i.larkAppId)}function H(){cl([]),j(new Set),A(!1)}function bl(){return{source:J.trim(),path:il.trim()||void 0,ref:al.trim()||void 0}}function ql(s){let i=s??[..._];return{...bl(),skillNames:i.length>0?i:void 0}}async function Jl(){ol(!0),y({text:e("skills.scanning"),ok:!0});try{let s=await h("/api/skills/discover",{method:"POST",body:JSON.stringify(bl())});if(!t.current)return[];let i=Array.isArray(s.discovery?.skills)?s.discovery.skills:[];return cl(i),j(new Set(i.map(o=>o.name))),i}finally{t.current&&ol(!1)}}async function hl(s){nl(!0);try{let i=await h("/api/skills/install",{method:"POST",body:JSON.stringify(ql(s))});if(!t.current)return;await gl(i.job,y),t.current&&H()}catch(i){t.current&&y({text:`${e("skills.failed")}: ${i?.message??i}`,ok:!1})}finally{t.current&&nl(!1)}}function _l(s){j(i=>{let o=new Set(i);return o.has(s)?o.delete(s):o.add(s),o})}function Kl(s){j(s?new Set(rl.map(i=>i.name)):new Set)}async function zl(){if(!J.trim()){y({text:e("skills.sourceRequired"),ok:!1});return}try{A(!1);let s=await Jl();if(!t.current)return;if(s.length===0){y({text:e("skills.scanEmpty"),ok:!1});return}if(s.length===1){await hl([s[0].name]);return}y({text:e("skills.scanFound",{count:s.length}),ok:!0}),A(!0)}catch(s){t.current&&y({text:`${e("skills.failed")}: ${s?.message??s}`,ok:!1})}}async function Wl(){let s=[..._];if(s.length===0){y({text:e("skills.discoverNothingSelected"),ok:!1});return}await hl(s)}async function Fl(){let s=[...W].filter(Boolean);if(s.length===0){y({text:e("skills.discoverNothingSelected"),ok:!1});return}dl(!0);try{if(y({text:e("skills.discoverRegisteringBatch",{total:s.length}),ok:!0}),await h("/api/skills/install-local-links",{method:"POST",body:JSON.stringify({sources:s})}),!t.current)return;x(!1),await w(),t.current&&y({text:e("skills.saved"),ok:!0})}catch(i){t.current&&y({text:`${e("skills.failed")}: ${i?.message??i}`,ok:!1})}finally{t.current&&dl(!1)}}async function Vl(s){if(b!==s){E("project");try{let i=await h("/api/skills/global",{method:"PUT",body:JSON.stringify({trustProjectSkills:s})});if(!t.current)return;g(i.trustProjectSkills==="all"?"all":s)}catch(i){t.current&&window.alert(`${e("skills.failed")}: ${i?.message??i}`)}finally{t.current&&E(null)}}}async function Ql(s){if(P!==s){E("delivery");try{let i=await h("/api/skills/global",{method:"PUT",body:JSON.stringify({delivery:s})});if(!t.current)return;u(i.delivery==="prompt"||i.delivery==="native"?i.delivery:s)}catch(i){t.current&&window.alert(`${e("skills.failed")}: ${i?.message??i}`)}finally{t.current&&E(null)}}}function Sl(s){let i=f.current,o=i?.querySelector(".skills-bot-card");if(!i||!o)return;let d=window.getComputedStyle(i),c=Number.parseFloat(d.columnGap||d.gap||"0")||0;i.scrollBy({left:s*(o.getBoundingClientRect().width+c),behavior:"smooth"})}async function Xl(s){M(`${s}:update`);try{let i=await h(`/api/skills/${encodeURIComponent(s)}/update`,{method:"POST",body:"{}"});if(!t.current)return;await gl(i.job,y)}catch(i){t.current&&window.alert(`${e("skills.failed")}: ${i?.message??i}`)}finally{t.current&&M(null)}}async function Yl(s){if(window.confirm(`${e("skills.remove")} ${s}?`)){M(`${s}:remove`);try{if(await h(`/api/skills/${encodeURIComponent(s)}`,{method:"DELETE",body:"{}"}),!t.current)return;await w()}catch(i){if(!t.current)return;if(i?.status===409&&i?.body?.error==="skill_in_use"){let o=Array.isArray(i.body.affectedBots)?i.body.affectedBots.map(c=>{let p=c?.botName||c?.larkAppId;return p?`${p}`:""}).filter(Boolean):Ul(s),d=[o.length?`Bot: ${o.join(", ")}`:""].filter(Boolean).join("; ")||"-";if(!window.confirm(e("skills.removeInUse",{skill:s,refs:d})))return;try{if(await h(`/api/skills/${encodeURIComponent(s)}?force=1`,{method:"DELETE",body:"{}"}),!t.current)return;await w();return}catch(c){t.current&&window.alert(`${e("skills.failed")}: ${c?.message??c}`);return}}window.alert(`${e("skills.failed")}: ${i?.message??i}`)}finally{t.current&&M(null)}}}async function Zl(s,i,o){let d=`${s}:${i}:${o}`;pl(d),ml(c=>({...c,[s]:null}));try{let c=await h(`/api/bots/${encodeURIComponent(s)}/skills`,{method:"PUT",body:JSON.stringify({action:i,name:o})});if(!t.current)return;D(p=>p.map(S=>S.larkAppId===s?{...S,skills:c.skills??null}:S))}catch(c){t.current&&ml(p=>({...p,[s]:{text:`${e("skills.failed")}: ${c?.message??c}`,ok:!1}}))}finally{t.current&&pl(null)}}let ls=v.filter(s=>ds(s.skills)).length,ss=v.reduce((s,i)=>s+cs(i.skills),0),es=el?(0,l.jsx)(ll,{html:Nl(),as:"div"}):R?(0,l.jsx)("p",{className:"hint-warn",children:R}):(0,l.jsxs)("div",{className:"skills-page-grid",children:[(0,l.jsxs)("aside",{className:"skills-side-rail",children:[(0,l.jsxs)("article",{className:"bd-card skills-defaults-panel",children:[(0,l.jsx)("h3",{className:"bd-section-title",children:e("skills.globalDefaults")}),(0,l.jsxs)("div",{className:"skills-control-block",children:[(0,l.jsx)("span",{className:"skills-control-label",children:e("skills.globalProject")}),(0,l.jsx)("div",{className:"skills-choice-group skills-choice-group-compact skills-project-group",children:[["off",e("skills.globalProjectOff"),e("skills.globalProjectOffHelp")],["all",e("skills.globalProjectAll"),e("skills.globalProjectAllHelp")]].map(([s,i,o])=>(0,l.jsxs)("button",{type:"button",className:`skills-choice${b===s?" selected":""}`,"data-global-project-value":s,"aria-pressed":b===s?"true":"false",disabled:ul==="project",onClick:()=>{Vl(s)},children:[(0,l.jsx)("strong",{children:i}),(0,l.jsx)("small",{children:o})]},s))})]}),(0,l.jsxs)("div",{className:"skills-control-block",children:[(0,l.jsx)("span",{className:"skills-control-label",children:e("skills.globalDelivery")}),(0,l.jsx)("div",{className:"skills-choice-group skills-delivery-group",children:[["auto",e("skills.deliveryAuto"),e("skills.deliveryAutoHelp")],["prompt",e("skills.deliveryPrompt"),e("skills.deliveryPromptHelp")],["native",e("skills.deliveryNative"),e("skills.deliveryNativeHelp")]].map(([s,i,o])=>(0,l.jsxs)("button",{type:"button",className:`skills-choice${P===s?" selected":""}`,"data-global-delivery-value":s,"aria-pressed":P===s?"true":"false",disabled:ul==="delivery",onClick:()=>{Ql(s)},children:[(0,l.jsx)("strong",{children:i}),(0,l.jsx)("small",{children:o})]},s))})]})]}),(0,l.jsx)(ks,{installSource:J,installPath:il,installRef:al,installStatus:Dl,installBusy:Al,installDiscovering:jl,installSelectionOpen:xl,installCandidates:rl,selectedInstallSkills:_,onInstallSourceChange:s=>{$l(s),H()},onInstallPathChange:s=>{Bl(s),H()},onInstallRefChange:s=>{Tl(s),H()},onToggleInstallSkill:_l,onSelectAllInstallSkills:Kl,onConfirmInstallSelection:()=>{Wl()},onCloseInstallSelection:()=>A(!1),onInstall:()=>{zl()},onOpenNativeDiscovery:()=>x(!0)})]}),(0,l.jsxs)("section",{className:"skills-main-panel",children:[(0,l.jsxs)("section",{className:"skills-overview",children:[(0,l.jsxs)("div",{className:"skills-overview-copy",children:[(0,l.jsx)("h2",{children:e("skills.overviewTitle")}),(0,l.jsx)("p",{children:e("skills.overviewBody")})]}),(0,l.jsxs)("div",{className:"skills-metric-strip",children:[(0,l.jsxs)("span",{children:[(0,l.jsx)("small",{children:e("skills.metricInstalled")}),(0,l.jsx)("strong",{children:m.length})]}),(0,l.jsxs)("span",{children:[(0,l.jsx)("small",{children:e("skills.metricBots")}),(0,l.jsxs)("strong",{children:[ls,"/",v.length]})]}),(0,l.jsxs)("span",{children:[(0,l.jsx)("small",{children:e("skills.metricAttached")}),(0,l.jsx)("strong",{children:ss})]})]})]}),(0,l.jsxs)("section",{className:"skills-bots-panel",children:[(0,l.jsxs)("div",{className:"skills-section-head skills-section-head-row",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{children:e("skills.bots")}),(0,l.jsx)("p",{children:e("skills.botsHelp")})]}),v.length>3?(0,l.jsxs)("div",{className:"skills-bot-rail-actions",children:[(0,l.jsx)("button",{type:"button",className:"skills-rail-button","data-action":"scroll-bots","data-dir":"-1","aria-label":e("skills.scrollBotsPrev"),title:e("skills.scrollBotsPrev"),onClick:()=>Sl(-1),children:"\u2039"}),(0,l.jsx)("span",{className:"skills-count-pill",children:e("skills.botCount",{count:v.length})}),(0,l.jsx)("button",{type:"button",className:"skills-rail-button","data-action":"scroll-bots","data-dir":"1","aria-label":e("skills.scrollBotsNext"),title:e("skills.scrollBotsNext"),onClick:()=>Sl(1),children:"\u203A"})]}):(0,l.jsx)("span",{className:"skills-count-pill",children:e("skills.botCount",{count:v.length})})]}),(0,l.jsx)("div",{className:"skills-bot-grid",ref:f,children:v.map(s=>(0,l.jsx)(ms,{bot:s,installedNames:L,skills:m,status:Ol[s.larkAppId]??null,busyKey:Ll,onUpdate:Zl},s.larkAppId))})]}),(0,l.jsxs)("section",{className:"bd-card skills-installed-panel",children:[(0,l.jsxs)("div",{className:"skills-section-head skills-section-head-row",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{children:e("skills.installed")}),(0,l.jsx)("p",{children:e("skills.installedHelp")})]}),$<=1?(0,l.jsx)("span",{className:"skills-count-pill",children:e("skills.skillCount",{count:m.length})}):(0,l.jsxs)("div",{className:"skills-installed-toolbar",children:[(0,l.jsx)("span",{className:"skills-count-pill",children:e("skills.skillCount",{count:m.length})}),(0,l.jsxs)("div",{className:"skills-pager",children:[(0,l.jsx)("button",{type:"button",className:"skills-pager-button","data-action":"page-installed-skills","data-dir":"-1","aria-label":e("skills.prevPage"),title:e("skills.prevPage"),disabled:B===0,onClick:()=>V(s=>Math.max(0,s-1)),children:"\u2039"}),(0,l.jsx)("span",{children:e("skills.pageStatus",{page:B+1,pages:$})}),(0,l.jsx)("button",{type:"button",className:"skills-pager-button","data-action":"page-installed-skills","data-dir":"1","aria-label":e("skills.nextPage"),title:e("skills.nextPage"),disabled:B>=$-1,onClick:()=>V(s=>Math.min($-1,s+1)),children:"\u203A"})]})]})]}),m.length===0?(0,l.jsx)("p",{className:"empty",children:e("skills.empty")}):(0,l.jsx)("div",{className:"skills-list",children:Hl.map(s=>(0,l.jsxs)("article",{className:"skills-row skills-installed-card","data-skill":s.name,children:[(0,l.jsxs)("div",{className:"skills-row-body",children:[(0,l.jsx)("strong",{children:s.name}),s.description?(0,l.jsx)("p",{children:s.description}):null,(0,l.jsx)("small",{className:"skills-source-badge",children:rs(s,e)})]}),(0,l.jsxs)("div",{className:"skills-card-actions",children:[(0,l.jsx)("button",{type:"button","data-action":"update-skill",disabled:kl===`${s.name}:update`,onClick:()=>{Xl(s.name)},children:e("skills.update")}),(0,l.jsx)("button",{type:"button","data-action":"remove-skill",disabled:kl===`${s.name}:remove`,onClick:()=>{Yl(s.name)},children:e("skills.remove")})]})]},s.name))})]})]}),(0,l.jsx)("dialog",{className:"skills-discovery-dialog",id:"skills-discovery-dialog",ref:k,onClose:()=>x(!1),children:(0,l.jsxs)("article",{children:[(0,l.jsxs)("header",{children:[(0,l.jsx)("h3",{children:e("skills.discoverTitle")}),(0,l.jsx)("p",{children:e("skills.discoverHelp")})]}),(0,l.jsx)("div",{className:"skills-discovery-body",children:N?(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("div",{className:"skills-discovery-tabs",role:"tablist","aria-label":e("skills.discoverTitle"),children:r.map(s=>{let i=U(s),o=i===Q;return(0,l.jsxs)("button",{type:"button",role:"tab","data-discovery-tab":i,className:o?"selected":"","aria-selected":o?"true":"false",onClick:()=>Ml(i),children:[(0,l.jsx)("strong",{children:s.label??s.cliId}),(0,l.jsx)("small",{children:e("skills.skillCount",{count:s.skills.length})})]},i)})}),(0,l.jsx)("div",{className:"skills-discovery-path",children:(0,l.jsx)("code",{children:N.rootDir})}),r.map(s=>{let i=U(s);return(0,l.jsx)("section",{className:"skills-discovery-group","data-discovery-panel":i,hidden:!(i===Q),children:s.skills.length===0?(0,l.jsx)("p",{className:"empty",children:e("skills.discoverGroupEmpty")}):(0,l.jsx)("div",{className:"skills-discovery-list",children:s.skills.map(d=>{let c=L.has(d.name),p=d.rootDir??d.source?.root??"";return(0,l.jsxs)("label",{className:`skills-discovery-row${c?" installed":""}`,children:[(0,l.jsx)("input",{type:"checkbox","data-discovered-skill":!0,value:p,disabled:c,checked:!c&&W.has(p),onChange:S=>{let ts=S.currentTarget.checked;F(is=>{let X=new Set(is);return ts?X.add(p):X.delete(p),X})}}),(0,l.jsxs)("span",{children:[(0,l.jsx)("strong",{children:d.name}),d.description?(0,l.jsx)("small",{children:d.description}):null]}),c?(0,l.jsx)("em",{children:e("skills.discoverRegistered")}):null]},`${d.name}:${p}`)})})},i)})]}):(0,l.jsx)("p",{className:"empty",children:e("skills.discoverEmpty")})}),(0,l.jsxs)("footer",{className:"actions",children:[(0,l.jsx)("button",{type:"button","data-action":"toggle-discovered-skills",disabled:T.length===0,onClick:()=>{F(s=>{let i=new Set(s);return vl?T.forEach(o=>i.delete(o)):T.forEach(o=>i.add(o)),i})},children:e(vl?"skills.discoverClearSelection":"skills.discoverSelectAll")}),(0,l.jsx)("button",{type:"button",className:"primary","data-action":"register-discovered-skills",disabled:El,onClick:()=>{Fl()},children:e("skills.discoverRegister")}),(0,l.jsx)("button",{type:"button","data-action":"close-discovery",onClick:()=>x(!1),children:e("skills.discoverClose")})]})]})})]});return(0,l.jsxs)("section",{className:"page",children:[(0,l.jsxs)("div",{className:"page-heading",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("p",{className:"eyebrow",children:e("nav.skills")}),(0,l.jsx)("h1",{children:e("skills.title")}),(0,l.jsx)("p",{children:e("skills.subtitle")})]}),(0,l.jsx)("button",{type:"button",id:"skills-refresh",disabled:el,onClick:()=>{w()},children:e("skills.refresh")})]}),(0,l.jsx)("div",{id:"skills-body",children:es})]})}function ms(e){let t=G(),{bot:n,installedNames:k,skills:f,status:m,busyKey:C,onUpdate:r}=e,I=n.botName??n.larkAppId,v=q(n.skills),D=new Set(v),b=f.filter(u=>!D.has(u.name)),[g,P]=(0,a.useState)(b[0]?.name??"");return(0,a.useEffect)(()=>{(!g||!b.some(u=>u.name===g))&&P(b[0]?.name??"")},[b,g]),n.error?(0,l.jsxs)("article",{className:"bd-card skills-bot-card","data-appid":n.larkAppId,children:[(0,l.jsxs)("header",{children:[(0,l.jsx)(ll,{html:Z({name:I,larkAppId:n.larkAppId,size:"sm"})}),(0,l.jsx)("strong",{children:I})]}),(0,l.jsx)("p",{className:"hint-warn-inline",children:n.error})]}):(0,l.jsxs)("article",{className:"bd-card skills-bot-card","data-appid":n.larkAppId,children:[(0,l.jsxs)("header",{className:"skills-bot-head",children:[(0,l.jsx)(ll,{html:Z({name:I,larkAppId:n.larkAppId,size:"sm",dot:"ok"})}),(0,l.jsxs)("div",{children:[(0,l.jsx)("strong",{children:I}),(0,l.jsx)("code",{children:n.larkAppId})]}),(0,l.jsx)("span",{className:"skills-count-pill",children:t("skills.skillCount",{count:v.length})})]}),(0,l.jsxs)("section",{className:"bd-section",children:[(0,l.jsx)("h3",{className:"bd-section-title",children:t("skills.priority")}),v.length===0?(0,l.jsx)("p",{className:"bd-section-note",children:t("skills.noPriority")}):(0,l.jsx)("div",{className:"skills-chip-list",children:v.map(u=>{let R=!k.has(u);return(0,l.jsxs)("span",{className:`skills-priority-row${R?" skills-priority-dangling":""}`,title:R?t("skills.dangling"):"",children:[(0,l.jsxs)("span",{className:"skills-priority-name",children:[u,R?(0,l.jsx)("small",{children:t("skills.dangling")}):null]}),(0,l.jsx)("button",{type:"button",className:"skills-priority-remove","data-action":"detach-skill","data-name":u,"aria-label":t("skills.detachNamed",{skill:u}),disabled:C===`${n.larkAppId}:detach:${u}`,onClick:()=>{r(n.larkAppId,"detach",u)},children:"\xD7"})]},u)})}),(0,l.jsx)("div",{className:"actions skills-attach-row",children:b.length===0?(0,l.jsx)("button",{type:"button",disabled:!0,children:t("skills.attach")}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("select",{"data-attach-picker":!0,value:g,onChange:u=>P(u.currentTarget.value),children:b.map(u=>(0,l.jsx)("option",{value:u.name,children:u.name},u.name))}),(0,l.jsx)("button",{type:"button","data-action":"attach-skill",disabled:!g||C===`${n.larkAppId}:attach:${g}`,onClick:()=>g&&void r(n.larkAppId,"attach",g),children:t("skills.attach")})]})})]}),(0,l.jsx)("span",{className:Il(m),"data-bot-status":!0,children:m?.text??""})]})}function gs(e){return wl(e,(0,l.jsx)(ps,{}))}export{ms as BotPolicyCard,ks as SkillsInstallPanel,gs as renderSkillsPage};