botmux 2.102.0 → 2.103.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 (45) hide show
  1. package/dist/cli.d.ts +9 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +141 -6
  4. package/dist/cli.js.map +1 -1
  5. package/dist/dashboard/bot-onboarding.d.ts +28 -0
  6. package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
  7. package/dist/dashboard/bot-onboarding.js +20 -0
  8. package/dist/dashboard/bot-onboarding.js.map +1 -1
  9. package/dist/dashboard/feishu-login.d.ts +64 -0
  10. package/dist/dashboard/feishu-login.d.ts.map +1 -0
  11. package/dist/dashboard/feishu-login.js +99 -0
  12. package/dist/dashboard/feishu-login.js.map +1 -0
  13. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  14. package/dist/dashboard/web/bot-defaults.js +108 -0
  15. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  16. package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
  17. package/dist/dashboard/web/bot-onboarding.js +4 -1
  18. package/dist/dashboard/web/bot-onboarding.js.map +1 -1
  19. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  20. package/dist/dashboard/web/i18n.js +22 -2
  21. package/dist/dashboard/web/i18n.js.map +1 -1
  22. package/dist/dashboard-web/app.js +6 -6
  23. package/dist/dashboard-web/chunks/bot-defaults-page-ZVBKVYIG.js +380 -0
  24. package/dist/dashboard-web/chunks/{chunk-DWFMPIAQ.js → chunk-HC7ANVX7.js} +5 -5
  25. package/dist/dashboard-web/chunks/{chunk-NC77G2OB.js → chunk-NNXPEJ7S.js} +1 -1
  26. package/dist/dashboard-web/chunks/{connectors-BW6WO7P5.js → connectors-POZADN75.js} +1 -1
  27. package/dist/dashboard-web/chunks/{groups-page-UTXUVV2M.js → groups-page-UQFQ6DRE.js} +1 -1
  28. package/dist/dashboard-web/chunks/{insights-page-IW3KNMG4.js → insights-page-ATW2W5KP.js} +1 -1
  29. package/dist/dashboard-web/chunks/{overview-page-RO6R26AZ.js → overview-page-Z7OV54XU.js} +1 -1
  30. package/dist/dashboard-web/chunks/{roles-page-5DYKR2I5.js → roles-page-4BJVXK2E.js} +1 -1
  31. package/dist/dashboard-web/chunks/{schedules-WUZP3UPF.js → schedules-XLETZ2EP.js} +1 -1
  32. package/dist/dashboard-web/chunks/{sessions-page-GWZ4GKSG.js → sessions-page-RMMQUGXJ.js} +1 -1
  33. package/dist/dashboard-web/chunks/{settings-page-HJH6HQ7D.js → settings-page-PWKI4TWF.js} +1 -1
  34. package/dist/dashboard-web/chunks/{skills-page-ATVGKR5I.js → skills-page-SH7KUD45.js} +1 -1
  35. package/dist/dashboard-web/chunks/{team-federation-page-JVC73TTF.js → team-federation-page-JAJXFLXA.js} +1 -1
  36. package/dist/dashboard-web/chunks/{workflows-YCZTOJUS.js → workflows-FRJ2DJAO.js} +1 -1
  37. package/dist/dashboard-web/style.css +57 -0
  38. package/dist/dashboard.js +78 -2
  39. package/dist/dashboard.js.map +1 -1
  40. package/dist/utils/bot-routing.d.ts +26 -3
  41. package/dist/utils/bot-routing.d.ts.map +1 -1
  42. package/dist/utils/bot-routing.js +38 -4
  43. package/dist/utils/bot-routing.js.map +1 -1
  44. package/package.json +1 -1
  45. package/dist/dashboard-web/chunks/bot-defaults-page-YAHNXFBC.js +0 -370
@@ -1,4 +1,4 @@
1
- import{b as jt}from"./chunk-NC77G2OB.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-DWFMPIAQ.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">
1
+ import{b as jt}from"./chunk-NNXPEJ7S.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-HC7ANVX7.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
2
  <summary>${i("sessions.cli")} \xB7 <b id="cli-filter-count">${i("common.all")}</b></summary>
3
3
  <div class="filter-cli-pop" role="group" aria-label="${i("sessions.cli")}">
