botmux 2.99.0 → 2.101.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 (147) hide show
  1. package/README.en.md +33 -7
  2. package/README.md +33 -7
  3. package/dist/adapters/backend/sandbox.d.ts +33 -4
  4. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  5. package/dist/adapters/backend/sandbox.js +90 -29
  6. package/dist/adapters/backend/sandbox.js.map +1 -1
  7. package/dist/adapters/cli/hermes.d.ts.map +1 -1
  8. package/dist/adapters/cli/hermes.js +6 -0
  9. package/dist/adapters/cli/hermes.js.map +1 -1
  10. package/dist/adapters/cli/opencode.d.ts.map +1 -1
  11. package/dist/adapters/cli/opencode.js +241 -13
  12. package/dist/adapters/cli/opencode.js.map +1 -1
  13. package/dist/adapters/cli/traex.d.ts.map +1 -1
  14. package/dist/adapters/cli/traex.js +8 -6
  15. package/dist/adapters/cli/traex.js.map +1 -1
  16. package/dist/adapters/cli/types.d.ts +10 -3
  17. package/dist/adapters/cli/types.d.ts.map +1 -1
  18. package/dist/bot-registry.d.ts +12 -0
  19. package/dist/bot-registry.d.ts.map +1 -1
  20. package/dist/bot-registry.js +10 -3
  21. package/dist/bot-registry.js.map +1 -1
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +659 -154
  24. package/dist/cli.js.map +1 -1
  25. package/dist/core/cost-calculator.d.ts.map +1 -1
  26. package/dist/core/cost-calculator.js +26 -36
  27. package/dist/core/cost-calculator.js.map +1 -1
  28. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  29. package/dist/core/dashboard-ipc-server.js +37 -2
  30. package/dist/core/dashboard-ipc-server.js.map +1 -1
  31. package/dist/core/session-manager.d.ts +11 -0
  32. package/dist/core/session-manager.d.ts.map +1 -1
  33. package/dist/core/session-manager.js +87 -17
  34. package/dist/core/session-manager.js.map +1 -1
  35. package/dist/core/worker-pool.d.ts.map +1 -1
  36. package/dist/core/worker-pool.js +6 -0
  37. package/dist/core/worker-pool.js.map +1 -1
  38. package/dist/daemon.d.ts +1 -1
  39. package/dist/daemon.d.ts.map +1 -1
  40. package/dist/daemon.js +24 -8
  41. package/dist/daemon.js.map +1 -1
  42. package/dist/dashboard/bot-onboarding.d.ts +6 -0
  43. package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
  44. package/dist/dashboard/bot-onboarding.js +3 -1
  45. package/dist/dashboard/bot-onboarding.js.map +1 -1
  46. package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
  47. package/dist/dashboard/web/bot-onboarding.js +24 -3
  48. package/dist/dashboard/web/bot-onboarding.js.map +1 -1
  49. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  50. package/dist/dashboard/web/i18n.js +14 -4
  51. package/dist/dashboard/web/i18n.js.map +1 -1
  52. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  53. package/dist/dashboard/web/sessions.js +5 -19
  54. package/dist/dashboard/web/sessions.js.map +1 -1
  55. package/dist/dashboard-web/app.js +40 -33
  56. package/dist/dashboard-web/chunks/{bot-defaults-page-3EV7K6LJ.js → bot-defaults-page-HOGLABBC.js} +1 -1
  57. package/dist/dashboard-web/chunks/{chunk-NASYW5FD.js → chunk-ECXPBQ3J.js} +1 -1
  58. package/dist/dashboard-web/chunks/chunk-MR57RUVP.js +31 -0
  59. package/dist/dashboard-web/chunks/{connectors-XPZKEHF6.js → connectors-UGTF4Q4I.js} +1 -1
  60. package/dist/dashboard-web/chunks/{groups-page-C54PVKYP.js → groups-page-IKTCMQ4A.js} +1 -1
  61. package/dist/dashboard-web/chunks/{insights-page-BBQYR7WY.js → insights-page-7CCSHEKM.js} +1 -1
  62. package/dist/dashboard-web/chunks/{overview-page-5PJCAMID.js → overview-page-JOJW65P5.js} +1 -1
  63. package/dist/dashboard-web/chunks/{roles-page-APUDLPVM.js → roles-page-E2VN2DLV.js} +1 -1
  64. package/dist/dashboard-web/chunks/{schedules-WG2UKHSO.js → schedules-6QIHJIHX.js} +1 -1
  65. package/dist/dashboard-web/chunks/sessions-page-QN2TARF2.js +238 -0
  66. package/dist/dashboard-web/chunks/{settings-page-OSBZNCXL.js → settings-page-WWTXB577.js} +1 -1
  67. package/dist/dashboard-web/chunks/{skills-page-Y3VUAOYG.js → skills-page-2FAUPQ6H.js} +1 -1
  68. package/dist/dashboard-web/chunks/{team-federation-page-CRH3WZPH.js → team-federation-page-PTBQQSFS.js} +1 -1
  69. package/dist/dashboard-web/chunks/{workflows-UB7OPYGI.js → workflows-ZNBB5KFV.js} +1 -1
  70. package/dist/dashboard.js +86 -1
  71. package/dist/dashboard.js.map +1 -1
  72. package/dist/i18n/en.d.ts.map +1 -1
  73. package/dist/i18n/en.js +2 -0
  74. package/dist/i18n/en.js.map +1 -1
  75. package/dist/i18n/zh.d.ts.map +1 -1
  76. package/dist/i18n/zh.js +2 -0
  77. package/dist/i18n/zh.js.map +1 -1
  78. package/dist/im/lark/card-builder.d.ts +2 -2
  79. package/dist/im/lark/card-builder.js +2 -2
  80. package/dist/im/lark/event-dispatcher.d.ts +8 -3
  81. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  82. package/dist/im/lark/event-dispatcher.js +45 -9
  83. package/dist/im/lark/event-dispatcher.js.map +1 -1
  84. package/dist/platform/bind.d.ts.map +1 -1
  85. package/dist/platform/bind.js +36 -15
  86. package/dist/platform/bind.js.map +1 -1
  87. package/dist/platform/binding.d.ts +5 -0
  88. package/dist/platform/binding.d.ts.map +1 -1
  89. package/dist/platform/binding.js +11 -0
  90. package/dist/platform/binding.js.map +1 -1
  91. package/dist/platform/platform-http.d.ts +11 -0
  92. package/dist/platform/platform-http.d.ts.map +1 -0
  93. package/dist/platform/platform-http.js +41 -0
  94. package/dist/platform/platform-http.js.map +1 -0
  95. package/dist/platform/tunnel-client.d.ts +14 -0
  96. package/dist/platform/tunnel-client.d.ts.map +1 -1
  97. package/dist/platform/tunnel-client.js +40 -3
  98. package/dist/platform/tunnel-client.js.map +1 -1
  99. package/dist/services/bot-union-ids-store.d.ts +9 -0
  100. package/dist/services/bot-union-ids-store.d.ts.map +1 -0
  101. package/dist/services/bot-union-ids-store.js +59 -0
  102. package/dist/services/bot-union-ids-store.js.map +1 -0
  103. package/dist/services/coco-transcript.d.ts.map +1 -1
  104. package/dist/services/coco-transcript.js +59 -64
  105. package/dist/services/coco-transcript.js.map +1 -1
  106. package/dist/services/jsonl-cursor.d.ts +12 -0
  107. package/dist/services/jsonl-cursor.d.ts.map +1 -1
  108. package/dist/services/jsonl-cursor.js +63 -4
  109. package/dist/services/jsonl-cursor.js.map +1 -1
  110. package/dist/services/opencode-paths.d.ts +7 -0
  111. package/dist/services/opencode-paths.d.ts.map +1 -0
  112. package/dist/services/opencode-paths.js +18 -0
  113. package/dist/services/opencode-paths.js.map +1 -0
  114. package/dist/services/platform-team-store.d.ts +37 -0
  115. package/dist/services/platform-team-store.d.ts.map +1 -0
  116. package/dist/services/platform-team-store.js +120 -0
  117. package/dist/services/platform-team-store.js.map +1 -0
  118. package/dist/services/team-groups-store.d.ts +14 -1
  119. package/dist/services/team-groups-store.d.ts.map +1 -1
  120. package/dist/services/team-groups-store.js +28 -1
  121. package/dist/services/team-groups-store.js.map +1 -1
  122. package/dist/setup/bot-config-editor.d.ts +6 -0
  123. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  124. package/dist/setup/bot-config-editor.js +18 -15
  125. package/dist/setup/bot-config-editor.js.map +1 -1
  126. package/dist/setup/interactive-select.d.ts +22 -0
  127. package/dist/setup/interactive-select.d.ts.map +1 -1
  128. package/dist/setup/interactive-select.js +101 -7
  129. package/dist/setup/interactive-select.js.map +1 -1
  130. package/dist/setup/open-platform-automation.d.ts +42 -0
  131. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  132. package/dist/setup/open-platform-automation.js +107 -0
  133. package/dist/setup/open-platform-automation.js.map +1 -1
  134. package/dist/setup/setup-args.d.ts +77 -0
  135. package/dist/setup/setup-args.d.ts.map +1 -0
  136. package/dist/setup/setup-args.js +272 -0
  137. package/dist/setup/setup-args.js.map +1 -0
  138. package/dist/types.d.ts +6 -0
  139. package/dist/types.d.ts.map +1 -1
  140. package/dist/worker.js +12 -2
  141. package/dist/worker.js.map +1 -1
  142. package/dist/workflows/attempt-resume.d.ts.map +1 -1
  143. package/dist/workflows/attempt-resume.js +4 -1
  144. package/dist/workflows/attempt-resume.js.map +1 -1
  145. package/package.json +1 -1
  146. package/dist/dashboard-web/chunks/chunk-JXLHRRJD.js +0 -31
  147. package/dist/dashboard-web/chunks/sessions-page-F3U5NFPD.js +0 -238