4
4
  ${nn.map(a=>`
@@ -1,2 +1,2 @@
1
- import{b as k}from"./chunk-NC77G2OB.js";import"./chunk-76J7PNZI.js";import"./chunk-DWFMPIAQ.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-NNXPEJ7S.js";import"./chunk-76J7PNZI.js";import"./chunk-HC7ANVX7.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-NC77G2OB.js";import"./chunk-76J7PNZI.js";import{p as W,w as ms}from"./chunk-DWFMPIAQ.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-NNXPEJ7S.js";import"./chunk-76J7PNZI.js";import{p as W,w as ms}from"./chunk-HC7ANVX7.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-NC77G2OB.js";import"./chunk-76J7PNZI.js";import{m as n,n as d}from"./chunk-DWFMPIAQ.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-NNXPEJ7S.js";import"./chunk-76J7PNZI.js";import{m as n,n as d}from"./chunk-HC7ANVX7.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-DWFMPIAQ.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-HC7ANVX7.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>
@@ -4329,6 +4329,63 @@ button.contrast:hover { background: var(--danger-soft); border-color: var(--dang
4329
4329
  .bd-name-editor button { padding: 4px 12px; font-size: 12px; }
4330
4330
  .bd-name-status { display: block; margin-top: 4px; font-size: 11.5px; }
4331
4331
  .bd-name-status:empty { display: none; }
4332
+ /* 「扫码登录飞书」——改名因缺登录态降级时才亮出 */
4333
+ .bd-feishu-login {
4334
+ display: inline-block;
4335
+ margin-top: 6px;
4336
+ padding: 4px 12px;
4337
+ font-size: 12px;
4338
+ font-weight: 600;
4339
+ border-radius: 8px;
4340
+ border: 1px solid var(--accent);
4341
+ background: color-mix(in srgb, var(--accent) 10%, transparent);
4342
+ color: var(--accent);
4343
+ cursor: pointer;
4344
+ }
4345
+ .bd-feishu-login:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); }
4346
+ .bd-feishu-login[hidden] { display: none; }
4347
+
4348
+ /* 飞书扫码登录 modal */
4349
+ .feishu-login-overlay {
4350
+ position: fixed;
4351
+ inset: 0;
4352
+ z-index: 100001;
4353
+ display: flex;
4354
+ align-items: center;
4355
+ justify-content: center;
4356
+ padding: 20px;
4357
+ background: rgba(0, 0, 0, 0.55);
4358
+ backdrop-filter: blur(3px);
4359
+ }
4360
+ .feishu-login-modal {
4361
+ position: relative;
4362
+ width: min(360px, 92vw);
4363
+ padding: 24px 24px 20px;
4364
+ border-radius: 16px;
4365
+ border: 1px solid var(--border-soft);
4366
+ background: var(--surface);
4367
+ box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35);
4368
+ text-align: center;
4369
+ }
4370
+ .feishu-login-close {
4371
+ position: absolute;
4372
+ top: 12px;
4373
+ right: 12px;
4374
+ width: 28px;
4375
+ height: 28px;
4376
+ padding: 0;
4377
+ border: none;
4378
+ border-radius: 8px;
4379
+ background: transparent;
4380
+ color: var(--faint);
4381
+ font-size: 15px;
4382
+ cursor: pointer;
4383
+ }
4384
+ .feishu-login-close:hover { background: color-mix(in srgb, var(--faint) 18%, transparent); color: inherit; }
4385
+ .feishu-login-title { margin: 0 0 8px; font-size: 16px; }
4386
+ .feishu-login-hint { margin: 0 0 14px; font-size: 12.5px; color: var(--faint); line-height: 1.5; }
4387
+ .feishu-login-qr { min-height: 40px; display: flex; justify-content: center; }
4388
+ .feishu-login-actions { margin-top: 14px; }
4332
4389
  .bd-profile-meta {
4333
4390
  margin: 0 0 0 auto;
4334
4391
  display: grid;
package/dist/dashboard.js CHANGED
@@ -26,12 +26,13 @@ import { handleFederationApi } from './dashboard/federation-api.js';
26
26
  import { handleFederationSpokeApi, syncAllMemberships, autoBindOwnerIfUnambiguous } from './dashboard/federation-spoke-api.js';
27
27
  import { getRunsDir } from './workflows/runs-dir.js';
28
28
  import { BotOnboardingManager } from './dashboard/bot-onboarding.js';
29
+ import { FeishuLoginManager } from './dashboard/feishu-login.js';
29
30
  import { CLI_SELECT_OPTIONS, resolveCliSelection, isTtadkWrapper, ttadkAcceptsModel, TTADK_DEFAULT_MODEL, TTADK_MODEL_SUGGESTIONS, } from './setup/cli-selection.js';
30
31
  import { invalidWorkingDirs } from './utils/working-dir.js';
31
32
  import { invalidateGlobalConfigCache, mergeGlobalConfig, readGlobalConfig } from './global-config.js';
32
33
  import { buildDashboardUrl } from './core/dashboard-url.js';
33
34
  import { deleteWhiteboard, listWhiteboards, readWhiteboard, whiteboardEnabled } from './services/whiteboard-store.js';
34
- import { isLocalDevInstall, botmuxVersion } from './utils/install-info.js';
35
+ import { isLocalDevInstall, botmuxVersion, botmuxCliEntry } from './utils/install-info.js';
35
36
  import { checkNode, detectBotmuxInstalls, resolveCurrentVersion } from './utils/install-diagnostics.js';
36
37
  import { fetchLatestVersion, fetchReleasesSince, isNewerVersion } from './core/update-check.js';
37
38
  import { GITHUB_REPO } from './core/restart-report.js';
@@ -168,7 +169,73 @@ function signDaemonTokenHeaders() {
168
169
  mkdirSync(REGISTRY_DIR, { recursive: true });
169
170
  const registry = new DaemonRegistry(REGISTRY_DIR);
170
171
  const aggregator = new Aggregator();
171
- const botOnboarding = new BotOnboardingManager({ botsJsonPath: BOTS_JSON_PATH });
172
+ /**
173
+ * Bring a freshly-onboarded bot online without a fleet-wide restart by spawning
174
+ * `botmux start-bot <appId> --json` (see cli.ts:ensureBotDaemonStarted). The new
175
+ * daemon is forked+supervised by pm2 (reparented off this process), self-registers
176
+ * and opens its Feishu WSClient, then publishes a descriptor the DaemonRegistry
177
+ * auto-discovers — so no dashboard reload is needed either. Runs `botmux` on the
178
+ * SAME host as the dashboard (shared pm2 home / bots.json — the documented
179
+ * dashboard↔daemon co-location assumption). Resolves best-effort; the caller
180
+ * falls back to the restart hint on failure.
181
+ */
182
+ function spawnStartBotLive(appId) {
183
+ return new Promise((resolve) => {
184
+ let out = '';
185
+ let err = '';
186
+ let settled = false;
187
+ const done = (r) => { if (!settled) {
188
+ settled = true;
189
+ resolve(r);
190
+ } };
191
+ try {
192
+ const child = spawn(process.execPath, [botmuxCliEntry(), 'start-bot', appId, '--json'], {
193
+ stdio: ['ignore', 'pipe', 'pipe'],
194
+ env: process.env,
195
+ });
196
+ const timer = setTimeout(() => {
197
+ try {
198
+ child.kill('SIGKILL');
199
+ }
200
+ catch { /* already gone */ }
201
+ done({ ok: false, message: 'start-bot 超时(30s)' });
202
+ }, 30_000);
203
+ timer.unref?.();
204
+ child.stdout?.on('data', (d) => { out += String(d); });
205
+ child.stderr?.on('data', (d) => { err += String(d); });
206
+ child.on('error', (e) => {
207
+ clearTimeout(timer);
208
+ done({ ok: false, message: e instanceof Error ? e.message : String(e) });
209
+ });
210
+ child.on('exit', (code) => {
211
+ clearTimeout(timer);
212
+ // `start-bot --json` prints a single StartBotLiveResult object; prefer its
213
+ // own message/processName over the raw exit code.
214
+ let parsed;
215
+ try {
216
+ parsed = JSON.parse(out.trim());
217
+ }
218
+ catch { /* non-JSON → fall through */ }
219
+ if (code === 0) {
220
+ done({ ok: true, message: parsed?.processName ? `${parsed.processName} 已上线` : undefined });
221
+ }
222
+ else {
223
+ done({ ok: false, message: parsed?.message || err.trim() || `start-bot 退出码 ${code}` });
224
+ }
225
+ });
226
+ }
227
+ catch (e) {
228
+ done({ ok: false, message: e instanceof Error ? e.message : String(e) });
229
+ }
230
+ });
231
+ }
232
+ const botOnboarding = new BotOnboardingManager({
233
+ botsJsonPath: BOTS_JSON_PATH,
234
+ startBotLive: spawnStartBotLive,
235
+ });
236
+ // 飞书 Web 登录态刷新(机器人改名缺登录态时的 dashboard 扫码入口)。机器级单例,
237
+ // 写 ~/.botmux/feishu-session.json,与 setup / onboarding 复用同一份登录态。
238
+ const feishuLogin = new FeishuLoginManager();
172
239
  const subs = new Map();
173
240
  const attaching = new Set(); // dedup concurrent attaches per appId
174
241
  function resolveDashboardSettings() {
@@ -1521,6 +1588,15 @@ const server = createServer(async (req, res) => {
1521
1588
  return jsonRes(res, 404, { ok: false, error: 'unknown_onboarding_job' });
1522
1589
  return jsonRes(res, 200, { job });
1523
1590
  }
1591
+ // 飞书 Web 登录态刷新(改名缺登录态 → dashboard 扫码)。POST 受 dashboard 的
1592
+ // 写操作 auth 闸保护(非 GET 需 owner cookie);GET 仅暴露二维码+状态,扫码
1593
+ // 授权的是扫码人自己的账号,风险模型与 onboarding 第二个二维码一致。
1594
+ if (req.method === 'POST' && url.pathname === '/api/feishu-login/start') {
1595
+ return jsonRes(res, 202, { login: feishuLogin.start() });
1596
+ }
1597
+ if (req.method === 'GET' && url.pathname === '/api/feishu-login/status') {
1598
+ return jsonRes(res, 200, { login: feishuLogin.get() });
1599
+ }
1524
1600
  let m;
1525
1601
  if (req.method === 'POST' && (m = url.pathname.match(/^\/api\/sessions\/([^/]+)\/(close|locate|resume|restart|start)$/))) {
1526
1602
  const sid = decodeURIComponent(m[1]);