@@ -0,0 +1,238 @@
1
+ import{b as jt}from"./chunk-ECXPBQ3J.js";import{a as _}from"./chunk-76J7PNZI.js";import{b as Nt,c as Bt,d as Rt,e as Qe,f as Pt,g as et,h as Ot,i as Dt,l as we,m as i,n as l,o as ue,p as ae,q as _t,r as qt,t as F,u as pe,v as U,y as Re}from"./chunk-MR57RUVP.js";import{a as Bn,b as Kt,c as Ut}from"./chunk-JTSE5VP6.js";import{c as Ze}from"./chunk-7SZRL6FY.js";var De=Ze(Bn(),1);var Pe=[24,72,168],Rn=new Set(Pe);function tt(a){let u=a==="7d"?168:Number(a);return!Number.isFinite(u)||!Rn.has(u)?null:u}function Pn(a){let u=Number(a);return Number.isFinite(u)&&u>0?u:null}function On(a,u=Date.now()){return u-a*60*60*1e3}function Dn(a,u,b=Date.now()){if(!a.sessionId||a.status!=="idle"||a.locked||a.pendingRepo||a.tuiPromptActive||a.agentAttention)return!1;let f=Pn(a.lastMessageAt);return f!==null&&f<On(u,b)}function Ft(a,u,b=Date.now()){return a.filter(f=>Dn(f,u,b))}var zt=["backlog","todo","in_progress","in_review","done"];function Wt(a){return typeof a=="string"&&zt.includes(a)?a:null}function Gt(a){if(a.status==="closed")return"done";let u=Wt(a.kanbanColumn);return u||(a.pendingRepo||a.tuiPromptActive||a.agentAttention||a.status==="limited"?"in_review":a.status==="starting"||a.status==="working"||a.status==="analyzing"||a.status==="active"?"in_progress":"todo")}var _n=1e15;function oe(a){if(typeof a.kanbanPosition=="number"&&Number.isFinite(a.kanbanPosition))return a.kanbanPosition;let u=typeof a.lastMessageAt=="number"&&Number.isFinite(a.lastMessageAt)?a.lastMessageAt:0;return _n-u}function nt(a,u){return a!==null&&u!==null?(a+u)/2:a!==null?a+1024:u!==null?u-1024:1024}var Vt={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"},ss=new Set(Object.values(Vt)),qn={"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"},Jt=Object.values(Vt).map(a=>({id:a,label:qn[a]??a}));function it(a){return typeof a=="number"&&Number.isFinite(a)?a:null}function Yt(a){let u=it(a);return u===null?"-":u.toLocaleString("en-US")}var nn=[...Jt.map(a=>a.id),"unknown"],Xt=[{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"}],st=50;function Kn(a){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(a){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 Oe(a){return String(a??"unknown").toLowerCase().replace(/[^a-z0-9_-]/g,"-")}var sn=["starting","working","idle","dormant","analyzing","active","limited","closed"];function Ie(a){let u=String(a??"unknown"),b=`sessions.status.${u}`,f=i(b);return f===b?u:f}function Se(a){let u=String(a??"unknown");return`<span class="status status-${l(Oe(u))}">${l(Ie(u))}</span>`}function Qt(a){let u=String(a??"").trim();return u?u.replace(/\\/g,"/").split("/").filter(Boolean).at(-1)??u:"-"}function at(a){if(!a.webPort)return null;if(location.protocol==="https:")return a.proxyPort?`${location.origin}/s/${encodeURIComponent(a.sessionId)}`:null;let u=a.proxyPort??a.webPort,b=a.proxyPort?`/s/${encodeURIComponent(a.sessionId)}`:"";return`http://${location.hostname}:${u}${b}`}var L={pin:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 14.3s4.2-3.9 4.2-7.3A4.2 4.2 0 0 0 8 2.9a4.2 4.2 0 0 0-4.2 4.1C3.8 10.4 8 14.3 8 14.3z"/><circle cx="8" cy="6.9" r="1.5"/></svg>',openChat:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M9.4 2.8h3.8v3.8"/><path d="M13.2 2.8 7.3 8.7"/><path d="M11.5 9.3v2.9a1.2 1.2 0 0 1-1.2 1.2H3.8a1.2 1.2 0 0 1-1.2-1.2V5.7a1.2 1.2 0 0 1 1.2-1.2h2.9"/></svg>',details:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2.2" y="2.9" width="11.6" height="10.2" rx="1.8"/><path d="M9.9 2.9v10.2"/></svg>',terminal:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="1.7" y="2.7" width="12.6" height="10.6" rx="2"/><path d="M4.4 6.3 6.4 8.1 4.4 9.9"/><path d="M8.2 10.2h3.4"/></svg>',key:'<svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="6" cy="6.1" r="3"/><path d="M8.1 8.2 13 13.1"/><path d="M11.3 11.4 12.6 10.1"/><path d="M12.7 12.8 13.7 11.8"/></svg>',lock:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="3.2" y="7" width="9.6" height="6.2" rx="1.4"/><path d="M5.2 7V5.2a2.8 2.8 0 0 1 5.6 0V7"/></svg>',unlock:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="3.2" y="7" width="9.6" height="6.2" rx="1.4"/><path d="M5.2 7V5.2a2.8 2.8 0 0 1 5.2-1.4"/></svg>',close:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4.2 4.2 11.8 11.8"/><path d="M11.8 4.2 4.2 11.8"/></svg>',edit:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M10.7 3.3 12.7 5.3 6.3 11.7 3.7 12.3 4.3 9.7 10.7 3.3z"/></svg>',history:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M2.2 4.8a2 2 0 0 1 2-2h7.6a2 2 0 0 1 2 2v4.6a2 2 0 0 1-2 2H6.6l-2.9 2.4v-2.4h-.5a2 2 0 0 1-2-2z"/><path d="M5.2 6.2h5.6M5.2 8.4h3.6"/></svg>',restart:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M12.4 6.2a4.8 4.8 0 1 0 1.1 3.1"/><path d="M12.4 2.9v3.3H9.1"/></svg>',feishu:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M2.6 4.4C6.4 4 10.4 5.4 13.4 8.2 9.8 7 6.4 6.6 3.4 7.4"/><path d="M13.4 8.2C9.6 8.7 6 10 2.9 12 5.6 9 8.8 7.6 13.4 8.2"/></svg>'};function Te(a,u,b,f=""){return`<button type="button" class="card-act${f?" "+f:""}" data-action="${a}" title="${l(b)}" aria-label="${l(b)}">${u}</button>`}function Ce(a){return a.locked?i("sessions.unlock"):i("sessions.lock")}function Le(a){return a.locked?`<span class="session-lock-badge" title="${l(i("sessions.locked"))}">${l(i("sessions.locked"))}</span>`:""}function en(a){if(!a)return"";let u=`<a class="term-btn term-open" href="${l(a)}" target="_blank" rel="noopener" title="${l(i("sessions.openTerminal"))}" aria-label="${l(i("sessions.openTerminal"))}">${L.terminal}</a>`;if(!we.authed)return`<span class="term-pill solo">${u}</span>`;let b=`<button type="button" class="term-btn term-write" data-action="write-link" title="${l(i("sessions.writeLinkHint"))}" aria-label="${l(i("sessions.writeLink"))}">${L.key}</button>`;return`<span class="term-pill">${u}${b}</span>`}async function tn(a,u){let b=window.open("about:blank","_blank");b&&(b.opener=null),u&&(u.disabled=!0);try{let f=await fetch(`/api/sessions/${encodeURIComponent(a.sessionId)}/write-link`),v=await f.json().catch(()=>({}));if(!f.ok||v?.ok===!1||!v?.url){b?.close(),f.status!==401&&alert(`${i("sessions.writeLinkFail")}: ${v?.error??f.status}`);return}b?b.location.href=v.url:window.open(v.url,"_blank","noopener")}catch(f){b?.close(),alert(`${i("sessions.writeLinkFail")}: ${f}`)}finally{u&&(u.disabled=!1)}}function Un(a){return a.status==="closed"?null:a.pendingRepo||a.tuiPromptActive||a.agentAttention||a.status==="limited"?"needs-you":a.status==="starting"?"starting":a.status==="working"||a.status==="analyzing"||a.status==="active"?"working":(a.status==="dormant","idle")}function an(){return`<details class="filter-cli">
2
+ <summary>${i("sessions.cli")} \xB7 <b id="cli-filter-count">${i("common.all")}</b></summary>
3
+ <div class="filter-cli-pop" role="group" aria-label="${i("sessions.cli")}">
4
+ ${nn.map(a=>`
5
+ <label class="filter-check">
6
+ <input type="checkbox" name="cli" value="${l(a)}" checked>
7
+ <span>${l(a)}</span>
8
+ </label>
9
+ `).join("")}
10
+ </div>
11
+ </details>`}function jn(a){let u=String(a.status??"unknown"),b=String(a.cliId??"unknown"),f=we.locale==="zh"?"\uFF1A":": ";return[i("sessions.restartConfirmIntro"),"",`${i("sessions.restartConfirmStatus")}${f}${Ie(u)}`,`${i("sessions.restartConfirmCli")}${f}${b}`,"",i("sessions.restartConfirmQuestion")].join(`
12
+ `)}function ot(a){return a.status!=="closed"&&!a.adopt&&!a.pendingRepo}async function Fn(){try{let a=await fetch("/api/groups");if(!a.ok)return[];let u=await a.json();return(Array.isArray(u?.bots)?u.bots:[]).filter(f=>f&&typeof f.larkAppId=="string").map(f=>({larkAppId:f.larkAppId,botName:typeof f.botName=="string"&&f.botName?f.botName:f.larkAppId}))}catch{return[]}}function zn(a){let u=a.map(b=>`
13
+ <label class="cs-bot"><input type="checkbox" name="bot" value="${l(b.larkAppId)}"> <span>${l(b.botName)}</span></label>`).join("");return`
14
+ <article class="cs-card">
15
+ <header><h3>${i("sessions.create.title")}</h3></header>
16
+ <form id="cs-form">
17
+ <label class="form-row">
18
+ <span>${i("sessions.create.content")}</span>
19
+ <textarea name="content" rows="5" placeholder="${l(i("sessions.create.contentPlaceholder"))}" required></textarea>
20
+ </label>
21
+ <fieldset class="cs-bots">
22
+ <legend>${i("sessions.create.bots")}</legend>
23
+ ${u||`<p class="cs-empty">${i("sessions.create.noBots")}</p>`}
24
+ </fieldset>
25
+ <fieldset class="cs-mode">
26
+ <legend>${i("sessions.create.mode")}</legend>
27
+ <label><input type="radio" name="mode" value="lead" checked> ${i("sessions.create.modeLead")}</label>
28
+ <label><input type="radio" name="mode" value="all"> ${i("sessions.create.modeAll")}</label>
29
+ <small>${i("sessions.create.modeHelp")}</small>
30
+ </fieldset>
31
+ <div class="cs-lead-row form-row" hidden>
32
+ <span>${i("sessions.create.lead")}</span>
33
+ <select name="lead"></select>
34
+ <small>${i("sessions.create.leadHelp")}</small>
35
+ </div>
36
+ <fieldset class="cs-column">
37
+ <legend>${i("sessions.create.column")}</legend>
38
+ <label><input type="radio" name="column" value="in_progress" checked> ${i("sessions.create.columnInProgress")}</label>
39
+ <label><input type="radio" name="column" value="backlog"> ${i("sessions.create.columnBacklog")}</label>
40
+ <small>${i("sessions.create.columnHelp")}</small>
41
+ </fieldset>
42
+ <details class="cs-advanced">
43
+ <summary>${i("sessions.create.advanced")}</summary>
44
+ <label class="form-row">
45
+ <span>${i("sessions.create.groupName")}</span>
46
+ <input type="text" name="name" maxlength="60" placeholder="${l(i("sessions.create.groupNamePlaceholder"))}">
47
+ </label>
48
+ <label class="form-row">
49
+ <span>${i("sessions.create.workingDir")}</span>
50
+ <input type="text" name="bindWorkingDir" placeholder="e.g. ~/projects/foo">
51
+ <small>${i("sessions.create.workingDirHelp")}</small>
52
+ </label>
53
+ </details>
54
+ <div class="actions cs-actions">
55
+ <button type="submit" class="primary">${i("sessions.create.submit")}</button>
56
+ <button type="button" id="cs-cancel">${i("sessions.create.cancel")}</button>
57
+ </div>
58
+ </form>
59
+ </article>`}function Wn(a,u){u.onclick=async()=>{u.disabled=!0;try{let b=await Fn();if(b.length===0){alert(i("sessions.create.noBots"));return}a.innerHTML=zn(b),a.showModal(),Gn(a,b)}finally{u.disabled=!1}}}function Gn(a,u){let b=a.querySelector("#cs-form"),f=a.querySelector(".cs-lead-row"),v=a.querySelector("select[name=lead]"),me=E=>u.find(P=>P.larkAppId===E)?.botName??E,ie=()=>Array.from(b.querySelectorAll("input[name=bot]:checked")).map(E=>E.value),W=()=>b.querySelector("input[name=mode]:checked")?.value??"all";function V(){let E=ie(),P=v.value;if(E.length===0){v.innerHTML=`<option value="" disabled selected>${l(i("sessions.create.leadPickFirst"))}</option>`,v.disabled=!0;return}v.disabled=!1,v.innerHTML=E.map(J=>`<option value="${l(J)}">${l(me(J))}</option>`).join(""),E.includes(P)&&(v.value=P)}function j(){W()==="lead"?(f.hidden=!1,V()):f.hidden=!0}b.querySelectorAll("input[name=mode]").forEach(E=>E.addEventListener("change",j)),b.querySelectorAll("input[name=bot]").forEach(E=>E.addEventListener("change",()=>{W()==="lead"&&V()})),j(),a.querySelector("#cs-cancel").onclick=()=>a.close(),b.onsubmit=async E=>{E.preventDefault();let P=new FormData(b),J=(P.get("content")??"").trim(),Q=ie(),be=W(),ee=P.get("column")??"in_progress",fe=(P.get("name")??"").trim(),O=(P.get("bindWorkingDir")??"").trim(),T=P.get("lead")??"";if(!J){alert(i("sessions.create.errContent"));return}if(Q.length===0){alert(i("sessions.create.errNoBot"));return}if(be==="lead"&&(!T||!Q.includes(T))){alert(i("sessions.create.errLead"));return}let $=b.querySelector("button[type=submit]");$&&($.disabled=!0,$.textContent=i("sessions.create.submitting"));try{let S=await fetch("/api/sessions/create",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({content:J,larkAppIds:Q,mode:be,column:ee,leadLarkAppId:be==="lead"?T:void 0,name:fe||void 0,bindWorkingDir:O||void 0})}),te=await S.json().catch(()=>null);S.ok&&te?.ok?Vn(a,te):S.status!==401&&(alert(`${i("sessions.create.failed")}: ${te?.error??S.status}`),$&&($.disabled=!1,$.textContent=i("sessions.create.submit")))}catch(S){alert(`${i("sessions.create.failed")}: ${S}`),$&&($.disabled=!1,$.textContent=i("sessions.create.submit"))}}}function Vn(a,u){let b=typeof u.shareLink=="string"&&u.shareLink?u.shareLink:"",f=Array.isArray(u.failed)?u.failed.length:0,v=Array.isArray(u.spawned)?u.spawned.length:0,me=u.column==="backlog"?i("sessions.create.doneBacklog"):i("sessions.create.doneInProgress"),ie=f>0?`<p class="cs-warn">${i("sessions.create.partialFail",{n:String(f)})}</p>`:"";a.innerHTML=`
60
+ <article class="cs-card">
61
+ <header><h3>${i("sessions.create.doneTitle")}</h3></header>
62
+ <p>${l(me)}\uFF08${v}\uFF09</p>
63
+ ${ie}
64
+ ${b?`<p><a href="${l(b)}" target="_blank" rel="noopener">${i("sessions.create.openChat")}</a></p>`:""}
65
+ <div class="actions"><button type="button" id="cs-done" class="primary">${i("sessions.create.close")}</button></div>
66
+ </article>`,a.querySelector("#cs-done").onclick=()=>a.close()}function on(a){let u=a.querySelector("#sessions-table tbody"),b=a.querySelector("#filters"),f=a.querySelector("#drawer"),v=a.querySelector("#select-all"),me=a.querySelector("#bulk-bar"),ie=a.querySelector("#bulk-count"),W=a.querySelector("#bulk-lock"),V=a.querySelector("#bulk-unlock"),j=a.querySelector("#bulk-close"),E=a.querySelector("#bulk-clear"),P=a.querySelector("#idle-cleanup-bar"),J=a.querySelector("#idle-cleanup-threshold"),Q=a.querySelector("#idle-cleanup-run"),be=a.querySelector("#idle-cleanup-count"),ee=a.querySelector("#idle-cleanup-status"),fe=a.querySelector("#sessions-table"),O=a.querySelector("#sessions-board"),T=a.querySelector("#sessions-kanban"),$=a.querySelector("#term-modal"),S=a.querySelector("#history-modal"),te=a.querySelector("#kanban-groupby"),q=a.querySelector("#kanban-team"),rt=a.querySelector("#kanban-team-stats"),lt=a.querySelectorAll(".sessions-view-toggle [data-view]"),rn=a.querySelector("#create-session-btn"),dt=a.querySelector("#create-session-modal");Wn(dt,rn);let w=new Set,ge="lastMessageAt",re="desc",H=Bt(window.localStorage),K=Rt(window.localStorage),Y=null,_e="",qe="",C="",ct=!1,ne=null,Ke=!1,ye=null,le=new Map,D=Ot(window.localStorage),se=null,Me=null,B=[],Ue=null,Ee=!1,je=!1,X=(()=>{try{return window.localStorage.getItem(et)??""}catch{return""}})(),He=!1,Ae=24;function ut(){return Ae}function ln(e){return e===168?"7d":`${e}H`}function pt(e){let t=new Set;if(!e)return t;for(let o of e.groupChats)t.add(o);if(Ue)for(let[o,n]of Ue){if(t.has(o))continue;let s=!1;for(let r of e.botIds)if(n.botIds.has(r)){s=!0;break}if(s){for(let r of n.observedNames)if(e.botNames.has(r)){t.add(o);break}}}return t}function dn(){let e=he();if(H==="kanban"&&D==="team"){let t=B.find(n=>n.key===X)??B[0],o=pt(t);return e.filter(n=>o.has(String(n.chatId)))}return e}function mt(){return Ft(dn(),ut())}function cn(){J.querySelectorAll("button[data-hours]").forEach(e=>{let t=tt(e.dataset.hours)===Ae;e.classList.toggle("active",t),e.setAttribute("aria-pressed",t?"true":"false")})}async function un(){if(!(je||Ee)){je=!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)&&(Ue=new Map(o.chats.map(r=>[String(r.chatId),{botIds:new Set((r.memberBots??[]).filter(d=>d.inChat).map(d=>String(d.larkAppId))),observedNames:new Set((r.observedBotNames??[]).map(d=>String(d)))}])));let n=r=>({ids:new Set(r.map(d=>String(d.larkAppId))),names:new Set(r.map(d=>String(d.name??"")).filter(Boolean))}),s=[];for(let r of e?.teams??[]){let{ids:d,names:c}=n(r.bots??[]);s.push({key:`local:${r.teamId}`,label:r.isDefault?i("team.myHostedTeam"):String(r.name??r.teamId),botIds:d,botNames:c,groupChats:new Set((r.groupChatIds??[]).map(m=>String(m)))})}for(let r of t?.memberships??[]){let{ids:d,names:c}=n(r.roster?.bots??[]);s.push({key:`${r.hubUrl}::${r.teamId}`,label:String(r.teamName??r.teamId??r.hubUrl),botIds:d,botNames:c,groupChats:new Set})}B=s}finally{Ee=!0,je=!1}B.length&&!B.some(e=>e.key===X)&&(X=B[0].key),delete q.dataset.loading,q.disabled=B.length===0,q.innerHTML=B.length?B.map(e=>`<option value="${l(e.key)}"${e.key===X?" selected":""}>${l(e.label)}</option>`).join(""):`<option value="">${l(i("sessions.kanban.noTeam"))}</option>`,C="",y()}}let A=null,de="",bt=0,Fe=!1,ze=new Map;async function pn(e){let t=de===e.key&&Date.now()-bt<3e4;if(!(Fe||t)){Fe=!0;try{let n=e.key.startsWith("local:")?`/api/team/board/local/${encodeURIComponent(e.key.slice(6))}`:`/api/team/remote-board?key=${encodeURIComponent(e.key)}`,s=await fetch(n),r=await s.json().catch(()=>({}));if(!s.ok||r?.ok===!1)return;let d=typeof r.deploymentId=="string"?r.deploymentId:null,c=[];ze=new Map;for(let m of Array.isArray(r.reports)?r.reports:[])if(!(d&&m.deploymentId===d))for(let g of Array.isArray(m.sessions)?m.sessions:[]){let I={...g,remoteDeployment:m.deploymentName||m.deploymentId};c.push(I),ze.set(String(g.sessionId),I)}A={board:r.board&&typeof r.board=="object"?r.board:{},remoteRows:c},de=e.key,bt=Date.now(),C="",y()}catch{}finally{Fe=!1}}}async function mn(e,t,o,n,s){try{let d=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})}),c=await d.json().catch(()=>({}));(!d.ok||c?.ok===!1)&&(A&&(s?A.board[t]=s:delete A.board[t]),C="",y(),d.status!==401&&alert(`${i("sessions.kanban.moveFail")}: ${c?.error??d.status}`))}catch(r){A&&(s?A.board[t]=s:delete A.board[t]),C="",y(),alert(`${i("sessions.kanban.moveFail")}: ${r}`)}}function ft(e,t,o){let n=B.find(r=>r.key===X)??B[0];if(!n)return;(!A||de!==n.key)&&(A={board:{},remoteRows:A?.remoteRows??[]},de=n.key);let s=A.board[e];A.board[e]={column:t,position:o},mn(n.key,e,t,o,s)}function bn(){return K.map(e=>Xt.find(t=>t.id===e)).filter(e=>!!e)}function fn(e,t){let o=K.indexOf(e),n=o+t;if(o<0||n<0||n>=K.length)return;let s=[...K];s.splice(o,1),s.splice(n,0,e),K=s,Qe(window.localStorage,K),y()}function gn(e,t){if(e===t)return;let o=K.indexOf(e),n=K.indexOf(t);if(o<0||n<0)return;let s=[...K];s.splice(o,1),s.splice(n,0,e),K=s,Qe(window.localStorage,K),y()}function yn(e){let t=e.status==="closed",o=w.has(e.sessionId)?"checked":"";return`<tr data-id="${l(e.sessionId)}">
67
+ <td><input type="checkbox" class="row-select" ${o} ${t?"disabled":""}></td>
68
+ <td>${l(F(e))}</td>
69
+ <td><span class="badge cli-${Oe(e.cliId)}">${l(e.cliId??"unknown")}</span></td>
70
+ <td>${Se(e.status)}${Le(e)}</td>
71
+ <td class="token-cell">${Yt(e.tokenUsage?.in)}</td>
72
+ <td class="token-cell">${Yt(e.tokenUsage?.out)}</td>
73
+ <td title="${l(String(e.title??""))}">${l(U(e.title??"").slice(0,48))}</td>
74
+ <td title="${l(e.workingDir??"")}">${l((e.workingDir??"").slice(-34))}</td>
75
+ <td>${ue(e.spawnedAt)}</td>
76
+ <td>${ue(e.lastMessageAt)}</td>
77
+ <td>${e.adopt?'<span class="badge">adopt</span>':""}</td>
78
+ <td><button class="open" type="button">${i("sessions.details")}</button></td>
79
+ </tr>`}function gt(e){if(e.scope!=="chat"||!e.feishuChatLink)return null;let t=i("sessions.openChat");return`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(t)}" aria-label="${l(t)}">${L.feishu}</a>`}function yt(e){return e.agentAttention?.reason?e.agentAttention.reason:e.agentAttention?i("sessions.board.signalAgent"):e.pendingRepo?i("sessions.board.signalRepo"):e.tuiPromptActive?i("sessions.board.signalPrompt"):e.status==="limited"?i("sessions.board.signalLimited"):""}function hn(e){let t=w.has(e.sessionId),o=U(e.title)||e.sessionId,n=F(e),s=pe(e),r=at(e),d=yt(e),c=Qt(e.workingDir);return`<article class="session-card${t?" selected":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" aria-pressed="${t}">
80
+ <div class="session-card-top">
81
+ ${ae({name:n,larkAppId:e.larkAppId,size:"sm"})}
82
+ <div class="session-card-title">
83
+ <strong title="${l(String(e.title??o))}">${l(String(o).slice(0,72))}</strong>
84
+ <span>${l(n)} \xB7 ${l(s??e.cliId??"unknown")}</span>
85
+ </div>
86
+ <span class="session-card-status-group">
87
+ ${Se(e.status)}
88
+ ${Le(e)}
89
+ </span>
90
+ </div>
91
+ ${c!=="-"||e.adopt?`<div class="session-card-meta">
92
+ ${c!=="-"?`<span title="${l(e.workingDir??"")}">${l(c)}</span>`:""}
93
+ ${e.adopt?'<span class="badge">adopt</span>':""}
94
+ </div>`:""}
95
+ <div class="session-card-time">
96
+ <span>${e.agentAttention?.at?`${l(i("sessions.board.waiting"))} ${ue(Re(e))}`:`${l(i("sessions.last"))}: ${ue(e.lastMessageAt)}`}</span>
97
+ </div>
98
+ ${d?`<div class="session-signal" title="${l(d)}">${l(d)}</div>`:""}
99
+ <div class="session-card-actions">
100
+ ${gt(e)??Te("locate",L.pin,i("sessions.locate"))}
101
+ ${Te("details",L.details,i("sessions.details"))}
102
+ ${ot(e)?Te("restart",L.restart,i("sessions.restart")):""}
103
+ ${en(r)}
104
+ ${Te("lock",e.locked?L.unlock:L.lock,Ce(e),e.locked?"locked":"")}
105
+ ${Te("close",L.close,i("sessions.close"),"danger")}
106
+ </div>
107
+ </article>`}function kn(e,t,o){let n=o==="needs-you"?Re(e):Number(e.lastMessageAt??0),s=o==="needs-you"?Re(t):Number(t.lastMessageAt??0);return n!==s?o==="needs-you"?n-s:s-n:String(e.title??e.sessionId).localeCompare(String(t.title??t.sessionId))}function $n(e){let t=new Map(Xt.map(s=>[s.id,[]]));for(let s of e){let r=Un(s);r&&t.get(r).push(s)}let o=bn(),n=o.map((s,r)=>{let d=(t.get(s.id)??[]).sort((c,m)=>kn(c,m,s.id));return`<section class="session-board-column session-board-${s.id}" data-col="${s.id}">
108
+ <header draggable="true" title="${l(i("sessions.board.dragHint"))}">
109
+ <div>
110
+ <h2>${l(i(s.labelKey))}</h2>
111
+ <p>${l(i(s.hintKey))}</p>
112
+ </div>
113
+ <span class="session-board-head-right">
114
+ <span class="session-board-move">
115
+ <button type="button" data-move-col="${s.id}" data-dir="-1"
116
+ aria-label="${l(i("sessions.board.moveLeft"))}" ${r===0?"disabled":""}>\u2039</button>
117
+ <button type="button" data-move-col="${s.id}" data-dir="1"
118
+ aria-label="${l(i("sessions.board.moveRight"))}" ${r===o.length-1?"disabled":""}>\u203A</button>
119
+ </span>
120
+ <span class="session-board-count">${d.length}</span>
121
+ </span>
122
+ </header>
123
+ <div class="session-board-list">
124
+ ${d.length?d.map(hn).join(""):`<div class="session-board-empty">${i("sessions.board.emptyColumn")}</div>`}
125
+ </div>
126
+ </section>`}).join("");n!==_e&&(_e=n,O.innerHTML=n,O.classList.toggle("board-enter",!ct),ct=!0)}function ht(e){let t=U(e.title)||e.sessionId,o=F(e),n=pe(e),s=Qt(e.workingDir),r=yt(e),d=[n,s!=="-"?s:null].filter(Boolean).join(" \xB7 "),c=String(e.status??"unknown"),m=typeof e.remoteDeployment=="string"?e.remoteDeployment:"";return`<article class="kanban-card${m?" kanban-card-remote":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" tabindex="0" role="button" draggable="true">
127
+ <div class="kanban-card-top">
128
+ <span class="badge cli-${Oe(e.cliId)}">${l(e.cliId??"unknown")}</span>
129
+ ${e.adopt?'<span class="badge">adopt</span>':""}
130
+ ${Le(e)}
131
+ ${m?`<span class="badge kanban-remote-badge" title="${l(i("sessions.kanban.remoteHint",{name:m}))}">${l(m)}</span>`:""}
132
+ <span class="kanban-card-top-right">
133
+ <span class="kanban-card-dot" data-status="${l(Oe(c))}" title="${l(Ie(c))}"></span>
134
+ ${m?"":`<button type="button" class="card-act kanban-card-act" data-action="history" title="${l(i("sessions.history.title"))}" aria-label="${l(i("sessions.history.title"))}">${L.history}</button>
135
+ ${e.feishuChatLink?`<a class="card-act kanban-card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(i("sessions.kanban.openFeishu"))}" aria-label="${l(i("sessions.kanban.openFeishu"))}">${L.feishu}</a>`:""}
136
+ <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?L.unlock:L.lock}</button>
137
+ <button type="button" class="card-act kanban-card-act" data-action="details" title="${l(i("sessions.details"))}" aria-label="${l(i("sessions.details"))}">${L.details}</button>
138
+ ${ot(e)?`<button type="button" class="card-act kanban-card-act" data-action="restart" title="${l(i("sessions.restart"))}" aria-label="${l(i("sessions.restart"))}">${L.restart}</button>`:""}`}
139
+ </span>
140
+ </div>
141
+ <p class="kanban-card-title" title="${l(String(e.title??t))}">${l(String(t).slice(0,140))}</p>
142
+ ${d?`<p class="kanban-card-desc" title="${l(d)}">${l(d)}</p>`:""}
143
+ ${r?`<div class="session-signal" title="${l(r)}">${l(r)}</div>`:""}
144
+ <div class="kanban-card-foot">
145
+ <span class="kanban-card-owner">${ae({name:o,larkAppId:e.larkAppId,size:"sm"})}<span>${l(o)}</span></span>
146
+ <span class="kanban-card-updated">${l(i("sessions.kanban.updated",{time:ue(e.lastMessageAt)}))}</span>
147
+ </div>
148
+ </article>`}function kt(e){let t=[],o=new Map;for(let r of e){let d=String(r.chatId??r.sessionId),c=o.get(d);c||(c={chatId:d,rows:[]},o.set(d,c),t.push(c)),c.rows.push(r)}let n=[];return{html:t.map(r=>{if(n.push(...r.rows),r.rows.length<2)return ht(r.rows[0]);let d=pe(r.rows[0])??r.chatId;return`<div class="kanban-cluster" data-chat="${l(r.chatId)}">
149
+ <header draggable="true" title="${l(d)} \xB7 ${l(i("sessions.kanban.clusterDragHint"))}">
150
+ ${_t({chatId:r.chatId,name:d,size:"sm"})}
151
+ <span class="kanban-cluster-name">${l(d)}</span>
152
+ <span class="kanban-cluster-count">${r.rows.length}</span>
153
+ </header>
154
+ ${r.rows.map(ht).join("")}
155
+ </div>`}).join(""),flat:n}}function vn(e){let t=new Map;for(let n of e){if(n.status==="closed")continue;let s=String(n.larkAppId||n.botName||"unknown"),r=t.get(s);r||(r={name:F(n),larkAppId:n.larkAppId,rows:[]},t.set(s,r)),r.rows.push(n)}let o=[...t.values()].sort((n,s)=>n.name.localeCompare(s.name));return o.length?o.map(n=>{let s=n.rows.sort((d,c)=>Number(c.lastMessageAt??0)-Number(d.lastMessageAt??0)),{html:r}=kt(s);return`<section class="kanban-column kanban-bot-col" data-bot="${l(n.larkAppId??n.name)}">
156
+ <header>
157
+ <span class="kanban-col-avatar">${ae({name:n.name,larkAppId:n.larkAppId,size:"sm"})}</span>
158
+ <h2>${l(n.name)}</h2>
159
+ <span class="kanban-col-count">${s.length}</span>
160
+ </header>
161
+ <div class="kanban-col-list">${r}</div>
162
+ </section>`}).join(""):`<div class="kanban-col-empty">${i("sessions.board.emptyColumn")}</div>`}function $t(e){let t=new Map(Zt.map(n=>[n.id,[]]));for(let n of e)t.get(Gt(n)).push(n);let o=Zt.map(n=>{let s=(t.get(n.id)??[]).sort((m,g)=>oe(m)-oe(g)),r=0;n.id==="done"&&s.length>st&&(r=s.length-st,s=s.slice(0,st));let{html:d,flat:c}=kt(s);return t.set(n.id,c),`<section class="kanban-column kanban-${n.id}" data-col="${n.id}">
163
+ <header>
164
+ <span class="kanban-col-icon">${Kn(n.id)}</span>
165
+ <h2>${l(i(n.labelKey))}</h2>
166
+ <span class="kanban-col-count">${s.length+r}</span>
167
+ </header>
168
+ <div class="kanban-col-list">
169
+ ${s.length?d:`<div class="kanban-col-empty">${i("sessions.board.emptyColumn")}</div>`}
170
+ ${r?`<div class="kanban-col-more">${l(i("sessions.kanban.moreHidden",{count:r}))}</div>`:""}
171
+ </div>
172
+ </section>`}).join("");return le=t,o}function wn(e){if(ne||se||Ke)return;T.classList.toggle("kanban-mode-bot",D==="bot");let t;if(D==="bot")t=vn(e),le=new Map;else if(D==="team")if(!Ee)t=`<div class="kanban-loading">${i("sessions.kanban.teamLoading")}</div>`,le=new Map,q.dataset.loading||(q.dataset.loading="1",q.disabled=!0,q.innerHTML=`<option>${l(i("sessions.kanban.teamLoading"))}</option>`),un();else{let n=B.find(g=>g.key===X)??B[0],s=pt(n),r=n?e.filter(g=>s.has(String(g.chatId))):[];n&&pn(n);let d=(de===n?.key?A?.board:null)??{},c=(de===n?.key?A?.remoteRows:null)??[],m=[...r,...c].map(g=>{let I=d[g.sessionId];return I?{...g,kanbanColumn:I.column,kanbanPosition:I.position}:g});rt.textContent=i("sessions.kanban.teamScope",{chats:s.size,sessions:m.length}),t=$t(m)}else t=$t(e);if(t===C)return;C=t;let o=new Map;T.querySelectorAll(".kanban-col-list").forEach(n=>{let s=n.closest(".kanban-column")?.dataset.col;s&&n.scrollTop&&o.set(s,n.scrollTop)}),T.innerHTML=t,o.size&&T.querySelectorAll(".kanban-col-list").forEach(n=>{let s=n.closest(".kanban-column")?.dataset.col,r=s?o.get(s):void 0;r&&(n.scrollTop=r)})}async function vt(e,t,o,n){try{let s=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/board`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({column:t,position:o})}),r=await s.json().catch(()=>({}));(!s.ok||r?.ok===!1)&&(e.kanbanColumn=n.column,e.kanbanPosition=n.position,C="",y(),s.status!==401&&alert(`${i("sessions.kanban.moveFail")}: ${r?.error??s.status}`))}catch(s){e.kanbanColumn=n.column,e.kanbanPosition=n.position,C="",y(),alert(`${i("sessions.kanban.moveFail")}: ${s}`)}}async function wt(e,t){let o=e.title;e.title=t,C="",y();try{let n=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/rename`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({title:t})}),s=await n.json().catch(()=>({}));(!n.ok||s?.ok===!1)&&(e.title=o,C="",y(),n.status!==401&&alert(`${i("sessions.kanban.renameFail")}: ${s?.error??n.status}`))}catch(n){e.title=o,C="",y(),alert(`${i("sessions.kanban.renameFail")}: ${n}`)}}function Sn(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 Tn(e,t,o){let n=t.senderType==="user",s=n?t.senderName||(o&&t.senderId===o?i("sessions.history.owner"):i("sessions.history.user")):F(e),r=Sn(t.createTime),d=String(t.content??"").trim()||`[${t.msgType??"message"}]`,c=n?t.senderAvatar?`<img class="history-avatar-img" src="${l(String(t.senderAvatar))}" alt="" decoding="async" referrerpolicy="no-referrer">`:`<span class="history-avatar-user" aria-hidden="true">${l(String(s).slice(0,1))}</span>`:ae({name:F(e),larkAppId:e.larkAppId,size:"sm"});return`<div class="history-msg${n?" mine":""}">
173
+ ${c}
174
+ <div class="history-msg-main">
175
+ <div class="history-msg-meta"><span>${l(s)}</span><time>${l(r)}</time></div>
176
+ <div class="history-bubble">${l(d)}</div>
177
+ </div>
178
+ </div>`}async function St(e){let t=F(e);S.innerHTML=`<div class="term-modal-head">
179
+ <span class="term-modal-title">
180
+ ${ae({name:t,larkAppId:e.larkAppId,size:"sm"})}
181
+ <strong title="${l(String(e.title??""))}">${l((U(e.title)||e.sessionId).slice(0,60))}</strong>
182
+ <span class="history-scope-tag">${l(i("sessions.history.title"))}</span>
183
+ </span>
184
+ <span class="term-modal-actions">
185
+ <button type="button" id="history-close" class="card-act" title="${l(i("sessions.dismiss"))}" aria-label="${l(i("sessions.dismiss"))}">${L.close}</button>
186
+ </span>
187
+ </div>
188
+ <div class="history-body"><div class="term-modal-loading">${i("sessions.history.loading")}</div></div>`,S.showModal(),S.querySelector("#history-close").onclick=()=>S.close();try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/history?limit=80`),n=await o.json().catch(()=>({}));if(!S.open)return;let s=S.querySelector(".history-body");if(!o.ok||n?.ok===!1){let d=String(n?.error??o.status),c=d==="not_found_yet"||d==="not_found";s.innerHTML=`<div class="history-error">${l(i("sessions.history.fail"))}: ${l(d)}${c?`<br><span>${l(i("sessions.history.staleHint"))}</span>`:""}</div>`;return}let r=Array.isArray(n.messages)?n.messages:[];if(!r.length){s.innerHTML=`<div class="history-error">${i("sessions.history.empty")}</div>`;return}s.innerHTML=`<div class="history-list">${r.map(d=>Tn(e,d,n.ownerOpenId)).join("")}</div>`,s.scrollTop=s.scrollHeight}catch(o){if(!S.open)return;let n=S.querySelector(".history-body");n&&(n.innerHTML=`<div class="history-error">${l(i("sessions.history.fail"))}: ${l(String(o))}</div>`)}}function Tt(e,t){let o=e.querySelector(".kanban-card-title");if(!o||e.querySelector(".kanban-rename-input"))return;Ke=!0;let n=document.createElement("input");n.type="text",n.className="kanban-rename-input",n.maxLength=200,n.value=U(t.title)||"",o.replaceWith(n),n.focus(),n.select();let s=!1,r=d=>{if(s)return;s=!0,Ke=!1;let c=n.value.trim();d&&c&&c!==(U(t.title)||"")?wt(t,c):(C="",y())};n.addEventListener("keydown",d=>{d.stopPropagation(),d.key==="Enter"?(d.preventDefault(),r(!0)):d.key==="Escape"&&(d.preventDefault(),r(!1))}),n.addEventListener("blur",()=>r(!0)),n.addEventListener("click",d=>d.stopPropagation())}function Ct(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 Lt(){T.querySelectorAll(".drag-over, .dragging, .drop-before").forEach(e=>e.classList.remove("drag-over","dragging","drop-before"))}function Cn(e){let t=$.querySelector(".term-modal-name");if(!t||$.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=U(e.title)||"",t.replaceWith(o);let n=()=>{let d=getComputedStyle(o),c=document.createElement("span");c.style.cssText="position:absolute;visibility:hidden;white-space:pre",c.style.fontSize=d.fontSize,c.style.fontFamily=d.fontFamily,c.style.fontWeight=d.fontWeight,c.style.letterSpacing=d.letterSpacing,c.textContent=o.value||" ",document.body.appendChild(c);let m=c.offsetWidth;c.remove();let g=Math.round(window.innerWidth*.6);o.style.width=`${Math.min(Math.max(m+22,80),g)}px`};n(),o.addEventListener("input",n),o.focus(),o.select();let s=!1,r=d=>{if(s)return;s=!0;let c=o.value.trim(),m=U(e.title)||"";if(d&&c&&c!==m){e.title=c;let g=document.createElement("strong");g.className="term-modal-name",g.title=c,g.textContent=c.slice(0,60),o.replaceWith(g),wt(e,c)}else{let g=document.createElement("strong");g.className="term-modal-name",g.title=String(e.title??m),g.textContent=m.slice(0,60),o.replaceWith(g)}};o.addEventListener("keydown",d=>{d.stopPropagation(),d.key==="Enter"?(d.preventDefault(),r(!0)):d.key==="Escape"&&(d.preventDefault(),r(!1))}),o.addEventListener("blur",()=>r(!0))}async function It(e){let t=at(e);if(!t){xe(e);return}let o=U(e.title)||e.sessionId,n=e.feishuChatLink?`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(i("sessions.kanban.openFeishu"))}" aria-label="${l(i("sessions.kanban.openFeishu"))}">${L.feishu}</a>`:"";$.innerHTML=`<div class="term-modal-head">
189
+ <span class="term-modal-title">
190
+ ${ae({name:F(e),larkAppId:e.larkAppId,size:"sm"})}
191
+ <strong class="term-modal-name" title="${l(String(e.title??o))}">${l(String(o).slice(0,60))}</strong>
192
+ <button type="button" id="term-modal-edit" class="card-act" title="${l(i("sessions.kanban.rename"))}" aria-label="${l(i("sessions.kanban.rename"))}">${L.edit}</button>
193
+ ${Se(e.status)}
194
+ </span>
195
+ <span class="term-modal-actions">
196
+ ${n}
197
+ <a id="term-modal-tab" class="card-act" href="${l(t)}" target="_blank" rel="noopener" title="${l(i("sessions.kanban.openTab"))}" aria-label="${l(i("sessions.kanban.openTab"))}">${L.terminal}</a>
198
+ <button type="button" id="term-modal-close" class="card-act" title="${l(i("sessions.dismiss"))}" aria-label="${l(i("sessions.dismiss"))}">${L.close}</button>
199
+ </span>
200
+ </div>
201
+ <div class="term-modal-body"><div class="term-modal-loading">${i("sessions.kanban.terminalLoading")}</div></div>`,$.showModal(),$.querySelector("#term-modal-close").onclick=()=>$.close(),$.querySelector("#term-modal-edit").onclick=()=>Cn(e);let s=t;if(we.authed)try{let c=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/write-link`),m=await c.json().catch(()=>({}));c.ok&&m?.ok!==!1&&m?.url&&(s=m.url)}catch{}if(!$.open)return;let r=$.querySelector(".term-modal-body");r.innerHTML=`<iframe class="term-modal-frame" src="${l(s)}" allow="clipboard-read; clipboard-write"></iframe>`;let d=$.querySelector("#term-modal-tab");d&&(d.href=s)}function he(){let e=new FormData(b),t=(e.get("q")??"").toLowerCase(),o=e.getAll("cli"),n=o.length>0&&o.length<nn.length,s=e.get("status"),r=e.get("adopt"),d=!!e.get("active"),c=H==="kanban",m=[..._.sessions.values()].filter(g=>!n||o.includes(g.cliId??"unknown")).filter(g=>!s||g.status===s).filter(g=>!r||r==="yes"==!!g.adopt).filter(g=>!d||c||g.status!=="closed").filter(g=>!t||JSON.stringify(g).toLowerCase().includes(t));return m.sort(Ln),m}function Mt(e,t){return t==="spawnedAt"||t==="lastMessageAt"?Number(e[t]??0):t==="tokenIn"?it(e.tokenUsage?.in)??-1:t==="tokenOut"?it(e.tokenUsage?.out)??-1:t==="adopt"?!!e.adopt:String(e[t]??"").toLowerCase()}function Ln(e,t){let o=Mt(e,ge),n=Mt(t,ge),s=0;return typeof o=="number"&&typeof n=="number"?s=o-n:typeof o=="boolean"&&typeof n=="boolean"?s=Number(o)-Number(n):s=String(o).localeCompare(String(n)),s===0&&(s=Number(e.lastMessageAt??0)-Number(t.lastMessageAt??0)),re==="asc"?s:-s}function In(){fe.querySelectorAll("th[data-sort]").forEach(e=>{let t=e.dataset.sort===ge;e.classList.toggle("sorted",t),e.setAttribute("aria-sort",t?re==="asc"?"ascending":"descending":"none");let o=e.dataset.label??e.textContent?.trim()??"";e.textContent=t?`${o} ${re==="asc"?"\u25B2":"\u25BC"}`:o})}function We(e){me.hidden=w.size===0,ie.textContent=i("sessions.selectedCount",{count:w.size});let t=[...w].map(s=>_.sessions.get(s)).filter(s=>!!s&&s.status!=="closed");W.disabled=!t.some(s=>!s.locked),V.disabled=!t.some(s=>!!s.locked);let o=e.filter(s=>s.status!=="closed");if(o.length===0){v.checked=!1,v.indeterminate=!1,v.disabled=!0;return}v.disabled=!1;let n=o.filter(s=>w.has(s.sessionId)).length;v.checked=n===o.length,v.indeterminate=n>0&&n<o.length}function Ge(){let e=mt().length;be.textContent=i("sessions.idleCleanupCount",{count:e}),Q.disabled=He||e===0,P.classList.toggle("is-empty",e===0),cn()}function Mn(){lt.forEach(e=>{let t=e.dataset.view===H;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))}),te.hidden=H!=="kanban",q.hidden=!(H==="kanban"&&D==="team"),rt.hidden=q.hidden||!Ee,te.querySelectorAll("[data-groupby]").forEach(e=>{let t=e.dataset.groupby===D;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))})}function En(){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?i("common.all"):`${o}/${t.length}`,e.classList.toggle("cli-filter-active",o!==t.length)}function y(){let e=he();for(let n of[...w]){let s=_.sessions.get(n);(!s||s.status==="closed")&&w.delete(n)}let t=e.filter(n=>n.status!=="closed"),o=H==="table"?e:t;if(fe.hidden=H!=="table",O.hidden=H!=="board",T.hidden=H!=="kanban",H==="table"){let n=e.length?e.map(yn).join(""):`<tr><td colspan="12" class="empty">${i("sessions.empty")}</td></tr>`;n!==qe&&(qe=n,u.innerHTML=n)}else H==="kanban"?wn(e):$n(t);Mn(),In(),En(),We(o),Ge()}async function Et(e,t){t&&(t.disabled=!0,t.textContent=i("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 s=30;t.textContent=i("sessions.cooldown",{seconds:s});let r=setInterval(()=>{s-=1,s<=0?(clearInterval(r),t.disabled=!1,t.textContent=i("sessions.locate")):t.textContent=i("sessions.cooldown",{seconds:s})},1e3)}else alert(`Locate failed: ${n.error??o.status}`),t&&(t.disabled=!1,t.textContent=i("sessions.locate"))}catch(o){alert(`Locate error: ${o}`),t&&(t.disabled=!1,t.textContent=i("sessions.locate"))}}async function Ht(e,t){if(!confirm(i("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 ke(){_e="",qe="",C=""}async function Ve(e,t,o){let n=!!e.locked;if(n===t)return!0;e.locked=t,ke(),y(),o&&(o.disabled=!0);try{let s=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:t})}),r=await s.json().catch(()=>({}));return!s.ok||r?.ok===!1?(e.locked=n,ke(),y(),s.status!==401&&alert(`${i("sessions.lockFailed")}: ${r?.error??s.status}`),!1):(e.locked=!!r.locked,ke(),y(),!0)}catch(s){return e.locked=n,ke(),y(),alert(`${i("sessions.lockFailed")}: ${s}`),!1}finally{o&&(o.disabled=!1)}}let Je=new Set;async function Ye(e,t){if(Je.has(e.sessionId)||!confirm(jn(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(`${i("sessions.restartFailed")}: ${n?.error??o.status}`),!1):(Je.add(e.sessionId),setTimeout(()=>Je.delete(e.sessionId),5e3),!0)}catch(o){return alert(`${i("sessions.restartFailed")}: ${o}`),!1}finally{t&&(t.disabled=!1)}}function Hn(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 An(e){if(!e||e.status!=="ok"){let r=e?.error?.message?l(String(e.error.message)):l(String(e?.status??"error"));return`<p>${i("sessions.insightUnavailable")}: ${r}</p>`}let t=e.agg??{};if(!t.totalSpans)return`<p>${i("sessions.insightEmpty")}</p>`;let o="color:var(--muted,#8f959e)",n=[],s=[];if(e.meta?.asOf&&s.push(l(i("sessions.insightAsOf",{asOf:String(e.meta.asOf)}))),e.meta?.partial&&s.push(l(i("sessions.insightPartial"))),s.length&&n.push(`<p style="font-size:12px;${o}">${s.join(" \xB7 ")}</p>`),n.push(`<p>${l(i("sessions.insightMetrics",{total:String(t.totalSpans??0),failed:String(t.failedSpans??0),slow:String(t.slowSpans??0),rw:t.readWriteRatio===null||t.readWriteRatio===void 0?"\u2014":String(t.readWriteRatio),compactions:String(t.compactions??0)}))}</p>`),Array.isArray(e.suggestions)&&e.suggestions.length){let r=c=>c==="bad"?"\u{1F534}":c==="warn"?"\u{1F7E1}":"\u2139\uFE0F",d=e.suggestions.map(c=>`<li>${r(c.severity)} <b>${l(String(c.title??""))}</b> \u2014 ${l(String(c.action??""))}`+(Array.isArray(c.evidence)&&c.evidence.length?`<br><small style="${o}">${l(c.evidence.join("\uFF1B"))}</small>`:"")+"</li>").join("");n.push(`<details open><summary>${i("sessions.insightSuggestions")}</summary><ul style="padding-left:18px;margin:6px 0">${d}</ul></details>`)}if(Array.isArray(e.spans)&&e.spans.length){let r=m=>m==="error"?"\u{1F534}":m==="running"?"\u23F3":"\u2705",d=[...e.spans].sort((m,g)=>(m.relStartMs??0)-(g.relStartMs??0)).map(m=>{let g=[m.inputSummary,m.outputSummary].filter(Boolean).map(x=>l(String(x))).join(" \u2192 ");return`<tr${m.status==="error"?' style="color:var(--danger,#d33)"':""}><td>${r(m.status)}</td><td><code>${l(String(m.tool??""))}</code></td><td>${l(String(m.phase??""))}</td><td>${Hn(m.durationMs)}</td><td>#${l(String(m.turnIndex??0))}</td><td>${g}</td></tr>`}).join(""),c=e.meta?.capped?`<p style="font-size:12px;${o}">${l(i("sessions.insightCapped",{shown:String(e.meta.spansReturned??e.spans.length),total:String(e.meta.spansTotal??e.spans.length)}))}</p>`:"";n.push(`<details><summary>${i("sessions.insightSpans")} (${e.spans.length})</summary>${c}<div style="max-height:320px;overflow:auto"><table style="width:100%;font-size:12px"><tbody>${d}</tbody></table></div></details>`)}return n.join("")}function xe(e){let t=e.status==="closed",o=at(e);f.innerHTML=`<article>
202
+ <header>
203
+ <h3>${l(U(e.title)||e.sessionId)}</h3>
204
+ <span class="drawer-status-line">
205
+ ${Se(e.status)}
206
+ ${Le(e)}
207
+ </span>
208
+ <p><code>${l(e.sessionId)}</code> <button data-copy="${l(e.sessionId)}">${i("sessions.copy")}</button></p>
209
+ </header>
210
+ <p><b>${i("sessions.bot")}:</b> ${l(F(e))} \xB7 <b>${i("sessions.cli")}:</b> ${l(e.cliId??"?")}</p>
211
+ ${pe(e)?`<p><b>${i("sessions.chat")}:</b> ${l(pe(e))}</p>`:""}
212
+ <p><b>chatId:</b> <code>${l(e.chatId??"")}</code> <button data-copy="${l(e.chatId??"")}">${i("sessions.copy")}</button></p>
213
+ <p><b>rootMessageId:</b> <code>${l(e.rootMessageId??"")}</code> <button data-copy="${l(e.rootMessageId??"")}">${i("sessions.copy")}</button></p>
214
+ ${e.threadId?`<p><b>threadId:</b> <code>${l(e.threadId)}</code></p>`:""}
215
+ <p><b>${i("sessions.workingDir")}:</b> ${l(e.workingDir??"-")}</p>
216
+ <div class="actions">
217
+ ${gt(e)??`<button id="locate-btn" type="button">${i("sessions.locate")}</button>`}
218
+ <button id="history-drawer-btn" type="button">${i("sessions.history.title")}</button>
219
+ ${en(o)}
220
+ ${ot(e)?`<button id="restart-btn" type="button">${i("sessions.restart")}</button>`:""}
221
+ ${t?"":`<button id="lock-btn" type="button">${l(Ce(e))}</button>`}
222
+ ${e.queued&&!t?`<button id="start-btn" type="button" class="primary">${i("sessions.create.start")}</button>`:""}
223
+ ${t?`<button id="resume-btn" type="button" class="primary">${i("sessions.resume")}</button>`:""}
224
+ ${t?"":`<button id="close-btn" type="button" class="contrast">${i("sessions.close")}</button>`}
225
+ <button id="land-btn" type="button">${i("sessions.land")}</button>
226
+ ${we.authed?`<button id="insight-btn" type="button">${i("sessions.insight")}</button>`:""}
227
+ </div>
228
+ <div id="land-area"></div>
229
+ <div id="insight-area"></div>
230
+ <form method="dialog"><button>${i("sessions.dismiss")}</button></form>
231
+ </article>`,f.querySelectorAll("[data-copy]").forEach(h=>{h.onclick=()=>{navigator.clipboard.writeText(h.dataset.copy??""),h.textContent=i("sessions.copied"),setTimeout(()=>{h.textContent=i("sessions.copy")},800)}});let n=f.querySelector("#locate-btn");n&&(n.onclick=()=>{Et(e,n)});let s=f.querySelector("#history-drawer-btn");s&&(s.onclick=()=>{St(e)});let r=f.querySelector(".term-write");r&&(r.onclick=()=>{tn(e,r)});let d=f.querySelector("#resume-btn");d&&(d.onclick=async()=>{d.disabled=!0;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/resume`,{method:"POST"}),k=await h.json().catch(()=>({}));if(!h.ok||k.ok===!1){alert(`${i("sessions.resumeFailed")}: ${k?.error??h.status}`),d.disabled=!1;return}f.close()}catch(h){alert(`${i("sessions.resumeFailed")}: ${h}`),d.disabled=!1}});let c=f.querySelector("#restart-btn");c&&(c.onclick=async()=>{await Ye(e,c)&&f.close()});let m=f.querySelector("#close-btn");m&&(m.onclick=async()=>{await Ht(e,m)&&f.close()});let g=f.querySelector("#lock-btn");g&&(g.onclick=async()=>{let h=!e.locked;if(await Ve(e,h,g)){g.textContent=Ce(e);let k=f.querySelector(".drawer-status-line");k&&(k.innerHTML=`${Se(e.status)}${Le(e)}`)}});let I=f.querySelector("#start-btn");I&&(I.onclick=async()=>{I.disabled=!0;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/start`,{method:"POST"}),k=await h.json().catch(()=>({}));if(!h.ok||k.ok===!1){h.status!==401&&alert(`${i("sessions.create.startFailed")}: ${k?.error??h.status}`),I.disabled=!1;return}f.close()}catch(h){alert(`${i("sessions.create.startFailed")}: ${h}`),I.disabled=!1}});let x=f.querySelector("#land-btn"),N=f.querySelector("#land-area");x&&N&&(x.onclick=async()=>{x.disabled=!0,N.innerHTML=`<p>${i("sessions.landLoading")}</p>`;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-diff`),k=await h.json().catch(()=>({}));if(!k.ok){N.innerHTML=`<p>${i("sessions.landUnavailable")}: ${l(k.error??String(h.status))}</p>`,x.disabled=!1;return}if(k.empty){N.innerHTML=`<p>${i("sessions.landEmpty")}</p>`,x.disabled=!1;return}let G=String(k.patch??""),Ne=G.slice(0,2e4)+(G.length>2e4?`
232
+ \u2026(truncated)`:"");N.innerHTML=`
233
+ <p><b>${k.files}</b> files (+${k.insertions}/-${k.deletions}) \u2192 <code>${l(String(k.workingDir??""))}</code></p>
234
+ <pre style="max-height:320px;overflow:auto;white-space:pre-wrap">${l(Ne)}</pre>
235
+ <div class="actions">
236
+ <button id="land-apply" type="button" class="primary">${i("sessions.landApply")}</button>
237
+ <button id="land-discard" type="button" class="contrast">${i("sessions.landDiscard")}</button>
238
+ </div>`;let ve=N.querySelector("#land-apply"),Be=N.querySelector("#land-discard");ve.onclick=async()=>{ve.disabled=!0,Be.disabled=!0;let M=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/apply`,{method:"POST"}),Z=await M.json().catch(()=>({}));N.innerHTML=Z.ok?`<p>\u2705 ${i("sessions.landApplied")}: ${Z.files} files (+${Z.insertions}/-${Z.deletions}) \u2192 <code>${l(String(Z.workingDir??""))}</code></p>`:`<p>\u274C ${i("sessions.landFailed")}: ${l(Z.error??String(M.status))}</p>`},Be.onclick=async()=>{await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/discard`,{method:"POST"}),N.innerHTML=`<p>\u{1F5D1} ${i("sessions.landDiscarded")}</p>`}}catch(h){N.innerHTML=`<p>${i("sessions.landUnavailable")}: ${l(String(h))}</p>`,x.disabled=!1}});let ce=f.querySelector("#insight-btn"),R=f.querySelector("#insight-area");ce&&R&&(ce.onclick=async()=>{ce.disabled=!0,R.innerHTML=`<p>${i("sessions.insightLoading")}</p>`;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/insight?detail=spans`),k=await h.json().catch(()=>({}));!k.ok||!k.report?R.innerHTML=`<p>${i("sessions.insightUnavailable")}: ${l(String(k.error??h.status))}</p>`:R.innerHTML=An(k.report)}catch(h){R.innerHTML=`<p>${i("sessions.insightUnavailable")}: ${l(String(h))}</p>`}ce.disabled=!1}),f.showModal()}u.addEventListener("click",e=>{let t=e.target;if(t.classList.contains("row-select")){let r=t.closest("tr[data-id]");if(!r)return;t.checked?w.add(r.dataset.id):w.delete(r.dataset.id),We(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 s=_.sessions.get(n.dataset.id);s&&xe(s)}),O.addEventListener("click",e=>{let t=e.target,o=t.closest("button[data-move-col]");if(o){fn(o.dataset.moveCol,Number(o.dataset.dir));return}let n=t.closest(".session-card[data-id]");if(!n)return;let s=_.sessions.get(n.dataset.id);if(!s)return;let r=t.closest("button[data-action]");if(r){let d=r.dataset.action;d==="details"?xe(s):d==="write-link"?tn(s,r):d==="locate"?Et(s,r):d==="restart"?Ye(s,r):d==="lock"?Ve(s,!s.locked,r):d==="close"&&Ht(s,r).then(c=>{c&&(w.delete(s.sessionId),y())});return}t.closest("a, button, input, label")||(w.has(s.sessionId)?w.delete(s.sessionId):w.add(s.sessionId),n.classList.toggle("selected",w.has(s.sessionId)),n.setAttribute("aria-pressed",String(w.has(s.sessionId))),We(he().filter(d=>d.status!=="closed")))}),O.addEventListener("dragstart",e=>{let o=e.target.closest(".session-board-column > header[draggable]")?.closest(".session-board-column");o?.dataset.col&&(Y=o.dataset.col,o.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",Y)))}),O.addEventListener("dragover",e=>{if(!Y)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".session-board-column");O.querySelectorAll(".drag-over").forEach(o=>o.classList.remove("drag-over")),t&&t.dataset.col!==Y&&t.classList.add("drag-over")}),O.addEventListener("drop",e=>{if(!Y)return;e.preventDefault();let t=e.target.closest(".session-board-column"),o=Y;Y=null,t?.dataset.col&&gn(o,t.dataset.col)}),O.addEventListener("dragend",()=>{Y=null,O.querySelectorAll(".drag-over, .dragging").forEach(e=>e.classList.remove("drag-over","dragging"))}),lt.forEach(e=>{e.addEventListener("click",()=>{let t=Nt(e.dataset.view)??"board";t!==H&&(H=t,Pt(window.localStorage,H),y())})}),te.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,Dt(window.localStorage,o),C="",y())})}),q.addEventListener("change",()=>{X=q.value;try{window.localStorage.setItem(et,X)}catch{}C="",y()});function $e(){ye!==null&&(clearTimeout(ye),ye=null)}T.addEventListener("click",e=>{let t=e.target,o=t.closest(".kanban-card[data-id]");if(!o)return;let n=_.sessions.get(o.dataset.id);if(!n)return;let s=t.closest("button[data-action]");if(s){s.dataset.action==="details"?xe(n):s.dataset.action==="rename"?Tt(o,n):s.dataset.action==="history"?St(n):s.dataset.action==="restart"?Ye(n,s):s.dataset.action==="lock"&&Ve(n,!n.locked,s);return}t.closest("a, button, input, label")||($e(),ye=setTimeout(()=>{ye=null,It(n)},220))}),T.addEventListener("dblclick",e=>{let t=e.target,o=t.closest(".kanban-card-title"),n=t.closest(".kanban-card[data-id]");if(!o||!n)return;$e();let s=_.sessions.get(n.dataset.id);s&&Tt(n,s)}),T.addEventListener("keydown",e=>{if(e.key!=="Enter"&&e.key!==" ")return;let t=e.target;if(!t.classList?.contains("kanban-card"))return;e.preventDefault();let o=_.sessions.get(t.dataset.id);o&&It(o)}),T.addEventListener("dragstart",e=>{if(D==="bot")return;let t=e.target,o=t.closest(".kanban-cluster > header[draggable]");if(o){let s=o.closest(".kanban-cluster"),r=s.closest(".kanban-column")?.dataset.col;if(!s.dataset.chat||!r)return;$e(),se=s.dataset.chat,Me=r,s.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",`cluster:${se}`));return}let n=t.closest(".kanban-card[data-id]");n&&($e(),ne=n.dataset.id,n.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",ne)))}),T.addEventListener("dragover",e=>{if(!ne&&!se)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".kanban-column");T.querySelectorAll(".drag-over").forEach(o=>o.classList.remove("drag-over")),T.querySelectorAll(".drop-before").forEach(o=>o.classList.remove("drop-before")),t&&(t.classList.add("drag-over"),Ct(t,e.clientY)?.classList.add("drop-before"))}),T.addEventListener("drop",e=>{let t=se,o=Me,n=ne;if(!n&&!t)return;e.preventDefault(),ne=null,se=null,Me=null,Lt();let s=e.target.closest(".kanban-column"),r=s?.dataset.col;if(!s||!r)return;let d=Ct(s,e.clientY);if(t&&o){let R=(le.get(o)??[]).filter(M=>String(M.chatId)===t).filter(M=>!(M.status==="closed"&&r!=="done"));if(!R.length)return;let h=new Set(R.map(M=>M.sessionId)),k=(le.get(r)??[]).filter(M=>!h.has(M.sessionId)),G=d?k.findIndex(M=>M.sessionId===d.dataset.id):k.length;G<0&&(G=k.length);let Ne=G>0?k[G-1]:null,ve=G<k.length?k[G]:null,Be=nt(Ne?oe(Ne):null,ve?oe(ve):null);R.forEach((M,Z)=>{let Xe=Be+Z*.001;if(D==="team")ft(String(M.sessionId),r,Xe);else{let Nn={column:M.kanbanColumn,position:M.kanbanPosition};M.kanbanColumn=r,M.kanbanPosition=Xe,vt(M,r,Xe,Nn)}}),C="",y();return}let c=_.sessions.get(n)??ze.get(n);if(!c||c.status==="closed"&&r!=="done")return;let m=(le.get(r)??[]).filter(R=>R.sessionId!==n),g=d?m.findIndex(R=>R.sessionId===d.dataset.id):m.length;g<0&&(g=m.length);let I=g>0?m[g-1]:null,x=g<m.length?m[g]:null,N=nt(I?oe(I):null,x?oe(x):null);if(D==="team"){ft(String(c.sessionId),r,N),C="",y();return}let ce={column:c.kanbanColumn,position:c.kanbanPosition};c.kanbanColumn=r,c.kanbanPosition=N,C="",y(),vt(c,r,N,ce)}),T.addEventListener("dragend",()=>{ne=null,se=null,Me=null,Lt(),C="",y()}),$.addEventListener("click",e=>{e.target===$&&$.close()}),$.addEventListener("close",()=>{$.innerHTML=""}),S.addEventListener("click",e=>{e.target===S&&S.close()}),S.addEventListener("close",()=>{S.innerHTML=""}),v.addEventListener("change",()=>{let e=he().filter(t=>t.status!=="closed");for(let t of e)v.checked?w.add(t.sessionId):w.delete(t.sessionId);y()}),E.addEventListener("click",()=>{w.clear(),y()}),j.addEventListener("click",async()=>{let e=[...w];if(e.length===0||!confirm(i("sessions.closeBulkConfirm",{count:e.length})))return;j.disabled=!0,E.disabled=!0;let t=j.textContent,o=0,n=0,s=[...e];j.textContent=`0/${e.length}`;async function r(){for(;s.length;){let d=s.shift();try{let c=await fetch(`/api/sessions/${encodeURIComponent(d)}/close`,{method:"POST"}),m=await c.json().catch(()=>({}));(!c.ok||m?.ok===!1)&&(n+=1)}catch{n+=1}finally{o+=1,j.textContent=`${o}/${e.length}`}}}await Promise.all(Array.from({length:Math.min(6,e.length)},()=>r())),j.textContent=t,j.disabled=!1,E.disabled=!1,w.clear(),y(),n>0&&alert(`Failed: ${n}/${e.length}`)});async function At(e){let t=[...w].map(m=>_.sessions.get(m)).filter(m=>!!m&&m.status!=="closed"&&!!m.locked!==e);if(t.length===0)return;W.disabled=!0,V.disabled=!0;let o=e?W.textContent:V.textContent,n=e?W:V,s=0,r=0,d=[...t];n.textContent=`0/${t.length}`;async function c(){for(;d.length;){let m=d.shift(),g=!!m.locked;try{let I=await fetch(`/api/sessions/${encodeURIComponent(m.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:e})}),x=await I.json().catch(()=>({}));!I.ok||x?.ok===!1?(r+=1,m.locked=g):m.locked=!!x.locked}catch{r+=1,m.locked=g}finally{s+=1,n.textContent=`${s}/${t.length}`}}}await Promise.all(Array.from({length:Math.min(6,t.length)},()=>c())),n.textContent=o,ke(),y(),r>0&&alert(`${i("sessions.lockFailed")}: ${r}/${t.length}`)}W.addEventListener("click",()=>{At(!0)}),V.addEventListener("click",()=>{At(!1)}),J.addEventListener("click",e=>{if(He)return;let t=e.target?.closest("button[data-hours]");if(!t)return;let o=tt(t.dataset.hours);!o||o===Ae||(Ae=o,ee.textContent="",Ge())}),Q.addEventListener("click",async()=>{let e=ut(),t=mt();if(t.length===0)return;let o=ln(e);if(confirm(i("sessions.idleCleanupConfirm",{count:t.length,threshold:o}))){He=!0,Q.disabled=!0,ee.textContent=i("sessions.idleCleanupRunning");try{let n=await fetch("/api/sessions/cleanup-idle",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({olderThanHours:e,sessionIds:t.map(r=>r.sessionId)})}),s=await n.json().catch(()=>({}));if(!n.ok){n.status!==401&&alert(`${i("sessions.idleCleanupFailed")}: ${s?.error??n.status}`),ee.textContent="";return}for(let r of s?.results??[])r?.ok&&r?.sessionId&&w.delete(String(r.sessionId));ee.textContent=i("sessions.idleCleanupDone",{closed:Number(s?.closed??0),failed:Number(s?.failed??0)}),y()}catch(n){alert(`${i("sessions.idleCleanupFailed")}: ${n}`),ee.textContent=""}finally{He=!1,Ge()}}}),fe.querySelectorAll("th[data-sort]").forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.sort;ge===t?re=re==="asc"?"desc":"asc":(ge=t,re=t==="spawnedAt"||t==="lastMessageAt"?"desc":"asc"),y()})}),b.addEventListener("input",y);let xn=_.on(y),xt=setInterval(()=>{if(!document.body.contains(T)){clearInterval(xt);return}H==="kanban"&&D==="team"&&(C="",y())},3e4);return y(),qt().then(y),()=>{xn(),clearInterval(xt),$e(),f.close(),$.close(),S.close(),dt.close()}}var p=Ze(Ut(),1);function z(a){return(0,p.jsx)("th",{"data-sort":a.sort,"data-label":a.label,children:a.label})}function Jn(){let a=jt(),u=(0,De.useRef)(null);return(0,De.useEffect)(()=>{if(u.current)return on(u.current)},[]),(0,p.jsxs)("section",{className:"page",ref:u,children:[(0,p.jsxs)("div",{className:"page-heading",children:[(0,p.jsxs)("div",{children:[(0,p.jsx)("p",{className:"eyebrow",children:a("nav.sessions")}),(0,p.jsx)("h1",{children:a("sessions.title")}),(0,p.jsx)("p",{children:a("sessions.subtitle")})]}),(0,p.jsxs)("div",{className:"sessions-view-controls",children:[(0,p.jsxs)("button",{type:"button",id:"create-session-btn",className:"primary create-session-btn",children:["+ ",a("sessions.create.button")]}),(0,p.jsx)("span",{id:"kanban-team-stats",className:"kanban-team-stats",hidden:!0}),(0,p.jsx)("select",{id:"kanban-team",className:"kanban-team-select","aria-label":a("sessions.kanban.groupTeam"),hidden:!0}),(0,p.jsxs)("div",{className:"segmented kanban-groupby",id:"kanban-groupby",role:"group","aria-label":a("sessions.kanban.groupBy"),hidden:!0,children:[(0,p.jsx)("button",{type:"button","data-groupby":"flow",children:a("sessions.kanban.groupFlow")}),(0,p.jsx)("button",{type:"button","data-groupby":"team",children:a("sessions.kanban.groupTeam")}),(0,p.jsx)("button",{type:"button","data-groupby":"bot",children:a("sessions.kanban.groupBot")})]}),(0,p.jsxs)("div",{className:"segmented sessions-view-toggle",role:"group","aria-label":a("sessions.viewMode"),children:[(0,p.jsx)("button",{type:"button","data-view":"kanban",children:a("sessions.viewKanban")}),(0,p.jsx)("button",{type:"button","data-view":"board",children:a("sessions.viewBoard")}),(0,p.jsx)("button",{type:"button","data-view":"table",children:a("sessions.viewTable")})]})]})]}),(0,p.jsxs)("form",{id:"filters",className:"filters sessions-filters",children:[(0,p.jsx)("input",{type:"search",name:"q",placeholder:a("sessions.search")}),(0,p.jsxs)("select",{name:"status",children:[(0,p.jsx)("option",{value:"",children:a("sessions.anyStatus")}),sn.map(b=>(0,p.jsx)("option",{value:b,children:Ie(b)},b))]}),(0,p.jsxs)("select",{name:"adopt",children:[(0,p.jsx)("option",{value:"",children:a("sessions.adoptAny")}),(0,p.jsx)("option",{value:"yes",children:a("sessions.adoptYes")}),(0,p.jsx)("option",{value:"no",children:a("sessions.adoptNo")})]}),(0,p.jsx)("span",{style:{display:"contents"},dangerouslySetInnerHTML:{__html:an()}}),(0,p.jsxs)("label",{className:"filter-toggle",children:[(0,p.jsx)("input",{type:"checkbox",name:"active",defaultChecked:!0})," ",(0,p.jsx)("span",{children:a("sessions.activeOnly")})]})]}),(0,p.jsxs)("div",{id:"idle-cleanup-bar",className:"idle-cleanup-bar",children:[(0,p.jsxs)("div",{className:"idle-cleanup-summary",children:[(0,p.jsx)("span",{className:"idle-cleanup-dot","aria-hidden":"true"}),(0,p.jsx)("span",{id:"idle-cleanup-count",className:"idle-cleanup-count"})]}),(0,p.jsxs)("div",{className:"idle-cleanup-controls",children:[(0,p.jsx)("span",{className:"idle-cleanup-label",children:a("sessions.idleCleanupOlderThan")}),(0,p.jsx)("div",{id:"idle-cleanup-threshold",className:"idle-cleanup-thresholds",role:"group","aria-label":a("sessions.idleCleanupThreshold"),children:Pe.map(b=>(0,p.jsx)("button",{type:"button","data-hours":b,"aria-pressed":b===24?"true":"false",children:b===168?"7d":`${b}H`},b))}),(0,p.jsx)("button",{type:"button",id:"idle-cleanup-run",className:"contrast idle-cleanup-run",children:a("sessions.idleCleanupRun")})]}),(0,p.jsx)("span",{id:"idle-cleanup-status",className:"idle-cleanup-status","aria-live":"polite"})]}),(0,p.jsxs)("div",{id:"bulk-bar",className:"bulk-bar",hidden:!0,children:[(0,p.jsx)("span",{id:"bulk-count"}),(0,p.jsx)("button",{type:"button",id:"bulk-lock",children:a("sessions.lockSelected")}),(0,p.jsx)("button",{type:"button",id:"bulk-unlock",children:a("sessions.unlockSelected")}),(0,p.jsx)("button",{type:"button",id:"bulk-close",className:"contrast",children:a("sessions.closeSelected")}),(0,p.jsx)("button",{type:"button",id:"bulk-clear",children:a("sessions.clearSelection")})]}),(0,p.jsxs)("table",{id:"sessions-table",children:[(0,p.jsx)("thead",{children:(0,p.jsxs)("tr",{children:[(0,p.jsx)("th",{children:(0,p.jsx)("input",{type:"checkbox",id:"select-all",title:a("sessions.activeOnly")})}),(0,p.jsx)(z,{sort:"botName",label:a("sessions.bot")}),(0,p.jsx)(z,{sort:"cliId",label:a("sessions.cli")}),(0,p.jsx)(z,{sort:"status",label:a("sessions.status")}),(0,p.jsx)(z,{sort:"tokenIn",label:a("sessions.tokenIn")}),(0,p.jsx)(z,{sort:"tokenOut",label:a("sessions.tokenOut")}),(0,p.jsx)(z,{sort:"title",label:a("sessions.titleCol")}),(0,p.jsx)(z,{sort:"workingDir",label:a("sessions.workingDir")}),(0,p.jsx)(z,{sort:"spawnedAt",label:a("sessions.created")}),(0,p.jsx)(z,{sort:"lastMessageAt",label:a("sessions.last")}),(0,p.jsx)(z,{sort:"adopt",label:a("sessions.adopt")}),(0,p.jsx)("th",{children:a("sessions.actions")})]})}),(0,p.jsx)("tbody",{})]}),(0,p.jsx)("div",{id:"sessions-board",className:"sessions-board",hidden:!0}),(0,p.jsx)("div",{id:"sessions-kanban",className:"sessions-kanban",hidden:!0}),(0,p.jsx)("dialog",{id:"drawer"}),(0,p.jsx)("dialog",{id:"term-modal",className:"term-modal"}),(0,p.jsx)("dialog",{id:"history-modal",className:"history-modal"}),(0,p.jsx)("dialog",{id:"create-session-modal",className:"create-session-modal"})]})}function gs(a){return Kt(a,(0,p.jsx)(Jn,{}))}export{gs as renderSessionsPage};
@@ -1,2 +1,2 @@
1
- import{b as k}from"./chunk-NASYW5FD.js";import"./chunk-76J7PNZI.js";import"./chunk-JXLHRRJD.js";import{a as oe,b as j,c as q}from"./chunk-JTSE5VP6.js";import{c as E}from"./chunk-7SZRL6FY.js";var i=E(oe(),1);var e=E(q(),1);function K(t){return{publicReadOnly:t?.publicReadOnly===!0,openTerminalInFeishu:t?.openTerminalInFeishu===!0,chatBotDiscovery:t?.chatBotDiscovery!==!1,repoPickerMode:t?.repoPickerMode==="repos"?"repos":"all",maintenance:t?.maintenance&&typeof t.maintenance=="object"?t.maintenance:{},localDevInstall:t?.localDevInstall===!0,whiteboard:{enabled:t?.whiteboard?.enabled===!0},remoteAccess:t?.remoteAccess===!0}}function le(t,n){let a=t?.[n]??{};return{enabled:a.enabled===!0,time:typeof a.time=="string"?a.time:"04:00"}}function _(t,n){return n(t==="npm-global"?"update.kindNpm":t==="source-checkout"?"update.kindSource":"update.kindUnknown")}function re(){let t=k(),n=(0,i.useRef)(!1),a=(0,i.useRef)(new Set),[r,p]=(0,i.useState)(null),[h,b]=(0,i.useState)(!1),[y,N]=(0,i.useState)(null),[S,U]=(0,i.useState)(!0),[l,c]=(0,i.useState)(!1),[d,x]=(0,i.useState)(null),[J,M]=(0,i.useState)(null),[L,C]=(0,i.useState)(null),[G,T]=(0,i.useState)(null),[A,R]=(0,i.useState)(null),[$,O]=(0,i.useState)(!1),[z,D]=(0,i.useState)(!0),[Q,B]=(0,i.useState)(!1),[X,Y]=(0,i.useState)(""),[Z,f]=(0,i.useState)(!1),[ee,m]=(0,i.useState)(null),F=(0,i.useCallback)(()=>{for(let s of a.current)window.clearTimeout(s);a.current.clear()},[]),H=(0,i.useCallback)((s,o)=>{let u=window.setTimeout(()=>{a.current.delete(u),s()},o);return a.current.add(u),u},[]),P=(0,i.useCallback)(async()=>{try{let s=await fetch("/api/update/status"),o=await s.json().catch(()=>({}));if(!n.current)return;if(!s.ok){C(null),T(o?.error??`HTTP ${s.status}`);return}C(o),T(null)}catch(s){if(!n.current)return;C(null),T(s instanceof Error?s.message:String(s))}},[]),V=(0,i.useCallback)(async()=>{try{let s=await fetch("/api/settings"),o=await s.json().catch(()=>({}));if(!n.current)return;if(!s.ok){p(null),N(o?.error??`HTTP ${s.status}`),b(!0);return}p(K(o.settings)),U(o.authed===!0),c(o.bound===!0),N(null),b(!0)}catch(s){if(!n.current)return;p(null),N(s instanceof Error?s.message:String(s)),b(!0)}},[]);(0,i.useEffect)(()=>(n.current=!0,V(),()=>{n.current=!1,F()}),[F,V]),(0,i.useEffect)(()=>{h&&(f(!1),m(null),O(!1),S&&P())},[S,P,h]);async function te(s,o,u){if(!r)return;let g=r;p(u(r)),x(s),M({text:t("settings.saving")});try{let v=await fetch("/api/settings",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(o)}),I=await v.json().catch(()=>({}));if(!n.current)return;if(!v.ok||I.ok===!1)throw new Error(I?.error??`HTTP ${v.status}`);p(K(I.settings)),M({text:t("settings.saved"),cls:"hint-ok"})}catch(v){if(!n.current)return;p(g),M({text:`${t("settings.saveFailed")}: ${v instanceof Error?v.message:String(v)}`,cls:"hint-warn-inline"})}finally{n.current&&x(null)}}async function ne(){R(null),D(!0),B(!1);try{let s=await fetch("/api/update/changelog"),o=await s.json().catch(()=>({}));if(!n.current)return;Y(typeof o?.releasesUrl=="string"?o.releasesUrl:""),s.ok?(R(Array.isArray(o.releases)?o.releases:[]),D(o.ok!==!1),B(o.rateLimited===!0)):(R([]),D(!1))}catch{if(!n.current)return;R([]),D(!1)}}function ae(){let s=Date.now(),o=async()=>{if(n.current){if(Date.now()-s>9e4){f(!1),m({text:t("update.restartSlow"),cls:"hint-warn-inline"});return}try{let u=await fetch("/__health",{cache:"no-store"});if(!n.current)return;if(u.ok){location.reload();return}}catch{}n.current&&H(()=>{o()},2e3)}};H(()=>{o()},3e3)}async function W(s){f(!0),m({text:t("update.restarting")});try{if(await fetch("/api/update/restart",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s?{update:s}:{})}),!n.current)return}catch(o){if(!n.current)return;f(!1),m({text:t("update.restartFailed",{detail:o instanceof Error?o.message:String(o)}),cls:"hint-warn-inline"});return}ae()}async function se(){let s=L;if(!s)return;if(!s.node.ok){window.alert(t("update.nodeTooOldAlert",{version:s.node.version,required:s.node.required}));return}if(s.installs.multiple){let u=s.installs.entries.map(g=>`\u2022 ${g.binPath} (${_(g.kind,t)})`).join(`
1
+ import{b as k}from"./chunk-ECXPBQ3J.js";import"./chunk-76J7PNZI.js";import"./chunk-MR57RUVP.js";import{a as oe,b as j,c as q}from"./chunk-JTSE5VP6.js";import{c as E}from"./chunk-7SZRL6FY.js";var i=E(oe(),1);var e=E(q(),1);function K(t){return{publicReadOnly:t?.publicReadOnly===!0,openTerminalInFeishu:t?.openTerminalInFeishu===!0,chatBotDiscovery:t?.chatBotDiscovery!==!1,repoPickerMode:t?.repoPickerMode==="repos"?"repos":"all",maintenance:t?.maintenance&&typeof t.maintenance=="object"?t.maintenance:{},localDevInstall:t?.localDevInstall===!0,whiteboard:{enabled:t?.whiteboard?.enabled===!0},remoteAccess:t?.remoteAccess===!0}}function le(t,n){let a=t?.[n]??{};return{enabled:a.enabled===!0,time:typeof a.time=="string"?a.time:"04:00"}}function _(t,n){return n(t==="npm-global"?"update.kindNpm":t==="source-checkout"?"update.kindSource":"update.kindUnknown")}function re(){let t=k(),n=(0,i.useRef)(!1),a=(0,i.useRef)(new Set),[r,p]=(0,i.useState)(null),[h,b]=(0,i.useState)(!1),[y,N]=(0,i.useState)(null),[S,U]=(0,i.useState)(!0),[l,c]=(0,i.useState)(!1),[d,x]=(0,i.useState)(null),[J,M]=(0,i.useState)(null),[L,C]=(0,i.useState)(null),[G,T]=(0,i.useState)(null),[A,R]=(0,i.useState)(null),[$,O]=(0,i.useState)(!1),[z,D]=(0,i.useState)(!0),[Q,B]=(0,i.useState)(!1),[X,Y]=(0,i.useState)(""),[Z,f]=(0,i.useState)(!1),[ee,m]=(0,i.useState)(null),F=(0,i.useCallback)(()=>{for(let s of a.current)window.clearTimeout(s);a.current.clear()},[]),H=(0,i.useCallback)((s,o)=>{let u=window.setTimeout(()=>{a.current.delete(u),s()},o);return a.current.add(u),u},[]),P=(0,i.useCallback)(async()=>{try{let s=await fetch("/api/update/status"),o=await s.json().catch(()=>({}));if(!n.current)return;if(!s.ok){C(null),T(o?.error??`HTTP ${s.status}`);return}C(o),T(null)}catch(s){if(!n.current)return;C(null),T(s instanceof Error?s.message:String(s))}},[]),V=(0,i.useCallback)(async()=>{try{let s=await fetch("/api/settings"),o=await s.json().catch(()=>({}));if(!n.current)return;if(!s.ok){p(null),N(o?.error??`HTTP ${s.status}`),b(!0);return}p(K(o.settings)),U(o.authed===!0),c(o.bound===!0),N(null),b(!0)}catch(s){if(!n.current)return;p(null),N(s instanceof Error?s.message:String(s)),b(!0)}},[]);(0,i.useEffect)(()=>(n.current=!0,V(),()=>{n.current=!1,F()}),[F,V]),(0,i.useEffect)(()=>{h&&(f(!1),m(null),O(!1),S&&P())},[S,P,h]);async function te(s,o,u){if(!r)return;let g=r;p(u(r)),x(s),M({text:t("settings.saving")});try{let v=await fetch("/api/settings",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(o)}),I=await v.json().catch(()=>({}));if(!n.current)return;if(!v.ok||I.ok===!1)throw new Error(I?.error??`HTTP ${v.status}`);p(K(I.settings)),M({text:t("settings.saved"),cls:"hint-ok"})}catch(v){if(!n.current)return;p(g),M({text:`${t("settings.saveFailed")}: ${v instanceof Error?v.message:String(v)}`,cls:"hint-warn-inline"})}finally{n.current&&x(null)}}async function ne(){R(null),D(!0),B(!1);try{let s=await fetch("/api/update/changelog"),o=await s.json().catch(()=>({}));if(!n.current)return;Y(typeof o?.releasesUrl=="string"?o.releasesUrl:""),s.ok?(R(Array.isArray(o.releases)?o.releases:[]),D(o.ok!==!1),B(o.rateLimited===!0)):(R([]),D(!1))}catch{if(!n.current)return;R([]),D(!1)}}function ae(){let s=Date.now(),o=async()=>{if(n.current){if(Date.now()-s>9e4){f(!1),m({text:t("update.restartSlow"),cls:"hint-warn-inline"});return}try{let u=await fetch("/__health",{cache:"no-store"});if(!n.current)return;if(u.ok){location.reload();return}}catch{}n.current&&H(()=>{o()},2e3)}};H(()=>{o()},3e3)}async function W(s){f(!0),m({text:t("update.restarting")});try{if(await fetch("/api/update/restart",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s?{update:s}:{})}),!n.current)return}catch(o){if(!n.current)return;f(!1),m({text:t("update.restartFailed",{detail:o instanceof Error?o.message:String(o)}),cls:"hint-warn-inline"});return}ae()}async function se(){let s=L;if(!s)return;if(!s.node.ok){window.alert(t("update.nodeTooOldAlert",{version:s.node.version,required:s.node.required}));return}if(s.installs.multiple){let u=s.installs.entries.map(g=>`\u2022 ${g.binPath} (${_(g.kind,t)})`).join(`
2
2
  `);if(!window.confirm(t("update.confirmMultiInstall",{paths:u})))return}let o=s.latest?t("update.confirmUpdate",{version:`v${s.latest}`}):t("update.confirmUpdateNoVer");if(window.confirm(o)){f(!0),m({text:t("update.updating")});try{let u=await fetch("/api/update/run",{method:"POST"}),g=await u.json().catch(()=>({}));if(!n.current)return;if(!u.ok||g.ok===!1){let v=g?.detail??g?.error??`HTTP ${u.status}`;f(!1),m({text:t("update.updateFailed",{detail:v}),cls:"hint-warn-inline"});return}g.changed?(f(!1),m({text:t("update.updatedChanged",{old:`v${g.oldVersion}`,new:`v${g.newVersion}`}),cls:"hint-ok"}),window.confirm(t("update.confirmRestart"))?await W({oldVersion:g.oldVersion,newVersion:g.newVersion}):n.current&&m({text:t("update.noRestartHint"),cls:"hint-ok"})):(f(!1),m({text:t("update.alreadyLatestRun",{version:`v${g.newVersion}`}),cls:"hint-ok"}),await P())}catch(u){if(!n.current)return;f(!1),m({text:t("update.updateFailed",{detail:u instanceof Error?u.message:String(u)}),cls:"hint-warn-inline"})}}}let ie=r?(0,e.jsx)(ce,{settings:r,canWrite:S,bound:l,savingKey:d,message:J,onSave:te}):y?(0,e.jsxs)("p",{className:"hint-warn",children:[t("settings.loadFailed"),": ",y]}):(0,e.jsx)("p",{className:"empty",children:t("settings.loading")});return(0,e.jsxs)("section",{className:"page",children:[(0,e.jsx)("div",{className:"page-heading",children:(0,e.jsxs)("div",{children:[(0,e.jsx)("p",{className:"eyebrow",children:t("nav.settings")}),(0,e.jsx)("h1",{children:t("settings.title")}),(0,e.jsx)("p",{children:t("settings.subtitle")})]})}),ie,(0,e.jsx)(ue,{canWrite:S,status:L,statusError:G,changelog:A,changelogOpen:$,changelogOk:z,changelogRateLimited:Q,releasesUrl:X,busy:Z,message:ee,onCheck:()=>{C(null),R(null),O(!1),m(null),T(null),P()},onToggleChangelog:()=>{let s=!$;O(s),s&&A===null&&ne()},onUpdate:()=>{se()},onRestart:()=>{window.confirm(t("update.confirmPlainRestart"))&&W(null)}})]})}function ce(t){let n=k(),{settings:a,canWrite:r,bound:p,savingKey:h}=t,b=!r,y=le(a.maintenance,"autoUpdate"),N=!r||a.localDevInstall,S=!r||a.maintenance.autoUpdate?.enabled!==!0,U=(l,c)=>{t.onSave(l,{[l]:c},d=>({...d,[l]:c}))};return(0,e.jsx)("div",{className:"settings-grid",children:(0,e.jsxs)("article",{className:"bd-card settings-card",children:[r?null:(0,e.jsx)("p",{className:"hint-warn",children:n("settings.readOnlyVisitor")}),(0,e.jsxs)("section",{className:"bd-section",children:[(0,e.jsx)("h3",{className:"bd-section-title",children:n("settings.sectionAccess")}),(0,e.jsx)(w,{title:n("settings.publicReadOnly"),help:n("settings.publicReadOnlyHelp"),checked:a.publicReadOnly,disabled:b||h==="publicReadOnly",onChange:l=>U("publicReadOnly",l)}),p?(0,e.jsx)(w,{title:n("settings.remoteAccess"),help:n("settings.remoteAccessHelp"),checked:a.remoteAccess,disabled:b||h==="remoteAccess",onChange:l=>U("remoteAccess",l)}):null]}),(0,e.jsxs)("section",{className:"bd-section",children:[(0,e.jsx)("h3",{className:"bd-section-title",children:n("settings.sectionCards")}),(0,e.jsx)(w,{title:n("settings.openTerminalInFeishu"),help:n("settings.openTerminalInFeishuHelp"),checked:a.openTerminalInFeishu,disabled:b||h==="openTerminalInFeishu",onChange:l=>U("openTerminalInFeishu",l)})]}),(0,e.jsxs)("section",{className:"bd-section",children:[(0,e.jsx)("h3",{className:"bd-section-title",children:n("settings.sectionExperimental")}),(0,e.jsx)(w,{title:n("settings.chatBotDiscovery"),help:n("settings.chatBotDiscoveryHelp"),checked:a.chatBotDiscovery,disabled:b||h==="chatBotDiscovery",onChange:l=>U("chatBotDiscovery",l)})]}),(0,e.jsxs)("section",{className:"bd-section",children:[(0,e.jsx)("h3",{className:"bd-section-title",children:"\u672C\u5730\u767D\u677F"}),(0,e.jsx)(w,{title:"\u542F\u7528\u9879\u76EE\u767D\u677F",help:"\u9ED8\u8BA4\u5173\u95ED\u3002\u5F00\u542F\u53EA\u542F\u7528\u80FD\u529B\uFF0C\u4E0D\u4F1A\u7ACB\u5373\u521B\u5EFA\u767D\u677F\uFF1B\u9996\u6B21\u9700\u8981\u65F6\u624D\u6309\u7FA4+\u9879\u76EE ensure\u3002",checked:a.whiteboard.enabled,disabled:b||h==="whiteboard",onChange:l=>{t.onSave("whiteboard",{whiteboard:{enabled:l}},c=>({...c,whiteboard:{enabled:l}}))}})]}),(0,e.jsxs)("section",{className:"bd-section",children:[(0,e.jsx)("h3",{className:"bd-section-title",children:n("settings.sectionRepoPicker")}),(0,e.jsxs)("label",{className:"form-row",children:[(0,e.jsx)("span",{children:n("settings.repoPickerMode")}),(0,e.jsxs)("select",{value:a.repoPickerMode,disabled:b||h==="repoPickerMode",onChange:l=>{let c=l.currentTarget.value==="repos"?"repos":"all";t.onSave("repoPickerMode",{repoPickerMode:c},d=>({...d,repoPickerMode:c}))},children:[(0,e.jsx)("option",{value:"all",children:n("settings.repoPickerModeAll")}),(0,e.jsx)("option",{value:"repos",children:n("settings.repoPickerModeRepos")})]}),(0,e.jsx)("small",{children:n("settings.repoPickerModeHelp")})]})]}),(0,e.jsxs)("section",{className:"bd-section",children:[(0,e.jsx)("h3",{className:"bd-section-title",children:n("settings.sectionMaintenance")}),(0,e.jsx)(w,{title:n("settings.autoUpdate"),help:n("settings.autoUpdateHelp"),checked:y.enabled,disabled:N||h==="autoUpdate",onChange:l=>{let c={enabled:l,time:y.time};t.onSave("autoUpdate",{maintenance:{autoUpdate:c}},d=>({...d,maintenance:{...d.maintenance,autoUpdate:c}}))}}),(0,e.jsx)("div",{className:"maint-time",children:(0,e.jsxs)("label",{children:[n("settings.maintenanceTime"),(0,e.jsx)("input",{type:"time",value:y.time,disabled:N||h==="autoUpdate",onChange:l=>{let c={enabled:y.enabled,time:l.currentTarget.value||"04:00"};t.onSave("autoUpdate",{maintenance:{autoUpdate:c}},d=>({...d,maintenance:{...d.maintenance,autoUpdate:c}}))}})]})}),a.localDevInstall?(0,e.jsx)("p",{className:"hint-warn",children:n("settings.autoUpdateLocalDev")}):null,(0,e.jsx)(w,{title:n("settings.autoRestart"),help:n("settings.autoRestartHelp"),checked:a.maintenance.autoRestart?.enabled===!0,disabled:S||h==="autoRestart",onChange:l=>{let c={enabled:l};t.onSave("autoRestart",{maintenance:{autoRestart:c}},d=>({...d,maintenance:{...d.maintenance,autoRestart:c}}))}})]}),(0,e.jsx)("div",{className:"actions settings-actions",children:(0,e.jsx)("span",{className:`oncall-status ${t.message?.cls??""}`,"data-settings-status":!0,children:t.message?.text??""})})]})})}function w(t){return(0,e.jsxs)("label",{className:"toggle-row",children:[(0,e.jsx)("input",{type:"checkbox",checked:t.checked,disabled:t.disabled,onChange:n=>t.onChange(n.currentTarget.checked)}),(0,e.jsx)("span",{className:"switch","aria-hidden":"true"}),(0,e.jsxs)("span",{className:"toggle-tx",children:[(0,e.jsx)("strong",{children:t.title}),(0,e.jsx)("small",{children:t.help})]})]})}function ue(t){let n=k(),a;if(!t.canWrite)a=(0,e.jsx)("p",{className:"hint-warn",children:n("update.loginRequired")});else if(t.statusError)a=(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("p",{className:"hint-warn",children:[n("update.checkFailed"),": ",t.statusError]}),(0,e.jsx)("div",{className:"update-actions",children:(0,e.jsx)("button",{type:"button","data-up":"check",onClick:t.onCheck,children:n("update.btnCheck")})})]});else if(!t.status)a=(0,e.jsx)("p",{className:"empty",children:n("update.loading")});else{let r=t.status,p=r.localDevInstall||t.busy;a=(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("p",{className:"update-version",children:[(0,e.jsxs)("span",{children:[n("update.current"),": ",(0,e.jsxs)("strong",{children:["v",r.current]})]})," ",(0,e.jsx)(de,{status:r})]}),r.node.ok?null:(0,e.jsx)("p",{className:"hint-warn",children:n("update.nodeWarn",{version:r.node.version,required:r.node.required})}),r.localDevInstall?(0,e.jsx)("p",{className:"hint-warn",children:n("update.localDev")}):null,r.installs.multiple?(0,e.jsx)(ge,{entries:r.installs.entries}):null,(0,e.jsxs)("div",{className:"update-actions",children:[(0,e.jsx)("button",{type:"button","data-up":"check",disabled:t.busy,onClick:t.onCheck,children:n("update.btnCheck")}),(0,e.jsx)("button",{type:"button","data-up":"changelog",disabled:t.busy,onClick:t.onToggleChangelog,children:t.changelogOpen?n("update.btnChangelogHide"):n("update.btnChangelog")}),(0,e.jsx)("button",{type:"button",className:"primary","data-up":"update",disabled:p,onClick:t.onUpdate,children:n("update.btnUpdate")}),(0,e.jsx)("button",{type:"button","data-up":"restart",disabled:t.busy,onClick:t.onRestart,children:n("update.btnRestart")})]}),t.changelogOpen?(0,e.jsx)(pe,{changelog:t.changelog,ok:t.changelogOk,rateLimited:t.changelogRateLimited,releasesUrl:t.releasesUrl}):null,t.message?(0,e.jsx)("p",{className:`oncall-status ${t.message.cls??""}`,children:t.message.text}):null]})}return(0,e.jsx)("div",{className:"settings-grid",children:(0,e.jsx)("article",{className:"bd-card settings-card",children:(0,e.jsxs)("section",{className:"bd-section",children:[(0,e.jsx)("h3",{className:"bd-section-title",children:n("update.section")}),a]})})})}function de(t){let n=k(),a=t.status;return a.latest?a.behind?(0,e.jsx)("span",{className:"update-badge update-badge-new",children:n("update.newAvailable",{version:`v${a.latest}`})}):(0,e.jsx)("span",{className:"update-badge update-badge-ok",children:n("update.upToDate")}):(0,e.jsx)("span",{className:"hint-warn-inline",children:n("update.checkUnavailable")})}function ge(t){let n=k();return(0,e.jsxs)("div",{className:"hint-warn",children:[(0,e.jsx)("p",{children:n("update.multiInstallWarn")}),(0,e.jsx)("ul",{className:"update-install-list",children:t.entries.map(a=>(0,e.jsxs)("li",{children:[(0,e.jsx)("code",{children:a.binPath})," \u2192 ",_(a.kind,n)," ",(0,e.jsx)("small",{children:a.root})]},`${a.binPath}:${a.root}`))})]})}function pe(t){let n=k();if(t.changelog===null)return(0,e.jsx)("p",{className:"empty",children:n("update.changelogLoading")});if(!t.ok){let a=t.rateLimited?n("update.changelogRateLimited"):n("update.changelogFailed");return(0,e.jsxs)("p",{className:"hint-warn-inline",children:[a,t.releasesUrl?(0,e.jsxs)(e.Fragment,{children:[" ",(0,e.jsx)("a",{href:t.releasesUrl,target:"_blank",rel:"noopener",children:n("update.changelogViewOnGitHub")})]}):null]})}return t.changelog.length===0?(0,e.jsx)("p",{className:"empty",children:n("update.changelogEmpty")}):(0,e.jsx)("div",{className:"update-changelog",children:t.changelog.map(a=>{let r=a.name&&a.name!==`v${a.version}`?a.name:"",p=a.publishedAt?new Date(a.publishedAt).toLocaleDateString():"";return(0,e.jsxs)("details",{className:"update-release",open:!0,children:[(0,e.jsxs)("summary",{children:[(0,e.jsxs)("strong",{children:["v",a.version]})," ",r," ",(0,e.jsx)("small",{children:p})," ",(0,e.jsx)("a",{href:a.url,target:"_blank",rel:"noopener",children:"\u2197"})]}),(0,e.jsx)("pre",{className:"update-release-body",children:a.body||""})]},a.version)})})}function fe(t){return j(t,(0,e.jsx)(re,{}))}export{fe as renderSettingsPage};
@@ -1,2 +1,2 @@
1
- import{b as F}from"./chunk-NASYW5FD.js";import"./chunk-76J7PNZI.js";import{p as W,w as ms}from"./chunk-JXLHRRJD.js";import{a as Js,b as ys,c as bs}from"./chunk-JTSE5VP6.js";import{c as z}from"./chunk-7SZRL6FY.js";var n=z(Js(),1);var s=z(bs(),1),qs=2;function V(e){let i=e.as??"span";return(0,s.jsx)(i,{style:{display:"contents"},dangerouslySetInnerHTML:{__html:e.html}})}function Ks(e,i){let a=String(e??"").replace(/\\/g,"/");return a.includes("/.codex/skills/")?i("skills.sourceCodex"):a.includes("/.claude/skills/")?i("skills.sourceClaude"):a.includes("/.trae/skills/")?i("skills.sourceTrae"):a.includes("/.cursor/skills/")?i("skills.sourceCursor"):a.includes("/.gemini/skills/")?i("skills.sourceGemini"):a.includes("/.config/opencode/skills/")?i("skills.sourceOpenCode"):null}function zs(e,i){let a=e.source??{};return a.type==="github"?`github:${a.owner}/${a.repo}/${a.path??""}`:a.type==="git"?`${a.url??"git"}#${a.path??""}`:a.type==="local-link"?Ks(a.path,i)??i("skills.sourceLocalLink"):a.type==="local-copy"?i("skills.sourceBotmuxCopy"):String(a.type??"unknown")}function G(e){return(e?.include??[]).filter(i=>i.startsWith("skill:")).map(i=>i.slice(6))}function Ws(e){return G(e).length}function Fs(e){return G(e).length>0}function M(e){return`${e.cliId}
1
+ import{b as F}from"./chunk-ECXPBQ3J.js";import"./chunk-76J7PNZI.js";import{p as W,w as ms}from"./chunk-MR57RUVP.js";import{a as Js,b as ys,c as bs}from"./chunk-JTSE5VP6.js";import{c as z}from"./chunk-7SZRL6FY.js";var n=z(Js(),1);var s=z(bs(),1),qs=2;function V(e){let i=e.as??"span";return(0,s.jsx)(i,{style:{display:"contents"},dangerouslySetInnerHTML:{__html:e.html}})}function Ks(e,i){let a=String(e??"").replace(/\\/g,"/");return a.includes("/.codex/skills/")?i("skills.sourceCodex"):a.includes("/.claude/skills/")?i("skills.sourceClaude"):a.includes("/.trae/skills/")?i("skills.sourceTrae"):a.includes("/.cursor/skills/")?i("skills.sourceCursor"):a.includes("/.gemini/skills/")?i("skills.sourceGemini"):a.includes("/.config/opencode/skills/")?i("skills.sourceOpenCode"):null}function zs(e,i){let a=e.source??{};return a.type==="github"?`github:${a.owner}/${a.repo}/${a.path??""}`:a.type==="git"?`${a.url??"git"}#${a.path??""}`:a.type==="local-link"?Ks(a.path,i)??i("skills.sourceLocalLink"):a.type==="local-copy"?i("skills.sourceBotmuxCopy"):String(a.type??"unknown")}function G(e){return(e?.include??[]).filter(i=>i.startsWith("skill:")).map(i=>i.slice(6))}function Ws(e){return G(e).length}function Fs(e){return G(e).length>0}function M(e){return`${e.cliId}
2
2
  ${e.rootDir}`}function Vs(e){return e>=1600?4:e<=620?1:e<=980?2:3}async function g(e,i){let a=await fetch(e,{...i,headers:{"content-type":"application/json",...i.headers??{}}}),f=await a.json().catch(()=>({}));if(!a.ok||f.ok===!1){let h=new Error(f?.error??`HTTP ${a.status}`);throw h.status=a.status,h.body=f,h}return f}function fs(e){return`oncall-status${e?` ${e.ok?"hint-ok":"hint-warn-inline"}`:""}`}function Qs(){let e=F(),i=(0,n.useRef)(!0),a=(0,n.useRef)(new Set),f=(0,n.useRef)(null),h=(0,n.useRef)(null),[p,A]=(0,n.useState)([]),[y,P]=(0,n.useState)([]),[k,I]=(0,n.useState)([]),[b,m]=(0,n.useState)("off"),[$,d]=(0,n.useState)("auto"),[C,Q]=(0,n.useState)(null),[X,Y]=(0,n.useState)(!0),[vs,gs]=(0,n.useState)(()=>window.innerWidth),[Z,hs]=(0,n.useState)(""),[ss,Ns]=(0,n.useState)(""),[ls,Ss]=(0,n.useState)(""),[es,N]=(0,n.useState)(null),[ws,ts]=(0,n.useState)(!1),[H,D]=(0,n.useState)(!1),[Ps,is]=(0,n.useState)(!1),[O,$s]=(0,n.useState)(null),[U,_]=(0,n.useState)(()=>new Set),[T,J]=(0,n.useState)(0),[as,j]=(0,n.useState)(null),[ns,E]=(0,n.useState)(null),[Cs,os]=(0,n.useState)(null),[Rs,rs]=(0,n.useState)({}),x=(0,n.useMemo)(()=>new Set(p.map(l=>l.name)),[p]),L=Vs(vs)*qs,R=Math.max(1,Math.ceil(p.length/L)),Ts=p.slice(T*L,T*L+L),S=(0,n.useMemo)(()=>y.length===0?void 0:(O?y.find(t=>M(t)===O):void 0)??y.find(t=>t.skills.length>0)??y[0],[O,y]),q=S?M(S):"",B=(0,n.useMemo)(()=>S?S.skills.filter(l=>!x.has(l.name)).map(l=>l.rootDir??l.source?.root??"").filter(Boolean):[],[S,x]),cs=B.length>0&&B.every(l=>U.has(l)),ds=(0,n.useCallback)(()=>{for(let l of a.current)window.clearTimeout(l);a.current.clear()},[]),Bs=(0,n.useCallback)(l=>new Promise(t=>{let o=window.setTimeout(()=>{a.current.delete(o),t()},l);a.current.add(o)}),[]),us=(0,n.useCallback)(async()=>{let[l,t]=await Promise.all([fetch("/api/skills"),fetch("/api/bots")]),o=await l.json().catch(()=>({})),c=await t.json().catch(()=>({}));if(!l.ok){let r=o?.error??`skills HTTP ${l.status}`;throw new Error(r==="not_found_yet"||r==="not_found"?e("skills.apiUnavailable"):r)}if(!t.ok)throw new Error(c?.error??`bots HTTP ${t.status}`);return{skills:Array.isArray(o.skills)?o.skills:[],nativeSkillGroups:Array.isArray(o.nativeSkillGroups)?o.nativeSkillGroups:[],bots:Array.isArray(c.bots)?c.bots:[],trustProjectSkills:o.trustProjectSkills==="all"?"all":"off",delivery:o.delivery==="prompt"||o.delivery==="native"?o.delivery:"auto"}},[e]),w=(0,n.useCallback)(async()=>{Y(!0);try{let l=await us();if(!i.current)return;A(l.skills),P(l.nativeSkillGroups),I(l.bots),m(l.trustProjectSkills),d(l.delivery),Q(null),_(t=>{let o=new Set,c=new Set(l.skills.map(r=>r.name));for(let r of l.nativeSkillGroups)for(let u of r.skills){let v=u.rootDir??u.source?.root??"";v&&!c.has(u.name)&&t.has(v)&&o.add(v)}return o})}catch(l){if(!i.current)return;Q(l?.message??String(l))}finally{i.current&&Y(!1)}},[us]);(0,n.useEffect)(()=>{i.current=!0,w();let l=()=>gs(window.innerWidth);return window.addEventListener("resize",l),()=>{i.current=!1,ds(),window.removeEventListener("resize",l)}},[ds,w]),(0,n.useEffect)(()=>{J(l=>Math.min(Math.max(0,l),R-1))},[R]),(0,n.useEffect)(()=>{let l=f.current;if(l)if(H&&!l.open)try{l.showModal()}catch{}else!H&&l.open&&l.close()},[H,q]);async function ks(l,t,o=!0){let c=l;for(t({text:e("skills.jobRunning"),ok:!0});;){if(!i.current)return;if(c.status==="succeeded"){t({text:e("skills.saved"),ok:!0}),o&&await w();return}if(c.status==="failed")throw new Error(c.error??"job_failed");if(await Bs(800),!i.current)return;let r=await g(`/api/skills/jobs/${encodeURIComponent(c.id)}`,{method:"GET"});if(!i.current)return;c=r.job}}function As(l){return k.filter(t=>G(t.skills).includes(l)).map(t=>t.botName??t.larkAppId)}async function Is(){ts(!0);try{let l=await g("/api/skills/install",{method:"POST",body:JSON.stringify({source:Z.trim(),path:ss.trim()||void 0,ref:ls.trim()||void 0})});if(!i.current)return;await ks(l.job,N)}catch(l){i.current&&N({text:`${e("skills.failed")}: ${l?.message??l}`,ok:!1})}finally{i.current&&ts(!1)}}async function Ds(){let l=[...U].filter(Boolean);if(l.length===0){N({text:e("skills.discoverNothingSelected"),ok:!1});return}is(!0);try{if(N({text:e("skills.discoverRegisteringBatch",{total:l.length}),ok:!0}),await g("/api/skills/install-local-links",{method:"POST",body:JSON.stringify({sources:l})}),!i.current)return;D(!1),await w(),i.current&&N({text:e("skills.saved"),ok:!0})}catch(t){i.current&&N({text:`${e("skills.failed")}: ${t?.message??t}`,ok:!1})}finally{i.current&&is(!1)}}async function js(l){if(b!==l){j("project");try{let t=await g("/api/skills/global",{method:"PUT",body:JSON.stringify({trustProjectSkills:l})});if(!i.current)return;m(t.trustProjectSkills==="all"?"all":l)}catch(t){i.current&&window.alert(`${e("skills.failed")}: ${t?.message??t}`)}finally{i.current&&j(null)}}}async function Es(l){if($!==l){j("delivery");try{let t=await g("/api/skills/global",{method:"PUT",body:JSON.stringify({delivery:l})});if(!i.current)return;d(t.delivery==="prompt"||t.delivery==="native"?t.delivery:l)}catch(t){i.current&&window.alert(`${e("skills.failed")}: ${t?.message??t}`)}finally{i.current&&j(null)}}}function ps(l){let t=h.current,o=t?.querySelector(".skills-bot-card");if(!t||!o)return;let c=window.getComputedStyle(t),r=Number.parseFloat(c.columnGap||c.gap||"0")||0;t.scrollBy({left:l*(o.getBoundingClientRect().width+r),behavior:"smooth"})}async function xs(l){E(`${l}:update`);try{let t=await g(`/api/skills/${encodeURIComponent(l)}/update`,{method:"POST",body:"{}"});if(!i.current)return;await ks(t.job,N)}catch(t){i.current&&window.alert(`${e("skills.failed")}: ${t?.message??t}`)}finally{i.current&&E(null)}}async function Ls(l){if(window.confirm(`${e("skills.remove")} ${l}?`)){E(`${l}:remove`);try{if(await g(`/api/skills/${encodeURIComponent(l)}`,{method:"DELETE",body:"{}"}),!i.current)return;await w()}catch(t){if(!i.current)return;if(t?.status===409&&t?.body?.error==="skill_in_use"){let o=Array.isArray(t.body.affectedBots)?t.body.affectedBots.map(r=>{let u=r?.botName||r?.larkAppId;return u?`${u}`:""}).filter(Boolean):As(l),c=[o.length?`Bot: ${o.join(", ")}`:""].filter(Boolean).join("; ")||"-";if(!window.confirm(e("skills.removeInUse",{skill:l,refs:c})))return;try{if(await g(`/api/skills/${encodeURIComponent(l)}?force=1`,{method:"DELETE",body:"{}"}),!i.current)return;await w();return}catch(r){i.current&&window.alert(`${e("skills.failed")}: ${r?.message??r}`);return}}window.alert(`${e("skills.failed")}: ${t?.message??t}`)}finally{i.current&&E(null)}}}async function Ms(l,t,o){let c=`${l}:${t}:${o}`;os(c),rs(r=>({...r,[l]:null}));try{let r=await g(`/api/bots/${encodeURIComponent(l)}/skills`,{method:"PUT",body:JSON.stringify({action:t,name:o})});if(!i.current)return;I(u=>u.map(v=>v.larkAppId===l?{...v,skills:r.skills??null}:v))}catch(r){i.current&&rs(u=>({...u,[l]:{text:`${e("skills.failed")}: ${r?.message??r}`,ok:!1}}))}finally{i.current&&os(null)}}let Gs=k.filter(l=>Fs(l.skills)).length,Hs=k.reduce((l,t)=>l+Ws(t.skills),0),Os=X?(0,s.jsx)(V,{html:ms(),as:"div"}):C?(0,s.jsx)("p",{className:"hint-warn",children:C}):(0,s.jsxs)("div",{className:"skills-page-grid",children:[(0,s.jsxs)("aside",{className:"skills-side-rail",children:[(0,s.jsxs)("article",{className:"bd-card skills-defaults-panel",children:[(0,s.jsx)("h3",{className:"bd-section-title",children:e("skills.globalDefaults")}),(0,s.jsxs)("div",{className:"skills-control-block",children:[(0,s.jsx)("span",{className:"skills-control-label",children:e("skills.globalProject")}),(0,s.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(([l,t,o])=>(0,s.jsxs)("button",{type:"button",className:`skills-choice${b===l?" selected":""}`,"data-global-project-value":l,"aria-pressed":b===l?"true":"false",disabled:as==="project",onClick:()=>{js(l)},children:[(0,s.jsx)("strong",{children:t}),(0,s.jsx)("small",{children:o})]},l))})]}),(0,s.jsxs)("div",{className:"skills-control-block",children:[(0,s.jsx)("span",{className:"skills-control-label",children:e("skills.globalDelivery")}),(0,s.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(([l,t,o])=>(0,s.jsxs)("button",{type:"button",className:`skills-choice${$===l?" selected":""}`,"data-global-delivery-value":l,"aria-pressed":$===l?"true":"false",disabled:as==="delivery",onClick:()=>{Es(l)},children:[(0,s.jsx)("strong",{children:t}),(0,s.jsx)("small",{children:o})]},l))})]})]}),(0,s.jsxs)("article",{className:"bd-card skills-install-panel",children:[(0,s.jsxs)("div",{className:"skills-install-title",children:[(0,s.jsx)("h3",{className:"bd-section-title",children:e("skills.install")}),(0,s.jsxs)("span",{className:"skills-help-tip",children:[(0,s.jsx)("button",{type:"button",className:"skills-help-button","aria-label":e("skills.installInfoLabel"),children:"?"}),(0,s.jsx)("span",{className:"skills-help-popover",role:"tooltip",children:e("skills.installInfo")})]})]}),(0,s.jsxs)("div",{className:"skills-install-grid",children:[(0,s.jsxs)("div",{className:"skills-source-label",children:[(0,s.jsx)("span",{children:e("skills.source")}),(0,s.jsxs)("div",{className:"skills-source-control",children:[(0,s.jsx)("input",{type:"text","data-install":"source","aria-label":e("skills.source"),placeholder:e("skills.sourcePlaceholder"),value:Z,onChange:l=>hs(l.currentTarget.value)}),(0,s.jsx)("button",{type:"button","data-action":"discover-native-skills",onClick:()=>D(!0),children:e("skills.discover")})]})]}),(0,s.jsxs)("div",{className:"bd-section-note skills-install-note",children:[(0,s.jsxs)("span",{children:[(0,s.jsx)("strong",{children:e("skills.sourceHelpRemoteLabel")}),e("skills.sourceHelpRemote")]}),(0,s.jsxs)("span",{children:[(0,s.jsx)("strong",{children:e("skills.sourceHelpLocalLabel")}),e("skills.sourceHelpLocal")]})]}),(0,s.jsxs)("label",{className:"skills-install-field-wide",children:[(0,s.jsx)("span",{children:e("skills.path")}),(0,s.jsx)("input",{type:"text","data-install":"path",placeholder:e("skills.pathPlaceholder"),value:ss,onChange:l=>Ns(l.currentTarget.value)})]}),(0,s.jsxs)("label",{className:"skills-install-field-wide",children:[(0,s.jsx)("span",{children:e("skills.ref")}),(0,s.jsx)("input",{type:"text","data-install":"ref",placeholder:e("skills.refPlaceholder"),value:ls,onChange:l=>Ss(l.currentTarget.value)})]})]}),(0,s.jsxs)("div",{className:"actions",children:[(0,s.jsx)("button",{type:"button",className:"primary","data-action":"install",disabled:ws,onClick:()=>{Is()},children:e("skills.installSubmit")}),(0,s.jsx)("span",{className:fs(es),"data-skills-status":!0,children:es?.text??""})]})]})]}),(0,s.jsxs)("section",{className:"skills-main-panel",children:[(0,s.jsxs)("section",{className:"skills-overview",children:[(0,s.jsxs)("div",{className:"skills-overview-copy",children:[(0,s.jsx)("h2",{children:e("skills.overviewTitle")}),(0,s.jsx)("p",{children:e("skills.overviewBody")})]}),(0,s.jsxs)("div",{className:"skills-metric-strip",children:[(0,s.jsxs)("span",{children:[(0,s.jsx)("small",{children:e("skills.metricInstalled")}),(0,s.jsx)("strong",{children:p.length})]}),(0,s.jsxs)("span",{children:[(0,s.jsx)("small",{children:e("skills.metricBots")}),(0,s.jsxs)("strong",{children:[Gs,"/",k.length]})]}),(0,s.jsxs)("span",{children:[(0,s.jsx)("small",{children:e("skills.metricAttached")}),(0,s.jsx)("strong",{children:Hs})]})]})]}),(0,s.jsxs)("section",{className:"skills-bots-panel",children:[(0,s.jsxs)("div",{className:"skills-section-head skills-section-head-row",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{children:e("skills.bots")}),(0,s.jsx)("p",{children:e("skills.botsHelp")})]}),k.length>3?(0,s.jsxs)("div",{className:"skills-bot-rail-actions",children:[(0,s.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:()=>ps(-1),children:"\u2039"}),(0,s.jsx)("span",{className:"skills-count-pill",children:e("skills.botCount",{count:k.length})}),(0,s.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:()=>ps(1),children:"\u203A"})]}):(0,s.jsx)("span",{className:"skills-count-pill",children:e("skills.botCount",{count:k.length})})]}),(0,s.jsx)("div",{className:"skills-bot-grid",ref:h,children:k.map(l=>(0,s.jsx)(Xs,{bot:l,installedNames:x,skills:p,status:Rs[l.larkAppId]??null,busyKey:Cs,onUpdate:Ms},l.larkAppId))})]}),(0,s.jsxs)("section",{className:"bd-card skills-installed-panel",children:[(0,s.jsxs)("div",{className:"skills-section-head skills-section-head-row",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{children:e("skills.installed")}),(0,s.jsx)("p",{children:e("skills.installedHelp")})]}),R<=1?(0,s.jsx)("span",{className:"skills-count-pill",children:e("skills.skillCount",{count:p.length})}):(0,s.jsxs)("div",{className:"skills-installed-toolbar",children:[(0,s.jsx)("span",{className:"skills-count-pill",children:e("skills.skillCount",{count:p.length})}),(0,s.jsxs)("div",{className:"skills-pager",children:[(0,s.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:T===0,onClick:()=>J(l=>Math.max(0,l-1)),children:"\u2039"}),(0,s.jsx)("span",{children:e("skills.pageStatus",{page:T+1,pages:R})}),(0,s.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:T>=R-1,onClick:()=>J(l=>Math.min(R-1,l+1)),children:"\u203A"})]})]})]}),p.length===0?(0,s.jsx)("p",{className:"empty",children:e("skills.empty")}):(0,s.jsx)("div",{className:"skills-list",children:Ts.map(l=>(0,s.jsxs)("article",{className:"skills-row skills-installed-card","data-skill":l.name,children:[(0,s.jsxs)("div",{className:"skills-row-body",children:[(0,s.jsx)("strong",{children:l.name}),l.description?(0,s.jsx)("p",{children:l.description}):null,(0,s.jsx)("small",{className:"skills-source-badge",children:zs(l,e)})]}),(0,s.jsxs)("div",{className:"skills-card-actions",children:[(0,s.jsx)("button",{type:"button","data-action":"update-skill",disabled:ns===`${l.name}:update`,onClick:()=>{xs(l.name)},children:e("skills.update")}),(0,s.jsx)("button",{type:"button","data-action":"remove-skill",disabled:ns===`${l.name}:remove`,onClick:()=>{Ls(l.name)},children:e("skills.remove")})]})]},l.name))})]})]}),(0,s.jsx)("dialog",{className:"skills-discovery-dialog",id:"skills-discovery-dialog",ref:f,onClose:()=>D(!1),children:(0,s.jsxs)("article",{children:[(0,s.jsxs)("header",{children:[(0,s.jsx)("h3",{children:e("skills.discoverTitle")}),(0,s.jsx)("p",{children:e("skills.discoverHelp")})]}),(0,s.jsx)("div",{className:"skills-discovery-body",children:S?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"skills-discovery-tabs",role:"tablist","aria-label":e("skills.discoverTitle"),children:y.map(l=>{let t=M(l),o=t===q;return(0,s.jsxs)("button",{type:"button",role:"tab","data-discovery-tab":t,className:o?"selected":"","aria-selected":o?"true":"false",onClick:()=>$s(t),children:[(0,s.jsx)("strong",{children:l.label??l.cliId}),(0,s.jsx)("small",{children:e("skills.skillCount",{count:l.skills.length})})]},t)})}),(0,s.jsx)("div",{className:"skills-discovery-path",children:(0,s.jsx)("code",{children:S.rootDir})}),y.map(l=>{let t=M(l);return(0,s.jsx)("section",{className:"skills-discovery-group","data-discovery-panel":t,hidden:!(t===q),children:l.skills.length===0?(0,s.jsx)("p",{className:"empty",children:e("skills.discoverGroupEmpty")}):(0,s.jsx)("div",{className:"skills-discovery-list",children:l.skills.map(c=>{let r=x.has(c.name),u=c.rootDir??c.source?.root??"";return(0,s.jsxs)("label",{className:`skills-discovery-row${r?" installed":""}`,children:[(0,s.jsx)("input",{type:"checkbox","data-discovered-skill":!0,value:u,disabled:r,checked:!r&&U.has(u),onChange:v=>{let Us=v.currentTarget.checked;_(_s=>{let K=new Set(_s);return Us?K.add(u):K.delete(u),K})}}),(0,s.jsxs)("span",{children:[(0,s.jsx)("strong",{children:c.name}),c.description?(0,s.jsx)("small",{children:c.description}):null]}),r?(0,s.jsx)("em",{children:e("skills.discoverRegistered")}):null]},`${c.name}:${u}`)})})},t)})]}):(0,s.jsx)("p",{className:"empty",children:e("skills.discoverEmpty")})}),(0,s.jsxs)("footer",{className:"actions",children:[(0,s.jsx)("button",{type:"button","data-action":"toggle-discovered-skills",disabled:B.length===0,onClick:()=>{_(l=>{let t=new Set(l);return cs?B.forEach(o=>t.delete(o)):B.forEach(o=>t.add(o)),t})},children:e(cs?"skills.discoverClearSelection":"skills.discoverSelectAll")}),(0,s.jsx)("button",{type:"button",className:"primary","data-action":"register-discovered-skills",disabled:Ps,onClick:()=>{Ds()},children:e("skills.discoverRegister")}),(0,s.jsx)("button",{type:"button","data-action":"close-discovery",onClick:()=>D(!1),children:e("skills.discoverClose")})]})]})})]});return(0,s.jsxs)("section",{className:"page",children:[(0,s.jsxs)("div",{className:"page-heading",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"eyebrow",children:e("nav.skills")}),(0,s.jsx)("h1",{children:e("skills.title")}),(0,s.jsx)("p",{children:e("skills.subtitle")})]}),(0,s.jsx)("button",{type:"button",id:"skills-refresh",disabled:X,onClick:()=>{w()},children:e("skills.refresh")})]}),(0,s.jsx)("div",{id:"skills-body",children:Os})]})}function Xs(e){let i=F(),{bot:a,installedNames:f,skills:h,status:p,busyKey:A,onUpdate:y}=e,P=a.botName??a.larkAppId,k=G(a.skills),I=new Set(k),b=h.filter(d=>!I.has(d.name)),[m,$]=(0,n.useState)(b[0]?.name??"");return(0,n.useEffect)(()=>{(!m||!b.some(d=>d.name===m))&&$(b[0]?.name??"")},[b,m]),a.error?(0,s.jsxs)("article",{className:"bd-card skills-bot-card","data-appid":a.larkAppId,children:[(0,s.jsxs)("header",{children:[(0,s.jsx)(V,{html:W({name:P,larkAppId:a.larkAppId,size:"sm"})}),(0,s.jsx)("strong",{children:P})]}),(0,s.jsx)("p",{className:"hint-warn-inline",children:a.error})]}):(0,s.jsxs)("article",{className:"bd-card skills-bot-card","data-appid":a.larkAppId,children:[(0,s.jsxs)("header",{className:"skills-bot-head",children:[(0,s.jsx)(V,{html:W({name:P,larkAppId:a.larkAppId,size:"sm",dot:"ok"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("strong",{children:P}),(0,s.jsx)("code",{children:a.larkAppId})]}),(0,s.jsx)("span",{className:"skills-count-pill",children:i("skills.skillCount",{count:k.length})})]}),(0,s.jsxs)("section",{className:"bd-section",children:[(0,s.jsx)("h3",{className:"bd-section-title",children:i("skills.priority")}),k.length===0?(0,s.jsx)("p",{className:"bd-section-note",children:i("skills.noPriority")}):(0,s.jsx)("div",{className:"skills-chip-list",children:k.map(d=>{let C=!f.has(d);return(0,s.jsxs)("span",{className:`skills-priority-row${C?" skills-priority-dangling":""}`,title:C?i("skills.dangling"):"",children:[(0,s.jsxs)("span",{className:"skills-priority-name",children:[d,C?(0,s.jsx)("small",{children:i("skills.dangling")}):null]}),(0,s.jsx)("button",{type:"button",className:"skills-priority-remove","data-action":"detach-skill","data-name":d,"aria-label":i("skills.detachNamed",{skill:d}),disabled:A===`${a.larkAppId}:detach:${d}`,onClick:()=>{y(a.larkAppId,"detach",d)},children:"\xD7"})]},d)})}),(0,s.jsx)("div",{className:"actions skills-attach-row",children:b.length===0?(0,s.jsx)("button",{type:"button",disabled:!0,children:i("skills.attach")}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("select",{"data-attach-picker":!0,value:m,onChange:d=>$(d.currentTarget.value),children:b.map(d=>(0,s.jsx)("option",{value:d.name,children:d.name},d.name))}),(0,s.jsx)("button",{type:"button","data-action":"attach-skill",disabled:!m||A===`${a.larkAppId}:attach:${m}`,onClick:()=>m&&void y(a.larkAppId,"attach",m),children:i("skills.attach")})]})})]}),(0,s.jsx)("span",{className:fs(p),"data-bot-status":!0,children:p?.text??""})]})}function ll(e){return ys(e,(0,s.jsx)(Qs,{}))}export{Xs as BotPolicyCard,ll as renderSkillsPage};
@@ -1,4 +1,4 @@
1
- import{b as w}from"./chunk-NASYW5FD.js";import"./chunk-76J7PNZI.js";import{m as n,n as d}from"./chunk-JXLHRRJD.js";import{a as V,b as R,c as P}from"./chunk-JTSE5VP6.js";import{c as N}from"./chunk-7SZRL6FY.js";var k=N(V(),1);async function E(e){let t=await fetch(e);return{status:t.status,body:await t.json().catch(()=>({}))}}async function S(e,t,o){let a=await fetch(t,{method:e,headers:{"content-type":"application/json"},body:o?JSON.stringify(o):void 0});return{status:a.status,body:await a.json().catch(()=>({}))}}var x=(e,t)=>S("POST",e,t),X=(e,t)=>S("PUT",e,t),z=[],U=[],q="",I="",A=new Map,H=new Map,$=new Set,M=new Set,y=0;function _(){return y+=1,y}function f(e){return y===e}function c(e){return document.getElementById(e)}function B(){return[...z,...U]}function T(e){let t=A.get(e);return t||(t=new Set,A.set(e,t)),t}function Y(e){return B().find(t=>t.key===e)}function Z(e){let t=(c("tf-search").value||"").trim().toLowerCase();if(t&&!((e.name||"")+" "+(e.cliId||"")+" "+(e.capability||"")).toLowerCase().includes(t))return!1;let o=c("tf-cli").value;return!(o&&e.cliId!==o||c("tf-fcap").checked&&!e.capability||c("tf-frole").checked&&!e.hasTeamRole)}function ee(e,t){let o=[...e.deployments].sort((r,s)=>r.local===s.local?0:r.local?-1:1),a="";for(let r of o){let s=t.filter(p=>p.deployment.id===r.id);if(!s.length)continue;let m=r.id===q,l=m?n("team.tagLocal"):r.stale?n("team.tagRemoteStale"):n("team.tagRemote"),u=e.kind==="local"&&!m?` <button class="tf-rmmember ghost" data-team="${d(e.teamId)}" data-dep="${d(r.id)}" data-name="${d(r.name)}" style="font-size:12px">${n("team.removeMember")}</button>`:"",g=`${e.key}::${r.id}`,b=M.has(g),v=s.filter(p=>T(e.key).has(p.larkAppId)).length;if(a+=`<div class="tf-dep-h" data-dk="${d(g)}" style="cursor:pointer;margin:10px 0 2px"><b>${b?"\u25BE":"\u25B8"} ${d(r.name)}</b> <span class="muted" style="font-size:12px">${n("team.depTag",{tag:l})} \xB7 ${n("team.depCount",{count:s.length})}${v?n("team.depSelected",{n:v}):""}</span>${u}</div>`,!!b){a+='<table style="width:100%;border-collapse:collapse;font-size:14px"><tbody>';for(let p of s){let C=d(p.larkAppId),W=T(e.key).has(p.larkAppId)?" checked":"",K=p.deployment.stale?"opacity:.55":"",J=m?`<input class="tf-cap" data-app="${C}" value="${d(p.capability||"")}" placeholder="${n("team.capPh")}" style="width:92%;padding:3px 6px">`:p.capability?d(p.capability):'<span class="muted">\u2014</span>',Q=p.hasTeamRole?m?`<button class="tf-role" data-app="${C}" data-name="${d(p.name)}">${n("team.viewRole")}</button>`:n("team.hasRoleShort"):'<span class="muted">\u2014</span>';a+=`<tr style="${K}"><td style="padding:4px 8px"><input type="checkbox" class="tf-pick" data-tk="${d(e.key)}" data-app="${C}"${W}></td><td style="padding:4px 8px">${d(p.name)}</td><td style="padding:4px 8px" class="muted">${d(p.cliId)}</td><td style="padding:4px 8px">${J}</td><td style="padding:4px 8px">${Q}</td></tr>`}a+="</tbody></table>"}}return a||(a=`<p class="muted" style="margin:8px 0 0">${n("team.noMatch")}</p>`),a+=`<div style="margin-top:12px;display:flex;gap:8px;flex-wrap:wrap;align-items:center"><input class="tf-gname" data-tk="${d(e.key)}" value="${d(H.get(e.key)||"")}" placeholder="${n("team.gnamePh")}" style="min-width:200px"><button class="tf-grp primary" data-tk="${d(e.key)}">${n("team.pullGroupBtn")}</button><span class="muted" style="font-size:13px">${n("team.pullGroupHint")}</span><span class="tf-gout" data-tk="${d(e.key)}" style="font-size:13px;display:block;flex-basis:100%"></span></div>`,a}function h(){let e=c("tf-teams"),t=B();if(!t.length){e.innerHTML=`<p class="muted">${n("team.noTeams")}</p>`,c("tf-count").textContent="";return}let o="",a=new Set,r=new Set;for(let l of t){let u=l.bots.filter(Z);u.forEach(p=>a.add(p.larkAppId)),l.bots.forEach(p=>r.add(p.larkAppId));let g=new Set(u.map(p=>p.larkAppId));[...T(l.key)].forEach(p=>{g.has(p)||T(l.key).delete(p)});let b=!$.has(l.key),v=l.kind==="remote"?l.ok?` <span class="ok" style="font-size:12px">${n("team.connected")}</span>`:` <span class="err" style="font-size:12px">${n("team.connectFail",{error:d(l.error||"")})}</span>`:` <span class="muted" style="font-size:12px">${n("team.iHost")}</span>`;o+=`<div class="card" style="margin:0 0 12px;padding:12px 14px;background:var(--bg-soft,#f6f7f9)"><div class="tf-team-h" data-tk="${d(l.key)}" style="cursor:pointer;display:flex;align-items:center;gap:8px;flex-wrap:wrap"><b style="font-size:15px">${b?"\u25B8":"\u25BE"} ${d(l.label)}</b>`+(l.sub?` <span class="muted" style="font-size:12px">${d(l.sub)}</span>`:"")+v+` <span class="muted" style="font-size:12px">\xB7 ${n("team.teamMeta",{deps:l.deployments.length,bots:l.bots.length})}</span></div>`,b||(o+=l.kind==="remote"&&!l.ok?`<p class="muted" style="margin:8px 0 0">${n("team.rosterFail")}</p>`:ee(l,u)),o+="</div>"}e.innerHTML=o;let s=t.length>1?n("team.acrossTeams",{n:t.length}):"",m=a.size===r.size?`${r.size}`:`${a.size} / ${r.size}`;c("tf-count").textContent=`\xB7 ${m} ${n("team.botsWord")}${s}`,te(y)}function te(e=y){let t=c("tf-teams");t.querySelectorAll(".tf-team-h").forEach(o=>{o.onclick=()=>{let a=o.dataset.tk;$.has(a)?$.delete(a):$.add(a),h()}}),t.querySelectorAll(".tf-dep-h").forEach(o=>{o.onclick=()=>{let a=o.dataset.dk;M.has(a)?M.delete(a):M.add(a),h()}}),t.querySelectorAll(".tf-pick").forEach(o=>{o.onchange=()=>{let a=T(o.dataset.tk);o.checked?a.add(o.dataset.app):a.delete(o.dataset.app)}}),t.querySelectorAll(".tf-gname").forEach(o=>{o.oninput=()=>{H.set(o.dataset.tk,o.value)}}),t.querySelectorAll(".tf-cap").forEach(o=>{o.onchange=async()=>{let a=o.dataset.app,r=o.value;await X("/api/team/local-bots/"+encodeURIComponent(a)+"/capability",{capability:r}),f(e)&&B().forEach(s=>{let m=s.bots.find(l=>l.larkAppId===a);m&&(m.capability=r.trim()||null)})}}),t.querySelectorAll(".tf-role").forEach(o=>{o.onclick=()=>ne(o.dataset.app,o.dataset.name||"",e)}),t.querySelectorAll(".tf-rmmember").forEach(o=>{o.onclick=async a=>{a.stopPropagation(),confirm(n("team.removeMemberConfirm",{name:o.dataset.name||""}))&&(await S("DELETE",`/api/team/hosted/${encodeURIComponent(o.dataset.team)}/members/${encodeURIComponent(o.dataset.dep)}`),f(e)&&L(e))}}),t.querySelectorAll(".tf-grp").forEach(o=>{o.onclick=async()=>{let a=o.dataset.tk,r=Y(a);if(!r)return;let s=[...T(a)],m=t.querySelector(`.tf-gout[data-tk="${CSS.escape(a)}"]`);if(!s.length){m.innerHTML=`<span class="err">${n("team.errPickBot")}</span>`;return}let l=(t.querySelector(`.tf-gname[data-tk="${CSS.escape(a)}"]`)?.value||"").trim()||n("team.defaultGroupName");m.innerHTML=`<span class="muted">${n("team.creatingGroup")}</span>`;let u=r.kind==="local"?await x("/api/team/federated-group",{name:l,larkAppIds:s,teamId:r.teamId}):await x("/api/team/remote-group",{hubUrl:r.hubUrl,teamId:r.teamId,name:l,larkAppIds:s});if(f(e)&&(ae(m,u.body,u.status),u.body?.ok)){T(a).clear(),H.delete(a);let g=m.innerHTML,b=()=>{if(!f(e))return;let v=t.querySelector(`.tf-gout[data-tk="${CSS.escape(a)}"]`);v&&(v.innerHTML=g)};r.kind==="local"?L(e).then(b):(h(),b())}}})}function ae(e,t,o){if(t?.ok&&t.chatId){let a=t.shareLink||"https://applink.feishu.cn/client/chat/open?openChatId="+encodeURIComponent(t.chatId),r=(t.invalidBotIds||[]).length?` <span class="err"> \xB7 ${n("team.invalidBots",{ids:d((t.invalidBotIds||[]).join(", "))})}</span>`:"",s=(t.invalidOwnerUnionIds||[]).length?`<span class="err"> \xB7 ${n("team.invalidOwners",{n:(t.invalidOwnerUnionIds||[]).length})}</span>`:"",m=t.missingOperatorIdentity?`<span class="err"> \xB7 ${n("team.missingIdentity")}</span>`:"",l=(t.skippedNoOwner||[]).length?`<span class="err"> \xB7 ${n("team.skippedNoOwner",{n:(t.skippedNoOwner||[]).length})}</span>`:"",u=t.delegatedTo?n("team.delegatedBy",{name:d(t.delegatedTo)}):"";e.innerHTML=`<span class="ok">${n("team.groupCreated")}</span>${u} \xB7 <a href="${d(a)}" target="_blank">${n("team.openInLark")}</a>${r}${s}${m}${l}`}else{let a=t?.error||o,r=a==="no_local_online_bot"?n("team.errNoLocalBot"):a==="all_bots_skipped_no_owner"?n("team.errAllSkipped"):a==="no_creator_available"?n("team.errNoCreator"):a==="delegation_timeout"?n("team.errDelegationTimeout"):n("team.errGroupCreate",{error:String(a)});e.innerHTML=`<span class="err">${d(String(r))}</span>`}}async function ne(e,t,o=y){let a=await E("/api/team/local-bots/"+encodeURIComponent(e)+"/role");f(o)&&(c("tf-modal-title").textContent=n("team.roleModalTitleName",{name:t}),c("tf-modal-text").value=a.body?.role||"",c("tf-modal").dataset.app=e,c("tf-modal").style.display="flex")}function D(){let e=Array.from(new Set(B().flatMap(a=>a.bots.map(r=>r.cliId)).filter(Boolean))).sort(),t=c("tf-cli"),o=t.value;t.innerHTML=`<option value="">${n("team.allCli")}</option>`+e.map(a=>`<option value="${d(a)}">${d(a)}</option>`).join(""),t.value=o}async function L(e=y){let t=await E("/api/team/hosted");if(!f(e))return;let o=t.body;if(!o?.ok){z=[],h();return}q=o.deployment.deploymentId,I=o.suggestedHubUrl||"",c("tf-owner").textContent=o.deployment.ownerName||(o.deployment.ownerUnionId?n("team.bound"):n("team.unbound")),z=(o.teams||[]).map(a=>({kind:"local",key:`local:${a.teamId}`,teamId:a.teamId,label:a.isDefault?n("team.myHostedTeam"):a.name,sub:"",ok:!0,deployments:a.deployments||[],bots:a.bots||[]})),D(),h()}async function oe(e=y){let t=await E("/api/team/remote-roster");if(!f(e))return;U=(t.body?.memberships||[]).map(a=>{let r=a.roster?.deployments||[],s=r.find(l=>l.local),m=s?.name?n("team.remoteTeamLabel",{name:s.name}):a.teamName||a.teamId;return{kind:"remote",key:`${a.hubUrl}::${a.teamId}`,teamId:a.teamId,label:m,sub:a.hubUrl,ok:!!a.ok,error:a.error,hubUrl:a.hubUrl,deployments:r,bots:a.roster?.bots||[]}}),D(),h()}function O(e){let t=_(),o=[],a=(r,s,m)=>{r&&(r.addEventListener(s,m),o.push(()=>r.removeEventListener(s,m)))};return A.clear(),H.clear(),$.clear(),M.clear(),["tf-search","tf-cli","tf-fcap","tf-frole"].forEach(r=>{let s=document.getElementById(r);a(s,"input",()=>{f(t)&&h()}),a(s,"change",()=>{f(t)&&h()})}),a(document.getElementById("tf-modal-cancel"),"click",()=>{f(t)&&(c("tf-modal").style.display="none")}),se(t),L(t),oe(t),()=>{f(t)&&(y+=1);for(let s of o.splice(0))s();let r=e.querySelector("#tf-modal");r&&(r.style.display="none")}}async function j(e=y){let t=await E("/api/team/hosted");if(!f(e))return;let o=t.body,a=c("tm-list");I=o?.suggestedHubUrl||I;let r=o?.teams||[];if(!r.length){a.innerHTML=`<p class="muted">${n("team.noTeamsShort")}</p>`;return}a.innerHTML=r.map(s=>{let m=(s.deployments||[]).filter(l=>!l.local).length;return`<div class="card" style="margin:0 0 8px;padding:10px 14px;background:var(--bg-soft,#f6f7f9)">
1
+ import{b as w}from"./chunk-ECXPBQ3J.js";import"./chunk-76J7PNZI.js";import{m as n,n as d}from"./chunk-MR57RUVP.js";import{a as V,b as R,c as P}from"./chunk-JTSE5VP6.js";import{c as N}from"./chunk-7SZRL6FY.js";var k=N(V(),1);async function E(e){let t=await fetch(e);return{status:t.status,body:await t.json().catch(()=>({}))}}async function S(e,t,o){let a=await fetch(t,{method:e,headers:{"content-type":"application/json"},body:o?JSON.stringify(o):void 0});return{status:a.status,body:await a.json().catch(()=>({}))}}var x=(e,t)=>S("POST",e,t),X=(e,t)=>S("PUT",e,t),z=[],U=[],q="",I="",A=new Map,H=new Map,$=new Set,M=new Set,y=0;function _(){return y+=1,y}function f(e){return y===e}function c(e){return document.getElementById(e)}function B(){return[...z,...U]}function T(e){let t=A.get(e);return t||(t=new Set,A.set(e,t)),t}function Y(e){return B().find(t=>t.key===e)}function Z(e){let t=(c("tf-search").value||"").trim().toLowerCase();if(t&&!((e.name||"")+" "+(e.cliId||"")+" "+(e.capability||"")).toLowerCase().includes(t))return!1;let o=c("tf-cli").value;return!(o&&e.cliId!==o||c("tf-fcap").checked&&!e.capability||c("tf-frole").checked&&!e.hasTeamRole)}function ee(e,t){let o=[...e.deployments].sort((r,s)=>r.local===s.local?0:r.local?-1:1),a="";for(let r of o){let s=t.filter(p=>p.deployment.id===r.id);if(!s.length)continue;let m=r.id===q,l=m?n("team.tagLocal"):r.stale?n("team.tagRemoteStale"):n("team.tagRemote"),u=e.kind==="local"&&!m?` <button class="tf-rmmember ghost" data-team="${d(e.teamId)}" data-dep="${d(r.id)}" data-name="${d(r.name)}" style="font-size:12px">${n("team.removeMember")}</button>`:"",g=`${e.key}::${r.id}`,b=M.has(g),v=s.filter(p=>T(e.key).has(p.larkAppId)).length;if(a+=`<div class="tf-dep-h" data-dk="${d(g)}" style="cursor:pointer;margin:10px 0 2px"><b>${b?"\u25BE":"\u25B8"} ${d(r.name)}</b> <span class="muted" style="font-size:12px">${n("team.depTag",{tag:l})} \xB7 ${n("team.depCount",{count:s.length})}${v?n("team.depSelected",{n:v}):""}</span>${u}</div>`,!!b){a+='<table style="width:100%;border-collapse:collapse;font-size:14px"><tbody>';for(let p of s){let C=d(p.larkAppId),W=T(e.key).has(p.larkAppId)?" checked":"",K=p.deployment.stale?"opacity:.55":"",J=m?`<input class="tf-cap" data-app="${C}" value="${d(p.capability||"")}" placeholder="${n("team.capPh")}" style="width:92%;padding:3px 6px">`:p.capability?d(p.capability):'<span class="muted">\u2014</span>',Q=p.hasTeamRole?m?`<button class="tf-role" data-app="${C}" data-name="${d(p.name)}">${n("team.viewRole")}</button>`:n("team.hasRoleShort"):'<span class="muted">\u2014</span>';a+=`<tr style="${K}"><td style="padding:4px 8px"><input type="checkbox" class="tf-pick" data-tk="${d(e.key)}" data-app="${C}"${W}></td><td style="padding:4px 8px">${d(p.name)}</td><td style="padding:4px 8px" class="muted">${d(p.cliId)}</td><td style="padding:4px 8px">${J}</td><td style="padding:4px 8px">${Q}</td></tr>`}a+="</tbody></table>"}}return a||(a=`<p class="muted" style="margin:8px 0 0">${n("team.noMatch")}</p>`),a+=`<div style="margin-top:12px;display:flex;gap:8px;flex-wrap:wrap;align-items:center"><input class="tf-gname" data-tk="${d(e.key)}" value="${d(H.get(e.key)||"")}" placeholder="${n("team.gnamePh")}" style="min-width:200px"><button class="tf-grp primary" data-tk="${d(e.key)}">${n("team.pullGroupBtn")}</button><span class="muted" style="font-size:13px">${n("team.pullGroupHint")}</span><span class="tf-gout" data-tk="${d(e.key)}" style="font-size:13px;display:block;flex-basis:100%"></span></div>`,a}function h(){let e=c("tf-teams"),t=B();if(!t.length){e.innerHTML=`<p class="muted">${n("team.noTeams")}</p>`,c("tf-count").textContent="";return}let o="",a=new Set,r=new Set;for(let l of t){let u=l.bots.filter(Z);u.forEach(p=>a.add(p.larkAppId)),l.bots.forEach(p=>r.add(p.larkAppId));let g=new Set(u.map(p=>p.larkAppId));[...T(l.key)].forEach(p=>{g.has(p)||T(l.key).delete(p)});let b=!$.has(l.key),v=l.kind==="remote"?l.ok?` <span class="ok" style="font-size:12px">${n("team.connected")}</span>`:` <span class="err" style="font-size:12px">${n("team.connectFail",{error:d(l.error||"")})}</span>`:` <span class="muted" style="font-size:12px">${n("team.iHost")}</span>`;o+=`<div class="card" style="margin:0 0 12px;padding:12px 14px;background:var(--bg-soft,#f6f7f9)"><div class="tf-team-h" data-tk="${d(l.key)}" style="cursor:pointer;display:flex;align-items:center;gap:8px;flex-wrap:wrap"><b style="font-size:15px">${b?"\u25B8":"\u25BE"} ${d(l.label)}</b>`+(l.sub?` <span class="muted" style="font-size:12px">${d(l.sub)}</span>`:"")+v+` <span class="muted" style="font-size:12px">\xB7 ${n("team.teamMeta",{deps:l.deployments.length,bots:l.bots.length})}</span></div>`,b||(o+=l.kind==="remote"&&!l.ok?`<p class="muted" style="margin:8px 0 0">${n("team.rosterFail")}</p>`:ee(l,u)),o+="</div>"}e.innerHTML=o;let s=t.length>1?n("team.acrossTeams",{n:t.length}):"",m=a.size===r.size?`${r.size}`:`${a.size} / ${r.size}`;c("tf-count").textContent=`\xB7 ${m} ${n("team.botsWord")}${s}`,te(y)}function te(e=y){let t=c("tf-teams");t.querySelectorAll(".tf-team-h").forEach(o=>{o.onclick=()=>{let a=o.dataset.tk;$.has(a)?$.delete(a):$.add(a),h()}}),t.querySelectorAll(".tf-dep-h").forEach(o=>{o.onclick=()=>{let a=o.dataset.dk;M.has(a)?M.delete(a):M.add(a),h()}}),t.querySelectorAll(".tf-pick").forEach(o=>{o.onchange=()=>{let a=T(o.dataset.tk);o.checked?a.add(o.dataset.app):a.delete(o.dataset.app)}}),t.querySelectorAll(".tf-gname").forEach(o=>{o.oninput=()=>{H.set(o.dataset.tk,o.value)}}),t.querySelectorAll(".tf-cap").forEach(o=>{o.onchange=async()=>{let a=o.dataset.app,r=o.value;await X("/api/team/local-bots/"+encodeURIComponent(a)+"/capability",{capability:r}),f(e)&&B().forEach(s=>{let m=s.bots.find(l=>l.larkAppId===a);m&&(m.capability=r.trim()||null)})}}),t.querySelectorAll(".tf-role").forEach(o=>{o.onclick=()=>ne(o.dataset.app,o.dataset.name||"",e)}),t.querySelectorAll(".tf-rmmember").forEach(o=>{o.onclick=async a=>{a.stopPropagation(),confirm(n("team.removeMemberConfirm",{name:o.dataset.name||""}))&&(await S("DELETE",`/api/team/hosted/${encodeURIComponent(o.dataset.team)}/members/${encodeURIComponent(o.dataset.dep)}`),f(e)&&L(e))}}),t.querySelectorAll(".tf-grp").forEach(o=>{o.onclick=async()=>{let a=o.dataset.tk,r=Y(a);if(!r)return;let s=[...T(a)],m=t.querySelector(`.tf-gout[data-tk="${CSS.escape(a)}"]`);if(!s.length){m.innerHTML=`<span class="err">${n("team.errPickBot")}</span>`;return}let l=(t.querySelector(`.tf-gname[data-tk="${CSS.escape(a)}"]`)?.value||"").trim()||n("team.defaultGroupName");m.innerHTML=`<span class="muted">${n("team.creatingGroup")}</span>`;let u=r.kind==="local"?await x("/api/team/federated-group",{name:l,larkAppIds:s,teamId:r.teamId}):await x("/api/team/remote-group",{hubUrl:r.hubUrl,teamId:r.teamId,name:l,larkAppIds:s});if(f(e)&&(ae(m,u.body,u.status),u.body?.ok)){T(a).clear(),H.delete(a);let g=m.innerHTML,b=()=>{if(!f(e))return;let v=t.querySelector(`.tf-gout[data-tk="${CSS.escape(a)}"]`);v&&(v.innerHTML=g)};r.kind==="local"?L(e).then(b):(h(),b())}}})}function ae(e,t,o){if(t?.ok&&t.chatId){let a=t.shareLink||"https://applink.feishu.cn/client/chat/open?openChatId="+encodeURIComponent(t.chatId),r=(t.invalidBotIds||[]).length?` <span class="err"> \xB7 ${n("team.invalidBots",{ids:d((t.invalidBotIds||[]).join(", "))})}</span>`:"",s=(t.invalidOwnerUnionIds||[]).length?`<span class="err"> \xB7 ${n("team.invalidOwners",{n:(t.invalidOwnerUnionIds||[]).length})}</span>`:"",m=t.missingOperatorIdentity?`<span class="err"> \xB7 ${n("team.missingIdentity")}</span>`:"",l=(t.skippedNoOwner||[]).length?`<span class="err"> \xB7 ${n("team.skippedNoOwner",{n:(t.skippedNoOwner||[]).length})}</span>`:"",u=t.delegatedTo?n("team.delegatedBy",{name:d(t.delegatedTo)}):"";e.innerHTML=`<span class="ok">${n("team.groupCreated")}</span>${u} \xB7 <a href="${d(a)}" target="_blank">${n("team.openInLark")}</a>${r}${s}${m}${l}`}else{let a=t?.error||o,r=a==="no_local_online_bot"?n("team.errNoLocalBot"):a==="all_bots_skipped_no_owner"?n("team.errAllSkipped"):a==="no_creator_available"?n("team.errNoCreator"):a==="delegation_timeout"?n("team.errDelegationTimeout"):n("team.errGroupCreate",{error:String(a)});e.innerHTML=`<span class="err">${d(String(r))}</span>`}}async function ne(e,t,o=y){let a=await E("/api/team/local-bots/"+encodeURIComponent(e)+"/role");f(o)&&(c("tf-modal-title").textContent=n("team.roleModalTitleName",{name:t}),c("tf-modal-text").value=a.body?.role||"",c("tf-modal").dataset.app=e,c("tf-modal").style.display="flex")}function D(){let e=Array.from(new Set(B().flatMap(a=>a.bots.map(r=>r.cliId)).filter(Boolean))).sort(),t=c("tf-cli"),o=t.value;t.innerHTML=`<option value="">${n("team.allCli")}</option>`+e.map(a=>`<option value="${d(a)}">${d(a)}</option>`).join(""),t.value=o}async function L(e=y){let t=await E("/api/team/hosted");if(!f(e))return;let o=t.body;if(!o?.ok){z=[],h();return}q=o.deployment.deploymentId,I=o.suggestedHubUrl||"",c("tf-owner").textContent=o.deployment.ownerName||(o.deployment.ownerUnionId?n("team.bound"):n("team.unbound")),z=(o.teams||[]).map(a=>({kind:"local",key:`local:${a.teamId}`,teamId:a.teamId,label:a.isDefault?n("team.myHostedTeam"):a.name,sub:"",ok:!0,deployments:a.deployments||[],bots:a.bots||[]})),D(),h()}async function oe(e=y){let t=await E("/api/team/remote-roster");if(!f(e))return;U=(t.body?.memberships||[]).map(a=>{let r=a.roster?.deployments||[],s=r.find(l=>l.local),m=s?.name?n("team.remoteTeamLabel",{name:s.name}):a.teamName||a.teamId;return{kind:"remote",key:`${a.hubUrl}::${a.teamId}`,teamId:a.teamId,label:m,sub:a.hubUrl,ok:!!a.ok,error:a.error,hubUrl:a.hubUrl,deployments:r,bots:a.roster?.bots||[]}}),D(),h()}function O(e){let t=_(),o=[],a=(r,s,m)=>{r&&(r.addEventListener(s,m),o.push(()=>r.removeEventListener(s,m)))};return A.clear(),H.clear(),$.clear(),M.clear(),["tf-search","tf-cli","tf-fcap","tf-frole"].forEach(r=>{let s=document.getElementById(r);a(s,"input",()=>{f(t)&&h()}),a(s,"change",()=>{f(t)&&h()})}),a(document.getElementById("tf-modal-cancel"),"click",()=>{f(t)&&(c("tf-modal").style.display="none")}),se(t),L(t),oe(t),()=>{f(t)&&(y+=1);for(let s of o.splice(0))s();let r=e.querySelector("#tf-modal");r&&(r.style.display="none")}}async function j(e=y){let t=await E("/api/team/hosted");if(!f(e))return;let o=t.body,a=c("tm-list");I=o?.suggestedHubUrl||I;let r=o?.teams||[];if(!r.length){a.innerHTML=`<p class="muted">${n("team.noTeamsShort")}</p>`;return}a.innerHTML=r.map(s=>{let m=(s.deployments||[]).filter(l=>!l.local).length;return`<div class="card" style="margin:0 0 8px;padding:10px 14px;background:var(--bg-soft,#f6f7f9)">
2
2
  <div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
3
3
  <b>${d(s.name)}</b>${s.isDefault?` <span class="muted" style="font-size:12px">${n("team.default")}</span>`:""}
4
4
  <span class="muted" style="font-size:12px">\xB7 ${n("team.manageMetaDeps",{count:(s.deployments||[]).length})}${m?n("team.manageMetaRemote",{r:m}):""} \xB7 ${n("team.manageMetaBots",{count:(s.bots||[]).length})}</span>
@@ -1,4 +1,4 @@
1
- import{m as i}from"./chunk-JXLHRRJD.js";import"./chunk-7SZRL6FY.js";function Rt(){let t=[["",i("workflow.filter.nonTerminal")],["all",i("workflow.filter.all")],["pending",C("pending")],["running",C("running")],["waiting",C("waiting")],["succeeded",C("succeeded")],["failed",C("failed")],["cancelled",C("cancelled")]];return`
1
+ import{m as i}from"./chunk-MR57RUVP.js";import"./chunk-7SZRL6FY.js";function Rt(){let t=[["",i("workflow.filter.nonTerminal")],["all",i("workflow.filter.all")],["pending",C("pending")],["running",C("running")],["waiting",C("waiting")],["succeeded",C("succeeded")],["failed",C("failed")],["cancelled",C("cancelled")]];return`
2
2
  <nav class="wf-subnav">
3
3
  <a href="#/legacy-workflow" class="active" data-i18n="workflow.subnav.runs">${r(i("workflow.subnav.runs"))}</a>
4
4
  <a href="#/workflows" data-i18n="workflow.subnav.v3">${r(i("workflow.subnav.v3"))}</a>