botmux 2.98.4-canary.2 → 2.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/dist/adapters/cli/genius.d.ts +4 -0
- package/dist/adapters/cli/genius.d.ts.map +1 -0
- package/dist/adapters/cli/genius.js +216 -0
- package/dist/adapters/cli/genius.js.map +1 -0
- package/dist/adapters/cli/registry.d.ts +2 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +3 -1
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +1 -1
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/core/dashboard-rows.d.ts +1 -1
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +2 -1
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/dashboard/session-card-model.d.ts +2 -2
- package/dist/dashboard/session-card-model.d.ts.map +1 -1
- package/dist/dashboard/session-card-model.js +5 -2
- package/dist/dashboard/session-card-model.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +28 -63
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +3 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -0
- package/dist/dashboard/web/bot-defaults-page.js +23 -0
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -0
- package/dist/dashboard/web/bot-defaults.d.ts +2 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +30 -30
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/connectors-page.d.ts +14 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -0
- package/dist/dashboard/web/connectors-page.js +303 -0
- package/dist/dashboard/web/connectors-page.js.map +1 -0
- package/dist/dashboard/web/connectors.d.ts +1 -12
- package/dist/dashboard/web/connectors.d.ts.map +1 -1
- package/dist/dashboard/web/connectors.js +1 -325
- package/dist/dashboard/web/connectors.js.map +1 -1
- package/dist/dashboard/web/dashboard-routes.d.ts +14 -0
- package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -0
- package/dist/dashboard/web/dashboard-routes.js +176 -0
- package/dist/dashboard/web/dashboard-routes.js.map +1 -0
- package/dist/dashboard/web/groups-page.d.ts +3 -0
- package/dist/dashboard/web/groups-page.d.ts.map +1 -0
- package/dist/dashboard/web/groups-page.js +26 -0
- package/dist/dashboard/web/groups-page.js.map +1 -0
- package/dist/dashboard/web/groups.d.ts +1 -1
- package/dist/dashboard/web/groups.d.ts.map +1 -1
- package/dist/dashboard/web/groups.js +113 -52
- package/dist/dashboard/web/groups.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +18 -0
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/insights-page.d.ts +3 -0
- package/dist/dashboard/web/insights-page.d.ts.map +1 -0
- package/dist/dashboard/web/insights-page.js +26 -0
- package/dist/dashboard/web/insights-page.js.map +1 -0
- package/dist/dashboard/web/insights.d.ts +18 -1
- package/dist/dashboard/web/insights.d.ts.map +1 -1
- package/dist/dashboard/web/insights.js +25 -61
- package/dist/dashboard/web/insights.js.map +1 -1
- package/dist/dashboard/web/office-page.d.ts +3 -0
- package/dist/dashboard/web/office-page.d.ts.map +1 -0
- package/dist/dashboard/web/office-page.js +149 -0
- package/dist/dashboard/web/office-page.js.map +1 -0
- package/dist/dashboard/web/office.d.ts +1 -1
- package/dist/dashboard/web/office.d.ts.map +1 -1
- package/dist/dashboard/web/office.js +1 -139
- package/dist/dashboard/web/office.js.map +1 -1
- package/dist/dashboard/web/overview-page.d.ts +3 -0
- package/dist/dashboard/web/overview-page.d.ts.map +1 -0
- package/dist/dashboard/web/overview-page.js +149 -0
- package/dist/dashboard/web/overview-page.js.map +1 -0
- package/dist/dashboard/web/overview.d.ts +2 -2
- package/dist/dashboard/web/overview.d.ts.map +1 -1
- package/dist/dashboard/web/overview.js +14 -3
- package/dist/dashboard/web/overview.js.map +1 -1
- package/dist/dashboard/web/react-hooks.d.ts +8 -0
- package/dist/dashboard/web/react-hooks.d.ts.map +1 -0
- package/dist/dashboard/web/react-hooks.js +43 -0
- package/dist/dashboard/web/react-hooks.js.map +1 -0
- package/dist/dashboard/web/react-mount.d.ts +4 -0
- package/dist/dashboard/web/react-mount.d.ts.map +1 -0
- package/dist/dashboard/web/react-mount.js +7 -0
- package/dist/dashboard/web/react-mount.js.map +1 -0
- package/dist/dashboard/web/roles-page.d.ts +4 -0
- package/dist/dashboard/web/roles-page.d.ts.map +1 -0
- package/dist/dashboard/web/roles-page.js +26 -0
- package/dist/dashboard/web/roles-page.js.map +1 -0
- package/dist/dashboard/web/roles.d.ts +1 -2
- package/dist/dashboard/web/roles.d.ts.map +1 -1
- package/dist/dashboard/web/roles.js +189 -135
- package/dist/dashboard/web/roles.js.map +1 -1
- package/dist/dashboard/web/route-lifecycle.d.ts +14 -0
- package/dist/dashboard/web/route-lifecycle.d.ts.map +1 -0
- package/dist/dashboard/web/route-lifecycle.js +29 -0
- package/dist/dashboard/web/route-lifecycle.js.map +1 -0
- package/dist/dashboard/web/schedules-page.d.ts +14 -0
- package/dist/dashboard/web/schedules-page.d.ts.map +1 -0
- package/dist/dashboard/web/schedules-page.js +84 -0
- package/dist/dashboard/web/schedules-page.js.map +1 -0
- package/dist/dashboard/web/schedules.d.ts +1 -1
- package/dist/dashboard/web/schedules.d.ts.map +1 -1
- package/dist/dashboard/web/schedules.js +1 -115
- package/dist/dashboard/web/schedules.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts +3 -0
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -0
- package/dist/dashboard/web/sessions-page.js +28 -0
- package/dist/dashboard/web/sessions-page.js.map +1 -0
- package/dist/dashboard/web/sessions.d.ts +4 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +43 -10
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +3 -0
- package/dist/dashboard/web/settings-page.d.ts.map +1 -0
- package/dist/dashboard/web/settings-page.js +387 -0
- package/dist/dashboard/web/settings-page.js.map +1 -0
- package/dist/dashboard/web/settings.d.ts +1 -1
- package/dist/dashboard/web/settings.d.ts.map +1 -1
- package/dist/dashboard/web/settings.js +1 -534
- package/dist/dashboard/web/settings.js.map +1 -1
- package/dist/dashboard/web/skills-page.d.ts +33 -0
- package/dist/dashboard/web/skills-page.d.ts.map +1 -0
- package/dist/dashboard/web/skills-page.js +515 -0
- package/dist/dashboard/web/skills-page.js.map +1 -0
- package/dist/dashboard/web/skills.d.ts +1 -1
- package/dist/dashboard/web/skills.d.ts.map +1 -1
- package/dist/dashboard/web/skills.js +1 -711
- package/dist/dashboard/web/skills.js.map +1 -1
- package/dist/dashboard/web/store.d.ts +9 -0
- package/dist/dashboard/web/store.d.ts.map +1 -1
- package/dist/dashboard/web/store.js +19 -2
- package/dist/dashboard/web/store.js.map +1 -1
- package/dist/dashboard/web/team-federation-page.d.ts +4 -0
- package/dist/dashboard/web/team-federation-page.d.ts.map +1 -0
- package/dist/dashboard/web/team-federation-page.js +47 -0
- package/dist/dashboard/web/team-federation-page.js.map +1 -0
- package/dist/dashboard/web/team-federation.d.ts +2 -2
- package/dist/dashboard/web/team-federation.d.ts.map +1 -1
- package/dist/dashboard/web/team-federation.js +104 -97
- package/dist/dashboard/web/team-federation.js.map +1 -1
- package/dist/dashboard/web/v3-page.d.ts +3 -0
- package/dist/dashboard/web/v3-page.d.ts.map +1 -0
- package/dist/dashboard/web/v3-page.js +27 -0
- package/dist/dashboard/web/v3-page.js.map +1 -0
- package/dist/dashboard/web/v3.d.ts +2 -1
- package/dist/dashboard/web/v3.d.ts.map +1 -1
- package/dist/dashboard/web/v3.js +18 -43
- package/dist/dashboard/web/v3.js.map +1 -1
- package/dist/dashboard/web/whiteboards-page.d.ts +3 -0
- package/dist/dashboard/web/whiteboards-page.d.ts.map +1 -0
- package/dist/dashboard/web/whiteboards-page.js +203 -0
- package/dist/dashboard/web/whiteboards-page.js.map +1 -0
- package/dist/dashboard/web/whiteboards.d.ts +1 -1
- package/dist/dashboard/web/whiteboards.d.ts.map +1 -1
- package/dist/dashboard/web/whiteboards.js +1 -275
- package/dist/dashboard/web/whiteboards.js.map +1 -1
- package/dist/dashboard-web/app.js +36 -2550
- package/dist/dashboard-web/chunks/bot-defaults-page-3EV7K6LJ.js +358 -0
- package/dist/dashboard-web/chunks/chunk-5E3MJJL4.js +1 -0
- package/dist/dashboard-web/chunks/chunk-76J7PNZI.js +1 -0
- package/dist/dashboard-web/chunks/chunk-7SZRL6FY.js +1 -0
- package/dist/dashboard-web/chunks/chunk-JTSE5VP6.js +54 -0
- package/dist/dashboard-web/chunks/chunk-JXLHRRJD.js +31 -0
- package/dist/dashboard-web/chunks/chunk-NASYW5FD.js +1 -0
- package/dist/dashboard-web/chunks/connectors-XPZKEHF6.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-C54PVKYP.js +207 -0
- package/dist/dashboard-web/chunks/insights-page-BBQYR7WY.js +309 -0
- package/dist/dashboard-web/chunks/office-page-6DXYOG55.js +1 -0
- package/dist/dashboard-web/chunks/overview-page-5PJCAMID.js +1 -0
- package/dist/dashboard-web/chunks/roles-page-APUDLPVM.js +98 -0
- package/dist/dashboard-web/chunks/schedules-WG2UKHSO.js +1 -0
- package/dist/dashboard-web/chunks/sessions-page-F3U5NFPD.js +238 -0
- package/dist/dashboard-web/chunks/settings-page-OSBZNCXL.js +2 -0
- package/dist/dashboard-web/chunks/skills-page-Y3VUAOYG.js +2 -0
- package/dist/dashboard-web/chunks/team-federation-page-CRH3WZPH.js +10 -0
- package/dist/dashboard-web/chunks/v3-page-FVPUL665.js +149 -0
- package/dist/dashboard-web/chunks/whiteboards-page-HLCTYSSV.js +1 -0
- package/dist/dashboard-web/chunks/workflows-UB7OPYGI.js +184 -0
- package/dist/dashboard-web/index.html +1 -1
- package/dist/dashboard-web/style.css +82 -1
- package/dist/dashboard.js +5 -6
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +1 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +1 -0
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +7 -0
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/sessions-card.d.ts.map +1 -1
- package/dist/im/lark/sessions-card.js +4 -1
- package/dist/im/lark/sessions-card.js.map +1 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +16 -14
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/package.json +8 -2
|
@@ -1,2572 +1,58 @@
|
|
|
1
|
-
"use strict";(()=>{var xd=Object.defineProperty;var no=(e,t)=>{for(var n in t)xd(e,n,{get:t[n],enumerable:!0})};var da=class{sessions=new Map;schedules=new Map;online=!0;listeners=new Set;upsertSessions(t){for(let n of t)this.sessions.set(n.sessionId,n);this.emit()}upsertSchedules(t){for(let n of t)this.schedules.set(n.id,n);this.emit()}applySse(t,n){if(t==="session.spawned")this.sessions.set(n.session.sessionId,n.session);else if(t==="session.update"){let a=this.sessions.get(n.sessionId);a&&this.sessions.set(n.sessionId,{...a,...n.patch})}else if(t==="session.exited"){let a=this.sessions.get(n.sessionId);a&&this.sessions.set(n.sessionId,{...a,status:"closed"})}else if(t==="schedule.created")this.schedules.set(n.schedule.id,n.schedule);else if(t==="schedule.updated"){let a=this.schedules.get(n.id);a&&this.schedules.set(n.id,{...a,...n.patch})}else if(t==="schedule.deleted")this.schedules.delete(n.id);else return;this.emit()}setOnline(t){this.online!==t&&(this.online=t,this.emit())}on(t){return this.listeners.add(t),()=>this.listeners.delete(t)}emit(){for(let t of this.listeners)t()}},ke=new da;async function Hr(){let[e,t]=await Promise.all([fetch("/api/sessions").then(o=>o.json()),fetch("/api/schedules").then(o=>o.json())]);ke.upsertSessions(e.sessions??[]),ke.upsertSchedules(t.schedules??[]);let n=new EventSource("/events"),a=["session.spawned","session.update","session.exited","schedule.created","schedule.updated","schedule.deleted","schedule.fired","heartbeat"];for(let o of a)n.addEventListener(o,i=>{try{let r=JSON.parse(i.data);ke.applySse(o,r.body??r)}catch{}});n.onerror=()=>ke.setOnline(!1),n.onopen=()=>ke.setOnline(!0)}var pa="botmux.dashboard.locale",Sd={"app.name":"botmux","app.subtitle":"\u98DE\u4E66 AI CLI \u63A7\u5236\u53F0","time.secondsAgo":"{value} \u79D2\u524D","time.minutesAgo":"{value} \u5206\u949F\u524D","time.hoursAgo":"{value} \u5C0F\u65F6\u524D","nav.overview":"\u603B\u89C8","nav.sessions":"\u4F1A\u8BDD","nav.sidebarCollapse":"\u6536\u8D77\u83DC\u5355\u680F","nav.sidebarExpand":"\u5C55\u5F00\u83DC\u5355\u680F","nav.groups":"\u7FA4\u7EC4","nav.schedules":"\u5B9A\u65F6","nav.settings":"\u8BBE\u7F6E","nav.botDefaults":"Bot \u914D\u7F6E","nav.skills":"Skills","status.live":"\u5B9E\u65F6\u8FDE\u63A5","status.disconnected":"\u8FDE\u63A5\u65AD\u5F00","status.system":"\u7CFB\u7EDF","status.light":"\u6D45\u8272","status.dark":"\u6697\u9ED1","status.language":"\u8BED\u8A00","status.theme":"\u4E3B\u9898","theme.base":"\u57FA\u7840","theme.skins":"\u4E3B\u9898\u76AE\u80A4","skin.cyber":"2077","skin.genshin":"\u539F\u795E","skin.fallout":"Fallout","skin.prts":"PRTS","skin.bluearchive":"\u851A\u84DD\u6863\u6848","skin.zzz":"\u7EDD\u533A\u96F6","skin.dragonball":"\u4E03\u9F99\u73E0","skin.ikun":"ikun","botOnboarding.add":"\u6DFB\u52A0\u673A\u5668\u4EBA","botOnboarding.title":"\u6DFB\u52A0\u673A\u5668\u4EBA","botOnboarding.intro":"\u9009\u62E9 CLI \u4E0E\u5DE5\u4F5C\u76EE\u5F55\uFF0C\u626B\u7801\u521B\u5EFA PersonalAgent \u5E94\u7528\u540E\u5199\u5165\u672C\u673A bots.json\uFF0C\u5E76\u81EA\u52A8\u914D\u7F6E\u5F00\u653E\u5E73\u53F0\u6743\u9650\u3002","botOnboarding.cliLabel":"CLI \u9002\u914D\u5668","botOnboarding.dirLabel":"\u5DE5\u4F5C\u76EE\u5F55","botOnboarding.dirPlaceholder":"\u9ED8\u8BA4 ~\uFF08\u5BB6\u76EE\u5F55\uFF09\uFF0C\u9700\u4E3A daemon \u4E3B\u673A\u4E0A\u5DF2\u5B58\u5728\u7684\u76EE\u5F55","botOnboarding.modelLabel":"\u6A21\u578B\uFF08\u53EF\u9009\uFF09","botOnboarding.modelPlaceholder":"\u7559\u7A7A\u4F7F\u7528\u8BE5 CLI \u7684\u9ED8\u8BA4\u6A21\u578B","botOnboarding.modelTtadkPlaceholder":"ttadk \u7F51\u5173\u6A21\u578B\uFF0C\u9ED8\u8BA4 {model}\uFF0C\u53EF\u6539\uFF08\u968F\u65F6\u5728\u6B64\u8C03\u6574\uFF09","botOnboarding.modelTtadkCocoPlaceholder":"CoCo \u65E0\u9700\u6307\u5B9A\u6A21\u578B","botOnboarding.startScan":"\u5F00\u59CB\u626B\u7801","botOnboarding.cancel":"\u53D6\u6D88","botOnboarding.starting":"\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801...","botOnboarding.waiting":"\u8BF7\u7528\u98DE\u4E66 App \u626B\u7801\u786E\u8BA4\u521B\u5EFA\u5E94\u7528\u3002","botOnboarding.verifying":"\u626B\u7801\u6210\u529F\uFF0C\u6B63\u5728\u6821\u9A8C\u51ED\u8BC1...","botOnboarding.configuringPermissions":"\u6B63\u5728\u81EA\u52A8\u914D\u7F6E\u5F00\u653E\u5E73\u53F0\u6743\u9650\u2026","botOnboarding.platformScanHint":"\u8BF7\u7528\u98DE\u4E66 App \u518D\u626B\u4E00\u6B21\u7801\u767B\u5F55\u5F00\u653E\u5E73\u53F0\uFF08\u7528\u4E8E\u81EA\u52A8\u5BFC\u5165\u6743\u9650\u3001\u914D\u7F6E\u56DE\u8C03\u3001\u63D0\u4EA4\u7248\u672C\uFF09\u3002","botOnboarding.platformQrAlt":"\u5F00\u653E\u5E73\u53F0\u767B\u5F55\u4E8C\u7EF4\u7801","botOnboarding.completed":"\u673A\u5668\u4EBA\u5DF2\u6DFB\u52A0\u3002","botOnboarding.permissionOk":"\u5DF2\u81EA\u52A8\u5BFC\u5165 {count} \u9879\u6743\u9650\u3002","botOnboarding.permissionSkipped":"\uFF08\u8DF3\u8FC7 {count} \u9879\u5F53\u524D\u79DF\u6237\u76EE\u5F55\u4E2D\u6CA1\u6709\u7684\u6743\u9650\uFF09","botOnboarding.permissionVersion":"\u5DF2\u63D0\u4EA4\u53D1\u5E03\u7248\u672C {version}\u3002","botOnboarding.permissionManual":"\u6743\u9650\u672A\u80FD\u81EA\u52A8\u914D\u7F6E\uFF0C\u8BF7\u624B\u52A8\u5B8C\u6210\u4EE5\u4E0B\u6B65\u9AA4\uFF1A","botOnboarding.metaDir":"\u76EE\u5F55","botOnboarding.failed":"\u6DFB\u52A0\u5931\u8D25","botOnboarding.openLink":"\u6253\u4E0D\u5F00\u626B\u7801\uFF1F\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00","botOnboarding.close":"\u5173\u95ED","botOnboarding.restartHint":"\u5DF2\u5199\u5165 bots.json\u3002\u6267\u884C pnpm daemon:restart \u540E\u65B0\u673A\u5668\u4EBA\u751F\u6548\u3002","botOnboarding.needsOwner":"\u65E0\u6CD5\u81EA\u52A8\u786E\u8BA4\u626B\u7801\u4EBA\u8EAB\u4EFD\uFF0C\u8BF7\u624B\u52A8\u586B\u5199 owner \u540E\u518D\u5B8C\u6210\u3002","botOnboarding.ownerLabel":"Owner\uFF08\u673A\u5668\u4EBA\u7BA1\u7406\u8005\uFF09","botOnboarding.ownerPlaceholder":"\u5B8C\u6574\u90AE\u7BB1 / union_id(on_) / open_id(ou_)\uFF0C\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694","botOnboarding.ownerHint":"\u4E3A\u907F\u514D\u300C\u65E0\u4EBA\u662F owner \u65F6\u4EFB\u4F55\u4EBA\u90FD\u80FD\u505A\u7BA1\u7406\u64CD\u4F5C\u300D\uFF0C\u5FC5\u987B\u6307\u5B9A\u81F3\u5C11\u4E00\u4E2A owner\u3002\u5EFA\u8BAE\u7528\u672C\u4F01\u4E1A\u90AE\u7BB1\u6216 union_id(on_)\u3002","botOnboarding.ownerSubmit":"\u4FDD\u5B58 owner \u5E76\u5B8C\u6210","botOnboarding.ownerEmpty":"\u8BF7\u586B\u5199\u81F3\u5C11\u4E00\u4E2A owner\u3002","botOnboarding.ownerInvalid":"owner \u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002","botOnboarding.qrAlt":"\u98DE\u4E66\u626B\u7801\u6DFB\u52A0\u673A\u5668\u4EBA\u4E8C\u7EF4\u7801","overview.title":"\u5DE5\u4F5C\u53F0","overview.subtitle":"\u6570\u5B57\u5458\u5DE5\u5B9E\u65F6\u72B6\u6001 \xB7 \u540C\u6B65\u98DE\u4E66\u8BDD\u9898","overview.team":"AI \u56E2\u961F","overview.teamHint":"\u6BCF\u4F4D\u6570\u5B57\u5458\u5DE5\u7684\u5B9E\u65F6\u72B6\u6001","overview.attention":"\u9700\u8981\u4F60\u5904\u7406","overview.attentionHint":"\u5361\u4F4F\u7684\u4EFB\u52A1\uFF0C\u56DE\u4E2A\u8BDD\u5C31\u80FD\u7EE7\u7EED\u8DD1","overview.activeSessions":"\u6D3B\u8DC3\u4F1A\u8BDD","overview.activeSessionsHint":"\u6B63\u5728\u8FD0\u8F6C\u7684\u4F1A\u8BDD","overview.today":"\u6B64\u523B\u6982\u89C8","overview.todayHint":"\u6D3B\u8DC3\u4F1A\u8BDD\u5206\u5E03","overview.viewAll":"\u67E5\u770B\u5168\u90E8 \u2192","overview.botIdle":"\u5F85\u547D\u4E2D\uFF0C\u968F\u65F6\u53EF\u63A5\u65B0\u4EFB\u52A1","overview.botOffline":"\u79BB\u7EBF \u2014 daemon \u672A\u4E0A\u7EBF","overview.botBusy":"\u6267\u884C\u4E2D \xB7 {count} \u4F1A\u8BDD","overview.botNeedsYou":"\u7B49\u4F60\u56DE\u590D","overview.botReady":"\u5C31\u7EEA","overview.botOff":"\u79BB\u7EBF","overview.sessionsCount":"{count} \u4F1A\u8BDD","overview.lastActive":"{time}\u524D\u6D3B\u8DC3","overview.noAttention":"\u6CA1\u6709\u7B49\u4F60\u5904\u7406\u7684\u4E8B\u9879","overview.teamExpand":"\u5C55\u5F00\u5168\u90E8 {count} \u4F4D \u25BE","overview.teamCollapse":"\u6536\u8D77 \u25B4","strip.pending":"{count} \u4EF6\u5F85\u5904\u7406","strip.longest":"\u6700\u4E45\u5DF2\u7B49 {time} \u2014 {bot} {reason}","strip.handle":"\u7ACB\u5373\u5904\u7406","overview.openSessions":"\u6D3B\u8DC3\u4F1A\u8BDD","overview.workingSessions":"\u5DE5\u4F5C\u4E2D","overview.onlineBots":"\u5728\u7EBF Bot","overview.schedules":"\u5B9A\u65F6\u4EFB\u52A1","overview.groups":"\u7FA4\u804A\u8986\u76D6","overview.enabledSchedules":"\u5DF2\u542F\u7528","overview.total":"\u603B\u8BA1","overview.active":"\u6D3B\u8DC3","overview.daemonRegistry":"daemon \u6CE8\u518C\u8868","overview.chatMatrix":"\u7FA4\u804A\u77E9\u9635","overview.recentSessions":"\u6700\u8FD1\u4F1A\u8BDD","overview.nextSchedules":"\u5373\u5C06\u6267\u884C","overview.noSessions":"\u6682\u65E0\u4F1A\u8BDD\u3002","overview.noSchedules":"\u6682\u65E0\u5B9A\u65F6\u4EFB\u52A1\u3002","sessions.title":"\u4F1A\u8BDD\u63A7\u5236","sessions.subtitle":"\u5B9A\u4F4D\u98DE\u4E66\u8BDD\u9898\u3001\u6253\u5F00 Web Terminal\u3001\u5173\u95ED\u6216\u6062\u590D CLI \u4F1A\u8BDD\u3002","sessions.search":"\u641C\u7D22\u5DE5\u4F5C\u76EE\u5F55 / \u6807\u9898 / ID","sessions.anyStatus":"\u5168\u90E8\u72B6\u6001","sessions.adoptAny":"adopt: \u5168\u90E8","sessions.adoptYes":"adopt: \u662F","sessions.adoptNo":"adopt: \u5426","sessions.activeOnly":"\u4EC5\u6D3B\u8DC3","sessions.closeSelected":"\u5173\u95ED\u9009\u4E2D","sessions.clearSelection":"\u53D6\u6D88\u9009\u62E9","sessions.selectedCount":"\u5DF2\u9009 {count} \u4E2A\u4F1A\u8BDD","sessions.idleCleanupOlderThan":"\u7A7A\u95F2\u8D85\u8FC7","sessions.idleCleanupThreshold":"\u7A7A\u95F2\u6E05\u7406\u9608\u503C","sessions.idleCleanupRun":"\u6E05\u7406\u7A7A\u95F2","sessions.idleCleanupCount":"\u53EF\u6E05\u7406 {count} \u4E2A","sessions.idleCleanupConfirm":"\u5C06\u5173\u95ED {count} \u4E2A\u7A7A\u95F2\u8D85\u8FC7 {threshold} \u7684\u4F1A\u8BDD\uFF0C\u786E\u5B9A\u7EE7\u7EED\uFF1F","sessions.idleCleanupRunning":"\u6E05\u7406\u4E2D\u2026","sessions.idleCleanupDone":"\u5DF2\u5173\u95ED {closed} \u4E2A\uFF0C\u5931\u8D25 {failed} \u4E2A","sessions.idleCleanupFailed":"\u6E05\u7406\u5931\u8D25","sessions.lock":"\u9501\u5B9A\u4F1A\u8BDD","sessions.unlock":"\u89E3\u9501\u4F1A\u8BDD","sessions.locked":"\u9501\u5B9A","sessions.lockSelected":"\u9501\u5B9A\u9009\u4E2D","sessions.unlockSelected":"\u89E3\u9501\u9009\u4E2D","sessions.lockFailed":"\u9501\u5B9A\u72B6\u6001\u66F4\u65B0\u5931\u8D25","sessions.bot":"bot","sessions.cli":"CLI","sessions.chat":"\u7FA4\u804A","sessions.openChat":"\u6253\u5F00\u7FA4\u804A","sessions.status":"\u72B6\u6001","sessions.tokenIn":"Token In","sessions.tokenOut":"Token Out","sessions.titleCol":"\u6807\u9898","sessions.workingDir":"\u5DE5\u4F5C\u76EE\u5F55","sessions.created":"\u521B\u5EFA","sessions.last":"\u6700\u8FD1","sessions.adopt":"\u63A5\u5165","sessions.actions":"\u64CD\u4F5C","sessions.details":"\u8BE6\u60C5","sessions.copy":"\u590D\u5236","sessions.copied":"\u5DF2\u590D\u5236","sessions.locate":"\u5B9A\u4F4D\u8BDD\u9898","sessions.locating":"\u53D1\u9001\u4E2D...","sessions.cooldown":"\u51B7\u5374 {seconds}s","sessions.openTerminal":"\u7EC8\u7AEF","sessions.writeLink":"\u64CD\u4F5C\u94FE\u63A5","sessions.writeLinkHint":"\u83B7\u53D6\u53EF\u64CD\u4F5C\u7EC8\u7AEF\u94FE\u63A5\uFF08\u5E26\u5199\u6743\u9650 token\uFF0C\u65B0\u6807\u7B7E\u6253\u5F00\uFF09","sessions.writeLinkFail":"\u83B7\u53D6\u64CD\u4F5C\u94FE\u63A5\u5931\u8D25","sessions.close":"\u5173\u95ED\u4F1A\u8BDD","sessions.restart":"\u91CD\u542F CLI","sessions.restartConfirmIntro":"\u51C6\u5907\u91CD\u542F\u5F53\u524D CLI\u3002","sessions.restartConfirmStatus":"\u5F53\u524D\u72B6\u6001","sessions.restartConfirmCli":"CLI","sessions.restartConfirmQuestion":"\u786E\u8BA4\u91CD\u542F\u8FD9\u4E2A CLI\uFF1F","sessions.restartFailed":"\u91CD\u542F\u5931\u8D25","sessions.resume":"\u6062\u590D\u4F1A\u8BDD","sessions.dismiss":"\u5173\u95ED","sessions.closeConfirm":"\u5173\u95ED\u8FD9\u4E2A\u4F1A\u8BDD\uFF1F","sessions.resumeFailed":"\u6062\u590D\u5931\u8D25","sessions.land":"\u843D\u76D8","sessions.landLoading":"\u52A0\u8F7D\u6C99\u76D2 diff\u2026","sessions.landUnavailable":"\u65E0\u6CD5\u843D\u76D8","sessions.landEmpty":"\u6C99\u76D2\u526F\u672C\u6CA1\u6709\u6539\u52A8\u3002","sessions.landApply":"\u5E94\u7528\u5230\u78C1\u76D8","sessions.landDiscard":"\u4E22\u5F03","sessions.landApplied":"\u5DF2\u843D\u76D8","sessions.landFailed":"\u843D\u76D8\u5931\u8D25","sessions.landDiscarded":"\u5DF2\u4E22\u5F03\uFF08\u6C99\u76D2\u526F\u672C\u672A\u5E94\u7528\uFF09\u3002","sessions.insight":"\u6D1E\u5BDF","sessions.insightLoading":"\u5206\u6790\u4E2D\u2026","sessions.insightUnavailable":"\u65E0\u6CD5\u5206\u6790","sessions.insightEmpty":"\u672C\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u53EF\u5206\u6790\u7684\u5DE5\u5177 span\u3002","sessions.insightMetrics":"span {total} \xB7 \u5931\u8D25 {failed} \xB7 \u6162 {slow} \xB7 \u8BFB\u6539\u6BD4 {rw} \xB7 \u538B\u7F29 {compactions}","sessions.insightSuggestions":"\u5EFA\u8BAE","sessions.insightSpans":"\u52A8\u4F5C span","sessions.insightCapped":"\u4EC5\u663E\u793A\u524D {shown}/{total} \u6761","sessions.insightAsOf":"\u622A\u81F3 {asOf}","sessions.insightPartial":"\uFF08\u53EF\u80FD\u4E0D\u542B\u8FDB\u884C\u4E2D\u7684\u6700\u65B0\u4E00\u8F6E\uFF09","nav.insights":"\u6D1E\u5BDF","insights.title":"\u5DE5\u4F5C\u6D41\u6D1E\u5BDF","insights.subtitle":"\u53EA\u8BFB\u5206\u6790\u672C\u673A Claude Code / Codex \u4F1A\u8BDD\u7684\u52A8\u4F5C\u8F68\u8FF9\u3001\u5931\u8D25\u4E0E\u6469\u64E6\uFF0C\u7ED9\u51FA\u89C4\u5219\u578B\u4F18\u5316\u5EFA\u8BAE\u3002","insights.refresh":"\u5237\u65B0","insights.search":"\u641C\u7D22\u4F1A\u8BDD / bot / \u76EE\u5F55\u2026","insights.filter":"\u7B5B\u9009","insights.filterAll":"\u5168\u90E8","insights.filterReview":"\u503C\u5F97\u590D\u76D8","insights.filterFailed":"\u6709\u5931\u8D25","insights.filterSlow":"\u6709\u6162 span","insights.loading":"\u5206\u6790\u4E2D\u2026","insights.loaded":"\u5DF2\u52A0\u8F7D {count} \u4E2A\u4F1A\u8BDD","insights.unavailable":"\u52A0\u8F7D\u5931\u8D25","insights.listCount":"\u663E\u793A {shown}/{total}","insights.tabOverview":"\u603B\u89C8","insights.tabSessions":"\u4F1A\u8BDD","insights.tabDist":"\u5206\u5E03","insights.tabHot":"\u70ED\u70B9","insights.projectAll":"\u5168\u90E8\u9879\u76EE","insights.timeAll":"\u5168\u90E8\u65F6\u95F4","insights.time1d":"\u8FD1 1 \u5929","insights.time7d":"\u8FD1 7 \u5929","insights.time30d":"\u8FD1 30 \u5929","insights.clear":"\u6E05\u9664","insights.emptyAnalyzableHint":"\u52FE\u9009\u300C\u542B\u672A\u5206\u6790\u300D\u53EF\u67E5\u770B\u5176\u4F59\u4F1A\u8BDD","insights.showAll":"\u542B\u672A\u5206\u6790","insights.distHint":"\u5F53\u524D\u7B5B\u9009\u4E0B\u5404\u4F1A\u8BDD\u7684\u6307\u6807\u5206\u5E03\u2014\u2014\u770B\u8D70\u52BF\u3001\u770B\u5178\u578B\u503C\u843D\u5728\u54EA\u3002","insights.distSpans":"\u6BCF\u4F1A\u8BDD span \u6570","insights.distFailed":"\u6BCF\u4F1A\u8BDD\u5931\u8D25\u6570","insights.distSlow":"\u6BCF\u4F1A\u8BDD\u6162 span","insights.distAgentTime":"agent \u5DE5\u4F5C\u65F6\u957F","insights.distRw":"\u8BFB\u6539\u6BD4","insights.distChurn":"\u4EE3\u7801\u6539\u52A8\u884C\u6570","insights.distTrend":"\u6309\u5929\u8D8B\u52BF\uFF08\u8FD1 4 \u5468\uFF09","insights.distTrendSub":"\u6BCF\u65E5\u4F1A\u8BDD\u6570","insights.distMedian":"\u4E2D\u4F4D {v}","insights.distEmpty":"\u5F53\u524D\u7B5B\u9009\u4E0B\u6CA1\u6709\u53EF\u5206\u6790\u7684\u4F1A\u8BDD\u3002","insights.disclosure":"\u53E3\u5F84\uFF1A\u8017\u65F6\u53EA\u7B97\u5DE5\u5177\u6267\u884C\u65F6\u95F4\uFF0C\u5DF2\u5254\u9664\u7B49\u7528\u6237\u56DE\u590D\uFF08\u95EE\u7B54/\u8BA1\u5212\u786E\u8BA4\uFF09\u7684\u6302\u673A\u65F6\u957F\uFF0C\u6545\u4E0D\u53CD\u6620\u5899\u949F\u65F6\u957F\uFF1BCodex \u4F1A\u8BDD\u7684\u300C\u8BFB\u300D\u591A\u8D70 shell\uFF08exec_command\uFF09\uFF0C\u4E0D\u8BA1\u5165\u300C\u8BFB\u300D\u76F8\uFF0C\u6545\u5176\u8BFB\u6539\u6BD4\u4F1A\u504F\u4F4E\u751A\u81F3\u4E3A 0\uFF1B\u4EE3\u7801\u6539\u52A8\u6309 patch \u89E3\u6790\uFF0C\u4EC5\u53D6\u6BCF\u4F1A\u8BDD\u6700\u6D3B\u8DC3\u7684\u82E5\u5E72\u6587\u4EF6\uFF0C\u4E0E Claude \u7684\u7ED3\u6784\u5316\u7EDF\u8BA1\u53E3\u5F84\u4E0D\u540C\u3002\u8DE8\u5DE5\u5177\u7684\u5206\u5E03\u4E0E\u6BD4\u503C\u4EC5\u4F9B\u53C2\u8003\uFF0C\u4E0D\u5B9C\u76F4\u63A5\u5BF9\u6BD4\u3002","insights.rwNote":"Codex \u8BFB\u591A\u8D70 shell\uFF0C\u672A\u8BA1\u5165\u8BFB\u76F8","insights.viewSessions":"\u6309\u4F1A\u8BDD\u67E5\u770B","insights.hotHint":"\u8DE8\u4F1A\u8BDD\u590D\u53D1\u4FE1\u53F7\u2014\u2014\u6700\u8BE5\u6536\u655B\u7684\u5730\u65B9\u3002","insights.hotToolFailures":"\u5DE5\u5177\u62A5\u9519\u70ED\u70B9","insights.hotSlowSessions":"\u6700\u6162\u7684\u4F1A\u8BDD","insights.hotProjects":"\u9879\u76EE\u5206\u5E03","insights.hotFiles":"\u6587\u4EF6\u590D\u53D1\u70ED\u70B9","insights.hotCommands":"\u547D\u4EE4\u590D\u53D1\u70ED\u70B9","insights.hotErrors":"\u62A5\u9519\u590D\u53D1\u70ED\u70B9","insights.hotComingSoon":"\u6587\u4EF6 / \u547D\u4EE4\u590D\u53D1\u70ED\u70B9\u5373\u5C06\u4E0A\u7EBF\uFF08\u9700\u7ED9\u5F15\u64CE\u52A0\u8DE8\u4F1A\u8BDD\u805A\u5408\uFF09\u3002","insights.hotSessionsCol":"\u4F1A\u8BDD","insights.hotFailsCol":"\u5931\u8D25","insights.hotSlowCol":"\u6162","insights.backToList":"\u8FD4\u56DE\u5217\u8868","insights.sortLabel":"\u6392\u5E8F","insights.sortRecent":"\u6700\u8FD1","insights.sortReview":"\u56DE\u770B\u5206","insights.sortSpans":"span \u6570","insights.sortFails":"\u5931\u8D25","insights.sortSlow":"\u6162","insights.sortAgent":"\u65F6\u957F","insights.layoutCard":"\u5361\u7247","insights.layoutTable":"\u8868\u683C","insights.colTitle":"\u4F1A\u8BDD","insights.colProject":"\u9879\u76EE","insights.colTime":"\u65F6\u95F4","insights.paletteOpen":"\u8DF3\u8F6C \u2318K","insights.palettePlaceholder":"\u8DF3\u8F6C\u5230 tab \u6216\u641C\u7D22\u4F1A\u8BDD\u2026","insights.paletteTabs":"\u89C6\u56FE","insights.paletteSessions":"\u4F1A\u8BDD","insights.paletteEmpty":"\u6CA1\u6709\u5339\u914D\u9879","insights.tabFlow":"\u884C\u4E3A\u6D41","insights.flowHint":"\u667A\u80FD\u4F53\u628A\u52A8\u4F5C\u4E0E\u65F6\u95F4\u82B1\u5728\u54EA\u4E9B\u6D3B\u52A8\u9636\u6BB5\uFF0C\u4EE5\u53CA\u5404\u4F1A\u8BDD\u7684\u8282\u594F\u5206\u5E03\u3002","insights.flowPipeline":"\u6D3B\u52A8\u9636\u6BB5\u6D41\u6C34\u7EBF","insights.flowPipeSub":"\u7814\u7A76 \u2192 \u4FEE\u6539 \u2192 \u8FD0\u884C \u2192 \u59D4\u6D3E \u2192 \u8BA8\u8BBA\uFF1B\u4E0A=\u52A8\u4F5C\u6570\uFF0C\u4E0B=\u8017\u65F6","insights.flowShares":"\u52A8\u4F5C\u5360\u6BD4 vs \u65F6\u95F4\u5360\u6BD4","insights.flowActShare":"\u52A8\u4F5C\u5360\u6BD4","insights.flowTimeShare":"\u65F6\u95F4\u5360\u6BD4","insights.flowRhythm":"\u5404\u4F1A\u8BDD\u8282\u594F\uFF08\u6309\u65F6\u957F\uFF09","insights.subagents":"\u5B50\u4EE3\u7406","insights.subagentsHint":"\u672C\u4F1A\u8BDD\u59D4\u6D3E\u51FA\u53BB\u7684\u5B50\u4EE3\u7406\uFF08Task/Agent\uFF09\uFF0C\u5404\u81EA\u505A\u4E86\u4EC0\u4E48\u3001\u8DD1\u4E86\u591A\u4E45\u3002","insights.readsShort":"\u8BFB","insights.editsShort":"\u6539","insights.durShort":"\u65F6\u957F","insights.empty":"\u6CA1\u6709\u5339\u914D\u7684\u4F1A\u8BDD\u3002","insights.selectSession":"\u4ECE\u5DE6\u4FA7\u9009\u4E00\u4E2A\u4F1A\u8BDD\uFF0C\u67E5\u770B\u52A8\u4F5C span \u4E0E\u5EFA\u8BAE\u3002","insights.detailLoading":"\u52A0\u8F7D\u4F1A\u8BDD\u8BE6\u60C5\u2026","insights.recommendations":"\u4F18\u5316\u5EFA\u8BAE","insights.recommendationsHint":"\u57FA\u4E8E\u89C4\u5219\u7684\u8DE8\u4F1A\u8BDD\u6C47\u603B\uFF0C\u6BCF\u6761\u53EF\u8FFD\u6EAF\u5230\u6307\u6807\u3002","insights.noRecommendations":"\u6682\u65E0\u5EFA\u8BAE\u3002","insights.seenInSessions":"\u51FA\u73B0\u5728 {count} \u4E2A\u4F1A\u8BDD","insights.toolFailures":"\u9AD8\u9891\u5DE5\u5177\u5931\u8D25","insights.toolFailuresHint":"\u6309\u5DE5\u5177\u6C47\u603B\u5931\u8D25 span\u3002","insights.noFailures":"\u6CA1\u6709\u5931\u8D25 span\u3002","insights.metricSessions":"\u4F1A\u8BDD","insights.metricAnalyzed":"\u5DF2\u5206\u6790 {count}","insights.metricSpans":"span","insights.metricSafe":"\u5DF2\u8131\u654F","insights.metricFailed":"\u5931\u8D25 span","insights.metricSlow":"\u6162 span","insights.metricRw":"\u8BFB\u6539\u6BD4","insights.metricCompactions":"\u538B\u7F29 {count}","insights.spansShort":"span ","insights.failedShort":"\u5931\u8D25 ","insights.slowShort":"\u6162 ","insights.rwShort":"\u8BFB\u6539 ","insights.unsupported":"\u8BE5 CLI \u6682\u4E0D\u652F\u6301","insights.noTranscript":"\u6682\u65E0 transcript","insights.parseError":"\u89E3\u6790\u5931\u8D25","insights.noSpans":"\u6682\u65E0\u53EF\u5206\u6790 span\u3002","insights.sevBad":"\u4E25\u91CD","insights.sevWarn":"\u6CE8\u610F","insights.sevInfo":"\u63D0\u793A","insights.phase.research":"\u7814\u7A76","insights.phase.edit":"\u4FEE\u6539","insights.phase.run":"\u8FD0\u884C","insights.phase.delegate":"\u59D4\u6D3E","insights.phase.discuss":"\u8BA8\u8BBA","insights.trace":"\u52A8\u4F5C span","insights.ledger":"\u9010\u8F6E\u5BF9\u8D26","insights.detailTabs":"\u89C2\u6D4B\u660E\u7EC6","insights.spanStatus":"\u72B6\u6001","insights.spanTool":"\u5DE5\u5177","insights.spanPhase":"\u9636\u6BB5","insights.spanDuration":"\u8017\u65F6","insights.spanTurn":"\u8F6E","insights.spanSummary":"\u6458\u8981","insights.ledgerMore":"\u5C55\u5F00\u53E6\u5916 {count} \u6761\u6458\u8981","insights.ledgerOmitted":"\u8FD8\u6709 {count} \u6761\u5DF2\u6298\u53E0","insights.ledgerNoContent":"\u672C\u8F6E\u6CA1\u6709\u53EF\u5C55\u793A\u7684\u8131\u654F\u6458\u8981\u3002","insights.diagShow":"\u67E5\u770B\u8BC1\u636E","insights.diagActive":"\u6B63\u5728\u67E5\u770B","insights.evMatched":"\u547D\u4E2D {count} \u6761\u8BC1\u636E","insights.evMatchedCapped":"\u547D\u4E2D {matched} \u6761\uFF0C\u663E\u793A\u524D {shown} \u6761","insights.evDefault":"\u91CD\u70B9 {shown} / \u5171 {total} \u6761","insights.evShowAll":"\u663E\u793A\u5168\u90E8 {count} \u6761","insights.evBackToEvidence":"\u53EA\u770B\u91CD\u70B9","insights.intent.run_script":"\u8FD0\u884C\u811A\u672C","insights.intent.test":"\u6D4B\u8BD5","insights.intent.typecheck":"\u7C7B\u578B\u68C0\u67E5","insights.intent.lint":"Lint","insights.intent.git":"Git","insights.intent.search":"\u641C\u7D22","insights.intent.read_file":"\u8BFB\u6587\u4EF6","insights.intent.edit_file":"\u6539\u6587\u4EF6","insights.intent.write_file":"\u5199\u6587\u4EF6","insights.intent.delegate":"\u59D4\u6D3E","insights.intent.unknown":"\u64CD\u4F5C","insights.result.ok":"\u6210\u529F","insights.result.tool_error":"\u5DE5\u5177\u62A5\u9519","insights.result.test_failed":"\u6D4B\u8BD5\u5931\u8D25","insights.result.typecheck_failed":"\u7C7B\u578B\u68C0\u67E5\u5931\u8D25","insights.result.lint_failed":"Lint \u5931\u8D25","insights.result.command_failed":"\u547D\u4EE4\u5931\u8D25","insights.result.timeout":"\u8D85\u65F6","insights.result.no_output":"\u65E0\u8F93\u51FA","insights.result.unknown":"\u672A\u77E5","insights.tag.failure":"\u5931\u8D25","insights.tag.slow":"\u6162","insights.tag.retry":"\u8FD4\u5DE5","insights.tag.read_write_imbalance":"\u8BFB\u6539\u5931\u8861","insights.tag.diagnostic":"\u8BCA\u65AD","insights.tag.normal":"\u6B63\u5E38","insights.turnHeadline.turn_has_failures":"\u672C\u8F6E {failures} \u6B21\u5931\u8D25","insights.turnHeadline.turn_has_slow_spans":"\u672C\u8F6E\u6709\u8017\u65F6\u504F\u957F\u7684\u64CD\u4F5C","insights.turnHeadline.turn_has_retries":"\u672C\u8F6E\u53CD\u590D\u91CD\u8BD5\u540C\u4E00\u64CD\u4F5C","insights.turnHeadline.turn_read_write_imbalance":"\u672C\u8F6E\u6539\u591A\u8BFB\u5C11\uFF08\u6539 {edits} / \u8BFB {reads}\uFF09","insights.evTimeline":"\u5168\u90E8 {count} \u6761 span \u65F6\u95F4\u7EBF","insights.evNoFlags":"\u6CA1\u6709\u88AB\u6807\u8BB0\u4E3A\u5931\u8D25 / \u6162 / \u8FD4\u5DE5\u7684 span","insights.turnAllNormal":"{count} \u4E2A\u8F6E\u6B21\u90FD\u6B63\u5E38\uFF0C\u6CA1\u6709\u503C\u5F97\u590D\u76D8\u7684","insights.turnEvidence":"\u67E5\u770B\u672C\u8F6E {count} \u6761\u8BC1\u636E","insights.turnHiddenNormal":"\u53E6\u6709 {count} \u4E2A\u6B63\u5E38\u8F6E\u6B21\uFF08\u5DF2\u9690\u85CF\uFF09","insights.mReads":"\u8BFB","insights.mEdits":"\u6539","insights.mRuns":"\u8DD1","insights.mFailures":"\u5931\u8D25","insights.mDur":"\u8017\u65F6","insights.turnHeadline.turn_normal":"\u6B63\u5E38","insights.rec.fix_repeated_tool_failures":"\u53CD\u590D\u5931\u8D25\u7684\u547D\u4EE4\u9700\u8981\u6536\u655B","insights.rec.split_slow_operation":"\u6162\u64CD\u4F5C\u62D6\u6162\u4E86\u6574\u4E2A\u4F1A\u8BDD","insights.rec.add_read_pass_before_edit":"\u6539\u4E4B\u524D\u8BFB\u5F97\u592A\u5C11","insights.rec.preserve_context_checkpoints":"\u4E0A\u4E0B\u6587\u88AB\u538B\u7F29\uFF0C\u6CE8\u610F\u7559\u5B58\u6863","insights.impact.impact_failed_spans":"{failedSpans} \u4E2A\u52A8\u4F5C\u5931\u8D25\uFF08\u6700\u591A\uFF1A{topTool} \xD7{topToolFailures}\uFF09","insights.impact.impact_slow_spans":"{slowSpansTotal} \u4E2A\u6162\u52A8\u4F5C\u62D6\u6162\u8FDB\u5EA6","insights.impact.impact_low_read_write_ratio":"\u6539\u4E86 {writeSpans} \u5904\uFF0C\u53EA\u8BFB\u4E86 {readSpans} \u5904","insights.impact.impact_context_compaction":"\u672C\u4F1A\u8BDD\u53D1\u751F {compactions} \u6B21\u4E0A\u4E0B\u6587\u538B\u7F29","insights.why.why_tool_failure_concentrated":"\u5931\u8D25\u96C6\u4E2D\u5728 {topTool}\uFF08\u5171 {topToolFailures} \u6B21\uFF09\uFF0C\u591A\u534A\u662F\u540C\u4E00\u7C7B\u95EE\u9898","insights.why.why_slow_span_dominates":"\u5C11\u6570\u8017\u65F6\u52A8\u4F5C\u5360\u4E86\u5927\u5934\uFF0C\u6700\u6162\u7684\u662F {slowestTool}","insights.why.why_edits_outpaced_reads":"\u8BFB\u5199\u6BD4 {readWriteRatio}\uFF0C\u6539\u5F97\u6BD4\u8BFB\u5F97\u591A\u5BB9\u6613\u8E29\u5751\u8FD4\u5DE5","insights.why.why_context_compaction_happened":"\u957F\u4F1A\u8BDD\u88AB\u538B\u7F29\uFF0C\u65E9\u671F\u7684\u51B3\u7B56/\u4E0A\u4E0B\u6587\u53EF\u80FD\u5DF2\u4E22\u5931","insights.action.inspect_failed_span_details":"\u9010\u4E2A\u770B\u5931\u8D25\u52A8\u4F5C\u7684\u8BE6\u60C5\uFF0C\u5B9A\u4F4D\u6839\u56E0","insights.action.add_preflight_or_timeout":"\u7ED9\u9AD8\u9891\u5931\u8D25\u7684\u547D\u4EE4\u52A0\u524D\u7F6E\u68C0\u67E5\u6216\u8D85\u65F6\u63A7\u5236","insights.action.narrow_or_split_slow_operation":"\u628A\u6162\u64CD\u4F5C\u6536\u7A84\u6216\u62C6\u5C0F\uFF08\u5982\u53EA\u8DD1\u5B9A\u5411\u7528\u4F8B\uFF09","insights.action.surface_timeout_or_progress":"\u66F4\u65E9\u66B4\u9732\u8D85\u65F6/\u8FDB\u5EA6\uFF0C\u522B\u8BA9\u5B83\u9ED8\u9ED8\u5361\u4F4F","insights.action.read_or_search_before_editing":"\u6539\u964C\u751F\u6587\u4EF6\u524D\u5148\u8BFB\u4E00\u904D\u6216\u641C\u4E00\u4E0B","insights.action.verify_assumptions_before_running":"\u52A8\u624B\u524D\u5148\u9A8C\u8BC1\u5047\u8BBE\uFF0C\u51CF\u5C11\u76F2\u6539","insights.action.write_checkpoints_for_long_tasks":"\u957F\u4EFB\u52A1\u628A\u51B3\u7B56\u548C\u68C0\u67E5\u70B9\u843D\u5230\u7B14\u8BB0\u91CC","insights.struct.shell":"shell \u547D\u4EE4","insights.struct.fileEdit":"\u6587\u4EF6\u7F16\u8F91","insights.struct.readSearch":"\u8BFB\u53D6/\u641C\u7D22","insights.struct.agentTask":"\u5B50 agent \u4EFB\u52A1","insights.struct.toolInput":"\u5DE5\u5177\u8F93\u5165","insights.struct.toolResult":"\u5DE5\u5177\u8F93\u51FA","insights.struct.toolError":"\u5DE5\u5177\u62A5\u9519","insights.struct.patchFailed":"\u8865\u4E01\u5931\u8D25","insights.struct.patchApplied":"\u8865\u4E01\u5DF2\u5E94\u7528","insights.struct.exit":"exit {code}","insights.spanAll":"\u5168\u90E8","insights.dDetail":"\u8BE6\u60C5","insights.dCollapse":"\u6536\u8D77","insights.dPhase":"\u9636\u6BB5","insights.dStart":"\u8D77\u59CB","insights.dDur":"\u8017\u65F6","insights.dIntent":"\u610F\u56FE","insights.dResult":"\u7ED3\u679C","insights.dIn":"\u8F93\u5165","insights.dOut":"\u8F93\u51FA","insights.dTags":"\u6807\u7B7E","insights.dTurnContext":"\u7B2C {turn} \u8F6E\u4E0A\u4E0B\u6587","insights.advice.failure":"\u{1F4A1} \u770B\u6E05\u62A5\u9519\u518D\u52A8\u624B\uFF0C\u522B\u76F2\u76EE\u91CD\u8BD5","insights.advice.retry":"\u{1F4A1} \u540C\u4E00\u6B65\u53CD\u590D\u91CD\u8BD5\u2014\u2014\u5148\u5B9A\u4F4D\u6839\u56E0\u518D\u7EE7\u7EED","insights.advice.read_write_imbalance":"\u{1F4A1} \u6539\u4E4B\u524D\u5148\u8BFB\u76F8\u5173\u6587\u4EF6\uFF0C\u51CF\u5C11\u8FD4\u5DE5","insights.advice.slow":"\u{1F4A1} \u6162\u64CD\u4F5C\uFF1A\u8003\u8651\u8DD1\u5B9A\u5411\u7528\u4F8B\u6216\u62C6\u5C0F","insights.turnPrompt":"\u7528\u6237","insights.turnExpand":"\u5C55\u5F00 {count} \u6B65","insights.turnCollapse":"\u6536\u8D77","insights.turnRail":"\u4F1A\u8BDD\u8F68\u8FF9","insights.gantt":"\u5DE5\u4F5C\u65F6\u5E8F","insights.ganttCaption":"{span} \u4E2A\u52A8\u4F5C \xB7 \u8DE8\u5EA6 {dur} \xB7 \u6D3B\u8DC3 {active}","insights.ctxCurve":"\u4E0A\u4E0B\u6587\u66F2\u7EBF","insights.ctxCaption":"\u6BCF\u8F6E\u5CF0\u503C in+cache \xB7 \u5CF0\u503C {peak} \xB7 {turns} \u8F6E","insights.ctxTurn":"\u8F6E {n}","insights.railSubagent":"\u5B50\u4EE3\u7406","insights.railSubagents":"{n} \u4E2A\u5B50\u4EE3\u7406","insights.turnPromptExpand":"\u5C55\u5F00","insights.turnPromptCollapse":"\u6536\u8D77","insights.turnPromptRaw":"\u539F\u6587","insights.turnPromptRendered":"\u6E32\u67D3","insights.srcMentions":"\u63D0\u5230","insights.senderHuman":"\u7528\u6237","insights.senderA2A":"A2A","insights.senderOther":"\u5176\u4ED6","insights.senderSystem":"\u7CFB\u7EDF","insights.turnPromptFull":"\u5168\u6587","insights.modalClose":"\u5173\u95ED","insights.promptTruncated":"\u5185\u5BB9\u8F83\u957F\uFF0C\u5DF2\u622A\u65AD","insights.replay":"\u5BF9\u8BDD\u56DE\u653E","insights.replayAgent":"agent \u64CD\u4F5C","insights.replaySearch":"\u641C\u7D22\u5BF9\u8BDD\u5185\u5BB9\u2026","insights.replayBy":"\u53D1\u8D77\u4EBA","insights.replayState":"\u72B6\u6001","insights.replayLoadMore":"\u52A0\u8F7D\u66F4\u591A\uFF08{shown}/{total}\uFF09","insights.replayAllLoaded":"\u5DF2\u5168\u90E8\u52A0\u8F7D\uFF08\u5171 {total} \u6761\uFF09","insights.replayEmpty":"\u6CA1\u6709\u5339\u914D\u7684\u6D88\u606F","insights.replayNoText":"\uFF08\u65E0\u6B63\u6587\uFF0C\u89C1\u64CD\u4F5C\uFF09","insights.replayOps":"{count} \u6B65\u64CD\u4F5C","insights.wsFiles":"\u6587\u4EF6\u6539\u52A8 \xB7 {n}","insights.wsCmds":"\u8DD1\u8FC7\u7684\u547D\u4EE4 \xB7 {n}","insights.wsReads":"\u8BFB {n}","insights.wsEdits":"\u6539 {n}","insights.wsFail":"\u5931\u8D25 {n}","insights.wsNoFiles":"\u65E0\u6587\u4EF6\u6539\u52A8","insights.wsNoCmds":"\u65E0\u547D\u4EE4\u8BB0\u5F55","insights.turnSummary":"\u5171 {total} \u8F6E \xB7 {flagged} \u8F6E\u9700\u5173\u6CE8","insights.dCommand":"\u547D\u4EE4","insights.dCmdOutput":"\u6267\u884C\u7ED3\u679C","insights.ledgerNormal":"\u6B63\u5E38\u6392\u5E8F","insights.ledgerGrouped":"\u6309\u5EFA\u8BAE\u5206\u7C7B","insights.ledgerOther":"\u5176\u4ED6\u8F6E\u6B21","insights.ledgerGroupCount":"{count} \u8F6E","insights.turnsCapped":"\u4EC5\u542B\u524D {shown}/{total} \u4E2A\u52A8\u4F5C\uFF0C\u65F6\u95F4\u7EBF\u53EF\u80FD\u4E0D\u5B8C\u6574","insights.suggestion.high_tool_failure.title":"\u5DE5\u5177\u5931\u8D25\u504F\u591A","insights.suggestion.high_tool_failure.action":"\u4F18\u5148\u770B\u5931\u8D25 span\uFF0C\u628A\u9AD8\u9891\u5931\u8D25\u547D\u4EE4\u505A\u524D\u7F6E\u68C0\u67E5\u6216\u8D85\u65F6\u63A7\u5236\u3002","insights.suggestion.tool_failure_present.title":"\u5B58\u5728\u5DE5\u5177\u8C03\u7528\u5931\u8D25","insights.suggestion.tool_failure_present.action":"\u91CD\u590D\u6267\u884C\u5DE5\u4F5C\u6D41\u524D\uFF0C\u5148\u590D\u76D8\u5931\u8D25 span\u3002","insights.suggestion.slow_span.title":"\u6162\u52A8\u4F5C\u4E3B\u5BFC\u4F1A\u8BDD","insights.suggestion.slow_span.action":"\u62C6\u5206\u6216\u9650\u5236\u6162\u64CD\u4F5C\uFF0C\u5E76\u66F4\u65E9\u66B4\u9732\u8D85\u65F6\u3001\u8FDB\u5EA6\u53CD\u9988\u3002","insights.suggestion.low_read_write_ratio.title":"\u4FEE\u6539\u591A\u4E8E\u9605\u8BFB","insights.suggestion.low_read_write_ratio.action":"\u6539\u964C\u751F\u6587\u4EF6\u524D\u5148\u8865\u4E00\u6B21\u8BFB\u53D6\u6216\u641C\u7D22\u3002","insights.suggestion.context_compaction.title":"\u53D1\u751F\u4E0A\u4E0B\u6587\u538B\u7F29","insights.suggestion.context_compaction.action":"\u957F\u4EFB\u52A1\u5EFA\u8BAE\u628A\u51B3\u7B56\u548C\u68C0\u67E5\u70B9\u843D\u5230\u6301\u4E45\u7B14\u8BB0\u6216\u62C6\u6210\u66F4\u5C0F\u5B50\u4EFB\u52A1\u3002","insights.suggestion.no_major_friction.title":"\u672A\u53D1\u73B0\u660E\u663E\u6469\u64E6","insights.suggestion.no_major_friction.action":"\u53EF\u7528\u52A8\u4F5C\u65F6\u95F4\u7EBF\u505A\u62BD\u67E5\uFF0C\u6216\u4E0E\u66F4\u6162\u7684\u4F1A\u8BDD\u5BF9\u6BD4\u3002","insights.evidence.failedSpans":"{count} \u4E2A\u5931\u8D25 span","insights.evidence.toolFailedTimes":"{tool} \u5931\u8D25 {count} \u6B21","insights.evidence.multipleToolsFailed":"\u591A\u4E2A\u5DE5\u5177\u53D1\u751F\u5931\u8D25","insights.evidence.toolRanSeconds":"{tool} \u8FD0\u884C {seconds}s","insights.evidence.readWriteRatio":"\u8BFB\u6539\u6BD4 {ratio}","insights.evidence.compactions":"\u4E0A\u4E0B\u6587\u538B\u7F29 {count} \u6B21","insights.evidence.spansAnalyzed":"\u5DF2\u5206\u6790 {count} \u4E2A span","connectors.lede":"\u8BA9\u5916\u90E8\u7CFB\u7EDF\uFF08\u76D1\u63A7\u544A\u8B66\u3001CI\u3001\u5DE5\u5355\u2026\uFF09\u901A\u8FC7\u4E00\u4E2A webhook \u89E6\u53D1\u673A\u5668\u4EBA\u5728\u7FA4\u91CC\u8BF4\u8BDD\u6216\u8DD1\u5DE5\u4F5C\u6D41\u3002","connectors.createTitle":"\u65B0\u5EFA Webhook","connectors.fName":"\u540D\u79F0","connectors.fNamePh":"\u5982\uFF1A\u7EBF\u4E0A\u544A\u8B66","connectors.fBot":"\u89E6\u53D1\u7684\u673A\u5668\u4EBA","connectors.fKind":"\u89E6\u53D1\u65B9\u5F0F","connectors.kindTurn":"\u5355\u8F6E\u5BF9\u8BDD\uFF08\u8BA9\u673A\u5668\u4EBA\u56DE\u5E94\u4E00\u6B21\uFF09","connectors.kindWorkflow":"\u5DE5\u4F5C\u6D41","connectors.fWf":"\u5DE5\u4F5C\u6D41 ID","connectors.fMode":"\u6295\u9012\u5230\u54EA\u4E2A\u7FA4","connectors.modeDynamic":"\u7531\u8BF7\u6C42\u6307\u5B9A\uFF08\u7FA4\u968F\u8BF7\u6C42\u4F20\u5165\uFF09","connectors.modeFixed":"\u56FA\u5B9A\u7FA4","connectors.modeNewGroup":"\u6BCF\u6B21\u65B0\u5EFA\u7FA4","connectors.fFixedChat":"\u6295\u9012\u5230\u7684\u7FA4","connectors.fChatManualPh":"\u624B\u52A8\u586B\u7FA4 ID\uFF1Aoc_\u2026","connectors.chatManualLink":"\u627E\u4E0D\u5230\u7FA4\uFF1F\u624B\u52A8\u586B ID \u2192","connectors.chatListLink":"\u4ECE\u7FA4\u5217\u8868\u9009\u62E9 \u2190","connectors.fAllow":"\u5141\u8BB8\u7684\u7FA4","connectors.optional":"\uFF08\u53EF\u9009\uFF09","connectors.allowHint":"\u6309\u4F4F Ctrl/\u2318 \u591A\u9009\uFF1B\u7559\u7A7A = \u4E0D\u9650\u3002\u53EA\u7528\u4E8E\u6821\u9A8C\u8BF7\u6C42\u4F20\u5165\u7684\u7FA4\u662F\u5426\u88AB\u5141\u8BB8\u3002","connectors.dynamicHint":'<b>\u52A8\u6001\u6A21\u5F0F</b>\uFF1A\u7FA4 ID \u968F\u6BCF\u6B21\u8BF7\u6C42\u4F20\u5165\uFF0C\u4E09\u9009\u4E00 \u2014\u2014 \u67E5\u8BE2\u53C2\u6570 <code>?chatId=<\u7FA4ID></code> \xB7 \u8BF7\u6C42\u5934 <code>x-botmux-chat-id: <\u7FA4ID></code> \xB7 \u8BF7\u6C42\u4F53 <code>{"chatId":"<\u7FA4ID>"}</code>\u3002<br>\u60F3"\u4E00\u4E2A URL \u76F4\u63A5\u89E6\u53D1\u3001\u4E0D\u5E26\u53C2\u6570"\uFF0C\u8BF7\u6539\u9009\u300C\u56FA\u5B9A\u7FA4\u300D\u3002',"connectors.fDedup":"\u53BB\u91CD\u5B57\u6BB5","connectors.fDedupPh":"\u5982 alert.id\uFF08\u4ECE\u4E8B\u4EF6 body \u53D6\u503C\uFF09","connectors.dedupHint":"\u586B\u4E86\uFF1A\u547D\u4E2D\u76F8\u540C\u503C\u7684\u4E8B\u4EF6\u90FD\u6295\u5230<b>\u540C\u4E00\u4E2A\u7FA4</b>\u3002\u7559\u7A7A\uFF1A\u6BCF\u4E2A\u4E8B\u4EF6<b>\u65B0\u5EFA\u4E00\u4E2A\u7FA4</b>\u3002","connectors.fInstruction":"\u5904\u7406\u6307\u4EE4","connectors.fInstructionPh":"\u4E8B\u4EF6\u89E6\u53D1\u65F6\u8BA9\u673A\u5668\u4EBA\u505A\u4EC0\u4E48\u3002\u5982\uFF1A\u603B\u7ED3\u8FD9\u6761\u544A\u8B66\u7684\u4E25\u91CD\u7A0B\u5EA6\uFF0C@\u76F8\u5173 oncall\uFF0C\u7ED9\u51FA\u6392\u67E5\u5EFA\u8BAE\u3002\u7559\u7A7A = \u53EA\u628A\u4E8B\u4EF6\u539F\u6837\u4EA4\u7ED9\u6A21\u578B\u81EA\u7531\u53D1\u6325\u3002","connectors.fVerify":"\u6821\u9A8C\u65B9\u5F0F","connectors.verifyToken":"\u4EE4\u724C\uFF08\u7B80\u5355\uFF1A\u5BC6\u94A5\u653E\u8FDB URL\uFF0C\u4E00\u6761 curl \u5C31\u80FD\u89E6\u53D1\uFF09","connectors.verifyHmac":"HMAC \u7B7E\u540D\uFF08\u9AD8\u7EA7\uFF1A\u66F4\u5B89\u5168\uFF0C\u9700\u81EA\u884C\u5BF9\u8BF7\u6C42\u7B7E\u540D\uFF09","connectors.fSecret":"\u5BC6\u94A5 / \u4EE4\u724C","connectors.fSecretPh":"\u7559\u7A7A\u81EA\u52A8\u751F\u6210\uFF08\u53EA\u663E\u793A\u4E00\u6B21\uFF09","connectors.btnCreate":"\u521B\u5EFA","connectors.listTitle":"\u5DF2\u6709 Webhook","connectors.loading":"\u52A0\u8F7D\u4E2D\u2026","connectors.noBotGroups":"\uFF08\u8BE5\u673A\u5668\u4EBA\u6682\u65E0\u53EF\u89C1\u7FA4\uFF0C\u70B9\u53F3\u4FA7\u624B\u52A8\u586B ID\uFF09","connectors.modeLabelFixed":"\u56FA\u5B9A\u7FA4","connectors.modeLabelNewGroup":"\u6BCF\u6B21\u65B0\u5EFA\u7FA4","connectors.modeLabelDynamic":"\u8BF7\u6C42\u6307\u5B9A\u7FA4","connectors.kindLabelWorkflow":"\u5DE5\u4F5C\u6D41","connectors.kindLabelTurn":"\u5355\u8F6E","connectors.count":"\xB7 {count} \u4E2A","connectors.empty":"\u8FD8\u6CA1\u6709 Webhook\u3002\u7528\u4E0A\u9762\u7684\u8868\u5355\u521B\u5EFA\u4E00\u4E2A\u3002","connectors.enabled":"\u5DF2\u542F\u7528","connectors.disabled":"\u5DF2\u505C\u7528","connectors.badgeToken":"\u4EE4\u724C","connectors.badgeSign":"\u7B7E\u540D","connectors.dest":"\u6295\u9012\u300C{name}\u300D","connectors.btnDisable":"\u505C\u7528","connectors.btnEnable":"\u542F\u7528","connectors.btnEdit":"\u7F16\u8F91","connectors.btnSave":"\u4FDD\u5B58","connectors.btnCancel":"\u53D6\u6D88","connectors.btnDel":"\u5220\u9664","connectors.webhookUrl":"Webhook URL\uFF1A","connectors.copy":"\u590D\u5236","connectors.copied":"\u5DF2\u590D\u5236","connectors.tokenHint":"\u4EE4\u724C\u6A21\u5F0F\uFF1A\u8C03\u7528\u65F6\u5728 URL \u672B\u5C3E\u8FFD\u52A0 <code>/<\u4EE4\u724C></code>\uFF08\u4EE4\u724C\u4EC5\u521B\u5EFA/\u8F6E\u6362\u65F6\u663E\u793A\u4E00\u6B21\uFF09\u3002","connectors.dynamicReqHint":'\u52A8\u6001\u6A21\u5F0F\uFF1A\u8BF7\u6C42\u9700\u5E26\u76EE\u6807\u7FA4 \u2014\u2014 <code>?chatId=<\u7FA4ID></code> \u6216\u5934 <code>x-botmux-chat-id</code> \u6216 body <code>{"chatId":"\u2026"}</code>\u3002',"connectors.instructionPrefix":"\u5904\u7406\u6307\u4EE4\uFF1A","connectors.delConfirm":"\u5220\u9664\u8FD9\u4E2A Webhook\uFF1F\u5B83\u7684 URL \u4F1A\u7ACB\u5373\u5931\u6548\u3002","connectors.errName":"\u8BF7\u586B\u540D\u79F0","connectors.errBot":"\u8BF7\u9009\u673A\u5668\u4EBA","connectors.errWf":"\u8BF7\u586B\u5DE5\u4F5C\u6D41 ID","connectors.errChat":"\u8BF7\u9009\u62E9\uFF08\u6216\u624B\u52A8\u586B\uFF09\u6295\u9012\u7684\u7FA4","connectors.creating":"\u521B\u5EFA\u4E2D\u2026","connectors.saving":"\u4FDD\u5B58\u4E2D\u2026","connectors.usageDynamicLede":"\u52A8\u6001\u6A21\u5F0F\uFF1AURL \u5DF2\u542B\u4EE4\u724C\uFF0C\u8C03\u7528\u65F6\u518D\u5E26\u4E0A\u76EE\u6807\u7FA4 ID{gn}\uFF1A","connectors.usageDynamicNote":'\u7FA4\u4E5F\u53EF\u653E\u8BF7\u6C42\u5934 <code>x-botmux-chat-id</code> \u6216 body <code>{"chatId":"\u2026"}</code>\u3002\u26A0\uFE0F URL \u5373\u51ED\u8BC1\uFF0C\u52FF\u6CC4\u6F0F\u3002',"connectors.usageTokenLede":"\u6B64 URL \u5DF2\u542B\u4EE4\u724C\u3001\u4E14\u56FA\u5B9A\u6295\u9012\u5230\u6240\u9009\u7FA4\uFF0C\u76F4\u63A5 POST \u5373\u53EF\u89E6\u53D1\uFF1A","connectors.usageTokenNote":"\u26A0\uFE0F URL \u5373\u51ED\u8BC1\uFF0C\u8BF7\u52FF\u516C\u5F00\u6CC4\u6F0F\uFF1B\u53EF\u5728\u4E0B\u65B9\u5217\u8868\u5220\u9664\u6216\u8F6E\u6362\u3002","connectors.usageHmac":"\u5916\u90E8\u7CFB\u7EDF\u9700\u5BF9 <code>timestamp.body</code> \u505A HMAC-SHA256 \u7B7E\u540D\uFF0C\u5E76\u5E26\u4E0A <code>x-botmux-timestamp</code> / <code>x-botmux-nonce</code> / <code>x-botmux-signature</code> \u5934\u8C03\u7528","connectors.usageHmacDynamic":"\uFF0C\u540C\u65F6\u6309\u4E0A\u9762\u65B9\u5F0F\u5E26\u76EE\u6807\u7FA4 ID","connectors.createdPrefix":"\u5DF2\u521B\u5EFA\u300C{name}\u300D","connectors.createdDest":"\u6295\u9012\u5230\u300C{name}\u300D","connectors.tokenLabel":"\u8BBF\u95EE\u4EE4\u724C","connectors.signLabel":"\u7B7E\u540D\u5BC6\u94A5","connectors.secretOnce":"\uFF08\u53EA\u663E\u793A\u8FD9\u4E00\u6B21\uFF0C\u8BF7\u4FDD\u5B58\uFF09\uFF1A","connectors.createFailed":"\u521B\u5EFA\u5931\u8D25\uFF1A{error}","connectors.saveFailed":"\u4FDD\u5B58\u5931\u8D25\uFF1A{error}","connectors.noOnlineBots":"\uFF08\u6CA1\u6709\u5728\u7EBF\u673A\u5668\u4EBA\uFF09","team.navHome":"\u6211\u7684\u56E2\u961F","team.navManage":"\u56E2\u961F\u7BA1\u7406","team.eyebrow":"\u56E2\u961F","team.homeTitle":"\u56E2\u961F\u534F\u4F5C\uFF08\u8DE8\u90E8\u7F72\uFF09","team.homeLede":"\u628A\u522B\u7684\u90E8\u7F72\uFF08\u540C\u4E8B\u81EA\u5DF1\u8DD1\u7684 botmux\uFF09\u9080\u8BF7\u8FDB\u540C\u4E00\u4E2A\u56E2\u961F\uFF0C\u4E92\u76F8\u53D1\u73B0\u673A\u5668\u4EBA\u3001\u534F\u4F5C\u62C9\u7FA4\u3002","team.localDeployTitle":"\u672C\u90E8\u7F72","team.myIdentity":"\u6211\u7684\u98DE\u4E66\u8EAB\u4EFD\uFF1A","team.unbound":"\u672A\u7ED1\u5B9A","team.bindBtn":"\u7ED1\u5B9A","team.bindHint":"\uFF08\u7528\u673A\u5668\u4EBA\u51ED\u8BC1\u81EA\u52A8\u8BC6\u522B\u4F60\uFF1B\u7ED1\u5B9A\u540E\u62C9\u7FA4\u4F1A\u628A\u4F60\u62C9\u8FDB\u7FA4\u3001\u673A\u5668\u4EBA\u4E5F\u5F52\u5230\u4F60\u540D\u4E0B\uFF09","team.myTeams":"\u6211\u7684\u56E2\u961F","team.searchPh":"\u641C\u7D22 \u540D\u79F0/\u80FD\u529B/CLI\u2026","team.allCli":"\u5168\u90E8 CLI","team.hasCap":"\u6709\u80FD\u529B\u6807\u7B7E","team.hasRole":"\u6709\u9ED8\u8BA4\u89D2\u8272","team.teamsHint":"\u6BCF\u4E2A\u56E2\u961F\u91CC\u52FE\u9009\u673A\u5668\u4EBA\u5373\u53EF\u5355\u72EC\u62C9\u7FA4\uFF08\u81EA\u52A8\u5E26\u4E0A\u5404\u81EA\u8D1F\u8D23\u4EBA\uFF09\u3002\u8981\u65B0\u5EFA\u56E2\u961F / \u751F\u6210\u9080\u8BF7\u7801 / \u52A0\u5165\u522B\u4EBA\u7684\u56E2\u961F\uFF0C\u53BB\u300C\u56E2\u961F\u7BA1\u7406\u300D\u3002","team.loading":"\u52A0\u8F7D\u4E2D\u2026","team.roleModalTitle":"\u9ED8\u8BA4\u89D2\u8272","team.roleModalHint":"\u8BE5\u673A\u5668\u4EBA\u7684\u9ED8\u8BA4\u4EBA\u8BBE\uFF08\u8DE8\u7FA4\u751F\u6548\uFF09\uFF0C\u6B64\u5904\u53EA\u8BFB\u3002\u5982\u9700\u4FEE\u6539\uFF0C\u8BF7\u5230\u300CBot \u914D\u7F6E\u300D\u9875\u3002","team.close":"\u5173\u95ED","team.tagLocal":"\u672C\u90E8\u7F72","team.tagRemoteStale":"\u8FDC\u7AEF\xB7\u79BB\u7EBF\uFF1F","team.tagRemote":"\u8FDC\u7AEF","team.removeMember":"\u79FB\u9664","team.depTag":"\uFF08{tag}\uFF09","team.depCount":"{count} \u4E2A","team.depSelected":"\uFF0C\u5DF2\u9009 {n}","team.capPh":"\u80FD\u529B\u6807\u7B7E\u2026","team.viewRole":"\u67E5\u770B","team.hasRoleShort":"\u6709\u89D2\u8272","team.noMatch":"\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u673A\u5668\u4EBA\u3002","team.gnamePh":"\u7FA4\u540D\uFF08\u5982\uFF1A\u8DE8\u56E2\u961F\u6392\u969C\uFF09","team.pullGroupBtn":"\u628A\u52FE\u9009\u7684\u673A\u5668\u4EBA\u62C9\u4E00\u4E2A\u7FA4","team.pullGroupHint":"\u52FE\u9009\u673A\u5668\u4EBA \u2192 \u62C9\u5230\u4E00\u4E2A\u98DE\u4E66\u7FA4\uFF08\u81EA\u52A8\u542B owner\uFF09","team.noTeams":"\u8FD8\u6CA1\u6709\u56E2\u961F\u3002\u53BB\u300C\u56E2\u961F\u7BA1\u7406\u300D\u751F\u6210\u9080\u8BF7\u7801\u8BA9\u522B\u4EBA\u52A0\u5165\u4F60\uFF0C\u6216\u52A0\u5165\u522B\u4EBA\u7684\u56E2\u961F\u3002","team.connected":"\u5DF2\u8FDE\u63A5","team.connectFail":"\u8FDE\u63A5\u5931\u8D25\uFF1A{error}","team.iHost":"\u6211\u6258\u7BA1","team.teamMeta":"{deps} \u4E2A\u90E8\u7F72 \xB7 {bots} \u4E2A\u673A\u5668\u4EBA","team.rosterFail":"\u65E0\u6CD5\u83B7\u53D6\u8BE5\u56E2\u961F\u82B1\u540D\u518C\u3002","team.acrossTeams":"\uFF08\u8DE8 {n} \u4E2A\u56E2\u961F\uFF0C\u53BB\u91CD\uFF09","team.botsWord":"\u4E2A\u673A\u5668\u4EBA","team.groupCreated":"\u7FA4\u5DF2\u521B\u5EFA","team.delegatedBy":"\uFF08\u7531\u300C{name}\u300D\u5EFA\u7FA4\uFF09","team.openInLark":"\u5728\u98DE\u4E66\u6253\u5F00","team.invalidBots":"\u672A\u52A0\u5165\u7684\u673A\u5668\u4EBA\uFF1A{ids}","team.invalidOwners":"{n} \u4E2A owner \u672A\u80FD\u62C9\u8FDB","team.missingIdentity":"\u4F60\u672A\u7ED1\u5B9A\u98DE\u4E66\u8EAB\u4EFD\uFF0C\u6CA1\u628A\u4F60\u81EA\u5DF1\u62C9\u8FDB\u7FA4\uFF08\u53BB\u300C\u6211\u7684\u56E2\u961F\u300D\u7ED1\u5B9A\uFF09","team.skippedNoOwner":"{n} \u4E2A\u673A\u5668\u4EBA\u56E0\u8D1F\u8D23\u4EBA\u672A\u7ED1\u5B9A\u8EAB\u4EFD\u88AB\u8DF3\u8FC7\uFF08\u672A\u52A0\u5165\u7FA4\uFF09","team.errNoLocalBot":"\u8BF7\u81F3\u5C11\u52FE\u9009\u4E00\u4E2A\u4F60\u81EA\u5DF1\uFF08\u672C\u90E8\u7F72\uFF09\u7684\u5728\u7EBF\u673A\u5668\u4EBA\u2014\u2014\u7FA4\u8981\u7531\u5B83\u521B\u5EFA\u5E76\u628A\u4F60\uFF08\u53D1\u8D77\u4EBA\uFF09\u62C9\u8FDB\u7FA4\u3002","team.errAllSkipped":"\u6240\u9009\u673A\u5668\u4EBA\u7684\u8D1F\u8D23\u4EBA\u90FD\u6CA1\u7ED1\u5B9A\u8EAB\u4EFD\uFF0C\u65E0\u6CD5\u62C9\u7FA4\uFF08\u673A\u5668\u4EBA\u4E0D\u80FD\u8FDB\u4E00\u4E2A owner \u4E0D\u5728\u7684\u7FA4\uFF09\u3002\u8BF7\u8BA9\u5BF9\u5E94\u90E8\u7F72\u5148\u7ED1\u5B9A\u8EAB\u4EFD\u3002","team.errNoCreator":"\u6CA1\u6709\u53EF\u7528\u7684\u5EFA\u7FA4\u53D1\u8D77\u65B9\uFF08\u76F8\u5173\u90E8\u7F72\u90FD\u6CA1\u6709\u5728\u7EBF\u673A\u5668\u4EBA\uFF0C\u6216\u4E0D\u53EF\u8FBE\uFF09","team.errDelegationTimeout":"\u59D4\u6258\u5BF9\u65B9\u90E8\u7F72\u5EFA\u7FA4\u8D85\u65F6\uFF08\u53EF\u80FD\u5DF2\u5EFA\uFF0C\u53BB\u98DE\u4E66\u786E\u8BA4\uFF0C\u52FF\u91CD\u590D\u70B9\uFF09","team.errGroupCreate":"\u5EFA\u7FA4\u5931\u8D25\uFF1A{error}","team.roleModalTitleName":"\u9ED8\u8BA4\u89D2\u8272 \xB7 {name}","team.bound":"\u5DF2\u7ED1\u5B9A","team.myHostedTeam":"\u6211\u6258\u7BA1\u7684\u56E2\u961F","team.remoteTeamLabel":"{name} \u7684\u56E2\u961F","team.manageTitle":"\u56E2\u961F\u7BA1\u7406","team.manageLede":"\u521B\u5EFA\u591A\u4E2A\u56E2\u961F\u3001\u7ED9\u6BCF\u4E2A\u56E2\u961F\u751F\u6210\u9080\u8BF7\u7801\u3001\u6216\u52A0\u5165\u522B\u4EBA\u7684\u56E2\u961F\u3002\u4E00\u4E2A\u56E2\u961F = \u4F60\u672C\u90E8\u7F72\u7684\u673A\u5668\u4EBA + \u52A0\u5165\u8BE5\u56E2\u961F\u7684\u5176\u5B83\u90E8\u7F72\u3002","team.hostedTitle":"\u6211\u6258\u7BA1\u7684\u56E2\u961F","team.newTeamPh":"\u65B0\u56E2\u961F\u540D\u79F0","team.createTeamBtn":"\u521B\u5EFA\u56E2\u961F","team.joinTitle":"\u52A0\u5165\u522B\u4EBA\u7684\u56E2\u961F","team.hubPh":"Hub \u5730\u5740\uFF0C\u5982 http://10.0.0.5:7891","team.codePh":"\u9080\u8BF7\u7801","team.joinBtn":"\u52A0\u5165","team.noTeamsShort":"\u8FD8\u6CA1\u6709\u56E2\u961F\u3002","team.default":"\u9ED8\u8BA4","team.manageMetaDeps":"{count} \u4E2A\u90E8\u7F72","team.manageMetaRemote":"\uFF08\u542B {r} \u8FDC\u7AEF\uFF09","team.manageMetaBots":"{count} \u4E2A\u673A\u5668\u4EBA","team.genInvite":"\u751F\u6210\u9080\u8BF7\u7801","team.delBtn":"\u5220\u9664","team.generating":"\u751F\u6210\u4E2D\u2026","team.inviteResultLede":"\u628A\u4E0B\u9762\u4E24\u9879\u53D1\u7ED9\u522B\u7684\u90E8\u7F72\u7684\u4EBA\uFF0824 \u5C0F\u65F6\u5185\u3001\u5355\u6B21\u6709\u6548\uFF09\uFF1A","team.inviteHub":"Hub \u5730\u5740\uFF1A","team.inviteCode":"\u9080\u8BF7\u7801\uFF1A","team.genFail":"\u751F\u6210\u5931\u8D25\u3002","team.delConfirm":"\u5220\u9664\u56E2\u961F\u300C{name}\u300D\uFF1F\u5DF2\u52A0\u5165\u5B83\u7684\u90E8\u7F72\u4F1A\u88AB\u79FB\u9664\uFF08\u4E0D\u5F71\u54CD\u4ED6\u4EEC\u81EA\u5DF1\u7684\u90E8\u7F72\uFF09\u3002","team.errName":"\u8BF7\u586B\u56E2\u961F\u540D\u79F0","team.creating":"\u521B\u5EFA\u4E2D\u2026","team.created":"\u5DF2\u521B\u5EFA","team.createFail":"\u521B\u5EFA\u5931\u8D25\uFF1A{error}","team.errHubCode":"\u8BF7\u586B Hub \u5730\u5740\u548C\u9080\u8BF7\u7801\u3002","team.joining":"\u52A0\u5165\u4E2D\u2026","team.joined":"\u5DF2\u52A0\u5165\u300C{name}\u300D\uFF0C\u53BB\u300C\u6211\u7684\u56E2\u961F\u300D\u67E5\u770B\u3002","team.joinErrSelf":"\u8FD9\u662F\u4F60\u81EA\u5DF1\u7684\u90E8\u7F72\uFF0C\u4E0D\u80FD\u52A0\u5165\u81EA\u5DF1\uFF08\u9080\u8BF7\u7801\u8981\u53D1\u7ED9\u522B\u7684\u90E8\u7F72\u7684\u4EBA\u7528\uFF09","team.joinErrAlready":"\u4F60\u7684\u90E8\u7F72\u5DF2\u7ECF\u52A0\u5165\u8FC7\u8FD9\u4E2A\u56E2\u961F\u4E86","team.joinErrUnreachable":"\u8FDE\u4E0D\u4E0A\u5BF9\u65B9 Hub\uFF08\u68C0\u67E5\u5730\u5740/\u7F51\u7EDC\uFF09","team.joinErrTimeout":"\u5BF9\u65B9 Hub \u54CD\u5E94\u8D85\u65F6","team.joinErrGeneric":"\u52A0\u5165\u5931\u8D25\uFF1A{error}","team.identifying":"\u8BC6\u522B\u4E2D\u2026","team.bound2":"\u5DF2\u7ED1\u5B9A\uFF1A{name}","team.multiCandidate":"\u8BC6\u522B\u5230\u591A\u4E2A\u5019\u9009\uFF0C\u70B9\u4F60\u81EA\u5DF1\uFF1A","team.binding":"\u7ED1\u5B9A\u4E2D\u2026","team.bindFail":"\u7ED1\u5B9A\u5931\u8D25\uFF1A{error}","team.noCandidates":"\u6CA1\u8BC6\u522B\u5230\u8EAB\u4EFD\uFF1A\u8BF7\u786E\u8BA4\u673A\u5668\u4EBA\u914D\u7F6E\u4E86 allowedUsers\uFF08\u5141\u8BB8\u4F7F\u7528\u8005\uFF09\uFF0C\u4E14\u673A\u5668\u4EBA\u6709\u901A\u8BAF\u5F55\u6743\u9650\u3002","team.removeMemberConfirm":"\u628A\u300C{name}\u300D\u79FB\u51FA\u8FD9\u4E2A\u56E2\u961F\uFF1F\u5B83\u7684\u673A\u5668\u4EBA\u5C06\u4ECE\u672C\u56E2\u961F\u82B1\u540D\u518C\u6D88\u5931\uFF08\u4E0D\u5F71\u54CD\u5BF9\u65B9\u81EA\u5DF1\u7684\u90E8\u7F72\uFF09\u3002","team.creatingGroup":"\u5EFA\u7FA4\u4E2D\u2026","team.defaultGroupName":"\u534F\u4F5C\u7FA4","team.errPickBot":"\u8BF7\u5148\u52FE\u9009\u81F3\u5C11\u4E00\u4E2A\u673A\u5668\u4EBA","sessions.closeBulkConfirm":"\u5173\u95ED\u9009\u4E2D\u7684 {count} \u4E2A\u4F1A\u8BDD\uFF1F","sessions.empty":"\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u4F1A\u8BDD\u3002","sessions.viewMode":"\u4F1A\u8BDD\u89C6\u56FE","sessions.viewKanban":"\u770B\u677F","sessions.viewBoard":"\u72B6\u6001\u677F","sessions.viewTable":"\u8868\u683C","sessions.selectSession":"\u9009\u62E9\u4F1A\u8BDD","sessions.board.needsYou":"\u9700\u8981\u4F60","sessions.board.needsYouHint":"\u7B49\u5F85\u4ED3\u5E93\u3001TUI \u9009\u62E9\u6216\u989D\u5EA6\u5904\u7406","sessions.board.starting":"\u542F\u52A8\u4E2D","sessions.board.startingHint":"CLI \u6B63\u5728\u521B\u5EFA\u6216\u6062\u590D","sessions.board.working":"\u5E72\u6D3B\u4E2D","sessions.board.workingHint":"\u6B63\u5728\u8F93\u51FA\u3001\u5206\u6790\u6216\u6267\u884C\u5DE5\u5177","sessions.board.idle":"\u7A7A\u95F2","sessions.board.idleHint":"\u53EF\u7EE7\u7EED\u5BF9\u8BDD\u6216\u63A5\u65B0\u4EFB\u52A1","sessions.board.emptyColumn":"\u6682\u65E0\u4F1A\u8BDD","sessions.board.signalRepo":"\u5F85\u9009\u4ED3\u5E93","sessions.board.signalPrompt":"\u7B49\u5F85 TUI \u9009\u62E9","sessions.board.signalLimited":"\u989D\u5EA6\u53D7\u9650","sessions.board.signalAgent":"\u9700\u8981\u4EBA\u5DE5\u4ECB\u5165","sessions.board.waiting":"\u7B49\u5F85","sessions.board.dragHint":"\u62D6\u52A8\u5217\u5934\u8C03\u6574\u5217\u987A\u5E8F","sessions.board.moveLeft":"\u5DE6\u79FB\u6B64\u5217","sessions.board.moveRight":"\u53F3\u79FB\u6B64\u5217","sessions.kanban.backlog":"\u5F85\u529E\u6C60","sessions.kanban.todo":"\u5F85\u529E","sessions.kanban.inProgress":"\u8FDB\u884C\u4E2D","sessions.kanban.inReview":"\u5F85\u786E\u8BA4","sessions.kanban.done":"\u5DF2\u5B8C\u6210","sessions.kanban.updated":"\u66F4\u65B0\u4E8E {time}","sessions.kanban.moreHidden":"\u8FD8\u6709 {count} \u4E2A\u672A\u663E\u793A","sessions.create.button":"\u521B\u5EFA\u4F1A\u8BDD","sessions.create.title":"\u521B\u5EFA\u4F1A\u8BDD","sessions.create.content":"\u5185\u5BB9","sessions.create.contentPlaceholder":"\u63CF\u8FF0\u8981\u505A\u7684\u4E8B\uFF1BLead \u5206\u914D\u6A21\u5F0F\u4E0B\u53EF\u5728\u8FD9\u91CC\u7ED9\u5404 agent \u5206\u914D\u4E0D\u540C\u7684\u5DE5\u4F5C","sessions.create.bots":"\u673A\u5668\u4EBA\uFF08\u62C9\u8FDB\u65B0\u7FA4\uFF09","sessions.create.noBots":"\u6CA1\u6709\u5728\u7EBF\u7684\u673A\u5668\u4EBA\u53EF\u9009","sessions.create.mode":"\u534F\u4F5C\u6A21\u5F0F","sessions.create.modeAll":"\u4E00\u8D77\u5F00\u5DE5","sessions.create.modeLead":"Lead \u5206\u914D\uFF08\u63A8\u8350\uFF09","sessions.create.modeHelp":"\u4E00\u8D77\u5F00\u5DE5\uFF1A\u6BCF\u4E2A\u88AB\u9009\u673A\u5668\u4EBA\u5404\u8D77\u4E00\u6761\u4F1A\u8BDD\u3001\u62FF\u540C\u4E00\u4EFD\u5185\u5BB9\u3002Lead \u5206\u914D\uFF1A\u53EA\u8D77 lead\uFF0C\u7531\u5B83\u5728\u7FA4\u91CC @ \u62C9\u8D77\u5176\u5B83\u673A\u5668\u4EBA\u5E72\u6D3B\u3002","sessions.create.lead":"Lead \u673A\u5668\u4EBA","sessions.create.leadHelp":"\u5185\u5BB9\u4F1A\u53D1\u7ED9 lead\uFF0C\u7531\u5B83\u51B3\u5B9A\u4F55\u65F6\u62C9\u8D77\u54EA\u4E2A sub bot\u3002","sessions.create.leadPickFirst":"\u8BF7\u5148\u5728\u4E0A\u65B9\u52FE\u9009\u673A\u5668\u4EBA","sessions.create.column":"\u5165\u5217","sessions.create.columnInProgress":"\u76F4\u63A5\u8FDB\u884C\u4E2D","sessions.create.columnBacklog":"\u5F85\u529E\u6C60","sessions.create.columnHelp":"\u76F4\u63A5\u8FDB\u884C\u4E2D\uFF1A\u5EFA\u5B8C\u7FA4\u7ACB\u523B\u5F00\u8DD1\u3002\u5F85\u529E\u6C60\uFF1A\u5148\u5EFA\u7FA4+\u62C9\u673A\u5668\u4EBA\u4F46\u4E0D\u8D77 CLI\uFF0C\u4E4B\u540E\u62D6\u5230\u300C\u8FDB\u884C\u4E2D\u300D\u6216\u70B9\u300C\u5F00\u59CB\u300D\u518D\u53D1\u7ED9\u673A\u5668\u4EBA\u3002","sessions.create.advanced":"\u66F4\u591A\u9009\u9879","sessions.create.groupName":"\u7FA4\u540D\u79F0","sessions.create.groupNamePlaceholder":"\u7559\u7A7A\u5219\u53D6\u5185\u5BB9\u9996\u884C","sessions.create.workingDir":"\u5DE5\u4F5C\u76EE\u5F55","sessions.create.workingDirHelp":"\u53EF\u9009\u3002\u586B\u4E86\u5219\u628A\u65B0\u7FA4\u7ED1\u5B9A\u5230\u8BE5\u76EE\u5F55\uFF08\u6240\u6709\u673A\u5668\u4EBA\u90FD\u5728\u6B64\u76EE\u5F55\u5DE5\u4F5C\uFF09\u3002\u7559\u7A7A\u5219\u673A\u5668\u4EBA\u5728\u7FA4\u91CC\u5F39 /repo \u5361\u7247\u8BA9\u4F60\u9009\u4ED3\u5E93\uFF08\u652F\u6301\u65B0\u5EFA worktree\uFF09\u3002","sessions.create.submit":"\u521B\u5EFA","sessions.create.submitting":"\u521B\u5EFA\u4E2D\u2026","sessions.create.cancel":"\u53D6\u6D88","sessions.create.start":"\u5F00\u59CB","sessions.create.errContent":"\u8BF7\u586B\u5199\u5185\u5BB9","sessions.create.errNoBot":"\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u673A\u5668\u4EBA","sessions.create.errLead":"Lead \u5FC5\u987B\u662F\u5DF2\u52FE\u9009\u7684\u673A\u5668\u4EBA\u4E4B\u4E00","sessions.create.failed":"\u521B\u5EFA\u5931\u8D25","sessions.create.startFailed":"\u5F00\u59CB\u5931\u8D25","sessions.create.doneTitle":"\u5DF2\u521B\u5EFA","sessions.create.doneInProgress":"\u5DF2\u5EFA\u7FA4\u5E76\u62C9\u8D77\u4F1A\u8BDD","sessions.create.doneBacklog":"\u5DF2\u5EFA\u7FA4\uFF0C\u4F1A\u8BDD\u5DF2\u5165\u5F85\u529E\u6C60","sessions.create.partialFail":"\u6709 {n} \u4E2A\u673A\u5668\u4EBA\u672A\u80FD\u62C9\u8D77\uFF0C\u53EF\u7A0D\u540E\u5728\u7FA4\u91CC @ \u91CD\u8BD5","sessions.create.openChat":"\u6253\u5F00\u98DE\u4E66\u7FA4","sessions.create.close":"\u5173\u95ED","sessions.kanban.openTab":"\u65B0\u6807\u7B7E\u9875\u6253\u5F00","sessions.kanban.openFeishu":"\u6253\u5F00\u98DE\u4E66","sessions.kanban.terminalLoading":"\u6B63\u5728\u6253\u5F00\u7EC8\u7AEF\u2026","sessions.kanban.rename":"\u91CD\u547D\u540D\uFF08\u53CC\u51FB\u6807\u9898\u4E5F\u53EF\uFF09","sessions.kanban.renameFail":"\u91CD\u547D\u540D\u5931\u8D25","sessions.kanban.moveFail":"\u79FB\u52A8\u5931\u8D25","sessions.kanban.groupBy":"\u5206\u7EC4\u7EF4\u5EA6","sessions.kanban.groupFlow":"\u5DE5\u4F5C\u6D41","sessions.kanban.groupTeam":"\u56E2\u961F","sessions.kanban.groupBot":"\u673A\u5668\u4EBA","sessions.kanban.teamLoading":"\u6B63\u5728\u52A0\u8F7D\u56E2\u961F\u2026","sessions.kanban.noTeam":"\u6682\u65E0\u56E2\u961F","sessions.kanban.teamScope":"{chats} \u4E2A\u534F\u4F5C\u7FA4 \xB7 {sessions} \u4E2A\u4F1A\u8BDD","sessions.kanban.remoteHint":"\u6765\u81EA {name} \u90E8\u7F72\u7684\u4F1A\u8BDD\uFF08\u5FEB\u7167\uFF0C\u7EC8\u7AEF/\u5386\u53F2\u5728\u5BF9\u65B9\u673A\u5668\u4E0A\uFF09","sessions.kanban.clusterDragHint":"\u62D6\u52A8\u6807\u9898\u6574\u7EC4\u79FB\u52A8","sessions.history.title":"\u4F1A\u8BDD\u5386\u53F2","sessions.history.loading":"\u6B63\u5728\u62C9\u53D6\u98DE\u4E66\u6D88\u606F\u2026","sessions.history.fail":"\u5386\u53F2\u62C9\u53D6\u5931\u8D25","sessions.history.empty":"\u6CA1\u6709\u6D88\u606F","sessions.history.user":"\u7528\u6237","sessions.history.owner":"\u521B\u5EFA\u8005","sessions.history.staleHint":"dashboard \u6216 daemon \u8FDB\u7A0B\u53EF\u80FD\u8FD8\u5728\u8DD1\u65E7\u7248\u672C\uFF0Cbotmux restart \u540E\u91CD\u8BD5","groups.title":"\u7FA4\u7EC4\u4E0E Bot","groups.subtitle":"\u67E5\u770B chat x bot \u8986\u76D6\u77E9\u9635\uFF0C\u7BA1\u7406\u62C9\u7FA4\u3001oncall\u3001\u9000\u7FA4\u548C\u89E3\u6563\u3002","groups.search":"\u641C\u7D22\u7FA4\u540D / ID / owner","groups.missingOnly":"\u4EC5\u7F3A bot","groups.refresh":"\u5237\u65B0","groups.create":"\u65B0\u5EFA\u7FA4","groups.chat":"\u7FA4\u804A","groups.actions":"\u64CD\u4F5C","groups.addBots":"\u6DFB\u52A0 bot","groups.saveAsProfile":"\u4FDD\u5B58\u4E3A Profile","groups.manage":"\u7BA1\u7406","groups.empty":"\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u7FA4\u804A\u3002","groups.profileStatusFull":"\u5B8C\u6574\u5339\u914D {name}\uFF08{matched}/{total}\uFF09","groups.profileStatusFullChat":"\u672C\u7FA4 Role \u5B8C\u6574\u5339\u914D {name}\uFF08{matched}/{total}\uFF09","groups.profileStatusPartial":"\u90E8\u5206\u5339\u914D {name}\uFF08{matched}/{total}\uFF09","groups.profileStatusUnmatched":"\u672A\u5339\u914D\u4EFB\u4F55 Profile","groups.saveProfileTitle":"\u4FDD\u5B58\u4E3A Profile","groups.saveProfileIntro":"\u5C06\u300C{name}\u300D\u91CC\u7684 {count} \u4E2A\u7FA4\u5185 bot \u914D\u7F6E\u4FDD\u5B58\u4E3A profile \u5FEB\u7167\u3002","groups.saveProfileScope":"\u4FDD\u5B58\u8303\u56F4","groups.saveProfileScopeHelp":"\u7FA4\u5185 bot \u914D\u7F6E\u5FEB\u7167","groups.saveProfileBotCount":"\u7FA4\u5185 bot","groups.saveProfileLoadFailed":"\u8BFB\u53D6\u5931\u8D25","groups.saveProfileStatus.entry":"\u751F\u6210 entry","groups.saveProfileStatus.error":"\u8BFB\u53D6\u5931\u8D25","groups.saveProfileMode":"\u4FDD\u5B58\u65B9\u5F0F","groups.saveProfileNew":"\u65B0\u5EFA Profile","groups.saveProfileNewHelp":"\u9ED8\u8BA4\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u5FEB\u7167\uFF1B\u5982\u679C id \u5DF2\u5B58\u5728\uFF0C\u4F1A\u8986\u76D6\u540C bot entry\u3002","groups.saveProfileOverwrite":"\u8986\u76D6\u5DF2\u6709 Profile","groups.saveProfileOverwriteHelp":"\u4ECE\u5217\u8868\u4E2D\u9009\u62E9\u4E00\u4E2A\u5DF2\u6709 profile\uFF0C\u8986\u76D6\u5176\u4E2D\u540C bot \u7684 entry\u3002","groups.saveProfileExistingMeta":"{count} \u4E2A entry","groups.saveProfileIdLabel":"Profile id","groups.saveProfileExistingLabel":"\u5DF2\u6709 Profile","groups.saveProfileExistingEmpty":"\u6682\u65E0\u5DF2\u6709 Profile","groups.saveProfileTarget":"\u76EE\u6807 Profile","groups.saveProfileTargetNew":"\u5C06\u65B0\u5EFA\u6216\u66F4\u65B0\u8FD9\u4E2A Profile \u7684\u7FA4\u5185 bot \u5FEB\u7167","groups.saveProfileTargetOverwrite":"\u5C06\u8986\u76D6\u5DF2\u6709 Profile \u4E2D\u8FD9\u4E9B bot \u7684 entry","groups.saveProfileEntrySummary":"\u5C06\u4E3A {count} \u4E2A\u7FA4\u5185 bot \u751F\u6210 profile entry\u3002","groups.saveProfileEntrySummaryWithEmpty":"\u5C06\u4E3A {count} \u4E2A\u7FA4\u5185 bot \u751F\u6210 profile entry\uFF1B\u5176\u4E2D {emptyCount} \u4E2A\u5F53\u524D\u672A\u8BFB\u5230 role \u5185\u5BB9\uFF0C\u4F1A\u4FDD\u5B58\u4E3A\u7A7A entry\u3002","groups.saveProfileFailedLoadSummary":"\u6709 {count} \u4E2A bot \u914D\u7F6E\u8BFB\u53D6\u5931\u8D25\uFF0C\u6682\u4E0D\u4FDD\u5B58\uFF0C\u907F\u514D\u751F\u6210\u4E0D\u5B8C\u6574\u5FEB\u7167\u3002","groups.saveProfileSubmit":"\u4FDD\u5B58 Profile","groups.saveProfileOverwriteSubmit":"\u8986\u76D6\u4FDD\u5B58","groups.saveProfileInvalid":"Profile id \u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u4E0B\u5212\u7EBF\u3001\u77ED\u6A2A\u7EBF\uFF0C\u6700\u957F 64\uFF0C\u4E14\u4E0D\u80FD\u662F . \u6216 ..","groups.saveProfileNoRoles":"\u8FD9\u4E2A\u7FA4\u91CC\u6CA1\u6709\u53EF\u4FDD\u5B58\u7684 bot \u914D\u7F6E\u3002","groups.saveProfileSaving":"\u4FDD\u5B58\u4E2D\u2026","groups.saveProfileDone":"\u5DF2\u4FDD\u5B58 {count} \u4E2A entry \u5230 {name}","groups.saveProfileFailed":"\u53EA\u4FDD\u5B58\u4E86 {saved}/{total} \u4E2A entry\uFF0C\u8BF7\u68C0\u67E5\u79BB\u7EBF bot \u6216\u6743\u9650\u3002","groups.createTitle":"\u65B0\u5EFA\u7FA4\u804A","groups.createHelp":"\u9009\u62E9\u8981\u9080\u8BF7\u7684 bot\u3002dashboard \u4F1A\u81EA\u52A8\u9009\u62E9\u5728\u7EBF daemon \u4F5C\u4E3A\u521B\u5EFA\u8005\u3002","groups.name":"\u7FA4\u540D","groups.namePlaceholder":"\u4F8B\u5982 AI ChangeLog","groups.bindDir":"\u7ED1\u5B9A\u76EE\u5F55","groups.bindDirHelp":"\u65B0\u8BDD\u9898\u76F4\u63A5\u7528\u8BE5\u76EE\u5F55\u542F\u52A8 CLI\uFF0C\u8DF3\u8FC7 repo \u9009\u62E9\u3002","groups.roleProfile":"Profile","groups.roleProfileNone":"\u4E0D\u4F7F\u7528","groups.roleProfileHelp":"\u521B\u5EFA\u540E\u5728\u65B0\u7FA4\u91CC\u53D1\u9001 profile apply bootstrap \u547D\u4EE4\u3002","groups.roleProfileBootstrapSent":"Profile\uFF1A{name}\uFF1Bbootstrap \u6D88\u606F\u5DF2\u53D1\u9001\uFF1A{messageId}","groups.roleProfileBootstrapDone":"Profile\uFF1A{name}\uFF1Bbootstrap \u5DF2\u5B8C\u6210\uFF0C\u65E0\u9700\u53D1\u9001 peer bootstrap \u6D88\u606F\u3002","groups.roleProfileBootstrapFailed":"Profile\uFF1A{name}\uFF1Bbootstrap \u5931\u8D25\uFF1A{reason}","groups.botPicker":"Bot","groups.createSubmit":"\u521B\u5EFA","groups.cancel":"\u53D6\u6D88","groups.successTitle":"\u7FA4\u521B\u5EFA\u6210\u529F","groups.openGroup":"\u6253\u5F00\u65B0\u7FA4","groups.manageTitle":"\u7BA1\u7406 {name}","groups.owner":"\u7FA4\u4E3B","groups.oncall":"Oncall \u6A21\u5F0F","groups.oncallHelp":"\u5F00\u542F\u540E\uFF0C\u7FA4\u5185\u6210\u5458\u53EF @ \u673A\u5668\u4EBA\uFF1B\u52FE\u9009\u7684 bot \u5728\u672C\u7FA4\u7684\u65B0\u8BDD\u9898\u76F4\u63A5\u4F7F\u7528\u5176\u7ED1\u5B9A\u76EE\u5F55\uFF08\u7ED1\u5B9A\u6309 bot \u8BA1\uFF0C\u53EA\u5F71\u54CD\u52FE\u9009\u7684 bot\uFF09\u3002","groups.leaveTitle":"\u9009\u62E9\u673A\u5668\u4EBA\u9000\u51FA\u7FA4\u804A","groups.leaveSelected":"\u9009\u4E2D\u673A\u5668\u4EBA\u9000\u51FA\u7FA4\u804A","groups.disband":"\u89E3\u6563\u7FA4\u804A","groups.dangerHint":"\u89E3\u6563\u4EC5\u5F53\u5728\u7FA4\u673A\u5668\u4EBA\u662F\u7FA4\u4E3B\u65F6\u624D\u4F1A\u6210\u529F\uFF0C\u5426\u5219\u5EFA\u8BAE\u4F7F\u7528\u9000\u51FA\u7FA4\u804A\u3002","groups.save":"\u4FDD\u5B58","groups.needWorkingDir":"\u8BF7\u586B\u5DE5\u4F5C\u76EE\u5F55","groups.noBotsOnline":"\u6CA1\u6709\u5728\u7EBF bot\u3002\u8BF7\u5148\u91CD\u542F daemon\u3002","schedules.title":"\u5B9A\u65F6\u4EFB\u52A1","schedules.subtitle":"\u8DE8 daemon \u67E5\u770B\u3001\u6682\u505C\u3001\u6062\u590D\u548C\u7ACB\u5373\u89E6\u53D1\u5B9A\u65F6\u4EFB\u52A1\u3002","schedules.search":"\u641C\u7D22\u540D\u79F0 / prompt / \u5DE5\u4F5C\u76EE\u5F55","schedules.anyKind":"\u5168\u90E8\u7C7B\u578B","schedules.enabledOnly":"\u4EC5\u542F\u7528","schedules.name":"\u540D\u79F0","schedules.bot":"bot","schedules.schedule":"\u89C4\u5219","schedules.next":"\u4E0B\u6B21","schedules.last":"\u4E0A\u6B21","schedules.repeat":"\u91CD\u590D","schedules.enabled":"\u542F\u7528","schedules.actions":"\u64CD\u4F5C","schedules.runNow":"\u7ACB\u5373\u8FD0\u884C","schedules.pause":"\u6682\u505C","schedules.resume":"\u6062\u590D","schedules.delivery":"\u6295\u9012","schedules.deliveryOrigin":"\u539F\u8BDD\u9898","schedules.deliveryNewTopic":"\u6BCF\u6B21\u65B0\u8BDD\u9898","schedules.deliveryLocal":"\u4EC5\u8BB0\u5F55","schedules.useNewTopic":"\u6539\u4E3A\u6BCF\u6B21\u65B0\u8BDD\u9898","schedules.useOrigin":"\u6539\u4E3A\u539F\u8BDD\u9898","schedules.empty":"\u6682\u65E0\u5B9A\u65F6\u4EFB\u52A1\u3002","settings.title":"\u5168\u5C40\u8BBE\u7F6E","settings.subtitle":"\u7BA1\u7406\u672C\u673A botmux dashboard \u4E0E\u6240\u6709 bot \u5171\u4EAB\u7684\u5168\u5C40\u884C\u4E3A\u3002","settings.loading":"\u6B63\u5728\u52A0\u8F7D\u8BBE\u7F6E\u2026","settings.loadFailed":"\u8BBE\u7F6E\u52A0\u8F7D\u5931\u8D25","settings.readOnlyVisitor":"\u5F53\u524D\u662F\u53EA\u8BFB\u8BBF\u95EE\uFF0C\u4FEE\u6539\u8BBE\u7F6E\u9700\u8981\u6388\u6743\u94FE\u63A5\uFF08\u8FD0\u884C botmux dashboard \u83B7\u53D6\uFF09","settings.sectionAccess":"\u8BBF\u95EE\u6743\u9650","settings.publicReadOnly":"\u5141\u8BB8\u65E0 token \u53EA\u8BFB\u8BBF\u95EE dashboard","settings.publicReadOnlyHelp":"\u5F00\u542F\u540E\uFF0C\u6CA1\u6709 token \u7684\u8BBF\u95EE\u8005\u53EF\u4EE5\u67E5\u770B dashboard\u3001\u4F1A\u8BDD\u3001\u5B9A\u65F6\u4EFB\u52A1\u548C SSE\uFF1B\u5173\u95ED\u3001\u6682\u505C\u3001\u5BA1\u6279\u7B49\u5199\u64CD\u4F5C\u4ECD\u5FC5\u987B\u901A\u8FC7 token \u9274\u6743\u3002\u654F\u611F\u7EC8\u7AEF\u539F\u59CB\u65E5\u5FD7\u59CB\u7EC8\u9700\u8981 token\u3002","settings.remoteAccess":"\u8FDC\u7A0B\u8BBF\u95EE\u7EC8\u7AEF","settings.remoteAccessHelp":"\u5F00\u542F\u540E\u4F1A\u8BDD Web \u7EC8\u7AEF /\u98DE\u4E66\u5361\u7247\u300C\u6253\u5F00\u7EC8\u7AEF\u300D/\u300C\u83B7\u53D6\u53EF\u64CD\u4F5C\u94FE\u63A5\u300D\u53CA webhook \u90FD\u8D70\u4E2D\u5FC3\u5316\u5E73\u53F0\u94FE\u63A5\uFF1B\u5173\u95ED\u5219\u7528\u672C\u5730\u94FE\u63A5\u3002\u9ED8\u8BA4\u5173\u95ED\u3002","settings.sectionCards":"\u98DE\u4E66\u5361\u7247","settings.openTerminalInFeishu":"\u6D41\u5F0F\u5361\u7247\u7EC8\u7AEF\u6309\u94AE\u5728\u98DE\u4E66\u4FA7\u680F\u6253\u5F00","settings.openTerminalInFeishuHelp":"\u9ED8\u8BA4\u5173\u95ED\uFF1A\u7EC8\u7AEF\u6309\u94AE\u76F4\u63A5\u6253\u5F00 Web Terminal URL\u3002\u5F00\u542F\u540E\u4F7F\u7528\u98DE\u4E66 web_url/open \u5305\u88C5\uFF0C\u5728\u98DE\u4E66 PC \u4FA7\u680F\u91CC\u6253\u5F00\uFF1B\u5199\u6743\u9650\u4ECD\u7531\u7EC8\u7AEF token \u63A7\u5236\u3002","settings.sectionExperimental":"\u5B9E\u9A8C\u6027\u914D\u7F6E","settings.chatBotDiscovery":"\u7FA4\u5185\u673A\u5668\u4EBA\u53D1\u73B0\uFF08\u98DE\u4E66 /members/bots\uFF09","settings.chatBotDiscoveryHelp":"\u5F00\u542F\u540E\u7528\u98DE\u4E66 /members/bots \u63A5\u53E3\u5B9E\u65F6\u8BFB\u53D6\u5F53\u524D\u7FA4\u91CC\u7684\u673A\u5668\u4EBA\u6210\u5458\uFF0C\u8BA9\u591A\u4E2A\u673A\u5668\u4EBA\u4E4B\u95F4\u80FD\u53EF\u9760\u5730\u4E92\u76F8 @\uFF08\u9996\u6761\u6D88\u606F\u5C31\u80FD\u8BC6\u522B\uFF0C\u65E0\u9700\u7B49\u5386\u53F2 @ \u8BB0\u5F55\u79EF\u7D2F\uFF09\uFF0C\u591A\u673A\u5668\u4EBA\u534F\u4F5C\u66F4\u7A33\u3002\u8BE5\u63A5\u53E3\u662F\u98DE\u4E66\u672A\u516C\u5F00 API\uFF1A\u9ED8\u8BA4\u5F00\u542F\uFF0C\u8C03\u7528\u5931\u8D25\u4F1A\u81EA\u52A8\u56DE\u9000\u5230\u65E7\u7684\u53D1\u73B0\u65B9\u5F0F\uFF08\u6309\u914D\u7F6E\u7684 bot \u9010\u4E2A\u63A2\u6D4B + \u5386\u53F2 @ \u8BB0\u5F55\uFF09\u3002\u4EC5\u5728\u4EE5\u4E0B\u60C5\u51B5\u9700\u8981\u5173\u95ED\u5B83\uFF08\u5F3A\u5236\u8D70\u65E7\u903B\u8F91\uFF09\uFF1A\u4F60\u7684\u79DF\u6237/\u7F51\u5173\u4E0D\u652F\u6301\u8BE5\u63A5\u53E3\u3001\u6216\u5B83\u8FD4\u56DE\u7684\u7FA4\u6210\u5458\u4E0D\u51C6\u5BFC\u81F4 @ \u9519\u4EBA/@ \u4E0D\u5230\u3001\u6216\u98DE\u4E66\u6539\u52A8\u8BE5\u63A5\u53E3\u540E\u884C\u4E3A\u5F02\u5E38\u3002","settings.sectionRepoPicker":"\u4ED3\u5E93\u9009\u62E9","settings.repoPickerMode":"\u4ED3\u5E93\u9009\u62E9\u5361\u6A21\u5F0F","settings.repoPickerModeAll":"\u4ED3\u5E93 + worktree","settings.repoPickerModeRepos":"\u4EC5\u4E3B\u4ED3\u5E93","settings.repoPickerModeHelp":"\u9ED8\u8BA4\u663E\u793A\u4ED3\u5E93\u548C linked worktree\u3002\u9009\u62E9\u300C\u4EC5\u4E3B\u4ED3\u5E93\u300D\u540E\uFF0C\u521D\u59CB\u5316\u548C\u88F8 /repo \u7684\u9009\u62E9\u5361\u53EA\u5217\u4E3B\u4ED3\u5E93\uFF1B\u663E\u5F0F /repo /abs/path/to/worktree \u4ECD\u53EF\u76F4\u8FBE worktree\u3002","settings.saving":"\u4FDD\u5B58\u4E2D\u2026","settings.saved":"\u5DF2\u4FDD\u5B58","settings.saveFailed":"\u4FDD\u5B58\u5931\u8D25","settings.sectionMaintenance":"\u81EA\u52A8\u7EF4\u62A4","settings.autoUpdate":"\u81EA\u52A8\u66F4\u65B0","settings.autoUpdateHelp":"\u9ED8\u8BA4\u5173\u95ED\u3002\u5230\u70B9\u6267\u884C npm install -g botmux@latest \u5B89\u88C5\u6700\u65B0\u7248\u672C\uFF08\u53EA\u4E0B\u8F7D\u5B89\u88C5\u3001\u672C\u8EAB\u4E0D\u91CD\u542F\uFF09\u3002\u4EC5 npm \u5168\u5C40\u5B89\u88C5\u53EF\u7528\u3002","settings.autoRestart":"\u81EA\u52A8\u91CD\u542F","settings.autoRestartHelp":"\u9ED8\u8BA4\u5173\u95ED\uFF0C\u9700\u5148\u5F00\u542F\u81EA\u52A8\u66F4\u65B0\u3002\u81EA\u52A8\u66F4\u65B0\u88C5\u5230\u65B0\u7248\u672C\u540E\uFF0C\u82E5\u6CA1\u6709\u8FDB\u884C\u4E2D\u7684\u4F1A\u8BDD\u5219\u81EA\u52A8\u91CD\u542F\u4EE5\u751F\u6548\uFF08\u649E\u4E0A\u5FD9\u788C\u4F1A\u8BDD\u5219\u8DF3\u5230\u6B21\u65E5\uFF09\u3002","settings.autoUpdateLocalDev":"\u5F53\u524D\u4E3A\u672C\u5730\u5F00\u53D1\u5B89\u88C5\uFF08\u4ECE\u6E90\u7801\u8FD0\u884C\uFF09\uFF0C\u81EA\u52A8\u66F4\u65B0\u4E0D\u53EF\u7528\u3002","settings.maintenanceTime":"\u65F6\u95F4","update.section":"\u7248\u672C\u4E0E\u66F4\u65B0","update.loginRequired":"\u767B\u5F55\u540E\u53EF\u68C0\u67E5\u7248\u672C\u3001\u6267\u884C\u66F4\u65B0\u6216\u91CD\u542F\u3002","update.loading":"\u68C0\u67E5\u4E2D\u2026","update.checkFailed":"\u68C0\u67E5\u5931\u8D25","update.current":"\u5F53\u524D\u7248\u672C","update.upToDate":"\u5DF2\u662F\u6700\u65B0\u7248\u672C","update.newAvailable":"\u53D1\u73B0\u65B0\u7248\u672C {version}","update.checkUnavailable":"\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\uFF08\u79BB\u7EBF\u6216\u53D7\u7F51\u7EDC\u9650\u5236\uFF09","update.nodeWarn":"\u5F53\u524D Node \u7248\u672C {version} \u8FC7\u4F4E\uFF0C\u66F4\u65B0\u8981\u6C42 \u2265 {required}\uFF0C\u8BF7\u5148\u5347\u7EA7 Node\u3002","update.localDev":"\u5F53\u524D\u4E3A\u672C\u5730\u5F00\u53D1\u5B89\u88C5\uFF08\u4ECE\u6E90\u7801\u8FD0\u884C\uFF09\uFF0C\u300C\u66F4\u65B0\u5230\u6700\u65B0\u7248\u300D\u4E0D\u53EF\u7528\uFF1B\u8BF7\u7528 git pull + \u6784\u5EFA\u540E\u91CD\u542F\u3002","update.multiInstallWarn":"\u68C0\u6D4B\u5230\u591A\u4E2A botmux \u5B89\u88C5\uFF0Cnpm \u66F4\u65B0\u53EA\u4F1A\u66F4\u65B0 npm \u5168\u5C40\u90A3\u4E2A\uFF0C\u53EF\u80FD\u4E0D\u662F\u5F53\u524D\u751F\u6548\u7684\u7248\u672C\uFF1A","update.kindNpm":"npm \u5168\u5C40","update.kindSource":"\u6E90\u7801 checkout","update.kindUnknown":"\u672A\u77E5","update.btnCheck":"\u68C0\u67E5\u66F4\u65B0","update.btnChangelog":"\u67E5\u770B\u66F4\u65B0\u5185\u5BB9","update.btnChangelogHide":"\u6536\u8D77\u66F4\u65B0\u5185\u5BB9","update.btnUpdate":"\u66F4\u65B0\u5230\u6700\u65B0\u7248","update.btnRestart":"\u91CD\u542F botmux","update.changelogLoading":"\u52A0\u8F7D\u66F4\u65B0\u5185\u5BB9\u2026","update.changelogEmpty":"\u6CA1\u6709\u6BD4\u5F53\u524D\u7248\u672C\u66F4\u65B0\u7684\u53D1\u5E03\u8BF4\u660E\u3002","update.changelogFailed":"\u65E0\u6CD5\u52A0\u8F7D\u66F4\u65B0\u5185\u5BB9\uFF08\u79BB\u7EBF\u6216\u53D7\u7F51\u7EDC\u9650\u5236\uFF09\u3002","update.changelogRateLimited":"GitHub \u63A5\u53E3\u8BF7\u6C42\u8D85\u9650\uFF08\u672A\u767B\u5F55\u6BCF\u5C0F\u65F6\u6BCF IP 60 \u6B21\uFF0C\u5171\u4EAB\u7F51\u7EDC\u6613\u89E6\u53D1\uFF09\uFF0C\u6682\u65F6\u62FF\u4E0D\u5230\u66F4\u65B0\u5185\u5BB9\u3002","update.changelogViewOnGitHub":"\u524D\u5F80 GitHub Releases \u67E5\u770B","update.navBadgeTitle":"\u6709\u65B0\u7248\u672C {version}","update.confirmMultiInstall":`\u68C0\u6D4B\u5230\u591A\u4E2A botmux \u5B89\u88C5\uFF1A
|
|
2
|
-
{paths}
|
|
3
|
-
|
|
4
|
-
npm \u66F4\u65B0\u53EA\u4F1A\u66F4\u65B0 npm \u5168\u5C40\u90A3\u4E2A\uFF0C\u53EF\u80FD\u4E0D\u662F\u5F53\u524D\u751F\u6548\u7684\u7248\u672C\u3002\u4ECD\u8981\u7EE7\u7EED\uFF1F`,"update.confirmUpdate":"\u5C06\u8FD0\u884C npm install -g botmux@latest\uFF0C\u66F4\u65B0\u5230 {version}\u3002\u786E\u8BA4\u7EE7\u7EED\uFF1F","update.confirmUpdateNoVer":"\u5C06\u8FD0\u884C npm install -g botmux@latest \u66F4\u65B0\u5230\u6700\u65B0\u7248\u3002\u786E\u8BA4\u7EE7\u7EED\uFF1F","update.nodeTooOldAlert":"\u5F53\u524D Node \u7248\u672C {version} \u8FC7\u4F4E\uFF08\u8981\u6C42 \u2265 {required}\uFF09\uFF0C\u8BF7\u5148\u5347\u7EA7 Node \u518D\u66F4\u65B0\u3002","update.updating":"\u6B63\u5728\u66F4\u65B0\uFF08npm install -g botmux@latest\uFF09\uFF0C\u8BF7\u7A0D\u5019\u2026","update.updatedChanged":"\u5DF2\u66F4\u65B0 {old} \u2192 {new}\u3002","update.confirmRestart":"\u9700\u8981\u91CD\u542F botmux \u4EE5\u5E94\u7528\u65B0\u7248\u672C\u3002\u73B0\u5728\u91CD\u542F\uFF1F\uFF08\u6240\u6709\u4F1A\u8BDD\u4F1A\u51B7\u6062\u590D\uFF0C\u4EEA\u8868\u76D8\u4F1A\u77ED\u6682\u65AD\u5F00\u5E76\u81EA\u52A8\u91CD\u8FDE\uFF09","update.alreadyLatestRun":"\u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF08{version}\uFF09\uFF0C\u65E0\u9700\u66F4\u65B0\u3002","update.updateFailed":"\u66F4\u65B0\u5931\u8D25\uFF1A{detail}","update.noRestartHint":"\u66F4\u65B0\u5B8C\u6210\u3002\u7A0D\u540E\u8BF7\u624B\u52A8\u91CD\u542F\uFF08botmux restart\uFF09\u4EE5\u5E94\u7528\u65B0\u7248\u672C\u3002","update.confirmPlainRestart":"\u91CD\u542F botmux\uFF1F\u6240\u6709\u4F1A\u8BDD\u4F1A\u51B7\u6062\u590D\uFF0C\u4EEA\u8868\u76D8\u4F1A\u77ED\u6682\u65AD\u5F00\u5E76\u81EA\u52A8\u91CD\u8FDE\u3002","update.restarting":"\u6B63\u5728\u91CD\u542F botmux\uFF0C\u7B49\u5F85\u91CD\u8FDE\u2026","update.restartSlow":"\u91CD\u542F\u8017\u65F6\u8F83\u957F\uFF0C\u8BF7\u7A0D\u540E\u624B\u52A8\u5237\u65B0\u9875\u9762\u3002","update.restartFailed":"\u91CD\u542F\u5931\u8D25\uFF1A{detail}","skills.title":"Skill \u7BA1\u7406","skills.subtitle":"\u7BA1\u7406 botmux \u7684 CLI \u65E0\u5173 Skill \u8D44\u4EA7\uFF0C\u5E76\u6309 bot \u9009\u62E9\u4F18\u5148\u62AB\u9732\u3002","skills.installed":"\u5DF2\u5B89\u88C5 Skills","skills.installedHelp":"\u672C\u673A registry \u4E2D\u53EF\u88AB bot \u4F18\u5148\u62AB\u9732\u7684 Skill \u8D44\u4EA7\u3002","skills.overviewTitle":"\u6309 Bot \u7EC4\u7EC7 Skill \u8D44\u4EA7","skills.overviewBody":"\u5168\u5C40 Skill \u6CE8\u5165\u914D\u7F6E\u63A7\u5236\u4F1A\u8BDD\u6CE8\u5165\u7B56\u7565\uFF1B\u6BCF\u4E2A bot \u53EA\u7EF4\u62A4\u81EA\u5DF1\u7684\u4F18\u5148\u62AB\u9732\u5217\u8868\u3002","skills.metricInstalled":"\u5DF2\u5B89\u88C5 Skills","skills.metricBots":"\u5DF2\u914D\u7F6E Bot","skills.metricAttached":"\u4F18\u5148\u5F15\u7528","skills.install":"\u5B89\u88C5 Skill","skills.installInfoLabel":"\u5B89\u88C5\u4F4D\u7F6E\u8BF4\u660E","skills.installInfo":`\u6CE8\u518C: ~/.botmux/skills/registry.json
|
|
5
|
-
\u5B89\u88C5: ~/.botmux/skills/store/\u6280\u80FD\u540D\uFF1BGit \u7F13\u5B58: ~/.botmux/skills/sources
|
|
6
|
-
\u9694\u79BB: \u4E0D\u5199\u5165 Codex/Claude \u5168\u5C40\u76EE\u5F55\uFF1B\u672C\u673A CLI Skill \u76F4\u63A5\u5F15\u7528\u539F\u5730\u5740`,"skills.source":"\u5BFC\u5165\u5730\u5740","skills.sourcePlaceholder":"\u7C98\u8D34 GitHub Skill \u9875\u9762\u3001Git URL \u6216\u672C\u673A Skill \u76EE\u5F55","skills.sourceHelpRemoteLabel":"GitHub / Git: ","skills.sourceHelpRemote":"\u53EF\u7C98\u8D34 Skill \u76EE\u5F55\u9875\u9762\u6216\u4ED3\u5E93\u5730\u5740\uFF1B\u4ED3\u5E93\u5730\u5740\u9700\u586B\u5199\u4ED3\u5E93\u5185\u8DEF\u5F84\u3002","skills.sourceHelpLocalLabel":"\u672C\u673A CLI Skill \u76EE\u5F55: ","skills.sourceHelpLocal":"\u76F4\u63A5\u5F15\u7528\u539F\u5730\u5740\uFF0C\u4E0D\u590D\u5236\u5230 botmux store\u3002","skills.discover":"\u53D1\u73B0 Skill","skills.discoverTitle":"\u53D1\u73B0\u672C\u673A CLI Skill","skills.discoverHelp":"\u626B\u63CF\u5F53\u524D\u90E8\u7F72\u4E2D\u5DF2\u914D\u7F6E bot \u5BF9\u5E94\u7684 CLI Skill \u76EE\u5F55\uFF1B\u9009\u4E2D\u540E\u6CE8\u518C\u4E3A\u672C\u5730\u5F15\u7528\uFF0C\u4E0D\u590D\u5236\u6587\u4EF6\u3002","skills.discoverEmpty":"\u6CA1\u6709\u5728\u672C\u673A CLI skill \u76EE\u5F55\u4E2D\u53D1\u73B0\u53EF\u6CE8\u518C\u7684 Skill\u3002","skills.discoverGroupEmpty":"\u8FD9\u4E2A CLI \u76EE\u5F55\u4E0B\u6CA1\u6709\u53EF\u6CE8\u518C\u7684 Skill\u3002","skills.discoverRegistered":"\u5DF2\u6CE8\u518C","skills.discoverSelectAll":"\u5168\u9009\u672A\u6CE8\u518C","skills.discoverClearSelection":"\u53D6\u6D88\u5168\u9009","skills.discoverRegister":"\u6CE8\u518C\u9009\u4E2D","skills.discoverClose":"\u5173\u95ED","skills.discoverNothingSelected":"\u8BF7\u9009\u62E9\u81F3\u5C11\u4E00\u4E2A\u672A\u6CE8\u518C\u7684 Skill\u3002","skills.discoverRegisteringBatch":"\u6B63\u5728\u6279\u91CF\u6CE8\u518C {total} \u4E2A Skill","skills.sourceCodex":"\u672C\u673A Codex","skills.sourceClaude":"\u672C\u673A Claude","skills.sourceTrae":"\u672C\u673A Trae","skills.sourceCursor":"\u672C\u673A Cursor","skills.sourceGemini":"\u672C\u673A Gemini","skills.sourceOpenCode":"\u672C\u673A OpenCode","skills.sourceLocalLink":"\u672C\u673A\u5F15\u7528","skills.sourceBotmuxCopy":"botmux store","skills.path":"\u4ED3\u5E93\u5185\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09","skills.pathPlaceholder":"\u7559\u7A7A\u5219\u4F7F\u7528 GitHub URL \u4E2D\u7684\u8DEF\u5F84","skills.ref":"Ref\uFF08\u53EF\u9009\uFF09","skills.refPlaceholder":"\u7559\u7A7A\u5219\u4F7F\u7528 GitHub URL \u4E2D\u7684\u5206\u652F\u6216\u9ED8\u8BA4 HEAD","skills.link":"\u672C\u5730\u94FE\u63A5\uFF08\u4E0D\u590D\u5236\uFF09","skills.installSubmit":"\u5B89\u88C5","skills.update":"\u66F4\u65B0","skills.remove":"\u5220\u9664","skills.pageStatus":"{page} / {pages}","skills.prevPage":"\u4E0A\u4E00\u9875","skills.nextPage":"\u4E0B\u4E00\u9875","skills.empty":"\u6682\u65E0\u5DF2\u5B89\u88C5 skill\u3002\u53EF\u4EE5\u4ECE\u672C\u673A\u76EE\u5F55\u3001Git \u6216 GitHub \u5B89\u88C5\u3002","skills.apiUnavailable":"\u5F53\u524D Dashboard \u540E\u7AEF\u4E0D\u652F\u6301 Skill API\uFF0C\u901A\u5E38\u662F\u524D\u7AEF\u5DF2\u66F4\u65B0\u4F46 botmux \u8FDB\u7A0B\u672A\u91CD\u542F\u3002\u8BF7\u91CD\u542F botmux \u540E\u5237\u65B0\u9875\u9762\u3002","skills.globalDefaults":"\u5168\u5C40 Skill \u6CE8\u5165\u914D\u7F6E","skills.globalProject":"\u5DE5\u4F5C\u533A Skill","skills.globalProjectOff":"\u5FFD\u7565\u5DE5\u4F5C\u533A Skill","skills.globalProjectOffHelp":"\u4EC5\u8BFB\u53D6\u5168\u5C40 CLI Skill \u548C botmux Skill","skills.globalProjectAll":"\u8BFB\u53D6\u5DE5\u4F5C\u533A Skill","skills.globalProjectAllHelp":`\u8BFB\u53D6 .agents/skills \u4E0E
|
|
7
|
-
.botmux/skills`,"skills.globalDelivery":"Skill \u6CE8\u5165\u65B9\u5F0F","skills.bots":"Bot Skill \u914D\u7F6E","skills.botsHelp":"\u4E3A\u6BCF\u4E2A bot \u9009\u62E9\u6700\u9700\u8981\u4F18\u5148\u62AB\u9732\u7684 Skill\u3002","skills.botCount":"{count} \u4E2A Bot","skills.scrollBotsPrev":"\u5411\u5DE6\u67E5\u770B Bot","skills.scrollBotsNext":"\u5411\u53F3\u67E5\u770B Bot","skills.skillCount":"{count} \u4E2A Skill","skills.attach":"\u52A0\u5165\u4F18\u5148\u62AB\u9732","skills.detach":"\u79FB\u9664","skills.detachNamed":"\u79FB\u9664 {skill}","skills.delivery":"\u6CE8\u5165\u65B9\u5F0F","skills.deliveryAuto":"\u81EA\u52A8","skills.deliveryAutoHelp":"\u4F18\u5148\u7528 CLI \u539F\u751F\u901A\u9053\uFF1B\u4E0D\u652F\u6301\u65F6\u81EA\u52A8\u6539\u7528\u63D0\u793A\u8BCD\u6CE8\u5165","skills.deliveryPrompt":"\u63D0\u793A\u8BCD","skills.deliveryPromptHelp":"\u628A Skill \u6E05\u5355\u5199\u5165\u4F1A\u8BDD\u63D0\u793A\u8BCD\uFF0C\u517C\u5BB9\u6240\u6709 CLI","skills.deliveryNative":"\u539F\u751F","skills.deliveryNativeHelp":"\u53EA\u4EA4\u7ED9 CLI \u81EA\u5DF1\u7684 Skill \u673A\u5236\uFF0C\u4E0D\u505A\u63D0\u793A\u8BCD\u515C\u5E95","skills.projectMode":"\u5DE5\u4F5C\u533A Skills","skills.projectDefault":"\u8DDF\u968F\u5168\u5C40","skills.projectDefaultHelp":"\u4F7F\u7528\u5DE6\u4FA7\u9879\u76EE Skill \u9ED8\u8BA4\u503C","skills.projectOff":"\u4E0D\u8BFB\u53D6","skills.projectOffHelp":"\u8FD9\u4E2A bot \u4E0D\u8BFB\u53D6\u5DE5\u4F5C\u533A skill","skills.projectAll":"\u8BFB\u53D6","skills.projectAllHelp":"\u8FD9\u4E2A bot \u52A0\u5165\u5DE5\u4F5C\u533A skill \u5019\u9009","skills.priority":"\u4F18\u5148 skills","skills.noPriority":"\u672A\u914D\u7F6E\uFF0C\u4FDD\u6301 CLI \u9ED8\u8BA4\u884C\u4E3A","skills.dangling":"\u672A\u5B89\u88C5","skills.removeInUse":'Skill "{skill}" \u4ECD\u88AB\u4EE5\u4E0B\u914D\u7F6E\u5F15\u7528\uFF1A{refs}\u3002\u5220\u9664\u53EA\u4F1A\u79FB\u9664 registry \u6587\u4EF6\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u6E05\u7406\u5F15\u7528\u3002\u7EE7\u7EED\u5220\u9664\uFF1F',"skills.saved":"\u5DF2\u4FDD\u5B58","skills.failed":"\u5931\u8D25","skills.jobRunning":"\u5904\u7406\u4E2D...","skills.refresh":"\u5237\u65B0","botDefaults.title":"\u6570\u5B57\u5458\u5DE5\u6863\u6848","botDefaults.subtitle":"\u6BCF\u4F4D\u5458\u5DE5\u7684\u9ED8\u8BA4\u884C\u4E3A\uFF1Aoncall\u3001\u4E3B\u52A8\u5F00\u5DE5\u3001\u4EBA\u8BBE\u89D2\u8272\u3001\u5361\u7247\u4E0E\u6388\u6743\u3002","botDefaults.metaOnline":"\u5728\u7EBF \xB7 daemon \u6B63\u5E38","botDefaults.search":"\u641C\u7D22 bot \u540D / app id","botDefaults.refresh":"\u5237\u65B0","botDefaults.sectionOncall":"\u65B0\u7FA4 Oncall","botDefaults.sectionBrand":"\u5361\u7247\u7B7E\u540D","botDefaults.sectionAgent":"CLI / \u6A21\u578B","botDefaults.agentCli":"CLI","botDefaults.agentModel":"\u6A21\u578B","botDefaults.agentModelPlaceholder":"\u7559\u7A7A\u4F7F\u7528\u8BE5 CLI \u9ED8\u8BA4\u6A21\u578B","botDefaults.agentHelp":"\u6539\u52A8\u53EA\u5F71\u54CD\u65B0\u521B\u5EFA\u7684\u4F1A\u8BDD\uFF1B\u5DF2\u6709\u4F1A\u8BDD\u4F1A\u7EE7\u7EED\u4F7F\u7528\u521B\u5EFA\u65F6\u7684 CLI / \u6A21\u578B\u3002\u82E5\u8981\u8BA9\u65E7\u5BF9\u8BDD\u4F7F\u7528\u65B0\u914D\u7F6E\uFF0C\u8BF7\u5173\u95ED\u540E\u91CD\u65B0\u5F00\u59CB\u3002","botDefaults.agentSave":"\u4FDD\u5B58 CLI / \u6A21\u578B","botDefaults.agentSaved":"\u5DF2\u4FDD\u5B58\uFF08\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u751F\u6548\uFF09","botDefaults.warning":"\u5F00\u542F\u540E\uFF0C\u6CA1\u6709 oncall binding \u7684\u7FA4\u4F1A\u5728\u4E0B\u6B21\u5F00\u65B0\u8BDD\u9898\u65F6\u81EA\u52A8\u7ED1\u5B9A\u5230\u8BE5\u76EE\u5F55\uFF1B\u624B\u52A8\u7ED1\u5B9A\u6216\u624B\u52A8\u89E3\u7ED1\u8FC7\u7684\u7FA4\u4E0D\u4F1A\u88AB\u8986\u76D6\u3002","botDefaults.empty":"\u6CA1\u6709\u5728\u7EBF bot\u3002\u5148 botmux restart \u8BA9 daemon \u4E0A\u7EBF\u3002","botDefaults.defaultOncall":"\u9ED8\u8BA4\u8FDB\u5165 oncall \u6A21\u5F0F","botDefaults.defaultOncallHelp":"\u6240\u6709\u672A\u7ED1\u5B9A\u7684\u7FA4\u4E0B\u6B21\u5F00\u8BDD\u9898\u81EA\u52A8\u7ED1\u5B9A","botDefaults.workingDir":"\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55","botDefaults.lastEnabled":"\u4E0A\u6B21\u542F\u7528\u65F6\u95F4","botDefaults.autobound":"\u5DF2\u81EA\u52A8\u7ED1\u5B9A {count} \u4E2A\u7FA4","botDefaults.save":"\u4FDD\u5B58","botDefaults.required":"\u9009\u62E9\u300C\u4EC5\u9ED8\u8BA4\u76EE\u5F55\u300D\u6216\u300COncall \u6A21\u5F0F\u300D\u65F6\u5FC5\u987B\u586B\u5DE5\u4F5C\u76EE\u5F55","botDefaults.sectionWorkingDir":"\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55","botDefaults.workingDirMode":"\u6A21\u5F0F","botDefaults.workingDirField":"\u76EE\u5F55","botDefaults.workingDirModeOff":"\u5173\u95ED\uFF08\u65B0\u4F1A\u8BDD\u5F39\u300C\u9009\u4ED3\u5E93\u300D\u5361\uFF09","botDefaults.workingDirModeDefault":"\u4EC5\u9ED8\u8BA4\u76EE\u5F55\uFF08\u4E0D\u6539\u6743\u9650\uFF09","botDefaults.workingDirModeOncall":"Oncall \u6A21\u5F0F\uFF08\u7FA4\u5185\u5F00\u653E\u5BF9\u8BDD\uFF09","botDefaults.workingDirModeHelp":"\u8BE5 bot \u65B0\u4F1A\u8BDD\u9ED8\u8BA4\u5728\u54EA\u4E2A\u76EE\u5F55\u542F\u52A8\uFF0C\u4E09\u9009\u4E00\uFF08\u4E92\u65A5\uFF09\uFF1A\u300C\u5173\u95ED\u300D\uFF1D\u4E0D\u9489\u76EE\u5F55\uFF0C\u65B0\u4F1A\u8BDD\u5F39\u300C\u9009\u4ED3\u5E93\u300D\u5361\uFF1B\u300C\u4EC5\u9ED8\u8BA4\u76EE\u5F55\u300D\uFF1D\u6240\u6709\u65B0\u4F1A\u8BDD\uFF08\u542B\u79C1\u804A/\u8BDD\u9898\uFF09\u76F4\u63A5\u8FDB\u8BE5\u76EE\u5F55\u3001\u8DF3\u8FC7\u9009\u4ED3\u5E93\u5361\uFF0C\u4E0D\u6539\u4EFB\u4F55\u6743\u9650\uFF08\u79C1\u6709 bot \u7528\uFF09\uFF1B\u300COncall \u6A21\u5F0F\u300D\uFF1D\u5728\u300C\u4EC5\u9ED8\u8BA4\u76EE\u5F55\u300D\u57FA\u7840\u4E0A\uFF0C\u989D\u5916\u628A\u65B0\u8FDB\u7684\u666E\u901A\u7FA4\u81EA\u52A8\u7ED1\u5B9A\u4E3A oncall\uFF08\u7FA4\u91CC\u4EFB\u4F55\u4EBA\u90FD\u80FD\u8DDF bot \u5BF9\u8BDD\uFF1B\u6309\u94AE/\u547D\u4EE4\u7B49\u5199\u64CD\u4F5C\u4ECD\u53EA\u9650 allowedUsers\uFF09\uFF0C\u9002\u5408\u503C\u73ED/\u5BF9\u5916\u652F\u6301\u3002\u6539\u540E\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u751F\u6548\uFF0C\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u9700 /restart\u3002","botDefaults.workingDirSaved":"\u5DF2\u4FDD\u5B58\uFF08\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u751F\u6548\uFF09","botDefaults.brandLabel":"\u4E2A\u6027\u7B7E\u540D\uFF08\u5361\u7247\u9875\u811A\uFF09","botDefaults.brandLabelHelp":"\u8BE5 bot \u53D1\u51FA\u7684\u5361\u7247\u9875\u811A\u7B7E\u540D\u3002\u7559\u7A7A\u4FDD\u5B58\uFF1D\u4E0D\u663E\u793A\uFF1B\u586B\u5199\uFF1D\u81EA\u5B9A\u4E49\uFF08\u652F\u6301 markdown\uFF0C\u5982 [Acme](https://\u2026)\uFF09\uFF1B\u6062\u590D\u9ED8\u8BA4\uFF1D\u663E\u793A botmux\u3002","botDefaults.brandLabelPlaceholder":"\u9ED8\u8BA4\uFF1Abotmux\uFF08\u7559\u7A7A\u5219\u4E0D\u663E\u793A\uFF09","botDefaults.sectionSandbox":"\u6587\u4EF6\u6C99\u76D2\uFF08oncall\uFF09","botDefaults.sandboxToggle":"\u5F00\u542F\u6587\u4EF6\u6C99\u76D2","botDefaults.sandboxHelp":"\u5F00\u542F\u540E\uFF0C\u8BE5 bot \u7684\u6BCF\u4E2A\u4F1A\u8BDD\u90FD\u8DD1\u5728\u6309\u4F1A\u8BDD\u9694\u79BB\u7684\u6C99\u76D2\u91CC\uFF1A\u53EA\u770B\u5F97\u5230\u4E00\u4EFD\u9879\u76EE\u526F\u672C\uFF0C\u78B0\u4E0D\u5230\u4F60\u78C1\u76D8\u4E0A\u7684\u771F\u5B9E\u6587\u4EF6\u3001\u5BC6\u94A5\u3001\u522B\u7684\u4F1A\u8BDD\u6570\u636E\u3002\u9002\u5408\u628A\u673A\u5668\u4EBA\u5206\u4EAB\u7ED9\u534A\u53D7\u4FE1\u4EFB\u7684\u4EBA\uFF08oncall\uFF09\u3002\u4EC5 Linux \u751F\u6548\uFF0C\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u8D77\u6548\u3002","botDefaults.sandboxSaved":"\u5DF2\u4FDD\u5B58\uFF08\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u751F\u6548\uFF09","botDefaults.brandSave":"\u4FDD\u5B58\u7B7E\u540D","botDefaults.brandReset":"\u6062\u590D\u9ED8\u8BA4","botDefaults.brandStateDefault":"\u5F53\u524D\uFF1A\u9ED8\u8BA4 botmux","botDefaults.brandStateOff":"\u5F53\u524D\uFF1A\u5DF2\u5173\u95ED","botDefaults.brandStateCustom":"\u5F53\u524D\uFF1A\u81EA\u5B9A\u4E49","botDefaults.sectionCard":"\u5361\u7247\u884C\u4E3A","botDefaults.disableStreaming":"\u5173\u95ED\u98DE\u4E66\u6D41\u5F0F\u5361\u7247","botDefaults.disableStreamingHelp":"\u4E0D\u518D\u53D1\u5B9E\u65F6\u5237\u65B0\u7684\u4F1A\u8BDD\u72B6\u6001\u5361\uFF08\u542B\u300C\u6253\u5F00\u7EC8\u7AEF\u300D\u5165\u53E3\uFF09\uFF1B\u4EFB\u52A1\u6700\u7EC8\u7ED3\u679C\u4ECD\u901A\u8FC7\u6D88\u606F\u9001\u8FBE\u3002\u9002\u5408\u5ACC\u6D41\u5F0F\u5361\u7247\u70E6\u7684\u573A\u666F\u3002","botDefaults.silentTurnReactions":"\u5173\u95ED\u65E0\u5361\u7247\u6A21\u5F0F\u4E0B\u7684\u72B6\u6001 reaction","botDefaults.silentTurnReactionsHelp":"\u5173\u95ED\u6D41\u5F0F\u5361\u7247\u540E\uFF0Cbotmux \u4F1A\u7528 \u270B\u2192\u2705 \u8FD9\u7C7B\u8F7B\u91CF reaction \u7ED9\u89E6\u53D1\u6D88\u606F\u6807\u300C\u5DF2\u6536\u5230 / \u5DF2\u5B8C\u6210\u300D\u3002\u52FE\u9009\u540E\u8FDE\u8FD9\u4E2A\u4E5F\u4E0D\u52A0\uFF0C\u9002\u5408\u4F4E\u566A\u97F3\u7684\u89C2\u5BDF\u578B bot\u3002\u4EC5\u5728\u300C\u5173\u95ED\u98DE\u4E66\u6D41\u5F0F\u5361\u7247\u300D\u5F00\u542F\u65F6\u53EF\u6539\u3002","botDefaults.writableLink":"\u5361\u7247\u4E0A\u76F4\u63A5\u7ED9\u53EF\u64CD\u4F5C\uFF08\u53EF\u5199\uFF09\u7EC8\u7AEF\u94FE\u63A5","botDefaults.writableLinkHelp":"\u26A0\uFE0F \u5728\u6D41\u5F0F\u5361\u7247\u6B63\u6587\u76F4\u63A5\u8D34\u51FA\u53EF\u5199\u7EC8\u7AEF\u94FE\u63A5\uFF0C\u7FA4\u5185\u4EFB\u4F55\u4EBA\u90FD\u80FD\u70B9\u5F00\u5E76\u64CD\u63A7\u7EC8\u7AEF\u3002\u4E0D\u52FE\uFF1D\u4FDD\u6301\u73B0\u72B6\uFF08\u8D70\u300C\u83B7\u53D6\u64CD\u4F5C\u94FE\u63A5\u300D\u6309\u94AE\u79C1\u804A\u53D1\u7ED9\u70B9\u51FB\u8005\uFF09\u3002","botDefaults.writableLinkMoot":"\u5DF2\u5173\u95ED\u6D41\u5F0F\u5361\u7247","botDefaults.privateCard":"/card \u53D1\u79C1\u5BC6\u5361\u7247\uFF08\u4EC5\u6388\u6743\u4EBA\u53EF\u89C1\uFF09","botDefaults.privateCardHelp":"\u5F00\u542F\u540E /card \u6539\u7528\u300C\u4EC5\u7279\u5B9A\u4EBA\u53EF\u89C1\u300D\u7684\u4E34\u65F6\u5361\u7247\uFF1A\u53EA\u53D1\u7ED9 owner\uFF08allowedUsers\uFF09\uFF0C/grant \u6388\u6743\u5BF9\u8BDD\u7684\u4EBA\u548C\u7FA4\u91CC\u5176\u4ED6\u4EBA\u90FD\u770B\u4E0D\u5230\u3002\u4EE3\u4EF7\uFF1A\u662F\u9759\u6001\u5FEB\u7167\u3001\u4E0D\u4F1A\u5B9E\u65F6\u5237\u65B0\uFF1B\u4E14\u4EC5\u666E\u901A\u7FA4\u53EF\u7528\uFF08\u8BDD\u9898\u7FA4 / \u5355\u804A\u4F1A\u5931\u8D25\uFF0C\u4E0D\u964D\u7EA7\uFF09\u3002\u53EA\u5F71\u54CD /card \u547D\u4EE4\uFF0C\u81EA\u52A8\u6D41\u5F0F\u5361\u4E0D\u53D8\u3002","botDefaults.sectionCrossBot":"\u8DE8 bot \u534F\u4F5C","botDefaults.botToBotSameDir":"bot@bot \u540C\u76EE\u5F55\u62C9\u8D77","botDefaults.botToBotSameDirHelp":"\u5F00\u542F\u540E\uFF0C\u672C bot \u88AB @ \u8FDB\u4E00\u4E2A\u5DF2\u6709\u5176\u5B83 bot \u5728\u5E72\u6D3B\u7684\u7FA4/\u8BDD\u9898\u65F6\uFF0C\u76F4\u63A5\u590D\u7528\u5BF9\u65B9\u7684\u5DE5\u4F5C\u76EE\u5F55\u3001\u8DF3\u8FC7\u4ED3\u5E93\u9009\u62E9\u5361\u7247\uFF08\u4E0E oncall \u7ED1\u5B9A\u65E0\u5173\uFF0C\u9ED8\u8BA4\u5F00\uFF09\u3002\u5173\u6389\u5219\u672C bot \u6C38\u8FDC\u8D70\u81EA\u5DF1\u7684\u4ED3\u5E93\u9009\u62E9\u5361 / \u9ED8\u8BA4\u76EE\u5F55\u3002","botDefaults.cardPrefSaved":"\u5DF2\u4FDD\u5B58","botDefaults.sectionSummaryTrigger":"/summary \u603B\u7ED3\u8303\u56F4","botDefaults.summaryLimit":"\u6700\u8FD1\u6D88\u606F\u6761\u6570","botDefaults.summarySinceHours":"\u6700\u8FD1\u5C0F\u65F6\u6570","botDefaults.summaryLimitHelp":"@ \u673A\u5668\u4EBA\u5E76\u8F93\u5165 /summary \u65F6\u8BFB\u53D6\u8BE5\u8303\u56F4\u5185\u5386\u53F2\u6D88\u606F\uFF1B\u9ED8\u8BA4\u6700\u8FD1 50 \u6761 / 24 \u5C0F\u65F6\uFF0C\u4EFB\u4E00\u9879\u586B 0 \u8868\u793A\u8BE5\u9879\u4E0D\u505A\u9650\u5236\u3002\u8BDD\u9898\u7FA4\u59CB\u7EC8\u8BFB\u53D6\u5F53\u524D\u8BDD\u9898\u5386\u53F2\u3002","botDefaults.summarySave":"\u4FDD\u5B58\u603B\u7ED3\u8303\u56F4","botDefaults.summaryNumberInvalid":"\u65F6\u957F\u548C\u6761\u6570\u5FC5\u987B\u662F 0 \u6216\u6B63\u6574\u6570","botDefaults.sectionRole":"\u9ED8\u8BA4\u89D2\u8272","botDefaults.roleHelp":"\u8BE5 bot \u7684\u9ED8\u8BA4\u4EBA\u8BBE\uFF08\u8DE8\u7FA4\u751F\u6548\uFF09\uFF0C\u4F1A\u6CE8\u5165\u5230\u8BE5 bot \u5728\u5404\u7FA4\u7684\u4F1A\u8BDD\u91CC\uFF1B\u5355\u4E2A\u7FA4\u53EF\u5728\u300C\u89D2\u8272\u300D\u9875\u5355\u72EC\u8986\u76D6\u3002\u7559\u7A7A\u4FDD\u5B58\uFF1D\u5220\u9664\u3002","botDefaults.rolePlaceholder":"\u4F8B\u5982\uFF1A\u4F60\u662F\u540E\u7AEF\u6392\u969C\u52A9\u624B\uFF0C\u56DE\u7B54\u7B80\u6D01\u3001\u4F18\u5148\u7ED9\u53EF\u6267\u884C\u547D\u4EE4\u2026","botDefaults.roleSave":"\u4FDD\u5B58\u89D2\u8272","botDefaults.roleDelete":"\u5220\u9664","botDefaults.roleSaved":"\u5DF2\u4FDD\u5B58","botDefaults.roleDeleted":"\u5DF2\u5220\u9664","botDefaults.roleLoadErr":"\u89D2\u8272\u52A0\u8F7D\u5931\u8D25","botDefaults.profileRoles":"Profile \u89D2\u8272","botDefaults.profileRolesHelp":"\u8BE5 bot \u5728\u5404\u4E2A Profile \u4E2D\u7684\u89D2\u8272\u6761\u76EE\uFF1B\u9ED8\u8BA4\u6298\u53E0\uFF0C\u5C55\u5F00\u540E\u8BFB\u53D6\u8BE6\u60C5\u3002","botDefaults.profileRolesEmpty":"\u8FD9\u4E2A bot \u6682\u65E0 Profile \u89D2\u8272\u3002","botDefaults.profileRolesLoadFailed":"Profile \u89D2\u8272\u52A0\u8F7D\u5931\u8D25\uFF1A{error}","botDefaults.profileRoleClickToLoad":"\u5C55\u5F00\u540E\u52A0\u8F7D\u89D2\u8272\u8BE6\u60C5\u3002","botDefaults.profileRoleDetailLoadFailed":"\u89D2\u8272\u8BE6\u60C5\u52A0\u8F7D\u5931\u8D25\uFF1A{error}","botDefaults.sectionAutoStart":"\u4E3B\u52A8\u5F00\u5DE5","botDefaults.autoStartJoin":"\u88AB\u62C9\u8FDB\u65B0\u7FA4\u81EA\u52A8\u5F00\u5DE5","botDefaults.autoStartJoinHelp":"\u5F00\u542F\u540E\uFF0C\u673A\u5668\u4EBA\u4E00\u88AB\u62C9\u8FDB\u65B0\u7FA4\uFF08\u7FA4\u91CC\u6709\u6388\u6743\u7528\u6237 allowedUsers \u65F6\uFF09\u5C31\u81EA\u52A8\u5F00\u4E00\u4E2A\u4F1A\u8BDD\u5F00\u59CB\u5DE5\u4F5C\uFF0C\u65E0\u9700 @\u3002\u5728\u673A\u5668\u4EBA\u7684\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55\u542F\u52A8\uFF1B\u672A\u914D\u7F6E\u9ED8\u8BA4\u76EE\u5F55\u65F6\u5148\u5F39\u4ED3\u5E93\u9009\u62E9\u5361\u8BA9\u4F60\u9009\u3002\u524D\u63D0\uFF1A\u9700\u5728\u98DE\u4E66\u5F00\u653E\u5E73\u53F0\u4E3A\u672C\u5E94\u7528\u8BA2\u9605\u300C\u673A\u5668\u4EBA\u8FDB\u7FA4\u300D\u4E8B\u4EF6 im.chat.member.bot.added_v1\uFF0C\u5E76\u5F00\u901A\u7FA4\u6210\u5458\u8BFB\u53D6\u6743\u9650\u3002","botDefaults.autoStartJoinPrompt":"\u5165\u7FA4\u9996\u8F6E prompt\uFF08\u53EF\u9009\uFF09","botDefaults.autoStartJoinPromptPlaceholder":"\u586B\u4E86\uFF1D\u4F5C\u4E3A\u5165\u7FA4\u540E\u7684\u7B2C\u4E00\u6761\u4EFB\u52A1\uFF1B\u7559\u7A7A\uFF1D\u673A\u5668\u4EBA\u81EA\u5DF1\u770B\u7FA4\u91CC\u4FE1\u606F\u51B3\u5B9A\u505A\u4EC0\u4E48","botDefaults.autoStartJoinPromptSave":"\u4FDD\u5B58 prompt","botDefaults.autoStartTopic":"\u8BDD\u9898\u7FA4\u65B0\u8BDD\u9898\u81EA\u52A8\u5F00\u5DE5","botDefaults.autoStartTopicHelp":"\u5F00\u542F\u540E\uFF0C\u5728\u8BDD\u9898\u7FA4\u91CC\u6BCF\u5F53\u6709\u4EBA\u65B0\u5F00\u4E00\u4E2A\u8BDD\u9898\uFF0C\u673A\u5668\u4EBA\u5C31\u4F1A\u81EA\u52A8\u63A5\u5165\u8BE5\u8BDD\u9898\u3001\u628A\u9996\u6761\u6D88\u606F\u5F53\u4F5C\u4EFB\u52A1\u5F00\u59CB\u5904\u7406\uFF0C\u65E0\u9700 @\u3002\u4EC5\u5BF9\u8BDD\u9898\u7FA4\u751F\u6548\uFF0C\u666E\u901A\u7FA4\u4E0D\u53D7\u5F71\u54CD\u3002","botDefaults.sectionSessionMode":"\u4F1A\u8BDD\u6A21\u5F0F","botDefaults.p2pMode":"\u79C1\u804A\u4F1A\u8BDD\u6A21\u5F0F","botDefaults.p2pThread":"thread\uFF08\u6BCF\u6761 DM \u72EC\u7ACB\u4F1A\u8BDD\uFF09","botDefaults.p2pChat":"chat\uFF08\u6241\u5E73\u8FDE\u7EED\u5355\u804A\u4F1A\u8BDD\uFF09","botDefaults.p2pHelp":"\u79C1\u804A\uFF081:1 DM\uFF09\u7684\u4F1A\u8BDD\u65B9\u5F0F\uFF1Athread = \u6BCF\u6761\u9876\u5C42\u6D88\u606F\u5404\u81EA\u8D77\u72EC\u7ACB\u4F1A\u8BDD\uFF08\u907F\u514D\u628A\u5BF9\u8BDD\u5806\u8FDB\u540C\u4E00\u4E2A CLI \u8FDB\u7A0B\uFF09\uFF1Bchat = \u6574\u6BB5 DM \u5171\u7528\u4E00\u4E2A\u8FDE\u7EED\u4F1A\u8BDD\u3001\u5171\u4EAB\u4E0A\u4E0B\u6587\uFF08\u7C7B Hermes\uFF09\u3002\u6539\u540E\u7ACB\u5373\u751F\u6548\u3002","botDefaults.regularGroupMode":"\u666E\u901A\u7FA4\u4F1A\u8BDD\u6A21\u5F0F","botDefaults.regularGroupModeChat":"chat\uFF08\u6241\u5E73\u8FDE\u7EED\u5355\u804A\u4F1A\u8BDD\uFF0C\u9ED8\u8BA4\uFF09","botDefaults.regularGroupModeChatTopic":"chat-topic\uFF08\u9876\u5C42\u5E73\u94FA\u8FDE\u7EED\u4F1A\u8BDD\uFF0C\u539F\u751F\u8BDD\u9898\u5404\u81EA\u72EC\u7ACB\u4F1A\u8BDD\uFF09","botDefaults.regularGroupModeNewTopic":"new-topic\uFF08\u6BCF\u6761\u9876\u5C42 @ \u5404\u5F00\u72EC\u7ACB\u8BDD\u9898\u4E0E\u4F1A\u8BDD\uFF09","botDefaults.regularGroupModeShared":"shared\uFF08\u8BDD\u9898\u6A21\u5F0F\u4F46\u590D\u7528\u540C\u4E00\u4E2A session\uFF09","botDefaults.regularGroupModeHelp":"\u666E\u901A\u7FA4\uFF08\u975E\u8BDD\u9898\u7FA4\uFF09\u91CC @ \u8BE5 bot \u7684\u65B0\u9876\u5C42\u6D88\u606F\u600E\u4E48\u5F00\u4F1A\u8BDD\uFF1Achat = \u6574\u7FA4\u5171\u7528\u4E00\u4E2A\u8FDE\u7EED\u4F1A\u8BDD\uFF08\u9ED8\u8BA4\uFF0C\u8FDE\u4F60\u5728\u7FA4\u91CC\u624B\u52A8\u5F00\u7684\u539F\u751F\u8BDD\u9898\u4E5F\u5E76\u8FDB\u8FD9\u4E2A\u4F1A\u8BDD\uFF09\uFF1Bchat-topic = \u9876\u5C42 @ \u4ECD\u5E73\u94FA\u8FDB\u7FA4\u91CC\u90A3\u4E00\u4E2A\u8FDE\u7EED\u4F1A\u8BDD\uFF0C\u4F46\u4F60\u624B\u52A8\u5F00\u7684\u539F\u751F\u8BDD\u9898\u5404\u81EA\u72EC\u7ACB\u4F1A\u8BDD\uFF08\u8BDD\u9898\u91CC\u5F00\u65B0\u4F1A\u8BDD\uFF09\uFF1Bnew-topic = \u6BCF\u6761\u9876\u5C42 @ \u5728\u539F\u6D88\u606F\u4E0B\u5F00\u72EC\u7ACB\u8BDD\u9898\u3001\u5404\u81EA\u72EC\u7ACB\u4F1A\u8BDD\uFF1Bshared = \u8BDD\u9898\u6A21\u5F0F\u4F46\u590D\u7528\u540C\u4E00\u4E2A session\uFF08\u56DE\u590D\u843D\u5728\u8BDD\u9898\u91CC\u3001\u4F46\u5171\u7528\u672C\u7FA4\u4F1A\u8BDD\u4E0E\u4E0A\u4E0B\u6587\uFF09\u3002\u8FD9\u662F per-bot \u9ED8\u8BA4\uFF0C\u5177\u4F53\u67D0\u4E2A\u7FA4\u53EF\u7528 /reply-mode \u5355\u72EC\u8986\u76D6\u3002\u6539\u540E\u7ACB\u5373\u751F\u6548\u3002","botDefaults.mentionMode":"\u7FA4\u804A @ \u7B56\u7565","botDefaults.mentionModeAlways":"\u90FD\u9700\u8981 @\uFF08\u9ED8\u8BA4\uFF09","botDefaults.mentionModeTopic":"\u4EC5\u8BDD\u9898\u5185\u4E0D\u9700\u8981 @","botDefaults.mentionModeNever":"\u6240\u6709\u6D88\u606F\u90FD\u4E0D\u9700\u8981 @","botDefaults.mentionModeAmbient":"\u90FD\u4E0D\u9700\u8981 @\uFF08\u4F46\u4F60 @ \u522B\u4EBA\u65F6\u8BA9\u4F4D\uFF09","botDefaults.mentionModeHelp":"\u8BE5 bot \u5168\u5C40\u751F\u6548\uFF0C\u51B3\u5B9A\u7FA4\u91CC\u8981\u4E0D\u8981 @ \u624D\u56DE\uFF1A\u300C\u90FD\u9700\u8981 @\u300D= \u4EFB\u4F55\u6D88\u606F\u90FD\u5F97 @\uFF08\u9ED8\u8BA4\uFF0C\u6700\u5B89\u5168\uFF1B\u591A\u4EBA\u7FA4\u91CC\u8BDD\u9898\u5185\u4E5F\u8981 @\uFF09\uFF1B\u300C\u4EC5\u8BDD\u9898\u5185\u4E0D\u9700\u8981 @\u300D= \u8D77\u65B0\u5BF9\u8BDD / \u9876\u5C42\u4ECD\u8981 @\uFF0C\u4F46\u5728\u8BE5 bot \u5DF2\u5F00\u7684\u4EFB\u4F55\u8BDD\u9898\u91CC\uFF08new-topic / shared / \u8BDD\u9898\u7FA4\uFF09\u540E\u7EED\u6D88\u606F\u514D @ \u7EED\u804A\uFF1B\u300C\u6240\u6709\u6D88\u606F\u90FD\u4E0D\u9700\u8981 @\u300D= \u8BE5 bot \u6709\u5BF9\u8BDD\u6743\u9650\u7684\u7FA4\u91CC\u975E @ \u6D88\u606F\u4E5F\u65E0\u6761\u4EF6\u56DE\uFF08\u542B\u5168\u65B0\u6D88\u606F\u51B7\u542F\u52A8\uFF0C\u9002\u5408\u4E13\u7528 / \u503C\u73ED\u5C0F\u7FA4\uFF09\uFF1B\u300C\u90FD\u4E0D\u9700\u8981 @\uFF08\u4F46\u4F60 @ \u522B\u4EBA\u65F6\u8BA9\u4F4D\uFF09\u300D= \u540C\u6837\u514D @ \u4E5F\u56DE\uFF0C\u4F46\u5F53\u8FD9\u6761\u6D88\u606F @ \u4E86\u522B\u7684\u4EBA\u6216\u522B\u7684 bot\uFF08\u800C\u6CA1 @ \u5B83\uFF09\u65F6\u5B83\u8BC6\u8DA3\u4E0D\u56DE\uFF0C\u76F8\u5F53\u4E8E\u4F60\u628A\u8FD9\u6761\u4EA4\u7ED9\u522B\u4EBA\u4E86\uFF08@\u6240\u6709\u4EBA \u4E0D\u7B97\u4EA4\u7ED9\u522B\u4EBA\uFF0C\u4ECD\u4F1A\u56DE\uFF09\uFF0C\u9002\u5408\u591A\u4EBA / \u591A bot \u7FA4\u91CC\u60F3\u8981\u4E00\u4E2A\u9ED8\u8BA4\u54CD\u5E94\u8005\u3001\u4F46\u4F60\u70B9\u540D\u522B\u4EBA\u65F6\u5B83\u5C31\u8BA9\u4F4D\u3002\u6CE8\uFF1A\u7FA4\u91CC\u53EA\u6709\u4F60\u548C\u8BE5 bot\uFF081 \u5BF9 1\uFF09\u65F6\u4E00\u76F4\u514D @\uFF0C\u4E0E\u672C\u8BBE\u7F6E\u65E0\u5173\u3002","botDefaults.docSubscribeMode":"\u6587\u6863\u8BA2\u9605\u89E6\u53D1\u8303\u56F4\uFF08\u9ED8\u8BA4\uFF09","botDefaults.docSubscribeModeMention":"\u4EC5\u8BC4\u8BBA @ \u6211\u624D\u89E6\u53D1","botDefaults.docSubscribeModeAll":"\u6240\u6709\u65B0\u8BC4\u8BBA\u90FD\u89E6\u53D1","botDefaults.docSubscribeModeHelp":"\u7528 /subscribe-lark-doc \u8BA2\u9605\u98DE\u4E66\u6587\u6863\u540E\uFF0C\u6587\u6863\u8BC4\u8BBA\u4F1A\u5582\u8FDB\u4F1A\u8BDD\u3001bot \u56DE\u590D\u53D1\u56DE\u8BC4\u8BBA\u3002\u8FD9\u91CC\u8BBE\u65B0\u8BA2\u9605\u7684\u9ED8\u8BA4\u89E6\u53D1\u8303\u56F4\uFF1A\u300C\u4EC5\u8BC4\u8BBA @ \u6211\u300D\u6700\u5B89\u5168\uFF08\u9632\u5237\u5C4F\uFF09\uFF1B\u300C\u6240\u6709\u65B0\u8BC4\u8BBA\u300D\u9002\u5408\u4E13\u7528\u6587\u6863\u3002","botDefaults.sectionGrant":"\u6388\u6743\u4E0E\u989D\u5EA6","botDefaults.autoGrantCard":"\u672A\u6388\u6743 @ \u81EA\u52A8\u5F39\u6388\u6743\u5361","botDefaults.autoGrantCardHelp":"\u5F00\u542F\u540E\uFF0C\u7FA4\u91CC\u6709\u4EBA\u6216\u5916\u90E8 bot \u660E\u786E @ \u8BE5 bot \u4F46\u88AB\u5BF9\u8BDD\u6743\u9650\u95F8\u6321\u4F4F\u65F6\uFF0C\u4F1A\u81EA\u52A8\u7ED9 owner \u53D1 /grant \u7533\u8BF7\u5361\uFF1B\u5173\u95ED\u540E\u4FDD\u6301\u6743\u9650\u62E6\u622A\u4F46\u9759\u9ED8\u4E22\u5F03\u3002","botDefaults.restrictGrant":"\u9650\u5236\u88AB\u6388\u6743\u4EBA\u53EA\u80FD\u7EAF\u5BF9\u8BDD","botDefaults.restrictGrantHelp":"\u5F00\u542F\u540E\uFF0C\u88AB /grant \u6388\u6743\u7684\u4EBA\uFF08owner \u81EA\u5DF1\u4E0D\u53D7\u9650\uFF09\u53EA\u80FD\u53D1\u666E\u901A\u5BF9\u8BDD\uFF0C\u6240\u6709 slash \u547D\u4EE4\u4E00\u5F8B\u62E6\u622A\uFF1Abotmux \u81EA\u5E26\u547D\u4EE4\u3001\u900F\u4F20\u547D\u4EE4\u3001/workflow\u3001/template\u3001/introduce\u3001/t \u4EE5\u53CA CLI \u539F\u751F\u547D\u4EE4\uFF08/help \u7B49\uFF09\u3002\u5F62\u5982 /path/to/file \u7684\u5185\u5BB9\u4E0D\u4F1A\u88AB\u8BEF\u5224\u3002","botDefaults.quotaDefault":"\u9ED8\u8BA4\u6D88\u606F\u989D\u5EA6","botDefaults.quotaPlaceholder":"\u7559\u7A7A\uFF1D\u4E0D\u914D\u7F6E\u9ED8\u8BA4\u989D\u5EA6","botDefaults.quotaHelp":"\u4E0D\u5E26\u6570\u5B57\u7684 /grant @x \u9ED8\u8BA4\u7ED9\u7684\u6D88\u606F\u6761\u6570\u3002\u7559\u7A7A\u6216\u70B9\u300C\u5173\u95ED\u300D\u53EA\u662F\u4E0D\u518D\u7ED9\u88F8 /grant \u5957\u9ED8\u8BA4\u989D\u5EA6\uFF0C\u4E0D\u4F1A\u6E05\u6389\u5DF2\u6709\u7684\u989D\u5EA6\u8BA1\u6570\uFF0C\u4E5F\u4E0D\u5F71\u54CD\u663E\u5F0F /grant @x N\u2014\u2014\u5B83\u4EEC\u7167\u5E38\u7EE7\u7EED enforce\u3002\u989D\u5EA6\u7528\u5C3D\u4F1A\u81EA\u52A8\u64A4\u9500\u8BE5\u4EBA\u6388\u6743\u3002","botDefaults.quotaSave":"\u4FDD\u5B58\u989D\u5EA6","botDefaults.quotaOff":"\u5173\u95ED","botDefaults.quotaInvalid":"\u989D\u5EA6\u5FC5\u987B\u662F\u6B63\u6574\u6570","botDefaults.quotaStateOff":"\u5F53\u524D\uFF1A\u672A\u914D\u7F6E\u9ED8\u8BA4\u989D\u5EA6","botDefaults.quotaStateOn":"\u5F53\u524D\uFF1A\u6BCF\u4EBA {count} \u6761","botDefaults.sectionSessionCap":"\u4F1A\u8BDD\u6570\u4E0A\u9650","botDefaults.maxLiveWorkers":"\u6700\u5927\u540C\u65F6\u6D3B\u8DC3\u4F1A\u8BDD\u6570","botDefaults.maxLiveWorkersPlaceholder":"\u7559\u7A7A\uFF1D\u9ED8\u8BA4 30","botDefaults.maxLiveWorkersHelp":"\u672C Bot \u540C\u65F6\u4FDD\u6D3B\u7684\u4F1A\u8BDD\u6570\u4E0A\u9650\uFF0C\u7528\u4E8E\u63A7\u5236\u5185\u5B58\u3002\u8D85\u8FC7\u540E\u6700\u4E45\u672A\u7528\u7684\u4F1A\u8BDD\u81EA\u52A8\u4F11\u7720\uFF1Aworker \u548C CLI \u8FDB\u7A0B\u4E00\u8D77\u6740\u6389\u3001\u56DE\u6536\u5168\u90E8\u5185\u5B58\uFF0C\u4E0B\u6761\u6D88\u606F\u65F6\u4ECE\u78C1\u76D8 transcript \u51B7\u6062\u590D\uFF08--resume \u91CD\u5EFA\u4E0A\u4E0B\u6587\uFF0C\u51E0\u79D2\uFF0C\u4E0D\u518D\u5E38\u9A7B\u5360\u5185\u5B58\uFF09\u3002\u7559\u7A7A\uFF1D\u7528\u9ED8\u8BA4 30\uFF1B\u586B\u6570\u5B57\uFF1D\u672C Bot \u81EA\u5B9A\u4E49\uFF08\u60F3\u8981\u66F4\u591A\u5C31\u586B\u5927\u6570\u5B57\uFF09\u3002\u6CE8\u610F\uFF1A\u4F11\u7720\u53EA\u5BF9\u53EF\u6062\u590D\u540E\u7AEF\uFF08tmux/herdr/zellij\uFF09\u751F\u6548\uFF0C\u7EAF PTY \u4F1A\u8BDD\u4E0D\u53D7\u5F71\u54CD\uFF1B\u6B63\u5728\u51FA\u7B54\u6848\u7684\u4F1A\u8BDD\u4E0D\u4F1A\u88AB\u6253\u65AD\u3002","botDefaults.maxLiveWorkersSave":"\u4FDD\u5B58\u4E0A\u9650","botDefaults.maxLiveWorkersOff":"\u6062\u590D\u9ED8\u8BA4","botDefaults.maxLiveWorkersInvalid":"\u4E0A\u9650\u5FC5\u987B\u662F\u6B63\u6574\u6570","botDefaults.maxLiveWorkersStateDefault":"\u5F53\u524D\uFF1A\u9ED8\u8BA4 30 \u4E2A\u6D3B\u8DC3\u4F1A\u8BDD","botDefaults.maxLiveWorkersStateOn":"\u5F53\u524D\uFF1A\u6700\u591A {count} \u4E2A\u6D3B\u8DC3\u4F1A\u8BDD","botDefaults.sectionStartupCommands":"\u542F\u52A8\u547D\u4EE4","botDefaults.startupCommandsHelp":"\u5F00\u4F1A\u8BDD\u540E\u3001\u9996\u6761\u6D88\u606F\u4E4B\u524D\uFF0C\u81EA\u52A8\u6309\u987A\u5E8F\u53D1\u7ED9 CLI \u7684\u547D\u4EE4\uFF08\u6BCF\u6761\u72EC\u7ACB\u56DE\u8F66\uFF09\uFF0C\u5982 /effort ultracode\u3002\u9017\u53F7\u6216\u6362\u884C\u5206\u9694\uFF0C\u6BCF\u884C\u4E00\u6761\uFF0C\u53EF\u5E26\u53C2\u6570\uFF1B\u7559\u7A7A\uFF1D\u4E0D\u53D1\u3002\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u8D77\u6548\uFF0C\u4E14\u6BCF\u6B21\u65B0\u4F1A\u8BDD\uFF08\u542B resume\uFF09\u90FD\u91CD\u653E\u2014\u2014\u6240\u4EE5 /effort ultracode \u8FD9\u7C7B\u53EA\u5BF9\u5F53\u524D\u4F1A\u8BDD\u751F\u6548\u7684\u8BBE\u7F6E\u4E0D\u4F1A\u56E0 resume \u4E22\u5931\u3002\u4EC5\u5BF9\u539F\u751F CLI \u4F1A\u8BDD\u751F\u6548\uFF0Cadopt \u63A5\u7BA1\u7684\u4F1A\u8BDD\u4E0D\u53D1\u3002","botDefaults.startupCommandsPlaceholder":"\u6BCF\u884C\u4E00\u6761\uFF0C\u5982 /effort ultracode","botDefaults.startupCommandsSave":"\u4FDD\u5B58\u542F\u52A8\u547D\u4EE4","botDefaults.sectionLaunchShell":"\u542F\u52A8 Shell","botDefaults.launchShellHelp":"\u542F\u52A8 CLI \u7528\u7684 shell\uFF0C\u8986\u76D6 daemon \u7684 $SHELL\uFF1A\u586B shell \u540D\uFF08zsh|bash|sh\uFF09\u6216\u7EDD\u5BF9\u8DEF\u5F84\uFF08\u5982 /usr/bin/zsh\uFF09\u3002\u7528\u4E8E\u767B\u5F55 $SHELL\uFF08\u5982 bash\uFF09\u7684 rc \u6587\u4EF6\u91CC\u6709 `exec zsh` \u4E4B\u7C7B\u8DF3\u8F6C\u3001\u628A CLI \u542F\u52A8\u547D\u4EE4\u9876\u6389\u3001\u5BFC\u81F4\u4F1A\u8BDD\u8D77\u4E0D\u6765\uFF08\u88F8\u58F3\u91CC\u62A5 parse error\uFF09\u7684\u573A\u666F\u2014\u2014\u6307\u5B9A launchShell \u76F4\u63A5\u7528\u5B83\u542F\u52A8\u3001\u7ED5\u5F00\u88AB\u8DF3\u8FC7\u7684 rc\u3002\u6CE8\u610F\uFF1APATH/nvm/pnpm \u7B49\u8981\u653E\u8FDB\u6240\u9009 shell \u7684 rc\uFF08\u5982 .zshrc/.zprofile\uFF09\u3002\u7559\u7A7A\uFF1D\u56DE $SHELL\u3002\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u8D77\u6548\uFF1B\u4EC5 tmux/zellij \u540E\u7AEF\uFF08pty \u76F4\u63A5 exec CLI\uFF0C\u672C\u5C31\u4E0D\u53D7\u5F71\u54CD\uFF09\u3002","botDefaults.launchShellPlaceholder":"\u5982 zsh \u6216 /usr/bin/zsh\uFF1B\u7559\u7A7A\uFF1D\u7528 $SHELL","botDefaults.launchShellSave":"\u4FDD\u5B58\u542F\u52A8 Shell","botDefaults.sectionEnv":"\u73AF\u5883\u53D8\u91CF","botDefaults.envHelp":"\u6CE8\u5165\u5230\u672C bot CLI \u8FDB\u7A0B\u7684\u73AF\u5883\u53D8\u91CF\uFF08JSON \u5BF9\u8C61\uFF09\u3002\u5178\u578B\u7528\u9014\uFF1A\u8BA9\u67D0\u4E2A bot \u8D70 GLM / \u7B2C\u4E09\u65B9 Anthropic\xB7OpenAI \u517C\u5BB9\u670D\u52A1\u5546\u2014\u2014\u586B ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN\uFF08GLM \u56FD\u9645\u7AD9 https://api.z.ai/api/anthropic\uFF0C\u56FD\u5185\u7AD9 https://open.bigmodel.cn/api/anthropic\uFF09\uFF0C\u6216\u8BBE HTTPS_PROXY\u3001CLI \u4E13\u5C5E\u5F00\u5173\u3002\u503C\u4EC5\u63A5\u53D7\u5B57\u7B26\u4E32/\u6570\u5B57/\u5E03\u5C14\uFF1BBOTMUX_ / LARK_APP_ \u7B49 botmux \u4FDD\u7559\u952E\u4F1A\u88AB\u5FFD\u7565\u3002\u4E0B\u4E2A\u65B0\u4F1A\u8BDD\u8D77\u6548\uFF0C\u6309\u4F1A\u8BDD\u6CE8\u5165\u5230 CLI \u8FDB\u7A0B\uFF08\u4E0D\u8FDB\u5171\u4EAB tmux server \u5168\u5C40\uFF0C\u4E0D\u4F1A\u4E32\u5230\u522B\u7684 bot\uFF09\u3002\u7559\u7A7A\uFF1D\u6E05\u9664\u3002\u6CE8\u610F\uFF1A\u503C\u4EE5\u660E\u6587\u5B58\u4E8E bots.json\uFF0C\u4E0D\u662F\u5BC6\u94A5\u4FDD\u9669\u7BB1\u3002","botDefaults.envPlaceholder":`{
|
|
8
|
-
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
|
|
9
|
-
"ANTHROPIC_AUTH_TOKEN": "\u4F60\u7684 GLM Coding Plan key"
|
|
10
|
-
}`,"botDefaults.envSave":"\u4FDD\u5B58\u73AF\u5883\u53D8\u91CF","nav.roles":"\u89D2\u8272\u7BA1\u7406","nav.groupRoles":"\u7FA4\u89D2\u8272","nav.roleProfiles":"Profiles","roles.title":"\u89D2\u8272\u7BA1\u7406","roles.subtitle":"\u7BA1\u7406\u6BCF\u4E2A\u7FA4\u7684 Bot \u89D2\u8272\uFF0C\u5E76\u7EF4\u62A4\u53EF\u590D\u7528\u7684 Profiles\u3002","roleProfiles.title":"Profiles","roleProfiles.subtitle":"\u7EF4\u62A4\u53EF\u590D\u7528\u7684\u591A Bot Profiles\uFF0C\u5E76\u5FEB\u901F\u9884\u89C8\u6216\u5E94\u7528\u5230\u76EE\u6807\u7FA4\u3002","roles.search":"\u641C\u7D22\u7FA4\u540D/Bot/ID","roles.refresh":"\u5237\u65B0","roles.selectHint":"\u2190 \u5C55\u5F00\u7FA4\u7EC4\uFF0C\u9009\u62E9\u4E00\u4E2A Bot \u6765\u7F16\u8F91\u89D2\u8272","roles.editorPlaceholder":`\u8F93\u5165\u89D2\u8272\u63CF\u8FF0\uFF0C\u4F8B\u5982\uFF1A
|
|
11
|
-
\u4F60\u662F\u672C\u7FA4\u7684\u6280\u672F\u987E\u95EE\uFF0C\u8D1F\u8D23\u56DE\u7B54\u6240\u6709\u6280\u672F\u95EE\u9898...`,"roles.configured":"\u5DF2\u914D\u7F6E","roles.unconfigured":"\u672A\u914D\u7F6E","roles.noChats":"\u6682\u65E0\u7FA4\u7EC4","roles.preview":"\u9884\u89C8","roles.previewEmpty":"\uFF08\u7A7A\u5185\u5BB9\uFF09","roles.saved":"\u5DF2\u4FDD\u5B58","roles.delete":"\u5220\u9664","roles.save":"\u4FDD\u5B58","roles.confirmDelete":"\u786E\u8BA4\u5220\u9664\u8BE5 Bot \u5728\u6B64\u7FA4\u7684\u89D2\u8272\u914D\u7F6E\uFF1F","roles.botsWithRoles":"\u4E2A Bot \u5DF2\u914D\u7F6E\u89D2\u8272","roles.emptyError":"\u89D2\u8272\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u8F93\u5165\u5185\u5BB9","roles.saveFailed":"\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5","roles.tabGroups":"\u6309\u7FA4\u7EC4","roles.tabProfiles":"Profiles","roles.profileIdPlaceholder":"profile id\uFF0C\u5982 collab-main","roles.profileIdInvalid":"Profile id \u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u4E0B\u5212\u7EBF\u3001\u77ED\u6A2A\u7EBF\uFF0C\u6700\u957F 64\uFF0C\u4E14\u4E0D\u80FD\u662F . \u6216 ..","roles.openProfile":"\u6253\u5F00","roles.profileSearch":"\u641C\u7D22 profile","roles.profileSelectHint":"\u2190 \u9009\u62E9\u6216\u8F93\u5165\u4E00\u4E2A profile \u6765\u7F16\u8F91","roles.profileEmpty":"\u6682\u65E0 Profiles","roles.profileEntries":"\u4E2A entry","roles.profileMissing":"\u7F3A\u5931","roles.profileRuntimeHint":"Profile \u53EA\u662F\u53EF\u590D\u7528\u5957\u88C5\uFF1BApply \u540E\u5199\u6210\u672C\u7FA4 Role\uFF0C\u4E0D\u589E\u52A0\u8FD0\u884C\u65F6\u5C42\u7EA7\u3002","roles.profileBots":"Bot Entries","roles.profileEditorPlaceholder":"\u8F93\u5165\u5F53\u524D bot \u5728\u8BE5 profile \u4E0B\u7684 Markdown role...","roles.saveEntry":"\u4FDD\u5B58 Entry","roles.profileBotSelectHint":"\u9009\u62E9\u4E00\u4E2A Bot \u6765\u7F16\u8F91\u5B83\u5728\u8BE5 profile \u91CC\u7684 entry","roles.applyToGroup":"Apply \u5230\u7FA4\u7EC4","roles.applyForce":"\u8986\u76D6\u5DF2\u6709\u672C\u7FA4 Role","roles.previewApply":"\u9884\u89C8 Apply","roles.applyProfile":"Apply Profile","roles.applyPickBots":"\u8BF7\u9009\u62E9\u81F3\u5C11\u4E00\u4E2A Bot","roles.applyWouldRefuse":"\u4F1A\u62D2\u7EDD\uFF08\u5DF2\u6709\u672C\u7FA4 Role\uFF09","roles.applyPreviewOk":"\u53EF\u5E94\u7528","roles.applyOk":"\u5DF2\u5E94\u7528","roles.applyFailed":"\u5931\u8D25","roles.confirmDeleteProfileEntry":"\u786E\u8BA4\u5220\u9664\u8BE5 Bot \u5728\u6B64 profile \u91CC\u7684 entry\uFF1F","common.none":"\u65E0","common.loading":"\u52A0\u8F7D\u4E2D\u2026","common.unknown":"\u672A\u77E5","common.now":"\u521A\u521A","common.never":"\u4ECE\u672A","common.all":"\u5168\u90E8","nav.workflows":"\u5DE5\u4F5C\u6D41","nav.workflowCatalog":"\u76EE\u5F55","workflow.subnav.runs":"\u8FD0\u884C","workflow.subnav.catalog":"\u76EE\u5F55","workflow.subnav.v3":"\u65B0\u7248\u5DE5\u4F5C\u6D41 \u2192","workflow.searchPlaceholder":"\u641C\u7D22 runId / workflowId / chatId","workflow.filter.nonTerminal":"\u975E\u7EC8\u6001","workflow.filter.all":"\u5168\u90E8","workflow.status.pending":"\u5F85\u5F00\u59CB","workflow.status.running":"\u8FD0\u884C\u4E2D","workflow.status.waiting":"\u7B49\u5F85\u4E2D","workflow.status.effectAttempting":"\u526F\u4F5C\u7528\u4E2D","workflow.status.timedOut":"\u5DF2\u8D85\u65F6","workflow.status.succeeded":"\u6210\u529F","workflow.status.failed":"\u5931\u8D25","workflow.status.cancelled":"\u5DF2\u53D6\u6D88","workflow.table.run":"\u8FD0\u884C","workflow.table.workflow":"\u5DE5\u4F5C\u6D41","workflow.table.status":"\u72B6\u6001","workflow.table.lastSeq":"\u6700\u540E\u5E8F\u53F7","workflow.table.dangling":"\u60AC\u6302 dEf/dAct/dWait","workflow.table.updated":"\u66F4\u65B0\u65F6\u95F4","workflow.table.chatApp":"\u7FA4\u804A / \u5E94\u7528","workflow.list.failedLoad":"\u52A0\u8F7D\u5931\u8D25\uFF1A{error}","workflow.list.noRuns":"\u6CA1\u6709\u5339\u914D\u7684\u8FD0\u884C\u3002","workflow.list.noFilterMatch":"\u6CA1\u6709\u7B26\u5408\u7B5B\u9009\u6761\u4EF6\u7684\u8FD0\u884C\u3002","workflow.list.loaded":"{count} \u4E2A\u8FD0\u884C \xB7 \u5237\u65B0\u4E8E {time}","workflow.list.error":"\u9519\u8BEF\uFF1A{error}","workflow.detail.back":"\u8FD4\u56DE","workflow.detail.loading":"\u52A0\u8F7D\u4E2D...","workflow.detail.loadFailed":"\u52A0\u8F7D\u5931\u8D25","workflow.detail.cancel":"\u53D6\u6D88","workflow.detail.cliCancelOnly":"\u4EC5 CLI \u53EF\u53D6\u6D88","workflow.detail.cancelTitle":"\u53D6\u6D88\u8FD9\u4E2A\u5DE5\u4F5C\u6D41\u8FD0\u884C","workflow.detail.cliCancelTitle":"\u65E0\u6CD5\u5728\u9875\u9762\u53D6\u6D88\uFF1A\u8BF7\u4F7F\u7528 botmux workflow cancel {runId}","workflow.detail.nodes":"\u8282\u70B9 / Activity","workflow.detail.parallel":"\u5E76\u53D1\u6267\u884C","workflow.detail.parallelMeta":"{count} \u6B21\u5C1D\u8BD5 \xB7 \u6700\u9AD8\u5E76\u53D1 {max} \xB7 \u8FD0\u884C\u4E2D {running}","workflow.detail.noParallelData":"\u8FD8\u6CA1\u6709 attempt \u65F6\u95F4\u6570\u636E\u3002","workflow.detail.parallelNow":"\u73B0\u5728","workflow.detail.node":"\u8282\u70B9","workflow.detail.nodeStatus":"\u8282\u70B9\u72B6\u6001","workflow.detail.activity":"Activity","workflow.detail.activityStatus":"Activity \u72B6\u6001","workflow.detail.attempts":"\u5C1D\u8BD5\u6B21\u6570","workflow.detail.current":"\u5F53\u524D\u5C1D\u8BD5","workflow.detail.detail":"\u8BE6\u60C5","workflow.detail.nodeIO":"\u8282\u70B9\u8F93\u5165\u8F93\u51FA","workflow.detail.timeline":"\u65F6\u95F4\u7EBF","workflow.detail.loadOlder":"\u52A0\u8F7D\u66F4\u65E9\u4E8B\u4EF6","workflow.detail.seq":"\u5E8F\u53F7","workflow.detail.actor":"\u6267\u884C\u8005","workflow.detail.error":"\u9519\u8BEF","workflow.detail.event":"\u4E8B\u4EF6","workflow.detail.time":"\u65F6\u95F4","workflow.detail.refreshed":"\u5237\u65B0\u4E8E {time}","workflow.detail.unknownRun":"\u672A\u77E5\u8FD0\u884C","workflow.detail.snapshotHttp":"snapshot HTTP {status}","workflow.detail.eventsHttp":"events HTTP {status}","workflow.detail.cancelUnavailable":"\u65E0\u6CD5\u53D6\u6D88\uFF1A\u8BF7\u4F7F\u7528 botmux workflow cancel {runId}","workflow.detail.cancelConfirm":`\u786E\u8BA4\u53D6\u6D88\u5DE5\u4F5C\u6D41\u8FD0\u884C {runId}\uFF1F
|
|
12
|
-
|
|
13
|
-
{total} \u4E2A\u60AC\u6302\u9879\u4F1A\u7531 cancel recovery \u5904\u7406\u3002
|
|
14
|
-
effects={effects}, activities={activities}, waits={waits}, cancels={cancels}`,"workflow.detail.writeAccessCancel":"\u9700\u8981\u5199\u6743\u9650\uFF1A\u8BF7\u5728\u7EC8\u7AEF\u8FD0\u884C `botmux dashboard` \u83B7\u53D6\u4E00\u6B21\u6027 URL\uFF0C\u6253\u5F00\u540E\u5199\u5165 cookie\uFF0C\u518D\u56DE\u6765\u70B9\u51FB\u53D6\u6D88\u3002","workflow.detail.cancelHttp":"cancel HTTP {status}","workflow.detail.cancelPending":"\u53D6\u6D88\u5DF2\u63D0\u4EA4\uFF1B\u7B49\u5F85\u8FD0\u884C\u4E2D\u7684 activity \u6536\u655B","workflow.detail.writeAccessApproval":"\u9700\u8981\u5199\u6743\u9650\uFF1A\u8BF7\u5728\u7EC8\u7AEF\u8FD0\u884C `botmux dashboard` \u83B7\u53D6\u4E00\u6B21\u6027 URL\uFF0C\u6253\u5F00\u540E\u5199\u5165 cookie\uFF0C\u518D\u56DE\u6765\u5BA1\u6279\u3002","workflow.detail.actionHttp":"{action} HTTP {status}","workflow.detail.approved":"\u5DF2\u901A\u8FC7","workflow.detail.rejected":"\u5DF2\u62D2\u7EDD","workflow.detail.alreadyTerminal":"\u8FD0\u884C\u5DF2\u7EC8\u6001\uFF1B\u672A\u5E94\u7528\u201C{label}\u201D\u3002","workflow.detail.workflowContinue":"{label}\uFF1B\u7B49\u5F85\u5DE5\u4F5C\u6D41\u7EE7\u7EED\u6267\u884C\u3002","workflow.detail.workflowRefreshing":"{label}\uFF1B\u6B63\u5728\u5237\u65B0\u5DE5\u4F5C\u6D41\u72B6\u6001\u3002","workflow.detail.eventsLoaded":"\u5DF2\u52A0\u8F7D {loaded}/{total} \u4E2A\u4E8B\u4EF6","workflow.detail.dangling":"\u60AC\u6302\u9879","workflow.detail.noDangling":"\u6CA1\u6709\u60AC\u6302\u5DE5\u4F5C\u3002","workflow.detail.none":"\u65E0","workflow.detail.noNodes":"\u8FD8\u6CA1\u6709\u8282\u70B9\u3002","workflow.detail.idle":"\u7A7A\u95F2","workflow.detail.noNodeIO":"\u8FD8\u6CA1\u6709\u8282\u70B9\u8F93\u5165\u8F93\u51FA\u3002","workflow.detail.notDispatched":"\u5C1A\u672A\u6D3E\u53D1","workflow.detail.noAttempt":"\u8FD8\u6CA1\u6709\u5C1D\u8BD5","workflow.detail.attempt":"\u5C1D\u8BD5","workflow.detail.authoredInput":"\u539F\u59CB\u8F93\u5165","workflow.detail.resolvedInput":"\u89E3\u6790\u540E\u8F93\u5165","workflow.detail.output":"\u8F93\u51FA","workflow.detail.executionLog":"\u6267\u884C\u65E5\u5FD7","workflow.detail.liveTerminal":"\u5B9E\u65F6\u7EC8\u7AEF","workflow.detail.terminalLive":"\u5728\u7EBF","workflow.detail.terminalClosedShort":"\u5DF2\u5173\u95ED","workflow.detail.terminalClosed":"\u7EC8\u7AEF\u5DF2\u5173\u95ED\u3002\u8BF7\u67E5\u770B\u4E0B\u65B9\u6267\u884C\u65E5\u5FD7\u83B7\u53D6\u6700\u7EC8\u8BB0\u5F55\u3002","workflow.detail.openTerminalNewTab":"\u5728\u65B0\u6807\u7B7E\u9875\u6253\u5F00\u7EC8\u7AEF","workflow.detail.terminalReplay":"\u7EC8\u7AEF\u56DE\u653E","workflow.detail.openReplayNewTab":"\u5728\u65B0\u6807\u7B7E\u9875\u6253\u5F00\u56DE\u653E","workflow.detail.downloadFullLog":"\u4E0B\u8F7D\u5B8C\u6574\u65E5\u5FD7","workflow.detail.terminalResume":"\u8C03\u8BD5\u4F1A\u8BDD","workflow.detail.openResumeNewTab":"\u5728\u65B0\u6807\u7B7E\u9875\u6253\u5F00\u8C03\u8BD5\u4F1A\u8BDD","workflow.detail.resumeSession":"\u7EE7\u7EED\u4F1A\u8BDD","workflow.detail.resumeStarting":"\u6B63\u5728\u542F\u52A8\u2026","workflow.detail.endResumeSession":"\u7ED3\u675F\u8C03\u8BD5\u4F1A\u8BDD","workflow.detail.resumeEnding":"\u7ED3\u675F\u4E2D\u2026","workflow.detail.resumeUnsupportedCli":"{cliId} CLI \u4E0D\u652F\u6301 resume","workflow.detail.resumeMissingCliSession":"\u7F3A\u5C11 cliSessionId\uFF0C\u65E0\u6CD5 resume","workflow.detail.resumeStartFailed":"\u542F\u52A8\u8C03\u8BD5\u4F1A\u8BDD\u5931\u8D25 (HTTP {status})","workflow.detail.resumeEndFailed":"\u7ED3\u675F\u8C03\u8BD5\u4F1A\u8BDD\u5931\u8D25 (HTTP {status})","workflow.detail.writeAccessResume":"\u9700\u8981\u5199\u5165\u6743\u9650\u624D\u80FD resume \u4F1A\u8BDD\u3002","workflow.detail.waitPrompt":"\u7B49\u5F85\u63D0\u793A","workflow.detail.approvalComment":"\u5BA1\u6279\u5907\u6CE8","workflow.detail.optionalComment":"\u53EF\u9009\u5907\u6CE8","workflow.detail.approve":"\u901A\u8FC7","workflow.detail.reject":"\u62D2\u7EDD","workflow.detail.submitting":"\u63D0\u4EA4\u4E2D...","workflow.detail.empty":"\u7A7A","workflow.detail.truncated":"\u5DF2\u622A\u65AD","workflow.detail.noData":"\u6CA1\u6709\u6570\u636E\u3002","workflow.detail.noPreview":"\u6CA1\u6709\u9884\u89C8\u3002","workflow.detail.open":"\u6253\u5F00","workflow.detail.deadline":"\u622A\u6B62","workflow.detail.effect":"\u526F\u4F5C\u7528","workflow.detail.wait":"\u7B49\u5F85","workflow.detail.noEvents":"\u8FD8\u6CA1\u6709\u4E8B\u4EF6\u3002","workflow.summary.workflow":"\u5DE5\u4F5C\u6D41","workflow.summary.status":"\u72B6\u6001","workflow.summary.lastSeq":"\u6700\u540E\u5E8F\u53F7","workflow.summary.updated":"\u66F4\u65B0\u65F6\u95F4","workflow.summary.revision":"\u4FEE\u8BA2","workflow.summary.initiator":"\u53D1\u8D77\u4EBA","workflow.summary.failedNode":"\u5931\u8D25\u8282\u70B9","workflow.summary.cancelOrigin":"\u53D6\u6D88\u6765\u6E90","workflow.summary.chat":"\u7FA4\u804A","workflow.summary.app":"\u5E94\u7528","workflow.dangling.activities":"Activities","workflow.dangling.effects":"Effects","workflow.dangling.waits":"Waits","workflow.dangling.cancels":"Cancels","catalog.title":"\u5DE5\u4F5C\u6D41\u76EE\u5F55","catalog.subtitle":"\u4ECE\u5DF2\u4FDD\u5B58\u7684 workflow \u5B9A\u4E49\u521B\u5EFA\u4E00\u6B21\u8FD0\u884C\u3002","catalog.searchPlaceholder":"\u641C\u7D22 workflowId / \u8DEF\u5F84","catalog.refresh":"\u5237\u65B0","catalog.loading":"\u6B63\u5728\u52A0\u8F7D\u76EE\u5F55...","catalog.loadFailed":"\u76EE\u5F55\u52A0\u8F7D\u5931\u8D25\uFF1A{error}","catalog.noDefinitions":"\u6CA1\u6709\u627E\u5230 workflow \u5B9A\u4E49\u3002","catalog.noFilterMatch":"\u6CA1\u6709\u7B26\u5408\u7B5B\u9009\u6761\u4EF6\u7684\u5B9A\u4E49\u3002","catalog.table.workflow":"\u5DE5\u4F5C\u6D41","catalog.table.version":"\u7248\u672C","catalog.table.params":"\u53C2\u6570","catalog.table.nodes":"\u8282\u70B9","catalog.table.revision":"\u4FEE\u8BA2","catalog.table.path":"\u8DEF\u5F84","catalog.paramSummary":"{required}/{total} \u5FC5\u586B","catalog.back":"\u8FD4\u56DE\u76EE\u5F55","catalog.detailTitle":"\u5DE5\u4F5C\u6D41\u5B9A\u4E49","catalog.definitionLoadFailed":"\u5B9A\u4E49\u52A0\u8F7D\u5931\u8D25\uFF1A{error}","catalog.summary":"\u6458\u8981","catalog.paramsSchema":"\u53C2\u6570 Schema","catalog.definitionJson":"\u5B9A\u4E49 JSON","catalog.runPanel":"\u8FD0\u884C\u5DE5\u4F5C\u6D41","catalog.paramsJson":"\u53C2\u6570 JSON","catalog.paramsPlaceholder":`{
|
|
15
|
-
"city": "\u5317\u4EAC"
|
|
16
|
-
}`,"catalog.chatId":"\u7FA4\u804A ID","catalog.larkAppId":"\u98DE\u4E66\u5E94\u7528 ID","catalog.chatBindingHint":"\u5FC5\u586B\uFF0C\u7528\u4E8E\u786E\u5B9A humanGate \u5361\u7247\u53D1\u9001\u5230\u54EA\u4E2A\u98DE\u4E66\u7FA4\uFF0C\u4EE5\u53CA\u53D6\u6D88\u8DEF\u7531\u5F52\u5C5E\u3002","catalog.run":"\u8FD0\u884C","catalog.running":"\u542F\u52A8\u4E2D...","catalog.badParamsJson":"\u53C2\u6570\u5FC5\u987B\u662F JSON object\u3002","catalog.writeAccess":"\u9700\u8981\u5199\u6743\u9650\uFF1A\u8BF7\u5728\u7EC8\u7AEF\u8FD0\u884C `botmux dashboard` \u83B7\u53D6\u4E00\u6B21\u6027 URL\uFF0C\u6253\u5F00\u540E\u5199\u5165 cookie\uFF0C\u518D\u56DE\u6765\u8FD0\u884C\u3002","catalog.runHttp":"run HTTP {status}","catalog.runStarted":"\u8FD0\u884C\u5DF2\u542F\u52A8\uFF1B\u6B63\u5728\u6253\u5F00\u8BE6\u60C5\u9875...","catalog.invalidParams":"\u53C2\u6570\u65E0\u6548","catalog.issue":"{path}: {message}","catalog.noParams":"\u6CA1\u6709\u58F0\u660E\u53C2\u6570\u3002","catalog.required":"\u5FC5\u586B","catalog.optional":"\u53EF\u9009","catalog.default":"\u9ED8\u8BA4\u503C","catalog.description":"\u8BF4\u660E","catalog.path":"\u8DEF\u5F84","catalog.revision":"\u4FEE\u8BA2","catalog.nodeCount":"\u8282\u70B9\u6570"},Ed={"app.name":"botmux","app.subtitle":"Feishu AI CLI Control","time.secondsAgo":"{value}s ago","time.minutesAgo":"{value}m ago","time.hoursAgo":"{value}h ago","nav.overview":"Overview","nav.sessions":"Sessions","nav.sidebarCollapse":"Collapse sidebar","nav.sidebarExpand":"Expand sidebar","nav.groups":"Groups","nav.schedules":"Schedules","nav.settings":"Settings","nav.botDefaults":"Bot Defaults","nav.skills":"Skills","status.live":"Live","status.disconnected":"Disconnected","status.system":"System","status.light":"Light","status.dark":"Dark","status.language":"Language","status.theme":"Theme","theme.base":"Basic","theme.skins":"Skins","skin.cyber":"2077","skin.genshin":"Genshin","skin.fallout":"Fallout","skin.prts":"PRTS","skin.bluearchive":"Blue Archive","skin.zzz":"ZZZ","skin.dragonball":"Dragon Ball","skin.ikun":"ikun","botOnboarding.add":"Add Bot","botOnboarding.title":"Add Bot","botOnboarding.intro":"Pick a CLI and working directory, scan to create a PersonalAgent app \u2014 the dashboard writes it to local bots.json and auto-configures Open Platform permissions.","botOnboarding.cliLabel":"CLI adapter","botOnboarding.dirLabel":"Working directory","botOnboarding.dirPlaceholder":"Default ~ (home); must exist on the daemon host","botOnboarding.modelLabel":"Model (optional)","botOnboarding.modelPlaceholder":"Leave empty for the CLI default model","botOnboarding.modelTtadkPlaceholder":"ttadk gateway model, default {model}, editable anytime","botOnboarding.modelTtadkCocoPlaceholder":"CoCo needs no model","botOnboarding.startScan":"Start scan","botOnboarding.cancel":"Cancel","botOnboarding.starting":"Generating QR code...","botOnboarding.waiting":"Scan with the Feishu app to create the app.","botOnboarding.verifying":"Scan accepted. Verifying credentials...","botOnboarding.configuringPermissions":"Auto-configuring Open Platform permissions\u2026","botOnboarding.platformScanHint":"Scan once more with the Feishu app to sign in to the Open Platform (to auto-import permissions, set the callback, and submit a version).","botOnboarding.platformQrAlt":"Open Platform login QR code","botOnboarding.completed":"Bot added.","botOnboarding.permissionOk":"Auto-imported {count} permissions.","botOnboarding.permissionSkipped":"({count} skipped \u2014 not in the tenant catalog)","botOnboarding.permissionVersion":"Submitted version {version}.","botOnboarding.permissionManual":"Permissions could not be auto-configured. Complete these steps manually:","botOnboarding.metaDir":"Dir","botOnboarding.failed":"Add failed","botOnboarding.openLink":"Open scan link in browser","botOnboarding.close":"Close","botOnboarding.restartHint":"bots.json has been updated. Run pnpm daemon:restart for the new bot to take effect.","botOnboarding.needsOwner":"Could not auto-confirm the scanner identity. Enter an owner manually to finish.","botOnboarding.ownerLabel":"Owner (bot administrator)","botOnboarding.ownerPlaceholder":"Full email / union_id (on_) / open_id (ou_), comma-separated","botOnboarding.ownerHint":"An owner is required so the bot is not left open for anyone to run admin actions. Prefer a company email or union_id (on_).","botOnboarding.ownerSubmit":"Save owner & finish","botOnboarding.ownerEmpty":"Enter at least one owner.","botOnboarding.ownerInvalid":"Owner validation failed. Please check and retry.","botOnboarding.qrAlt":"Feishu bot onboarding QR code","overview.title":"Workbench","overview.subtitle":"Live status of your AI teammates \xB7 synced with Feishu topics","overview.team":"AI Team","overview.teamHint":"Live status of every digital teammate","overview.attention":"Needs You","overview.attentionHint":"Blocked tasks \u2014 one reply gets them moving again","overview.activeSessions":"Active Sessions","overview.activeSessionsHint":"Sessions currently running","overview.today":"Right Now","overview.todayHint":"Active session distribution","overview.viewAll":"View all \u2192","overview.botIdle":"Standing by, ready for new tasks","overview.botOffline":"Offline \u2014 daemon not running","overview.botBusy":"Working \xB7 {count} sessions","overview.botNeedsYou":"Waiting on you","overview.botReady":"Ready","overview.botOff":"Offline","overview.sessionsCount":"{count} sessions","overview.lastActive":"active {time} ago","overview.noAttention":"Nothing waiting on you","overview.teamExpand":"Show all {count} \u25BE","overview.teamCollapse":"Collapse \u25B4","strip.pending":"{count} pending","strip.longest":"waiting {time} \u2014 {bot} {reason}","strip.handle":"Handle now","overview.openSessions":"Active Sessions","overview.workingSessions":"Working","overview.onlineBots":"Online Bots","overview.schedules":"Schedules","overview.groups":"Groups Seen","overview.enabledSchedules":"Enabled","overview.total":"total","overview.active":"active","overview.daemonRegistry":"daemon registry","overview.chatMatrix":"chat matrix","overview.recentSessions":"Recent Sessions","overview.nextSchedules":"Next Runs","overview.noSessions":"No sessions yet.","overview.noSchedules":"No schedules yet.","sessions.title":"Session Control","sessions.subtitle":"Locate Feishu topics, open Web Terminal, close or resume CLI sessions.","sessions.search":"Search working dir / title / IDs","sessions.anyStatus":"Any status","sessions.adoptAny":"adopt: any","sessions.adoptYes":"adopt: yes","sessions.adoptNo":"adopt: no","sessions.activeOnly":"Active only","sessions.closeSelected":"Close selected","sessions.clearSelection":"Clear","sessions.selectedCount":"{count} sessions selected","sessions.idleCleanupOlderThan":"Idle over","sessions.idleCleanupThreshold":"Idle cleanup threshold","sessions.idleCleanupRun":"Clean idle","sessions.idleCleanupCount":"{count} cleanable","sessions.idleCleanupConfirm":"Close {count} sessions idle for more than {threshold}?","sessions.idleCleanupRunning":"Cleaning\u2026","sessions.idleCleanupDone":"Closed {closed}, failed {failed}","sessions.idleCleanupFailed":"Cleanup failed","sessions.lock":"Lock session","sessions.unlock":"Unlock session","sessions.locked":"Locked","sessions.lockSelected":"Lock selected","sessions.unlockSelected":"Unlock selected","sessions.lockFailed":"Failed to update lock state","sessions.bot":"Bot","sessions.cli":"CLI","sessions.chat":"Chat","sessions.openChat":"Open chat","sessions.status":"Status","sessions.tokenIn":"Token In","sessions.tokenOut":"Token Out","sessions.titleCol":"Title","sessions.workingDir":"Working Dir","sessions.created":"Created","sessions.last":"Last","sessions.adopt":"Adopt","sessions.actions":"Actions","sessions.details":"Details","sessions.copy":"Copy","sessions.copied":"Copied","sessions.locate":"Locate Topic","sessions.locating":"Sending...","sessions.cooldown":"Cooldown {seconds}s","sessions.openTerminal":"Terminal","sessions.writeLink":"Write Link","sessions.writeLinkHint":"Get a writable terminal link (carries a write-access token; opens in a new tab)","sessions.writeLinkFail":"Failed to get write link","sessions.close":"Close Session","sessions.restart":"Restart CLI","sessions.restartConfirmIntro":"You are about to restart this CLI.","sessions.restartConfirmStatus":"Current status","sessions.restartConfirmCli":"CLI","sessions.restartConfirmQuestion":"Restart this CLI?","sessions.restartFailed":"Restart failed","sessions.resume":"Resume Session","sessions.dismiss":"Close","sessions.closeConfirm":"Close this session?","sessions.resumeFailed":"Resume failed","sessions.land":"Land","sessions.landLoading":"Loading sandbox diff\u2026","sessions.landUnavailable":"Cannot land","sessions.landEmpty":"No changes in the sandbox clone.","sessions.landApply":"Apply to disk","sessions.landDiscard":"Discard","sessions.landApplied":"Landed","sessions.landFailed":"Land failed","sessions.landDiscarded":"Discarded (sandbox clone not applied).","sessions.insight":"Insight","sessions.insightLoading":"Analyzing\u2026","sessions.insightUnavailable":"Insight unavailable","sessions.insightEmpty":"No analyzable tool spans in this session yet.","sessions.insightMetrics":"spans {total} \xB7 failed {failed} \xB7 slow {slow} \xB7 read/write {rw} \xB7 compactions {compactions}","sessions.insightSuggestions":"Suggestions","sessions.insightSpans":"Action spans","sessions.insightCapped":"showing first {shown}/{total}","sessions.insightAsOf":"as of {asOf}","sessions.insightPartial":"(may exclude the in-flight latest turn)","nav.insights":"Insight","insights.title":"Workflow Insight","insights.subtitle":"Read-only analysis of local Claude Code / Codex sessions \u2014 action trace, failures, friction, with rule-based optimization tips.","insights.refresh":"Refresh","insights.search":"Search session / bot / dir\u2026","insights.filter":"Filter","insights.filterAll":"All","insights.filterReview":"Worth review","insights.filterFailed":"Has failures","insights.filterSlow":"Has slow spans","insights.loading":"Analyzing\u2026","insights.loaded":"Loaded {count} sessions","insights.unavailable":"Load failed","insights.listCount":"showing {shown}/{total}","insights.tabOverview":"Overview","insights.tabSessions":"Sessions","insights.tabDist":"Distribution","insights.tabHot":"Hotspots","insights.projectAll":"All projects","insights.timeAll":"All time","insights.time1d":"Last 1d","insights.time7d":"Last 7d","insights.time30d":"Last 30d","insights.clear":"Clear","insights.emptyAnalyzableHint":"Check \u201CIncl. unanalyzed\u201D to see the remaining sessions.","insights.showAll":"Incl. unanalyzed","insights.distHint":"Metric distribution across the currently filtered sessions \u2014 see the shape and where typical values land.","insights.distSpans":"Spans per session","insights.distFailed":"Failures per session","insights.distSlow":"Slow spans per session","insights.distAgentTime":"Agent working time","insights.distRw":"Read/write ratio","insights.distChurn":"Code churn (lines)","insights.distTrend":"Trend by day (last 4 weeks)","insights.distTrendSub":"sessions / day","insights.distMedian":"median {v}","insights.distEmpty":"No analyzable sessions under the current filter.","insights.disclosure":`Measurement note: durations count tool-execution time only and exclude time spent waiting for a user reply (question / plan approval), so they do not reflect wall-clock; Codex reads files mostly via shell (exec_command), not counted as "read", so its read/write ratio runs low or 0; code churn is parsed from patches and covers only each session's most active files. Cross-tool distributions and ratios are indicative only, not directly comparable.`,"insights.rwNote":"Codex reads mostly via shell, not counted as reads","insights.viewSessions":"View sessions","insights.hotHint":"Cross-session recurrence \u2014 where it pays to converge.","insights.hotToolFailures":"Tool failure hotspots","insights.hotSlowSessions":"Slowest sessions","insights.hotProjects":"Projects","insights.hotFiles":"File recurrence","insights.hotCommands":"Command recurrence","insights.hotErrors":"Error recurrence","insights.hotComingSoon":"File / command recurrence hotspots coming soon (needs cross-session engine aggregation).","insights.hotSessionsCol":"sessions","insights.hotFailsCol":"fails","insights.hotSlowCol":"slow","insights.backToList":"Back to list","insights.sortLabel":"Sort","insights.sortRecent":"Recent","insights.sortReview":"Review","insights.sortSpans":"Spans","insights.sortFails":"Failures","insights.sortSlow":"Slow","insights.sortAgent":"Duration","insights.layoutCard":"Cards","insights.layoutTable":"Table","insights.colTitle":"Session","insights.colProject":"Project","insights.colTime":"Time","insights.paletteOpen":"Jump \u2318K","insights.palettePlaceholder":"Jump to a tab or search sessions\u2026","insights.paletteTabs":"Views","insights.paletteSessions":"Sessions","insights.paletteEmpty":"No matches","insights.tabFlow":"Flow","insights.flowHint":"Where the agent spends its actions and time across activity phases, and each session\u2019s rhythm.","insights.flowPipeline":"Activity-phase pipeline","insights.flowPipeSub":"research \u2192 edit \u2192 run \u2192 delegate \u2192 discuss; top = actions, bottom = time","insights.flowShares":"Action share vs time share","insights.flowActShare":"Action share","insights.flowTimeShare":"Time share","insights.flowRhythm":"Per-session rhythm (by duration)","insights.subagents":"Sub-agents","insights.subagentsHint":"Sub-agents this session delegated to (Task/Agent) \u2014 what each did and how long it ran.","insights.readsShort":"read","insights.editsShort":"edit","insights.durShort":"dur","insights.empty":"No matching sessions.","insights.selectSession":"Pick a session on the left to see action spans and suggestions.","insights.detailLoading":"Loading session detail\u2026","insights.recommendations":"Suggestions","insights.recommendationsHint":"Rule-based cross-session rollup, each traceable to a metric.","insights.noRecommendations":"No suggestions.","insights.seenInSessions":"seen in {count} sessions","insights.toolFailures":"Top tool failures","insights.toolFailuresHint":"Failed spans grouped by tool.","insights.noFailures":"No failed spans.","insights.metricSessions":"Sessions","insights.metricAnalyzed":"{count} analyzed","insights.metricSpans":"Spans","insights.metricSafe":"redacted","insights.metricFailed":"Failed spans","insights.metricSlow":"Slow spans","insights.metricRw":"Read/write","insights.metricCompactions":"compactions {count}","insights.spansShort":"span ","insights.failedShort":"fail ","insights.slowShort":"slow ","insights.rwShort":"r/w ","insights.unsupported":"CLI not supported","insights.noTranscript":"No transcript","insights.parseError":"Parse failed","insights.noSpans":"No analyzable spans.","insights.sevBad":"Critical","insights.sevWarn":"Warn","insights.sevInfo":"Info","insights.phase.research":"Research","insights.phase.edit":"Edit","insights.phase.run":"Run","insights.phase.delegate":"Delegate","insights.phase.discuss":"Discuss","insights.trace":"Action spans","insights.ledger":"Per-turn ledger","insights.detailTabs":"Detail views","insights.spanStatus":"Status","insights.spanTool":"Tool","insights.spanPhase":"Phase","insights.spanDuration":"Duration","insights.spanTurn":"Turn","insights.spanSummary":"Summary","insights.ledgerMore":"Show {count} more summaries","insights.ledgerOmitted":"{count} more hidden","insights.ledgerNoContent":"No redacted summary for this turn.","insights.diagShow":"Show evidence","insights.diagActive":"Viewing","insights.evMatched":"{count} matching spans","insights.evMatchedCapped":"{matched} matched \xB7 showing {shown}","insights.evDefault":"{shown} of {total} spans (focused)","insights.evShowAll":"Show all {count}","insights.evBackToEvidence":"Focused view","insights.intent.run_script":"Run script","insights.intent.test":"Test","insights.intent.typecheck":"Typecheck","insights.intent.lint":"Lint","insights.intent.git":"Git","insights.intent.search":"Search","insights.intent.read_file":"Read","insights.intent.edit_file":"Edit","insights.intent.write_file":"Write","insights.intent.delegate":"Delegate","insights.intent.unknown":"Action","insights.result.ok":"OK","insights.result.tool_error":"Tool error","insights.result.test_failed":"Test failed","insights.result.typecheck_failed":"Typecheck failed","insights.result.lint_failed":"Lint failed","insights.result.command_failed":"Command failed","insights.result.timeout":"Timeout","insights.result.no_output":"No output","insights.result.unknown":"Unknown","insights.tag.failure":"Failures","insights.tag.slow":"Slow","insights.tag.retry":"Retries","insights.tag.read_write_imbalance":"Read/write imbalance","insights.tag.diagnostic":"Diagnostic","insights.tag.normal":"Normal","insights.turnHeadline.turn_has_failures":"{failures} failures this turn","insights.turnHeadline.turn_has_slow_spans":"Slow operations this turn","insights.turnHeadline.turn_has_retries":"Retried the same action repeatedly","insights.turnHeadline.turn_read_write_imbalance":"Edit-heavy turn (edits {edits} / reads {reads})","insights.evTimeline":"Full timeline ({count} spans)","insights.evNoFlags":"No spans flagged as failure / slow / retry","insights.turnAllNormal":"All {count} turns look normal \u2014 nothing to review","insights.turnEvidence":"View {count} evidence spans","insights.turnHiddenNormal":"{count} normal turns hidden","insights.mReads":"Read","insights.mEdits":"Edit","insights.mRuns":"Run","insights.mFailures":"Fail","insights.mDur":"Time","insights.turnHeadline.turn_normal":"Normal","insights.rec.fix_repeated_tool_failures":"Repeated command failures need to converge","insights.rec.split_slow_operation":"Slow operations dragged the whole session","insights.rec.add_read_pass_before_edit":"Too little reading before editing","insights.rec.preserve_context_checkpoints":"Context was compacted \u2014 keep checkpoints","insights.impact.impact_failed_spans":"{failedSpans} actions failed (top: {topTool} \xD7{topToolFailures})","insights.impact.impact_slow_spans":"{slowSpansTotal} slow operations slowed progress","insights.impact.impact_low_read_write_ratio":"Edited {writeSpans}, read only {readSpans}","insights.impact.impact_context_compaction":"{compactions} context compactions this session","insights.why.why_tool_failure_concentrated":"Failures concentrate on {topTool} ({topToolFailures}\xD7) \u2014 likely one root cause","insights.why.why_slow_span_dominates":"A few long operations dominate; slowest is {slowestTool}","insights.why.why_edits_outpaced_reads":"Read/write ratio {readWriteRatio}; editing more than reading invites rework","insights.why.why_context_compaction_happened":"Long session was compacted; early decisions/context may be lost","insights.action.inspect_failed_span_details":"Open each failed action\u2019s detail to find the root cause","insights.action.add_preflight_or_timeout":"Add preflight checks or timeouts to frequently failing commands","insights.action.narrow_or_split_slow_operation":"Narrow or split slow operations (e.g. run targeted tests)","insights.action.surface_timeout_or_progress":"Surface timeouts/progress earlier instead of silently hanging","insights.action.read_or_search_before_editing":"Read or search an unfamiliar file before editing it","insights.action.verify_assumptions_before_running":"Verify assumptions before acting to avoid blind edits","insights.action.write_checkpoints_for_long_tasks":"Write decisions and checkpoints to notes for long tasks","insights.struct.shell":"shell command","insights.struct.fileEdit":"file edit","insights.struct.readSearch":"read/search","insights.struct.agentTask":"agent task","insights.struct.toolInput":"tool input","insights.struct.toolResult":"tool result","insights.struct.toolError":"tool error","insights.struct.patchFailed":"patch failed","insights.struct.patchApplied":"patch applied","insights.struct.exit":"exit {code}","insights.spanAll":"All","insights.dDetail":"Detail","insights.dCollapse":"Hide","insights.dPhase":"Phase","insights.dStart":"Start","insights.dDur":"Duration","insights.dIntent":"Intent","insights.dResult":"Result","insights.dIn":"Input","insights.dOut":"Output","insights.dTags":"Tags","insights.dTurnContext":"Turn {turn} context","insights.advice.failure":"\u{1F4A1} Read the error before retrying \u2014 don\u2019t retry blindly","insights.advice.retry":"\u{1F4A1} Same step retried repeatedly \u2014 find the root cause first","insights.advice.read_write_imbalance":"\u{1F4A1} Read the relevant files before editing to avoid rework","insights.advice.slow":"\u{1F4A1} Slow op: run targeted tests or split it up","insights.turnPrompt":"User","insights.turnExpand":"Expand {count} steps","insights.turnCollapse":"Collapse","insights.turnRail":"Session trace","insights.gantt":"Work timeline","insights.ganttCaption":"{span} actions \xB7 {dur} elapsed \xB7 {active} active","insights.ctxCurve":"Context curve","insights.ctxCaption":"Per-turn in+cache peak \xB7 max {peak} \xB7 {turns} turns","insights.ctxTurn":"Turn {n}","insights.railSubagent":"Subagent","insights.railSubagents":"{n} subagents","insights.turnPromptExpand":"Expand","insights.turnPromptCollapse":"Collapse","insights.turnPromptRaw":"Raw","insights.turnPromptRendered":"Rendered","insights.srcMentions":"mentions","insights.senderHuman":"User","insights.senderA2A":"A2A","insights.senderOther":"Other","insights.senderSystem":"System","insights.turnPromptFull":"Full text","insights.modalClose":"Close","insights.promptTruncated":"Long content, truncated","insights.replay":"Replay","insights.replayAgent":"agent ops","insights.replaySearch":"Search conversation\u2026","insights.replayBy":"From","insights.replayState":"State","insights.replayLoadMore":"Load more ({shown}/{total})","insights.replayAllLoaded":"All loaded ({total})","insights.replayEmpty":"No matching messages","insights.replayNoText":"(no text \u2014 see ops)","insights.replayOps":"{count} ops","insights.wsFiles":"File changes \xB7 {n}","insights.wsCmds":"Commands \xB7 {n}","insights.wsReads":"read {n}","insights.wsEdits":"edit {n}","insights.wsFail":"{n} failed","insights.wsNoFiles":"No file changes","insights.wsNoCmds":"No commands","insights.turnSummary":"{total} turns \xB7 {flagged} need attention","insights.dCommand":"Command","insights.dCmdOutput":"Output","insights.ledgerNormal":"By order","insights.ledgerGrouped":"By recommendation","insights.ledgerOther":"Other turns","insights.ledgerGroupCount":"{count} turns","insights.turnsCapped":"Only first {shown}/{total} actions \u2014 timeline may be incomplete","insights.suggestion.high_tool_failure.title":"Tool failures are concentrated","insights.suggestion.high_tool_failure.action":"Check failed spans first, then add preflight checks or timeout control for repeated failing commands.","insights.suggestion.tool_failure_present.title":"Some tool calls failed","insights.suggestion.tool_failure_present.action":"Review failed spans before repeating the workflow.","insights.suggestion.slow_span.title":"A slow span dominates the session","insights.suggestion.slow_span.action":"Split or bound the slow operation, and surface timeout or progress feedback earlier.","insights.suggestion.low_read_write_ratio.title":"Edits outpaced reads","insights.suggestion.low_read_write_ratio.action":"Add a read/search pass before edits when changing unfamiliar files.","insights.suggestion.context_compaction.title":"Context compaction happened","insights.suggestion.context_compaction.action":"For long tasks, preserve decisions and checkpoints in durable notes or smaller subtasks.","insights.suggestion.no_major_friction.title":"No major trace friction detected","insights.suggestion.no_major_friction.action":"Use the span timeline for spot checks or compare against slower sessions.","insights.evidence.failedSpans":"{count} failed spans","insights.evidence.toolFailedTimes":"{tool} failed {count} times","insights.evidence.multipleToolsFailed":"multiple tools failed","insights.evidence.toolRanSeconds":"{tool} ran for {seconds}s","insights.evidence.readWriteRatio":"read/write ratio {ratio}","insights.evidence.compactions":"compactions {count}","insights.evidence.spansAnalyzed":"{count} spans analyzed","connectors.lede":"Let external systems (alerts, CI, tickets\u2026) trigger a bot to speak in a group or run a workflow via one webhook.","connectors.createTitle":"New Webhook","connectors.fName":"Name","connectors.fNamePh":"e.g. Prod alerts","connectors.fBot":"Trigger bot","connectors.fKind":"Trigger type","connectors.kindTurn":"Single turn (bot responds once)","connectors.kindWorkflow":"Workflow","connectors.fWf":"Workflow ID","connectors.fMode":"Deliver to which group","connectors.modeDynamic":"Specified per request (chat passed in)","connectors.modeFixed":"Fixed group","connectors.modeNewGroup":"New group each time","connectors.fFixedChat":"Target group","connectors.fChatManualPh":"Enter chat ID manually: oc_\u2026","connectors.chatManualLink":"Group not listed? Enter ID manually \u2192","connectors.chatListLink":"\u2190 Pick from group list","connectors.fAllow":"Allowed groups","connectors.optional":" (optional)","connectors.allowHint":"Hold Ctrl/\u2318 to multi-select; empty = unrestricted. Only validates the chat passed in the request.","connectors.dynamicHint":'<b>Dynamic mode</b>: the chat ID is passed per request, one of three ways \u2014 query <code>?chatId=<chatId></code> \xB7 header <code>x-botmux-chat-id: <chatId></code> \xB7 body <code>{"chatId":"<chatId>"}</code>.<br>For "one URL triggers directly, no params", choose Fixed group instead.',"connectors.fDedup":"Dedup field","connectors.fDedupPh":"e.g. alert.id (read from event body)","connectors.dedupHint":"Set: events with the same value go to the <b>same group</b>. Empty: each event <b>creates a new group</b>.","connectors.fInstruction":"Instruction","connectors.fInstructionPh":"What the bot should do on the event. e.g. Summarize the severity, @ the oncall, suggest next steps. Empty = hand the raw event to the model.","connectors.fVerify":"Verification","connectors.verifyToken":"Token (simple: secret in the URL, one curl triggers it)","connectors.verifyHmac":"HMAC signature (advanced: more secure, sign the request yourself)","connectors.fSecret":"Secret / token","connectors.fSecretPh":"Leave empty to auto-generate (shown once)","connectors.btnCreate":"Create","connectors.listTitle":"Existing Webhooks","connectors.loading":"Loading\u2026","connectors.noBotGroups":"(This bot has no visible groups; enter an ID manually on the right)","connectors.modeLabelFixed":"Fixed group","connectors.modeLabelNewGroup":"New group each time","connectors.modeLabelDynamic":"Per-request group","connectors.kindLabelWorkflow":"Workflow","connectors.kindLabelTurn":"Single turn","connectors.count":"\xB7 {count}","connectors.empty":"No webhooks yet. Create one with the form above.","connectors.enabled":"Enabled","connectors.disabled":"Disabled","connectors.badgeToken":"Token","connectors.badgeSign":"Signed","connectors.dest":'to "{name}"',"connectors.btnDisable":"Disable","connectors.btnEnable":"Enable","connectors.btnEdit":"Edit","connectors.btnSave":"Save","connectors.btnCancel":"Cancel","connectors.btnDel":"Delete","connectors.webhookUrl":"Webhook URL: ","connectors.copy":"Copy","connectors.copied":"Copied","connectors.tokenHint":"Token mode: append <code>/<token></code> to the URL when calling (the token is shown only on create/rotate).","connectors.dynamicReqHint":'Dynamic mode: the request must carry the target chat \u2014 <code>?chatId=<chatId></code> or header <code>x-botmux-chat-id</code> or body <code>{"chatId":"\u2026"}</code>.',"connectors.instructionPrefix":"Instruction: ","connectors.delConfirm":"Delete this webhook? Its URL stops working immediately.","connectors.errName":"Enter a name","connectors.errBot":"Pick a bot","connectors.errWf":"Enter a workflow ID","connectors.errChat":"Pick (or enter) a target group","connectors.creating":"Creating\u2026","connectors.saving":"Saving\u2026","connectors.usageDynamicLede":"Dynamic mode: the URL already has the token; pass the target chat ID when calling{gn}:","connectors.usageDynamicNote":'The chat can also go in header <code>x-botmux-chat-id</code> or body <code>{"chatId":"\u2026"}</code>. \u26A0\uFE0F The URL is the credential \u2014 keep it secret.',"connectors.usageTokenLede":"This URL already has the token and a fixed target group; just POST to trigger:","connectors.usageTokenNote":"\u26A0\uFE0F The URL is the credential \u2014 keep it private; delete or rotate it in the list below.","connectors.usageHmac":"The external system must HMAC-SHA256-sign <code>timestamp.body</code> and call with <code>x-botmux-timestamp</code> / <code>x-botmux-nonce</code> / <code>x-botmux-signature</code> headers","connectors.usageHmacDynamic":", and also pass the target chat ID as above","connectors.createdPrefix":'Created "{name}"',"connectors.createdDest":'to "{name}"',"connectors.tokenLabel":"Access token","connectors.signLabel":"Signing secret","connectors.secretOnce":" (shown once \u2014 save it): ","connectors.createFailed":"Create failed: {error}","connectors.saveFailed":"Save failed: {error}","connectors.noOnlineBots":"(No online bots)","team.navHome":"My team","team.navManage":"Team management","team.eyebrow":"Team","team.homeTitle":"Team collaboration (cross-deployment)","team.homeLede":"Invite other deployments (botmux instances teammates run) into one team to discover bots across deployments and pull collaborative groups.","team.localDeployTitle":"This deployment","team.myIdentity":"My Lark identity: ","team.unbound":"Not bound","team.bindBtn":"Bind","team.bindHint":" (auto-identifies you via the bot credentials; once bound, pulling a group adds you and attributes the bots to you)","team.myTeams":"My teams","team.searchPh":"Search name / capability / CLI\u2026","team.allCli":"All CLIs","team.hasCap":"Has capability tag","team.hasRole":"Has default role","team.teamsHint":"Tick bots in any team to pull them into a group (each with its owner). To create a team / generate an invite code / join another team, go to Team management.","team.loading":"Loading\u2026","team.roleModalTitle":"Default role","team.roleModalHint":"The bot default persona (applies across groups), read-only here. To edit, go to the Bot Defaults page.","team.close":"Close","team.tagLocal":"This deployment","team.tagRemoteStale":"Remote \xB7 offline?","team.tagRemote":"Remote","team.removeMember":"Remove","team.depTag":"({tag})","team.depCount":"{count}","team.depSelected":", {n} selected","team.capPh":"Capability tag\u2026","team.viewRole":"View","team.hasRoleShort":"Has role","team.noMatch":"No bots match the filters.","team.gnamePh":"Group name (e.g. cross-team triage)","team.pullGroupBtn":"Pull ticked bots into a group","team.pullGroupHint":"Tick bots \u2192 pull into a Lark group (owner included automatically)","team.noTeams":"No teams yet. Go to Team management to generate an invite code for others to join you, or join another team.","team.connected":"Connected","team.connectFail":"Connection failed: {error}","team.iHost":"I host","team.teamMeta":"{deps} deployments \xB7 {bots} bots","team.rosterFail":"Could not fetch this team roster.","team.acrossTeams":" (across {n} teams, deduped)","team.botsWord":"bots","team.groupCreated":"Group created","team.delegatedBy":' (created by "{name}")',"team.openInLark":"Open in Lark","team.invalidBots":"Bots not added: {ids}","team.invalidOwners":"{n} owner(s) could not be added","team.missingIdentity":"You have not bound a Lark identity, so you were not added to the group (bind it in My team)","team.skippedNoOwner":"{n} bot(s) skipped because their owner has no bound identity (not added)","team.errNoLocalBot":"Tick at least one of your own (this deployment) online bots \u2014 the group is created by it and adds you (the initiator).","team.errAllSkipped":"None of the selected bot owners have a bound identity, so the group cannot be pulled (a bot cannot join a group without its owner). Have those deployments bind an identity first.","team.errNoCreator":"No available group creator (the relevant deployments have no online bot, or are unreachable)","team.errDelegationTimeout":"Timed out delegating group creation to the other deployment (it may have succeeded \u2014 check Lark, do not retry)","team.errGroupCreate":"Group creation failed: {error}","team.roleModalTitleName":"Default role \xB7 {name}","team.bound":"Bound","team.myHostedTeam":"My hosted team","team.remoteTeamLabel":"{name} team","team.manageTitle":"Team management","team.manageLede":"Create multiple teams, generate an invite code per team, or join another team. A team = this deployment bots + the other deployments that joined it.","team.hostedTitle":"Teams I host","team.newTeamPh":"New team name","team.createTeamBtn":"Create team","team.joinTitle":"Join another team","team.hubPh":"Hub address, e.g. http://10.0.0.5:7891","team.codePh":"Invite code","team.joinBtn":"Join","team.noTeamsShort":"No teams yet.","team.default":"Default","team.manageMetaDeps":"{count} deployments","team.manageMetaRemote":" (incl. {r} remote)","team.manageMetaBots":"{count} bots","team.genInvite":"Generate invite code","team.delBtn":"Delete","team.generating":"Generating\u2026","team.inviteResultLede":"Send the two items below to someone on another deployment (valid once, within 24h):","team.inviteHub":"Hub address: ","team.inviteCode":"Invite code: ","team.genFail":"Generation failed.","team.delConfirm":'Delete team "{name}"? Deployments that joined it will be removed (their own deployments are unaffected).',"team.errName":"Enter a team name","team.creating":"Creating\u2026","team.created":"Created","team.createFail":"Create failed: {error}","team.errHubCode":"Enter the hub address and invite code.","team.joining":"Joining\u2026","team.joined":'Joined "{name}" \u2014 see it in My team.',"team.joinErrSelf":"This is your own deployment; you cannot join yourself (the invite code is for someone on another deployment).","team.joinErrAlready":"Your deployment already joined this team.","team.joinErrUnreachable":"Cannot reach the hub (check the address/network).","team.joinErrTimeout":"The hub timed out.","team.joinErrGeneric":"Join failed: {error}","team.identifying":"Identifying\u2026","team.bound2":"Bound: {name}","team.multiCandidate":"Multiple candidates found \u2014 click yourself:","team.binding":"Binding\u2026","team.bindFail":"Bind failed: {error}","team.noCandidates":"No identity found: make sure the bot has allowedUsers configured and contacts permission.","team.removeMemberConfirm":'Remove "{name}" from this team? Its bots disappear from this team roster (their own deployment is unaffected).',"team.creatingGroup":"Creating group\u2026","team.defaultGroupName":"Collaboration group","team.errPickBot":"Tick at least one bot first","sessions.closeBulkConfirm":"Close {count} selected sessions?","sessions.empty":"No sessions match the filters.","sessions.viewMode":"Session view","sessions.viewKanban":"Kanban","sessions.viewBoard":"Board","sessions.viewTable":"Table","sessions.selectSession":"Select session","sessions.board.needsYou":"Needs You","sessions.board.needsYouHint":"Repo, TUI, or usage limit waiting","sessions.board.starting":"Starting","sessions.board.startingHint":"CLI is spawning or resuming","sessions.board.working":"Working","sessions.board.workingHint":"Streaming, analyzing, or using tools","sessions.board.idle":"Idle","sessions.board.idleHint":"Ready for the next message","sessions.board.emptyColumn":"No sessions","sessions.board.signalRepo":"Repo needed","sessions.board.signalPrompt":"TUI choice needed","sessions.board.signalLimited":"Usage limited","sessions.board.signalAgent":"Needs human input","sessions.board.waiting":"Waiting","sessions.board.dragHint":"Drag header to reorder columns","sessions.board.moveLeft":"Move column left","sessions.board.moveRight":"Move column right","sessions.kanban.backlog":"Backlog","sessions.kanban.todo":"Todo","sessions.kanban.inProgress":"In Progress","sessions.kanban.inReview":"In Review","sessions.kanban.done":"Done","sessions.kanban.updated":"Updated {time}","sessions.kanban.moreHidden":"{count} more hidden","sessions.create.button":"Create session","sessions.create.title":"Create session","sessions.create.content":"Content","sessions.create.contentPlaceholder":"Describe the task; in Lead-dispatch mode you can assign different work to each agent here","sessions.create.bots":"Bots (added to the new group)","sessions.create.noBots":"No online bots to pick","sessions.create.mode":"Collaboration mode","sessions.create.modeAll":"Work together","sessions.create.modeLead":"Lead dispatch (recommended)","sessions.create.modeHelp":"Work together: every selected bot starts its own session with the same content. Lead dispatch: only the lead starts; it @-mentions the other bots in the chat to bring them in.","sessions.create.lead":"Lead bot","sessions.create.leadHelp":"The content goes to the lead, which decides when to bring up each sub-bot.","sessions.create.leadPickFirst":"Pick bots above first","sessions.create.column":"Initial column","sessions.create.columnInProgress":"In progress now","sessions.create.columnBacklog":"Backlog","sessions.create.columnHelp":"In progress: start immediately after the group is created. Backlog: create the group and add bots but do not start the CLI; drag to \u201CIn Progress\u201D or hit \u201CStart\u201D later to send the content.","sessions.create.advanced":"More options","sessions.create.groupName":"Group name","sessions.create.groupNamePlaceholder":"Defaults to the first line of the content","sessions.create.workingDir":"Working directory","sessions.create.workingDirHelp":"Optional. If set, binds the new group to this directory (all bots work there). Leave blank to pick a repo via the /repo card in the chat (worktree creation supported).","sessions.create.submit":"Create","sessions.create.submitting":"Creating\u2026","sessions.create.cancel":"Cancel","sessions.create.start":"Start","sessions.create.errContent":"Please enter the content","sessions.create.errNoBot":"Pick at least one bot","sessions.create.errLead":"Lead must be one of the selected bots","sessions.create.failed":"Create failed","sessions.create.startFailed":"Start failed","sessions.create.doneTitle":"Created","sessions.create.doneInProgress":"Group created and session(s) started","sessions.create.doneBacklog":"Group created; session(s) queued in Backlog","sessions.create.partialFail":"{n} bot(s) could not be started \u2014 you can @-mention them in the chat to retry","sessions.create.openChat":"Open Feishu chat","sessions.create.close":"Close","sessions.kanban.openTab":"Open in new tab","sessions.kanban.openFeishu":"Open in Feishu","sessions.kanban.terminalLoading":"Opening terminal\u2026","sessions.kanban.rename":"Rename (double-click title works too)","sessions.kanban.renameFail":"Rename failed","sessions.kanban.moveFail":"Move failed","sessions.kanban.groupBy":"Group by","sessions.kanban.groupFlow":"Workflow","sessions.kanban.groupTeam":"Team","sessions.kanban.groupBot":"Bots","sessions.kanban.teamLoading":"Loading teams\u2026","sessions.kanban.noTeam":"No teams","sessions.kanban.teamScope":"{chats} collab chats \xB7 {sessions} sessions","sessions.kanban.remoteHint":"Session from the {name} deployment (snapshot; terminal/history live on their machine)","sessions.kanban.clusterDragHint":"Drag header to move the whole group","sessions.history.title":"History","sessions.history.loading":"Fetching Feishu messages\u2026","sessions.history.fail":"Failed to load history","sessions.history.empty":"No messages","sessions.history.user":"User","sessions.history.owner":"Owner","sessions.history.staleHint":"The dashboard or daemon process may still run an old build \u2014 botmux restart and retry","groups.title":"Groups & Bots","groups.subtitle":"Inspect the chat x bot matrix and manage group creation, oncall, leave, and disband flows.","groups.search":"Search chat name / ID / owner","groups.missingOnly":"Missing bot only","groups.refresh":"Refresh","groups.create":"New Group","groups.chat":"Chat","groups.actions":"Actions","groups.addBots":"Add Bots","groups.saveAsProfile":"Save as Profile","groups.manage":"Manage","groups.empty":"No chats match the filters.","groups.profileStatusFull":"Fully matches {name} ({matched}/{total})","groups.profileStatusFullChat":"Group roles fully match {name} ({matched}/{total})","groups.profileStatusPartial":"Partially matches {name} ({matched}/{total})","groups.profileStatusUnmatched":"No profile match","groups.saveProfileTitle":"Save as Profile","groups.saveProfileIntro":'Save {count} in-chat bot configs from "{name}" as a profile snapshot.',"groups.saveProfileScope":"Save scope","groups.saveProfileScopeHelp":"In-chat bot config snapshot","groups.saveProfileBotCount":"Bots in chat","groups.saveProfileLoadFailed":"Load failed","groups.saveProfileStatus.entry":"Create entry","groups.saveProfileStatus.error":"Load failed","groups.saveProfileMode":"Save mode","groups.saveProfileNew":"New Profile","groups.saveProfileNewHelp":"Create a new snapshot by default; if the id exists, matching bot entries are overwritten.","groups.saveProfileOverwrite":"Overwrite Existing Profile","groups.saveProfileOverwriteHelp":"Pick an existing profile and overwrite entries for the same bots.","groups.saveProfileExistingMeta":"{count} entries","groups.saveProfileIdLabel":"Profile id","groups.saveProfileExistingLabel":"Existing Profile","groups.saveProfileExistingEmpty":"No existing profiles","groups.saveProfileTarget":"Target Profile","groups.saveProfileTargetNew":"Will create or update this profile with the in-chat bot snapshot","groups.saveProfileTargetOverwrite":"Will overwrite entries for these bots in the existing profile","groups.saveProfileEntrySummary":"Will create profile entries for {count} in-chat bots.","groups.saveProfileEntrySummaryWithEmpty":"Will create profile entries for {count} in-chat bots; {emptyCount} currently have no returned role content and will be saved as empty entries.","groups.saveProfileFailedLoadSummary":"{count} bot configs failed to load. Saving is paused to avoid an incomplete snapshot.","groups.saveProfileSubmit":"Save Profile","groups.saveProfileOverwriteSubmit":"Overwrite Save","groups.saveProfileInvalid":"Profile id may contain letters, numbers, dots, underscores, and hyphens only; max 64; cannot be . or ..","groups.saveProfileNoRoles":"This chat has no bot configs to save.","groups.saveProfileSaving":"Saving\u2026","groups.saveProfileDone":"Saved {count} entries into {name}","groups.saveProfileFailed":"Saved only {saved}/{total} entries. Check offline bots or permissions.","groups.createTitle":"Create New Group","groups.createHelp":"Pick bots to invite. The dashboard chooses an online daemon as creator.","groups.name":"Group Name","groups.namePlaceholder":"e.g. AI ChangeLog","groups.bindDir":"Bind Directory","groups.bindDirHelp":"New topics start the CLI here and skip repo selection.","groups.roleProfile":"Profile","groups.roleProfileNone":"None","groups.roleProfileHelp":"After creation, send a profile apply bootstrap command in the new group.","groups.roleProfileBootstrapSent":"Profile: {name}; bootstrap message sent: {messageId}","groups.roleProfileBootstrapDone":"Profile: {name}; bootstrap completed with no peer bootstrap message needed.","groups.roleProfileBootstrapFailed":"Profile: {name}; bootstrap failed: {reason}","groups.botPicker":"Bots","groups.createSubmit":"Create","groups.cancel":"Cancel","groups.successTitle":"Group Created","groups.openGroup":"Open Group","groups.manageTitle":"Manage {name}","groups.owner":"Owner","groups.oncall":"Oncall Mode","groups.oncallHelp":"When enabled, group members can @ the bot; the selected bot's new topics in this group use its bound directory (binding is per-bot \u2014 only the checked bots are affected).","groups.leaveTitle":"Select Bots to Leave","groups.leaveSelected":"Selected Bots Leave","groups.disband":"Disband Group","groups.dangerHint":"Disband only works when an in-chat bot is the owner. Otherwise prefer leaving the chat.","groups.save":"Save","groups.needWorkingDir":"Working directory is required","groups.noBotsOnline":"No bots online. Restart the daemon first.","schedules.title":"Schedules","schedules.subtitle":"View, pause, resume, and run scheduled tasks across daemons.","schedules.search":"Search name / prompt / working dir","schedules.anyKind":"Any kind","schedules.enabledOnly":"Enabled only","schedules.name":"Name","schedules.bot":"Bot","schedules.schedule":"Schedule","schedules.next":"Next","schedules.last":"Last","schedules.repeat":"Repeat","schedules.enabled":"Enabled","schedules.actions":"Actions","schedules.runNow":"Run Now","schedules.pause":"Pause","schedules.resume":"Resume","schedules.delivery":"Delivery","schedules.deliveryOrigin":"Original thread","schedules.deliveryNewTopic":"New topic each run","schedules.deliveryLocal":"Log only","schedules.useNewTopic":"Switch to new-topic","schedules.useOrigin":"Switch to original","schedules.empty":"No schedules.","settings.title":"Global Settings","settings.subtitle":"Manage machine-wide botmux dashboard behavior shared by every bot.","settings.loading":"Loading settings\u2026","settings.loadFailed":"Failed to load settings","settings.readOnlyVisitor":"Read-only access \u2014 changing settings requires an authorized link (run botmux dashboard).","settings.sectionAccess":"Access","settings.publicReadOnly":"Allow tokenless read-only dashboard access","settings.publicReadOnlyHelp":"When enabled, visitors without a token can view the dashboard, sessions, schedules, and SSE. Writes such as close, pause, and approvals still require token auth. Sensitive raw terminal logs always require a token.","settings.remoteAccess":"Remote terminal access","settings.remoteAccessHelp":'When enabled, session web terminals, Feishu card "Open terminal" / "Get writable link" buttons, and webhooks all use central-platform links; when off, local links are used. Off by default.',"settings.sectionCards":"Feishu Cards","settings.openTerminalInFeishu":"Open streaming-card terminals in the Feishu sidebar","settings.openTerminalInFeishuHelp":"Off by default: terminal buttons open the Web Terminal URL directly. When enabled, botmux wraps the URL with Feishu web_url/open so Feishu PC opens it in a sidebar. Terminal write access is still controlled by its token.","settings.sectionExperimental":"Experimental","settings.chatBotDiscovery":"In-chat bot discovery (Feishu /members/bots)","settings.chatBotDiscoveryHelp":"When enabled, botmux reads the current chat's bot members in real time via Feishu /members/bots so multiple bots can reliably @-mention each other \u2014 it works from the very first message, with no need to accumulate past @ history, making multi-bot collaboration more robust. This is a non-public Feishu endpoint: it is on by default and automatically falls back to legacy discovery (per-bot probing + observed @ history) on failure. Turn it off (forcing the legacy path) only if your tenant/gateway does not support the endpoint, if it returns inaccurate membership that causes wrong or missing @-mentions, or if a Feishu change breaks its behaviour.","settings.sectionRepoPicker":"Repo Picker","settings.repoPickerMode":"Repo picker card mode","settings.repoPickerModeAll":"Repos + worktrees","settings.repoPickerModeRepos":"Main repos only","settings.repoPickerModeHelp":"Default shows repositories and linked worktrees. Main repos only hides linked worktrees from initialization and bare /repo cards; explicit /repo /abs/path/to/worktree still works.","settings.saving":"Saving\u2026","settings.saved":"Saved","settings.saveFailed":"Save failed","settings.sectionMaintenance":"Auto Maintenance","settings.autoUpdate":"Auto update","settings.autoUpdateHelp":"Off by default. At the set time, runs npm install -g botmux@latest to install the latest version (download/install only \u2014 no restart). npm-global installs only.","settings.autoRestart":"Auto restart","settings.autoRestartHelp":"Off by default; requires auto-update. After auto-update installs a newer version, restart to apply it if no session is in progress (busy \u21D2 slips to the next day).","settings.autoUpdateLocalDev":"This is a local-dev install (running from source); auto-update is unavailable.","settings.maintenanceTime":"Time","update.section":"Version & Update","update.loginRequired":"Sign in to check the version, update, or restart.","update.loading":"Checking\u2026","update.checkFailed":"Check failed","update.current":"Current version","update.upToDate":"Up to date","update.newAvailable":"New version {version} available","update.checkUnavailable":"Couldn't fetch the latest version (offline or network-restricted)","update.nodeWarn":"Node {version} is too old; update requires \u2265 {required}. Please upgrade Node first.","update.localDev":'This is a local-dev install (running from source); "Update to latest" is unavailable \u2014 use git pull + build, then restart.',"update.multiInstallWarn":"Multiple botmux installs detected. npm only updates the npm-global one, which may not be the active version:","update.kindNpm":"npm-global","update.kindSource":"source checkout","update.kindUnknown":"unknown","update.btnCheck":"Check for updates","update.btnChangelog":"View what's new","update.btnChangelogHide":"Hide changelog","update.btnUpdate":"Update to latest","update.btnRestart":"Restart botmux","update.changelogLoading":"Loading changelog\u2026","update.changelogEmpty":"No release notes newer than the current version.","update.changelogFailed":"Couldn't load the changelog (offline or network-restricted).","update.changelogRateLimited":"GitHub API rate limit hit (60 req/h per IP unauthenticated, easily tripped on shared networks). Try again later.","update.changelogViewOnGitHub":"View on GitHub Releases","update.navBadgeTitle":"New version {version} available","update.confirmMultiInstall":`Multiple botmux installs detected:
|
|
17
|
-
{paths}
|
|
18
|
-
|
|
19
|
-
npm only updates the npm-global one, which may not be the active version. Continue anyway?`,"update.confirmUpdate":"This will run npm install -g botmux@latest to update to {version}. Continue?","update.confirmUpdateNoVer":"This will run npm install -g botmux@latest to update to the latest version. Continue?","update.nodeTooOldAlert":"Node {version} is too old (requires \u2265 {required}). Please upgrade Node before updating.","update.updating":"Updating (npm install -g botmux@latest)\u2026","update.updatedChanged":"Updated {old} \u2192 {new}.","update.confirmRestart":"A restart is required to apply the new version. Restart now? (Sessions cold-resume; the dashboard briefly disconnects and reconnects.)","update.alreadyLatestRun":"Already on the latest version ({version}); nothing to update.","update.updateFailed":"Update failed: {detail}","update.noRestartHint":"Update installed. Restart later (botmux restart) to apply the new version.","update.confirmPlainRestart":"Restart botmux? Sessions cold-resume; the dashboard briefly disconnects and reconnects.","update.restarting":"Restarting botmux, waiting to reconnect\u2026","update.restartSlow":"Restart is taking a while; please refresh the page manually.","update.restartFailed":"Restart failed: {detail}","skills.title":"Skill Management","skills.subtitle":"Manage CLI-neutral botmux Skill assets and choose priority disclosure per bot.","skills.installed":"Installed Skills","skills.installedHelp":"Skill assets in the local registry that bots can disclose first.","skills.overviewTitle":"Organize Skill assets by bot","skills.overviewBody":"Global Skill delivery settings control session injection; each bot only manages its priority disclosure list.","skills.metricInstalled":"Installed Skills","skills.metricBots":"Configured Bots","skills.metricAttached":"Priority refs","skills.install":"Install Skill","skills.installInfoLabel":"Install location details","skills.installInfo":`Registry: ~/.botmux/skills/registry.json
|
|
20
|
-
Install: ~/.botmux/skills/store/skill-name; Git cache: ~/.botmux/skills/sources
|
|
21
|
-
Isolation: Codex/Claude global directories are not modified; local CLI Skills are referenced in place`,"skills.source":"Import Address","skills.sourcePlaceholder":"Paste a GitHub Skill page, Git URL, or local Skill directory","skills.sourceHelpRemoteLabel":"GitHub / Git: ","skills.sourceHelpRemote":"Paste a Skill directory page or repository URL; repository URLs need a repo path.","skills.sourceHelpLocalLabel":"Local CLI Skill directory: ","skills.sourceHelpLocal":"Referenced in place without copying into the botmux store.","skills.discover":"Discover Skills","skills.discoverTitle":"Discover Local CLI Skills","skills.discoverHelp":"Scan CLI Skill directories used by bots configured in this deployment. Selected Skills are registered as local links without copying files.","skills.discoverEmpty":"No registerable Skills were found in local CLI skill directories.","skills.discoverGroupEmpty":"No registerable Skills were found in this CLI directory.","skills.discoverRegistered":"Registered","skills.discoverSelectAll":"Select unregistered","skills.discoverClearSelection":"Clear selection","skills.discoverRegister":"Register selected","skills.discoverClose":"Close","skills.discoverNothingSelected":"Select at least one unregistered Skill.","skills.discoverRegisteringBatch":"Registering {total} Skills","skills.sourceCodex":"Local Codex","skills.sourceClaude":"Local Claude","skills.sourceTrae":"Local Trae","skills.sourceCursor":"Local Cursor","skills.sourceGemini":"Local Gemini","skills.sourceOpenCode":"Local OpenCode","skills.sourceLocalLink":"Local link","skills.sourceBotmuxCopy":"botmux store","skills.path":"Repo Path (optional)","skills.pathPlaceholder":"Blank uses the path from the GitHub URL","skills.ref":"Ref (optional)","skills.refPlaceholder":"Blank uses the GitHub URL ref or default HEAD","skills.link":"Local link (no copy)","skills.installSubmit":"Install","skills.update":"Update","skills.remove":"Remove","skills.pageStatus":"{page} / {pages}","skills.prevPage":"Previous page","skills.nextPage":"Next page","skills.empty":"No installed skills yet. Install from a local directory, Git, or GitHub.","skills.apiUnavailable":"This Dashboard backend does not expose the Skill API. Usually the frontend was updated before the botmux process restarted. Restart botmux, then refresh this page.","skills.globalDefaults":"Global Skill Delivery","skills.globalProject":"Workspace Skills","skills.globalProjectOff":"Ignore workspace Skills","skills.globalProjectOffHelp":"Read global CLI Skills and botmux Skills only","skills.globalProjectAll":"Read workspace Skills","skills.globalProjectAllHelp":`Read .agents/skills and
|
|
22
|
-
.botmux/skills`,"skills.globalDelivery":"Skill Delivery","skills.bots":"Bot Skill Settings","skills.botsHelp":"Choose the Skills each bot should disclose first.","skills.botCount":"{count} Bots","skills.scrollBotsPrev":"Scroll bots left","skills.scrollBotsNext":"Scroll bots right","skills.skillCount":"{count} Skills","skills.attach":"Add to priority","skills.detach":"Remove","skills.detachNamed":"Remove {skill}","skills.delivery":"Injection","skills.deliveryAuto":"Auto","skills.deliveryAutoHelp":"Use native CLI delivery first; fall back to Prompt when unsupported","skills.deliveryPrompt":"Prompt","skills.deliveryPromptHelp":"Inject the Skill catalog into the session prompt; works with every CLI","skills.deliveryNative":"Native","skills.deliveryNativeHelp":"Use only the CLI native Skill mechanism; no Prompt fallback","skills.projectMode":"Workspace Skills","skills.projectDefault":"Follow global","skills.projectDefaultHelp":"Use the project default on the left","skills.projectOff":"Do not read","skills.projectOffHelp":"This bot ignores workspace skills","skills.projectAll":"Read","skills.projectAllHelp":"This bot includes workspace skill candidates","skills.priority":"Priority skills","skills.noPriority":"Not configured, keeping CLI default behavior","skills.dangling":"Not installed","skills.removeInUse":'Skill "{skill}" is still referenced by: {refs}. Removing it deletes the registry package but does not automatically clean references. Continue?',"skills.saved":"Saved","skills.failed":"Failed","skills.jobRunning":"Working...","skills.refresh":"Refresh","botDefaults.title":"Bot Profiles","botDefaults.subtitle":"Per-bot defaults: oncall, proactive start, persona role, cards and grants.","botDefaults.metaOnline":"Online \xB7 daemon healthy","botDefaults.search":"Search bot name / app id","botDefaults.refresh":"Refresh","botDefaults.sectionOncall":"New-chat Oncall","botDefaults.sectionBrand":"Card Signature","botDefaults.sectionAgent":"CLI / Model","botDefaults.agentCli":"CLI","botDefaults.agentModel":"Model","botDefaults.agentModelPlaceholder":"Leave empty for the CLI default model","botDefaults.agentHelp":"Changes affect only newly created sessions. Existing sessions keep the CLI / model they were created with; close and start again to use the new configuration.","botDefaults.agentSave":"Save CLI / Model","botDefaults.agentSaved":"Saved (takes effect next session)","botDefaults.warning":"When enabled, chats without an oncall binding auto-bind to this directory on their next new topic. Manually bound or unbound chats are preserved.","botDefaults.empty":"No bots online. Run botmux restart first.","botDefaults.defaultOncall":"Default to oncall mode","botDefaults.defaultOncallHelp":"Unbound chats auto-bind on the next new topic","botDefaults.workingDir":"Default Working Directory","botDefaults.lastEnabled":"Last Enabled","botDefaults.autobound":"{count} chats auto-bound","botDefaults.save":"Save","botDefaults.required":'Working directory is required for "Default directory only" or "Oncall mode"',"botDefaults.sectionWorkingDir":"Default Working Directory","botDefaults.workingDirMode":"Mode","botDefaults.workingDirField":"Directory","botDefaults.workingDirModeOff":"Off (new sessions show the repo picker)","botDefaults.workingDirModeDefault":"Default directory only (no permission change)","botDefaults.workingDirModeOncall":"Oncall mode (open chat to the whole group)","botDefaults.workingDirModeHelp":'Where this bot starts new sessions, pick one (mutually exclusive): "Off" = no pinned dir, new sessions show the repo picker; "Default directory only" = every new session (incl. DMs / topics) starts in this dir and skips the picker, with no permission change (private bots); "Oncall mode" = same dir for all sessions PLUS newly-seen group chats auto-bind to oncall (anyone in the group can talk to the bot; write actions like buttons/commands still require allowedUsers), for on-call / support. Takes effect next session; running sessions need /restart.',"botDefaults.workingDirSaved":"Saved (takes effect next session)","botDefaults.brandLabel":"Signature (card footer)","botDefaults.brandLabelHelp":"Footer signature on cards this bot sends. Save empty = hide; fill in = custom (markdown ok, e.g. [Acme](https://\u2026)); Reset = show botmux.","botDefaults.brandLabelPlaceholder":"Default: botmux (empty = hidden)","botDefaults.sectionSandbox":"File sandbox (oncall)","botDefaults.sandboxToggle":"Enable file sandbox","botDefaults.sandboxHelp":"When on, every session of this bot runs in a per-session sandbox: only a project copy is visible \u2014 your real files, secrets, and other sessions are not. For sharing the bot with semi-trusted users (oncall). Linux only; applies to the next new session.","botDefaults.sandboxSaved":"Saved (applies to the next new session)","botDefaults.brandSave":"Save Signature","botDefaults.brandReset":"Reset to default","botDefaults.brandStateDefault":"Current: default botmux","botDefaults.brandStateOff":"Current: off","botDefaults.brandStateCustom":"Current: custom","botDefaults.sectionCard":"Card Behavior","botDefaults.disableStreaming":"Disable streaming card","botDefaults.disableStreamingHelp":"Stop posting the live session status card (and its Open Terminal entry). The task's final result still arrives as a message. For those who find the live card noisy.","botDefaults.silentTurnReactions":"Disable status reactions in card-off mode","botDefaults.silentTurnReactionsHelp":'With the streaming card off, botmux marks the triggering message with lightweight \u270B\u2192\u2705 reactions ("received / done"). Check this to drop those too \u2014 handy for low-noise observer bots. Editable only while "Disable streaming card" is on.',"botDefaults.writableLink":"Put a writable terminal link on the card","botDefaults.writableLinkHelp":'\u26A0\uFE0F Embeds a writable terminal link in the streaming card body \u2014 anyone in the chat can open and drive the terminal. Off = current behavior (private DM via the "Get Write Link" button).',"botDefaults.writableLinkMoot":"Streaming card disabled \u2014 this has no effect","botDefaults.privateCard":"/card sends a private card (authorized users only)","botDefaults.privateCardHelp":'Makes /card send an ephemeral "visible-to-specific-people" card: delivered only to the owner (allowedUsers); /grant-authorized talk users and everyone else in the chat cannot see it. Trade-off: it is a static snapshot (no live updates) and only works in regular group chats (topic groups / DMs fail, with no fallback). Affects only the /card command; the auto streaming card is unchanged.',"botDefaults.sectionCrossBot":"Cross-bot","botDefaults.botToBotSameDir":"bot@bot same-directory launch","botDefaults.botToBotSameDirHelp":"When ON, if this bot is @-ed into a chat/thread where another bot is already working, it reuses that bot's working directory and skips the repo-selection card (independent of oncall; default ON). When OFF, this bot always falls through to its own repo card / default dir.","botDefaults.cardPrefSaved":"Saved","botDefaults.sectionSummaryTrigger":"/summary Range","botDefaults.summaryLimit":"Recent message count","botDefaults.summarySinceHours":"Recent hours","botDefaults.summaryLimitHelp":"When the user mentions the bot and sends /summary, this range is read. Defaults to latest 50 messages / 24 hours. Set either value to 0 to remove that limit. Topic groups always read the current topic history.","botDefaults.summarySave":"Save summary range","botDefaults.summaryNumberInvalid":"Hours and message count must be 0 or a positive integer","botDefaults.sectionRole":"Default Role","botDefaults.roleHelp":"This bot's default persona (applies across all chats), injected into the bot's sessions in every chat; a single group can override it on the Roles page. Save empty = delete.","botDefaults.rolePlaceholder":"e.g. You are a backend triage assistant; answer concisely, prefer runnable commands\u2026","botDefaults.roleSave":"Save role","botDefaults.roleDelete":"Delete","botDefaults.roleSaved":"Saved","botDefaults.roleDeleted":"Deleted","botDefaults.roleLoadErr":"Failed to load role","botDefaults.profileRoles":"Profile Roles","botDefaults.profileRolesHelp":"Role entries this bot has in Profiles. Collapsed by default; expand a profile to load details.","botDefaults.profileRolesEmpty":"This bot has no profile roles.","botDefaults.profileRolesLoadFailed":"Failed to load profile roles: {error}","botDefaults.profileRoleClickToLoad":"Expand to load role details.","botDefaults.profileRoleDetailLoadFailed":"Failed to load role detail: {error}","botDefaults.sectionAutoStart":"Proactive Start","botDefaults.autoStartJoin":"Auto-start when added to a new chat","botDefaults.autoStartJoinHelp":'When enabled, the bot auto-starts a session and gets to work the moment it is added to a new chat (when an authorized user / allowedUsers is a member), no @ needed. It launches in the bot default working dir; if none is configured it shows a repo-select card first. Prerequisite: subscribe the "bot joined chat" event im.chat.member.bot.added_v1 for this app and grant the member-read scope in the Feishu console.',"botDefaults.autoStartJoinPrompt":"First-turn prompt on join (optional)","botDefaults.autoStartJoinPromptPlaceholder":"Filled = used as the first task after joining; blank = the bot reads the chat and decides what to do","botDefaults.autoStartJoinPromptSave":"Save prompt","botDefaults.autoStartTopic":"Auto-start on new topics in topic groups","botDefaults.autoStartTopicHelp":"When enabled, in a topic group the bot automatically joins each newly opened topic and starts working on its first message, no @ needed. Topic groups only \u2014 regular groups are unaffected.","botDefaults.sectionSessionMode":"Session mode","botDefaults.p2pMode":"Private chat session mode","botDefaults.p2pThread":"thread (separate session per DM)","botDefaults.p2pChat":"chat (flat continuous session)","botDefaults.p2pHelp":"How 1:1 DMs are sessioned: thread = each top-level message starts its own session (keeps chatter out of one CLI process); chat = the whole DM shares one continuous session and context (Hermes-like). Takes effect immediately.","botDefaults.regularGroupMode":"Regular group session mode","botDefaults.regularGroupModeChat":"chat (flat continuous session, default)","botDefaults.regularGroupModeChatTopic":"chat-topic (flat continuous at top level, native topics each get their own session)","botDefaults.regularGroupModeNewTopic":"new-topic (each top-level @ opens its own topic & session)","botDefaults.regularGroupModeShared":"shared (topic display, reusing one session)","botDefaults.regularGroupModeHelp":"How new top-level @mentions in regular (non-topic) groups are sessioned: chat = the whole group shares one continuous session (default, even a native Lark topic you open folds into it); chat-topic = top-level @ still stays flat in the one group session, but each native Lark topic you open runs its own independent session (a new session per topic); new-topic = each top-level @ opens its own topic with a separate session; shared = topic display but reuse the same session (replies fold into a topic yet share the group session & context). This is the per-bot default; a specific group can override it via /reply-mode. Takes effect immediately.","botDefaults.mentionMode":"Group @ policy","botDefaults.mentionModeAlways":"Always require @ (default)","botDefaults.mentionModeTopic":"No @ needed inside topics","botDefaults.mentionModeNever":"Never require @","botDefaults.mentionModeAmbient":"No @ needed, but yields when you @ someone else","botDefaults.mentionModeHelp":'Bot-global: controls when an @ is required to get a reply in groups. "Always require @" = every message needs an @ (default, safest; inside topics too, in multi-person groups); "No @ needed inside topics" = starting a new conversation / top-level still needs @, but follow-ups inside ANY topic this bot already drives (new-topic / shared / topic-group) continue without @; "Never require @" = non-@ messages are always answered wherever the bot has talk access (including cold-starting on a brand-new message) \u2014 for dedicated / on-call small groups; "No @ needed, but yields when you @ someone else" = same no-@ answering, EXCEPT when your message @mentions another person or bot (and not this one), in which case it backs off, treating it as handed to someone else (@all does not count, so it still replies) \u2014 best for multi-bot / multi-person groups that want a default responder which yields the moment you address someone else. Note: when you are alone with this bot (1:1) replies never need an @, independent of this setting.',"botDefaults.docSubscribeMode":"Doc subscription trigger (default)","botDefaults.docSubscribeModeMention":"Only when a comment @s me","botDefaults.docSubscribeModeAll":"Every new comment","botDefaults.docSubscribeModeHelp":'After subscribing to a Feishu doc with /subscribe-lark-doc, its comments feed into the session and the bot replies back into the comment. This sets the default trigger range for new subscriptions: "only when a comment @s me" is safest (avoids noise); "every new comment" suits dedicated docs.',"botDefaults.sectionGrant":"Authorization & Quota","botDefaults.autoGrantCard":"Auto grant card for blocked @mentions","botDefaults.autoGrantCardHelp":"When enabled, if a person or external bot explicitly @mentions this bot in a group but the talk gate blocks it, BotMux sends a /grant request card to the owner. When disabled, the gate still blocks but stays silent.","botDefaults.restrictGrant":"Restrict grantees to plain conversation","botDefaults.restrictGrantHelp":"When enabled, /grant-authorized users (the owner is exempt) can only send plain messages; every slash command is blocked: botmux built-in commands, passthrough commands, /workflow, /template, /introduce, /t, and CLI-native commands (/help, etc.). Text like /path/to/file is not misclassified.","botDefaults.quotaDefault":"Default message quota","botDefaults.quotaPlaceholder":"Empty = no default quota","botDefaults.quotaHelp":'Message count a bare /grant @x (no number) hands out. Empty or "Turn off" merely stops applying a default to bare /grant \u2014 it does NOT clear existing quota counters, nor affect an explicit /grant @x N; those keep being enforced. Authorization is auto-revoked once a quota runs out.',"botDefaults.quotaSave":"Save quota","botDefaults.quotaOff":"Turn off","botDefaults.quotaInvalid":"Quota must be a positive integer","botDefaults.quotaStateOff":"Current: no default quota","botDefaults.quotaStateOn":"Current: {count} per grantee","botDefaults.sectionSessionCap":"Session limit","botDefaults.maxLiveWorkers":"Max live sessions","botDefaults.maxLiveWorkersPlaceholder":"Empty = default 30","botDefaults.maxLiveWorkersHelp":"Cap on this bot's simultaneously-live sessions, to bound memory. Beyond it, the least-recently-used sessions are suspended: both the worker AND the CLI process are killed to reclaim all their memory, and the session cold-resumes from its on-disk transcript on the next message (--resume rebuilds context in a few seconds \u2014 nothing stays resident). Empty = use the default of 30; a number = a per-bot override (set a larger number if you want more). Note: suspension only applies to resumable backends (tmux/herdr/zellij), never plain PTY; a session that is mid-reply is never interrupted.","botDefaults.maxLiveWorkersSave":"Save limit","botDefaults.maxLiveWorkersOff":"Reset to default","botDefaults.maxLiveWorkersInvalid":"Limit must be a positive integer","botDefaults.maxLiveWorkersStateDefault":"Current: default 30 live sessions","botDefaults.maxLiveWorkersStateOn":"Current: up to {count} live sessions","botDefaults.sectionStartupCommands":"Startup commands","botDefaults.startupCommandsHelp":"Commands auto-sent to the CLI in order after launch, before the first message (each its own Enter), e.g. /effort ultracode. Comma- or newline-separated, one per line, arguments allowed; empty = none. Takes effect from the next session, and replays on every new session (incl. resume) \u2014 so session-only settings like /effort ultracode survive a resume. Native CLI sessions only; adopted sessions are not driven.","botDefaults.startupCommandsPlaceholder":"One per line, e.g. /effort ultracode","botDefaults.startupCommandsSave":"Save startup commands","botDefaults.sectionLaunchShell":"Launch shell","botDefaults.launchShellHelp":"Shell used to launch the CLI, overriding the daemon $SHELL: a shell name (zsh|bash|sh) or an absolute path (e.g. /usr/bin/zsh). For when the login $SHELL (e.g. bash) has an rcfile that `exec`-trampolines into another shell (`exec zsh`), pre-empting the CLI launch so the session never starts (bare-shell `parse error`) \u2014 pinning launchShell launches under it directly, bypassing the skipped rcfile. Note: PATH/nvm/pnpm must then live in the chosen shell\u2019s rcfiles (e.g. .zshrc/.zprofile). Empty = use $SHELL. Takes effect next session; tmux/zellij backends only (pty execs the CLI directly and is unaffected).","botDefaults.launchShellPlaceholder":"e.g. zsh or /usr/bin/zsh; empty = $SHELL","botDefaults.launchShellSave":"Save launch shell","botDefaults.sectionEnv":"Environment variables","botDefaults.envHelp":"Environment variables injected into THIS bot's CLI process (a JSON object). Typical use: run a bot on GLM / a third-party Anthropic\xB7OpenAI-compatible provider \u2014 set ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN (GLM: https://api.z.ai/api/anthropic, or https://open.bigmodel.cn/api/anthropic in China), or set HTTPS_PROXY / a CLI feature flag. Values accept string/number/boolean only; botmux-reserved keys (BOTMUX_, LARK_APP_, \u2026) are ignored. Takes effect from the next session, injected per-session into the CLI process (never into the shared tmux server env, so it can't leak across bots). Empty = clear. Note: values live in bots.json in plaintext \u2014 not a secret vault.","botDefaults.envPlaceholder":`{
|
|
23
|
-
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
|
|
24
|
-
"ANTHROPIC_AUTH_TOKEN": "your GLM Coding Plan key"
|
|
25
|
-
}`,"botDefaults.envSave":"Save environment variables","nav.roles":"Role Management","nav.groupRoles":"Group Roles","nav.roleProfiles":"Profiles","roles.title":"Role Management","roles.subtitle":"Manage per-group bot roles and reusable Profiles.","roleProfiles.title":"Profiles","roleProfiles.subtitle":"Maintain reusable multi-bot Profiles, then preview or apply them to target groups.","roles.search":"Search group / bot / ID","roles.refresh":"Refresh","roles.selectHint":"\u2190 Expand a group and select a bot to edit its role","roles.editorPlaceholder":`Enter role description, e.g.:
|
|
26
|
-
You are a code reviewer for this group...`,"roles.configured":"Configured","roles.unconfigured":"None","roles.noChats":"No groups","roles.preview":"Preview","roles.previewEmpty":"(empty)","roles.saved":"Saved","roles.delete":"Delete","roles.save":"Save","roles.confirmDelete":"Delete this bot's role config for this group?","roles.botsWithRoles":"bots configured","roles.emptyError":"Role content cannot be empty","roles.saveFailed":"Save failed, please retry","roles.tabGroups":"By Group","roles.tabProfiles":"Profiles","roles.profileIdPlaceholder":"profile id, e.g. collab-main","roles.profileIdInvalid":"Profile id may contain letters, numbers, dots, underscores, and hyphens only; max 64; cannot be . or ..","roles.openProfile":"Open","roles.profileSearch":"Search profile","roles.profileSelectHint":"\u2190 Select or enter a profile to edit","roles.profileEmpty":"No Profiles","roles.profileEntries":"entries","roles.profileMissing":"Missing","roles.profileRuntimeHint":"Profiles are reusable suites; applying one writes a group role, not a new runtime layer.","roles.profileBots":"Bot Entries","roles.profileEditorPlaceholder":"Enter this bot's Markdown role for this profile...","roles.saveEntry":"Save Entry","roles.profileBotSelectHint":"Select a bot to edit its entry in this profile","roles.applyToGroup":"Apply To Group","roles.applyForce":"Overwrite existing group roles","roles.previewApply":"Preview Apply","roles.applyProfile":"Apply Profile","roles.applyPickBots":"Select at least one bot","roles.applyWouldRefuse":"Would refuse (group role exists)","roles.applyPreviewOk":"Can apply","roles.applyOk":"Applied","roles.applyFailed":"Failed","roles.confirmDeleteProfileEntry":"Delete this bot entry from the profile?","common.none":"None","common.loading":"Loading\u2026","common.unknown":"Unknown","common.now":"now","common.never":"never","common.all":"All","nav.workflows":"Workflows","nav.workflowCatalog":"Catalog","workflow.subnav.runs":"Runs","workflow.subnav.catalog":"Catalog","workflow.subnav.v3":"New workflow \u2192","workflow.searchPlaceholder":"search runId / workflowId / chatId","workflow.filter.nonTerminal":"non-terminal","workflow.filter.all":"all","workflow.status.pending":"pending","workflow.status.running":"running","workflow.status.waiting":"waiting","workflow.status.effectAttempting":"effect","workflow.status.timedOut":"timed out","workflow.status.succeeded":"succeeded","workflow.status.failed":"failed","workflow.status.cancelled":"cancelled","workflow.table.run":"run","workflow.table.workflow":"workflow","workflow.table.status":"status","workflow.table.lastSeq":"lastSeq","workflow.table.dangling":"dEf/dAct/dWait","workflow.table.updated":"updated","workflow.table.chatApp":"chat / app","workflow.list.failedLoad":"Failed to load: {error}","workflow.list.noRuns":"No runs match.","workflow.list.noFilterMatch":"No runs match this filter.","workflow.list.loaded":"{count} runs \xB7 refreshed {time}","workflow.list.error":"error: {error}","workflow.detail.back":"Back","workflow.detail.loading":"Loading...","workflow.detail.loadFailed":"Load failed","workflow.detail.cancel":"Cancel","workflow.detail.cliCancelOnly":"CLI cancel only","workflow.detail.cancelTitle":"Cancel this workflow run","workflow.detail.cliCancelTitle":"Cancel unavailable: use botmux workflow cancel {runId}","workflow.detail.nodes":"Nodes / Activities","workflow.detail.parallel":"Parallel execution","workflow.detail.parallelMeta":"{count} attempt(s) \xB7 max parallel {max} \xB7 running {running}","workflow.detail.noParallelData":"No attempt timing data yet.","workflow.detail.parallelNow":"now","workflow.detail.node":"node","workflow.detail.nodeStatus":"node status","workflow.detail.activity":"activity","workflow.detail.activityStatus":"activity status","workflow.detail.attempts":"attempts","workflow.detail.current":"current","workflow.detail.detail":"detail","workflow.detail.nodeIO":"Node I/O","workflow.detail.timeline":"Timeline","workflow.detail.loadOlder":"Load older","workflow.detail.seq":"seq","workflow.detail.actor":"actor","workflow.detail.error":"error","workflow.detail.event":"event","workflow.detail.time":"time","workflow.detail.refreshed":"refreshed {time}","workflow.detail.unknownRun":"unknown run","workflow.detail.snapshotHttp":"snapshot HTTP {status}","workflow.detail.eventsHttp":"events HTTP {status}","workflow.detail.cancelUnavailable":"cancel unavailable: use botmux workflow cancel {runId}","workflow.detail.cancelConfirm":`Cancel workflow run {runId}?
|
|
27
|
-
|
|
28
|
-
{total} dangling item(s) will be handled by cancel-driven recovery.
|
|
29
|
-
effects={effects}, activities={activities}, waits={waits}, cancels={cancels}`,"workflow.detail.writeAccessCancel":"write access required: run `botmux dashboard` in the terminal to get a one-time URL, open it once to set the cookie, then come back and click cancel again.","workflow.detail.cancelHttp":"cancel HTTP {status}","workflow.detail.cancelPending":"cancel pending; waiting for running activity to drain","workflow.detail.writeAccessApproval":"write access required: run `botmux dashboard` in the terminal to get a one-time URL, open it once to set the cookie, then come back and approve/reject again.","workflow.detail.actionHttp":"{action} HTTP {status}","workflow.detail.approved":"approved","workflow.detail.rejected":"rejected","workflow.detail.alreadyTerminal":"Run already terminal; {label} was not applied.","workflow.detail.workflowContinue":"{label}; waiting for workflow to continue.","workflow.detail.workflowRefreshing":"{label}; refreshing workflow state.","workflow.detail.eventsLoaded":"{loaded}/{total} events loaded","workflow.detail.dangling":"Dangling","workflow.detail.noDangling":"No dangling work.","workflow.detail.none":"none","workflow.detail.noNodes":"No nodes yet.","workflow.detail.idle":"idle","workflow.detail.noNodeIO":"No node I/O yet.","workflow.detail.notDispatched":"not dispatched","workflow.detail.noAttempt":"No attempt yet","workflow.detail.attempt":"attempt","workflow.detail.authoredInput":"Authored input","workflow.detail.resolvedInput":"Resolved input","workflow.detail.output":"Output","workflow.detail.executionLog":"Execution log","workflow.detail.liveTerminal":"Live terminal","workflow.detail.terminalLive":"live","workflow.detail.terminalClosedShort":"closed","workflow.detail.terminalClosed":"Terminal is closed. Use the execution log below for the final transcript.","workflow.detail.openTerminalNewTab":"Open terminal in new tab","workflow.detail.terminalReplay":"Terminal replay","workflow.detail.openReplayNewTab":"Open replay in new tab","workflow.detail.downloadFullLog":"Download full log","workflow.detail.terminalResume":"Debug session","workflow.detail.openResumeNewTab":"Open debug session in new tab","workflow.detail.resumeSession":"Resume session","workflow.detail.resumeStarting":"Starting\u2026","workflow.detail.endResumeSession":"End debug session","workflow.detail.resumeEnding":"Ending\u2026","workflow.detail.resumeUnsupportedCli":'CLI "{cliId}" does not support resume',"workflow.detail.resumeMissingCliSession":"Missing cliSessionId \u2014 cannot resume","workflow.detail.resumeStartFailed":"Failed to start debug session (HTTP {status})","workflow.detail.resumeEndFailed":"Failed to end debug session (HTTP {status})","workflow.detail.writeAccessResume":"Resume requires dashboard write access.","workflow.detail.waitPrompt":"Wait prompt","workflow.detail.approvalComment":"Approval comment","workflow.detail.optionalComment":"Optional comment","workflow.detail.approve":"Approve","workflow.detail.reject":"Reject","workflow.detail.submitting":"Submitting...","workflow.detail.empty":"empty","workflow.detail.truncated":"truncated","workflow.detail.noData":"No data.","workflow.detail.noPreview":"No preview.","workflow.detail.open":"open","workflow.detail.deadline":"deadline","workflow.detail.effect":"effect","workflow.detail.wait":"wait","workflow.detail.noEvents":"No events.","workflow.summary.workflow":"workflow","workflow.summary.status":"status","workflow.summary.lastSeq":"lastSeq","workflow.summary.updated":"updated","workflow.summary.revision":"revision","workflow.summary.initiator":"initiator","workflow.summary.failedNode":"failedNode","workflow.summary.cancelOrigin":"cancelOrigin","workflow.summary.chat":"chat","workflow.summary.app":"app","workflow.dangling.activities":"activities","workflow.dangling.effects":"effects","workflow.dangling.waits":"waits","workflow.dangling.cancels":"cancels","catalog.title":"Workflow catalog","catalog.subtitle":"Create a workflow run from a saved workflow definition.","catalog.searchPlaceholder":"search workflowId / path","catalog.refresh":"Refresh","catalog.loading":"Loading catalog...","catalog.loadFailed":"Failed to load catalog: {error}","catalog.noDefinitions":"No workflow definitions found.","catalog.noFilterMatch":"No definitions match this filter.","catalog.table.workflow":"workflow","catalog.table.version":"version","catalog.table.params":"params","catalog.table.nodes":"nodes","catalog.table.revision":"revision","catalog.table.path":"path","catalog.paramSummary":"{required}/{total} required","catalog.back":"Back to catalog","catalog.detailTitle":"Workflow definition","catalog.definitionLoadFailed":"Failed to load definition: {error}","catalog.summary":"Summary","catalog.paramsSchema":"Params schema","catalog.definitionJson":"Definition JSON","catalog.runPanel":"Run workflow","catalog.paramsJson":"Params JSON","catalog.paramsPlaceholder":`{
|
|
30
|
-
"city": "\u5317\u4EAC"
|
|
31
|
-
}`,"catalog.chatId":"Chat ID","catalog.larkAppId":"Lark app ID","catalog.chatBindingHint":"Required so humanGate cards and cancel routing know which Lark chat owns the run.","catalog.run":"Run","catalog.running":"Starting...","catalog.badParamsJson":"Params must be a JSON object.","catalog.writeAccess":"write access required: run `botmux dashboard` in the terminal to get a one-time URL, open it once to set the cookie, then come back and run again.","catalog.runHttp":"run HTTP {status}","catalog.runStarted":"Run started; opening detail page...","catalog.invalidParams":"Invalid params","catalog.issue":"{path}: {message}","catalog.noParams":"No params declared.","catalog.required":"required","catalog.optional":"optional","catalog.default":"default","catalog.description":"description","catalog.path":"path","catalog.revision":"revision","catalog.nodeCount":"nodes"},_r={zh:Sd,en:Ed};function so(e){if(typeof e!="string")return null;let t=e.trim().toLowerCase();return t==="zh"||t.startsWith("zh-")?"zh":t==="en"||t.startsWith("en-")?"en":null}function Td(e=[]){for(let t of e){let n=so(t);if(n)return n}return"zh"}function oo(e){return(t,n)=>{let a=_r[e][t]??_r.zh[t]??t;return n?a.replace(/\{(\w+)\}/g,(o,i)=>{let r=n[i];return r==null?`{${i}}`:String(r)}):a}}function Rr(e,t){return(e?so(e.getItem(pa)):null)??Td(t)}var fa="botmux.dashboard.theme",Pr="botmux.dashboard.sessions.view";function Ld(e){return e==="system"||e==="light"||e==="dark"?e:null}function ma(e){return e==="kanban"||e==="board"||e==="table"?e:null}function Br(e,t){return e==="system"?t?"dark":"light":e}function Or(e){return Ld(e?.getItem(fa))??"dark"}function Fr(e){return ma(e?.getItem(Pr))??"board"}var Nr="botmux.dashboard.sessions.boardOrder",xs=["needs-you","starting","working","idle"];function Cd(e){if(!Array.isArray(e)||e.length!==xs.length)return null;let t=new Set(e);if(t.size!==e.length)return null;for(let n of xs)if(!t.has(n))return null;return e.slice()}function qr(e){try{let t=e?.getItem(Nr);return t?Cd(JSON.parse(t))??[...xs]:[...xs]}catch{return[...xs]}}function ha(e,t){try{e?.setItem(Nr,JSON.stringify(t))}catch{}}function jr(e,t){try{e?.setItem(Pr,t)}catch{}}var Ur="botmux.dashboard.sessions.kanbanGroupBy",ga="botmux.dashboard.sessions.kanbanTeam";function Id(e){return e==="flow"||e==="team"||e==="bot"?e:null}function zr(e){return Id(e?.getItem(Ur))??"flow"}function Gr(e,t){try{e?.setItem(Ur,t)}catch{}}var Wr="botmux.dashboard.sidebar";function Md(e){return e==="expanded"||e==="collapsed"?e:null}function Vr(e){return Md(e?.getItem(Wr))??"expanded"}function Kr(e,t){try{e?.setItem(Wr,t)}catch{}}var Ad=["default","cyber","genshin","fallout","prts","bluearchive","zzz","dragonball","ikun"],ba="botmux.dashboard.skin";function Dd(e){return typeof e=="string"&&Ad.includes(e)?e:null}function Jr(e){return Dd(e?.getItem(ba))??"default"}var Hd="\uFF71\uFF72\uFF73\uFF74\uFF75\uFF76\uFF77\uFF78\uFF79\uFF7A\uFF7B\uFF7C\uFF7D\uFF7E\uFF7F\uFF80\uFF81\uFF82\uFF830123456789\uFF8A\uFF8B\uFF8C\uFF8D\uFF8E$#%&@*+=<>/\\",Yr=["186 100% 60%","56 97% 60%","330 100% 64%","150 80% 58%"],va=[{key:"shake",dur:280},{key:"rgb",dur:340},{key:"tear",dur:400},{key:"invert",dur:220},{key:"slice",dur:320},{key:"blackout",dur:260}],Zr=["ESTABLISHING NETLINK","BYPASSING ICE","DECRYPTING DATAFLOW","SYNCING BOTMUX TELEMETRY","ACCESS GRANTED"],Qr="0123456789ABCDEF#<>*/=+\uFF71\uFF72\uFF73\uFF74\uFF75\uFF76\uFF77\uFF78\uFF85\uFF86\uFF87\uFF88\uFF89\uFF8A\uFF8B\uFF8C",_d=3200,Ss=[],Qn=0,ao=0;function $a(){return typeof window<"u"&&!!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches}function wa(e,t){let n="";for(let a=0;a<e;a++)n+=t[Math.floor(Math.random()*t.length)];return n}function Rd(e){let t=document.createElement("div");t.className="cyber-rain";let n=Math.max(10,Math.min(26,Math.round(window.innerWidth/70)));for(let a=0;a<n;a++){let o=document.createElement("span");o.className="cyber-rain-col",o.textContent=wa(28+Math.floor(Math.random()*22),Hd);let i=Yr[Math.floor(Math.random()*Yr.length)];o.style.cssText=`left:${(a+.5)/n*100}%;--rc:${i};--sz:${10+Math.floor(Math.random()*9)}px;--op:${(.25+Math.random()*.45).toFixed(2)};--dur:${(6+Math.random()*9).toFixed(1)}s;--delay:${(-Math.random()*12).toFixed(1)}s;`,t.appendChild(o)}e.appendChild(t)}function Pd(){if($a())return;let e=document.body,t=()=>{let n=va[Math.floor(Math.random()*va.length)],a=`cp-fx-${n.key}`;e.classList.add(a),Ss.push(window.setTimeout(()=>e.classList.remove(a),n.dur)),Ss.push(window.setTimeout(t,2400+Math.random()*4200))};Ss.push(window.setTimeout(t,1800+Math.random()*2600))}function Bd(){Ss.forEach(e=>window.clearTimeout(e)),Ss=[];for(let e of va)document.body.classList.remove(`cp-fx-${e.key}`)}function Od(){if($a()||document.getElementById("cyber-boot"))return;let e=document.createElement("div");e.id="cyber-boot",e.className="cyber-boot",e.setAttribute("aria-hidden","true"),e.innerHTML='<div class="cyber-boot-grid"></div><div class="cyber-loader"><div class="cyber-loader-frame"><div class="cyber-loader-head"><span>KIROSHI NETLINK</span><span class="cyber-loader-jp">\u4FB5\u5165\u4E2D</span></div><div class="cyber-loader-line"><span class="cyber-loader-prompt">></span><span class="cyber-loader-text"></span><span class="cyber-loader-cursor">_</span></div><div class="cyber-loader-stream"></div></div></div>',document.body.appendChild(e);let t=e.querySelector(".cyber-loader-text"),n=e.querySelector(".cyber-loader-stream"),a=0,o=0,i=0;Qn=window.setInterval(()=>{let r=Zr[a];t&&(o<r.length?(o+=1,t.textContent=r.slice(0,o)+wa(r.length-o,Qr),t.classList.remove("done")):i<16?(i+=1,t.textContent=r,t.classList.add("done")):(a=(a+1)%Zr.length,o=0,i=0)),n&&(n.textContent=wa(26,Qr))},50),ao=window.setTimeout(()=>{window.clearInterval(Qn),Qn=0,e.remove()},_d)}function Fd(){Qn&&(window.clearInterval(Qn),Qn=0),ao&&(window.clearTimeout(ao),ao=0),document.getElementById("cyber-boot")?.remove()}var Nd=320,Xr=16,Es=!0,Zn=0,ya=0,io=!1,ro=[],ka=[];function qd(){if(io)return;io=!0,Es=!1,Zn=0;let e=$a(),t="";for(let a=0;a<Xr;a++){let o=a%3===0?"186 100% 52%":a%3===1?"330 100% 58%":"56 97% 52%",i=(a%2===0?1:-1)*(8+a%5*7);t+=`<span class="cyber-breach-shard" style="top:${a/Xr*100}%;height:${2+a%4*3}%;--shift:${i}px;--delay:${a%8*.09}s;--dur:${(.36+a%5*.12).toFixed(2)}s;--hue:${o}"></span>`}let n=document.createElement("div");n.id="cyber-breach",n.className="cyber-breach",n.setAttribute("aria-hidden","true"),n.innerHTML=`<span class="cyber-breach-flash"></span><span class="cyber-breach-grid"></span><div class="cyber-breach-shards">${t}</div><div class="cyber-breach-banner"><span class="cyber-breach-tag">// BREACH PROTOCOL \u2014 SYSTEM OVERRIDE</span><span class="cyber-breach-caption" data-text="SYSTEM BREACH">SYSTEM BREACH</span><span class="cyber-breach-sub" data-text="NETWATCH OVERRIDE ENGAGED">NETWATCH OVERRIDE ENGAGED</span></div>`,document.body.appendChild(n),e||document.body.classList.add("cyber-breach-quake"),ro.push(window.setTimeout(()=>document.body.classList.remove("cyber-breach-quake"),760)),ro.push(window.setTimeout(()=>{n.remove(),io=!1},e?2600:4200))}function jd(){Es=!0,Zn=0;let e=document.documentElement,t=()=>e.scrollHeight-(window.innerHeight+window.scrollY)<=4,n=c=>{c<=0||!t()||(Zn+=c,Zn>Nd&&Es&&qd())},a=c=>n(c.deltaY),o=c=>{ya=c.touches[0]?.clientY??0},i=c=>{let p=c.touches[0]?.clientY??0,f=ya-p;ya=p,n(f)},r=()=>{t()||(Zn=0,Es=!0)},u=(c,p)=>{window.addEventListener(c,p,{passive:!0}),ka.push([c,p])};u("wheel",a),u("touchstart",o),u("touchmove",i),u("scroll",r)}function Ud(){for(let[e,t]of ka)window.removeEventListener(e,t);ka=[],ro.forEach(e=>window.clearTimeout(e)),ro=[],document.body.classList.remove("cyber-breach-quake"),document.getElementById("cyber-breach")?.remove(),io=!1,Es=!0,Zn=0}function el(e,t=!1){if(!(typeof document>"u")){if(!e){document.getElementById("cyber-fx")?.remove(),document.getElementById("cyber-hud")?.remove(),document.getElementById("cyber-glitch")?.remove(),Bd(),Fd(),Ud();return}if(!document.getElementById("cyber-fx")){let n=document.createElement("div");n.id="cyber-fx",n.className="cyber-fx",n.setAttribute("aria-hidden","true"),n.innerHTML='<div class="cyber-fx-grid"></div><div class="cyber-fx-scan"></div><span class="cyber-flicker"></span><span class="cyber-rollline"></span>',Rd(n),document.body.appendChild(n);let a=document.createElement("div");a.id="cyber-hud",a.className="cyber-hud",a.setAttribute("aria-hidden","true"),a.innerHTML='<span class="cyber-hud-corner tl"></span><span class="cyber-hud-corner tr"></span><span class="cyber-hud-corner bl"></span><span class="cyber-hud-corner br"></span><span class="cyber-hud-tag">NIGHT CITY // NETWATCH</span>',document.body.appendChild(a);let o=document.createElement("div");o.id="cyber-glitch",o.className="cyber-glitch",o.setAttribute("aria-hidden","true"),document.body.appendChild(o),Pd(),jd()}t&&Od()}}var zd={genshin:2e3,zzz:1900,dragonball:1900,ikun:1900},Gd='<span class="si-bball" aria-hidden="true"><span class="si-bball-seams"><svg viewBox="0 0 100 100"><g fill="none" stroke="#3a1d08" stroke-width="3.4" stroke-linecap="round"><path d="M50 4V96"/><path d="M4 50H96"/><path d="M50 4 Q14 50 50 96"/><path d="M50 4 Q86 50 50 96"/></g></svg></span></span>';function Wd(e){switch(e){case"genshin":return'<span class="si-gi-shine" aria-hidden="true"></span><span class="si-gi-text">\u539F\u795E\uFF0C\u542F\u52A8</span>';case"zzz":return'<span class="si-static" aria-hidden="true"></span><span class="si-roll" aria-hidden="true"></span><span class="si-now">NOW LOADING</span>';case"dragonball":return'<span class="si-speed" aria-hidden="true"></span><img class="si-cloud" src="/assets/skins/dragonball-wukong.webp" alt="">';case"ikun":return Gd;default:return""}}function Vd(){return typeof window<"u"&&!!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches}function tl(e){if(typeof document>"u"||Vd())return;let t=zd[e];if(!t)return;document.getElementById("skin-intro")?.remove();let n=document.createElement("div");n.id="skin-intro",n.className=`skin-intro si-${e}`,n.setAttribute("aria-hidden","true"),n.style.setProperty("--si-dur",`${t}ms`),n.innerHTML=Wd(e),document.body.appendChild(n),window.setTimeout(()=>n.remove(),t+80)}var Sa=class{locale="zh";themeMode="system";resolvedTheme="light";skin="default";authed=!0;listeners=new Set;translate=oo(this.locale);mediaQuery=null;init(){let t=typeof window<"u"?window:void 0;this.locale=Rr(t?.localStorage,Jd()),this.translate=oo(this.locale),this.themeMode=Or(t?.localStorage),this.skin=Jr(t?.localStorage),this.mediaQuery=t?.matchMedia?.("(prefers-color-scheme: dark)")??null,this.mediaQuery?.addEventListener("change",()=>{this.applyTheme(),this.emit()}),this.applyTheme(),this.applySkin(),this.applyLocale()}t(t,n){return this.translate(t,n)}setLocale(t){this.locale!==t&&(this.locale=t,this.translate=oo(t),window.localStorage.setItem(pa,t),this.applyLocale(),this.emit())}get theme(){return this.skin==="default"?this.themeMode:this.skin}setTheme(t){let n=t==="system"||t==="light"||t==="dark",a=n?"default":t,o=a!==this.skin;n&&this.themeMode!==t&&(this.themeMode=t,window.localStorage.setItem(fa,this.themeMode)),o&&(this.skin=a,window.localStorage.setItem(ba,this.skin)),this.applyTheme(),this.applySkin(o),this.emit()}on(t){return this.listeners.add(t),()=>this.listeners.delete(t)}emit(){for(let t of this.listeners)t()}applyTheme(){this.resolvedTheme=Br(this.themeMode,!!this.mediaQuery?.matches);let t=this.skin==="default"?this.resolvedTheme:Kd[this.skin];document.documentElement.dataset.theme=t,document.documentElement.dataset.themeMode=this.themeMode}applySkin(t=!1){document.documentElement.dataset.skin=this.skin,el(this.skin==="cyber",t),t&&this.skin!=="cyber"&&this.skin!=="default"&&tl(this.skin)}applyLocale(){document.documentElement.lang=this.locale==="zh"?"zh-CN":"en"}},Kd={default:"light",cyber:"dark",genshin:"light",fallout:"dark",prts:"dark",bluearchive:"dark",zzz:"dark",dragonball:"light",ikun:"dark"};function Jd(){return typeof navigator>"u"?[]:navigator.languages?.length?navigator.languages:[navigator.language].filter(Boolean)}var Qe=new Sa;function s(e,t){return Qe.t(e,t)}function l(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function at(e){if(!e)return"-";let t=Date.now()-e;return t<6e4?s("common.now"):t<36e5?Math.floor(t/6e4)+"m":t<864e5?Math.floor(t/36e5)+"h":Math.floor(t/864e5)+"d"}var nl=[{c1:"#5be3ff",c2:"#4f8bff"},{c1:"#b89bff",c2:"#6b4df0"},{c1:"#7ce0c3",c2:"#2e9e8f"},{c1:"#8fb4ff",c2:"#3b62d8"},{c1:"#ffd28f",c2:"#d8783b"},{c1:"#7df0a8",c2:"#1f9e63"},{c1:"#9fd0ff",c2:"#4878c8"},{c1:"#ff9fb8",c2:"#d84a78"}];function sl(e){let t=0,n=String(e??"");for(let i=0;i<n.length;i++)t=t*31+n.charCodeAt(i)>>>0;let{c1:a,c2:o}=nl[t%nl.length];return`--c1:${a};--c2:${o}`}var lo=new Map,uo=new Map;function Yd(e,t){return t?lo.get(t):e?uo.get(String(e)):void 0}function Re(e){let t=e.name??"",n=e.avatarUrl??Yd(e.name,e.larkAppId),a=e.size==="sm"?" orb-avatar-sm":"",o=n?" orb-has-img":"",i=e.dot?`<i class="orb-dot orb-dot-${e.dot}"></i>`:"",r=n?`<img class="orb-img" src="${l(n)}" alt="" decoding="async" referrerpolicy="no-referrer" onerror="this.closest('.orb-avatar')?.classList.remove('orb-has-img');this.remove()"/>`:"";return`<span class="orb-avatar${a}${o}" style="${sl(t)}" aria-hidden="true">${r}${i}</span>`}function Zd(e){return e?fo.get(e):void 0}function co(e){let t=e.name??e.chatId??"",n=e.avatarUrl??Zd(e.chatId),a=e.size==="sm"?" orb-avatar-sm":"",o=n?" orb-has-img":"",i=n?`<img class="orb-img" src="${l(n)}" alt="" decoding="async" referrerpolicy="no-referrer" onerror="this.closest('.orb-avatar')?.classList.remove('orb-has-img');this.remove()"/>`:"";return`<span class="orb-avatar orb-square${a}${o}" style="${sl(t)}" aria-hidden="true">${i}</span>`}var Ts=new Map,po=new Map,fo=new Map,xa=null,ol="botmux.avatarCache.v1";function Qd(){try{let e=typeof window<"u"?window.localStorage.getItem(ol):null;if(!e)return;let t=JSON.parse(e);for(let[n,a]of Object.entries(t.botByAppId??{}))lo.set(n,a);for(let[n,a]of Object.entries(t.botByName??{}))uo.set(n,a);for(let[n,a]of Object.entries(t.chatById??{}))fo.set(n,a);for(let[n,a]of Object.entries(t.nameByAppId??{}))Ts.set(n,a);for(let[n,a]of Object.entries(t.chatNameById??{}))po.set(n,a)}catch{}}function Xd(){try{if(typeof window>"u")return;window.localStorage.setItem(ol,JSON.stringify({botByAppId:Object.fromEntries(lo),botByName:Object.fromEntries(uo),chatById:Object.fromEntries(fo),nameByAppId:Object.fromEntries(Ts),chatNameById:Object.fromEntries(po)}))}catch{}}Qd();function bt(){return xa??=(async()=>{try{let e=await fetch("/api/groups");if(!e.ok)throw new Error(`HTTP ${e.status}`);let t=await e.json();for(let n of t.bots??[])n.larkAppId&&n.botName&&n.botName!==n.larkAppId&&Ts.set(n.larkAppId,String(n.botName)),n.botAvatarUrl&&(n.larkAppId&&lo.set(n.larkAppId,String(n.botAvatarUrl)),n.botName&&uo.set(String(n.botName),String(n.botAvatarUrl)));for(let n of t.chats??[])n.chatId&&n.name&&po.set(n.chatId,String(n.name)),n.chatId&&n.avatar&&fo.set(n.chatId,String(n.avatar));Xd()}catch{xa=null}})(),xa}function al(e){return e?Ts.get(e):void 0}function De(e){let t=e.larkAppId?Ts.get(e.larkAppId):void 0;return t||(e.botName&&e.botName!==e.larkAppId?String(e.botName):String(e.botName??e.larkAppId??"-"))}function pn(e){return e.chatId&&po.get(e.chatId)||null}function nt(e){let t=String(e??"");return t.replace(/^(?:@\S+\s*)+/,"").trim()||t}function Tt(e){return`<div class="page-loading" role="status"><i class="page-loading-spin" aria-hidden="true"></i>${l(e??s("common.loading"))}</div>`}function fn(e){return e.status==="closed"?null:e.agentAttention?.reason?e.agentAttention.reason:e.agentAttention?s("sessions.board.signalAgent"):e.pendingRepo?s("sessions.board.signalRepo"):e.tuiPromptActive?s("sessions.board.signalPrompt"):e.status==="limited"?s("sessions.board.signalLimited"):null}function ct(e){let t=Number(e.agentAttention?.at??e.lastMessageAt??0);if(Number.isFinite(t))return t;let n=Number(e.lastMessageAt??0);return Number.isFinite(n)?n:0}var ll={chats:[],bots:[]};async function ep(){try{let e=await fetch("/api/groups");if(!e.ok)return;ll=await e.json()}catch{}}var Ea=new Set(["working","analyzing","active","starting"]);function tp(e){let t=new Map,n=o=>{let i=t.get(o);return i||(i={botName:o,larkAppId:o,cliId:"unknown",online:!1,sessions:[],active:[],busy:[],attention:[],lastActiveAt:0},t.set(o,i)),i};for(let o of ll.bots??[]){let i=n(o.larkAppId??o.botName??"-");i.online=!0,o.botName&&(i.botName=o.botName),o.botAvatarUrl&&(i.botAvatarUrl=o.botAvatarUrl),o.cliId&&(i.cliId=o.cliId)}let a=[...e].sort((o,i)=>+(o.status==="closed")-+(i.status==="closed"));for(let o of a){let i=o.larkAppId??o.botName??"-";if(o.status==="closed"&&!t.has(i))continue;let r=n(i);o.botName&&(r.botName===r.larkAppId||!r.botName)&&(r.botName=o.botName),r.sessions.push(o),o.cliId&&r.cliId==="unknown"&&(r.cliId=o.cliId),r.lastActiveAt=Math.max(r.lastActiveAt,Number(o.lastMessageAt??0)),o.status!=="closed"&&(r.active.push(o),Ea.has(o.status)&&r.busy.push(o),fn(o)&&r.attention.push(o))}for(let o of t.values())if(o.botName===o.larkAppId){let i=al(o.larkAppId);i&&(o.botName=i)}return[...t.values()].sort((o,i)=>{let r=u=>u.attention.length?0:u.busy.length?1:u.online||u.active.length?2:3;return r(o)!==r(i)?r(o)-r(i):i.lastActiveAt-o.lastActiveAt})}var ul="botmux.overview.teamExpanded",np=230,il=13,rl=2;function sp(e){let t=e.clientWidth;return t?Math.max(1,Math.floor((t+il)/(np+il)))*rl:rl*3}function op(){try{return window.localStorage.getItem(ul)==="1"}catch{return!1}}function ap(e){try{window.localStorage.setItem(ul,e?"1":"0")}catch{}}function ip(e){let t=!e.online&&e.active.length===0,n=e.attention.length>0,a=e.busy.length>0,o=n?"warn":a?"busy":t?"off":"ok",i;if(n){let u=[...e.attention].sort((c,p)=>ct(c)-ct(p))[0];i=`<b>${l((nt(u.title)||u.sessionId).slice(0,60))}</b> \xB7 ${l(fn(u)??"")}`}else if(a){let u=[...e.busy].sort((c,p)=>Number(p.lastMessageAt??0)-Number(c.lastMessageAt??0))[0];i=`<b>${l((nt(u.title)||u.sessionId).slice(0,60))}</b>`}else t?i=l(s("overview.botOffline")):i=l(s("overview.botIdle"));let r=n?`<span class="tag tag-warn">${l(s("overview.botNeedsYou"))}</span>`:a?`<span class="tag tag-run">${l(s("overview.botBusy",{count:e.busy.length}))}</span>`:t?`<span class="tag tag-off">${l(s("overview.botOff"))}</span>`:`<span class="tag tag-ok">${l(s("overview.botReady"))}</span>`;return`<article class="mate${n?" mate-attn":""}${t?" mate-off":""}">
|
|
32
|
-
<div class="mate-top">
|
|
33
|
-
${Re({name:e.botName,larkAppId:e.larkAppId,avatarUrl:e.botAvatarUrl,dot:o})}
|
|
34
|
-
<div class="mate-id">
|
|
35
|
-
<b>${l(e.botName)}</b>
|
|
36
|
-
<span class="mate-role">${l(e.cliId)}</span>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
<div class="mate-task">${i}</div>
|
|
40
|
-
<div class="mate-foot">
|
|
41
|
-
${r}
|
|
42
|
-
<span>${e.lastActiveAt?l(s("overview.lastActive",{time:at(e.lastActiveAt)})):l(s("common.never"))}</span>
|
|
43
|
-
</div>
|
|
44
|
-
</article>`}function rp(e){let t=De(e);return`<article class="qcard" data-id="${l(e.sessionId)}">
|
|
45
|
-
${Re({name:t,larkAppId:e.larkAppId,size:"sm"})}
|
|
46
|
-
<div class="qcard-tx">
|
|
47
|
-
<b>${l(t)} \xB7 ${l((nt(e.title)||e.sessionId).slice(0,56))}</b>
|
|
48
|
-
<span>${l(fn(e)??"")} \xB7 ${at(ct(e))}</span>
|
|
49
|
-
</div>
|
|
50
|
-
<a class="qcard-go" href="#/sessions">${l(s("strip.handle"))}</a>
|
|
51
|
-
</article>`}function lp(e){let t=De(e);return`<li class="sess-row">
|
|
52
|
-
${Re({name:t,larkAppId:e.larkAppId,size:"sm"})}
|
|
53
|
-
<div class="sess-tx">
|
|
54
|
-
<b>${l((nt(e.title)||e.sessionId).slice(0,64))}</b>
|
|
55
|
-
<span>${l(t)} \xB7 ${l(pn(e)??e.cliId??"unknown")} \xB7 ${at(e.lastMessageAt)}</span>
|
|
56
|
-
</div>
|
|
57
|
-
<span class="status status-${l(e.status??"unknown")}">${l(e.status??"unknown")}</span>
|
|
58
|
-
</li>`}function up(e){let t=e.nextRunAt?new Date(e.nextRunAt).toLocaleString():"-";return`<li class="overview-list-row">
|
|
59
|
-
<div>
|
|
60
|
-
<strong>${l(e.name??e.id)}</strong>
|
|
61
|
-
<span>${l(De(e))} \xB7 ${l(e.parsed?.display??"")}</span>
|
|
62
|
-
</div>
|
|
63
|
-
<span>${l(t)}</span>
|
|
64
|
-
</li>`}function cp(e,t,n){let a=e+t+n;if(a===0)return`<div class="donut-wrap"><div class="donut" style="background:conic-gradient(var(--border) 0 360deg)"></div>
|
|
65
|
-
<div class="donut-center"><b>0</b><span>${l(s("overview.openSessions"))}</span></div></div>`;let o=e/a*360,i=o+t/a*360;return`<div class="donut-wrap">
|
|
66
|
-
<div class="donut" style="background:conic-gradient(var(--accent) 0 ${o}deg, var(--warning) ${o}deg ${i}deg, var(--success) ${i}deg 360deg)"></div>
|
|
67
|
-
<div class="donut-center"><b>${a}</b><span>${l(s("overview.openSessions"))}</span></div>
|
|
68
|
-
</div>`}async function cl(e){e.innerHTML=`<section class="page hero-page">
|
|
69
|
-
<div class="page-heading">
|
|
70
|
-
<div>
|
|
71
|
-
<p class="eyebrow">${s("app.subtitle")}</p>
|
|
72
|
-
<h1>${s("overview.title")}</h1>
|
|
73
|
-
<p id="overview-sub">${s("overview.subtitle")}</p>
|
|
74
|
-
</div>
|
|
75
|
-
<div class="hero-pills" id="overview-pills"></div>
|
|
76
|
-
</div>
|
|
77
|
-
|
|
78
|
-
<div class="sect-head">
|
|
79
|
-
<h2>${s("overview.team")}</h2><span>${s("overview.teamHint")}</span>
|
|
80
|
-
<a href="#/bot-defaults">${s("overview.viewAll")}</a>
|
|
81
|
-
</div>
|
|
82
|
-
<div class="team-grid" id="team-grid"></div>
|
|
83
|
-
<button type="button" class="team-toggle" id="team-toggle" hidden></button>
|
|
84
|
-
|
|
85
|
-
<div class="sect-head" id="attention-head">
|
|
86
|
-
<h2>${s("overview.attention")}</h2><span>${s("overview.attentionHint")}</span>
|
|
87
|
-
</div>
|
|
88
|
-
<div class="qgrid" id="attention-list"></div>
|
|
89
|
-
|
|
90
|
-
<div class="overview-cols">
|
|
91
|
-
<section class="panel">
|
|
92
|
-
<header class="panel-header">
|
|
93
|
-
<div>
|
|
94
|
-
<h2>${s("overview.activeSessions")}</h2>
|
|
95
|
-
<p>${s("overview.activeSessionsHint")}</p>
|
|
96
|
-
</div>
|
|
97
|
-
<a class="btn-link" href="#/sessions">${s("overview.viewAll")}</a>
|
|
98
|
-
</header>
|
|
99
|
-
<ul class="overview-list" id="recent-sessions"></ul>
|
|
100
|
-
</section>
|
|
101
|
-
<div class="overview-side">
|
|
102
|
-
<section class="panel">
|
|
103
|
-
<header class="panel-header">
|
|
104
|
-
<div>
|
|
105
|
-
<h2>${s("overview.today")}</h2>
|
|
106
|
-
<p>${s("overview.todayHint")}</p>
|
|
107
|
-
</div>
|
|
108
|
-
</header>
|
|
109
|
-
<div class="donut-row" id="today-donut"></div>
|
|
110
|
-
</section>
|
|
111
|
-
<section class="panel">
|
|
112
|
-
<header class="panel-header">
|
|
113
|
-
<div>
|
|
114
|
-
<h2>${s("overview.nextSchedules")}</h2>
|
|
115
|
-
<p>${s("schedules.subtitle")}</p>
|
|
116
|
-
</div>
|
|
117
|
-
<a class="btn-link" href="#/schedules">${s("overview.viewAll")}</a>
|
|
118
|
-
</header>
|
|
119
|
-
<ul class="overview-list" id="next-schedules"></ul>
|
|
120
|
-
</section>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</section>`;let t=e.querySelector("#overview-pills"),n=e.querySelector("#team-grid"),a=e.querySelector("#team-toggle"),o=op();a.onclick=()=>{o=!o,ap(o),p()};let i=e.querySelector("#attention-list"),r=e.querySelector("#recent-sessions"),u=e.querySelector("#today-donut"),c=e.querySelector("#next-schedules");function p(){let h=[...ke.sessions.values()],y=h.filter(I=>I.status!=="closed"),g=y.filter(I=>fn(I)).sort((I,N)=>ct(I)-ct(N)),v=y.filter(I=>Ea.has(I.status)&&!fn(I)),M=y.length-g.length-v.length,$=tp(h),L=$.filter(I=>I.online||I.active.length>0).length;t.innerHTML=`
|
|
124
|
-
<span class="pill">${l(s("overview.workingSessions"))} <b>${v.length}</b></span>
|
|
125
|
-
<span class="pill${g.length?" pill-hot":""}">${l(s("overview.attention"))} <b>${g.length}</b></span>
|
|
126
|
-
<span class="pill">${l(s("overview.onlineBots"))} <b>${L}</b></span>`;let C=sp(n),P=o?$:$.slice(0,C);n.innerHTML=P.length?P.map(ip).join(""):`<div class="empty">${s("overview.noSessions")}</div>`,$.length>C?(a.hidden=!1,a.textContent=o?s("overview.teamCollapse"):s("overview.teamExpand",{count:$.length})):a.hidden=!0,i.innerHTML=g.length?g.map(rp).join(""):`<div class="qcard qcard-empty">${s("overview.noAttention")}</div>`;let H=y.filter(I=>Ea.has(I.status)||I.status==="idle").sort((I,N)=>Number(N.lastMessageAt??0)-Number(I.lastMessageAt??0)).slice(0,7);r.innerHTML=H.length?H.map(lp).join(""):`<li class="empty">${s("overview.noSessions")}</li>`,u.innerHTML=`${cp(v.length,g.length,Math.max(0,M))}
|
|
127
|
-
<div class="donut-legend">
|
|
128
|
-
<span><i style="background:var(--accent)"></i>${l(s("overview.workingSessions"))} ${v.length}</span>
|
|
129
|
-
<span><i style="background:var(--warning)"></i>${l(s("overview.attention"))} ${g.length}</span>
|
|
130
|
-
<span><i style="background:var(--success)"></i>${l(s("sessions.board.idle"))} ${Math.max(0,M)}</span>
|
|
131
|
-
</div>`;let q=[...ke.schedules.values()].filter(I=>I.nextRunAt).sort((I,N)=>Date.parse(I.nextRunAt)-Date.parse(N.nextRunAt)).slice(0,5);c.innerHTML=q.length?q.map(up).join(""):`<li class="empty">${s("overview.noSchedules")}</li>`}let f=()=>{if(!document.body.contains(n)){window.removeEventListener("resize",f);return}o||p()};window.addEventListener("resize",f),ke.on(p),p(),ep().then(p),bt().then(p)}var dl=["backlog","todo","in_progress","in_review","done"];function pl(e){return typeof e=="string"&&dl.includes(e)?e:null}function fl(e){if(e.status==="closed")return"done";let t=pl(e.kanbanColumn);return t||(e.pendingRepo||e.tuiPromptActive||e.agentAttention||e.status==="limited"?"in_review":e.status==="starting"||e.status==="working"||e.status==="analyzing"||e.status==="active"?"in_progress":"todo")}var dp=1e15;function Ln(e){if(typeof e.kanbanPosition=="number"&&Number.isFinite(e.kanbanPosition))return e.kanbanPosition;let t=typeof e.lastMessageAt=="number"&&Number.isFinite(e.lastMessageAt)?e.lastMessageAt:0;return dp-t}function Ta(e,t){return e!==null&&t!==null?(e+t)/2:e!==null?e+1024:t!==null?t-1024:1024}var La=[24,72,168],pp=new Set(La);function Ca(e){let t=e==="7d"?168:Number(e);return!Number.isFinite(t)||!pp.has(t)?null:t}function fp(e){let t=Number(e);return Number.isFinite(t)&&t>0?t:null}function mp(e,t=Date.now()){return t-e*60*60*1e3}function hp(e,t,n=Date.now()){if(!e.sessionId||e.status!=="idle"||e.locked||e.pendingRepo||e.tuiPromptActive||e.agentAttention)return!1;let a=fp(e.lastMessageAt);return a!==null&&a<mp(t,n)}function ml(e,t,n=Date.now()){return e.filter(a=>hp(a,t,n))}function Ot(e,t){return`<th data-sort="${e}" data-label="${l(t)}">${l(t)}</th>`}function Da(e){return typeof e=="number"&&Number.isFinite(e)?e:null}function hl(e){let t=Da(e);return t===null?"-":t.toLocaleString("en-US")}var $l=["claude-code","seed","relay","codex","codex-app","cursor","gemini","opencode","mtr","hermes","mira","pi","copilot","aiden","coco","oh-my-pi","unknown"],gl=[{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"}],bl=[{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"}],Ia=50;function gp(e){let t=(n="")=>`<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"${n}/>`;switch(e){case"backlog":return`${t(' stroke-dasharray="1.6 2.1"')}</svg>`;case"in_progress":return`${t()}<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`${t()}<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`${t()}</svg>`}}function yl(e){return String(e??"unknown").toLowerCase().replace(/[^a-z0-9_-]/g,"-")}function vl(e){let t=String(e??"").trim();return t?t.replace(/\\/g,"/").split("/").filter(Boolean).at(-1)??t:"-"}function Ma(e){if(!e.webPort)return null;if(location.protocol==="https:")return e.proxyPort?`${location.origin}/s/${encodeURIComponent(e.sessionId)}`:null;let t=e.proxyPort??e.webPort,n=e.proxyPort?`/s/${encodeURIComponent(e.sessionId)}`:"";return`http://${location.hostname}:${t}${n}`}var Oe={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 Ls(e,t,n,a=""){return`<button type="button" class="card-act${a?" "+a:""}" data-action="${e}" title="${l(n)}" aria-label="${l(n)}">${t}</button>`}function Cs(e){return e.locked?s("sessions.unlock"):s("sessions.lock")}function Is(e){return e.locked?`<span class="session-lock-badge" title="${l(s("sessions.locked"))}">${l(s("sessions.locked"))}</span>`:""}function wl(e){if(!e)return"";let t=`<a class="term-btn term-open" href="${l(e)}" target="_blank" rel="noopener" title="${l(s("sessions.openTerminal"))}" aria-label="${l(s("sessions.openTerminal"))}">${Oe.terminal}</a>`;if(!Qe.authed)return`<span class="term-pill solo">${t}</span>`;let n=`<button type="button" class="term-btn term-write" data-action="write-link" title="${l(s("sessions.writeLinkHint"))}" aria-label="${l(s("sessions.writeLink"))}">${Oe.key}</button>`;return`<span class="term-pill">${t}${n}</span>`}async function kl(e,t){let n=window.open("about:blank","_blank");n&&(n.opener=null),t&&(t.disabled=!0);try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/write-link`),o=await a.json().catch(()=>({}));if(!a.ok||o?.ok===!1||!o?.url){n?.close(),a.status!==401&&alert(`${s("sessions.writeLinkFail")}: ${o?.error??a.status}`);return}n?n.location.href=o.url:window.open(o.url,"_blank","noopener")}catch(a){n?.close(),alert(`${s("sessions.writeLinkFail")}: ${a}`)}finally{t&&(t.disabled=!1)}}function bp(e){return e.status==="closed"?null:e.pendingRepo||e.tuiPromptActive||e.agentAttention||e.status==="limited"?"needs-you":e.status==="starting"?"starting":e.status==="working"||e.status==="analyzing"||e.status==="active"?"working":"idle"}function yp(){return`<details class="filter-cli">
|
|
132
|
-
<summary>${s("sessions.cli")} \xB7 <b id="cli-filter-count">${s("common.all")}</b></summary>
|
|
133
|
-
<div class="filter-cli-pop" role="group" aria-label="${s("sessions.cli")}">
|
|
134
|
-
${$l.map(e=>`
|
|
135
|
-
<label class="filter-check">
|
|
136
|
-
<input type="checkbox" name="cli" value="${l(e)}" checked>
|
|
137
|
-
<span>${l(e)}</span>
|
|
138
|
-
</label>
|
|
139
|
-
`).join("")}
|
|
140
|
-
</div>
|
|
141
|
-
</details>`}function vp(e){let t=String(e.status??"unknown"),n=String(e.cliId??"unknown"),a=Qe.locale==="zh"?"\uFF1A":": ";return[s("sessions.restartConfirmIntro"),"",`${s("sessions.restartConfirmStatus")}${a}${t}`,`${s("sessions.restartConfirmCli")}${a}${n}`,"",s("sessions.restartConfirmQuestion")].join(`
|
|
142
|
-
`)}function Aa(e){return e.status!=="closed"&&!e.adopt&&!e.pendingRepo}function wp(){return`<section class="page">
|
|
143
|
-
<div class="page-heading">
|
|
144
|
-
<div>
|
|
145
|
-
<p class="eyebrow">${s("nav.sessions")}</p>
|
|
146
|
-
<h1>${s("sessions.title")}</h1>
|
|
147
|
-
<p>${s("sessions.subtitle")}</p>
|
|
148
|
-
</div>
|
|
149
|
-
<div class="sessions-view-controls">
|
|
150
|
-
<button type="button" id="create-session-btn" class="primary create-session-btn">\uFF0B ${s("sessions.create.button")}</button>
|
|
151
|
-
<span id="kanban-team-stats" class="kanban-team-stats" hidden></span>
|
|
152
|
-
<select id="kanban-team" class="kanban-team-select" aria-label="${s("sessions.kanban.groupTeam")}" hidden></select>
|
|
153
|
-
<div class="segmented kanban-groupby" id="kanban-groupby" role="group" aria-label="${s("sessions.kanban.groupBy")}" hidden>
|
|
154
|
-
<button type="button" data-groupby="flow">${s("sessions.kanban.groupFlow")}</button>
|
|
155
|
-
<button type="button" data-groupby="team">${s("sessions.kanban.groupTeam")}</button>
|
|
156
|
-
<button type="button" data-groupby="bot">${s("sessions.kanban.groupBot")}</button>
|
|
157
|
-
</div>
|
|
158
|
-
<div class="segmented sessions-view-toggle" role="group" aria-label="${s("sessions.viewMode")}">
|
|
159
|
-
<button type="button" data-view="kanban">${s("sessions.viewKanban")}</button>
|
|
160
|
-
<button type="button" data-view="board">${s("sessions.viewBoard")}</button>
|
|
161
|
-
<button type="button" data-view="table">${s("sessions.viewTable")}</button>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
</div>
|
|
165
|
-
<form id="filters" class="filters sessions-filters">
|
|
166
|
-
<input type="search" name="q" placeholder="${s("sessions.search")}" />
|
|
167
|
-
<select name="status">
|
|
168
|
-
<option value="">${s("sessions.anyStatus")}</option>
|
|
169
|
-
<option>starting</option><option>working</option><option>idle</option>
|
|
170
|
-
<option>analyzing</option><option>active</option><option>closed</option>
|
|
171
|
-
</select>
|
|
172
|
-
<select name="adopt">
|
|
173
|
-
<option value="">${s("sessions.adoptAny")}</option>
|
|
174
|
-
<option value="yes">${s("sessions.adoptYes")}</option>
|
|
175
|
-
<option value="no">${s("sessions.adoptNo")}</option>
|
|
176
|
-
</select>
|
|
177
|
-
${yp()}
|
|
178
|
-
<label class="filter-toggle"><input type="checkbox" name="active" checked> <span>${s("sessions.activeOnly")}</span></label>
|
|
179
|
-
</form>
|
|
180
|
-
<div id="idle-cleanup-bar" class="idle-cleanup-bar">
|
|
181
|
-
<div class="idle-cleanup-summary">
|
|
182
|
-
<span class="idle-cleanup-dot" aria-hidden="true"></span>
|
|
183
|
-
<span id="idle-cleanup-count" class="idle-cleanup-count"></span>
|
|
184
|
-
</div>
|
|
185
|
-
<div class="idle-cleanup-controls">
|
|
186
|
-
<span class="idle-cleanup-label">${s("sessions.idleCleanupOlderThan")}</span>
|
|
187
|
-
<div id="idle-cleanup-threshold" class="idle-cleanup-thresholds" role="group" aria-label="${s("sessions.idleCleanupThreshold")}">
|
|
188
|
-
${La.map(e=>`<button type="button" data-hours="${e}" aria-pressed="${e===24?"true":"false"}">${e===168?"7d":`${e}H`}</button>`).join("")}
|
|
189
|
-
</div>
|
|
190
|
-
<button type="button" id="idle-cleanup-run" class="contrast idle-cleanup-run">${s("sessions.idleCleanupRun")}</button>
|
|
191
|
-
</div>
|
|
192
|
-
<span id="idle-cleanup-status" class="idle-cleanup-status" aria-live="polite"></span>
|
|
193
|
-
</div>
|
|
194
|
-
<div id="bulk-bar" class="bulk-bar" hidden>
|
|
195
|
-
<span id="bulk-count"></span>
|
|
196
|
-
<button type="button" id="bulk-lock">${s("sessions.lockSelected")}</button>
|
|
197
|
-
<button type="button" id="bulk-unlock">${s("sessions.unlockSelected")}</button>
|
|
198
|
-
<button type="button" id="bulk-close" class="contrast">${s("sessions.closeSelected")}</button>
|
|
199
|
-
<button type="button" id="bulk-clear">${s("sessions.clearSelection")}</button>
|
|
200
|
-
</div>
|
|
201
|
-
<table id="sessions-table">
|
|
202
|
-
<thead><tr>
|
|
203
|
-
<th><input type="checkbox" id="select-all" title="${s("sessions.activeOnly")}"></th>
|
|
204
|
-
${Ot("botName",s("sessions.bot"))}
|
|
205
|
-
${Ot("cliId",s("sessions.cli"))}
|
|
206
|
-
${Ot("status",s("sessions.status"))}
|
|
207
|
-
${Ot("tokenIn",s("sessions.tokenIn"))}
|
|
208
|
-
${Ot("tokenOut",s("sessions.tokenOut"))}
|
|
209
|
-
${Ot("title",s("sessions.titleCol"))}
|
|
210
|
-
${Ot("workingDir",s("sessions.workingDir"))}
|
|
211
|
-
${Ot("spawnedAt",s("sessions.created"))}
|
|
212
|
-
${Ot("lastMessageAt",s("sessions.last"))}
|
|
213
|
-
${Ot("adopt",s("sessions.adopt"))}
|
|
214
|
-
<th>${s("sessions.actions")}</th>
|
|
215
|
-
</tr></thead>
|
|
216
|
-
<tbody></tbody>
|
|
217
|
-
</table>
|
|
218
|
-
<div id="sessions-board" class="sessions-board" hidden></div>
|
|
219
|
-
<div id="sessions-kanban" class="sessions-kanban" hidden></div>
|
|
220
|
-
<dialog id="drawer"></dialog>
|
|
221
|
-
<dialog id="term-modal" class="term-modal"></dialog>
|
|
222
|
-
<dialog id="history-modal" class="history-modal"></dialog>
|
|
223
|
-
<dialog id="create-session-modal" class="create-session-modal"></dialog>
|
|
224
|
-
</section>`}async function kp(){try{let e=await fetch("/api/groups");if(!e.ok)return[];let t=await e.json();return(Array.isArray(t?.bots)?t.bots:[]).filter(a=>a&&typeof a.larkAppId=="string").map(a=>({larkAppId:a.larkAppId,botName:typeof a.botName=="string"&&a.botName?a.botName:a.larkAppId}))}catch{return[]}}function $p(e){let t=e.map(n=>`
|
|
225
|
-
<label class="cs-bot"><input type="checkbox" name="bot" value="${l(n.larkAppId)}"> <span>${l(n.botName)}</span></label>`).join("");return`
|
|
226
|
-
<article class="cs-card">
|
|
227
|
-
<header><h3>${s("sessions.create.title")}</h3></header>
|
|
228
|
-
<form id="cs-form">
|
|
229
|
-
<label class="form-row">
|
|
230
|
-
<span>${s("sessions.create.content")}</span>
|
|
231
|
-
<textarea name="content" rows="5" placeholder="${l(s("sessions.create.contentPlaceholder"))}" required></textarea>
|
|
232
|
-
</label>
|
|
233
|
-
<fieldset class="cs-bots">
|
|
234
|
-
<legend>${s("sessions.create.bots")}</legend>
|
|
235
|
-
${t||`<p class="cs-empty">${s("sessions.create.noBots")}</p>`}
|
|
236
|
-
</fieldset>
|
|
237
|
-
<fieldset class="cs-mode">
|
|
238
|
-
<legend>${s("sessions.create.mode")}</legend>
|
|
239
|
-
<label><input type="radio" name="mode" value="lead" checked> ${s("sessions.create.modeLead")}</label>
|
|
240
|
-
<label><input type="radio" name="mode" value="all"> ${s("sessions.create.modeAll")}</label>
|
|
241
|
-
<small>${s("sessions.create.modeHelp")}</small>
|
|
242
|
-
</fieldset>
|
|
243
|
-
<div class="cs-lead-row form-row" hidden>
|
|
244
|
-
<span>${s("sessions.create.lead")}</span>
|
|
245
|
-
<select name="lead"></select>
|
|
246
|
-
<small>${s("sessions.create.leadHelp")}</small>
|
|
247
|
-
</div>
|
|
248
|
-
<fieldset class="cs-column">
|
|
249
|
-
<legend>${s("sessions.create.column")}</legend>
|
|
250
|
-
<label><input type="radio" name="column" value="in_progress" checked> ${s("sessions.create.columnInProgress")}</label>
|
|
251
|
-
<label><input type="radio" name="column" value="backlog"> ${s("sessions.create.columnBacklog")}</label>
|
|
252
|
-
<small>${s("sessions.create.columnHelp")}</small>
|
|
253
|
-
</fieldset>
|
|
254
|
-
<details class="cs-advanced">
|
|
255
|
-
<summary>${s("sessions.create.advanced")}</summary>
|
|
256
|
-
<label class="form-row">
|
|
257
|
-
<span>${s("sessions.create.groupName")}</span>
|
|
258
|
-
<input type="text" name="name" maxlength="60" placeholder="${l(s("sessions.create.groupNamePlaceholder"))}">
|
|
259
|
-
</label>
|
|
260
|
-
<label class="form-row">
|
|
261
|
-
<span>${s("sessions.create.workingDir")}</span>
|
|
262
|
-
<input type="text" name="bindWorkingDir" placeholder="e.g. ~/projects/foo">
|
|
263
|
-
<small>${s("sessions.create.workingDirHelp")}</small>
|
|
264
|
-
</label>
|
|
265
|
-
</details>
|
|
266
|
-
<div class="actions cs-actions">
|
|
267
|
-
<button type="submit" class="primary">${s("sessions.create.submit")}</button>
|
|
268
|
-
<button type="button" id="cs-cancel">${s("sessions.create.cancel")}</button>
|
|
269
|
-
</div>
|
|
270
|
-
</form>
|
|
271
|
-
</article>`}function xp(e,t){t.onclick=async()=>{t.disabled=!0;try{let n=await kp();if(n.length===0){alert(s("sessions.create.noBots"));return}e.innerHTML=$p(n),e.showModal(),Sp(e,n)}finally{t.disabled=!1}}}function Sp(e,t){let n=e.querySelector("#cs-form"),a=e.querySelector(".cs-lead-row"),o=e.querySelector("select[name=lead]"),i=f=>t.find(h=>h.larkAppId===f)?.botName??f,r=()=>Array.from(n.querySelectorAll("input[name=bot]:checked")).map(f=>f.value),u=()=>n.querySelector("input[name=mode]:checked")?.value??"all";function c(){let f=r(),h=o.value;if(f.length===0){o.innerHTML=`<option value="" disabled selected>${l(s("sessions.create.leadPickFirst"))}</option>`,o.disabled=!0;return}o.disabled=!1,o.innerHTML=f.map(y=>`<option value="${l(y)}">${l(i(y))}</option>`).join(""),f.includes(h)&&(o.value=h)}function p(){u()==="lead"?(a.hidden=!1,c()):a.hidden=!0}n.querySelectorAll("input[name=mode]").forEach(f=>f.addEventListener("change",p)),n.querySelectorAll("input[name=bot]").forEach(f=>f.addEventListener("change",()=>{u()==="lead"&&c()})),p(),e.querySelector("#cs-cancel").onclick=()=>e.close(),n.onsubmit=async f=>{f.preventDefault();let h=new FormData(n),y=(h.get("content")??"").trim(),g=r(),v=u(),M=h.get("column")??"in_progress",$=(h.get("name")??"").trim(),L=(h.get("bindWorkingDir")??"").trim(),C=h.get("lead")??"";if(!y){alert(s("sessions.create.errContent"));return}if(g.length===0){alert(s("sessions.create.errNoBot"));return}if(v==="lead"&&(!C||!g.includes(C))){alert(s("sessions.create.errLead"));return}let P=n.querySelector("button[type=submit]");P&&(P.disabled=!0,P.textContent=s("sessions.create.submitting"));try{let H=await fetch("/api/sessions/create",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({content:y,larkAppIds:g,mode:v,column:M,leadLarkAppId:v==="lead"?C:void 0,name:$||void 0,bindWorkingDir:L||void 0})}),q=await H.json().catch(()=>null);H.ok&&q?.ok?Ep(e,q):H.status!==401&&(alert(`${s("sessions.create.failed")}: ${q?.error??H.status}`),P&&(P.disabled=!1,P.textContent=s("sessions.create.submit")))}catch(H){alert(`${s("sessions.create.failed")}: ${H}`),P&&(P.disabled=!1,P.textContent=s("sessions.create.submit"))}}}function Ep(e,t){let n=typeof t.shareLink=="string"&&t.shareLink?t.shareLink:"",a=Array.isArray(t.failed)?t.failed.length:0,o=Array.isArray(t.spawned)?t.spawned.length:0,i=t.column==="backlog"?s("sessions.create.doneBacklog"):s("sessions.create.doneInProgress"),r=a>0?`<p class="cs-warn">${s("sessions.create.partialFail",{n:String(a)})}</p>`:"";e.innerHTML=`
|
|
272
|
-
<article class="cs-card">
|
|
273
|
-
<header><h3>${s("sessions.create.doneTitle")}</h3></header>
|
|
274
|
-
<p>${l(i)}\uFF08${o}\uFF09</p>
|
|
275
|
-
${r}
|
|
276
|
-
${n?`<p><a href="${l(n)}" target="_blank" rel="noopener">${s("sessions.create.openChat")}</a></p>`:""}
|
|
277
|
-
<div class="actions"><button type="button" id="cs-done" class="primary">${s("sessions.create.close")}</button></div>
|
|
278
|
-
</article>`,e.querySelector("#cs-done").onclick=()=>e.close()}function xl(e){e.innerHTML=wp();let t=e.querySelector("#sessions-table tbody"),n=e.querySelector("#filters"),a=e.querySelector("#drawer"),o=e.querySelector("#select-all"),i=e.querySelector("#bulk-bar"),r=e.querySelector("#bulk-count"),u=e.querySelector("#bulk-lock"),c=e.querySelector("#bulk-unlock"),p=e.querySelector("#bulk-close"),f=e.querySelector("#bulk-clear"),h=e.querySelector("#idle-cleanup-bar"),y=e.querySelector("#idle-cleanup-threshold"),g=e.querySelector("#idle-cleanup-run"),v=e.querySelector("#idle-cleanup-count"),M=e.querySelector("#idle-cleanup-status"),$=e.querySelector("#sessions-table"),L=e.querySelector("#sessions-board"),C=e.querySelector("#sessions-kanban"),P=e.querySelector("#term-modal"),H=e.querySelector("#history-modal"),q=e.querySelector("#kanban-groupby"),I=e.querySelector("#kanban-team"),N=e.querySelector("#kanban-team-stats"),O=e.querySelectorAll(".sessions-view-toggle [data-view]"),A=e.querySelector("#create-session-btn"),R=e.querySelector("#create-session-modal");xp(R,A);let B=new Set,V="lastMessageAt",Z="desc",G=Fr(window.localStorage),j=qr(window.localStorage),z=null,b="",S="",E="",U=!1,ee=null,pe=!1,he=null,ae=new Map,se=zr(window.localStorage),ie=null,me=null,be=[],Me=null,le=!1,ve=!1,$e=(()=>{try{return window.localStorage.getItem(ga)??""}catch{return""}})(),Pe=!1,Ge=24;function it(){return Ge}function He(d){return d===168?"7d":`${d}H`}function Xe(d){let m=new Set;if(!d)return m;for(let k of d.groupChats)m.add(k);if(Me)for(let[k,w]of Me){if(m.has(k))continue;let x=!1;for(let T of d.botIds)if(w.botIds.has(T)){x=!0;break}if(x){for(let T of w.observedNames)if(d.botNames.has(T)){m.add(k);break}}}return m}function Ye(){let d=Bt();if(G==="kanban"&&se==="team"){let m=be.find(w=>w.key===$e)??be[0],k=Xe(m);return d.filter(w=>k.has(String(w.chatId)))}return d}function K(){return ml(Ye(),it())}function Ae(){y.querySelectorAll("button[data-hours]").forEach(d=>{let m=Ca(d.dataset.hours)===Ge;d.classList.toggle("active",m),d.setAttribute("aria-pressed",m?"true":"false")})}async function fe(){if(!(ve||le)){ve=!0;try{let[d,m,k]=await Promise.all([fetch("/api/team/hosted").then(T=>T.json()).catch(()=>null),fetch("/api/team/remote-roster").then(T=>T.json()).catch(()=>null),fetch("/api/groups").then(T=>T.json()).catch(()=>null)]);Array.isArray(k?.chats)&&(Me=new Map(k.chats.map(T=>[String(T.chatId),{botIds:new Set((T.memberBots??[]).filter(F=>F.inChat).map(F=>String(F.larkAppId))),observedNames:new Set((T.observedBotNames??[]).map(F=>String(F)))}])));let w=T=>({ids:new Set(T.map(F=>String(F.larkAppId))),names:new Set(T.map(F=>String(F.name??"")).filter(Boolean))}),x=[];for(let T of d?.teams??[]){let{ids:F,names:W}=w(T.bots??[]);x.push({key:`local:${T.teamId}`,label:T.isDefault?s("team.myHostedTeam"):String(T.name??T.teamId),botIds:F,botNames:W,groupChats:new Set((T.groupChatIds??[]).map(ne=>String(ne)))})}for(let T of m?.memberships??[]){let{ids:F,names:W}=w(T.roster?.bots??[]);x.push({key:`${T.hubUrl}::${T.teamId}`,label:String(T.teamName??T.teamId??T.hubUrl),botIds:F,botNames:W,groupChats:new Set})}be=x}finally{le=!0,ve=!1}be.length&&!be.some(d=>d.key===$e)&&($e=be[0].key),delete I.dataset.loading,I.disabled=be.length===0,I.innerHTML=be.length?be.map(d=>`<option value="${l(d.key)}"${d.key===$e?" selected":""}>${l(d.label)}</option>`).join(""):`<option value="">${l(s("sessions.kanban.noTeam"))}</option>`,E="",ye()}}let re=null,Be="",rt=0,wt=!1,kt=new Map;async function et(d){let m=Be===d.key&&Date.now()-rt<3e4;if(!(wt||m)){wt=!0;try{let w=d.key.startsWith("local:")?`/api/team/board/local/${encodeURIComponent(d.key.slice(6))}`:`/api/team/remote-board?key=${encodeURIComponent(d.key)}`,x=await fetch(w),T=await x.json().catch(()=>({}));if(!x.ok||T?.ok===!1)return;let F=typeof T.deploymentId=="string"?T.deploymentId:null,W=[];kt=new Map;for(let ne of Array.isArray(T.reports)?T.reports:[])if(!(F&&ne.deploymentId===F))for(let de of Array.isArray(ne.sessions)?ne.sessions:[]){let Ne={...de,remoteDeployment:ne.deploymentName||ne.deploymentId};W.push(Ne),kt.set(String(de.sessionId),Ne)}re={board:T.board&&typeof T.board=="object"?T.board:{},remoteRows:W},Be=d.key,rt=Date.now(),E="",ye()}catch{}finally{wt=!1}}}async function xn(d,m,k,w,x){try{let F=d.startsWith("local:")?await fetch(`/api/team/board/local/${encodeURIComponent(d.slice(6))}/move`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({sessionId:m,column:k,position:w})}):await fetch("/api/team/remote-board-move",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:d,sessionId:m,column:k,position:w})}),W=await F.json().catch(()=>({}));(!F.ok||W?.ok===!1)&&(re&&(x?re.board[m]=x:delete re.board[m]),E="",ye(),F.status!==401&&alert(`${s("sessions.kanban.moveFail")}: ${W?.error??F.status}`))}catch(T){re&&(x?re.board[m]=x:delete re.board[m]),E="",ye(),alert(`${s("sessions.kanban.moveFail")}: ${T}`)}}function ot(d,m,k){let w=be.find(T=>T.key===$e)??be[0];if(!w)return;(!re||Be!==w.key)&&(re={board:{},remoteRows:re?.remoteRows??[]},Be=w.key);let x=re.board[d];re.board[d]={column:m,position:k},xn(w.key,d,m,k,x)}function Ze(){return j.map(d=>gl.find(m=>m.id===d)).filter(d=>!!d)}function Vt(d,m){let k=j.indexOf(d),w=k+m;if(k<0||w<0||w>=j.length)return;let x=[...j];x.splice(k,1),x.splice(w,0,d),j=x,ha(window.localStorage,j),ye()}function $t(d,m){if(d===m)return;let k=j.indexOf(d),w=j.indexOf(m);if(k<0||w<0)return;let x=[...j];x.splice(k,1),x.splice(w,0,d),j=x,ha(window.localStorage,j),ye()}function Wn(d){let m=d.status==="closed",k=B.has(d.sessionId)?"checked":"";return`<tr data-id="${l(d.sessionId)}">
|
|
279
|
-
<td><input type="checkbox" class="row-select" ${k} ${m?"disabled":""}></td>
|
|
280
|
-
<td>${l(De(d))}</td>
|
|
281
|
-
<td><span class="badge cli-${yl(d.cliId)}">${l(d.cliId??"unknown")}</span></td>
|
|
282
|
-
<td><span class="status status-${l(d.status??"unknown")}">${l(d.status??"unknown")}</span>${Is(d)}</td>
|
|
283
|
-
<td class="token-cell">${hl(d.tokenUsage?.in)}</td>
|
|
284
|
-
<td class="token-cell">${hl(d.tokenUsage?.out)}</td>
|
|
285
|
-
<td title="${l(String(d.title??""))}">${l(nt(d.title??"").slice(0,48))}</td>
|
|
286
|
-
<td title="${l(d.workingDir??"")}">${l((d.workingDir??"").slice(-34))}</td>
|
|
287
|
-
<td>${at(d.spawnedAt)}</td>
|
|
288
|
-
<td>${at(d.lastMessageAt)}</td>
|
|
289
|
-
<td>${d.adopt?'<span class="badge">adopt</span>':""}</td>
|
|
290
|
-
<td><button class="open" type="button">${s("sessions.details")}</button></td>
|
|
291
|
-
</tr>`}function At(d){if(d.scope!=="chat"||!d.feishuChatLink)return null;let m=s("sessions.openChat");return`<a class="card-act" href="${l(d.feishuChatLink)}" target="_blank" rel="noopener" title="${l(m)}" aria-label="${l(m)}">${Oe.feishu}</a>`}function xt(d){return d.agentAttention?.reason?d.agentAttention.reason:d.agentAttention?s("sessions.board.signalAgent"):d.pendingRepo?s("sessions.board.signalRepo"):d.tuiPromptActive?s("sessions.board.signalPrompt"):d.status==="limited"?s("sessions.board.signalLimited"):""}function Dt(d){let m=B.has(d.sessionId),k=nt(d.title)||d.sessionId,w=De(d),x=pn(d),T=Ma(d),F=xt(d),W=vl(d.workingDir);return`<article class="session-card${m?" selected":""}${d.locked?" locked":""}" data-id="${l(d.sessionId)}" aria-pressed="${m}">
|
|
292
|
-
<div class="session-card-top">
|
|
293
|
-
${Re({name:w,larkAppId:d.larkAppId,size:"sm"})}
|
|
294
|
-
<div class="session-card-title">
|
|
295
|
-
<strong title="${l(String(d.title??k))}">${l(String(k).slice(0,72))}</strong>
|
|
296
|
-
<span>${l(w)} \xB7 ${l(x??d.cliId??"unknown")}</span>
|
|
297
|
-
</div>
|
|
298
|
-
<span class="session-card-status-group">
|
|
299
|
-
<span class="status status-${l(d.status??"unknown")}">${l(d.status??"unknown")}</span>
|
|
300
|
-
${Is(d)}
|
|
301
|
-
</span>
|
|
302
|
-
</div>
|
|
303
|
-
${W!=="-"||d.adopt?`<div class="session-card-meta">
|
|
304
|
-
${W!=="-"?`<span title="${l(d.workingDir??"")}">${l(W)}</span>`:""}
|
|
305
|
-
${d.adopt?'<span class="badge">adopt</span>':""}
|
|
306
|
-
</div>`:""}
|
|
307
|
-
<div class="session-card-time">
|
|
308
|
-
<span>${d.agentAttention?.at?`${l(s("sessions.board.waiting"))} ${at(ct(d))}`:`${l(s("sessions.last"))}: ${at(d.lastMessageAt)}`}</span>
|
|
309
|
-
</div>
|
|
310
|
-
${F?`<div class="session-signal" title="${l(F)}">${l(F)}</div>`:""}
|
|
311
|
-
<div class="session-card-actions">
|
|
312
|
-
${At(d)??Ls("locate",Oe.pin,s("sessions.locate"))}
|
|
313
|
-
${Ls("details",Oe.details,s("sessions.details"))}
|
|
314
|
-
${Aa(d)?Ls("restart",Oe.restart,s("sessions.restart")):""}
|
|
315
|
-
${wl(T)}
|
|
316
|
-
${Ls("lock",d.locked?Oe.unlock:Oe.lock,Cs(d),d.locked?"locked":"")}
|
|
317
|
-
${Ls("close",Oe.close,s("sessions.close"),"danger")}
|
|
318
|
-
</div>
|
|
319
|
-
</article>`}function Ee(d,m,k){let w=k==="needs-you"?ct(d):Number(d.lastMessageAt??0),x=k==="needs-you"?ct(m):Number(m.lastMessageAt??0);return w!==x?k==="needs-you"?w-x:x-w:String(d.title??d.sessionId).localeCompare(String(m.title??m.sessionId))}function _e(d){let m=new Map(gl.map(x=>[x.id,[]]));for(let x of d){let T=bp(x);T&&m.get(T).push(x)}let k=Ze(),w=k.map((x,T)=>{let F=(m.get(x.id)??[]).sort((W,ne)=>Ee(W,ne,x.id));return`<section class="session-board-column session-board-${x.id}" data-col="${x.id}">
|
|
320
|
-
<header draggable="true" title="${l(s("sessions.board.dragHint"))}">
|
|
321
|
-
<div>
|
|
322
|
-
<h2>${l(s(x.labelKey))}</h2>
|
|
323
|
-
<p>${l(s(x.hintKey))}</p>
|
|
324
|
-
</div>
|
|
325
|
-
<span class="session-board-head-right">
|
|
326
|
-
<span class="session-board-move">
|
|
327
|
-
<button type="button" data-move-col="${x.id}" data-dir="-1"
|
|
328
|
-
aria-label="${l(s("sessions.board.moveLeft"))}" ${T===0?"disabled":""}>\u2039</button>
|
|
329
|
-
<button type="button" data-move-col="${x.id}" data-dir="1"
|
|
330
|
-
aria-label="${l(s("sessions.board.moveRight"))}" ${T===k.length-1?"disabled":""}>\u203A</button>
|
|
331
|
-
</span>
|
|
332
|
-
<span class="session-board-count">${F.length}</span>
|
|
333
|
-
</span>
|
|
334
|
-
</header>
|
|
335
|
-
<div class="session-board-list">
|
|
336
|
-
${F.length?F.map(Dt).join(""):`<div class="session-board-empty">${s("sessions.board.emptyColumn")}</div>`}
|
|
337
|
-
</div>
|
|
338
|
-
</section>`}).join("");w!==b&&(b=w,L.innerHTML=w,L.classList.toggle("board-enter",!U),U=!0)}function Ht(d){let m=nt(d.title)||d.sessionId,k=De(d),w=pn(d),x=vl(d.workingDir),T=xt(d),F=[w,x!=="-"?x:null].filter(Boolean).join(" \xB7 "),W=String(d.status??"unknown"),ne=typeof d.remoteDeployment=="string"?d.remoteDeployment:"";return`<article class="kanban-card${ne?" kanban-card-remote":""}${d.locked?" locked":""}" data-id="${l(d.sessionId)}" tabindex="0" role="button" draggable="true">
|
|
339
|
-
<div class="kanban-card-top">
|
|
340
|
-
<span class="badge cli-${yl(d.cliId)}">${l(d.cliId??"unknown")}</span>
|
|
341
|
-
${d.adopt?'<span class="badge">adopt</span>':""}
|
|
342
|
-
${Is(d)}
|
|
343
|
-
${ne?`<span class="badge kanban-remote-badge" title="${l(s("sessions.kanban.remoteHint",{name:ne}))}">${l(ne)}</span>`:""}
|
|
344
|
-
<span class="kanban-card-top-right">
|
|
345
|
-
<span class="kanban-card-dot" data-status="${l(W)}" title="${l(W)}"></span>
|
|
346
|
-
${ne?"":`<button type="button" class="card-act kanban-card-act" data-action="history" title="${l(s("sessions.history.title"))}" aria-label="${l(s("sessions.history.title"))}">${Oe.history}</button>
|
|
347
|
-
${d.feishuChatLink?`<a class="card-act kanban-card-act" href="${l(d.feishuChatLink)}" target="_blank" rel="noopener" title="${l(s("sessions.kanban.openFeishu"))}" aria-label="${l(s("sessions.kanban.openFeishu"))}">${Oe.feishu}</a>`:""}
|
|
348
|
-
<button type="button" class="card-act kanban-card-act${d.locked?" locked":""}" data-action="lock" title="${l(Cs(d))}" aria-label="${l(Cs(d))}">${d.locked?Oe.unlock:Oe.lock}</button>
|
|
349
|
-
<button type="button" class="card-act kanban-card-act" data-action="details" title="${l(s("sessions.details"))}" aria-label="${l(s("sessions.details"))}">${Oe.details}</button>
|
|
350
|
-
${Aa(d)?`<button type="button" class="card-act kanban-card-act" data-action="restart" title="${l(s("sessions.restart"))}" aria-label="${l(s("sessions.restart"))}">${Oe.restart}</button>`:""}`}
|
|
351
|
-
</span>
|
|
352
|
-
</div>
|
|
353
|
-
<p class="kanban-card-title" title="${l(String(d.title??m))}">${l(String(m).slice(0,140))}</p>
|
|
354
|
-
${F?`<p class="kanban-card-desc" title="${l(F)}">${l(F)}</p>`:""}
|
|
355
|
-
${T?`<div class="session-signal" title="${l(T)}">${l(T)}</div>`:""}
|
|
356
|
-
<div class="kanban-card-foot">
|
|
357
|
-
<span class="kanban-card-owner">${Re({name:k,larkAppId:d.larkAppId,size:"sm"})}<span>${l(k)}</span></span>
|
|
358
|
-
<span class="kanban-card-updated">${l(s("sessions.kanban.updated",{time:at(d.lastMessageAt)}))}</span>
|
|
359
|
-
</div>
|
|
360
|
-
</article>`}function dt(d){let m=[],k=new Map;for(let T of d){let F=String(T.chatId??T.sessionId),W=k.get(F);W||(W={chatId:F,rows:[]},k.set(F,W),m.push(W)),W.rows.push(T)}let w=[];return{html:m.map(T=>{if(w.push(...T.rows),T.rows.length<2)return Ht(T.rows[0]);let F=pn(T.rows[0])??T.chatId;return`<div class="kanban-cluster" data-chat="${l(T.chatId)}">
|
|
361
|
-
<header draggable="true" title="${l(F)} \xB7 ${l(s("sessions.kanban.clusterDragHint"))}">
|
|
362
|
-
${co({chatId:T.chatId,name:F,size:"sm"})}
|
|
363
|
-
<span class="kanban-cluster-name">${l(F)}</span>
|
|
364
|
-
<span class="kanban-cluster-count">${T.rows.length}</span>
|
|
365
|
-
</header>
|
|
366
|
-
${T.rows.map(Ht).join("")}
|
|
367
|
-
</div>`}).join(""),flat:w}}function Vn(d){let m=new Map;for(let w of d){if(w.status==="closed")continue;let x=String(w.larkAppId||w.botName||"unknown"),T=m.get(x);T||(T={name:De(w),larkAppId:w.larkAppId,rows:[]},m.set(x,T)),T.rows.push(w)}let k=[...m.values()].sort((w,x)=>w.name.localeCompare(x.name));return k.length?k.map(w=>{let x=w.rows.sort((F,W)=>Number(W.lastMessageAt??0)-Number(F.lastMessageAt??0)),{html:T}=dt(x);return`<section class="kanban-column kanban-bot-col" data-bot="${l(w.larkAppId??w.name)}">
|
|
368
|
-
<header>
|
|
369
|
-
<span class="kanban-col-avatar">${Re({name:w.name,larkAppId:w.larkAppId,size:"sm"})}</span>
|
|
370
|
-
<h2>${l(w.name)}</h2>
|
|
371
|
-
<span class="kanban-col-count">${x.length}</span>
|
|
372
|
-
</header>
|
|
373
|
-
<div class="kanban-col-list">${T}</div>
|
|
374
|
-
</section>`}).join(""):`<div class="kanban-col-empty">${s("sessions.board.emptyColumn")}</div>`}function _t(d){let m=new Map(bl.map(w=>[w.id,[]]));for(let w of d)m.get(fl(w)).push(w);let k=bl.map(w=>{let x=(m.get(w.id)??[]).sort((ne,de)=>Ln(ne)-Ln(de)),T=0;w.id==="done"&&x.length>Ia&&(T=x.length-Ia,x=x.slice(0,Ia));let{html:F,flat:W}=dt(x);return m.set(w.id,W),`<section class="kanban-column kanban-${w.id}" data-col="${w.id}">
|
|
375
|
-
<header>
|
|
376
|
-
<span class="kanban-col-icon">${gp(w.id)}</span>
|
|
377
|
-
<h2>${l(s(w.labelKey))}</h2>
|
|
378
|
-
<span class="kanban-col-count">${x.length+T}</span>
|
|
379
|
-
</header>
|
|
380
|
-
<div class="kanban-col-list">
|
|
381
|
-
${x.length?F:`<div class="kanban-col-empty">${s("sessions.board.emptyColumn")}</div>`}
|
|
382
|
-
${T?`<div class="kanban-col-more">${l(s("sessions.kanban.moreHidden",{count:T}))}</div>`:""}
|
|
383
|
-
</div>
|
|
384
|
-
</section>`}).join("");return ae=m,k}function vs(d){if(ee||ie||pe)return;C.classList.toggle("kanban-mode-bot",se==="bot");let m;if(se==="bot")m=Vn(d),ae=new Map;else if(se==="team")if(!le)m=`<div class="kanban-loading">${s("sessions.kanban.teamLoading")}</div>`,ae=new Map,I.dataset.loading||(I.dataset.loading="1",I.disabled=!0,I.innerHTML=`<option>${l(s("sessions.kanban.teamLoading"))}</option>`),fe();else{let w=be.find(de=>de.key===$e)??be[0],x=Xe(w),T=w?d.filter(de=>x.has(String(de.chatId))):[];w&&et(w);let F=(Be===w?.key?re?.board:null)??{},W=(Be===w?.key?re?.remoteRows:null)??[],ne=[...T,...W].map(de=>{let Ne=F[de.sessionId];return Ne?{...de,kanbanColumn:Ne.column,kanbanPosition:Ne.position}:de});N.textContent=s("sessions.kanban.teamScope",{chats:x.size,sessions:ne.length}),m=_t(ne)}else m=_t(d);if(m===E)return;E=m;let k=new Map;C.querySelectorAll(".kanban-col-list").forEach(w=>{let x=w.closest(".kanban-column")?.dataset.col;x&&w.scrollTop&&k.set(x,w.scrollTop)}),C.innerHTML=m,k.size&&C.querySelectorAll(".kanban-col-list").forEach(w=>{let x=w.closest(".kanban-column")?.dataset.col,T=x?k.get(x):void 0;T&&(w.scrollTop=T)})}async function Rt(d,m,k,w){try{let x=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/board`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({column:m,position:k})}),T=await x.json().catch(()=>({}));(!x.ok||T?.ok===!1)&&(d.kanbanColumn=w.column,d.kanbanPosition=w.position,E="",ye(),x.status!==401&&alert(`${s("sessions.kanban.moveFail")}: ${T?.error??x.status}`))}catch(x){d.kanbanColumn=w.column,d.kanbanPosition=w.position,E="",ye(),alert(`${s("sessions.kanban.moveFail")}: ${x}`)}}async function St(d,m){let k=d.title;d.title=m,E="",ye();try{let w=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/rename`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({title:m})}),x=await w.json().catch(()=>({}));(!w.ok||x?.ok===!1)&&(d.title=k,E="",ye(),w.status!==401&&alert(`${s("sessions.kanban.renameFail")}: ${x?.error??w.status}`))}catch(w){d.title=k,E="",ye(),alert(`${s("sessions.kanban.renameFail")}: ${w}`)}}function Pt(d){if(d==null||d==="")return"";let m=Number(d),k=Number.isFinite(m)&&m>0?new Date(m):new Date(String(d));return Number.isNaN(k.getTime())?"":k.toLocaleString()}function _(d,m,k){let w=m.senderType==="user",x=w?m.senderName||(k&&m.senderId===k?s("sessions.history.owner"):s("sessions.history.user")):De(d),T=Pt(m.createTime),F=String(m.content??"").trim()||`[${m.msgType??"message"}]`,W=w?m.senderAvatar?`<img class="history-avatar-img" src="${l(String(m.senderAvatar))}" alt="" decoding="async" referrerpolicy="no-referrer">`:`<span class="history-avatar-user" aria-hidden="true">${l(String(x).slice(0,1))}</span>`:Re({name:De(d),larkAppId:d.larkAppId,size:"sm"});return`<div class="history-msg${w?" mine":""}">
|
|
385
|
-
${W}
|
|
386
|
-
<div class="history-msg-main">
|
|
387
|
-
<div class="history-msg-meta"><span>${l(x)}</span><time>${l(T)}</time></div>
|
|
388
|
-
<div class="history-bubble">${l(F)}</div>
|
|
389
|
-
</div>
|
|
390
|
-
</div>`}async function te(d){let m=De(d);H.innerHTML=`<div class="term-modal-head">
|
|
391
|
-
<span class="term-modal-title">
|
|
392
|
-
${Re({name:m,larkAppId:d.larkAppId,size:"sm"})}
|
|
393
|
-
<strong title="${l(String(d.title??""))}">${l((nt(d.title)||d.sessionId).slice(0,60))}</strong>
|
|
394
|
-
<span class="history-scope-tag">${l(s("sessions.history.title"))}</span>
|
|
395
|
-
</span>
|
|
396
|
-
<span class="term-modal-actions">
|
|
397
|
-
<button type="button" id="history-close" class="card-act" title="${l(s("sessions.dismiss"))}" aria-label="${l(s("sessions.dismiss"))}">${Oe.close}</button>
|
|
398
|
-
</span>
|
|
399
|
-
</div>
|
|
400
|
-
<div class="history-body"><div class="term-modal-loading">${s("sessions.history.loading")}</div></div>`,H.showModal(),H.querySelector("#history-close").onclick=()=>H.close();try{let k=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/history?limit=80`),w=await k.json().catch(()=>({}));if(!H.open)return;let x=H.querySelector(".history-body");if(!k.ok||w?.ok===!1){let F=String(w?.error??k.status),W=F==="not_found_yet"||F==="not_found";x.innerHTML=`<div class="history-error">${l(s("sessions.history.fail"))}: ${l(F)}${W?`<br><span>${l(s("sessions.history.staleHint"))}</span>`:""}</div>`;return}let T=Array.isArray(w.messages)?w.messages:[];if(!T.length){x.innerHTML=`<div class="history-error">${s("sessions.history.empty")}</div>`;return}x.innerHTML=`<div class="history-list">${T.map(F=>_(d,F,w.ownerOpenId)).join("")}</div>`,x.scrollTop=x.scrollHeight}catch(k){if(!H.open)return;let w=H.querySelector(".history-body");w&&(w.innerHTML=`<div class="history-error">${l(s("sessions.history.fail"))}: ${l(String(k))}</div>`)}}function oe(d,m){let k=d.querySelector(".kanban-card-title");if(!k||d.querySelector(".kanban-rename-input"))return;pe=!0;let w=document.createElement("input");w.type="text",w.className="kanban-rename-input",w.maxLength=200,w.value=nt(m.title)||"",k.replaceWith(w),w.focus(),w.select();let x=!1,T=F=>{if(x)return;x=!0,pe=!1;let W=w.value.trim();F&&W&&W!==(nt(m.title)||"")?St(m,W):(E="",ye())};w.addEventListener("keydown",F=>{F.stopPropagation(),F.key==="Enter"?(F.preventDefault(),T(!0)):F.key==="Escape"&&(F.preventDefault(),T(!1))}),w.addEventListener("blur",()=>T(!0)),w.addEventListener("click",F=>F.stopPropagation())}function ue(d,m){for(let k of d.querySelectorAll(".kanban-card:not(.dragging)")){if(k.closest(".kanban-cluster.dragging"))continue;let w=k.getBoundingClientRect();if(m<w.top+w.height/2)return k}return null}function J(){C.querySelectorAll(".drag-over, .dragging, .drop-before").forEach(d=>d.classList.remove("drag-over","dragging","drop-before"))}function ce(d){let m=P.querySelector(".term-modal-name");if(!m||P.querySelector(".term-modal-name-input"))return;let k=document.createElement("input");k.type="text",k.className="term-modal-name-input",k.maxLength=200,k.value=nt(d.title)||"",m.replaceWith(k);let w=()=>{let F=getComputedStyle(k),W=document.createElement("span");W.style.cssText="position:absolute;visibility:hidden;white-space:pre",W.style.fontSize=F.fontSize,W.style.fontFamily=F.fontFamily,W.style.fontWeight=F.fontWeight,W.style.letterSpacing=F.letterSpacing,W.textContent=k.value||" ",document.body.appendChild(W);let ne=W.offsetWidth;W.remove();let de=Math.round(window.innerWidth*.6);k.style.width=`${Math.min(Math.max(ne+22,80),de)}px`};w(),k.addEventListener("input",w),k.focus(),k.select();let x=!1,T=F=>{if(x)return;x=!0;let W=k.value.trim(),ne=nt(d.title)||"";if(F&&W&&W!==ne){d.title=W;let de=document.createElement("strong");de.className="term-modal-name",de.title=W,de.textContent=W.slice(0,60),k.replaceWith(de),St(d,W)}else{let de=document.createElement("strong");de.className="term-modal-name",de.title=String(d.title??ne),de.textContent=ne.slice(0,60),k.replaceWith(de)}};k.addEventListener("keydown",F=>{F.stopPropagation(),F.key==="Enter"?(F.preventDefault(),T(!0)):F.key==="Escape"&&(F.preventDefault(),T(!1))}),k.addEventListener("blur",()=>T(!0))}async function ge(d){let m=Ma(d);if(!m){ks(d);return}let k=nt(d.title)||d.sessionId,w=d.feishuChatLink?`<a class="card-act" href="${l(d.feishuChatLink)}" target="_blank" rel="noopener" title="${l(s("sessions.kanban.openFeishu"))}" aria-label="${l(s("sessions.kanban.openFeishu"))}">${Oe.feishu}</a>`:"";P.innerHTML=`<div class="term-modal-head">
|
|
401
|
-
<span class="term-modal-title">
|
|
402
|
-
${Re({name:De(d),larkAppId:d.larkAppId,size:"sm"})}
|
|
403
|
-
<strong class="term-modal-name" title="${l(String(d.title??k))}">${l(String(k).slice(0,60))}</strong>
|
|
404
|
-
<button type="button" id="term-modal-edit" class="card-act" title="${l(s("sessions.kanban.rename"))}" aria-label="${l(s("sessions.kanban.rename"))}">${Oe.edit}</button>
|
|
405
|
-
<span class="status status-${l(d.status??"unknown")}">${l(d.status??"unknown")}</span>
|
|
406
|
-
</span>
|
|
407
|
-
<span class="term-modal-actions">
|
|
408
|
-
${w}
|
|
409
|
-
<a id="term-modal-tab" class="card-act" href="${l(m)}" target="_blank" rel="noopener" title="${l(s("sessions.kanban.openTab"))}" aria-label="${l(s("sessions.kanban.openTab"))}">${Oe.terminal}</a>
|
|
410
|
-
<button type="button" id="term-modal-close" class="card-act" title="${l(s("sessions.dismiss"))}" aria-label="${l(s("sessions.dismiss"))}">${Oe.close}</button>
|
|
411
|
-
</span>
|
|
412
|
-
</div>
|
|
413
|
-
<div class="term-modal-body"><div class="term-modal-loading">${s("sessions.kanban.terminalLoading")}</div></div>`,P.showModal(),P.querySelector("#term-modal-close").onclick=()=>P.close(),P.querySelector("#term-modal-edit").onclick=()=>ce(d);let x=m;if(Qe.authed)try{let W=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/write-link`),ne=await W.json().catch(()=>({}));W.ok&&ne?.ok!==!1&&ne?.url&&(x=ne.url)}catch{}if(!P.open)return;let T=P.querySelector(".term-modal-body");T.innerHTML=`<iframe class="term-modal-frame" src="${l(x)}" allow="clipboard-read; clipboard-write"></iframe>`;let F=P.querySelector("#term-modal-tab");F&&(F.href=x)}function Bt(){let d=new FormData(n),m=(d.get("q")??"").toLowerCase(),k=d.getAll("cli"),w=k.length>0&&k.length<$l.length,x=d.get("status"),T=d.get("adopt"),F=!!d.get("active"),W=G==="kanban",ne=[...ke.sessions.values()].filter(de=>!w||k.includes(de.cliId??"unknown")).filter(de=>!x||de.status===x).filter(de=>!T||T==="yes"==!!de.adopt).filter(de=>!F||W||de.status!=="closed").filter(de=>!m||JSON.stringify(de).toLowerCase().includes(m));return ne.sort(un),ne}function ln(d,m){return m==="spawnedAt"||m==="lastMessageAt"?Number(d[m]??0):m==="tokenIn"?Da(d.tokenUsage?.in)??-1:m==="tokenOut"?Da(d.tokenUsage?.out)??-1:m==="adopt"?!!d.adopt:String(d[m]??"").toLowerCase()}function un(d,m){let k=ln(d,V),w=ln(m,V),x=0;return typeof k=="number"&&typeof w=="number"?x=k-w:typeof k=="boolean"&&typeof w=="boolean"?x=Number(k)-Number(w):x=String(k).localeCompare(String(w)),x===0&&(x=Number(d.lastMessageAt??0)-Number(m.lastMessageAt??0)),Z==="asc"?x:-x}function Kn(){$.querySelectorAll("th[data-sort]").forEach(d=>{let m=d.dataset.sort===V;d.classList.toggle("sorted",m),d.setAttribute("aria-sort",m?Z==="asc"?"ascending":"descending":"none");let k=d.dataset.label??d.textContent?.trim()??"";d.textContent=m?`${k} ${Z==="asc"?"\u25B2":"\u25BC"}`:k})}function Sn(d){i.hidden=B.size===0,r.textContent=s("sessions.selectedCount",{count:B.size});let m=[...B].map(x=>ke.sessions.get(x)).filter(x=>!!x&&x.status!=="closed");u.disabled=!m.some(x=>!x.locked),c.disabled=!m.some(x=>!!x.locked);let k=d.filter(x=>x.status!=="closed");if(k.length===0){o.checked=!1,o.indeterminate=!1,o.disabled=!0;return}o.disabled=!1;let w=k.filter(x=>B.has(x.sessionId)).length;o.checked=w===k.length,o.indeterminate=w>0&&w<k.length}function tt(){let d=K().length;v.textContent=s("sessions.idleCleanupCount",{count:d}),g.disabled=Pe||d===0,h.classList.toggle("is-empty",d===0),Ae()}function Xs(){O.forEach(d=>{let m=d.dataset.view===G;d.classList.toggle("active",m),d.setAttribute("aria-pressed",String(m))}),q.hidden=G!=="kanban",I.hidden=!(G==="kanban"&&se==="team"),N.hidden=I.hidden||!le,q.querySelectorAll("[data-groupby]").forEach(d=>{let m=d.dataset.groupby===se;d.classList.toggle("active",m),d.setAttribute("aria-pressed",String(m))})}function ws(){let d=n.querySelector("#cli-filter-count");if(!d)return;let m=[...n.querySelectorAll('input[name="cli"]')],k=m.filter(w=>w.checked).length;d.textContent=k===m.length?s("common.all"):`${k}/${m.length}`,d.classList.toggle("cli-filter-active",k!==m.length)}function ye(){let d=Bt();for(let w of[...B]){let x=ke.sessions.get(w);(!x||x.status==="closed")&&B.delete(w)}let m=d.filter(w=>w.status!=="closed"),k=G==="table"?d:m;if($.hidden=G!=="table",L.hidden=G!=="board",C.hidden=G!=="kanban",G==="table"){let w=d.length?d.map(Wn).join(""):`<tr><td colspan="12" class="empty">${s("sessions.empty")}</td></tr>`;w!==S&&(S=w,t.innerHTML=w)}else G==="kanban"?vs(d):_e(m);Xs(),Kn(),ws(),Sn(k),tt()}async function En(d,m){m&&(m.disabled=!0,m.textContent=s("sessions.locating"));try{let k=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/locate`,{method:"POST"}),w=await k.json();if(w.ok){if(!m)return;let x=30;m.textContent=s("sessions.cooldown",{seconds:x});let T=setInterval(()=>{x-=1,x<=0?(clearInterval(T),m.disabled=!1,m.textContent=s("sessions.locate")):m.textContent=s("sessions.cooldown",{seconds:x})},1e3)}else alert(`Locate failed: ${w.error??k.status}`),m&&(m.disabled=!1,m.textContent=s("sessions.locate"))}catch(k){alert(`Locate error: ${k}`),m&&(m.disabled=!1,m.textContent=s("sessions.locate"))}}async function gt(d,m){if(!confirm(s("sessions.closeConfirm")))return!1;m&&(m.disabled=!0);try{let k=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/close`,{method:"POST"}),w=await k.json().catch(()=>({}));return!k.ok||w?.ok===!1?(k.status!==401&&alert(`Close failed: ${w?.error??k.status}`),!1):!0}catch(k){return alert(`Close error: ${k}`),!1}finally{m&&(m.disabled=!1)}}function Kt(){b="",S="",E=""}async function cn(d,m,k){let w=!!d.locked;if(w===m)return!0;d.locked=m,Kt(),ye(),k&&(k.disabled=!0);try{let x=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:m})}),T=await x.json().catch(()=>({}));return!x.ok||T?.ok===!1?(d.locked=w,Kt(),ye(),x.status!==401&&alert(`${s("sessions.lockFailed")}: ${T?.error??x.status}`),!1):(d.locked=!!T.locked,Kt(),ye(),!0)}catch(x){return d.locked=w,Kt(),ye(),alert(`${s("sessions.lockFailed")}: ${x}`),!1}finally{k&&(k.disabled=!1)}}let pt=new Set;async function Tn(d,m){if(pt.has(d.sessionId)||!confirm(vp(d)))return!1;m&&(m.disabled=!0);try{let k=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/restart`,{method:"POST"}),w=await k.json().catch(()=>({}));return!k.ok||w?.ok===!1?(k.status!==401&&alert(`${s("sessions.restartFailed")}: ${w?.error??k.status}`),!1):(pt.add(d.sessionId),setTimeout(()=>pt.delete(d.sessionId),5e3),!0)}catch(k){return alert(`${s("sessions.restartFailed")}: ${k}`),!1}finally{m&&(m.disabled=!1)}}function Jn(d){return d===void 0?"\u2014":d<1e3?`${d}ms`:d<6e4?`${(d/1e3).toFixed(1)}s`:`${Math.floor(d/6e4)}m${Math.round(d%6e4/1e3)}s`}function Et(d){if(!d||d.status!=="ok"){let T=d?.error?.message?l(String(d.error.message)):l(String(d?.status??"error"));return`<p>${s("sessions.insightUnavailable")}: ${T}</p>`}let m=d.agg??{};if(!m.totalSpans)return`<p>${s("sessions.insightEmpty")}</p>`;let k="color:var(--muted,#8f959e)",w=[],x=[];if(d.meta?.asOf&&x.push(l(s("sessions.insightAsOf",{asOf:String(d.meta.asOf)}))),d.meta?.partial&&x.push(l(s("sessions.insightPartial"))),x.length&&w.push(`<p style="font-size:12px;${k}">${x.join(" \xB7 ")}</p>`),w.push(`<p>${l(s("sessions.insightMetrics",{total:String(m.totalSpans??0),failed:String(m.failedSpans??0),slow:String(m.slowSpans??0),rw:m.readWriteRatio===null||m.readWriteRatio===void 0?"\u2014":String(m.readWriteRatio),compactions:String(m.compactions??0)}))}</p>`),Array.isArray(d.suggestions)&&d.suggestions.length){let T=W=>W==="bad"?"\u{1F534}":W==="warn"?"\u{1F7E1}":"\u2139\uFE0F",F=d.suggestions.map(W=>`<li>${T(W.severity)} <b>${l(String(W.title??""))}</b> \u2014 ${l(String(W.action??""))}`+(Array.isArray(W.evidence)&&W.evidence.length?`<br><small style="${k}">${l(W.evidence.join("\uFF1B"))}</small>`:"")+"</li>").join("");w.push(`<details open><summary>${s("sessions.insightSuggestions")}</summary><ul style="padding-left:18px;margin:6px 0">${F}</ul></details>`)}if(Array.isArray(d.spans)&&d.spans.length){let T=ne=>ne==="error"?"\u{1F534}":ne==="running"?"\u23F3":"\u2705",F=[...d.spans].sort((ne,de)=>(ne.relStartMs??0)-(de.relStartMs??0)).map(ne=>{let de=[ne.inputSummary,ne.outputSummary].filter(Boolean).map(lt=>l(String(lt))).join(" \u2192 ");return`<tr${ne.status==="error"?' style="color:var(--danger,#d33)"':""}><td>${T(ne.status)}</td><td><code>${l(String(ne.tool??""))}</code></td><td>${l(String(ne.phase??""))}</td><td>${Jn(ne.durationMs)}</td><td>#${l(String(ne.turnIndex??0))}</td><td>${de}</td></tr>`}).join(""),W=d.meta?.capped?`<p style="font-size:12px;${k}">${l(s("sessions.insightCapped",{shown:String(d.meta.spansReturned??d.spans.length),total:String(d.meta.spansTotal??d.spans.length)}))}</p>`:"";w.push(`<details><summary>${s("sessions.insightSpans")} (${d.spans.length})</summary>${W}<div style="max-height:320px;overflow:auto"><table style="width:100%;font-size:12px"><tbody>${F}</tbody></table></div></details>`)}return w.join("")}function ks(d){let m=d.status==="closed",k=Ma(d);a.innerHTML=`<article>
|
|
414
|
-
<header>
|
|
415
|
-
<h3>${l(nt(d.title)||d.sessionId)}</h3>
|
|
416
|
-
<span class="drawer-status-line">
|
|
417
|
-
<span class="status status-${l(d.status??"unknown")}">${l(d.status??"unknown")}</span>
|
|
418
|
-
${Is(d)}
|
|
419
|
-
</span>
|
|
420
|
-
<p><code>${l(d.sessionId)}</code> <button data-copy="${l(d.sessionId)}">${s("sessions.copy")}</button></p>
|
|
421
|
-
</header>
|
|
422
|
-
<p><b>${s("sessions.bot")}:</b> ${l(De(d))} \xB7 <b>${s("sessions.cli")}:</b> ${l(d.cliId??"?")}</p>
|
|
423
|
-
${pn(d)?`<p><b>${s("sessions.chat")}:</b> ${l(pn(d))}</p>`:""}
|
|
424
|
-
<p><b>chatId:</b> <code>${l(d.chatId??"")}</code> <button data-copy="${l(d.chatId??"")}">${s("sessions.copy")}</button></p>
|
|
425
|
-
<p><b>rootMessageId:</b> <code>${l(d.rootMessageId??"")}</code> <button data-copy="${l(d.rootMessageId??"")}">${s("sessions.copy")}</button></p>
|
|
426
|
-
${d.threadId?`<p><b>threadId:</b> <code>${l(d.threadId)}</code></p>`:""}
|
|
427
|
-
<p><b>${s("sessions.workingDir")}:</b> ${l(d.workingDir??"-")}</p>
|
|
428
|
-
<div class="actions">
|
|
429
|
-
${At(d)??`<button id="locate-btn" type="button">${s("sessions.locate")}</button>`}
|
|
430
|
-
<button id="history-drawer-btn" type="button">${s("sessions.history.title")}</button>
|
|
431
|
-
${wl(k)}
|
|
432
|
-
${Aa(d)?`<button id="restart-btn" type="button">${s("sessions.restart")}</button>`:""}
|
|
433
|
-
${m?"":`<button id="lock-btn" type="button">${l(Cs(d))}</button>`}
|
|
434
|
-
${d.queued&&!m?`<button id="start-btn" type="button" class="primary">${s("sessions.create.start")}</button>`:""}
|
|
435
|
-
${m?`<button id="resume-btn" type="button" class="primary">${s("sessions.resume")}</button>`:""}
|
|
436
|
-
${m?"":`<button id="close-btn" type="button" class="contrast">${s("sessions.close")}</button>`}
|
|
437
|
-
<button id="land-btn" type="button">${s("sessions.land")}</button>
|
|
438
|
-
${Qe.authed?`<button id="insight-btn" type="button">${s("sessions.insight")}</button>`:""}
|
|
439
|
-
</div>
|
|
440
|
-
<div id="land-area"></div>
|
|
441
|
-
<div id="insight-area"></div>
|
|
442
|
-
<form method="dialog"><button>${s("sessions.dismiss")}</button></form>
|
|
443
|
-
</article>`,a.querySelectorAll("[data-copy]").forEach(xe=>{xe.onclick=()=>{navigator.clipboard.writeText(xe.dataset.copy??""),xe.textContent=s("sessions.copied"),setTimeout(()=>{xe.textContent=s("sessions.copy")},800)}});let w=a.querySelector("#locate-btn");w&&(w.onclick=()=>{En(d,w)});let x=a.querySelector("#history-drawer-btn");x&&(x.onclick=()=>{te(d)});let T=a.querySelector(".term-write");T&&(T.onclick=()=>{kl(d,T)});let F=a.querySelector("#resume-btn");F&&(F.onclick=async()=>{F.disabled=!0;try{let xe=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/resume`,{method:"POST"}),Te=await xe.json().catch(()=>({}));if(!xe.ok||Te.ok===!1){alert(`${s("sessions.resumeFailed")}: ${Te?.error??xe.status}`),F.disabled=!1;return}a.close()}catch(xe){alert(`${s("sessions.resumeFailed")}: ${xe}`),F.disabled=!1}});let W=a.querySelector("#restart-btn");W&&(W.onclick=async()=>{await Tn(d,W)&&a.close()});let ne=a.querySelector("#close-btn");ne&&(ne.onclick=async()=>{await gt(d,ne)&&a.close()});let de=a.querySelector("#lock-btn");de&&(de.onclick=async()=>{let xe=!d.locked;if(await cn(d,xe,de)){de.textContent=Cs(d);let Te=a.querySelector(".drawer-status-line");Te&&(Te.innerHTML=`<span class="status status-${l(d.status??"unknown")}">${l(d.status??"unknown")}</span>${Is(d)}`)}});let Ne=a.querySelector("#start-btn");Ne&&(Ne.onclick=async()=>{Ne.disabled=!0;try{let xe=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/start`,{method:"POST"}),Te=await xe.json().catch(()=>({}));if(!xe.ok||Te.ok===!1){xe.status!==401&&alert(`${s("sessions.create.startFailed")}: ${Te?.error??xe.status}`),Ne.disabled=!1;return}a.close()}catch(xe){alert(`${s("sessions.create.startFailed")}: ${xe}`),Ne.disabled=!1}});let lt=a.querySelector("#land-btn"),ut=a.querySelector("#land-area");lt&&ut&&(lt.onclick=async()=>{lt.disabled=!0,ut.innerHTML=`<p>${s("sessions.landLoading")}</p>`;try{let xe=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/sandbox-diff`),Te=await xe.json().catch(()=>({}));if(!Te.ok){ut.innerHTML=`<p>${s("sessions.landUnavailable")}: ${l(Te.error??String(xe.status))}</p>`,lt.disabled=!1;return}if(Te.empty){ut.innerHTML=`<p>${s("sessions.landEmpty")}</p>`,lt.disabled=!1;return}let Jt=String(Te.patch??""),eo=Jt.slice(0,2e4)+(Jt.length>2e4?`
|
|
444
|
-
\u2026(truncated)`:"");ut.innerHTML=`
|
|
445
|
-
<p><b>${Te.files}</b> files (+${Te.insertions}/-${Te.deletions}) \u2192 <code>${l(String(Te.workingDir??""))}</code></p>
|
|
446
|
-
<pre style="max-height:320px;overflow:auto;white-space:pre-wrap">${l(eo)}</pre>
|
|
447
|
-
<div class="actions">
|
|
448
|
-
<button id="land-apply" type="button" class="primary">${s("sessions.landApply")}</button>
|
|
449
|
-
<button id="land-discard" type="button" class="contrast">${s("sessions.landDiscard")}</button>
|
|
450
|
-
</div>`;let $s=ut.querySelector("#land-apply"),to=ut.querySelector("#land-discard");$s.onclick=async()=>{$s.disabled=!0,to.disabled=!0;let qe=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/sandbox-land/apply`,{method:"POST"}),dn=await qe.json().catch(()=>({}));ut.innerHTML=dn.ok?`<p>\u2705 ${s("sessions.landApplied")}: ${dn.files} files (+${dn.insertions}/-${dn.deletions}) \u2192 <code>${l(String(dn.workingDir??""))}</code></p>`:`<p>\u274C ${s("sessions.landFailed")}: ${l(dn.error??String(qe.status))}</p>`},to.onclick=async()=>{await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/sandbox-land/discard`,{method:"POST"}),ut.innerHTML=`<p>\u{1F5D1} ${s("sessions.landDiscarded")}</p>`}}catch(xe){ut.innerHTML=`<p>${s("sessions.landUnavailable")}: ${l(String(xe))}</p>`,lt.disabled=!1}});let Yn=a.querySelector("#insight-btn"),ft=a.querySelector("#insight-area");Yn&&ft&&(Yn.onclick=async()=>{Yn.disabled=!0,ft.innerHTML=`<p>${s("sessions.insightLoading")}</p>`;try{let xe=await fetch(`/api/sessions/${encodeURIComponent(d.sessionId)}/insight?detail=spans`),Te=await xe.json().catch(()=>({}));!Te.ok||!Te.report?ft.innerHTML=`<p>${s("sessions.insightUnavailable")}: ${l(String(Te.error??xe.status))}</p>`:ft.innerHTML=Et(Te.report)}catch(xe){ft.innerHTML=`<p>${s("sessions.insightUnavailable")}: ${l(String(xe))}</p>`}Yn.disabled=!1}),a.showModal()}t.addEventListener("click",d=>{let m=d.target;if(m.classList.contains("row-select")){let T=m.closest("tr[data-id]");if(!T)return;m.checked?B.add(T.dataset.id):B.delete(T.dataset.id),Sn(Bt());return}let k=m.closest("td");if(k&&k.querySelector(".row-select"))return;let w=m.closest("tr[data-id]");if(!w)return;let x=ke.sessions.get(w.dataset.id);x&&ks(x)}),L.addEventListener("click",d=>{let m=d.target,k=m.closest("button[data-move-col]");if(k){Vt(k.dataset.moveCol,Number(k.dataset.dir));return}let w=m.closest(".session-card[data-id]");if(!w)return;let x=ke.sessions.get(w.dataset.id);if(!x)return;let T=m.closest("button[data-action]");if(T){let F=T.dataset.action;F==="details"?ks(x):F==="write-link"?kl(x,T):F==="locate"?En(x,T):F==="restart"?Tn(x,T):F==="lock"?cn(x,!x.locked,T):F==="close"&>(x,T).then(W=>{W&&(B.delete(x.sessionId),ye())});return}m.closest("a, button, input, label")||(B.has(x.sessionId)?B.delete(x.sessionId):B.add(x.sessionId),w.classList.toggle("selected",B.has(x.sessionId)),w.setAttribute("aria-pressed",String(B.has(x.sessionId))),Sn(Bt().filter(F=>F.status!=="closed")))}),L.addEventListener("dragstart",d=>{let k=d.target.closest(".session-board-column > header[draggable]")?.closest(".session-board-column");k?.dataset.col&&(z=k.dataset.col,k.classList.add("dragging"),d.dataTransfer&&(d.dataTransfer.effectAllowed="move",d.dataTransfer.setData("text/plain",z)))}),L.addEventListener("dragover",d=>{if(!z)return;d.preventDefault(),d.dataTransfer&&(d.dataTransfer.dropEffect="move");let m=d.target.closest(".session-board-column");L.querySelectorAll(".drag-over").forEach(k=>k.classList.remove("drag-over")),m&&m.dataset.col!==z&&m.classList.add("drag-over")}),L.addEventListener("drop",d=>{if(!z)return;d.preventDefault();let m=d.target.closest(".session-board-column"),k=z;z=null,m?.dataset.col&&$t(k,m.dataset.col)}),L.addEventListener("dragend",()=>{z=null,L.querySelectorAll(".drag-over, .dragging").forEach(d=>d.classList.remove("drag-over","dragging"))}),O.forEach(d=>{d.addEventListener("click",()=>{let m=ma(d.dataset.view)??"board";m!==G&&(G=m,jr(window.localStorage,G),ye())})}),q.querySelectorAll("[data-groupby]").forEach(d=>{d.addEventListener("click",()=>{let m=d.dataset.groupby,k=m==="bot"?"bot":m==="team"?"team":"flow";k!==se&&(se=k,Gr(window.localStorage,k),E="",ye())})}),I.addEventListener("change",()=>{$e=I.value;try{window.localStorage.setItem(ga,$e)}catch{}E="",ye()});function Y(){he!==null&&(clearTimeout(he),he=null)}C.addEventListener("click",d=>{let m=d.target,k=m.closest(".kanban-card[data-id]");if(!k)return;let w=ke.sessions.get(k.dataset.id);if(!w)return;let x=m.closest("button[data-action]");if(x){x.dataset.action==="details"?ks(w):x.dataset.action==="rename"?oe(k,w):x.dataset.action==="history"?te(w):x.dataset.action==="restart"?Tn(w,x):x.dataset.action==="lock"&&cn(w,!w.locked,x);return}m.closest("a, button, input, label")||(Y(),he=setTimeout(()=>{he=null,ge(w)},220))}),C.addEventListener("dblclick",d=>{let m=d.target,k=m.closest(".kanban-card-title"),w=m.closest(".kanban-card[data-id]");if(!k||!w)return;Y();let x=ke.sessions.get(w.dataset.id);x&&oe(w,x)}),C.addEventListener("keydown",d=>{if(d.key!=="Enter"&&d.key!==" ")return;let m=d.target;if(!m.classList?.contains("kanban-card"))return;d.preventDefault();let k=ke.sessions.get(m.dataset.id);k&&ge(k)}),C.addEventListener("dragstart",d=>{if(se==="bot")return;let m=d.target,k=m.closest(".kanban-cluster > header[draggable]");if(k){let x=k.closest(".kanban-cluster"),T=x.closest(".kanban-column")?.dataset.col;if(!x.dataset.chat||!T)return;Y(),ie=x.dataset.chat,me=T,x.classList.add("dragging"),d.dataTransfer&&(d.dataTransfer.effectAllowed="move",d.dataTransfer.setData("text/plain",`cluster:${ie}`));return}let w=m.closest(".kanban-card[data-id]");w&&(Y(),ee=w.dataset.id,w.classList.add("dragging"),d.dataTransfer&&(d.dataTransfer.effectAllowed="move",d.dataTransfer.setData("text/plain",ee)))}),C.addEventListener("dragover",d=>{if(!ee&&!ie)return;d.preventDefault(),d.dataTransfer&&(d.dataTransfer.dropEffect="move");let m=d.target.closest(".kanban-column");C.querySelectorAll(".drag-over").forEach(k=>k.classList.remove("drag-over")),C.querySelectorAll(".drop-before").forEach(k=>k.classList.remove("drop-before")),m&&(m.classList.add("drag-over"),ue(m,d.clientY)?.classList.add("drop-before"))}),C.addEventListener("drop",d=>{let m=ie,k=me,w=ee;if(!w&&!m)return;d.preventDefault(),ee=null,ie=null,me=null,J();let x=d.target.closest(".kanban-column"),T=x?.dataset.col;if(!x||!T)return;let F=ue(x,d.clientY);if(m&&k){let ft=(ae.get(k)??[]).filter(qe=>String(qe.chatId)===m).filter(qe=>!(qe.status==="closed"&&T!=="done"));if(!ft.length)return;let xe=new Set(ft.map(qe=>qe.sessionId)),Te=(ae.get(T)??[]).filter(qe=>!xe.has(qe.sessionId)),Jt=F?Te.findIndex(qe=>qe.sessionId===F.dataset.id):Te.length;Jt<0&&(Jt=Te.length);let eo=Jt>0?Te[Jt-1]:null,$s=Jt<Te.length?Te[Jt]:null,to=Ta(eo?Ln(eo):null,$s?Ln($s):null);ft.forEach((qe,dn)=>{let ca=to+dn*.001;if(se==="team")ot(String(qe.sessionId),T,ca);else{let $d={column:qe.kanbanColumn,position:qe.kanbanPosition};qe.kanbanColumn=T,qe.kanbanPosition=ca,Rt(qe,T,ca,$d)}}),E="",ye();return}let W=ke.sessions.get(w)??kt.get(w);if(!W||W.status==="closed"&&T!=="done")return;let ne=(ae.get(T)??[]).filter(ft=>ft.sessionId!==w),de=F?ne.findIndex(ft=>ft.sessionId===F.dataset.id):ne.length;de<0&&(de=ne.length);let Ne=de>0?ne[de-1]:null,lt=de<ne.length?ne[de]:null,ut=Ta(Ne?Ln(Ne):null,lt?Ln(lt):null);if(se==="team"){ot(String(W.sessionId),T,ut),E="",ye();return}let Yn={column:W.kanbanColumn,position:W.kanbanPosition};W.kanbanColumn=T,W.kanbanPosition=ut,E="",ye(),Rt(W,T,ut,Yn)}),C.addEventListener("dragend",()=>{ee=null,ie=null,me=null,J(),E="",ye()}),P.addEventListener("click",d=>{d.target===P&&P.close()}),P.addEventListener("close",()=>{P.innerHTML=""}),H.addEventListener("click",d=>{d.target===H&&H.close()}),H.addEventListener("close",()=>{H.innerHTML=""}),o.addEventListener("change",()=>{let d=Bt().filter(m=>m.status!=="closed");for(let m of d)o.checked?B.add(m.sessionId):B.delete(m.sessionId);ye()}),f.addEventListener("click",()=>{B.clear(),ye()}),p.addEventListener("click",async()=>{let d=[...B];if(d.length===0||!confirm(s("sessions.closeBulkConfirm",{count:d.length})))return;p.disabled=!0,f.disabled=!0;let m=p.textContent,k=0,w=0,x=[...d];p.textContent=`0/${d.length}`;async function T(){for(;x.length;){let F=x.shift();try{let W=await fetch(`/api/sessions/${encodeURIComponent(F)}/close`,{method:"POST"}),ne=await W.json().catch(()=>({}));(!W.ok||ne?.ok===!1)&&(w+=1)}catch{w+=1}finally{k+=1,p.textContent=`${k}/${d.length}`}}}await Promise.all(Array.from({length:Math.min(6,d.length)},()=>T())),p.textContent=m,p.disabled=!1,f.disabled=!1,B.clear(),ye(),w>0&&alert(`Failed: ${w}/${d.length}`)});async function Q(d){let m=[...B].map(ne=>ke.sessions.get(ne)).filter(ne=>!!ne&&ne.status!=="closed"&&!!ne.locked!==d);if(m.length===0)return;u.disabled=!0,c.disabled=!0;let k=d?u.textContent:c.textContent,w=d?u:c,x=0,T=0,F=[...m];w.textContent=`0/${m.length}`;async function W(){for(;F.length;){let ne=F.shift(),de=!!ne.locked;try{let Ne=await fetch(`/api/sessions/${encodeURIComponent(ne.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:d})}),lt=await Ne.json().catch(()=>({}));!Ne.ok||lt?.ok===!1?(T+=1,ne.locked=de):ne.locked=!!lt.locked}catch{T+=1,ne.locked=de}finally{x+=1,w.textContent=`${x}/${m.length}`}}}await Promise.all(Array.from({length:Math.min(6,m.length)},()=>W())),w.textContent=k,Kt(),ye(),T>0&&alert(`${s("sessions.lockFailed")}: ${T}/${m.length}`)}u.addEventListener("click",()=>{Q(!0)}),c.addEventListener("click",()=>{Q(!1)}),y.addEventListener("click",d=>{if(Pe)return;let m=d.target?.closest("button[data-hours]");if(!m)return;let k=Ca(m.dataset.hours);!k||k===Ge||(Ge=k,M.textContent="",tt())}),g.addEventListener("click",async()=>{let d=it(),m=K();if(m.length===0)return;let k=He(d);if(confirm(s("sessions.idleCleanupConfirm",{count:m.length,threshold:k}))){Pe=!0,g.disabled=!0,M.textContent=s("sessions.idleCleanupRunning");try{let w=await fetch("/api/sessions/cleanup-idle",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({olderThanHours:d,sessionIds:m.map(T=>T.sessionId)})}),x=await w.json().catch(()=>({}));if(!w.ok){w.status!==401&&alert(`${s("sessions.idleCleanupFailed")}: ${x?.error??w.status}`),M.textContent="";return}for(let T of x?.results??[])T?.ok&&T?.sessionId&&B.delete(String(T.sessionId));M.textContent=s("sessions.idleCleanupDone",{closed:Number(x?.closed??0),failed:Number(x?.failed??0)}),ye()}catch(w){alert(`${s("sessions.idleCleanupFailed")}: ${w}`),M.textContent=""}finally{Pe=!1,tt()}}}),$.querySelectorAll("th[data-sort]").forEach(d=>{d.addEventListener("click",()=>{let m=d.dataset.sort;V===m?Z=Z==="asc"?"desc":"asc":(V=m,Z=m==="spawnedAt"||m==="lastMessageAt"?"desc":"asc"),ye()})}),n.addEventListener("input",ye),ke.on(ye);let X=setInterval(()=>{if(!document.body.contains(C)){clearInterval(X);return}G==="kanban"&&se==="team"&&(E="",ye())},3e4);ye(),bt().then(ye)}function Tp(){return`<section class="page">
|
|
451
|
-
<div class="page-heading">
|
|
452
|
-
<div>
|
|
453
|
-
<p class="eyebrow">${s("nav.schedules")}</p>
|
|
454
|
-
<h1>${s("schedules.title")}</h1>
|
|
455
|
-
<p>${s("schedules.subtitle")}</p>
|
|
456
|
-
</div>
|
|
457
|
-
</div>
|
|
458
|
-
<form id="sched-filters" class="filters">
|
|
459
|
-
<input type="search" name="q" placeholder="${s("schedules.search")}" />
|
|
460
|
-
<select name="kind">
|
|
461
|
-
<option value="">${s("schedules.anyKind")}</option>
|
|
462
|
-
<option>cron</option>
|
|
463
|
-
<option>interval</option>
|
|
464
|
-
<option>once</option>
|
|
465
|
-
</select>
|
|
466
|
-
<label><input type="checkbox" name="enabled"> ${s("schedules.enabledOnly")}</label>
|
|
467
|
-
</form>
|
|
468
|
-
<table>
|
|
469
|
-
<thead><tr>
|
|
470
|
-
<th>${s("schedules.name")}</th><th>${s("schedules.bot")}</th><th>${s("schedules.schedule")}</th><th>${s("schedules.delivery")}</th><th>${s("schedules.next")}</th><th>${s("schedules.last")}</th>
|
|
471
|
-
<th>${s("schedules.repeat")}</th><th>${s("schedules.enabled")}</th><th>${s("schedules.actions")}</th>
|
|
472
|
-
</tr></thead>
|
|
473
|
-
<tbody id="schedules-tbody"></tbody>
|
|
474
|
-
</table>
|
|
475
|
-
</section>`}function Sl(e){if(!e)return"\u2014";try{return new Date(e).toLocaleString()}catch{return e}}function El(e){e.innerHTML=Tp();let t=e.querySelector("#schedules-tbody"),n=e.querySelector("#sched-filters");function a(){let i=new FormData(n),r=(i.get("q")??"").toLowerCase(),u=i.get("kind"),c=!!i.get("enabled");return[...ke.schedules.values()].filter(p=>!u||p.parsed?.kind===u).filter(p=>!c||p.enabled).filter(p=>!r||JSON.stringify(p).toLowerCase().includes(r)).sort((p,f)=>{if(p.enabled!==f.enabled)return p.enabled?-1:1;let h=p.nextRunAt?Date.parse(p.nextRunAt):1/0,y=f.nextRunAt?Date.parse(f.nextRunAt):1/0;return h-y})}function o(){t.innerHTML=a().map(i=>`<tr data-id="${l(i.id)}">
|
|
476
|
-
<td>${l(i.name??i.id)}</td>
|
|
477
|
-
<td>${l(i.botName??i.larkAppId??"-")}</td>
|
|
478
|
-
<td><code>${l(i.parsed?.display??"?")}</code></td>
|
|
479
|
-
<td>${i.deliver==="new-topic"?`\u{1F195} ${s("schedules.deliveryNewTopic")}`:i.deliver==="local"?`\u{1F515} ${s("schedules.deliveryLocal")}`:s("schedules.deliveryOrigin")}</td>
|
|
480
|
-
<td>${Sl(i.nextRunAt)}</td>
|
|
481
|
-
<td>${Sl(i.lastRunAt)} ${i.lastStatus==="error"?"\u26A0\uFE0F":""}</td>
|
|
482
|
-
<td>${i.repeat?`${i.repeat.completed}/${i.repeat.times??"\u221E"}`:"\u2014"}</td>
|
|
483
|
-
<td>${i.enabled?"\u2713":"\u2717"}</td>
|
|
484
|
-
<td class="actions-cell">
|
|
485
|
-
<button data-op="run" type="button">${s("schedules.runNow")}</button>
|
|
486
|
-
${i.enabled?`<button data-op="pause" type="button">${s("schedules.pause")}</button>`:`<button data-op="resume" type="button">${s("schedules.resume")}</button>`}
|
|
487
|
-
${i.deliver==="local"?"":`<button data-op="delivery" type="button">${i.deliver==="new-topic"?s("schedules.useOrigin"):s("schedules.useNewTopic")}</button>`}
|
|
488
|
-
</td>
|
|
489
|
-
</tr>`).join("")||`<tr><td colspan="9" class="empty">${s("schedules.empty")}</td></tr>`}t.addEventListener("click",async i=>{let r=i.target.closest("button[data-op]");if(!r)return;let u=r.closest("tr[data-id]");if(!u)return;let c=u.dataset.id,p=r.dataset.op;r.disabled=!0;let f=r.textContent;r.textContent="...";try{let h=await fetch(`/api/schedules/${encodeURIComponent(c)}/${p}`,{method:"POST"}),y=await h.json().catch(()=>({}));(!h.ok||y.ok===!1)&&alert(`Failed: ${h.status} ${y?.error??""}`.trim())}catch(h){alert("Network error: "+h)}finally{r.disabled=!1,r.textContent=f}}),n.addEventListener("input",o),ke.on(o),o()}function Tl(e){return e==null||typeof e=="string"?{content:e??null,source:e==null?"none":"chat"}:{content:e.content??null,source:e.source??"none"}}function mo(e){for(let t of e.values()){let n=Tl(t);if(n.source==="chat"&&n.content!==null)return!0}return!1}function ho(e,t,n,a){let o=new Set(e.filter(r=>r.inChat).map(r=>String(r.larkAppId)));if(o.size===0)return[];let i=[];for(let r of t){let u=(n.get(r.profileId)??[]).filter(f=>o.has(f.larkAppId)&&typeof f.content=="string"&&f.content!=="");if(u.length===0)continue;let c=0,p=0;for(let f of u){let h=Tl(a.get(f.larkAppId));h.source==="chat"&&h.content===f.content&&(c++,p++)}c===u.length?i.push({profileId:r.profileId,matched:c,total:u.length,chatMatched:p,kind:"full"}):c>0&&i.push({profileId:r.profileId,matched:c,total:u.length,chatMatched:p,kind:"partial"})}return i.sort((r,u)=>{if(r.kind!==u.kind)return r.kind==="full"?-1:1;let c=u.matched/u.total-r.matched/r.total;return c!==0?c:u.chatMatched!==r.chatMatched?u.chatMatched-r.chatMatched:u.matched!==r.matched?u.matched-r.matched:r.profileId.localeCompare(u.profileId)})}var st={chats:[],bots:[]},Lp=/^[A-Za-z0-9._-]{1,64}$/,Ml=(e,t)=>`${e}\0${t}`,go=[],Ha=new Map,_a=new Map,Ll=!1;function Al(e){return Lp.test(e)&&e!=="."&&e!==".."}function Cl(e){let t=String(e??"").trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,64);return Al(t)?t:"profile"}function Cp(){return`<section class="page">
|
|
490
|
-
<div class="page-heading">
|
|
491
|
-
<div>
|
|
492
|
-
<p class="eyebrow">${s("nav.groups")}</p>
|
|
493
|
-
<h1>${s("groups.title")}</h1>
|
|
494
|
-
<p>${s("groups.subtitle")}</p>
|
|
495
|
-
</div>
|
|
496
|
-
</div>
|
|
497
|
-
<form id="g-filters" class="filters">
|
|
498
|
-
<input type="search" name="q" placeholder="${s("groups.search")}" />
|
|
499
|
-
<label><input type="checkbox" name="missing"> ${s("groups.missingOnly")}</label>
|
|
500
|
-
<button type="button" id="g-refresh">${s("groups.refresh")}</button>
|
|
501
|
-
<button type="button" id="g-create" class="primary">${s("groups.create")}</button>
|
|
502
|
-
</form>
|
|
503
|
-
<div id="g-loading">${Tt()}</div>
|
|
504
|
-
<div class="table-scroll matrix-scroll" id="g-table-wrap" hidden>
|
|
505
|
-
<table>
|
|
506
|
-
<thead id="g-head"></thead>
|
|
507
|
-
<tbody id="g-body"></tbody>
|
|
508
|
-
</table>
|
|
509
|
-
</div>
|
|
510
|
-
<dialog id="g-drawer"></dialog>
|
|
511
|
-
</section>`}async function Xn(){st=await(await fetch("/api/groups")).json()}async function Ip(){return(await fetch("/api/groups")).json()}async function Mp(){let t=await(await fetch("/api/role-profiles")).json().catch(()=>({})),n=Array.isArray(t.profiles)?t.profiles:[],a=await Promise.all(n.map(async r=>{try{let c=await(await fetch(`/api/role-profiles/${encodeURIComponent(r.profileId)}`)).json().catch(()=>({}));return[r.profileId,Array.isArray(c.entries)?c.entries:[]]}catch{return[r.profileId,[]]}})),o=new Map,i=new Set;await Promise.all((st.chats??[]).flatMap(r=>(r.memberBots??[]).filter(u=>u?.inChat&&u?.larkAppId).map(async u=>{let c=Ml(u.larkAppId,r.chatId);if(!i.has(c)){i.add(c);try{let f=await(await fetch(`/api/roles/${encodeURIComponent(u.larkAppId)}/${encodeURIComponent(r.chatId)}`)).json().catch(()=>({})),h=f?.hasEffectiveRole??f?.hasRole,y="effectiveContent"in f?f.effectiveContent:f.content;o.set(c,{content:h?String(y??""):null,source:f?.effectiveSource??(f?.hasRole?"chat":"none")})}catch{o.set(c,null)}}}))),go=n,Ha=new Map(a),_a=o}async function Ap(){let t=await(await fetch("/api/role-profiles")).json().catch(()=>({}));return Array.isArray(t.profiles)?t.profiles:[]}function Dp(e,t){if(t.size===0)return!0;let n=e?.memberBots??[];for(let a of t)if(!n.some(o=>o.larkAppId===a&&o.inChat))return!1;return!0}function Il(e,t){return e.filter(n=>!t||!t.has(n.larkAppId)).map(n=>`
|
|
512
|
-
<label class="checkbox-row">
|
|
513
|
-
<input type="checkbox" name="bot" value="${l(n.larkAppId)}">
|
|
514
|
-
${l(n.botName??n.larkAppId)} <small>(${l(n.larkAppId)})</small>
|
|
515
|
-
</label>
|
|
516
|
-
`).join("")}function Hp(e,t,n){let a=String(e??"").trim();if(!a)return"";if(n)return`<p class="hint-warn">${l(s("groups.roleProfileBootstrapFailed",{name:a,reason:String(n)}))}</p>`;let o=typeof t=="string"&&t.trim()?t.trim():"";return o?`<p class="hint-ok">${l(s("groups.roleProfileBootstrapSent",{name:a,messageId:o}))}</p>`:`<p class="hint-ok">${l(s("groups.roleProfileBootstrapDone",{name:a}))}</p>`}function _p(e){let t=Array.isArray(e)?e:[];if(!t.length)return'<p class="hint-warn">\u6CA1\u6709\u8FD4\u56DE\u6DFB\u52A0\u7ED3\u679C\u3002</p>';let n=t.filter(r=>!!r?.ok).length,a=t.length-n,o=a?"hint-warn":"hint-ok",i=t.map(r=>{let u=String(r?.id??"?");return r?.ok?`<li><code>${l(u)}</code>: OK</li>`:`<li><code>${l(u)}</code>: failed (${l(String(r?.error??"unknown"))})</li>`}).join("");return`<div class="${o}">
|
|
517
|
-
<strong>\u6DFB\u52A0\u7ED3\u679C\uFF1A\u6210\u529F ${n}/${t.length}${a?`\uFF0C\u5931\u8D25 ${a}`:""}</strong>
|
|
518
|
-
<ul>${i}</ul>
|
|
519
|
-
</div>`}async function Dl(e){e.innerHTML=Cp();let t=e.querySelector("#g-head"),n=e.querySelector("#g-body"),a=e.querySelector("#g-filters"),o=e.querySelector("#g-refresh"),i=e.querySelector("#g-drawer");o.onclick=async()=>{o.disabled=!0;try{await Xn(),L(),p()}finally{o.disabled=!1}};let r=e.querySelector("#g-create");r.onclick=()=>{g()};let u=e.querySelector("#g-loading"),c=e.querySelector("#g-table-wrap");try{await Xn()}finally{u.remove(),c.hidden=!1}async function p(){try{await Mp()}catch{go=[],Ha=new Map,_a=new Map}finally{Ll=!0,L()}}function f(I,N){I.innerHTML=N}function h(I,N){return`<p class="hint-warn"><strong>${l(I)}</strong><br><small>${l(String(N??"unknown"))}</small></p>`}function y(I,N){I&&(I.disabled=!1,I.textContent=N)}async function g(){let I=st.bots;if(I.length===0){alert(s("groups.noBotsOnline"));return}let N=[];try{N=(await(await fetch("/api/role-profiles")).json()).profiles??[]}catch{}i.innerHTML=`
|
|
520
|
-
<article>
|
|
521
|
-
<header><h3>${s("groups.createTitle")}</h3></header>
|
|
522
|
-
<p>${s("groups.createHelp")}</p>
|
|
523
|
-
<form id="g-createform">
|
|
524
|
-
<label class="form-row">
|
|
525
|
-
<span>${s("groups.name")}</span>
|
|
526
|
-
<input type="text" name="name" placeholder="${s("groups.namePlaceholder")}" maxlength="60">
|
|
527
|
-
</label>
|
|
528
|
-
<label class="form-row">
|
|
529
|
-
<span>${s("groups.bindDir")}</span>
|
|
530
|
-
<input type="text" name="bindWorkingDir" placeholder="e.g. ~/projects/botmux">
|
|
531
|
-
<small>${s("groups.bindDirHelp")}</small>
|
|
532
|
-
</label>
|
|
533
|
-
<label class="form-row">
|
|
534
|
-
<span>${s("groups.roleProfile")}</span>
|
|
535
|
-
<select name="roleProfileId">
|
|
536
|
-
<option value="">${s("groups.roleProfileNone")}</option>
|
|
537
|
-
${N.map(R=>`<option value="${l(R.profileId)}">${l(R.profileId)}</option>`).join("")}
|
|
538
|
-
</select>
|
|
539
|
-
<small>${s("groups.roleProfileHelp")}</small>
|
|
540
|
-
</label>
|
|
541
|
-
<fieldset>
|
|
542
|
-
<legend>${s("groups.botPicker")}</legend>
|
|
543
|
-
${Il(I)}
|
|
544
|
-
</fieldset>
|
|
545
|
-
<div data-create-status aria-live="polite"></div>
|
|
546
|
-
<div class="actions">
|
|
547
|
-
<button type="submit" class="primary">${s("groups.createSubmit")}</button>
|
|
548
|
-
<button type="button" id="g-create-cancel">${s("groups.cancel")}</button>
|
|
549
|
-
</div>
|
|
550
|
-
</form>
|
|
551
|
-
</article>`,i.showModal(),i.querySelector("#g-create-cancel").onclick=()=>i.close(),i.querySelector("#g-createform").onsubmit=async R=>{R.preventDefault();let B=new FormData(R.target),V=(B.get("name")??"").trim(),Z=(B.get("bindWorkingDir")??"").trim(),G=(B.get("roleProfileId")??"").trim(),j=B.getAll("bot"),z=i.querySelector("[data-create-status]");if(j.length===0){f(z,h("\u8BF7\u9009\u62E9 bot","\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A bot \u540E\u518D\u521B\u5EFA\u7FA4\u804A\u3002"));return}let b=R.target.querySelector("button[type=submit]");b&&(b.disabled=!0,b.textContent="Creating..."),f(z,"");try{let S=await fetch("/api/groups/create",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({name:V||void 0,larkAppIds:j,bindWorkingDir:Z||void 0,roleProfileId:G||void 0})}),E=await S.json();if(E.ok&&E.chatId){v(E);let U=Array.isArray(E.invalidBotIds)?E.invalidBotIds:[],ee=j.filter(he=>!U.includes(he)),pe=new Set(ee);typeof E.creator=="string"&&E.creator&&pe.add(E.creator),O(E.chatId,V||E.chatId,ee,E.creator),L(),p(),A(E.chatId,pe).catch(()=>{})}else f(z,h("\u521B\u5EFA\u5931\u8D25",E.error??`HTTP ${S.status}`)),y(b,s("groups.createSubmit"))}catch(S){f(z,h("\u7F51\u7EDC\u9519\u8BEF",S)),y(b,s("groups.createSubmit"))}};function O(R,B,V,Z){let G=new Set(V);Z&&G.add(Z);let j=st.bots.map(b=>({larkAppId:b.larkAppId,botName:b.botName,inChat:G.has(b.larkAppId),oncallChat:null})),z={chatId:R,name:B,ownerId:Z??null,memberBots:j};st.chats=[z,...st.chats.filter(b=>b.chatId!==R)]}async function A(R,B){let V=[600,1200,1200,1200,1200,1200];for(let Z of V){await new Promise(z=>setTimeout(z,Z));let G;try{G=await Ip()}catch{continue}let j=(G.chats??[]).find(z=>z.chatId===R);if(j&&Dp(j,B)){st=G,L(),p();return}}}}function v(I){let N=String(I.chatId),O=typeof I.shareLink=="string"&&I.shareLink?I.shareLink:`https://applink.feishu.cn/client/chat/open?openChatId=${encodeURIComponent(N)}`,A=I.invalidBotIds??[],R=I.invalidUserIds??[],B=I.autoInvitedOpenId,V=!!I.autoInviteRejected,Z=I.ownerTransferredTo,G=I.transferError,j=I.notifyMessageId,z=I.notifyError,b=Array.isArray(I.oncallBindings)?I.oncallBindings:[],S=b.filter(ae=>ae?.ok).length,E=b.filter(ae=>!ae?.ok),U=b.length>0?E.length===0?`<p class="hint-ok">\u5DF2\u7ED1\u5B9A\u76EE\u5F55\uFF1A<code>${l(I.bindResolvedPath??"")}</code>\uFF08${S}/${b.length} bots\uFF09</p>`:`<p class="hint-warn">\u76EE\u5F55\u7ED1\u5B9A\u90E8\u5206\u5931\u8D25\uFF1A\u6210\u529F ${S}/${b.length}\u3002${E.map(ae=>`<br><code>${l(ae.larkAppId??"?")}</code>: ${l(ae.error??"unknown")}`).join("")}</p>`:"",ee;if(B){let ae=Z?"<br><small>\u7FA4\u4E3B\u5DF2\u4ECE\u673A\u5668\u4EBA\u8F6C\u8BA9\u7ED9\u4F60\u3002</small>":G?`<br><small class="hint-warn-inline">\u26A0 \u81EA\u52A8\u8F6C\u8BA9\u7FA4\u4E3B\u5931\u8D25\uFF08${l(G)}\uFF09\uFF0C\u4F60\u73B0\u5728\u662F\u6210\u5458\u4F46\u7FA4\u4E3B\u4ECD\u662F\u673A\u5668\u4EBA\u3002</small>`:"",se=j?`<br><small>\u673A\u5668\u4EBA\u5DF2\u5728\u7FA4\u91CC @ \u4E86\u4F60\uFF08\u6D88\u606F id <code>${l(j)}</code>\uFF09\uFF0C\u770B\u98DE\u4E66\u901A\u77E5\u5C31\u80FD\u8FDB\u7FA4\u3002</small>`:z?`<br><small class="hint-warn-inline">\u26A0 \u81EA\u52A8 @ \u901A\u77E5\u5931\u8D25\uFF08${l(z)}\uFF09\uFF0C\u65B0\u7FA4\u53EF\u80FD\u4E0D\u4F1A\u4E3B\u52A8\u51FA\u73B0\u5728\u4F60\u4FA7\u8FB9\u680F\uFF0C\u5EFA\u8BAE\u4ECE\u4E0B\u9762\u6309\u94AE\u8DF3\u8FDB\u53BB\u3002</small>`:"";ee=`<p class="hint-ok">\u5DF2\u81EA\u52A8\u9080\u8BF7\u4F60\uFF08<code>${l(B)}</code>\uFF09\u4F5C\u4E3A\u6210\u5458\u3002${ae}${se}</p>`}else V?ee='<p class="hint-warn">\u98DE\u4E66\u62D2\u7EDD\u4E86\u81EA\u52A8\u9080\u8BF7\uFF08\u4F60\u7684 open_id \u5728\u521B\u5EFA\u8005 bot \u7684 scope \u4E0B\u4E0D\u53EF\u7528\uFF09\u3002<strong>\u4F60\u76EE\u524D\u4E0D\u662F\u65B0\u7FA4\u6210\u5458</strong>\uFF0C\u9700\u8981\u8BA9\u7FA4\u91CC\u7684\u67D0\u4E2A\u673A\u5668\u4EBA\u624B\u52A8\u628A\u4F60\u52A0\u8FDB\u6765\u3002</p>':ee='<p class="hint-warn">\u6CA1\u5728 dashboard \u7F13\u5B58\u91CC\u627E\u5230 ownerOpenId\uFF0C<strong>\u6CA1\u6709\u81EA\u52A8\u9080\u8BF7\u4F60</strong>\u3002\u70B9\u5F00\u4E0B\u9762\u94FE\u63A5\u524D\uFF0C\u5148\u8BA9\u7FA4\u91CC\u4EFB\u4E00\u673A\u5668\u4EBA\u624B\u52A8\u628A\u4F60\u52A0\u8FDB\u53BB\u3002</p>';let pe=[A.length?`<li>\u65E0\u6548 bot id: <code>${A.map(l).join(", ")}</code></li>`:"",R.length?`<li>\u65E0\u6548\u7528\u6237 open_id: <code>${R.map(l).join(", ")}</code></li>`:""].filter(Boolean).join(""),he=Hp(typeof I.roleProfileId=="string"?I.roleProfileId:"",I.roleProfileBootstrapMessageId,I.roleProfileBootstrapError);i.innerHTML=`
|
|
552
|
-
<article>
|
|
553
|
-
<header><h3>${s("groups.successTitle")}</h3></header>
|
|
554
|
-
<p><b>chatId:</b> <code>${l(N)}</code> <button type="button" data-copy="${l(N)}">${s("sessions.copy")}</button></p>
|
|
555
|
-
<p><b>\u521B\u5EFA\u8005:</b> <code>${l(I.creator??"?")}</code></p>
|
|
556
|
-
${ee}
|
|
557
|
-
${U}
|
|
558
|
-
${he}
|
|
559
|
-
${pe?`<ul>${pe}</ul>`:""}
|
|
560
|
-
<div class="actions">
|
|
561
|
-
<a class="btn-link primary" href="${O}" target="_blank" rel="noopener">${s("groups.openGroup")}</a>
|
|
562
|
-
<button type="button" id="g-create-close">${s("sessions.dismiss")}</button>
|
|
563
|
-
</div>
|
|
564
|
-
</article>`,i.querySelectorAll("[data-copy]").forEach(ae=>{ae.onclick=()=>{navigator.clipboard.writeText(ae.dataset.copy??""),ae.textContent=s("sessions.copied"),setTimeout(()=>{ae.textContent=s("sessions.copy")},800)}}),i.querySelector("#g-create-close").onclick=()=>i.close()}function M(I){if(!go.length||!Ll)return"";let N=new Map;for(let B of I.memberBots??[])B?.inChat&&N.set(B.larkAppId,_a.get(Ml(B.larkAppId,I.chatId))??null);if(!mo(N))return"";let A=ho(I.memberBots??[],go,Ha,N)[0];if(!A)return`<div class="g-profile-status muted">${s("groups.profileStatusUnmatched")}</div>`;let R=A.kind==="full"?"groups.profileStatusFullChat":"groups.profileStatusPartial";return`<div class="g-profile-status ${A.kind}">
|
|
565
|
-
${l(s(R,{name:A.profileId,matched:A.matched,total:A.total,chat:A.chatMatched}))}
|
|
566
|
-
</div>`}function $(){t.innerHTML=`<tr>
|
|
567
|
-
<th>${s("groups.chat")}</th>
|
|
568
|
-
${st.bots.map(I=>`<th>${l(I.botName??I.larkAppId)}</th>`).join("")}
|
|
569
|
-
<th>${s("groups.actions")}</th>
|
|
570
|
-
</tr>`}function L(){$();let I=new FormData(a),N=(I.get("q")??"").toLowerCase(),O=!!I.get("missing"),A=st.chats.filter(R=>!N||(R.name??"").toLowerCase().includes(N)||R.chatId.toLowerCase().includes(N)||(R.ownerId??"").toLowerCase().includes(N)).filter(R=>!O||R.memberBots.some(B=>!B.inChat));if(A.length===0){n.innerHTML=`<tr><td colspan="${st.bots.length+2}" class="empty">${s("groups.empty")}</td></tr>`;return}n.innerHTML=A.map(R=>`<tr data-chat="${l(R.chatId)}">
|
|
571
|
-
<td>
|
|
572
|
-
<div class="g-chat-cell">
|
|
573
|
-
${co({chatId:R.chatId,name:R.name,avatarUrl:R.avatar,size:"sm"})}
|
|
574
|
-
<div class="g-chat-meta">
|
|
575
|
-
<strong>${l(R.name??R.chatId)}</strong><br>
|
|
576
|
-
<small><code>${l(R.chatId)}</code></small>
|
|
577
|
-
${M(R)}
|
|
578
|
-
</div>
|
|
579
|
-
</div>
|
|
580
|
-
</td>
|
|
581
|
-
${st.bots.map(B=>{let V=R.memberBots.find(j=>j.larkAppId===B.larkAppId),Z=V?V.error?"!":V.inChat?"\u2713":"\u2717":"?";return`<td class="${V?V.error?"cell-error":V.inChat?"cell-in":"cell-out":"cell-unknown"}" title="${l(V?.error??"")}">${Z}</td>`}).join("")}
|
|
582
|
-
<td>
|
|
583
|
-
<button class="add-bots" type="button">${s("groups.addBots")}</button>
|
|
584
|
-
<button class="save-profile" type="button">${s("groups.saveAsProfile")}</button>
|
|
585
|
-
<button class="manage-chat" type="button">${s("groups.manage")}</button>
|
|
586
|
-
</td>
|
|
587
|
-
</tr>`).join("")}L(),p(),n.addEventListener("click",async I=>{let N=I.target.closest("button.add-bots");if(!N)return;let A=N.closest("tr[data-chat]").dataset.chat,R=st.chats.find(Z=>Z.chatId===A);if(!R)return;let B=new Set(R.memberBots.filter(Z=>Z.inChat).map(Z=>Z.larkAppId));if(!st.bots.filter(Z=>!B.has(Z.larkAppId)).length){alert("All configured bots are already in this chat.");return}i.innerHTML=`
|
|
588
|
-
<article>
|
|
589
|
-
<header><h3>${s("groups.addBots")} \xB7 ${l(R.name??R.chatId)}</h3></header>
|
|
590
|
-
<p>${s("groups.createHelp")}</p>
|
|
591
|
-
<form id="g-addform">
|
|
592
|
-
${Il(st.bots,B)}
|
|
593
|
-
<div data-add-status aria-live="polite"></div>
|
|
594
|
-
<div class="actions">
|
|
595
|
-
<button type="submit" class="primary">${s("groups.addBots")}</button>
|
|
596
|
-
<button type="button" id="g-cancel">${s("groups.cancel")}</button>
|
|
597
|
-
</div>
|
|
598
|
-
</form>
|
|
599
|
-
</article>`,i.showModal(),i.querySelector("#g-cancel").onclick=()=>i.close(),i.querySelector("#g-addform").onsubmit=async Z=>{Z.preventDefault();let j=new FormData(Z.target).getAll("bot"),z=i.querySelector("[data-add-status]");if(j.length===0){f(z,h("\u8BF7\u9009\u62E9 bot","\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A bot \u540E\u518D\u6DFB\u52A0\u3002"));return}let b=Z.target.querySelector("button[type=submit]");b&&(b.disabled=!0,b.textContent="Adding..."),f(z,"");try{let E=await(await fetch(`/api/groups/${encodeURIComponent(A)}/add-bots`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({larkAppIds:j})})).json();if(E.error==="no_proxy_bot")f(z,h("\u65E0\u6CD5\u6DFB\u52A0 bot","\u5F53\u524D\u7FA4\u91CC\u6CA1\u6709\u53EF\u4EE3\u7406\u64CD\u4F5C\u7684 bot\u3002\u8BF7\u5148\u5728\u98DE\u4E66\u91CC\u624B\u52A8\u62C9\u5165\u4E00\u4E2A bot\uFF0C\u7136\u540E\u91CD\u8BD5\u3002"));else if(E.result){let U=_p(E.result);f(z,U);try{await Xn(),L(),p()}catch(ee){f(z,`${U}${h("\u5237\u65B0\u5931\u8D25",`\u6DFB\u52A0\u7ED3\u679C\u5DF2\u8FD4\u56DE\uFF0C\u4F46\u5237\u65B0\u7FA4\u7EC4\u5217\u8868\u5931\u8D25\uFF1A${ee}`)}`)}}else f(z,h("\u54CD\u5E94\u5F02\u5E38",JSON.stringify(E)))}catch(S){f(z,h("\u7F51\u7EDC\u9519\u8BEF",S))}finally{y(b,s("groups.addBots"))}}}),n.addEventListener("click",async I=>{let N=I.target.closest("button.save-profile");if(!N)return;let A=N.closest("tr[data-chat]").dataset.chat,R=st.chats.find(B=>B.chatId===A);R&&await C(R,N)});async function C(I,N){let O=Cl(I.name??""),A=O==="profile"?Cl(I.chatId):O;N.disabled=!0;let R=N.textContent;N.textContent=s("groups.saveProfileSaving");try{let[B,V]=await Promise.all([P(I),Ap()]);H(I,A,B,V)}finally{N.disabled=!1,N.textContent=R}}async function P(I){let N=(I.memberBots??[]).filter(A=>A?.inChat&&A?.larkAppId);return await Promise.all(N.map(async A=>{try{let B=await(await fetch(`/api/roles/${encodeURIComponent(A.larkAppId)}/${encodeURIComponent(I.chatId)}`)).json().catch(()=>({})),V=B?.hasEffectiveRole??B?.hasRole,Z="effectiveContent"in B?B.effectiveContent:B.content,G=V?String(Z??"").trim():"",j=B?.effectiveSource==="chat"||B?.effectiveSource==="team"?B.effectiveSource:null;return{larkAppId:A.larkAppId,botName:A.botName,content:G,status:G?j??"chat":"empty"}}catch{return{larkAppId:A.larkAppId,botName:A.botName,content:"",status:"error"}}}))}function H(I,N,O,A){let R=[...A].sort((le,ve)=>le.profileId.localeCompare(ve.profileId)),B=R.map((le,ve)=>`
|
|
600
|
-
<button type="button"
|
|
601
|
-
class="g-save-profile-pick ${ve===0?"selected":""}"
|
|
602
|
-
data-profile-id="${l(le.profileId)}"
|
|
603
|
-
aria-pressed="${ve===0?"true":"false"}">
|
|
604
|
-
<span>${l(le.profileId)}</span>
|
|
605
|
-
<small>${l(s("groups.saveProfileExistingMeta",{count:le.entryCount??0}))}</small>
|
|
606
|
-
</button>`).join(""),V=R.length>0,Z=O.filter(le=>le.status==="empty").length,G=O.filter(le=>le.status==="error").length,j=O.length>0&&G===0,z=O.map(le=>`
|
|
607
|
-
<div class="g-save-profile-entry ${le.status==="error"?"error":""}">
|
|
608
|
-
<div>
|
|
609
|
-
<strong>${l(le.botName??le.larkAppId)}</strong>
|
|
610
|
-
<code>${l(le.larkAppId)}</code>
|
|
611
|
-
</div>
|
|
612
|
-
<span class="g-save-profile-entry-status ${le.status==="error"?"error":"ok"}">
|
|
613
|
-
${s(le.status==="error"?"groups.saveProfileStatus.error":"groups.saveProfileStatus.entry")}
|
|
614
|
-
</span>
|
|
615
|
-
</div>`).join("");i.innerHTML=`
|
|
616
|
-
<article class="g-save-profile-dialog">
|
|
617
|
-
<header>
|
|
618
|
-
<h3>${s("groups.saveProfileTitle")}</h3>
|
|
619
|
-
<p>${l(s("groups.saveProfileIntro",{name:I.name??I.chatId,count:O.length}))}</p>
|
|
620
|
-
</header>
|
|
621
|
-
<form id="g-save-profile-form">
|
|
622
|
-
<section class="g-save-profile-panel">
|
|
623
|
-
<div class="g-save-profile-section-head">
|
|
624
|
-
<span>${s("groups.saveProfileScope")}</span>
|
|
625
|
-
<small>${s("groups.saveProfileScopeHelp")}</small>
|
|
626
|
-
</div>
|
|
627
|
-
<div class="g-save-profile-stats">
|
|
628
|
-
<span>${s("groups.saveProfileBotCount")} <strong>${O.length}</strong></span>
|
|
629
|
-
${G?`<span class="warn">${s("groups.saveProfileLoadFailed")} <strong>${G}</strong></span>`:""}
|
|
630
|
-
</div>
|
|
631
|
-
<div class="g-save-profile-entry-list">
|
|
632
|
-
${z||`<div class="g-save-profile-empty">${s("groups.saveProfileNoRoles")}</div>`}
|
|
633
|
-
</div>
|
|
634
|
-
</section>
|
|
635
|
-
|
|
636
|
-
<div class="form-row">
|
|
637
|
-
<span>${s("groups.saveProfileMode")}</span>
|
|
638
|
-
<div class="g-save-profile-switch" role="tablist" aria-label="${s("groups.saveProfileMode")}">
|
|
639
|
-
<button type="button" class="active" data-save-profile-mode="new">${s("groups.saveProfileNew")}</button>
|
|
640
|
-
<button type="button" data-save-profile-mode="overwrite" ${V?"":"disabled"}>${s("groups.saveProfileOverwrite")}</button>
|
|
641
|
-
</div>
|
|
642
|
-
</div>
|
|
643
|
-
<label class="form-row" data-profile-mode-row="new">
|
|
644
|
-
<span>${s("groups.saveProfileIdLabel")}</span>
|
|
645
|
-
<input type="text" name="profileId" value="${l(N)}" maxlength="64" autocomplete="off">
|
|
646
|
-
<small>${s("groups.saveProfileInvalid")}</small>
|
|
647
|
-
</label>
|
|
648
|
-
<div class="form-row" data-profile-mode-row="overwrite" hidden>
|
|
649
|
-
<span>${s("groups.saveProfileExistingLabel")}</span>
|
|
650
|
-
${V?`<div class="g-save-profile-picker">${B}</div>`:`<div class="g-save-profile-summary warn">${s("groups.saveProfileExistingEmpty")}</div>`}
|
|
651
|
-
<small>${s("groups.saveProfileOverwriteHelp")}</small>
|
|
652
|
-
</div>
|
|
653
|
-
<div class="g-save-profile-target">
|
|
654
|
-
<span>${s("groups.saveProfileTarget")}</span>
|
|
655
|
-
<code data-save-profile-target>${l(N)}</code>
|
|
656
|
-
<small data-save-profile-target-mode>${s("groups.saveProfileTargetNew")}</small>
|
|
657
|
-
</div>
|
|
658
|
-
<div class="g-save-profile-summary ${j?"":"warn"}">
|
|
659
|
-
${G?l(s("groups.saveProfileFailedLoadSummary",{count:G})):O.length?l(Z?s("groups.saveProfileEntrySummaryWithEmpty",{count:O.length,emptyCount:Z}):s("groups.saveProfileEntrySummary",{count:O.length})):l(s("groups.saveProfileNoRoles"))}
|
|
660
|
-
</div>
|
|
661
|
-
<div class="g-save-profile-status" data-save-profile-status></div>
|
|
662
|
-
<div class="actions">
|
|
663
|
-
<button type="submit" class="primary" ${j?"":"disabled"}>${s("groups.saveProfileSubmit")}</button>
|
|
664
|
-
<button type="button" id="g-save-profile-cancel">${s("groups.cancel")}</button>
|
|
665
|
-
</div>
|
|
666
|
-
</form>
|
|
667
|
-
</article>`,i.showModal();let b=i.querySelector("#g-save-profile-form"),S=[...i.querySelectorAll("[data-profile-mode-row]")],E=i.querySelector("[data-save-profile-status]"),U=b.querySelector("button[type=submit]"),ee=[...b.querySelectorAll("[data-save-profile-mode]")],pe=[...b.querySelectorAll("[data-profile-id]")],he=b.querySelector("input[name=profileId]"),ae=b.querySelector("[data-save-profile-target]"),se=b.querySelector("[data-save-profile-target-mode]"),ie="new",me=R[0]?.profileId??"";function be(){return ie==="overwrite"?me:he.value.trim()}function Me(){for(let le of S)le.hidden=le.dataset.profileModeRow!==ie;for(let le of ee){let ve=le.dataset.saveProfileMode===ie;le.classList.toggle("active",ve),le.setAttribute("aria-pressed",String(ve))}for(let le of pe){let ve=le.dataset.profileId===me;le.classList.toggle("selected",ve),le.setAttribute("aria-pressed",String(ve))}U.textContent=ie==="overwrite"?s("groups.saveProfileOverwriteSubmit"):s("groups.saveProfileSubmit"),U.disabled=!j||ie==="overwrite"&&!me,ae.textContent=be()||"-",se.textContent=ie==="overwrite"?s("groups.saveProfileTargetOverwrite"):s("groups.saveProfileTargetNew"),E.textContent="",E.className="g-save-profile-status"}ee.forEach(le=>{le.addEventListener("click",()=>{let ve=le.dataset.saveProfileMode==="overwrite"?"overwrite":"new";ve==="overwrite"&&!V||(ie=ve,Me())})}),pe.forEach(le=>{le.addEventListener("click",()=>{me=le.dataset.profileId??"",ie="overwrite",Me()})}),he.addEventListener("input",Me),Me(),i.querySelector("#g-save-profile-cancel").onclick=()=>i.close(),b.onsubmit=async le=>{if(le.preventDefault(),!j)return;let ve=be();if(!Al(ve)){E.textContent=s("groups.saveProfileInvalid"),E.className="g-save-profile-status error";return}U.disabled=!0,U.textContent=s("groups.saveProfileSaving"),E.textContent=s("groups.saveProfileSaving"),E.className="g-save-profile-status";try{let Pe=(await Promise.all(O.map(async Ge=>(await fetch(`/api/role-profiles/${encodeURIComponent(ve)}/${encodeURIComponent(Ge.larkAppId)}`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({content:Ge.content,allowEmpty:!0})})).ok))).filter(Boolean).length;if(Pe!==O.length){E.textContent=s("groups.saveProfileFailed",{saved:Pe,total:O.length}),E.className="g-save-profile-status error",U.disabled=!1,U.textContent=ie==="overwrite"?s("groups.saveProfileOverwriteSubmit"):s("groups.saveProfileSubmit");return}E.textContent=s("groups.saveProfileDone",{name:ve,count:Pe}),E.className="g-save-profile-status ok",await p(),setTimeout(()=>i.close(),700)}catch($e){E.textContent=String($e),E.className="g-save-profile-status error",U.disabled=!1,U.textContent=ie==="overwrite"?s("groups.saveProfileOverwriteSubmit"):s("groups.saveProfileSubmit")}}}n.addEventListener("click",async I=>{let N=I.target.closest("button.manage-chat");if(!N)return;let A=N.closest("tr[data-chat]").dataset.chat,R=st.chats.find(B=>B.chatId===A);R&&q(R)});function q(I){let N=I.memberBots.filter(A=>A.inChat),O=typeof I.ownerId=="string"?I.ownerId:"";i.innerHTML=`
|
|
668
|
-
<article>
|
|
669
|
-
<header><h3>${s("groups.manageTitle",{name:I.name??I.chatId})}</h3></header>
|
|
670
|
-
<p><b>chatId:</b> <code>${l(I.chatId)}</code></p>
|
|
671
|
-
<p><b>${s("groups.owner")}:</b> <code>${l(I.ownerId??s("common.unknown"))}</code></p>
|
|
672
|
-
|
|
673
|
-
<fieldset>
|
|
674
|
-
<legend>${s("groups.oncall")}</legend>
|
|
675
|
-
<p><small>${s("groups.oncallHelp")}</small></p>
|
|
676
|
-
${N.length===0?'<p class="empty">\u6CA1\u6709\u673A\u5668\u4EBA\u5728\u7FA4\u91CC</p>':N.map(A=>{let R=!!A.oncallChat,B=A.oncallChat?.workingDir??"";return`
|
|
677
|
-
<div class="oncall-row" data-bot="${l(A.larkAppId)}">
|
|
678
|
-
<label class="checkbox-row">
|
|
679
|
-
<input type="checkbox" data-action="toggle" ${R?"checked":""}>
|
|
680
|
-
<strong>${l(A.botName??A.larkAppId)}</strong>
|
|
681
|
-
<small>(${l(A.larkAppId)})</small>
|
|
682
|
-
</label>
|
|
683
|
-
<div class="oncall-row-body">
|
|
684
|
-
<input type="text" data-input="workingDir" placeholder="e.g. /root/iserver/botmux"
|
|
685
|
-
value="${l(B)}" ${R?"":"disabled"}>
|
|
686
|
-
<button type="button" data-action="save">${s("groups.save")}</button>
|
|
687
|
-
<span class="oncall-status" data-status></span>
|
|
688
|
-
</div>
|
|
689
|
-
</div>
|
|
690
|
-
`}).join("")}
|
|
691
|
-
</fieldset>
|
|
692
|
-
|
|
693
|
-
<fieldset>
|
|
694
|
-
<legend>${s("groups.leaveTitle")}</legend>
|
|
695
|
-
${N.length===0?'<p class="empty">\u6CA1\u6709\u673A\u5668\u4EBA\u5728\u7FA4\u91CC</p>':N.map(A=>`
|
|
696
|
-
<label class="checkbox-row">
|
|
697
|
-
<input type="checkbox" name="leave-bot" value="${l(A.larkAppId)}">
|
|
698
|
-
${l(A.botName??A.larkAppId)}
|
|
699
|
-
<small>${A.larkAppId===O?"\xB7 \u7FA4\u4E3B":""}</small>
|
|
700
|
-
</label>
|
|
701
|
-
`).join("")}
|
|
702
|
-
</fieldset>
|
|
703
|
-
|
|
704
|
-
<div class="actions">
|
|
705
|
-
<button id="g-leave-btn" type="button" ${N.length===0?"disabled":""}>${s("groups.leaveSelected")}</button>
|
|
706
|
-
<button id="g-disband-btn" type="button" class="contrast" ${N.length===0?"disabled":""}>${s("groups.disband")}</button>
|
|
707
|
-
</div>
|
|
708
|
-
<p class="hint-warn"><small>${s("groups.dangerHint")}</small></p>
|
|
709
|
-
<form method="dialog"><button>${s("sessions.dismiss")}</button></form>
|
|
710
|
-
</article>`,i.showModal(),i.querySelectorAll(".oncall-row").forEach(A=>{let R=A.dataset.bot,B=A.querySelector("input[data-action=toggle]"),V=A.querySelector("input[data-input=workingDir]"),Z=A.querySelector("button[data-action=save]"),G=A.querySelector("[data-status]");B.addEventListener("change",()=>{V.disabled=!B.checked,B.checked&&V.focus()}),Z.addEventListener("click",async()=>{G.textContent="",G.className="oncall-status";let j=B.checked,z=V.value.trim();if(j&&!z){G.textContent=s("groups.needWorkingDir"),G.classList.add("hint-warn-inline");return}Z.disabled=!0;try{let b=`/api/groups/${encodeURIComponent(I.chatId)}/oncall/${encodeURIComponent(R)}`,S=j?await fetch(b,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({workingDir:z})}):await fetch(b,{method:"DELETE"}),E=await S.json().catch(()=>({}));if(S.ok&&E.ok){G.textContent=j?`\u2713 \u5DF2\u7ED1\u5B9A \u2192 ${E.resolvedPath??z}`:"\u2713 \u5DF2\u89E3\u7ED1",G.classList.add("hint-ok");try{await Xn(),L(),p()}catch{}}else G.textContent=`\u2717 ${E.error??S.status}`,G.classList.add("hint-warn-inline")}catch(b){G.textContent=`\u2717 ${b?.message??b}`,G.classList.add("hint-warn-inline")}finally{Z.disabled=!1}})}),i.querySelector("#g-leave-btn").onclick=async()=>{let A=[...i.querySelectorAll("input[name=leave-bot]:checked")].map(R=>R.value);if(A.length===0){alert("\u81F3\u5C11\u9009\u4E00\u4E2A\u673A\u5668\u4EBA");return}if(confirm(`\u786E\u5B9A\u8BA9 ${A.length} \u4E2A\u673A\u5668\u4EBA\u9000\u51FA\u7FA4\u804A\uFF1F\u8BE5 bot \u5728\u6B64\u7FA4\u7684\u4F1A\u8BDD\u4F1A\u4E00\u5E76\u5173\u95ED\u3002`))try{let B=await(await fetch(`/api/groups/${encodeURIComponent(I.chatId)}/leave`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({larkAppIds:A})})).json(),V=(B.result??[]).map(Z=>{if(!Z.ok)return`${Z.larkAppId}: \u5931\u8D25 (${Z.error??"unknown"})`;let G=Z.closedSessions??[],j=G.filter(S=>!S.ok).length,z=G.length-j,b=G.length===0?"":j===0?`\uFF08\u5173\u95ED ${z} \u4E2A\u4F1A\u8BDD\uFF09`:`\uFF08\u5173\u95ED ${z} \u4E2A\uFF0C${j} \u4E2A\u5931\u8D25\uFF09`;return`${Z.larkAppId}: OK${b}`}).join(`
|
|
711
|
-
`);alert(V||`Unexpected: ${JSON.stringify(B)}`),await Xn(),L(),p()}catch(R){alert("Network error: "+R)}finally{i.close()}},i.querySelector("#g-disband-btn").onclick=async()=>{if(N.length===0||!confirm(`\u786E\u5B9A\u89E3\u6563\u7FA4\u804A\u300C${I.name??I.chatId}\u300D\uFF1F\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\uFF0C\u672C\u7FA4\u6240\u6709\u673A\u5668\u4EBA\u4F1A\u8BDD\u4E5F\u4F1A\u4E00\u5E76\u5173\u95ED\u3002`))return;let A=[...N].sort((B,V)=>(V.larkAppId===O?1:0)-(B.larkAppId===O?1:0)),R=[];for(let B of A)try{let V=await fetch(`/api/groups/${encodeURIComponent(I.chatId)}/disband`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({larkAppId:B.larkAppId})}),Z=await V.json();if(Z.ok){let G=Z.closedSessions??[],j=G.filter(S=>!S.ok).length,z=G.length-j,b=G.length===0?"":j===0?`
|
|
712
|
-
\u5173\u95ED\u4E86 ${z} \u4E2A\u4F1A\u8BDD\u3002`:`
|
|
713
|
-
\u5173\u95ED\u4E86 ${z} \u4E2A\u4F1A\u8BDD\uFF0C${j} \u4E2A\u4F1A\u8BDD\u5173\u95ED\u5931\u8D25\u3002`;alert(`\u5DF2\u89E3\u6563\uFF08\u7531 ${B.botName??B.larkAppId} \u6267\u884C\uFF09${b}`),await Xn(),L(),p(),i.close();return}R.push(`${B.botName??B.larkAppId}: ${Z.error??V.status}`)}catch(V){R.push(`${B.botName??B.larkAppId}: ${V}`)}alert(`\u6240\u6709\u5728\u7FA4\u673A\u5668\u4EBA\u5747\u65E0\u6CD5\u89E3\u6563\uFF1A
|
|
714
|
-
${R.join(`
|
|
715
|
-
`)}
|
|
716
|
-
|
|
717
|
-
\u5EFA\u8BAE\u6539\u7528\u300C\u9000\u51FA\u7FA4\u804A\u300D\u3002`)}}a.addEventListener("input",L)}var We={bots:[]},ns=null,Pa=[{id:"claude-code",label:"Claude"},{id:"codex",label:"Codex"},{id:"traex",label:"traex"}],Hl=!1,bo="glm-5.1",Ba=[],es=null;function Ra(e,t){return typeof e?.cliId=="string"&&e.cliId?e.cliId:t}var ts=new Map;function _l(e){let t=null;for(let n of ke.sessions.values())n.larkAppId!==e||!n.cliId||(!t||Number(n.lastMessageAt??0)>Number(t.lastMessageAt??0))&&(t=n);return t?.cliId??""}async function Rl(){if(!Hl){Hl=!0;try{let e=await fetch("/api/cli-options"),t=await e.json().catch(()=>({}));e.ok&&Array.isArray(t?.options)&&(Pa=t.options.filter(n=>n&&typeof n.id=="string"&&typeof n.label=="string"),typeof t.ttadkModelDefault=="string"&&t.ttadkModelDefault.trim()&&(bo=t.ttadkModelDefault.trim()),Array.isArray(t.ttadkModelSuggestions)&&(Ba=t.ttadkModelSuggestions.filter(n=>typeof n=="string")))}catch{}}}function Rp(e,t){let n=typeof e?.agentSelectionKey=="string"&&e.agentSelectionKey?e.agentSelectionKey:"";return n||Ra(e,t)||"claude-code"}function yo(e){return Pa.find(t=>t.id===e)}function Pp(e){return e?.gateway==="ttadk"&&e.acceptsModel!==!1?Ba:[]}function Bp(e,t){let n=Rp(e,t),a=Pa.map(u=>`<option value="${l(u.id)}" ${u.id===n?"selected":""}>${l(u.label)}\uFF08${l(u.id)}\uFF09</option>`).join(""),o=typeof e?.model=="string"?e.model:"",i=Pp(yo(n)),r=yo(n)?.gateway==="ttadk"&&yo(n)?.acceptsModel===!1;return`<section class="bd-section">
|
|
718
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionAgent")}</h3>
|
|
719
|
-
<div class="bd-row">
|
|
720
|
-
<label>
|
|
721
|
-
<span>${s("botDefaults.agentCli")}</span>
|
|
722
|
-
<select data-input="agentCliId">${a}</select>
|
|
723
|
-
</label>
|
|
724
|
-
</div>
|
|
725
|
-
<div class="bd-row">
|
|
726
|
-
<label>
|
|
727
|
-
<span>${s("botDefaults.agentModel")}</span>
|
|
728
|
-
<input type="text" data-input="agentModel" list="agent-model-suggestions-${l(e.larkAppId)}"
|
|
729
|
-
placeholder="${l(s("botDefaults.agentModelPlaceholder"))}"
|
|
730
|
-
value="${l(o)}" ${r?"disabled":""}>
|
|
731
|
-
<datalist id="agent-model-suggestions-${l(e.larkAppId)}">
|
|
732
|
-
${i.map(u=>`<option value="${l(u)}"></option>`).join("")}
|
|
733
|
-
</datalist>
|
|
734
|
-
</label>
|
|
735
|
-
<small class="bd-help">${s("botDefaults.agentHelp")}</small>
|
|
736
|
-
<div class="actions">
|
|
737
|
-
<button type="button" class="primary" data-action="save-agent">${s("botDefaults.agentSave")}</button>
|
|
738
|
-
<span class="oncall-status" data-agent-status></span>
|
|
739
|
-
</div>
|
|
740
|
-
</div>
|
|
741
|
-
</section>`}function Op(){return`<section class="page">
|
|
742
|
-
<div class="page-heading">
|
|
743
|
-
<div>
|
|
744
|
-
<p class="eyebrow">${s("nav.botDefaults")}</p>
|
|
745
|
-
<h1>${s("botDefaults.title")}</h1>
|
|
746
|
-
<p>${s("botDefaults.subtitle")}</p>
|
|
747
|
-
</div>
|
|
748
|
-
</div>
|
|
749
|
-
<form id="bd-filters" class="filters sessions-filters">
|
|
750
|
-
<input type="search" name="q" placeholder="${s("botDefaults.search")}" />
|
|
751
|
-
<button type="button" id="bd-refresh">${s("botDefaults.refresh")}</button>
|
|
752
|
-
</form>
|
|
753
|
-
<div class="bd-layout">
|
|
754
|
-
<aside id="bd-roster" class="bd-roster"></aside>
|
|
755
|
-
<div id="bd-list" class="bd-detail"></div>
|
|
756
|
-
</div>
|
|
757
|
-
</section>`}async function Pl(){try{let e=await fetch("/api/bots"),t=await e.json().catch(()=>({}));if(!e.ok){ns=t?.error?`HTTP ${e.status}: ${t.error}${t.path?` (${t.path})`:""}`:`HTTP ${e.status}`,We={bots:[]};return}if(!t||!Array.isArray(t.bots)){ns="unexpected response shape (no `bots` array)",We={bots:[]};return}ns=null,We=t}catch(e){ns=e?.message??String(e),We={bots:[]}}}function Bl(e){if(!e)return"\u2014";let t=new Date(e);return Number.isNaN(t.getTime())?"\u2014":t.toLocaleString()}async function Ol(e){e.innerHTML=Op();let t=e.querySelector("#bd-list"),n=e.querySelector("#bd-roster"),a=e.querySelector("#bd-filters"),o=e.querySelector("#bd-refresh");o.onclick=async()=>{o.disabled=!0;try{ts.clear(),await Promise.all([Pl(),Rl()]),i()}finally{o.disabled=!1}},t.addEventListener("click",b=>{let S=b.target.closest(".toggle-tx small, small.bd-help");S&&(b.preventDefault(),S.classList.toggle("open"))}),t.innerHTML=Tt(),await Promise.all([Pl(),Rl()]);function i(){let S=(new FormData(a).get("q")??"").toLowerCase(),E=We.bots.filter(ee=>!S||(ee.botName??"").toLowerCase().includes(S)||(ee.larkAppId??"").toLowerCase().includes(S));if(ns){n.innerHTML="",t.innerHTML=`<p class="hint-warn">\u65E0\u6CD5\u52A0\u8F7D bot \u5217\u8868\uFF1A${l(ns)}<br>\u5E38\u89C1\u539F\u56E0\uFF1Adashboard / daemon \u8FDB\u7A0B\u8FD8\u5728\u8DD1\u65E7\u4EE3\u7801\uFF0C\u6267\u884C <code>botmux restart</code> \u540E\u5237\u65B0\u3002</p>`;return}if(E.length===0){n.innerHTML="",t.innerHTML=`<p class="empty">${s("botDefaults.empty")}</p>`;return}(!es||!E.some(ee=>ee.larkAppId===es))&&(es=E[0].larkAppId),n.innerHTML=E.map(r).join(""),n.querySelectorAll(".bd-roster-item").forEach(ee=>{ee.onclick=()=>{es=ee.dataset.appid,i()}});let U=E.find(ee=>ee.larkAppId===es);t.innerHTML=u(U),z()}function r(b){let S=b.botName??b.larkAppId,E=Ra(b,_l(b.larkAppId)),U=b.defaultOncall?.enabled?'<span class="bd-roster-flag">oncall</span>':"";return`<div class="bd-roster-item${b.larkAppId===es?" on":""}" data-appid="${l(b.larkAppId)}" role="button" tabindex="0">
|
|
758
|
-
${Re({name:S,larkAppId:b.larkAppId,size:"sm"})}
|
|
759
|
-
<div class="bd-roster-tx">
|
|
760
|
-
<b>${l(S)}</b>
|
|
761
|
-
<span>${l(E||b.larkAppId.slice(0,14))}</span>
|
|
762
|
-
</div>
|
|
763
|
-
${U}
|
|
764
|
-
</div>`}function u(b){if(b.error)return`<article class="bd-card bd-profile" data-appid="${l(b.larkAppId)}">
|
|
765
|
-
<header class="bd-profile-head">
|
|
766
|
-
${Re({name:b.botName??b.larkAppId,larkAppId:b.larkAppId})}
|
|
767
|
-
<div class="bd-profile-id"><strong>${l(b.botName??b.larkAppId)}</strong>
|
|
768
|
-
<code>${l(b.larkAppId)}</code></div>
|
|
769
|
-
</header>
|
|
770
|
-
<p class="hint-warn-inline">\u67E5\u8BE2\u5931\u8D25\uFF1A${l(b.error)}</p>
|
|
771
|
-
</article>`;let S=b.defaultOncall??{enabled:!1,workingDir:"",since:0},E=S.enabled?"oncall":b.defaultWorkingDir?"default":"off",U=b.defaultWorkingDir||S.workingDir||"",ee=b.botName??b.larkAppId,pe=Ra(b,_l(b.larkAppId));return`<article class="bd-card bd-profile" data-appid="${l(b.larkAppId)}">
|
|
772
|
-
<header class="bd-profile-head">
|
|
773
|
-
${Re({name:ee,larkAppId:b.larkAppId,dot:"ok"})}
|
|
774
|
-
<div class="bd-profile-id">
|
|
775
|
-
<strong>${l(ee)}</strong>
|
|
776
|
-
${pe?`<span class="mate-role">${l(pe)}</span>`:""}
|
|
777
|
-
<code>${l(b.larkAppId)}</code>
|
|
778
|
-
</div>
|
|
779
|
-
<div class="bd-profile-meta bd-meta">
|
|
780
|
-
<small class="bd-meta-ok">\u25CF ${s("botDefaults.metaOnline")}</small>
|
|
781
|
-
<small data-oncall-since>${s("botDefaults.lastEnabled")}: ${l(Bl(S.since??0))}</small>
|
|
782
|
-
<small>${s("botDefaults.autobound",{count:b.autoboundChatCount??0})}</small>
|
|
783
|
-
</div>
|
|
784
|
-
</header>
|
|
785
|
-
<div class="bd-body bd-grid">
|
|
786
|
-
<section class="bd-tile">
|
|
787
|
-
${Bp(b,pe)}
|
|
788
|
-
<section class="bd-section">
|
|
789
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionWorkingDir")}</h3>
|
|
790
|
-
<div class="bd-row">
|
|
791
|
-
<label>
|
|
792
|
-
<span>${s("botDefaults.workingDirMode")}</span>
|
|
793
|
-
<select data-input="workingDirMode">
|
|
794
|
-
<option value="off" ${E==="off"?"selected":""}>${l(s("botDefaults.workingDirModeOff"))}</option>
|
|
795
|
-
<option value="default" ${E==="default"?"selected":""}>${l(s("botDefaults.workingDirModeDefault"))}</option>
|
|
796
|
-
<option value="oncall" ${E==="oncall"?"selected":""}>${l(s("botDefaults.workingDirModeOncall"))}</option>
|
|
797
|
-
</select>
|
|
798
|
-
</label>
|
|
799
|
-
<small class="bd-help">${s("botDefaults.workingDirModeHelp")}</small>
|
|
800
|
-
</div>
|
|
801
|
-
<div class="bd-row" data-wd-dir-row ${E==="off"?"hidden":""}>
|
|
802
|
-
<label>
|
|
803
|
-
<span>${s("botDefaults.workingDirField")}</span>
|
|
804
|
-
<input type="text" data-input="workingDir" placeholder="e.g. /root/iserver/botmux"
|
|
805
|
-
value="${l(U)}">
|
|
806
|
-
</label>
|
|
807
|
-
</div>
|
|
808
|
-
<div class="actions">
|
|
809
|
-
<button type="button" class="primary" data-action="save-working-dir">${s("botDefaults.save")}</button>
|
|
810
|
-
<span class="oncall-status" data-status></span>
|
|
811
|
-
</div>
|
|
812
|
-
${A(b)}
|
|
813
|
-
</section>
|
|
814
|
-
${I(b)}
|
|
815
|
-
</section>
|
|
816
|
-
<section class="bd-tile">${c(b)}</section>
|
|
817
|
-
<section class="bd-tile">${$(b)}${v(b)}${C(b)}${P(b)}${H(b)}${q(b)}</section>
|
|
818
|
-
<section class="bd-tile">${g(b)}${M(b)}${y(b)}</section>
|
|
819
|
-
<section class="bd-tile">${O(b)}</section>
|
|
820
|
-
</div>
|
|
821
|
-
</article>`}function c(b){let S=typeof b.teamRole=="string";return`<section class="bd-section">
|
|
822
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionRole")}</h3>
|
|
823
|
-
<p class="bd-section-note">${s("botDefaults.roleHelp")}</p>
|
|
824
|
-
<textarea data-input="teamRole" rows="6"
|
|
825
|
-
placeholder="${l(s("botDefaults.rolePlaceholder"))}"
|
|
826
|
-
style="width:100%;box-sizing:border-box;font:13px/1.5 ui-monospace,Menlo,monospace;padding:10px"${S?"":" disabled"}>${S?l(b.teamRole):""}</textarea>
|
|
827
|
-
<div class="actions">
|
|
828
|
-
<button type="button" class="primary" data-action="save-role"${S?"":" disabled"}>${s("botDefaults.roleSave")}</button>
|
|
829
|
-
<button type="button" data-action="delete-role"${S?"":" disabled"}>${s("botDefaults.roleDelete")}</button>
|
|
830
|
-
<span class="oncall-status" data-role-status></span>
|
|
831
|
-
</div>
|
|
832
|
-
<div class="bd-profile-roles" data-profile-roles>
|
|
833
|
-
<h4 class="bd-subsection-title">${s("botDefaults.profileRoles")}</h4>
|
|
834
|
-
<p class="bd-section-note">${s("botDefaults.profileRolesHelp")}</p>
|
|
835
|
-
<div class="bd-profile-role-list" data-profile-role-list>${p(b.larkAppId)}</div>
|
|
836
|
-
</div>
|
|
837
|
-
</section>`}function p(b){let S=ts.get(b);return!S||S.loading?Tt():S.error?`<p class="hint-warn-inline">${l(s("botDefaults.profileRolesLoadFailed",{error:S.error}))}</p>`:S.items.length===0?`<p class="empty">${s("botDefaults.profileRolesEmpty")}</p>`:S.items.map(E=>`
|
|
838
|
-
<details class="bd-profile-role-entry" data-profile-id="${l(E.profileId)}">
|
|
839
|
-
<summary><code>${l(E.profileId)}</code></summary>
|
|
840
|
-
<div class="bd-profile-role-content" data-profile-role-body="${l(E.profileId)}">
|
|
841
|
-
${f(E)}
|
|
842
|
-
</div>
|
|
843
|
-
</details>
|
|
844
|
-
`).join("")}function f(b){return b.loading?Tt():b.error?`<p class="hint-warn-inline">${l(s("botDefaults.profileRoleDetailLoadFailed",{error:b.error}))}</p>`:b.loaded?`<pre>${l(b.content??"")}</pre>`:`<p class="empty">${s("botDefaults.profileRoleClickToLoad")}</p>`}function h(b){return b==null?s("botDefaults.brandStateDefault"):b.trim()===""?s("botDefaults.brandStateOff"):s("botDefaults.brandStateCustom")}function y(b){let S=b.brandLabel??null;return`<section class="bd-section">
|
|
845
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionBrand")}</h3>
|
|
846
|
-
<div class="bd-row bd-brand">
|
|
847
|
-
<label>
|
|
848
|
-
<span>${s("botDefaults.brandLabel")}</span>
|
|
849
|
-
<input type="text" data-input="brandLabel"
|
|
850
|
-
placeholder="${l(s("botDefaults.brandLabelPlaceholder"))}"
|
|
851
|
-
value="${l(S??"")}">
|
|
852
|
-
</label>
|
|
853
|
-
<small data-brand-state>${l(h(S))}</small>
|
|
854
|
-
<small class="bd-help">${s("botDefaults.brandLabelHelp")}</small>
|
|
855
|
-
<div class="actions">
|
|
856
|
-
<button type="button" class="primary" data-action="save-brand">${s("botDefaults.brandSave")}</button>
|
|
857
|
-
<button type="button" data-action="reset-brand">${s("botDefaults.brandReset")}</button>
|
|
858
|
-
<span class="oncall-status" data-brand-status></span>
|
|
859
|
-
</div>
|
|
860
|
-
</div>
|
|
861
|
-
</section>`}function g(b){let S=b.disableStreamingCard===!0,E=b.silentTurnReactions===!0,U=b.writableTerminalLinkInCard===!0,ee=b.privateCard===!0;return`<section class="bd-section">
|
|
862
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionCard")}</h3>
|
|
863
|
-
<label class="toggle-row">
|
|
864
|
-
<input type="checkbox" data-action="toggle-disable-streaming" ${S?"checked":""}>
|
|
865
|
-
<span class="switch" aria-hidden="true"></span>
|
|
866
|
-
<span class="toggle-tx"><strong>${s("botDefaults.disableStreaming")}</strong>
|
|
867
|
-
<small>${s("botDefaults.disableStreamingHelp")}</small></span>
|
|
868
|
-
</label>
|
|
869
|
-
<label class="toggle-row">
|
|
870
|
-
<input type="checkbox" data-action="toggle-silent-reactions" ${E?"checked":""} ${S?"":"disabled"}>
|
|
871
|
-
<span class="switch" aria-hidden="true"></span>
|
|
872
|
-
<span class="toggle-tx"><strong>${s("botDefaults.silentTurnReactions")}</strong>
|
|
873
|
-
<small>${s("botDefaults.silentTurnReactionsHelp")}</small></span>
|
|
874
|
-
</label>
|
|
875
|
-
<label class="toggle-row">
|
|
876
|
-
<input type="checkbox" data-action="toggle-writable-link" ${U?"checked":""} ${S?"disabled":""}>
|
|
877
|
-
<span class="switch" aria-hidden="true"></span>
|
|
878
|
-
<span class="toggle-tx"><strong>${s("botDefaults.writableLink")}</strong>
|
|
879
|
-
<small>${s("botDefaults.writableLinkHelp")}</small></span>
|
|
880
|
-
</label>
|
|
881
|
-
<label class="toggle-row">
|
|
882
|
-
<input type="checkbox" data-action="toggle-private-card" ${ee?"checked":""}>
|
|
883
|
-
<span class="switch" aria-hidden="true"></span>
|
|
884
|
-
<span class="toggle-tx"><strong>${s("botDefaults.privateCard")}</strong>
|
|
885
|
-
<small>${s("botDefaults.privateCardHelp")}</small></span>
|
|
886
|
-
</label>
|
|
887
|
-
<div class="actions">
|
|
888
|
-
<small data-card-pref-moot class="hint-warn-inline" ${S?"":"hidden"}>${s("botDefaults.writableLinkMoot")}</small>
|
|
889
|
-
<span class="oncall-status" data-card-pref-status></span>
|
|
890
|
-
</div>
|
|
891
|
-
</section>`}function v(b){let S=b.botToBotSameDir!==!1;return`<section class="bd-section">
|
|
892
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionCrossBot")}</h3>
|
|
893
|
-
<label class="toggle-row">
|
|
894
|
-
<input type="checkbox" data-action="toggle-cross-bot-samedir" ${S?"checked":""}>
|
|
895
|
-
<span class="switch" aria-hidden="true"></span>
|
|
896
|
-
<span class="toggle-tx"><strong>${s("botDefaults.botToBotSameDir")}</strong>
|
|
897
|
-
<small>${s("botDefaults.botToBotSameDirHelp")}</small></span>
|
|
898
|
-
</label>
|
|
899
|
-
<div class="actions"><span class="oncall-status" data-crossbot-status></span></div>
|
|
900
|
-
</section>`}function M(b){let S=b.summaryRange??{limit:50,sinceHours:24},E=Number.isInteger(S.limit)&&S.limit>=0?S.limit:50,U=Number.isInteger(S.sinceHours)&&S.sinceHours>=0?S.sinceHours:24;return`<section class="bd-section">
|
|
901
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionSummaryTrigger")}</h3>
|
|
902
|
-
<div class="bd-row bd-summary-limits">
|
|
903
|
-
<label>
|
|
904
|
-
<span>${s("botDefaults.summaryLimit")}</span>
|
|
905
|
-
<input type="number" min="0" step="1" data-input="summaryLimit" value="${E}">
|
|
906
|
-
</label>
|
|
907
|
-
<label>
|
|
908
|
-
<span>${s("botDefaults.summarySinceHours")}</span>
|
|
909
|
-
<input type="number" min="0" step="1" data-input="summarySinceHours" value="${U}">
|
|
910
|
-
</label>
|
|
911
|
-
</div>
|
|
912
|
-
<small class="bd-help">${s("botDefaults.summaryLimitHelp")}</small>
|
|
913
|
-
<div class="actions">
|
|
914
|
-
<button type="button" class="primary" data-action="save-summary-trigger">${s("botDefaults.summarySave")}</button>
|
|
915
|
-
<span class="oncall-status" data-summary-trigger-status></span>
|
|
916
|
-
</div>
|
|
917
|
-
</section>`}function $(b){let S=b.p2pMode==="chat"?"chat":"thread",E=b.regularGroupReplyMode==="new-topic"||b.regularGroupReplyMode==="shared"||b.regularGroupReplyMode==="chat-topic"?b.regularGroupReplyMode:"chat",U=b.regularGroupMentionMode==="topic"||b.regularGroupMentionMode==="never"||b.regularGroupMentionMode==="ambient"?b.regularGroupMentionMode:"always",ee=b.docSubscribeDefaultMode==="all"?"all":"mention-only",pe=(se,ie)=>`<option value="${se}" ${E===se?"selected":""}>${l(ie)}</option>`,he=(se,ie)=>`<option value="${se}" ${U===se?"selected":""}>${l(ie)}</option>`,ae=(se,ie)=>`<option value="${se}" ${ee===se?"selected":""}>${l(ie)}</option>`;return`<section class="bd-section">
|
|
918
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionSessionMode")}</h3>
|
|
919
|
-
<div class="bd-row">
|
|
920
|
-
<label>
|
|
921
|
-
<span>${s("botDefaults.p2pMode")}</span>
|
|
922
|
-
<select data-input="p2pMode">
|
|
923
|
-
<option value="thread" ${S==="chat"?"":"selected"}>${l(s("botDefaults.p2pThread"))}</option>
|
|
924
|
-
<option value="chat" ${S==="chat"?"selected":""}>${l(s("botDefaults.p2pChat"))}</option>
|
|
925
|
-
</select>
|
|
926
|
-
</label>
|
|
927
|
-
<small class="bd-help">${s("botDefaults.p2pHelp")}</small>
|
|
928
|
-
<div class="actions">
|
|
929
|
-
<span class="oncall-status" data-p2p-status></span>
|
|
930
|
-
</div>
|
|
931
|
-
</div>
|
|
932
|
-
<div class="bd-row">
|
|
933
|
-
<label>
|
|
934
|
-
<span>${s("botDefaults.regularGroupMode")}</span>
|
|
935
|
-
<select data-input="regularGroupMode">
|
|
936
|
-
${pe("chat",s("botDefaults.regularGroupModeChat"))}
|
|
937
|
-
${pe("chat-topic",s("botDefaults.regularGroupModeChatTopic"))}
|
|
938
|
-
${pe("new-topic",s("botDefaults.regularGroupModeNewTopic"))}
|
|
939
|
-
${pe("shared",s("botDefaults.regularGroupModeShared"))}
|
|
940
|
-
</select>
|
|
941
|
-
</label>
|
|
942
|
-
<small class="bd-help">${s("botDefaults.regularGroupModeHelp")}</small>
|
|
943
|
-
<div class="actions">
|
|
944
|
-
<span class="oncall-status" data-regular-group-status></span>
|
|
945
|
-
</div>
|
|
946
|
-
</div>
|
|
947
|
-
<div class="bd-row">
|
|
948
|
-
<label>
|
|
949
|
-
<span>${s("botDefaults.mentionMode")}</span>
|
|
950
|
-
<select data-input="regularGroupMentionMode">
|
|
951
|
-
${he("always",s("botDefaults.mentionModeAlways"))}
|
|
952
|
-
${he("topic",s("botDefaults.mentionModeTopic"))}
|
|
953
|
-
${he("never",s("botDefaults.mentionModeNever"))}
|
|
954
|
-
${he("ambient",s("botDefaults.mentionModeAmbient"))}
|
|
955
|
-
</select>
|
|
956
|
-
</label>
|
|
957
|
-
<small class="bd-help">${s("botDefaults.mentionModeHelp")}</small>
|
|
958
|
-
<div class="actions">
|
|
959
|
-
<span class="oncall-status" data-mention-mode-status></span>
|
|
960
|
-
</div>
|
|
961
|
-
</div>
|
|
962
|
-
<div class="bd-row">
|
|
963
|
-
<label>
|
|
964
|
-
<span>${s("botDefaults.docSubscribeMode")}</span>
|
|
965
|
-
<select data-input="docSubscribeDefaultMode">
|
|
966
|
-
${ae("mention-only",s("botDefaults.docSubscribeModeMention"))}
|
|
967
|
-
${ae("all",s("botDefaults.docSubscribeModeAll"))}
|
|
968
|
-
</select>
|
|
969
|
-
</label>
|
|
970
|
-
<small class="bd-help">${s("botDefaults.docSubscribeModeHelp")}</small>
|
|
971
|
-
<div class="actions">
|
|
972
|
-
<span class="oncall-status" data-doc-subscribe-mode-status></span>
|
|
973
|
-
</div>
|
|
974
|
-
</div>
|
|
975
|
-
</section>`}function L(b){return b==null?s("botDefaults.maxLiveWorkersStateDefault"):s("botDefaults.maxLiveWorkersStateOn",{count:b})}function C(b){let S=typeof b.maxLiveWorkers=="number"?b.maxLiveWorkers:null;return`<div class="bd-subsection">
|
|
976
|
-
<h4 class="bd-subsection-title">${s("botDefaults.sectionSessionCap")}</h4>
|
|
977
|
-
<div class="bd-row bd-quota">
|
|
978
|
-
<label>
|
|
979
|
-
<span>${s("botDefaults.maxLiveWorkers")}</span>
|
|
980
|
-
<input type="number" min="1" step="1" data-input="maxLiveWorkers"
|
|
981
|
-
placeholder="${l(s("botDefaults.maxLiveWorkersPlaceholder"))}"
|
|
982
|
-
value="${S??""}">
|
|
983
|
-
</label>
|
|
984
|
-
<small data-session-cap-state>${l(L(S))}</small>
|
|
985
|
-
<small class="bd-help">${s("botDefaults.maxLiveWorkersHelp")}</small>
|
|
986
|
-
<div class="actions">
|
|
987
|
-
<button type="button" class="primary" data-action="save-session-cap">${s("botDefaults.maxLiveWorkersSave")}</button>
|
|
988
|
-
<button type="button" data-action="off-session-cap">${s("botDefaults.maxLiveWorkersOff")}</button>
|
|
989
|
-
<span class="oncall-status" data-session-cap-status></span>
|
|
990
|
-
</div>
|
|
991
|
-
</div>
|
|
992
|
-
</div>`}function P(b){let S=typeof b.startupCommands=="string"?b.startupCommands:"";return`<div class="bd-subsection">
|
|
993
|
-
<h4 class="bd-subsection-title">${s("botDefaults.sectionStartupCommands")}</h4>
|
|
994
|
-
<p class="bd-section-note">${s("botDefaults.startupCommandsHelp")}</p>
|
|
995
|
-
<textarea data-input="startupCommands" rows="3"
|
|
996
|
-
placeholder="${l(s("botDefaults.startupCommandsPlaceholder"))}"
|
|
997
|
-
style="width:100%;box-sizing:border-box;font:13px/1.5 ui-monospace,Menlo,monospace;padding:10px">${l(S)}</textarea>
|
|
998
|
-
<div class="actions">
|
|
999
|
-
<button type="button" class="primary" data-action="save-startup-commands">${s("botDefaults.startupCommandsSave")}</button>
|
|
1000
|
-
<span class="oncall-status" data-startup-commands-status></span>
|
|
1001
|
-
</div>
|
|
1002
|
-
</div>`}function H(b){let S=typeof b.launchShell=="string"?b.launchShell:"";return`<div class="bd-subsection">
|
|
1003
|
-
<h4 class="bd-subsection-title">${s("botDefaults.sectionLaunchShell")}</h4>
|
|
1004
|
-
<p class="bd-section-note">${s("botDefaults.launchShellHelp")}</p>
|
|
1005
|
-
<input type="text" data-input="launchShell"
|
|
1006
|
-
placeholder="${l(s("botDefaults.launchShellPlaceholder"))}"
|
|
1007
|
-
value="${l(S)}"
|
|
1008
|
-
style="width:100%;box-sizing:border-box;font:13px/1.5 ui-monospace,Menlo,monospace;padding:10px">
|
|
1009
|
-
<div class="actions">
|
|
1010
|
-
<button type="button" class="primary" data-action="save-launch-shell">${s("botDefaults.launchShellSave")}</button>
|
|
1011
|
-
<span class="oncall-status" data-launch-shell-status></span>
|
|
1012
|
-
</div>
|
|
1013
|
-
</div>`}function q(b){let S=typeof b.env=="string"?b.env:"";return`<div class="bd-subsection">
|
|
1014
|
-
<h4 class="bd-subsection-title">${s("botDefaults.sectionEnv")}</h4>
|
|
1015
|
-
<p class="bd-section-note">${s("botDefaults.envHelp")}</p>
|
|
1016
|
-
<textarea data-input="env" rows="5"
|
|
1017
|
-
placeholder="${l(s("botDefaults.envPlaceholder"))}"
|
|
1018
|
-
style="width:100%;box-sizing:border-box;font:13px/1.5 ui-monospace,Menlo,monospace;padding:10px">${l(S)}</textarea>
|
|
1019
|
-
<div class="actions">
|
|
1020
|
-
<button type="button" class="primary" data-action="save-env">${s("botDefaults.envSave")}</button>
|
|
1021
|
-
<span class="oncall-status" data-env-status></span>
|
|
1022
|
-
</div>
|
|
1023
|
-
</div>`}function I(b){let S=b.sandbox===!0;return`<section class="bd-section">
|
|
1024
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionSandbox")}</h3>
|
|
1025
|
-
<label class="toggle-row">
|
|
1026
|
-
<input type="checkbox" data-action="toggle-sandbox" ${S?"checked":""}>
|
|
1027
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1028
|
-
<span class="toggle-tx"><strong>${s("botDefaults.sandboxToggle")}</strong>
|
|
1029
|
-
<small>${s("botDefaults.sandboxHelp")}</small></span>
|
|
1030
|
-
</label>
|
|
1031
|
-
<div class="actions">
|
|
1032
|
-
<span class="oncall-status" data-sandbox-status></span>
|
|
1033
|
-
</div>
|
|
1034
|
-
</section>`}function N(b){return b==null?s("botDefaults.quotaStateOff"):s("botDefaults.quotaStateOn",{count:b})}function O(b){let S=b.restrictGrantCommands===!0,E=b.autoGrantRequestCards!==!1,U=typeof b.messageQuotaDefaultLimit=="number"?b.messageQuotaDefaultLimit:null;return`<section class="bd-section">
|
|
1035
|
-
<h3 class="bd-section-title">${s("botDefaults.sectionGrant")}</h3>
|
|
1036
|
-
<label class="toggle-row">
|
|
1037
|
-
<input type="checkbox" data-action="toggle-auto-grant-card" ${E?"checked":""}>
|
|
1038
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1039
|
-
<span class="toggle-tx"><strong>${s("botDefaults.autoGrantCard")}</strong>
|
|
1040
|
-
<small>${s("botDefaults.autoGrantCardHelp")}</small></span>
|
|
1041
|
-
</label>
|
|
1042
|
-
<label class="toggle-row">
|
|
1043
|
-
<input type="checkbox" data-action="toggle-restrict-grant" ${S?"checked":""}>
|
|
1044
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1045
|
-
<span class="toggle-tx"><strong>${s("botDefaults.restrictGrant")}</strong>
|
|
1046
|
-
<small>${s("botDefaults.restrictGrantHelp")}</small></span>
|
|
1047
|
-
</label>
|
|
1048
|
-
<div class="bd-row bd-quota">
|
|
1049
|
-
<label>
|
|
1050
|
-
<span>${s("botDefaults.quotaDefault")}</span>
|
|
1051
|
-
<input type="number" min="1" step="1" data-input="quotaLimit"
|
|
1052
|
-
placeholder="${l(s("botDefaults.quotaPlaceholder"))}"
|
|
1053
|
-
value="${U??""}">
|
|
1054
|
-
</label>
|
|
1055
|
-
<small data-quota-state>${l(N(U))}</small>
|
|
1056
|
-
<small class="bd-help">${s("botDefaults.quotaHelp")}</small>
|
|
1057
|
-
<div class="actions">
|
|
1058
|
-
<button type="button" class="primary" data-action="save-quota">${s("botDefaults.quotaSave")}</button>
|
|
1059
|
-
<button type="button" data-action="off-quota">${s("botDefaults.quotaOff")}</button>
|
|
1060
|
-
<span class="oncall-status" data-grant-status></span>
|
|
1061
|
-
</div>
|
|
1062
|
-
</div>
|
|
1063
|
-
</section>`}function A(b){let S=b.autoStartOnGroupJoin===!0,E=b.autoStartOnNewTopic===!0,U=typeof b.autoStartOnGroupJoinPrompt=="string"?b.autoStartOnGroupJoinPrompt:"";return`<div class="bd-subsection">
|
|
1064
|
-
<h4 class="bd-subsection-title">${s("botDefaults.sectionAutoStart")}</h4>
|
|
1065
|
-
<label class="toggle-row">
|
|
1066
|
-
<input type="checkbox" data-action="toggle-auto-join" ${S?"checked":""}>
|
|
1067
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1068
|
-
<span class="toggle-tx"><strong>${s("botDefaults.autoStartJoin")}</strong>
|
|
1069
|
-
<small>${s("botDefaults.autoStartJoinHelp")}</small></span>
|
|
1070
|
-
</label>
|
|
1071
|
-
<div class="bd-row">
|
|
1072
|
-
<label>
|
|
1073
|
-
<span>${s("botDefaults.autoStartJoinPrompt")}</span>
|
|
1074
|
-
<textarea data-input="autoJoinPrompt" rows="3"
|
|
1075
|
-
placeholder="${l(s("botDefaults.autoStartJoinPromptPlaceholder"))}">${l(U)}</textarea>
|
|
1076
|
-
</label>
|
|
1077
|
-
<div class="actions">
|
|
1078
|
-
<button type="button" class="primary" data-action="save-auto-join-prompt">${s("botDefaults.autoStartJoinPromptSave")}</button>
|
|
1079
|
-
</div>
|
|
1080
|
-
</div>
|
|
1081
|
-
<label class="toggle-row">
|
|
1082
|
-
<input type="checkbox" data-action="toggle-auto-topic" ${E?"checked":""}>
|
|
1083
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1084
|
-
<span class="toggle-tx"><strong>${s("botDefaults.autoStartTopic")}</strong>
|
|
1085
|
-
<small>${s("botDefaults.autoStartTopicHelp")}</small></span>
|
|
1086
|
-
</label>
|
|
1087
|
-
<div class="actions">
|
|
1088
|
-
<span class="oncall-status" data-auto-start-status></span>
|
|
1089
|
-
</div>
|
|
1090
|
-
</div>`}function R(b){return t.querySelector(`.bd-card[data-appid="${CSS.escape(b)}"]`)}function B(b,S){let E=b?.querySelector("[data-profile-role-list]");E&&(E.innerHTML=p(S),Z(b,S))}async function V(b,S){let E=ts.get(b);if(E?.loaded||E?.loading){B(S,b);return}E={loaded:!1,loading:!0,items:[]},ts.set(b,E),B(S,b);try{let U=await fetch("/api/role-profiles"),ee=await U.json().catch(()=>({}));if(!U.ok)throw new Error(ee?.error??String(U.status));let pe=Array.isArray(ee.profiles)?ee.profiles:[];E.items=pe.filter(he=>(he.botEntries??[]).some(ae=>ae?.larkAppId===b&&ae?.hasEntry)).map(he=>({profileId:String(he.profileId)})),E.loaded=!0}catch(U){E.error=U?.message??String(U),E.loaded=!0}finally{E.loading=!1,B(R(b),b)}}function Z(b,S){b.querySelectorAll("details.bd-profile-role-entry[data-profile-id]").forEach(E=>{E.addEventListener("toggle",()=>{if(!E.open)return;let U=E.dataset.profileId;U&&G(S,U)})})}async function G(b,S){let U=ts.get(b)?.items.find(ee=>ee.profileId===S);if(!(!U||U.loaded||U.loading)){U.loading=!0,j(b,S);try{let ee=await fetch(`/api/role-profiles/${encodeURIComponent(S)}/${encodeURIComponent(b)}`),pe=await ee.json().catch(()=>({}));if(!ee.ok)throw new Error(pe?.error??String(ee.status));U.content=pe?.hasEntry?String(pe.content??""):"",U.loaded=!0}catch(ee){U.error=ee?.message??String(ee)}finally{U.loading=!1,j(b,S)}}}function j(b,S){let U=ts.get(b)?.items.find(pe=>pe.profileId===S);if(!U)return;let ee=R(b)?.querySelector(`[data-profile-role-body="${CSS.escape(S)}"]`);ee&&(ee.innerHTML=f(U))}function z(){t.querySelectorAll(".bd-card").forEach(b=>{let S=b.dataset.appid;V(S,b);let E=b.querySelector("select[data-input=workingDirMode]"),U=b.querySelector("input[data-input=workingDir]"),ee=b.querySelector("[data-wd-dir-row]"),pe=b.querySelector("button[data-action=save-working-dir]"),he=b.querySelector("[data-status]");if(!E||!U||!pe||!he)return;let ae=b.querySelector("select[data-input=agentCliId]"),se=b.querySelector("input[data-input=agentModel]"),ie=b.querySelector("button[data-action=save-agent]"),me=b.querySelector("[data-agent-status]");function be(){if(!ae||!se)return;let Y=b.querySelector(`#agent-model-suggestions-${CSS.escape(S)}`),Q=yo(ae.value),X=Q?.gateway==="ttadk",d=X&&Q.acceptsModel!==!1;if(X&&!d){Y&&(Y.innerHTML=""),se.value="",se.disabled=!0,se.placeholder=s("botOnboarding.modelTtadkCocoPlaceholder");return}se.disabled=!1,d?(Y&&(Y.innerHTML=Ba.map(m=>`<option value="${l(m)}"></option>`).join("")),se.placeholder=s("botOnboarding.modelTtadkPlaceholder").replace("{model}",bo),se.value.trim()||(se.value=bo)):(Y&&(Y.innerHTML=""),se.placeholder=s("botDefaults.agentModelPlaceholder"),se.value.trim()===bo&&(se.value=""))}ae&&se&&ie&&me&&(ae.addEventListener("change",be),ie.addEventListener("click",async()=>{me.textContent="",me.className="oncall-status",ie.disabled=!0,ae.disabled=!0,se.disabled=!0;try{let Y=await fetch(`/api/bots/${encodeURIComponent(S)}/agent`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({cliId:ae.value,model:se.value})}),Q=await Y.json().catch(()=>({}));if(Y.ok&&Q.ok){me.textContent=`\u2713 ${s("botDefaults.agentSaved")}`,me.classList.add("hint-ok");let X=We.bots.find(d=>d.larkAppId===S);X&&(X.cliId=Q.cliId,X.wrapperCli=Q.wrapperCli??null,X.model=Q.model??"",X.agentSelectionKey=Q.selectionKey??ae.value)}else me.textContent=`\u2717 ${Q.error??Y.status}`,me.classList.add("hint-warn-inline")}catch(Y){me.textContent=`\u2717 ${Y?.message??Y}`,me.classList.add("hint-warn-inline")}finally{ie.disabled=!1,ae.disabled=!1,se.disabled=!1,be()}})),E.addEventListener("change",()=>{let Y=E.value==="off";ee&&(ee.hidden=Y),Y||U.focus()}),pe.addEventListener("click",async()=>{he.textContent="",he.className="oncall-status";let Y=E.value,Q=U.value.trim();if(Y!=="off"&&!Q){he.textContent=s("botDefaults.required"),he.classList.add("hint-warn-inline");return}pe.disabled=!0;try{let X=await fetch(`/api/bots/${encodeURIComponent(S)}/working-dir-mode`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({mode:Y,workingDir:Q})}),d=await X.json().catch(()=>({}));if(X.ok&&d.ok){let m=d.resolvedPath?` \u2192 ${d.resolvedPath}`:"";he.textContent=`\u2713 ${s("botDefaults.workingDirSaved")}${m}`,he.classList.add("hint-ok");let k=We.bots.find(x=>x.larkAppId===S);k&&(d.defaultOncall&&(k.defaultOncall=d.defaultOncall),k.defaultWorkingDir=d.defaultWorkingDir??null);let w=b.querySelector("[data-oncall-since]");w&&d.defaultOncall?.since!=null&&(w.textContent=`${s("botDefaults.lastEnabled")}: ${Bl(d.defaultOncall.since)}`)}else he.textContent=`\u2717 ${d.error??X.status}`,he.classList.add("hint-warn-inline")}catch(X){he.textContent=`\u2717 ${X?.message??X}`,he.classList.add("hint-warn-inline")}finally{pe.disabled=!1}});let Me=b.querySelector("input[data-input=brandLabel]"),le=b.querySelector("button[data-action=save-brand]"),ve=b.querySelector("button[data-action=reset-brand]"),$e=b.querySelector("[data-brand-status]"),Pe=b.querySelector("[data-brand-state]");async function Ge(Y,Q){if($e){$e.textContent="",$e.className="oncall-status",Q.disabled=!0;try{let X=await fetch(`/api/bots/${encodeURIComponent(S)}/brand-label`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({brandLabel:Y})}),d=await X.json().catch(()=>({}));if(X.ok&&d.ok){let m=d.brandLabel??null;$e.textContent="\u2713",$e.classList.add("hint-ok"),Me&&(Me.value=m??""),Pe&&(Pe.textContent=h(m));let k=We.bots.find(w=>w.larkAppId===S);k&&(k.brandLabel=m)}else $e.textContent=`\u2717 ${d.error??X.status}`,$e.classList.add("hint-warn-inline")}catch(X){$e.textContent=`\u2717 ${X?.message??X}`,$e.classList.add("hint-warn-inline")}finally{Q.disabled=!1}}}Me&&le&&le.addEventListener("click",()=>Ge(Me.value,le)),ve&&ve.addEventListener("click",()=>Ge(null,ve));let it=b.querySelector("input[data-action=toggle-disable-streaming]"),He=b.querySelector("input[data-action=toggle-silent-reactions]"),Xe=b.querySelector("input[data-action=toggle-writable-link]"),Ye=b.querySelector("input[data-action=toggle-private-card]"),K=b.querySelector("[data-card-pref-status]"),Ae=b.querySelector("[data-card-pref-moot]");async function fe(Y,Q,X=K){if(X){X.textContent="",X.className="oncall-status",Q.disabled=!0;try{let d=await fetch(`/api/bots/${encodeURIComponent(S)}/card-prefs`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(Y)}),m=await d.json().catch(()=>({}));if(d.ok&&m.ok){X.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,X.classList.add("hint-ok");let k=We.bots.find(w=>w.larkAppId===S);k&&(k.disableStreamingCard=m.disableStreamingCard,k.silentTurnReactions=m.silentTurnReactions,k.writableTerminalLinkInCard=m.writableTerminalLinkInCard,k.privateCard=m.privateCard,k.botToBotSameDir=m.botToBotSameDir,k.autoStartOnGroupJoin=m.autoStartOnGroupJoin,k.autoStartOnGroupJoinPrompt=m.autoStartOnGroupJoinPrompt,k.autoStartOnNewTopic=m.autoStartOnNewTopic,k.regularGroupReplyMode=m.regularGroupReplyMode,k.regularGroupMentionMode=m.regularGroupMentionMode,k.docSubscribeDefaultMode=m.docSubscribeDefaultMode)}else X.textContent=`\u2717 ${m.error??d.status}`,X.classList.add("hint-warn-inline")}catch(d){X.textContent=`\u2717 ${d?.message??d}`,X.classList.add("hint-warn-inline")}finally{Q===Xe?Q.disabled=!!it?.checked:Q===He?Q.disabled=!it?.checked:Q.disabled=!1}}}it&&it.addEventListener("change",()=>{let Y=it.checked;Xe&&(Xe.disabled=Y),He&&(He.disabled=!Y),Ae&&(Ae.hidden=!Y),fe({disableStreamingCard:Y},it)}),He&&He.addEventListener("change",()=>{fe({silentTurnReactions:He.checked},He)}),Xe&&Xe.addEventListener("change",()=>{fe({writableTerminalLinkInCard:Xe.checked},Xe)}),Ye&&Ye.addEventListener("change",()=>{fe({privateCard:Ye.checked},Ye)});let re=b.querySelector("input[data-action=toggle-cross-bot-samedir]"),Be=b.querySelector("[data-crossbot-status]");re&&re.addEventListener("change",()=>{fe({botToBotSameDir:re.checked},re,Be)});let rt=b.querySelector("input[data-input=summaryLimit]"),wt=b.querySelector("input[data-input=summarySinceHours]"),kt=b.querySelector("button[data-action=save-summary-trigger]"),et=b.querySelector("[data-summary-trigger-status]");function xn(Y,Q){let X=Y.value.trim();return X===""?Q:/^(0|[1-9]\d*)$/.test(X)?Number(X):null}rt&&wt&&kt&&kt.addEventListener("click",async()=>{if(!et)return;et.textContent="",et.className="oncall-status";let Y=xn(rt,50),Q=xn(wt,24);if(Y==null||Q==null){et.textContent=`\u2717 ${s("botDefaults.summaryNumberInvalid")}`,et.classList.add("hint-warn-inline");return}kt.disabled=!0;try{let X=await fetch(`/api/bots/${encodeURIComponent(S)}/summary-range`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({limit:Y,sinceHours:Q})}),d=await X.json().catch(()=>({}));if(X.ok&&d.ok){et.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,et.classList.add("hint-ok");let m=d.summaryRange??{limit:Y,sinceHours:Q};rt.value=String(Number.isInteger(m.limit)&&m.limit>=0?m.limit:Y),wt.value=String(Number.isInteger(m.sinceHours)&&m.sinceHours>=0?m.sinceHours:Q);let k=We.bots.find(w=>w.larkAppId===S);k&&(k.summaryRange=m)}else et.textContent=`\u2717 ${d.error??X.status}`,et.classList.add("hint-warn-inline")}catch(X){et.textContent=`\u2717 ${X?.message??X}`,et.classList.add("hint-warn-inline")}finally{kt.disabled=!1}});let ot=b.querySelector("input[data-action=toggle-sandbox]"),Ze=b.querySelector("[data-sandbox-status]");ot&&ot.addEventListener("change",async()=>{let Y=ot.checked;Ze&&(Ze.textContent="",Ze.className="oncall-status"),ot.disabled=!0;try{let Q=await fetch(`/api/bots/${encodeURIComponent(S)}/sandbox`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({enabled:Y})}),X=await Q.json().catch(()=>({}));if(Q.ok&&X.ok){Ze&&(Ze.textContent=`\u2713 ${s("botDefaults.sandboxSaved")}`,Ze.classList.add("hint-ok"));let d=We.bots.find(m=>m.larkAppId===S);d&&(d.sandbox=X.sandbox===!0)}else Ze&&(Ze.textContent=`\u2717 ${X.error??Q.status}`,Ze.classList.add("hint-warn-inline")),ot.checked=!Y}catch(Q){Ze&&(Ze.textContent=`\u2717 ${Q?.message??Q}`,Ze.classList.add("hint-warn-inline")),ot.checked=!Y}finally{ot.disabled=!1}});let Vt=b.querySelector("input[data-action=toggle-auto-join]"),$t=b.querySelector("input[data-action=toggle-auto-topic]"),Wn=b.querySelector("textarea[data-input=autoJoinPrompt]"),At=b.querySelector("button[data-action=save-auto-join-prompt]"),xt=b.querySelector("[data-auto-start-status]");Vt&&Vt.addEventListener("change",()=>{fe({autoStartOnGroupJoin:Vt.checked},Vt,xt)}),$t&&$t.addEventListener("change",()=>{fe({autoStartOnNewTopic:$t.checked},$t,xt)}),Wn&&At&&At.addEventListener("click",()=>{fe({autoStartOnGroupJoinPrompt:Wn.value},At,xt)});let Dt=b.querySelector("select[data-input=p2pMode]"),Ee=b.querySelector("[data-p2p-status]");Dt&&Ee&&Dt.addEventListener("change",async()=>{let Y=Dt.value==="chat"?"chat":"thread";Ee.textContent="",Ee.className="oncall-status",Dt.disabled=!0;try{let Q=await fetch(`/api/bots/${encodeURIComponent(S)}/p2p-mode`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({p2pMode:Y})}),X=await Q.json().catch(()=>({}));if(Q.ok&&X.ok){Ee.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,Ee.classList.add("hint-ok");let d=We.bots.find(m=>m.larkAppId===S);d&&(d.p2pMode=X.p2pMode==="chat"?"chat":"thread")}else Ee.textContent=`\u2717 ${X.error??Q.status}`,Ee.classList.add("hint-warn-inline")}catch(Q){Ee.textContent=`\u2717 ${Q?.message??Q}`,Ee.classList.add("hint-warn-inline")}finally{Dt.disabled=!1}});let _e=b.querySelector("select[data-input=regularGroupMode]"),Ht=b.querySelector("[data-regular-group-status]");_e&&_e.addEventListener("change",()=>{fe({regularGroupReplyMode:_e.value},_e,Ht)});let dt=b.querySelector("select[data-input=regularGroupMentionMode]"),Vn=b.querySelector("[data-mention-mode-status]");dt&&dt.addEventListener("change",()=>{fe({regularGroupMentionMode:dt.value},dt,Vn)});let _t=b.querySelector("select[data-input=docSubscribeDefaultMode]"),vs=b.querySelector("[data-doc-subscribe-mode-status]");_t&&_t.addEventListener("change",()=>{fe({docSubscribeDefaultMode:_t.value},_t,vs)});let Rt=b.querySelector("textarea[data-input=teamRole]"),St=b.querySelector("button[data-action=save-role]"),Pt=b.querySelector("button[data-action=delete-role]"),_=b.querySelector("[data-role-status]");if(Rt&&St&&Pt&&_){let X=function(m){let k=t.querySelector(`.bd-card[data-appid="${CSS.escape(S)}"]`);if(!k)return;let w=k.querySelector("textarea[data-input=teamRole]"),x=k.querySelector("button[data-action=save-role]"),T=k.querySelector("button[data-action=delete-role]");w&&(w.value=m,w.disabled=!1),x&&(x.disabled=!1),T&&(T.disabled=!1)};var ks=X;let Y=`/api/team/local-bots/${encodeURIComponent(S)}/role`,Q=We.bots.find(m=>m.larkAppId===S);Q&&typeof Q.teamRole!="string"&&!Q.teamRoleLoading&&(Q.teamRoleLoading=!0,(async()=>{try{let m=await fetch(Y),k=await m.json().catch(()=>({}));m.ok&&k.ok?(Q.teamRole=k.role??"",X(Q.teamRole)):(_.textContent=`\u2717 ${s("botDefaults.roleLoadErr")}: ${k.error??m.status}`,_.classList.add("hint-warn-inline"))}catch(m){_.textContent=`\u2717 ${s("botDefaults.roleLoadErr")}: ${m?.message??m}`,_.classList.add("hint-warn-inline")}finally{Q.teamRoleLoading=!1}})());async function d(m,k,w){if(_&&!(!Q||typeof Q.teamRole!="string")){_.textContent="",_.className="oncall-status",St.disabled=!0,Pt.disabled=!0;try{let x=await fetch(Y,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({role:m})}),T=await x.json().catch(()=>({}));x.ok&&T.ok?(Q&&(Q.teamRole=m.trim()),_.textContent=`\u2713 ${w?s("botDefaults.roleDeleted"):s("botDefaults.roleSaved")}`,_.classList.add("hint-ok")):(_.textContent=`\u2717 ${T.error??x.status}`,_.classList.add("hint-warn-inline"))}catch(x){_.textContent=`\u2717 ${x?.message??x}`,_.classList.add("hint-warn-inline")}finally{St.disabled=!1,Pt.disabled=!1}}}St.addEventListener("click",()=>d(Rt.value,St,!1)),Pt.addEventListener("click",()=>{Rt.value="",d("",Pt,!0)})}let te=b.querySelector("input[data-action=toggle-auto-grant-card]"),oe=b.querySelector("input[data-action=toggle-restrict-grant]"),ue=b.querySelector("input[data-input=quotaLimit]"),J=b.querySelector("button[data-action=save-quota]"),ce=b.querySelector("button[data-action=off-quota]"),ge=b.querySelector("[data-grant-status]"),Bt=b.querySelector("[data-quota-state]");async function ln(Y,Q){if(ge){ge.textContent="",ge.className="oncall-status",Q.disabled=!0;try{let X=await fetch(`/api/bots/${encodeURIComponent(S)}/grant-prefs`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(Y)}),d=await X.json().catch(()=>({}));if(X.ok&&d.ok){ge.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,ge.classList.add("hint-ok");let m=typeof d.messageQuotaDefaultLimit=="number"?d.messageQuotaDefaultLimit:null,k=We.bots.find(w=>w.larkAppId===S);k&&(k.autoGrantRequestCards=d.autoGrantRequestCards!==!1,k.restrictGrantCommands=d.restrictGrantCommands===!0,k.messageQuotaDefaultLimit=m),Bt&&(Bt.textContent=N(m)),ue&&"messageQuotaDefaultLimit"in Y&&(ue.value=m==null?"":String(m))}else ge.textContent=`\u2717 ${d.error??X.status}`,ge.classList.add("hint-warn-inline")}catch(X){ge.textContent=`\u2717 ${X?.message??X}`,ge.classList.add("hint-warn-inline")}finally{Q.disabled=!1}}}te&&te.addEventListener("change",()=>{ln({autoGrantRequestCards:te.checked},te)}),oe&&oe.addEventListener("change",()=>{ln({restrictGrantCommands:oe.checked},oe)}),ue&&J&&J.addEventListener("click",()=>{let Y=ue.value.trim();if(Y===""){ln({messageQuotaDefaultLimit:null},J);return}if(!/^[1-9]\d*$/.test(Y)){ge&&(ge.textContent=`\u2717 ${s("botDefaults.quotaInvalid")}`,ge.className="oncall-status hint-warn-inline");return}ln({messageQuotaDefaultLimit:Number(Y)},J)}),ue&&ce&&ce.addEventListener("click",()=>{ue.value="",ln({messageQuotaDefaultLimit:null},ce)});let un=b.querySelector("input[data-input=maxLiveWorkers]"),Kn=b.querySelector("button[data-action=save-session-cap]"),Sn=b.querySelector("button[data-action=off-session-cap]"),tt=b.querySelector("[data-session-cap-status]"),Xs=b.querySelector("[data-session-cap-state]");async function ws(Y,Q){if(tt){tt.textContent="",tt.className="oncall-status",Q.disabled=!0;try{let X=await fetch(`/api/bots/${encodeURIComponent(S)}/max-live-workers`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({maxLiveWorkers:Y})}),d=await X.json().catch(()=>({}));if(X.ok&&d.ok){tt.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,tt.classList.add("hint-ok");let m=typeof d.maxLiveWorkers=="number"?d.maxLiveWorkers:null,k=We.bots.find(w=>w.larkAppId===S);k&&(k.maxLiveWorkers=m),Xs&&(Xs.textContent=L(m)),un&&(un.value=m==null?"":String(m))}else tt.textContent=`\u2717 ${d.error??X.status}`,tt.classList.add("hint-warn-inline")}catch(X){tt.textContent=`\u2717 ${X?.message??X}`,tt.classList.add("hint-warn-inline")}finally{Q.disabled=!1}}}un&&Kn&&Kn.addEventListener("click",()=>{let Y=un.value.trim();if(Y===""){ws(null,Kn);return}if(!/^[1-9]\d*$/.test(Y)){tt&&(tt.textContent=`\u2717 ${s("botDefaults.maxLiveWorkersInvalid")}`,tt.className="oncall-status hint-warn-inline");return}ws(Number(Y),Kn)}),un&&Sn&&Sn.addEventListener("click",()=>{un.value="",ws(null,Sn)});let ye=b.querySelector("textarea[data-input=startupCommands]"),En=b.querySelector("button[data-action=save-startup-commands]"),gt=b.querySelector("[data-startup-commands-status]");ye&&En&&En.addEventListener("click",async()=>{if(gt){gt.textContent="",gt.className="oncall-status",En.disabled=!0;try{let Y=await fetch(`/api/bots/${encodeURIComponent(S)}/startup-commands`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({startupCommands:ye.value})}),Q=await Y.json().catch(()=>({}));if(Y.ok&&Q.ok){gt.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,gt.classList.add("hint-ok");let X=typeof Q.startupCommands=="string"?Q.startupCommands:"";ye.value=X;let d=We.bots.find(m=>m.larkAppId===S);d&&(d.startupCommands=X)}else gt.textContent=`\u2717 ${Q.error??Y.status}`,gt.classList.add("hint-warn-inline")}catch(Y){gt.textContent=`\u2717 ${Y?.message??Y}`,gt.classList.add("hint-warn-inline")}finally{En.disabled=!1}}});let Kt=b.querySelector("input[data-input=launchShell]"),cn=b.querySelector("button[data-action=save-launch-shell]"),pt=b.querySelector("[data-launch-shell-status]");Kt&&cn&&cn.addEventListener("click",async()=>{if(pt){pt.textContent="",pt.className="oncall-status",cn.disabled=!0;try{let Y=await fetch(`/api/bots/${encodeURIComponent(S)}/launch-shell`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({launchShell:Kt.value})}),Q=await Y.json().catch(()=>({}));if(Y.ok&&Q.ok){pt.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,pt.classList.add("hint-ok");let X=typeof Q.launchShell=="string"?Q.launchShell:"";Kt.value=X;let d=We.bots.find(m=>m.larkAppId===S);d&&(d.launchShell=X)}else pt.textContent=`\u2717 ${Q.error??Y.status}`,pt.classList.add("hint-warn-inline")}catch(Y){pt.textContent=`\u2717 ${Y?.message??Y}`,pt.classList.add("hint-warn-inline")}finally{cn.disabled=!1}}});let Tn=b.querySelector("textarea[data-input=env]"),Jn=b.querySelector("button[data-action=save-env]"),Et=b.querySelector("[data-env-status]");Tn&&Jn&&Jn.addEventListener("click",async()=>{if(Et){Et.textContent="",Et.className="oncall-status",Jn.disabled=!0;try{let Y=await fetch(`/api/bots/${encodeURIComponent(S)}/env`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({env:Tn.value})}),Q=await Y.json().catch(()=>({}));if(Y.ok&&Q.ok){Et.textContent=`\u2713 ${s("botDefaults.cardPrefSaved")}`,Et.classList.add("hint-ok");let X=typeof Q.env=="string"?Q.env:"";Tn.value=X;let d=We.bots.find(m=>m.larkAppId===S);d&&(d.env=X)}else Et.textContent=`\u2717 ${Q.error??Y.status}`,Et.classList.add("hint-warn-inline")}catch(Y){Et.textContent=`\u2717 ${Y?.message??Y}`,Et.classList.add("hint-warn-inline")}finally{Jn.disabled=!1}}})})}i(),bt().then(i),a.addEventListener("input",i)}var Le={skills:[],nativeSkillGroups:[],bots:[],trustProjectSkills:"off",delivery:"auto"},wo=null,Fp=2,In=0,vo=null;function Np(){return`<section class="page">
|
|
1091
|
-
<div class="page-heading">
|
|
1092
|
-
<div>
|
|
1093
|
-
<p class="eyebrow">${s("nav.skills")}</p>
|
|
1094
|
-
<h1>${s("skills.title")}</h1>
|
|
1095
|
-
<p>${s("skills.subtitle")}</p>
|
|
1096
|
-
</div>
|
|
1097
|
-
<button type="button" id="skills-refresh">${s("skills.refresh")}</button>
|
|
1098
|
-
</div>
|
|
1099
|
-
<div id="skills-body"></div>
|
|
1100
|
-
</section>`}function qp(e){let t=e.source??{};return t.type==="github"?`github:${t.owner}/${t.repo}/${t.path??""}`:t.type==="git"?`${t.url??"git"}#${t.path??""}`:t.type==="local-link"?jp(t.path)??s("skills.sourceLocalLink"):t.type==="local-copy"?s("skills.sourceBotmuxCopy"):String(t.type??"unknown")}function jp(e){let t=String(e??"").replace(/\\/g,"/");return t.includes("/.codex/skills/")?s("skills.sourceCodex"):t.includes("/.claude/skills/")?s("skills.sourceClaude"):t.includes("/.trae/skills/")?s("skills.sourceTrae"):t.includes("/.cursor/skills/")?s("skills.sourceCursor"):t.includes("/.gemini/skills/")?s("skills.sourceGemini"):t.includes("/.config/opencode/skills/")?s("skills.sourceOpenCode"):null}function Ms(e){return(e?.include??[]).filter(t=>t.startsWith("skill:")).map(t=>t.slice(6))}function Up(e){return Ms(e).length}function zp(e){return Ms(e).length>0}function Fl(){return new Set(Le.skills.map(e=>e.name))}function Cn(e){return`${e.cliId}
|
|
1101
|
-
${e.rootDir}`}function Gp(){return Le.nativeSkillGroups}function Wp(e){if(e.length===0)return;let n=(vo?e.find(a=>Cn(a)===vo):void 0)??e.find(a=>a.skills.length>0)??e[0];return vo=Cn(n),n}function Vp(e){return Le.bots.filter(t=>Ms(t.skills).includes(e)).map(t=>t.botName??t.larkAppId)}function Kp(){return`<article class="bd-card skills-install-panel">
|
|
1102
|
-
<div class="skills-install-title">
|
|
1103
|
-
<h3 class="bd-section-title">${s("skills.install")}</h3>
|
|
1104
|
-
<span class="skills-help-tip">
|
|
1105
|
-
<button type="button" class="skills-help-button" aria-label="${s("skills.installInfoLabel")}">?</button>
|
|
1106
|
-
<span class="skills-help-popover" role="tooltip">${s("skills.installInfo")}</span>
|
|
1107
|
-
</span>
|
|
1108
|
-
</div>
|
|
1109
|
-
<div class="skills-install-grid">
|
|
1110
|
-
<label class="skills-source-label"><span>${s("skills.source")}</span>
|
|
1111
|
-
<div class="skills-source-control">
|
|
1112
|
-
<input type="text" data-install="source" placeholder="${s("skills.sourcePlaceholder")}">
|
|
1113
|
-
<button type="button" data-action="discover-native-skills">${s("skills.discover")}</button>
|
|
1114
|
-
</div>
|
|
1115
|
-
</label>
|
|
1116
|
-
<div class="bd-section-note skills-install-note">
|
|
1117
|
-
<span><strong>${s("skills.sourceHelpRemoteLabel")}</strong>${s("skills.sourceHelpRemote")}</span>
|
|
1118
|
-
<span><strong>${s("skills.sourceHelpLocalLabel")}</strong>${s("skills.sourceHelpLocal")}</span>
|
|
1119
|
-
</div>
|
|
1120
|
-
<label class="skills-install-field-wide"><span>${s("skills.path")}</span>
|
|
1121
|
-
<input type="text" data-install="path" placeholder="${s("skills.pathPlaceholder")}">
|
|
1122
|
-
</label>
|
|
1123
|
-
<label class="skills-install-field-wide"><span>${s("skills.ref")}</span>
|
|
1124
|
-
<input type="text" data-install="ref" placeholder="${s("skills.refPlaceholder")}">
|
|
1125
|
-
</label>
|
|
1126
|
-
</div>
|
|
1127
|
-
<div class="actions">
|
|
1128
|
-
<button type="button" class="primary" data-action="install">${s("skills.installSubmit")}</button>
|
|
1129
|
-
<span class="oncall-status" data-skills-status></span>
|
|
1130
|
-
</div>
|
|
1131
|
-
</article>`}function Jp(){let e=Fl(),t=Gp(),n=Wp(t),a=n?`<div class="skills-discovery-tabs" role="tablist" aria-label="${s("skills.discoverTitle")}">
|
|
1132
|
-
${t.map(o=>{let i=Cn(o),r=i===Cn(n);return`<button type="button" role="tab" data-discovery-tab="${l(i)}" class="${r?"selected":""}" aria-selected="${r?"true":"false"}">
|
|
1133
|
-
<strong>${l(o.label??o.cliId)}</strong>
|
|
1134
|
-
<small>${s("skills.skillCount",{count:o.skills.length})}</small>
|
|
1135
|
-
</button>`}).join("")}
|
|
1136
|
-
</div>
|
|
1137
|
-
<div class="skills-discovery-path"><code>${l(n.rootDir)}</code></div>
|
|
1138
|
-
${t.map(o=>{let i=Cn(o),r=n&&i===Cn(n);return`<section class="skills-discovery-group" data-discovery-panel="${l(i)}" ${r?"":"hidden"}>
|
|
1139
|
-
${o.skills.length===0?`<p class="empty">${s("skills.discoverGroupEmpty")}</p>`:`<div class="skills-discovery-list">
|
|
1140
|
-
${o.skills.map(u=>{let c=e.has(u.name),p=u.rootDir??u.source?.root??"";return`<label class="skills-discovery-row${c?" installed":""}">
|
|
1141
|
-
<input type="checkbox" data-discovered-skill value="${l(p)}" ${c?"disabled":""}>
|
|
1142
|
-
<span>
|
|
1143
|
-
<strong>${l(u.name)}</strong>
|
|
1144
|
-
${u.description?`<small>${l(u.description)}</small>`:""}
|
|
1145
|
-
</span>
|
|
1146
|
-
${c?`<em>${s("skills.discoverRegistered")}</em>`:""}
|
|
1147
|
-
</label>`}).join("")}
|
|
1148
|
-
</div>`}
|
|
1149
|
-
</section>`}).join("")}`:`<p class="empty">${s("skills.discoverEmpty")}</p>`;return`<dialog class="skills-discovery-dialog" id="skills-discovery-dialog">
|
|
1150
|
-
<article>
|
|
1151
|
-
<header>
|
|
1152
|
-
<h3>${s("skills.discoverTitle")}</h3>
|
|
1153
|
-
<p>${s("skills.discoverHelp")}</p>
|
|
1154
|
-
</header>
|
|
1155
|
-
<div class="skills-discovery-body">${a}</div>
|
|
1156
|
-
<footer class="actions">
|
|
1157
|
-
<button type="button" data-action="toggle-discovered-skills">${s("skills.discoverSelectAll")}</button>
|
|
1158
|
-
<button type="button" class="primary" data-action="register-discovered-skills">${s("skills.discoverRegister")}</button>
|
|
1159
|
-
<button type="button" data-action="close-discovery">${s("skills.discoverClose")}</button>
|
|
1160
|
-
</footer>
|
|
1161
|
-
</article>
|
|
1162
|
-
</dialog>`}function Yp(){if(Le.skills.length===0)return`<p class="empty">${s("skills.empty")}</p>`;ko();let e=Nl(),t=In*e;return`<div class="skills-list">${Le.skills.slice(t,t+e).map(a=>`
|
|
1163
|
-
<article class="skills-row skills-installed-card" data-skill="${l(a.name)}">
|
|
1164
|
-
<div class="skills-row-body">
|
|
1165
|
-
<strong>${l(a.name)}</strong>
|
|
1166
|
-
${a.description?`<p>${l(a.description)}</p>`:""}
|
|
1167
|
-
<small class="skills-source-badge">${l(qp(a))}</small>
|
|
1168
|
-
</div>
|
|
1169
|
-
<div class="skills-card-actions">
|
|
1170
|
-
<button type="button" data-action="update-skill">${s("skills.update")}</button>
|
|
1171
|
-
<button type="button" data-action="remove-skill">${s("skills.remove")}</button>
|
|
1172
|
-
</div>
|
|
1173
|
-
</article>`).join("")}</div>`}function Zp(){let e=typeof window>"u"?1440:window.innerWidth;return e>=1600?4:e<=620?1:e<=980?2:3}function Nl(){return Zp()*Fp}function ql(){return Math.max(1,Math.ceil(Le.skills.length/Nl()))}function ko(){In=Math.min(Math.max(0,In),ql()-1)}function Qp(){ko();let e=`<span class="skills-count-pill">${s("skills.skillCount",{count:Le.skills.length})}</span>`,t=ql();return t<=1?e:`<div class="skills-installed-toolbar">
|
|
1174
|
-
${e}
|
|
1175
|
-
<div class="skills-pager">
|
|
1176
|
-
<button type="button" class="skills-pager-button" data-action="page-installed-skills" data-dir="-1" aria-label="${s("skills.prevPage")}" title="${s("skills.prevPage")}" ${In===0?"disabled":""}>‹</button>
|
|
1177
|
-
<span>${s("skills.pageStatus",{page:In+1,pages:t})}</span>
|
|
1178
|
-
<button type="button" class="skills-pager-button" data-action="page-installed-skills" data-dir="1" aria-label="${s("skills.nextPage")}" title="${s("skills.nextPage")}" ${In>=t-1?"disabled":""}>›</button>
|
|
1179
|
-
</div>
|
|
1180
|
-
</div>`}function Xp(){let e=[["auto",s("skills.deliveryAuto"),s("skills.deliveryAutoHelp")],["prompt",s("skills.deliveryPrompt"),s("skills.deliveryPromptHelp")],["native",s("skills.deliveryNative"),s("skills.deliveryNativeHelp")]];return`<article class="bd-card skills-defaults-panel">
|
|
1181
|
-
<h3 class="bd-section-title">${s("skills.globalDefaults")}</h3>
|
|
1182
|
-
<div class="skills-control-block">
|
|
1183
|
-
<span class="skills-control-label">${s("skills.globalProject")}</span>
|
|
1184
|
-
<div class="skills-choice-group skills-choice-group-compact skills-project-group">
|
|
1185
|
-
${[["off",s("skills.globalProjectOff"),s("skills.globalProjectOffHelp")],["all",s("skills.globalProjectAll"),s("skills.globalProjectAllHelp")]].map(([t,n,a])=>`<button type="button" class="skills-choice${Le.trustProjectSkills===t?" selected":""}" data-global-project-value="${t}" aria-pressed="${Le.trustProjectSkills===t?"true":"false"}">
|
|
1186
|
-
<strong>${n}</strong><small>${a}</small>
|
|
1187
|
-
</button>`).join("")}
|
|
1188
|
-
</div>
|
|
1189
|
-
</div>
|
|
1190
|
-
<div class="skills-control-block">
|
|
1191
|
-
<span class="skills-control-label">${s("skills.globalDelivery")}</span>
|
|
1192
|
-
<div class="skills-choice-group skills-delivery-group">
|
|
1193
|
-
${e.map(([t,n,a])=>`<button type="button" class="skills-choice${Le.delivery===t?" selected":""}" data-global-delivery-value="${t}" aria-pressed="${Le.delivery===t?"true":"false"}">
|
|
1194
|
-
<strong>${n}</strong><small>${a}</small>
|
|
1195
|
-
</button>`).join("")}
|
|
1196
|
-
</div>
|
|
1197
|
-
</div>
|
|
1198
|
-
</article>`}function ef(e){let t=new Set(Ms(e.skills)),n=Le.skills.filter(a=>!t.has(a.name));return n.length===0?`<button type="button" disabled>${s("skills.attach")}</button>`:`<select data-attach-picker>
|
|
1199
|
-
${n.map(a=>`<option value="${l(a.name)}">${l(a.name)}</option>`).join("")}
|
|
1200
|
-
</select>
|
|
1201
|
-
<button type="button" data-action="attach-skill">${s("skills.attach")}</button>`}function tf(e){if(e.error)return`<article class="bd-card skills-bot-card" data-appid="${l(e.larkAppId)}">
|
|
1202
|
-
<header>${Re({name:e.botName??e.larkAppId,larkAppId:e.larkAppId,size:"sm"})}
|
|
1203
|
-
<strong>${l(e.botName??e.larkAppId)}</strong></header>
|
|
1204
|
-
<p class="hint-warn-inline">${l(e.error)}</p>
|
|
1205
|
-
</article>`;let t=Ms(e.skills),n=Fl();return`<article class="bd-card skills-bot-card" data-appid="${l(e.larkAppId)}">
|
|
1206
|
-
<header class="skills-bot-head">
|
|
1207
|
-
${Re({name:e.botName??e.larkAppId,larkAppId:e.larkAppId,size:"sm",dot:"ok"})}
|
|
1208
|
-
<div><strong>${l(e.botName??e.larkAppId)}</strong><code>${l(e.larkAppId)}</code></div>
|
|
1209
|
-
<span class="skills-count-pill">${s("skills.skillCount",{count:t.length})}</span>
|
|
1210
|
-
</header>
|
|
1211
|
-
<section class="bd-section">
|
|
1212
|
-
<h3 class="bd-section-title">${s("skills.priority")}</h3>
|
|
1213
|
-
${t.length===0?`<p class="bd-section-note">${s("skills.noPriority")}</p>`:`<div class="skills-chip-list">${t.map(a=>{let o=!n.has(a);return`<span class="skills-priority-row${o?" skills-priority-dangling":""}" title="${o?l(s("skills.dangling")):""}">
|
|
1214
|
-
<span class="skills-priority-name">${l(a)}${o?`<small>${s("skills.dangling")}</small>`:""}</span>
|
|
1215
|
-
<button type="button" class="skills-priority-remove" data-action="detach-skill" data-name="${l(a)}" aria-label="${l(s("skills.detachNamed",{skill:a}))}">×</button>
|
|
1216
|
-
</span>`}).join("")}</div>`}
|
|
1217
|
-
<div class="actions skills-attach-row">${ef(e)}</div>
|
|
1218
|
-
</section>
|
|
1219
|
-
<span class="oncall-status" data-bot-status></span>
|
|
1220
|
-
</article>`}function nf(){return Le.bots.reduce((e,t)=>e+Up(t.skills),0)}function sf(){return Le.bots.filter(e=>zp(e.skills)).length}function of(){return`<section class="skills-overview">
|
|
1221
|
-
<div class="skills-overview-copy">
|
|
1222
|
-
<h2>${s("skills.overviewTitle")}</h2>
|
|
1223
|
-
<p>${s("skills.overviewBody")}</p>
|
|
1224
|
-
</div>
|
|
1225
|
-
<div class="skills-metric-strip">
|
|
1226
|
-
<span><small>${s("skills.metricInstalled")}</small><strong>${Le.skills.length}</strong></span>
|
|
1227
|
-
<span><small>${s("skills.metricBots")}</small><strong>${sf()}/${Le.bots.length}</strong></span>
|
|
1228
|
-
<span><small>${s("skills.metricAttached")}</small><strong>${nf()}</strong></span>
|
|
1229
|
-
</div>
|
|
1230
|
-
</section>`}function af(){let e=`<span class="skills-count-pill">${s("skills.botCount",{count:Le.bots.length})}</span>`;return Le.bots.length<=3?e:`<div class="skills-bot-rail-actions">
|
|
1231
|
-
<button type="button" class="skills-rail-button" data-action="scroll-bots" data-dir="-1" aria-label="${s("skills.scrollBotsPrev")}" title="${s("skills.scrollBotsPrev")}">‹</button>
|
|
1232
|
-
${e}
|
|
1233
|
-
<button type="button" class="skills-rail-button" data-action="scroll-bots" data-dir="1" aria-label="${s("skills.scrollBotsNext")}" title="${s("skills.scrollBotsNext")}">›</button>
|
|
1234
|
-
</div>`}function rf(){return wo?`<p class="hint-warn">${l(wo)}</p>`:`<div class="skills-page-grid">
|
|
1235
|
-
<aside class="skills-side-rail">
|
|
1236
|
-
${Xp()}
|
|
1237
|
-
${Kp()}
|
|
1238
|
-
</aside>
|
|
1239
|
-
<section class="skills-main-panel">
|
|
1240
|
-
${of()}
|
|
1241
|
-
<section class="skills-bots-panel">
|
|
1242
|
-
<div class="skills-section-head skills-section-head-row">
|
|
1243
|
-
<div>
|
|
1244
|
-
<h2>${s("skills.bots")}</h2>
|
|
1245
|
-
<p>${s("skills.botsHelp")}</p>
|
|
1246
|
-
</div>
|
|
1247
|
-
${af()}
|
|
1248
|
-
</div>
|
|
1249
|
-
<div class="skills-bot-grid">${Le.bots.map(tf).join("")}</div>
|
|
1250
|
-
</section>
|
|
1251
|
-
<section class="bd-card skills-installed-panel">
|
|
1252
|
-
<div class="skills-section-head skills-section-head-row">
|
|
1253
|
-
<div>
|
|
1254
|
-
<h2>${s("skills.installed")}</h2>
|
|
1255
|
-
<p>${s("skills.installedHelp")}</p>
|
|
1256
|
-
</div>
|
|
1257
|
-
${Qp()}
|
|
1258
|
-
</div>
|
|
1259
|
-
${Yp()}
|
|
1260
|
-
</section>
|
|
1261
|
-
</section>
|
|
1262
|
-
${Jp()}
|
|
1263
|
-
</div>`}async function lf(){try{let[e,t]=await Promise.all([fetch("/api/skills"),fetch("/api/bots")]),n=await e.json().catch(()=>({})),a=await t.json().catch(()=>({}));if(!e.ok){let o=n?.error??`skills HTTP ${e.status}`;throw new Error(o==="not_found_yet"||o==="not_found"?s("skills.apiUnavailable"):o)}if(!t.ok)throw new Error(a?.error??`bots HTTP ${t.status}`);Le={skills:Array.isArray(n.skills)?n.skills:[],nativeSkillGroups:Array.isArray(n.nativeSkillGroups)?n.nativeSkillGroups:[],bots:Array.isArray(a.bots)?a.bots:[],trustProjectSkills:n.trustProjectSkills==="all"?"all":"off",delivery:n.delivery==="prompt"||n.delivery==="native"?n.delivery:"auto"},ko(),wo=null}catch(e){wo=e?.message??String(e)}}async function Ft(e,t){let n=await fetch(e,{...t,headers:{"content-type":"application/json",...t.headers??{}}}),a=await n.json().catch(()=>({}));if(!n.ok||a.ok===!1){let o=new Error(a?.error??`HTTP ${n.status}`);throw o.status=n.status,o.body=a,o}return a}function uf(e){return new Promise(t=>setTimeout(t,e))}async function jl(e){e.innerHTML=Np();let t=e.querySelector("#skills-body"),n=e.querySelector("#skills-refresh");async function a(){t.innerHTML=Tt(),await lf(),c()}function o(g){return g?.querySelector("[data-skills-status], [data-bot-status]")??null}function i(g,v,M){g&&(g.textContent=v,g.className=`oncall-status ${M?"hint-ok":"hint-warn-inline"}`)}function r(g,v){t.querySelectorAll(g).forEach(M=>{M.disabled=v})}function u(g,v,M){t.querySelectorAll(g).forEach($=>{let L=$.dataset[v]===M;$.classList.toggle("selected",L),$.setAttribute("aria-pressed",L?"true":"false")})}function c(){t.innerHTML=rf(),y()}async function p(g,v,M=!0){let $=g;for(i(v,s("skills.jobRunning"),!0);;){if($.status==="succeeded"){i(v,s("skills.saved"),!0),M&&await a();return}if($.status==="failed")throw new Error($.error??"job_failed");await uf(800),$=(await Ft(`/api/skills/jobs/${encodeURIComponent($.id)}`,{method:"GET"})).job}}function f(){return t.querySelector("[data-discovery-panel]:not([hidden])")}function h(){let g=t.querySelector('[data-action="toggle-discovered-skills"]');if(!g)return;let v=[...f()?.querySelectorAll("[data-discovered-skill]:not(:disabled)")??[]],M=v.some($=>!$.checked);g.textContent=v.length>0&&!M?s("skills.discoverClearSelection"):s("skills.discoverSelectAll"),g.disabled=v.length===0}function y(){t.querySelector('[data-action="install"]')?.addEventListener("click",async()=>{let g=t.querySelector(".skills-install-panel"),v=o(g),M=t.querySelector('[data-action="install"]'),$=t.querySelector('[data-install="source"]')?.value.trim()??"",L=t.querySelector('[data-install="path"]')?.value.trim()??"",C=t.querySelector('[data-install="ref"]')?.value.trim()??"";try{M&&(M.disabled=!0);let P=await Ft("/api/skills/install",{method:"POST",body:JSON.stringify({source:$,path:L||void 0,ref:C||void 0})});await p(P.job,v)}catch(P){i(v,`${s("skills.failed")}: ${P?.message??P}`,!1)}finally{M&&(M.disabled=!1)}}),t.querySelector('[data-action="discover-native-skills"]')?.addEventListener("click",()=>{t.querySelector("#skills-discovery-dialog")?.showModal(),h()}),t.querySelector('[data-action="close-discovery"]')?.addEventListener("click",()=>{t.querySelector("#skills-discovery-dialog")?.close()}),t.querySelectorAll("[data-discovery-tab]").forEach(g=>{g.addEventListener("click",()=>{let v=g.dataset.discoveryTab??"";vo=v,t.querySelectorAll("[data-discovery-tab]").forEach(L=>{let C=L.dataset.discoveryTab===v;L.classList.toggle("selected",C),L.setAttribute("aria-selected",C?"true":"false")}),t.querySelectorAll("[data-discovery-panel]").forEach(L=>{L.hidden=L.dataset.discoveryPanel!==v});let M=Le.nativeSkillGroups.find(L=>Cn(L)===v),$=t.querySelector(".skills-discovery-path code");$&&M&&($.textContent=M.rootDir),h()})}),t.querySelectorAll("[data-discovered-skill]").forEach(g=>{g.addEventListener("change",h)}),t.querySelector('[data-action="toggle-discovered-skills"]')?.addEventListener("click",()=>{let g=[...f()?.querySelectorAll("[data-discovered-skill]:not(:disabled)")??[]],v=g.some(M=>!M.checked);g.forEach(M=>{M.checked=v}),h()}),t.querySelector('[data-action="register-discovered-skills"]')?.addEventListener("click",async()=>{let g=t.querySelector("#skills-discovery-dialog"),v=t.querySelector(".skills-install-panel"),M=o(v),$=[...t.querySelectorAll("[data-discovered-skill]:checked:not(:disabled)")].map(C=>C.value).filter(Boolean);if($.length===0){i(M,s("skills.discoverNothingSelected"),!1);return}let L=t.querySelector('[data-action="register-discovered-skills"]');try{L&&(L.disabled=!0),i(M,s("skills.discoverRegisteringBatch",{total:$.length}),!0),await Ft("/api/skills/install-local-links",{method:"POST",body:JSON.stringify({sources:$})}),g?.close(),await a()}catch(C){i(M,`${s("skills.failed")}: ${C?.message??C}`,!1)}finally{L&&(L.disabled=!1)}}),t.querySelectorAll("[data-global-project-value]").forEach(g=>g.addEventListener("click",async()=>{let v=g.dataset.globalProjectValue==="all"?"all":"off";if(Le.trustProjectSkills!==v)try{r("[data-global-project-value]",!0);let M=await Ft("/api/skills/global",{method:"PUT",body:JSON.stringify({trustProjectSkills:v})});Le.trustProjectSkills=M.trustProjectSkills==="all"?"all":v,u("[data-global-project-value]","globalProjectValue",Le.trustProjectSkills)}catch(M){window.alert(`${s("skills.failed")}: ${M?.message??M}`)}finally{r("[data-global-project-value]",!1)}})),t.querySelectorAll("[data-global-delivery-value]").forEach(g=>g.addEventListener("click",async()=>{let v=g.dataset.globalDeliveryValue==="prompt"||g.dataset.globalDeliveryValue==="native"?g.dataset.globalDeliveryValue:"auto";if(Le.delivery!==v)try{r("[data-global-delivery-value]",!0);let M=await Ft("/api/skills/global",{method:"PUT",body:JSON.stringify({delivery:v})});Le.delivery=M.delivery==="prompt"||M.delivery==="native"?M.delivery:v,u("[data-global-delivery-value]","globalDeliveryValue",Le.delivery)}catch(M){window.alert(`${s("skills.failed")}: ${M?.message??M}`)}finally{r("[data-global-delivery-value]",!1)}})),t.querySelectorAll('[data-action="scroll-bots"]').forEach(g=>g.addEventListener("click",()=>{let v=t.querySelector(".skills-bot-grid"),M=v?.querySelector(".skills-bot-card");if(!v||!M)return;let $=window.getComputedStyle(v),L=Number.parseFloat($.columnGap||$.gap||"0")||0,C=g.dataset.dir==="-1"?-1:1;v.scrollBy({left:C*(M.getBoundingClientRect().width+L),behavior:"smooth"})})),t.querySelectorAll('[data-action="page-installed-skills"]').forEach(g=>g.addEventListener("click",()=>{let v=g.dataset.dir==="-1"?-1:1;In+=v,ko(),c()})),t.querySelectorAll(".skills-row").forEach(g=>{let v=g.dataset.skill??"";g.querySelector('[data-action="update-skill"]')?.addEventListener("click",async()=>{let M=g.querySelector('[data-action="update-skill"]'),$=t.querySelector(".skills-install-panel"),L=o($);try{M&&(M.disabled=!0);let C=await Ft(`/api/skills/${encodeURIComponent(v)}/update`,{method:"POST",body:"{}"});await p(C.job,L)}catch(C){window.alert(`${s("skills.failed")}: ${C?.message??C}`)}finally{M&&(M.disabled=!1)}}),g.querySelector('[data-action="remove-skill"]')?.addEventListener("click",async()=>{if(window.confirm(`${s("skills.remove")} ${v}?`))try{await Ft(`/api/skills/${encodeURIComponent(v)}`,{method:"DELETE",body:"{}"}),await a()}catch(M){if(M?.status===409&&M?.body?.error==="skill_in_use"){let $=Array.isArray(M.body.affectedBots)?M.body.affectedBots.map(C=>{let P=C?.botName||C?.larkAppId;return P?`${P}`:""}).filter(Boolean):Vp(v),L=[$.length?`Bot: ${$.join(", ")}`:""].filter(Boolean).join("; ")||"-";if(!window.confirm(s("skills.removeInUse",{skill:v,refs:L})))return;try{await Ft(`/api/skills/${encodeURIComponent(v)}?force=1`,{method:"DELETE",body:"{}"}),await a();return}catch(C){window.alert(`${s("skills.failed")}: ${C?.message??C}`);return}}window.alert(`${s("skills.failed")}: ${M?.message??M}`)}})}),t.querySelectorAll(".skills-bot-card").forEach(g=>{let v=g.dataset.appid??"",M=Le.bots.find($=>$.larkAppId===v);M&&(g.querySelector('[data-action="attach-skill"]')?.addEventListener("click",async()=>{let $=g.querySelector("[data-attach-picker]")?.value;if($)try{let L=await Ft(`/api/bots/${encodeURIComponent(v)}/skills`,{method:"PUT",body:JSON.stringify({action:"attach",name:$})});M.skills=L.skills??null,c()}catch(L){i(o(g),`${s("skills.failed")}: ${L?.message??L}`,!1)}}),g.querySelectorAll('[data-action="detach-skill"]').forEach($=>{$.addEventListener("click",async()=>{let L=$.dataset.name;if(L)try{let C=await Ft(`/api/bots/${encodeURIComponent(v)}/skills`,{method:"PUT",body:JSON.stringify({action:"detach",name:L})});M.skills=C.skills??null,c()}catch(C){i(o(g),`${s("skills.failed")}: ${C?.message??C}`,!1)}})}))})}n.onclick=()=>{a()},await a()}var as=4096,cf=/^[A-Za-z0-9._-]{1,64}$/,It=[],$o=[],As=[],Kl=[],Ua=new Map,za=new Map,Jl=!1,Oa="groups",Nt=null,qt=null,yt="",os=new Set,je=null,Lt=null,Ct="",Mn=null;function Yl(e){return cf.test(e)&&e!=="."&&e!==".."}function df(){let[,e=""]=location.hash.split("?");return new URLSearchParams(e).get("chatId")?.trim()||null}function pf(e){let t=e==="profiles";return`<section class="page roles-page">
|
|
1264
|
-
<div class="page-heading roles-heading">
|
|
1265
|
-
<div>
|
|
1266
|
-
<p class="eyebrow">${s("nav.roles")}</p>
|
|
1267
|
-
<h1>${s("roles.title")}</h1>
|
|
1268
|
-
<p>${s("roles.subtitle")}</p>
|
|
1269
|
-
</div>
|
|
1270
|
-
</div>
|
|
1271
|
-
<nav class="wf-subnav roles-subnav">
|
|
1272
|
-
<a href="#/roles" ${t?"":'class="active"'}>${s("roles.tabGroups")}</a>
|
|
1273
|
-
<a href="#/roles/profile" ${t?'class="active"':""}>${s("roles.tabProfiles")}</a>
|
|
1274
|
-
</nav>
|
|
1275
|
-
|
|
1276
|
-
<div id="roles-by-group-view" class="roles-layout" ${t?"hidden":""}>
|
|
1277
|
-
<div class="roles-tree-panel">
|
|
1278
|
-
<div class="roles-tree-header">
|
|
1279
|
-
<input type="search" id="roles-search" placeholder="${s("roles.search")}" />
|
|
1280
|
-
<button type="button" id="roles-refresh">${s("roles.refresh")}</button>
|
|
1281
|
-
</div>
|
|
1282
|
-
<div id="roles-tree" class="roles-tree"></div>
|
|
1283
|
-
</div>
|
|
1284
|
-
<div class="roles-editor-panel">
|
|
1285
|
-
<div id="roles-editor-empty" class="roles-editor-empty">${s("roles.selectHint")}</div>
|
|
1286
|
-
<div id="roles-editor-form" class="roles-editor-form" style="display:none">
|
|
1287
|
-
<div class="roles-editor-breadcrumb">
|
|
1288
|
-
<span id="roles-editor-group-name"></span>
|
|
1289
|
-
<span class="roles-breadcrumb-sep">\u203A</span>
|
|
1290
|
-
<span id="roles-editor-bot-name"></span>
|
|
1291
|
-
</div>
|
|
1292
|
-
<div class="roles-editor-meta">
|
|
1293
|
-
<span id="roles-editor-chat-id" class="roles-editor-meta-line"></span>
|
|
1294
|
-
</div>
|
|
1295
|
-
<textarea id="roles-editor-textarea" placeholder="${s("roles.editorPlaceholder")}" rows="14"></textarea>
|
|
1296
|
-
<div class="roles-editor-footer">
|
|
1297
|
-
<span id="roles-editor-bytecount" class="roles-bytecount"></span>
|
|
1298
|
-
<div class="roles-editor-actions">
|
|
1299
|
-
<button type="button" id="roles-delete" class="danger">${s("roles.delete")}</button>
|
|
1300
|
-
<button type="button" id="roles-save" class="primary">${s("roles.save")}</button>
|
|
1301
|
-
</div>
|
|
1302
|
-
</div>
|
|
1303
|
-
<div id="roles-preview" class="roles-preview"></div>
|
|
1304
|
-
</div>
|
|
1305
|
-
</div>
|
|
1306
|
-
</div>
|
|
1307
|
-
|
|
1308
|
-
<div id="roles-profiles-view" class="roles-layout roles-profiles-layout" ${t?"":"hidden"}>
|
|
1309
|
-
<div class="roles-tree-panel">
|
|
1310
|
-
<div class="roles-tree-header roles-profile-create">
|
|
1311
|
-
<input type="text" id="roles-profile-id" placeholder="${s("roles.profileIdPlaceholder")}" maxlength="64" />
|
|
1312
|
-
<button type="button" id="roles-profile-select">${s("roles.openProfile")}</button>
|
|
1313
|
-
</div>
|
|
1314
|
-
<div class="roles-tree-header">
|
|
1315
|
-
<input type="search" id="roles-profile-search" placeholder="${s("roles.profileSearch")}" />
|
|
1316
|
-
<button type="button" id="roles-profile-refresh">${s("roles.refresh")}</button>
|
|
1317
|
-
</div>
|
|
1318
|
-
<div id="roles-profile-list" class="roles-tree"></div>
|
|
1319
|
-
</div>
|
|
1320
|
-
<div class="roles-editor-panel">
|
|
1321
|
-
<div id="roles-profile-empty" class="roles-editor-empty">${s("roles.profileSelectHint")}</div>
|
|
1322
|
-
<div id="roles-profile-detail" class="roles-editor-form roles-profile-detail" style="display:none"></div>
|
|
1323
|
-
</div>
|
|
1324
|
-
</div>
|
|
1325
|
-
</section>`}async function ss(){let t=await(await fetch("/api/groups")).json();$o=(t.bots??[]).map(n=>({larkAppId:n.larkAppId,botName:n.botName??n.larkAppId,botAvatarUrl:n.botAvatarUrl})),It=(t.chats??[]).map(n=>({chatId:n.chatId,name:n.name??n.chatId,memberBots:(n.memberBots??[]).map(a=>({larkAppId:a.larkAppId,botName:a.botName??a.larkAppId,inChat:a.inChat??!1,hasRole:a.hasRole??!1,oncallChat:a.oncallChat??null}))}))}async function xo(){As=(await(await fetch("/api/role-profiles")).json()).profiles??[]}async function Ds(e){Kl=(await(await fetch(`/api/role-profiles/${encodeURIComponent(e)}`)).json()).entries??[]}async function Ga(e,t){return(await fetch(`/api/roles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).json()}function Zl(e,t){return`${e}\0${t}`}async function ff(){let e=await Promise.all(As.map(async a=>{try{let i=await(await fetch(`/api/role-profiles/${encodeURIComponent(a.profileId)}`)).json().catch(()=>({}));return[a.profileId,Array.isArray(i.entries)?i.entries:[]]}catch{return[a.profileId,[]]}})),t=new Map,n=new Set;await Promise.all(It.flatMap(a=>a.memberBots.filter(o=>o.inChat).map(async o=>{let i=Zl(o.larkAppId,a.chatId);if(!n.has(i)){n.add(i);try{let r=await Ga(o.larkAppId,a.chatId),u=r.hasEffectiveRole??r.hasRole,c="effectiveContent"in r?r.effectiveContent:r.content;t.set(i,{content:u?String(c??""):null,source:r.effectiveSource??(r.hasRole?"chat":"none")})}catch{t.set(i,null)}}}))),Ua=new Map(e),za=t}async function mn(){try{await ff()}catch{Ua=new Map,za=new Map}finally{Jl=!0,Yt(document.getElementById("roles-search")?.value??"")}}async function mf(e,t,n){return(await fetch(`/api/roles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({content:n})})).ok}async function hf(e,t){return(await fetch(`/api/roles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"DELETE"})).ok}async function gf(e,t){return(await fetch(`/api/role-profiles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).json()}async function bf(e,t,n){return(await fetch(`/api/role-profiles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({content:n,allowEmpty:!0})})).ok}async function yf(e,t){return(await fetch(`/api/role-profiles/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:"DELETE"})).ok}function Wa(e){return new TextEncoder().encode(e).length}function Ql(e){return e.memberBots.filter(t=>t.inChat&&t.hasRole).length}function vf(e){return e.memberBots.filter(t=>t.inChat).length}function Fa(e){return Kl.find(t=>t.larkAppId===e)}function Ul(e){Oa=e,document.getElementById("roles-by-group-view")?.toggleAttribute("hidden",e!=="groups"),document.getElementById("roles-profiles-view")?.toggleAttribute("hidden",e!=="profiles")}function wf(e){if(!As.length||!Jl)return"";let t=new Map;for(let o of e.memberBots)o.inChat&&t.set(o.larkAppId,za.get(Zl(o.larkAppId,e.chatId))??null);if(!mo(t))return"";let n=ho(e.memberBots,As,Ua,t)[0];if(!n)return`<div class="roles-profile-match muted">${s("groups.profileStatusUnmatched")}</div>`;let a=n.kind==="full"?"groups.profileStatusFullChat":"groups.profileStatusPartial";return`<div class="roles-profile-match ${n.kind}">
|
|
1326
|
-
${l(s(a,{name:n.profileId,matched:n.matched,total:n.total,chat:n.chatMatched}))}
|
|
1327
|
-
</div>`}function Yt(e=""){let t=document.getElementById("roles-tree");if(!t)return;let n=e.toLowerCase(),a=It.filter(o=>{if(!n)return!0;let i=o.chatId.toLowerCase().includes(n)||(o.name??"").toLowerCase().includes(n),r=o.memberBots.some(u=>u.larkAppId.toLowerCase().includes(n)||(u.botName??"").toLowerCase().includes(n));return i||r});if(a.length===0){t.innerHTML=`<div class="roles-empty">${s("roles.noChats")}</div>`;return}t.innerHTML=a.map(o=>{let i=os.has(o.chatId),r=o.memberBots.filter(h=>h.inChat),u=i?"\u25BE":"\u25B8",c=Ql(o),p=vf(o),f=i?r.map(h=>`
|
|
1328
|
-
<div class="roles-bot-row ${Nt===o.chatId&&qt===h.larkAppId?"selected":""}"
|
|
1329
|
-
data-group-id="${l(o.chatId)}"
|
|
1330
|
-
data-bot-id="${l(h.larkAppId)}">
|
|
1331
|
-
<span class="roles-bot-indent"></span>
|
|
1332
|
-
${Re({name:h.botName,larkAppId:h.larkAppId,size:"sm"})}
|
|
1333
|
-
<div class="roles-bot-info">
|
|
1334
|
-
<div class="roles-bot-name">${l(h.botName)}</div>
|
|
1335
|
-
<div class="roles-bot-id">${l(h.larkAppId)}</div>
|
|
1336
|
-
</div>
|
|
1337
|
-
<span class="roles-badge ${h.hasRole?"has-role":"no-role"}">
|
|
1338
|
-
${h.hasRole?s("roles.configured"):s("roles.unconfigured")}
|
|
1339
|
-
</span>
|
|
1340
|
-
</div>`).join(""):"";return`
|
|
1341
|
-
<div class="roles-group-section">
|
|
1342
|
-
<div class="roles-group-row ${i?"expanded":""} ${Nt===o.chatId&&!qt?"selected":""}"
|
|
1343
|
-
data-group-id="${l(o.chatId)}">
|
|
1344
|
-
<span class="roles-group-arrow">${u}</span>
|
|
1345
|
-
<span class="roles-group-icon" aria-hidden="true"><svg viewBox="0 0 16 16"><circle cx="5.6" cy="5.8" r="2.4"/><path d="M1.8 13.2c.5-2.4 2-3.6 3.8-3.6s3.3 1.2 3.8 3.6"/><circle cx="11" cy="6.8" r="1.9"/><path d="M9.8 12.6c.4-1.7 1.5-2.6 2.8-2.6 1 0 1.9.5 2.4 1.6"/></svg></span>
|
|
1346
|
-
<div class="roles-group-info">
|
|
1347
|
-
<div class="roles-group-name">${l(o.name??o.chatId)}</div>
|
|
1348
|
-
<div class="roles-group-meta">
|
|
1349
|
-
${c}/${p} ${s("roles.botsWithRoles")}
|
|
1350
|
-
</div>
|
|
1351
|
-
${wf(o)}
|
|
1352
|
-
</div>
|
|
1353
|
-
<span class="roles-group-chevron"></span>
|
|
1354
|
-
</div>
|
|
1355
|
-
<div class="roles-bot-list">${f}</div>
|
|
1356
|
-
</div>`}).join(""),t.querySelectorAll(".roles-group-row").forEach(o=>{o.addEventListener("click",()=>{let i=o.dataset.groupId;i&&(os.has(i)?os.delete(i):os.add(i),Yt(document.getElementById("roles-search")?.value??""))})}),t.querySelectorAll(".roles-bot-row").forEach(o=>{o.addEventListener("click",i=>{i.stopPropagation();let r=o.dataset.groupId,u=o.dataset.botId;r&&u&&kf(r,u)})})}async function kf(e,t){Nt=e,qt=t;let n=await Ga(t,e),a=document.getElementById("roles-editor-empty"),o=document.getElementById("roles-editor-form"),i=document.getElementById("roles-editor-textarea"),r=document.getElementById("roles-editor-group-name"),u=document.getElementById("roles-editor-bot-name"),c=document.getElementById("roles-editor-chat-id");a&&(a.style.display="none"),o&&(o.style.display="");let p=It.find(y=>y.chatId===e),f=p?.memberBots.find(y=>y.larkAppId===t);r&&(r.textContent=p?.name??e),u&&(u.textContent=f?.botName??t),c&&(c.textContent=`${e} \xB7 ${t}`),yt=n.content??"",i&&(i.value=yt,i.focus()),Na(),qa(),Yt(document.getElementById("roles-search")?.value??"");let h=document.getElementById("roles-delete");h&&(h.style.display=n.hasRole?"":"none")}function Na(){let e=document.getElementById("roles-editor-bytecount");if(!e)return;let t=Wa(yt);e.textContent=`${t} / ${as} bytes`,e.className=`roles-bytecount ${t>3800?"warn":""} ${t>as?"over":""}`,$f(t)}function $f(e){let t=document.getElementById("roles-save");if(!t)return;let n=e??Wa(yt);t.disabled=n>as||yt.trim().length===0}function qa(){let e=document.getElementById("roles-preview");e&&(yt.trim()?e.innerHTML=`<strong>${s("roles.preview")}</strong><pre>${l(yt)}</pre>`:e.innerHTML=`<small>${s("roles.previewEmpty")}</small>`)}function zl(){Nt=null,qt=null,yt="";let e=document.getElementById("roles-editor-empty"),t=document.getElementById("roles-editor-form"),n=document.getElementById("roles-editor-textarea"),a=document.getElementById("roles-delete");e&&(e.style.display=""),t&&(t.style.display="none"),n&&(n.value=""),a&&(a.style.display="none")}function is(e=""){let t=document.getElementById("roles-profile-list");if(!t)return;let n=e.toLowerCase(),a=As.filter(o=>!n||o.profileId.toLowerCase().includes(n));if(a.length===0){t.innerHTML=`<div class="roles-empty">${s("roles.profileEmpty")}</div>`;return}t.innerHTML=a.map(o=>{let i=je===o.profileId,r=(o.botEntries??[]).some(u=>u.hasEntry);return`
|
|
1357
|
-
<div class="roles-profile-row ${i?"selected":""}" data-profile-id="${l(o.profileId)}">
|
|
1358
|
-
<div class="roles-profile-row-main">
|
|
1359
|
-
<div class="roles-profile-name">${l(o.profileId)}</div>
|
|
1360
|
-
<div class="roles-group-meta">${o.entryCount} ${s("roles.profileEntries")}</div>
|
|
1361
|
-
</div>
|
|
1362
|
-
<span class="roles-badge ${r?"has-role":"no-role"}">${r?s("roles.configured"):s("roles.profileMissing")}</span>
|
|
1363
|
-
</div>`}).join(""),t.querySelectorAll(".roles-profile-row").forEach(o=>{o.addEventListener("click",()=>{let i=o.dataset.profileId;i&&ja(i)})})}async function ja(e){Yl(e.trim())&&(je=e.trim(),Lt=null,Ct="",Mn=Mn??It[0]?.chatId??null,await Ds(je),is(document.getElementById("roles-profile-search")?.value??""),Hs())}function Hs(){let e=document.getElementById("roles-profile-empty"),t=document.getElementById("roles-profile-detail");if(!e||!t)return;if(!je){e.style.display="",t.style.display="none",t.innerHTML="";return}e.style.display="none",t.style.display="";let n=$o.find(o=>o.larkAppId===Lt),a=Lt?Fa(Lt):void 0;t.innerHTML=`
|
|
1364
|
-
<div class="roles-profile-title">
|
|
1365
|
-
<div>
|
|
1366
|
-
<div class="roles-editor-breadcrumb">
|
|
1367
|
-
<span>${l(je)}</span>
|
|
1368
|
-
${n?`<span class="roles-breadcrumb-sep">\u203A</span><span>${l(n.botName??n.larkAppId)}</span>`:""}
|
|
1369
|
-
</div>
|
|
1370
|
-
<div class="roles-editor-meta-line">${s("roles.profileRuntimeHint")}</div>
|
|
1371
|
-
</div>
|
|
1372
|
-
</div>
|
|
1373
|
-
<div class="roles-profile-grid">
|
|
1374
|
-
<div class="roles-profile-bots">
|
|
1375
|
-
<div class="roles-profile-section-title">${s("roles.profileBots")}</div>
|
|
1376
|
-
<div class="roles-profile-bot-list">
|
|
1377
|
-
${$o.map(o=>{let i=!!Fa(o.larkAppId);return`
|
|
1378
|
-
<div class="roles-bot-row roles-profile-bot-row ${Lt===o.larkAppId?"selected":""}" data-profile-bot-id="${l(o.larkAppId)}">
|
|
1379
|
-
${Re({name:o.botName,larkAppId:o.larkAppId,size:"sm"})}
|
|
1380
|
-
<div class="roles-bot-info">
|
|
1381
|
-
<div class="roles-bot-name">${l(o.botName??o.larkAppId)}</div>
|
|
1382
|
-
<div class="roles-bot-id">${l(o.larkAppId)}</div>
|
|
1383
|
-
</div>
|
|
1384
|
-
<span class="roles-badge ${i?"has-role":"no-role"}">${i?s("roles.configured"):s("roles.unconfigured")}</span>
|
|
1385
|
-
</div>`}).join("")}
|
|
1386
|
-
</div>
|
|
1387
|
-
</div>
|
|
1388
|
-
<div class="roles-profile-editor">
|
|
1389
|
-
${Lt?`
|
|
1390
|
-
<textarea id="roles-profile-textarea" placeholder="${s("roles.profileEditorPlaceholder")}" rows="12">${l(Ct||a?.content||"")}</textarea>
|
|
1391
|
-
<div class="roles-editor-footer">
|
|
1392
|
-
<span id="roles-profile-bytecount" class="roles-bytecount"></span>
|
|
1393
|
-
<div class="roles-editor-actions">
|
|
1394
|
-
<button type="button" id="roles-profile-delete" class="danger" ${a?"":'style="display:none"'}>${s("roles.delete")}</button>
|
|
1395
|
-
<button type="button" id="roles-profile-save" class="primary">${s("roles.saveEntry")}</button>
|
|
1396
|
-
</div>
|
|
1397
|
-
</div>
|
|
1398
|
-
<div id="roles-profile-preview" class="roles-preview"></div>
|
|
1399
|
-
`:`<div class="roles-editor-empty roles-profile-inline-empty">${s("roles.profileBotSelectHint")}</div>`}
|
|
1400
|
-
</div>
|
|
1401
|
-
</div>
|
|
1402
|
-
<div class="roles-profile-apply">
|
|
1403
|
-
<div class="roles-profile-section-title">${s("roles.applyToGroup")}</div>
|
|
1404
|
-
<div class="roles-profile-apply-controls">
|
|
1405
|
-
<select id="roles-profile-apply-group">
|
|
1406
|
-
${It.map(o=>`<option value="${l(o.chatId)}" ${Mn===o.chatId?"selected":""}>${l(o.name??o.chatId)}</option>`).join("")}
|
|
1407
|
-
</select>
|
|
1408
|
-
<label class="roles-profile-force"><input type="checkbox" id="roles-profile-apply-force"> ${s("roles.applyForce")}</label>
|
|
1409
|
-
</div>
|
|
1410
|
-
<div id="roles-profile-apply-bots"></div>
|
|
1411
|
-
<div class="roles-editor-actions">
|
|
1412
|
-
<button type="button" id="roles-profile-preview-apply">${s("roles.previewApply")}</button>
|
|
1413
|
-
<button type="button" id="roles-profile-apply" class="primary">${s("roles.applyProfile")}</button>
|
|
1414
|
-
</div>
|
|
1415
|
-
<div id="roles-profile-apply-status" class="roles-profile-status"></div>
|
|
1416
|
-
</div>
|
|
1417
|
-
`,t.querySelectorAll(".roles-profile-bot-row").forEach(o=>{o.addEventListener("click",()=>{let i=o.dataset.profileBotId;i&&xf(i)})}),Xl(),Sf()}async function xf(e){if(!je)return;Lt=e,Ct=(await gf(je,e)).content??"",await Ds(je),Hs()}function Sf(){let e=document.getElementById("roles-profile-textarea");e&&(Ct=e.value,Gl(),Wl(),e.addEventListener("input",t=>{Ct=t.target.value,Gl(),Wl()})),document.getElementById("roles-profile-save")?.addEventListener("click",async function(){if(!(!je||!Lt)){this.disabled=!0,this.textContent="...";try{let t=await bf(je,Lt,Ct);await xo(),await Ds(je),is(document.getElementById("roles-profile-search")?.value??""),mn(),Hs(),Ef(t?s("roles.saved"):s("roles.saveFailed"),!t)}finally{this.disabled=!1,this.textContent=s("roles.saveEntry")}}}),document.getElementById("roles-profile-delete")?.addEventListener("click",async function(){if(!(!je||!Lt)&&confirm(s("roles.confirmDeleteProfileEntry"))){this.disabled=!0;try{await yf(je,Lt),Ct="",await xo(),await Ds(je),is(document.getElementById("roles-profile-search")?.value??""),mn(),Hs()}finally{this.disabled=!1}}}),document.getElementById("roles-profile-apply-group")?.addEventListener("change",t=>{Mn=t.target.value,Xl()}),document.getElementById("roles-profile-preview-apply")?.addEventListener("click",()=>Vl(!0)),document.getElementById("roles-profile-apply")?.addEventListener("click",()=>Vl(!1))}function Gl(){let e=document.getElementById("roles-profile-bytecount"),t=document.getElementById("roles-profile-save");if(!e)return;let n=Wa(Ct);e.textContent=`${n} / ${as} bytes`,e.className=`roles-bytecount ${n>3800?"warn":""} ${n>as?"over":""}`,t&&(t.disabled=n>as||Ct.trim().length===0)}function Wl(){let e=document.getElementById("roles-profile-preview");e&&(e.innerHTML=Ct.trim()?`<strong>${s("roles.preview")}</strong><pre>${l(Ct)}</pre>`:`<small>${s("roles.previewEmpty")}</small>`)}function Xl(){let e=document.getElementById("roles-profile-apply-bots");if(!e)return;let t=Mn??It[0]?.chatId??"",n=It.find(o=>o.chatId===t),a=n?.memberBots.filter(o=>o.inChat)??[];if(!n||a.length===0){e.innerHTML=`<div class="roles-empty">${s("roles.noChats")}</div>`;return}e.innerHTML=a.map(o=>{let i=!!Fa(o.larkAppId);return`
|
|
1418
|
-
<label class="checkbox-row roles-profile-apply-bot">
|
|
1419
|
-
<input type="checkbox" name="profile-apply-bot" value="${l(o.larkAppId)}" ${i?"checked":""}>
|
|
1420
|
-
<span>${l(o.botName??o.larkAppId)}</span>
|
|
1421
|
-
<small>${i?s("roles.configured"):s("roles.profileMissing")}</small>
|
|
1422
|
-
</label>`}).join("")}async function Vl(e){let t=je;if(!t)return;let n=Mn??It[0]?.chatId;if(!n)return;let a=document.getElementById("roles-profile-apply-force")?.checked===!0,o=[...document.querySelectorAll("input[name=profile-apply-bot]:checked")].map(u=>u.value),i=document.getElementById("roles-profile-apply-status");if(o.length===0){i&&(i.textContent=s("roles.applyPickBots"));return}i&&(i.textContent="...");let r=await Promise.all(o.map(async u=>{let c=await fetch(`/api/role-profiles/${encodeURIComponent(t)}/apply`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({chatId:n,larkAppId:u,force:a,preview:e})}),p=await c.json().catch(()=>({}));return{larkAppId:u,ok:c.ok&&p.ok!==!1,status:c.status,error:p.error,wouldRefuse:p.wouldRefuse}}));i&&(i.innerHTML=r.map(u=>{let c=$o.find(h=>h.larkAppId===u.larkAppId),p=l(c?.botName??u.larkAppId),f=u.ok?e?u.wouldRefuse?s("roles.applyWouldRefuse"):s("roles.applyPreviewOk"):s("roles.applyOk"):`${s("roles.applyFailed")}: ${l(u.error??`HTTP ${u.status}`)}`;return`<div>${p}: ${f}</div>`}).join("")),e||(await ss(),Yt(document.getElementById("roles-search")?.value??""),mn())}function Ef(e,t=!1){let n=document.querySelector("#roles-profile-detail .roles-editor-footer");if(!n)return;let a=document.createElement("span");a.className=`roles-saved-flash ${t?"roles-save-error":""}`,a.textContent=` ${e}`,n.appendChild(a),setTimeout(()=>a.remove(),t?3e3:2e3)}async function eu(e,t){Oa=t,e.innerHTML=pf(t),os.clear(),zl(),Ul(Oa);let n=document.getElementById("roles-tree"),a=document.getElementById("roles-profile-list");if(n&&(n.innerHTML=Tt()),a&&(a.innerHTML=Tt()),await ss(),await xo(),await bt(),t==="profiles"){let o=df();o&&It.some(i=>i.chatId===o)&&(Mn=o)}for(let o of It)Ql(o)>0&&os.add(o.chatId);Yt(),is(),je&&await ja(je),mn(),document.getElementById("roles-search")?.addEventListener("input",o=>{Yt(o.target.value)}),document.getElementById("roles-refresh")?.addEventListener("click",async()=>{if(await ss(),Yt(document.getElementById("roles-search")?.value??""),mn(),Nt&&qt){let o=await Ga(qt,Nt),i=document.getElementById("roles-editor-textarea");i&&(i.value=o.content??""),yt=o.content??"",Na(),qa();let r=document.getElementById("roles-delete");r&&(r.style.display=o.hasRole?"":"none")}}),document.getElementById("roles-save")?.addEventListener("click",async function(){if(!(!Nt||!qt)){this.disabled=!0,this.textContent="...";try{if(await mf(qt,Nt,yt)){await ss(),Yt(document.getElementById("roles-search")?.value??""),mn();let i=document.getElementById("roles-delete");i&&(i.style.display="");let r=document.createElement("span");r.className="roles-saved-flash",r.textContent=` ${s("roles.saved")}`,document.querySelector(".roles-editor-footer")?.appendChild(r),setTimeout(()=>r.remove(),2e3)}else{let i=document.createElement("span");i.className="roles-saved-flash roles-save-error",i.textContent=yt.trim().length===0?` ${s("roles.emptyError")}`:` ${s("roles.saveFailed")}`,document.querySelector(".roles-editor-footer")?.appendChild(i),setTimeout(()=>i.remove(),3e3)}}finally{this.disabled=!1,this.textContent=s("roles.save")}}}),document.getElementById("roles-delete")?.addEventListener("click",async function(){if(!(!Nt||!qt)&&confirm(s("roles.confirmDelete"))){this.disabled=!0,this.textContent="...";try{await hf(qt,Nt)&&(await ss(),zl(),Yt(document.getElementById("roles-search")?.value??""),mn())}finally{this.disabled=!1,this.textContent=s("roles.delete")}}}),document.getElementById("roles-editor-textarea")?.addEventListener("input",o=>{yt=o.target.value,Na(),qa()}),document.getElementById("roles-profile-search")?.addEventListener("input",o=>{is(o.target.value)}),document.getElementById("roles-profile-refresh")?.addEventListener("click",async()=>{await ss(),await xo(),mn(),je&&await Ds(je),is(document.getElementById("roles-profile-search")?.value??""),Hs()}),document.getElementById("roles-profile-select")?.addEventListener("click",async()=>{let o=document.getElementById("roles-profile-id"),i=o?.value.trim();if(i){if(!Yl(i)){o?.setCustomValidity(s("roles.profileIdInvalid")),o?.reportValidity();return}o?.setCustomValidity(""),await ja(i),location.hash.startsWith("#/roles/profile")?Ul("profiles"):location.hash="#/roles/profile"}}),document.getElementById("roles-profile-id")?.addEventListener("input",o=>{o.target.setCustomValidity("")})}async function tu(e){await eu(e,"groups")}async function nu(e){await eu(e,"profiles")}async function To(e){let t=await fetch(e);return{status:t.status,body:await t.json().catch(()=>({}))}}async function Lo(e,t,n){let a=await fetch(t,{method:e,headers:{"content-type":"application/json"},body:n?JSON.stringify(n):void 0});return{status:a.status,body:await a.json().catch(()=>({}))}}var Dn=(e,t)=>Lo("POST",e,t),Tf=(e,t)=>Lo("PUT",e,t),Va=[],su=[],ou="",So="",Ka=new Map,Eo=new Map,_s=new Set,Rs=new Set;function Ce(e){return document.getElementById(e)}function Co(){return[...Va,...su]}function An(e){let t=Ka.get(e);return t||(t=new Set,Ka.set(e,t)),t}function Lf(e){return Co().find(t=>t.key===e)}function au(e){let t=(n,a,o)=>`<a href="${n}" style="padding:6px 14px;border-radius:8px;text-decoration:none;font-size:14px;font-weight:600;${o?"background:var(--accent);color:var(--on-accent)":"color:var(--muted);background:var(--surface-muted)"}">${a}</a>`;return`<div style="display:flex;gap:8px;margin-bottom:14px">${t("#/team",s("team.navHome"),e==="home")}${t("#/team/manage",s("team.navManage"),e==="manage")}</div>`}function Cf(){return`<section class="page">
|
|
1423
|
-
<div class="page-heading"><div>
|
|
1424
|
-
<p class="eyebrow">${s("team.eyebrow")}</p><h1>${s("team.homeTitle")}</h1>
|
|
1425
|
-
<p class="tf-lede">${s("team.homeLede")}</p>
|
|
1426
|
-
</div></div>
|
|
1427
|
-
${au("home")}
|
|
1428
|
-
<div class="card" style="margin-bottom:16px">
|
|
1429
|
-
<h2 style="margin-top:0">${s("team.localDeployTitle")}</h2>
|
|
1430
|
-
<p>${s("team.myIdentity")}<b id="tf-owner">${s("team.unbound")}</b>
|
|
1431
|
-
<button id="tf-autobind" class="primary" style="margin-left:8px">${s("team.bindBtn")}</button>
|
|
1432
|
-
<span class="muted" style="font-size:13px">${s("team.bindHint")}</span></p>
|
|
1433
|
-
<div id="tf-bind-out" style="display:none;margin-top:6px"></div>
|
|
1434
|
-
</div>
|
|
1435
|
-
<div class="card">
|
|
1436
|
-
<h2 style="margin-top:0">${s("team.myTeams")} <span class="muted" id="tf-count" style="font-size:13px"></span></h2>
|
|
1437
|
-
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:8px;font-size:13px">
|
|
1438
|
-
<input id="tf-search" placeholder="${s("team.searchPh")}" style="padding:5px 9px;min-width:180px">
|
|
1439
|
-
<select id="tf-cli" style="padding:5px"><option value="">${s("team.allCli")}</option></select>
|
|
1440
|
-
<label><input type="checkbox" id="tf-fcap"> ${s("team.hasCap")}</label>
|
|
1441
|
-
<label><input type="checkbox" id="tf-frole"> ${s("team.hasRole")}</label>
|
|
1442
|
-
</div>
|
|
1443
|
-
<p class="muted" style="font-size:13px;margin:0 0 4px">${s("team.teamsHint")}</p>
|
|
1444
|
-
<div id="tf-teams">${s("team.loading")}</div>
|
|
1445
|
-
</div>
|
|
1446
|
-
<div id="tf-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);align-items:center;justify-content:center;z-index:50">
|
|
1447
|
-
<div style="background:var(--surface);color:var(--fg);border:1px solid var(--border);border-radius:10px;padding:18px 20px;width:min(560px,92vw)">
|
|
1448
|
-
<h2 id="tf-modal-title" style="margin-top:0">${s("team.roleModalTitle")}</h2>
|
|
1449
|
-
<p class="muted" style="font-size:13px">${s("team.roleModalHint")}</p>
|
|
1450
|
-
<textarea id="tf-modal-text" readonly style="width:100%;min-height:200px;font:13px/1.5 ui-monospace,Menlo,monospace;padding:10px;box-sizing:border-box"></textarea>
|
|
1451
|
-
<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:12px">
|
|
1452
|
-
<button id="tf-modal-cancel">${s("team.close")}</button>
|
|
1453
|
-
</div>
|
|
1454
|
-
</div>
|
|
1455
|
-
</div>
|
|
1456
|
-
</section>`}function If(e){let t=(Ce("tf-search").value||"").trim().toLowerCase();if(t&&!((e.name||"")+" "+(e.cliId||"")+" "+(e.capability||"")).toLowerCase().includes(t))return!1;let n=Ce("tf-cli").value;return!(n&&e.cliId!==n||Ce("tf-fcap").checked&&!e.capability||Ce("tf-frole").checked&&!e.hasTeamRole)}function Mf(e,t){let n=[...e.deployments].sort((o,i)=>o.local===i.local?0:o.local?-1:1),a="";for(let o of n){let i=t.filter(y=>y.deployment.id===o.id);if(!i.length)continue;let r=o.id===ou,u=r?s("team.tagLocal"):o.stale?s("team.tagRemoteStale"):s("team.tagRemote"),c=e.kind==="local"&&!r?` <button class="tf-rmmember ghost" data-team="${l(e.teamId)}" data-dep="${l(o.id)}" data-name="${l(o.name)}" style="font-size:12px">${s("team.removeMember")}</button>`:"",p=`${e.key}::${o.id}`,f=Rs.has(p),h=i.filter(y=>An(e.key).has(y.larkAppId)).length;if(a+=`<div class="tf-dep-h" data-dk="${l(p)}" style="cursor:pointer;margin:10px 0 2px"><b>${f?"\u25BE":"\u25B8"} ${l(o.name)}</b> <span class="muted" style="font-size:12px">${s("team.depTag",{tag:u})} \xB7 ${s("team.depCount",{count:i.length})}${h?s("team.depSelected",{n:h}):""}</span>${c}</div>`,!!f){a+='<table style="width:100%;border-collapse:collapse;font-size:14px"><tbody>';for(let y of i){let g=l(y.larkAppId),v=An(e.key).has(y.larkAppId)?" checked":"",M=y.deployment.stale?"opacity:.55":"",$=r?`<input class="tf-cap" data-app="${g}" value="${l(y.capability||"")}" placeholder="${s("team.capPh")}" style="width:92%;padding:3px 6px">`:y.capability?l(y.capability):'<span class="muted">\u2014</span>',L=y.hasTeamRole?r?`<button class="tf-role" data-app="${g}" data-name="${l(y.name)}">${s("team.viewRole")}</button>`:s("team.hasRoleShort"):'<span class="muted">\u2014</span>';a+=`<tr style="${M}"><td style="padding:4px 8px"><input type="checkbox" class="tf-pick" data-tk="${l(e.key)}" data-app="${g}"${v}></td><td style="padding:4px 8px">${l(y.name)}</td><td style="padding:4px 8px" class="muted">${l(y.cliId)}</td><td style="padding:4px 8px">${$}</td><td style="padding:4px 8px">${L}</td></tr>`}a+="</tbody></table>"}}return a||(a=`<p class="muted" style="margin:8px 0 0">${s("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="${l(e.key)}" value="${l(Eo.get(e.key)||"")}" placeholder="${s("team.gnamePh")}" style="min-width:200px"><button class="tf-grp primary" data-tk="${l(e.key)}">${s("team.pullGroupBtn")}</button><span class="muted" style="font-size:13px">${s("team.pullGroupHint")}</span><span class="tf-gout" data-tk="${l(e.key)}" style="font-size:13px;display:block;flex-basis:100%"></span></div>`,a}function hn(){let e=Ce("tf-teams"),t=Co();if(!t.length){e.innerHTML=`<p class="muted">${s("team.noTeams")}</p>`,Ce("tf-count").textContent="";return}let n="",a=new Set,o=new Set;for(let u of t){let c=u.bots.filter(If);c.forEach(y=>a.add(y.larkAppId)),u.bots.forEach(y=>o.add(y.larkAppId));let p=new Set(c.map(y=>y.larkAppId));[...An(u.key)].forEach(y=>{p.has(y)||An(u.key).delete(y)});let f=!_s.has(u.key),h=u.kind==="remote"?u.ok?` <span class="ok" style="font-size:12px">${s("team.connected")}</span>`:` <span class="err" style="font-size:12px">${s("team.connectFail",{error:l(u.error||"")})}</span>`:` <span class="muted" style="font-size:12px">${s("team.iHost")}</span>`;n+=`<div class="card" style="margin:0 0 12px;padding:12px 14px;background:var(--bg-soft,#f6f7f9)"><div class="tf-team-h" data-tk="${l(u.key)}" style="cursor:pointer;display:flex;align-items:center;gap:8px;flex-wrap:wrap"><b style="font-size:15px">${f?"\u25B8":"\u25BE"} ${l(u.label)}</b>`+(u.sub?` <span class="muted" style="font-size:12px">${l(u.sub)}</span>`:"")+h+` <span class="muted" style="font-size:12px">\xB7 ${s("team.teamMeta",{deps:u.deployments.length,bots:u.bots.length})}</span></div>`,f||(n+=u.kind==="remote"&&!u.ok?`<p class="muted" style="margin:8px 0 0">${s("team.rosterFail")}</p>`:Mf(u,c)),n+="</div>"}e.innerHTML=n;let i=t.length>1?s("team.acrossTeams",{n:t.length}):"",r=a.size===o.size?`${o.size}`:`${a.size} / ${o.size}`;Ce("tf-count").textContent=`\xB7 ${r} ${s("team.botsWord")}${i}`,Af()}function Af(){let e=Ce("tf-teams");e.querySelectorAll(".tf-team-h").forEach(t=>{t.onclick=()=>{let n=t.dataset.tk;_s.has(n)?_s.delete(n):_s.add(n),hn()}}),e.querySelectorAll(".tf-dep-h").forEach(t=>{t.onclick=()=>{let n=t.dataset.dk;Rs.has(n)?Rs.delete(n):Rs.add(n),hn()}}),e.querySelectorAll(".tf-pick").forEach(t=>{t.onchange=()=>{let n=An(t.dataset.tk);t.checked?n.add(t.dataset.app):n.delete(t.dataset.app)}}),e.querySelectorAll(".tf-gname").forEach(t=>{t.oninput=()=>{Eo.set(t.dataset.tk,t.value)}}),e.querySelectorAll(".tf-cap").forEach(t=>{t.onchange=async()=>{let n=t.dataset.app,a=t.value;await Tf("/api/team/local-bots/"+encodeURIComponent(n)+"/capability",{capability:a}),Co().forEach(o=>{let i=o.bots.find(r=>r.larkAppId===n);i&&(i.capability=a.trim()||null)})}}),e.querySelectorAll(".tf-role").forEach(t=>{t.onclick=()=>Hf(t.dataset.app,t.dataset.name||"")}),e.querySelectorAll(".tf-rmmember").forEach(t=>{t.onclick=async n=>{n.stopPropagation(),confirm(s("team.removeMemberConfirm",{name:t.dataset.name||""}))&&(await Lo("DELETE",`/api/team/hosted/${encodeURIComponent(t.dataset.team)}/members/${encodeURIComponent(t.dataset.dep)}`),Ps())}}),e.querySelectorAll(".tf-grp").forEach(t=>{t.onclick=async()=>{let n=t.dataset.tk,a=Lf(n);if(!a)return;let o=[...An(n)],i=e.querySelector(`.tf-gout[data-tk="${CSS.escape(n)}"]`);if(!o.length){i.innerHTML=`<span class="err">${s("team.errPickBot")}</span>`;return}let r=(e.querySelector(`.tf-gname[data-tk="${CSS.escape(n)}"]`)?.value||"").trim()||s("team.defaultGroupName");i.innerHTML=`<span class="muted">${s("team.creatingGroup")}</span>`;let u=a.kind==="local"?await Dn("/api/team/federated-group",{name:r,larkAppIds:o,teamId:a.teamId}):await Dn("/api/team/remote-group",{hubUrl:a.hubUrl,teamId:a.teamId,name:r,larkAppIds:o});if(Df(i,u.body,u.status),u.body?.ok){An(n).clear(),Eo.delete(n);let c=i.innerHTML,p=()=>{let f=e.querySelector(`.tf-gout[data-tk="${CSS.escape(n)}"]`);f&&(f.innerHTML=c)};a.kind==="local"?Ps().then(p):(hn(),p())}}})}function Df(e,t,n){if(t?.ok&&t.chatId){let a=t.shareLink||"https://applink.feishu.cn/client/chat/open?openChatId="+encodeURIComponent(t.chatId),o=(t.invalidBotIds||[]).length?` <span class="err"> \xB7 ${s("team.invalidBots",{ids:l((t.invalidBotIds||[]).join(", "))})}</span>`:"",i=(t.invalidOwnerUnionIds||[]).length?`<span class="err"> \xB7 ${s("team.invalidOwners",{n:(t.invalidOwnerUnionIds||[]).length})}</span>`:"",r=t.missingOperatorIdentity?`<span class="err"> \xB7 ${s("team.missingIdentity")}</span>`:"",u=(t.skippedNoOwner||[]).length?`<span class="err"> \xB7 ${s("team.skippedNoOwner",{n:(t.skippedNoOwner||[]).length})}</span>`:"",c=t.delegatedTo?s("team.delegatedBy",{name:l(t.delegatedTo)}):"";e.innerHTML=`<span class="ok">${s("team.groupCreated")}</span>${c} \xB7 <a href="${l(a)}" target="_blank">${s("team.openInLark")}</a>${o}${i}${r}${u}`}else{let a=t?.error||n,o=a==="no_local_online_bot"?s("team.errNoLocalBot"):a==="all_bots_skipped_no_owner"?s("team.errAllSkipped"):a==="no_creator_available"?s("team.errNoCreator"):a==="delegation_timeout"?s("team.errDelegationTimeout"):s("team.errGroupCreate",{error:String(a)});e.innerHTML=`<span class="err">${l(String(o))}</span>`}}async function Hf(e,t){let n=await To("/api/team/local-bots/"+encodeURIComponent(e)+"/role");Ce("tf-modal-title").textContent=s("team.roleModalTitleName",{name:t}),Ce("tf-modal-text").value=n.body?.role||"",Ce("tf-modal").dataset.app=e,Ce("tf-modal").style.display="flex"}function iu(){let e=Array.from(new Set(Co().flatMap(a=>a.bots.map(o=>o.cliId)).filter(Boolean))).sort(),t=Ce("tf-cli"),n=t.value;t.innerHTML=`<option value="">${s("team.allCli")}</option>`+e.map(a=>`<option value="${l(a)}">${l(a)}</option>`).join(""),t.value=n}async function Ps(){let t=(await To("/api/team/hosted")).body;if(!t?.ok){Va=[],hn();return}ou=t.deployment.deploymentId,So=t.suggestedHubUrl||"",Ce("tf-owner").textContent=t.deployment.ownerName||(t.deployment.ownerUnionId?s("team.bound"):s("team.unbound")),Va=(t.teams||[]).map(n=>({kind:"local",key:`local:${n.teamId}`,teamId:n.teamId,label:n.isDefault?s("team.myHostedTeam"):n.name,sub:"",ok:!0,deployments:n.deployments||[],bots:n.bots||[]})),iu(),hn()}async function _f(){su=((await To("/api/team/remote-roster")).body?.memberships||[]).map(n=>{let a=n.roster?.deployments||[],o=a.find(r=>r.local),i=o?.name?s("team.remoteTeamLabel",{name:o.name}):n.teamName||n.teamId;return{kind:"remote",key:`${n.hubUrl}::${n.teamId}`,teamId:n.teamId,label:i,sub:n.hubUrl,ok:!!n.ok,error:n.error,hubUrl:n.hubUrl,deployments:a,bots:n.roster?.bots||[]}}),iu(),hn()}function ru(e){e.innerHTML=Cf(),Ka.clear(),Eo.clear(),_s.clear(),Rs.clear(),["tf-search","tf-cli","tf-fcap","tf-frole"].forEach(t=>{let n=Ce(t);n.oninput=hn,n.onchange=hn}),Ce("tf-modal-cancel").onclick=()=>{Ce("tf-modal").style.display="none"},Pf(),Ps(),_f()}function Rf(){return`<section class="page">
|
|
1457
|
-
<div class="page-heading"><div>
|
|
1458
|
-
<p class="eyebrow">${s("team.eyebrow")}</p><h1>${s("team.manageTitle")}</h1>
|
|
1459
|
-
<p class="tf-lede">${s("team.manageLede")}</p>
|
|
1460
|
-
</div></div>
|
|
1461
|
-
${au("manage")}
|
|
1462
|
-
<div class="card" style="margin-bottom:16px">
|
|
1463
|
-
<h2 style="margin-top:0">${s("team.hostedTitle")}</h2>
|
|
1464
|
-
<p style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:6px">
|
|
1465
|
-
<input id="tm-newname" placeholder="${s("team.newTeamPh")}" style="min-width:200px">
|
|
1466
|
-
<button id="tm-create" class="primary">${s("team.createTeamBtn")}</button>
|
|
1467
|
-
<span class="muted tm-cout" style="font-size:13px"></span>
|
|
1468
|
-
</p>
|
|
1469
|
-
<div id="tm-list">${s("team.loading")}</div>
|
|
1470
|
-
</div>
|
|
1471
|
-
<div class="card">
|
|
1472
|
-
<h2 style="margin-top:0">${s("team.joinTitle")}</h2>
|
|
1473
|
-
<p style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
|
|
1474
|
-
<input id="tm-hub" placeholder="${s("team.hubPh")}" style="flex:1;min-width:240px">
|
|
1475
|
-
<input id="tm-code" placeholder="${s("team.codePh")}" style="min-width:160px">
|
|
1476
|
-
<button id="tm-join" class="primary">${s("team.joinBtn")}</button>
|
|
1477
|
-
</p>
|
|
1478
|
-
<div id="tm-join-out" style="display:none;margin-top:6px"></div>
|
|
1479
|
-
</div>
|
|
1480
|
-
</section>`}async function Ja(){let t=(await To("/api/team/hosted")).body,n=Ce("tm-list");So=t?.suggestedHubUrl||So;let a=t?.teams||[];if(!a.length){n.innerHTML=`<p class="muted">${s("team.noTeamsShort")}</p>`;return}n.innerHTML=a.map(o=>{let i=(o.deployments||[]).filter(r=>!r.local).length;return`<div class="card" style="margin:0 0 8px;padding:10px 14px;background:var(--bg-soft,#f6f7f9)">
|
|
1481
|
-
<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
|
|
1482
|
-
<b>${l(o.name)}</b>${o.isDefault?` <span class="muted" style="font-size:12px">${s("team.default")}</span>`:""}
|
|
1483
|
-
<span class="muted" style="font-size:12px">\xB7 ${s("team.manageMetaDeps",{count:(o.deployments||[]).length})}${i?s("team.manageMetaRemote",{r:i}):""} \xB7 ${s("team.manageMetaBots",{count:(o.bots||[]).length})}</span>
|
|
1484
|
-
<span style="margin-left:auto;display:flex;gap:6px">
|
|
1485
|
-
<button class="tm-invite ghost" data-team="${l(o.teamId)}" style="font-size:12px">${s("team.genInvite")}</button>
|
|
1486
|
-
${o.isDefault?"":`<button class="tm-del ghost" data-team="${l(o.teamId)}" data-name="${l(o.name)}" style="font-size:12px">${s("team.delBtn")}</button>`}
|
|
1487
|
-
</span>
|
|
1488
|
-
</div>
|
|
1489
|
-
<div class="tm-inv-out" data-team="${l(o.teamId)}" style="display:none;margin-top:6px;font-size:13px"></div></div>`}).join(""),n.querySelectorAll(".tm-invite").forEach(o=>{o.onclick=async()=>{let i=o.dataset.team,r=n.querySelector(`.tm-inv-out[data-team="${CSS.escape(i)}"]`);r.style.display="",r.innerHTML=`<span class="muted">${s("team.generating")}</span>`;let u=await Dn("/api/team/local-invite",{teamId:i});u.body?.code?r.innerHTML=`${s("team.inviteResultLede")}<br>${s("team.inviteHub")}<code>${l(So)}</code><br>${s("team.inviteCode")}<code style="font-size:15px">${l(u.body.code)}</code>`:r.innerHTML=`<span class="err">${s("team.genFail")}</span>`}}),n.querySelectorAll(".tm-del").forEach(o=>{o.onclick=async()=>{confirm(s("team.delConfirm",{name:o.dataset.name||""}))&&(await Lo("DELETE","/api/team/hosted/"+encodeURIComponent(o.dataset.team)),Ja())}})}function lu(e){e.innerHTML=Rf(),Ce("tm-create").onclick=async()=>{let t=Ce("tm-newname").value.trim(),n=e.querySelector(".tm-cout");if(!t){n.innerHTML=`<span class="err">${s("team.errName")}</span>`;return}n.innerHTML=`<span class="muted">${s("team.creating")}</span>`;let a=await Dn("/api/team/hosted",{name:t});a.body?.ok?(n.innerHTML=`<span class="ok">${s("team.created")}</span>`,Ce("tm-newname").value="",Ja()):n.innerHTML=`<span class="err">${s("team.createFail",{error:l(String(a.body?.error||a.status))})}</span>`},Ce("tm-join").onclick=async()=>{let t=Ce("tm-hub").value.trim(),n=Ce("tm-code").value.trim(),a=Ce("tm-join-out");if(a.style.display="",!t||!n){a.innerHTML=`<span class="err">${s("team.errHubCode")}</span>`;return}a.innerHTML=`<span class="muted">${s("team.joining")}</span>`;let o=await Dn("/api/team/join-remote",{hubUrl:t,inviteCode:n});if(o.body?.ok)a.innerHTML=`<span class="ok">${s("team.joined",{name:l(o.body.teamName||"")})}</span>`,Ce("tm-code").value="";else{let i=o.body?.error||o.status,r=i==="cannot_join_self"?s("team.joinErrSelf"):i==="deployment_already_joined"?s("team.joinErrAlready"):i==="hub_unreachable"?s("team.joinErrUnreachable"):i==="hub_timeout"?s("team.joinErrTimeout"):s("team.joinErrGeneric",{error:String(i)});a.innerHTML=`<span class="err">${l(String(r))}</span>`}},Ja()}function Pf(){Ce("tf-autobind").onclick=async()=>{let e=Ce("tf-bind-out");e.style.display="",e.innerHTML=`<span class="muted">${s("team.identifying")}</span>`;let n=(await Dn("/api/team/identity/auto-bind")).body;if(n?.ok&&n.owner){e.innerHTML=`<span class="ok">${s("team.bound2",{name:l(n.owner.name||n.owner.unionId)})}</span>`,Ps();return}if(n?.ok&&n.needChoice&&Array.isArray(n.candidates)){let a=n.candidates.map(o=>`<button class="tf-pickowner ghost" data-union="${l(o.unionId)}" style="margin:2px">${l(o.name||o.unionId)}</button>`).join(" ");e.innerHTML=`${s("team.multiCandidate")}<br>${a}`,e.querySelectorAll(".tf-pickowner").forEach(o=>{o.onclick=async()=>{e.innerHTML=`<span class="muted">${s("team.binding")}</span>`;let r=(await Dn("/api/team/identity/auto-bind",{unionId:o.dataset.union})).body;r?.ok&&r.owner?(e.innerHTML=`<span class="ok">${s("team.bound2",{name:l(r.owner.name||r.owner.unionId)})}</span>`,Ps()):e.innerHTML=`<span class="err">${s("team.bindFail",{error:l(String(r?.error||"unknown"))})}</span>`}});return}if(n?.error==="no_candidates"){e.innerHTML=`<span class="err">${s("team.noCandidates")}</span>`;return}e.innerHTML=`<span class="err">${s("team.bindFail",{error:l(String(n?.error||"unknown"))})}</span>`}}async function Ya(e){let t=await fetch(e);return{status:t.status,body:await t.json().catch(()=>({}))}}async function Mo(e,t,n){let a=await fetch(t,{method:e,headers:{"content-type":"application/json"},body:n?JSON.stringify(n):void 0});return{status:a.status,body:await a.json().catch(()=>({}))}}function Ie(e){return document.getElementById(e)}function Hn(e){return(Ie(e).value||"").trim()}var Qa=[],ti=[],Io=null;function Bf(e,t){return{promptEnvelope:{sourceName:e.promptEnvelope?.sourceName||e.name,instruction:t}}}function Of(){return`<section class="page">
|
|
1490
|
-
<div class="page-heading">
|
|
1491
|
-
<div>
|
|
1492
|
-
<p class="eyebrow">Webhook</p>
|
|
1493
|
-
<h1>Webhook</h1>
|
|
1494
|
-
<p>${s("connectors.lede")}</p>
|
|
1495
|
-
</div>
|
|
1496
|
-
</div>
|
|
1497
|
-
|
|
1498
|
-
<div class="card" style="margin-bottom:16px">
|
|
1499
|
-
<h2 style="margin-top:0">${s("connectors.createTitle")}</h2>
|
|
1500
|
-
<div class="cn-form" style="display:grid;grid-template-columns:140px 1fr;gap:10px 14px;align-items:center;max-width:680px">
|
|
1501
|
-
<label>${s("connectors.fName")}</label><input id="cn-name" placeholder="${s("connectors.fNamePh")}">
|
|
1502
|
-
<label>${s("connectors.fBot")}</label><select id="cn-bot"></select>
|
|
1503
|
-
<label>${s("connectors.fKind")}</label>
|
|
1504
|
-
<select id="cn-kind"><option value="turn">${s("connectors.kindTurn")}</option><option value="workflow">${s("connectors.kindWorkflow")}</option></select>
|
|
1505
|
-
<label class="cn-wf" style="display:none">${s("connectors.fWf")}</label><input class="cn-wf" id="cn-wf" style="display:none" placeholder="workflowId">
|
|
1506
|
-
<label>${s("connectors.fMode")}</label>
|
|
1507
|
-
<select id="cn-mode">
|
|
1508
|
-
<option value="dynamic">${s("connectors.modeDynamic")}</option>
|
|
1509
|
-
<option value="fixed">${s("connectors.modeFixed")}</option>
|
|
1510
|
-
<option value="new-group">${s("connectors.modeNewGroup")}</option>
|
|
1511
|
-
</select>
|
|
1512
|
-
<label class="cn-fixed" style="display:none">${s("connectors.fFixedChat")}</label>
|
|
1513
|
-
<div class="cn-fixed" style="display:none">
|
|
1514
|
-
<select id="cn-chat-sel" style="width:100%;box-sizing:border-box"></select>
|
|
1515
|
-
<input id="cn-chat" placeholder="${s("connectors.fChatManualPh")}" style="display:none;width:100%;box-sizing:border-box;margin-top:6px">
|
|
1516
|
-
<a href="#" id="cn-chat-manual" style="font-size:12px;display:inline-block;margin-top:4px">${s("connectors.chatManualLink")}</a>
|
|
1517
|
-
</div>
|
|
1518
|
-
<label class="cn-allow">${s("connectors.fAllow")}<span class="muted" style="font-weight:400">${s("connectors.optional")}</span></label>
|
|
1519
|
-
<div class="cn-allow">
|
|
1520
|
-
<select id="cn-allow-sel" multiple size="4" style="width:100%;box-sizing:border-box"></select>
|
|
1521
|
-
<div class="muted" style="font-size:12px;margin-top:4px">${s("connectors.allowHint")}</div>
|
|
1522
|
-
</div>
|
|
1523
|
-
<div class="cn-dyn" style="display:none;grid-column:1 / -1">
|
|
1524
|
-
<div class="muted" style="font-size:12px;line-height:1.7;background:var(--bg-soft,#f6f7f9);padding:8px 10px;border-radius:6px">
|
|
1525
|
-
${s("connectors.dynamicHint")}
|
|
1526
|
-
</div>
|
|
1527
|
-
</div>
|
|
1528
|
-
<label class="cn-life" style="display:none">${s("connectors.fDedup")}<span class="muted" style="font-weight:400">${s("connectors.optional")}</span></label>
|
|
1529
|
-
<div class="cn-life" style="display:none">
|
|
1530
|
-
<input id="cn-dedup" placeholder="${s("connectors.fDedupPh")}" style="width:100%;box-sizing:border-box">
|
|
1531
|
-
<div class="muted" style="font-size:12px;margin-top:4px">${s("connectors.dedupHint")}</div>
|
|
1532
|
-
</div>
|
|
1533
|
-
<label style="align-self:start">${s("connectors.fInstruction")}<span class="muted" style="font-weight:400">${s("connectors.optional")}</span></label>
|
|
1534
|
-
<textarea id="cn-instruction" rows="3" placeholder="${s("connectors.fInstructionPh")}" style="width:100%;box-sizing:border-box;font-family:inherit;font-size:13px"></textarea>
|
|
1535
|
-
<label>${s("connectors.fVerify")}</label>
|
|
1536
|
-
<select id="cn-verify">
|
|
1537
|
-
<option value="token">${s("connectors.verifyToken")}</option>
|
|
1538
|
-
<option value="hmac-sha256">${s("connectors.verifyHmac")}</option>
|
|
1539
|
-
</select>
|
|
1540
|
-
<label>${s("connectors.fSecret")}</label><input id="cn-secret" placeholder="${s("connectors.fSecretPh")}">
|
|
1541
|
-
</div>
|
|
1542
|
-
<div style="margin-top:14px"><button id="cn-create" class="primary">${s("connectors.btnCreate")}</button>
|
|
1543
|
-
<span class="muted" id="cn-create-out" style="margin-left:10px;font-size:13px"></span></div>
|
|
1544
|
-
<div id="cn-created" style="display:none;margin-top:12px"></div>
|
|
1545
|
-
</div>
|
|
1546
|
-
|
|
1547
|
-
<div class="card">
|
|
1548
|
-
<h2 style="margin-top:0">${s("connectors.listTitle")} <span class="muted" id="cn-count" style="font-size:13px"></span></h2>
|
|
1549
|
-
<div id="cn-list">${s("connectors.loading")}</div>
|
|
1550
|
-
</div>
|
|
1551
|
-
</section>`}function Za(){let e=Ie("cn-kind").value,t=Ie("cn-mode").value;document.querySelectorAll(".cn-wf").forEach(n=>{n.style.display=e==="workflow"?"":"none"}),document.querySelectorAll(".cn-fixed").forEach(n=>{n.style.display=t==="fixed"?"":"none"}),document.querySelectorAll(".cn-allow").forEach(n=>{n.style.display=t==="fixed"?"none":""}),document.querySelectorAll(".cn-dyn").forEach(n=>{n.style.display=t==="dynamic"?"":"none"}),document.querySelectorAll(".cn-life").forEach(n=>{n.style.display=t==="new-group"?"":"none"})}function uu(e){return`${location.origin}/webhook/${encodeURIComponent(e)}`}function Ff(e){return e==="fixed"?s("connectors.modeLabelFixed"):e==="new-group"?s("connectors.modeLabelNewGroup"):s("connectors.modeLabelDynamic")}function Nf(e){return e==="workflow"?s("connectors.kindLabelWorkflow"):s("connectors.kindLabelTurn")}function Xa(e){return ti.find(n=>n.chatId===e)?.name||e}function qf(e){return ti.filter(t=>t.bots.includes(e))}function cu(){let e=Ie("cn-bot").value,t=qf(e),n=u=>`<option value="${l(u.chatId)}">${l(u.name||u.chatId)}</option>`,a=Ie("cn-chat-sel"),o=a.value;a.innerHTML=t.length?t.map(n).join(""):`<option value="">${s("connectors.noBotGroups")}</option>`,o&&t.some(u=>u.chatId===o)&&(a.value=o);let i=Ie("cn-allow-sel"),r=new Set(Array.from(i.selectedOptions).map(u=>u.value));i.innerHTML=t.map(n).join(""),Array.from(i.options).forEach(u=>{r.has(u.value)&&(u.selected=!0)})}function ei(e){let t=Ie("cn-list");if(Ie("cn-count").textContent=e.length?s("connectors.count",{count:e.length}):"",!e.length){t.innerHTML=`<p class="muted">${s("connectors.empty")}</p>`;return}t.innerHTML=e.map(n=>{let a=Qa.find(c=>c.larkAppId===n.target.botId),o=uu(n.id),i=(n.verify?.type??"token")==="token",r=i?s("connectors.badgeToken"):s("connectors.badgeSign"),u=n.target.mode==="fixed"&&n.target.chatId?` \xB7 ${s("connectors.dest",{name:l(Xa(n.target.chatId))})}`:"";return`<div class="card" style="margin:0 0 10px;padding:12px 14px;background:var(--bg-soft,#f6f7f9)">
|
|
1552
|
-
<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
|
|
1553
|
-
<b style="font-size:15px">${l(n.name)}</b>
|
|
1554
|
-
<span class="${n.enabled?"ok":"muted"}" style="font-size:12px">${n.enabled?s("connectors.enabled"):s("connectors.disabled")}</span>
|
|
1555
|
-
<span class="muted" style="font-size:12px">\xB7 ${l(a?.botName||n.target.botId)} \xB7 ${Nf(n.target.kind)} \xB7 ${Ff(n.target.mode)}${u} \xB7 ${r}</span>
|
|
1556
|
-
<span style="margin-left:auto;display:flex;gap:6px">
|
|
1557
|
-
<button class="cn-edit ghost" data-id="${l(n.id)}" style="font-size:12px">${s("connectors.btnEdit")}</button>
|
|
1558
|
-
<button class="cn-toggle ghost" data-id="${l(n.id)}" data-on="${n.enabled}" style="font-size:12px">${n.enabled?s("connectors.btnDisable"):s("connectors.btnEnable")}</button>
|
|
1559
|
-
<button class="cn-del ghost" data-id="${l(n.id)}" style="font-size:12px">${s("connectors.btnDel")}</button>
|
|
1560
|
-
</span>
|
|
1561
|
-
</div>
|
|
1562
|
-
<div style="margin-top:6px;font-size:13px;display:flex;align-items:center;gap:8px;flex-wrap:wrap">
|
|
1563
|
-
<span class="muted">${s("connectors.webhookUrl")}</span><code style="font-size:12px;word-break:break-all">${l(o)}${i?"/<token>":""}</code>
|
|
1564
|
-
<button class="cn-copy ghost" data-url="${l(o)}" style="font-size:12px">${s("connectors.copy")}</button>
|
|
1565
|
-
</div>${i?`<div class="muted" style="font-size:12px;margin-top:4px">${s("connectors.tokenHint")}</div>`:""}${n.target.mode==="dynamic"?`<div class="muted" style="font-size:12px;margin-top:4px">${s("connectors.dynamicReqHint")}</div>`:""}${n.promptEnvelope?.instruction?`<div class="muted" style="font-size:12px;margin-top:4px">${s("connectors.instructionPrefix")}${l(n.promptEnvelope.instruction)}</div>`:""}${Io===n.id?`<div class="cn-edit-box" data-id="${l(n.id)}" style="margin-top:8px">
|
|
1566
|
-
<textarea class="cn-edit-instruction" rows="3" style="width:100%;box-sizing:border-box;font-family:inherit;font-size:13px" placeholder="${s("connectors.fInstructionPh")}">${l(n.promptEnvelope?.instruction||"")}</textarea>
|
|
1567
|
-
<div style="margin-top:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap">
|
|
1568
|
-
<button class="cn-save-instruction primary" data-id="${l(n.id)}" style="font-size:12px">${s("connectors.btnSave")}</button>
|
|
1569
|
-
<button class="cn-cancel-instruction ghost" data-id="${l(n.id)}" style="font-size:12px">${s("connectors.btnCancel")}</button>
|
|
1570
|
-
<span class="muted cn-edit-out" style="font-size:12px"></span>
|
|
1571
|
-
</div>
|
|
1572
|
-
</div>`:""}</div>`}).join(""),t.querySelectorAll(".cn-copy").forEach(n=>{n.onclick=()=>{navigator.clipboard?.writeText(n.dataset.url),n.textContent=s("connectors.copied"),setTimeout(()=>n.textContent=s("connectors.copy"),1200)}}),t.querySelectorAll(".cn-edit").forEach(n=>{n.onclick=()=>{Io=n.dataset.id,ei(e)}}),t.querySelectorAll(".cn-cancel-instruction").forEach(n=>{n.onclick=()=>{Io=null,ei(e)}}),t.querySelectorAll(".cn-save-instruction").forEach(n=>{n.onclick=async()=>{let a=n.dataset.id,o=e.find(p=>p.id===a),i=n.closest(".cn-edit-box"),r=i?.querySelector(".cn-edit-out"),u=i?.querySelector(".cn-edit-instruction")?.value??"";if(!o||!i||!r)return;r.textContent=s("connectors.saving");let c=await Mo("PUT","/api/connectors/"+encodeURIComponent(a),Bf(o,u));if(c.status===200&&c.body?.ok)Io=null,await Bs();else{let p=c.body?.error||c.status;r.innerHTML=`<span class="err">${s("connectors.saveFailed",{error:l(String(p))})}</span>`}}}),t.querySelectorAll(".cn-toggle").forEach(n=>{n.onclick=async()=>{await Mo("PATCH","/api/connectors/"+encodeURIComponent(n.dataset.id),{enabled:n.dataset.on!=="true"}),Bs()}}),t.querySelectorAll(".cn-del").forEach(n=>{n.onclick=async()=>{confirm(s("connectors.delConfirm"))&&(await Mo("DELETE","/api/connectors/"+encodeURIComponent(n.dataset.id)),Bs())}})}async function Bs(){let[e,t,n]=await Promise.all([Ya("/api/bots"),Ya("/api/connectors"),Ya("/api/groups")]);Qa=(e.body?.bots||[]).map(i=>({larkAppId:i.larkAppId,botName:i.botName||i.larkAppId})),ti=(n.body?.chats||[]).map(i=>({chatId:i.chatId,name:i.name||"",bots:(i.memberBots||[]).filter(r=>r.inChat).map(r=>r.larkAppId)}));let a=Ie("cn-bot"),o=a.value;a.innerHTML=Qa.map(i=>`<option value="${l(i.larkAppId)}">${l(i.botName)}</option>`).join("")||`<option value="">${s("connectors.noOnlineBots")}</option>`,o&&(a.value=o),cu(),ei(t.body?.connectors||[])}function du(e){e.innerHTML=Of(),Ie("cn-kind").onchange=Za,Ie("cn-mode").onchange=Za,Ie("cn-bot").onchange=cu,Ie("cn-chat-manual").onclick=t=>{t.preventDefault();let n=Ie("cn-chat"),a=Ie("cn-chat-sel"),o=n.style.display==="none";n.style.display=o?"":"none",a.style.display=o?"none":"",Ie("cn-chat-manual").textContent=o?s("connectors.chatListLink"):s("connectors.chatManualLink")},Za(),Ie("cn-create").onclick=async()=>{let t=Ie("cn-create-out"),n=Hn("cn-name"),a=Ie("cn-bot").value;if(!n){t.innerHTML=`<span class="err">${s("connectors.errName")}</span>`;return}if(!a){t.innerHTML=`<span class="err">${s("connectors.errBot")}</span>`;return}let o=Ie("cn-kind").value,i=Ie("cn-mode").value,r={name:n,enabled:!0,target:{kind:o,mode:i,botId:a},promptEnvelope:{sourceName:n}},u=Hn("cn-instruction");if(u&&(r.promptEnvelope.instruction=u),o==="workflow"){if(!Hn("cn-wf")){t.innerHTML=`<span class="err">${s("connectors.errWf")}</span>`;return}r.target.workflowId=Hn("cn-wf")}if(i==="fixed"){let h=Ie("cn-chat").style.display!=="none"?Hn("cn-chat"):Ie("cn-chat-sel").value;if(!h){t.innerHTML=`<span class="err">${s("connectors.errChat")}</span>`;return}r.target.chatId=h}else{let f=Array.from(Ie("cn-allow-sel").selectedOptions).map(h=>h.value).filter(Boolean);f.length&&(r.target.allowChats=f)}if(i==="new-group"){let f=Hn("cn-dedup");r.lifecycleExtractors=f?{dedupKey:f}:null}r.verify={type:Ie("cn-verify").value};let c=Hn("cn-secret");c&&(r.secret=c),t.innerHTML=`<span class="muted">${s("connectors.creating")}</span>`;let p=await Mo("POST","/api/connectors",r);if(p.status===201&&p.body?.ok){t.innerHTML="";let f=Ie("cn-created");f.style.display="";let h=p.body.webhookUrl||uu(p.body.connector.id),y=p.body.secret,g=(p.body.connector?.verify?.type??"token")==="token",v=i==="dynamic",M=v?r.target.allowChats?.[0]||"<chatId>":"",$=v?`${l(h)}?chatId=${l(M)}`:l(h),L;if(g&&v){let C=M!=="<chatId>"?`\uFF08${l(Xa(r.target.allowChats[0]))}\uFF09`:"";L=`<p class="muted" style="font-size:12px;margin:6px 0 0">${s("connectors.usageDynamicLede",{gn:C})}</p>
|
|
1573
|
-
<pre style="margin:6px 0 0;font-size:12px;white-space:pre-wrap;word-break:break-all"><code>curl -X POST '${$}' -H 'content-type: application/json' -d '{}'</code></pre>
|
|
1574
|
-
<p class="muted" style="font-size:12px;margin:6px 0 0">${s("connectors.usageDynamicNote")}</p>`}else g?L=`<p class="muted" style="font-size:12px;margin:6px 0 0">${s("connectors.usageTokenLede")}</p>
|
|
1575
|
-
<pre style="margin:6px 0 0;font-size:12px;white-space:pre-wrap;word-break:break-all"><code>curl -X POST '${$}' -H 'content-type: application/json' -d '{}'</code></pre>
|
|
1576
|
-
<p class="muted" style="font-size:12px;margin:6px 0 0">${s("connectors.usageTokenNote")}</p>`:L=`<p class="muted" style="font-size:12px;margin:6px 0 0">${s("connectors.usageHmac")}${v?s("connectors.usageHmacDynamic"):""}</p>`;f.innerHTML=`<div class="card" style="padding:12px 14px;background:var(--bg-soft,#f6f7f9)">
|
|
1577
|
-
<p class="ok" style="margin:0 0 6px">${s("connectors.createdPrefix",{name:l(n)})}${i==="fixed"&&r.target.chatId?`<span class="muted" style="font-weight:400;font-size:13px"> \xB7 ${s("connectors.createdDest",{name:l(Xa(r.target.chatId))})}</span>`:""}</p>
|
|
1578
|
-
<p style="margin:4px 0;font-size:13px"><span class="muted">${s("connectors.webhookUrl")}</span><code style="word-break:break-all">${l(h)}</code></p>
|
|
1579
|
-
${y?`<p style="margin:4px 0;font-size:13px"><span class="muted">${g?s("connectors.tokenLabel"):s("connectors.signLabel")}${s("connectors.secretOnce")}</span><code>${l(y)}</code></p>`:""}
|
|
1580
|
-
${L}</div>`,["cn-name","cn-wf","cn-chat","cn-dedup","cn-secret","cn-instruction"].forEach(C=>{Ie(C).value=""}),Ie("cn-allow-sel").selectedIndex=-1,Bs()}else{let f=p.body?.error||p.status;t.innerHTML=`<span class="err">${s("connectors.createFailed",{error:l(String(f))})}</span>`}},Bs()}var Ue=null,Fs=null,rs=!0,pu=!1;function fu(e){return{publicReadOnly:e?.publicReadOnly===!0,openTerminalInFeishu:e?.openTerminalInFeishu===!0,chatBotDiscovery:e?.chatBotDiscovery!==!1,repoPickerMode:e?.repoPickerMode==="repos"?"repos":"all",maintenance:e?.maintenance&&typeof e.maintenance=="object"?e.maintenance:{},localDevInstall:e?.localDevInstall===!0,whiteboard:{enabled:e?.whiteboard?.enabled===!0},remoteAccess:e?.remoteAccess===!0}}function jf(e,t){let n=e?.[t]??{};return{enabled:n.enabled===!0,time:typeof n.time=="string"?n.time:"04:00"}}function Uf(){return`<section class="page">
|
|
1581
|
-
<div class="page-heading">
|
|
1582
|
-
<div>
|
|
1583
|
-
<p class="eyebrow">${s("nav.settings")}</p>
|
|
1584
|
-
<h1>${s("settings.title")}</h1>
|
|
1585
|
-
<p>${s("settings.subtitle")}</p>
|
|
1586
|
-
</div>
|
|
1587
|
-
</div>
|
|
1588
|
-
<div id="settings-body"></div>
|
|
1589
|
-
<div id="update-body"></div>
|
|
1590
|
-
</section>`}function zf(e){let{enabled:t,time:n}=jf(Ue.maintenance,"autoUpdate"),a=e?"disabled":"";return`<label class="toggle-row">
|
|
1591
|
-
<input type="checkbox" data-maint="autoUpdate" ${t?"checked":""} ${a}>
|
|
1592
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1593
|
-
<span class="toggle-tx"><strong>${s("settings.autoUpdate")}</strong>
|
|
1594
|
-
<small>${s("settings.autoUpdateHelp")}</small></span>
|
|
1595
|
-
</label>
|
|
1596
|
-
<div class="maint-time">
|
|
1597
|
-
<label>${s("settings.maintenanceTime")}
|
|
1598
|
-
<input type="time" data-maint-time="autoUpdate" value="${l(n)}" ${a}>
|
|
1599
|
-
</label>
|
|
1600
|
-
</div>`}function Gf(e){return`<label class="toggle-row">
|
|
1601
|
-
<input type="checkbox" data-maint="autoRestart" ${Ue.maintenance.autoRestart?.enabled===!0?"checked":""} ${e?"disabled":""}>
|
|
1602
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1603
|
-
<span class="toggle-tx"><strong>${s("settings.autoRestart")}</strong>
|
|
1604
|
-
<small>${s("settings.autoRestartHelp")}</small></span>
|
|
1605
|
-
</label>`}function Wf(){if(Fs)return`<p class="hint-warn">${s("settings.loadFailed")}: ${l(Fs)}</p>`;if(!Ue)return`<p class="empty">${s("settings.loading")}</p>`;let e=rs?"":"disabled",t=!rs||Ue.localDevInstall;return`<div class="settings-grid">
|
|
1606
|
-
<article class="bd-card settings-card">
|
|
1607
|
-
${rs?"":`<p class="hint-warn">${s("settings.readOnlyVisitor")}</p>`}
|
|
1608
|
-
<section class="bd-section">
|
|
1609
|
-
<h3 class="bd-section-title">${s("settings.sectionAccess")}</h3>
|
|
1610
|
-
<label class="toggle-row">
|
|
1611
|
-
<input type="checkbox" data-setting="publicReadOnly" ${Ue.publicReadOnly?"checked":""} ${e}>
|
|
1612
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1613
|
-
<span class="toggle-tx"><strong>${s("settings.publicReadOnly")}</strong>
|
|
1614
|
-
<small>${s("settings.publicReadOnlyHelp")}</small></span>
|
|
1615
|
-
</label>
|
|
1616
|
-
${pu?`<label class="toggle-row">
|
|
1617
|
-
<input type="checkbox" data-setting="remoteAccess" ${Ue.remoteAccess?"checked":""} ${e}>
|
|
1618
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1619
|
-
<span class="toggle-tx"><strong>${s("settings.remoteAccess")}</strong>
|
|
1620
|
-
<small>${s("settings.remoteAccessHelp")}</small></span>
|
|
1621
|
-
</label>`:""}
|
|
1622
|
-
</section>
|
|
1623
|
-
<section class="bd-section">
|
|
1624
|
-
<h3 class="bd-section-title">${s("settings.sectionCards")}</h3>
|
|
1625
|
-
<label class="toggle-row">
|
|
1626
|
-
<input type="checkbox" data-setting="openTerminalInFeishu" ${Ue.openTerminalInFeishu?"checked":""} ${e}>
|
|
1627
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1628
|
-
<span class="toggle-tx"><strong>${s("settings.openTerminalInFeishu")}</strong>
|
|
1629
|
-
<small>${s("settings.openTerminalInFeishuHelp")}</small></span>
|
|
1630
|
-
</label>
|
|
1631
|
-
</section>
|
|
1632
|
-
<section class="bd-section">
|
|
1633
|
-
<h3 class="bd-section-title">${s("settings.sectionExperimental")}</h3>
|
|
1634
|
-
<label class="toggle-row">
|
|
1635
|
-
<input type="checkbox" data-setting="chatBotDiscovery" ${Ue.chatBotDiscovery?"checked":""} ${e}>
|
|
1636
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1637
|
-
<span class="toggle-tx"><strong>${s("settings.chatBotDiscovery")}</strong>
|
|
1638
|
-
<small>${s("settings.chatBotDiscoveryHelp")}</small></span>
|
|
1639
|
-
</label>
|
|
1640
|
-
</section>
|
|
1641
|
-
<section class="bd-section">
|
|
1642
|
-
<h3 class="bd-section-title">\u672C\u5730\u767D\u677F</h3>
|
|
1643
|
-
<label class="toggle-row">
|
|
1644
|
-
<input type="checkbox" data-whiteboard-enabled ${Ue.whiteboard.enabled?"checked":""} ${e}>
|
|
1645
|
-
<span class="switch" aria-hidden="true"></span>
|
|
1646
|
-
<span class="toggle-tx"><strong>\u542F\u7528\u9879\u76EE\u767D\u677F</strong>
|
|
1647
|
-
<small>\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</small></span>
|
|
1648
|
-
</label>
|
|
1649
|
-
</section>
|
|
1650
|
-
<section class="bd-section">
|
|
1651
|
-
<h3 class="bd-section-title">${s("settings.sectionRepoPicker")}</h3>
|
|
1652
|
-
<label class="form-row">
|
|
1653
|
-
<span>${s("settings.repoPickerMode")}</span>
|
|
1654
|
-
<select data-select-setting="repoPickerMode" ${e}>
|
|
1655
|
-
<option value="all" ${Ue.repoPickerMode==="all"?"selected":""}>${s("settings.repoPickerModeAll")}</option>
|
|
1656
|
-
<option value="repos" ${Ue.repoPickerMode==="repos"?"selected":""}>${s("settings.repoPickerModeRepos")}</option>
|
|
1657
|
-
</select>
|
|
1658
|
-
<small>${s("settings.repoPickerModeHelp")}</small>
|
|
1659
|
-
</label>
|
|
1660
|
-
</section>
|
|
1661
|
-
<section class="bd-section">
|
|
1662
|
-
<h3 class="bd-section-title">${s("settings.sectionMaintenance")}</h3>
|
|
1663
|
-
${zf(t)}
|
|
1664
|
-
${Ue.localDevInstall?`<p class="hint-warn">${s("settings.autoUpdateLocalDev")}</p>`:""}
|
|
1665
|
-
${Gf(!rs||Ue.maintenance.autoUpdate?.enabled!==!0)}
|
|
1666
|
-
</section>
|
|
1667
|
-
<div class="actions settings-actions">
|
|
1668
|
-
<span class="oncall-status" data-settings-status></span>
|
|
1669
|
-
</div>
|
|
1670
|
-
</article>
|
|
1671
|
-
</div>`}var _n=null,ls=null,Zt=null,Rn=!1,Os=!0,ni=!1,si="",mt=!1,us=null;function mu(e){return e==="npm-global"?s("update.kindNpm"):e==="source-checkout"?s("update.kindSource"):s("update.kindUnknown")}function Vf(){if(Zt===null)return`<p class="empty">${s("update.changelogLoading")}</p>`;if(!Os){let e=ni?s("update.changelogRateLimited"):s("update.changelogFailed"),t=si?` <a href="${l(si)}" target="_blank" rel="noopener">${s("update.changelogViewOnGitHub")}</a>`:"";return`<p class="hint-warn-inline">${e}${t}</p>`}return Zt.length===0?`<p class="empty">${s("update.changelogEmpty")}</p>`:`<div class="update-changelog">${Zt.map(e=>{let t=e.name&&e.name!==`v${e.version}`?e.name:"",n=e.publishedAt?new Date(e.publishedAt).toLocaleDateString():"";return`<details class="update-release" open>
|
|
1672
|
-
<summary><strong>v${l(e.version)}</strong> ${l(t)} <small>${l(n)}</small>
|
|
1673
|
-
<a href="${l(e.url)}" target="_blank" rel="noopener">\u2197</a></summary>
|
|
1674
|
-
<pre class="update-release-body">${l(e.body||"")}</pre>
|
|
1675
|
-
</details>`}).join("")}</div>`}function Kf(e){let t;if(!e)t=`<p class="hint-warn">${s("update.loginRequired")}</p>`;else if(ls)t=`<p class="hint-warn">${s("update.checkFailed")}: ${l(ls)}</p>
|
|
1676
|
-
<div class="update-actions"><button type="button" data-up="check">${s("update.btnCheck")}</button></div>`;else if(!_n)t=`<p class="empty">${s("update.loading")}</p>`;else{let n=_n,a=n.latest?n.behind?`<span class="update-badge update-badge-new">${s("update.newAvailable",{version:`v${n.latest}`})}</span>`:`<span class="update-badge update-badge-ok">${s("update.upToDate")}</span>`:`<span class="hint-warn-inline">${s("update.checkUnavailable")}</span>`,o=`<p class="update-version"><span>${s("update.current")}: <strong>v${l(n.current)}</strong></span> ${a}</p>`,i=[];if(n.node.ok||i.push(`<p class="hint-warn">${s("update.nodeWarn",{version:n.node.version,required:n.node.required})}</p>`),n.localDevInstall&&i.push(`<p class="hint-warn">${s("update.localDev")}</p>`),n.installs.multiple){let f=n.installs.entries.map(h=>`<li><code>${l(h.binPath)}</code> \u2192 ${mu(h.kind)} <small>${l(h.root)}</small></li>`).join("");i.push(`<div class="hint-warn"><p>${s("update.multiInstallWarn")}</p><ul class="update-install-list">${f}</ul></div>`)}let r=n.localDevInstall||mt,u=`<div class="update-actions">
|
|
1677
|
-
<button type="button" data-up="check" ${mt?"disabled":""}>${s("update.btnCheck")}</button>
|
|
1678
|
-
<button type="button" data-up="changelog" ${mt?"disabled":""}>${Rn?s("update.btnChangelogHide"):s("update.btnChangelog")}</button>
|
|
1679
|
-
<button type="button" class="primary" data-up="update" ${r?"disabled":""}>${s("update.btnUpdate")}</button>
|
|
1680
|
-
<button type="button" data-up="restart" ${mt?"disabled":""}>${s("update.btnRestart")}</button>
|
|
1681
|
-
</div>`,c=Rn?Vf():"",p=us?`<p class="oncall-status ${l(us.cls)}">${l(us.text)}</p>`:"";t=o+i.join("")+u+c+p}return`<div class="settings-grid">
|
|
1682
|
-
<article class="bd-card settings-card">
|
|
1683
|
-
<section class="bd-section">
|
|
1684
|
-
<h3 class="bd-section-title">${s("update.section")}</h3>
|
|
1685
|
-
${t}
|
|
1686
|
-
</section>
|
|
1687
|
-
</article>
|
|
1688
|
-
</div>`}function Jf(e,t){function n(){e.innerHTML=Kf(t),p()}function a(f,h=""){us={text:f,cls:h}}async function o(){try{let f=await fetch("/api/update/status"),h=await f.json().catch(()=>({}));if(!f.ok){_n=null,ls=h?.error??`HTTP ${f.status}`;return}_n=h,ls=null}catch(f){_n=null,ls=f?.message??String(f)}}async function i(){Zt=null,Os=!0,ni=!1,n();try{let f=await fetch("/api/update/changelog"),h=await f.json().catch(()=>({}));si=typeof h?.releasesUrl=="string"?h.releasesUrl:"",f.ok?(Zt=Array.isArray(h.releases)?h.releases:[],Os=h.ok!==!1,ni=h.rateLimited===!0):(Zt=[],Os=!1)}catch{Zt=[],Os=!1}n()}function r(){let f=Date.now(),h=async()=>{if(Date.now()-f>9e4){mt=!1,a(s("update.restartSlow"),"hint-warn-inline"),n();return}try{if((await fetch("/__health",{cache:"no-store"})).ok){location.reload();return}}catch{}setTimeout(()=>{h()},2e3)};setTimeout(()=>{h()},3e3)}async function u(f){mt=!0,a(s("update.restarting")),n();try{await fetch("/api/update/restart",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(f?{update:f}:{})})}catch(h){mt=!1,a(s("update.restartFailed",{detail:h?.message??h}),"hint-warn-inline"),n();return}r()}async function c(){let f=_n;if(!f)return;if(!f.node.ok){window.alert(s("update.nodeTooOldAlert",{version:f.node.version,required:f.node.required}));return}if(f.installs.multiple){let y=f.installs.entries.map(g=>`\u2022 ${g.binPath} (${mu(g.kind)})`).join(`
|
|
1689
|
-
`);if(!window.confirm(s("update.confirmMultiInstall",{paths:y})))return}let h=f.latest?s("update.confirmUpdate",{version:`v${f.latest}`}):s("update.confirmUpdateNoVer");if(window.confirm(h)){mt=!0,a(s("update.updating")),n();try{let y=await fetch("/api/update/run",{method:"POST"}),g=await y.json().catch(()=>({}));if(!y.ok||g.ok===!1){let v=g?.detail??g?.error??`HTTP ${y.status}`;mt=!1,a(s("update.updateFailed",{detail:v}),"hint-warn-inline"),n();return}g.changed?(mt=!1,a(s("update.updatedChanged",{old:`v${g.oldVersion}`,new:`v${g.newVersion}`}),"hint-ok"),n(),window.confirm(s("update.confirmRestart"))?await u({oldVersion:g.oldVersion,newVersion:g.newVersion}):(a(s("update.noRestartHint"),"hint-ok"),n())):(mt=!1,a(s("update.alreadyLatestRun",{version:`v${g.newVersion}`}),"hint-ok"),await o(),n())}catch(y){mt=!1,a(s("update.updateFailed",{detail:y?.message??y}),"hint-warn-inline"),n()}}}function p(){e.querySelectorAll("button[data-up]").forEach(f=>{f.addEventListener("click",()=>{let h=f.dataset.up;h==="check"?(_n=null,Zt=null,Rn=!1,us=null,ls=null,n(),o().then(n)):h==="changelog"?(Rn=!Rn,Rn&&Zt===null?i():n()):h==="update"?c():h==="restart"&&window.confirm(s("update.confirmPlainRestart"))&&u(null)})})}n(),t&&o().then(n)}async function Yf(){try{let e=await fetch("/api/settings"),t=await e.json().catch(()=>({}));if(!e.ok){Ue=null,Fs=t?.error??`HTTP ${e.status}`;return}Ue=fu(t.settings),rs=t.authed===!0,pu=t.bound===!0,Fs=null}catch(e){Ue=null,Fs=e?.message??String(e)}}async function hu(e){e.innerHTML=Uf();let t=e.querySelector("#settings-body");function n(){t.innerHTML=Wf(),i()}function a(){return t.querySelector("[data-settings-status]")}async function o(u,c,p){if(!Ue)return;p.disabled=!0;let f=a();f&&(f.textContent=s("settings.saving"),f.className="oncall-status");try{let h=await fetch("/api/settings",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify(u)}),y=await h.json().catch(()=>({}));if(!h.ok||y.ok===!1)throw new Error(y?.error??`HTTP ${h.status}`);Ue=fu(y.settings),f&&(f.textContent=s("settings.saved"),f.classList.add("hint-ok"))}catch(h){c(),f&&(f.textContent=`${s("settings.saveFailed")}: ${h?.message??h}`,f.classList.add("hint-warn-inline"))}finally{p.disabled=!1}}function i(){t.querySelectorAll("input[data-setting]").forEach(c=>{c.addEventListener("change",()=>{let p=c.dataset.setting,f=!c.checked;o({[p]:c.checked},()=>{c.checked=f},c)})}),t.querySelector("input[data-whiteboard-enabled]")?.addEventListener("change",c=>{let p=c.currentTarget,f=!p.checked;o({whiteboard:{enabled:p.checked}},()=>{p.checked=f},p)}),t.querySelectorAll("select[data-select-setting]").forEach(c=>{c.addEventListener("change",()=>{let p=c.dataset.selectSetting,f=Ue?.[p]??"all";o({[p]:c.value},()=>{c.value=f},c)})});let u=(c,p,f)=>{let y=t.querySelector(`input[data-maint="${c}"]`)?.checked??!1,g;if(c==="autoUpdate"){let v=t.querySelector('input[data-maint-time="autoUpdate"]');g={enabled:y,time:v?.value||"04:00"}}else g={enabled:y};o({maintenance:{[c]:g}},f,p).then(()=>n())};t.querySelectorAll("input[data-maint]").forEach(c=>{c.addEventListener("change",()=>{let p=c.dataset.maint,f=!c.checked;u(p,c,()=>{c.checked=f})})}),t.querySelectorAll("input[data-maint-time]").forEach(c=>{c.addEventListener("change",()=>{let p=c.dataset.maintTime,f=c.defaultValue;u(p,c,()=>{c.value=f})})})}n(),await Yf(),n(),mt=!1,us=null,Rn=!1;let r=e.querySelector("#update-body");Jf(r,rs)}function gu(e,t,n){e.setAttribute("data-run-id",t),e.setAttribute("data-node-id",n.id);let a=n.webTerminal;if(a?.status==="live"&&a.webPort&&a.webPort>0){Zf(e,a.webPort);return}if(n.hasPtyLog){Qf(e,t,n.id,a?.status==="closed");return}Xf(e,a?.status==="live"?"\u7EC8\u7AEF\u6B63\u5728\u542F\u52A8\uFF0C\u7A0D\u540E\u5237\u65B0":"\u6682\u65E0\u7EC8\u7AEF\u8BB0\u5F55")}function Zf(e,t){let n=em(t);e.innerHTML=`<div class="v3-terminal-panel">
|
|
1690
|
-
<div class="v3-terminal-head">
|
|
1691
|
-
<span class="v3-terminal-dot live"></span>
|
|
1692
|
-
<span>\u5B9E\u65F6\u7EC8\u7AEF\uFF08\u53EA\u8BFB\uFF09</span>
|
|
1693
|
-
<span class="muted">:${t}</span>
|
|
1694
|
-
<a class="btn-link" href="${Ao(n)}" target="_blank" rel="noopener">\u65B0\u7A97\u53E3\u6253\u5F00</a>
|
|
1695
|
-
</div>
|
|
1696
|
-
<iframe class="wf-terminal-frame v3-terminal-frame" src="${Ao(n)}" title="v3 live terminal" loading="lazy"></iframe>
|
|
1697
|
-
</div>`}function Qf(e,t,n,a){let o=`/api/v3/runs/${encodeURIComponent(t)}/nodes/${encodeURIComponent(n)}/pty-log`,i=tm(o,`${t} / ${n}`);e.innerHTML=`<div class="v3-terminal-panel">
|
|
1698
|
-
<div class="v3-terminal-head">
|
|
1699
|
-
<span class="v3-terminal-dot ${a?"closed":"replay"}"></span>
|
|
1700
|
-
<span>${a?"\u7EC8\u7AEF\u56DE\u653E":"\u7EC8\u7AEF\u8BB0\u5F55"}</span>
|
|
1701
|
-
<span class="muted">PTY log</span>
|
|
1702
|
-
<a class="btn-link" href="${Ao(o)}" target="_blank" rel="noopener">\u4E0B\u8F7D/\u6253\u5F00\u539F\u59CB\u65E5\u5FD7</a>
|
|
1703
|
-
</div>
|
|
1704
|
-
<iframe class="wf-terminal-frame v3-terminal-frame" srcdoc="${Ao(i)}" title="v3 terminal replay" loading="lazy"></iframe>
|
|
1705
|
-
</div>`}function Xf(e,t){e.innerHTML=`<div class="v3-terminal-empty muted">${oi(t)}</div>`}function em(e){return`http://${window.location.hostname||"127.0.0.1"}:${e}/`}function tm(e,t){let n=JSON.stringify(e);return`<!doctype html>
|
|
1706
|
-
<html>
|
|
1707
|
-
<head>
|
|
1708
|
-
<meta charset="utf-8">
|
|
1709
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.css">
|
|
1710
|
-
<style>
|
|
1711
|
-
html,body{margin:0;height:100%;background:#0d1117;color:#c9d1d9;font:12px ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
1712
|
-
#bar{height:31px;display:flex;align-items:center;gap:10px;padding:0 10px;background:#161b22;border-bottom:1px solid #30363d;box-sizing:border-box}
|
|
1713
|
-
#status{margin-left:auto;color:#8b949e;white-space:nowrap}
|
|
1714
|
-
#term{height:calc(100% - 31px);padding:4px;box-sizing:border-box;overflow:auto}
|
|
1715
|
-
a{color:#58a6ff;text-decoration:none}
|
|
1716
|
-
</style>
|
|
1717
|
-
</head>
|
|
1718
|
-
<body>
|
|
1719
|
-
<div id="bar"><span>${oi(t)}</span><span id="status">loading...</span></div>
|
|
1720
|
-
<div id="term"></div>
|
|
1721
|
-
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.js"><\/script>
|
|
1722
|
-
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.10.0/lib/addon-fit.js"><\/script>
|
|
1723
|
-
<script>
|
|
1724
|
-
(function(){
|
|
1725
|
-
var endpoint=${n};
|
|
1726
|
-
// v3 ephemeral workers spawn their PTY at DEFAULT_RENDER_COLS (=160, see
|
|
1727
|
-
// worker.ts) and never adopt, so the captured stream's TUI / box-drawing
|
|
1728
|
-
// is exactly 160 cols wide. Fitting it into a narrower (or oddly-measured)
|
|
1729
|
-
// grid re-wraps those fixed-width lines into a stair-stepped mess and
|
|
1730
|
-
// wastes the panel. So we render at the capture width and let FitAddon
|
|
1731
|
-
// only size the ROW count to the iframe height (cols pinned back to 160).
|
|
1732
|
-
var COLS=160;
|
|
1733
|
-
var status=document.getElementById('status');
|
|
1734
|
-
var termEl=document.getElementById('term');
|
|
1735
|
-
if(!window.Terminal){status.textContent='xterm.js failed to load';return;}
|
|
1736
|
-
var term=new Terminal({
|
|
1737
|
-
cols:COLS,
|
|
1738
|
-
convertEol:false,
|
|
1739
|
-
scrollback:100000,
|
|
1740
|
-
fontSize:13,
|
|
1741
|
-
disableStdin:true,
|
|
1742
|
-
theme:{background:'#0d1117',foreground:'#c9d1d9',cursor:'#c9d1d9'}
|
|
1743
|
-
});
|
|
1744
|
-
var fit=null;
|
|
1745
|
-
if(window.FitAddon){fit=new window.FitAddon.FitAddon();term.loadAddon(fit);}
|
|
1746
|
-
term.open(termEl);
|
|
1747
|
-
function doFit(){
|
|
1748
|
-
try{if(fit)fit.fit()}catch(_){}
|
|
1749
|
-
if(term.cols!==COLS)term.resize(COLS,term.rows||24);
|
|
1750
|
-
}
|
|
1751
|
-
doFit(); window.addEventListener('resize',doFit);
|
|
1752
|
-
fetch(endpoint,{credentials:'include'}).then(function(res){
|
|
1753
|
-
if(!res.ok){
|
|
1754
|
-
if(res.status===401){status.textContent='\u9700\u8981\u767B\u5F55 dashboard \u540E\u67E5\u770B\u56DE\u653E';}
|
|
1755
|
-
else if(res.status===404){status.textContent='\u6CA1\u6709 PTY \u65E5\u5FD7';}
|
|
1756
|
-
else{status.textContent='\u52A0\u8F7D\u5931\u8D25 HTTP '+res.status;}
|
|
1757
|
-
return null;
|
|
1758
|
-
}
|
|
1759
|
-
var total=Number(res.headers.get('x-botmux-log-bytes')||0);
|
|
1760
|
-
var served=Number(res.headers.get('x-botmux-served-bytes')||0);
|
|
1761
|
-
var truncated=res.headers.get('x-botmux-truncated')==='1';
|
|
1762
|
-
status.textContent=truncated
|
|
1763
|
-
? 'showing tail '+formatBytes(served)+' / '+formatBytes(total)
|
|
1764
|
-
: 'loaded '+formatBytes(total);
|
|
1765
|
-
return res.arrayBuffer();
|
|
1766
|
-
}).then(function(buf){
|
|
1767
|
-
if(!buf)return;
|
|
1768
|
-
term.write(new TextDecoder().decode(buf));
|
|
1769
|
-
setTimeout(doFit,0);
|
|
1770
|
-
}).catch(function(err){
|
|
1771
|
-
status.textContent='\u52A0\u8F7D\u5931\u8D25: '+(err&&err.message?err.message:String(err));
|
|
1772
|
-
});
|
|
1773
|
-
function formatBytes(n){
|
|
1774
|
-
if(!Number.isFinite(n)||n<=0)return '0 B';
|
|
1775
|
-
var u=['B','KiB','MiB','GiB'];var i=0;
|
|
1776
|
-
while(n>=1024&&i<u.length-1){n/=1024;i++;}
|
|
1777
|
-
return (i===0?String(n):n.toFixed(1))+' '+u[i];
|
|
1778
|
-
}
|
|
1779
|
-
})();
|
|
1780
|
-
<\/script>
|
|
1781
|
-
</body>
|
|
1782
|
-
</html>`}function oi(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function Ao(e){return oi(e).replace(/`/g,"`")}function bu(e,t){let n=t?`?${t}`:"";return`#/legacy-workflow/${encodeURIComponent(e)}${n}`}var ku=2e3;function yu(e){return e==="succeeded"||e==="failed"}var Ns={pending:"\u5F85\u673A",gateWaiting:"\u7B49\u5BA1\u6279",running:"\u8FD0\u884C\u4E2D",done:"\u5B8C\u6210",skipped:"\u5DF2\u8DF3\u8FC7",cancelled:"\u5DF2\u53D6\u6D88",blocked:"\u53D7\u963B",superseded:"\u5DF2\u5237\u65B0",failed:"\u5931\u8D25"},nm={exit:"\u2713 \u901A\u8FC7",continue:"\u21BB \u7EE7\u7EED\u8FD4\u5DE5",exhausted:"\u26D4 \u8F6E\u6570\u8017\u5C3D"};function ze(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function sm(e){let t=e.webTerminal;return`${t?.status??"-"}|${t?.webPort??"-"}|${e.hasPtyLog?"1":"0"}`}function $u(e){let t=location.hash.match(/^#\/workflows\/([^?#]+)/);return t?im(e,decodeURIComponent(t[1])):om(e)}function om(e){e.innerHTML=`
|
|
1783
|
-
<div class="page-head">
|
|
1784
|
-
<h1>\u5DE5\u4F5C\u6D41</h1>
|
|
1785
|
-
<p class="muted">LLM \u7F16\u6392\u7684 workflow \u8FD0\u884C \u2014 DAG \u56FE + \u6BCF\u8282\u70B9\u7EC8\u7AEF</p>
|
|
1786
|
-
</div>
|
|
1787
|
-
<table class="data-table">
|
|
1788
|
-
<thead><tr><th>Run</th><th>\u72B6\u6001</th><th>\u8282\u70B9\u6570</th></tr></thead>
|
|
1789
|
-
<tbody id="v3-tbody"></tbody>
|
|
1790
|
-
</table>
|
|
1791
|
-
<div id="v3-empty" class="muted" hidden style="padding:1rem">\u6682\u65E0\u5DE5\u4F5C\u6D41\u8FD0\u884C\uFF08\u7528 <code>/workflow new</code> \u53D1\u8D77\u4E00\u4E2A\uFF09</div>`;let t=e.querySelector("#v3-tbody"),n=e.querySelector("#v3-empty"),a=null,o=!1;async function i(){if(!(o||document.hidden))try{let u=await fetch("/api/v3/runs"),c=u.ok?await u.json():{runs:[]};if(o)return;let p=c.runs??[];n.hidden=p.length>0,t.innerHTML=p.map(f=>`<tr>
|
|
1792
|
-
<td><a class="v3r-runid" href="#/workflows/${encodeURIComponent(f.runId)}">${ze(f.runId)}</a></td>
|
|
1793
|
-
<td><span class="v3r-pill rs-${ze(f.runStatus)}">${ze(f.runStatus)}</span></td>
|
|
1794
|
-
<td>${f.nodeCount}</td>
|
|
1795
|
-
</tr>`).join("")}catch{}}function r(){o||i().then(()=>{o||(a=window.setTimeout(r,ku))})}return r(),()=>{o=!0,a!==null&&window.clearTimeout(a)}}var qs=168,ri=48,Ho=70,vu=226,wu=30,Do=26,am=8;function ai(e){return e.isLoop?Ho:ri}function im(e,t){e.innerHTML=`
|
|
1796
|
-
<div class="page-head">
|
|
1797
|
-
<a href="#/workflows" class="btn-link">\u2190 \u5DE5\u4F5C\u6D41</a>
|
|
1798
|
-
<h1 class="v3r-title">${ze(t)}</h1>
|
|
1799
|
-
<span id="v3-runstatus" class="v3r-pill"></span>
|
|
1800
|
-
</div>
|
|
1801
|
-
<div class="v3r-wrap">
|
|
1802
|
-
<div class="v3r-graph-card">
|
|
1803
|
-
<div id="v3-graph" class="v3r-graph"></div>
|
|
1804
|
-
<div class="v3r-legend">
|
|
1805
|
-
<span class="lg st-pending">\u5F85\u673A</span>
|
|
1806
|
-
<span class="lg st-running">\u8FD0\u884C\u4E2D</span>
|
|
1807
|
-
<span class="lg st-gateWaiting">\u7B49\u5BA1\u6279</span>
|
|
1808
|
-
<span class="lg st-done">\u5B8C\u6210</span>
|
|
1809
|
-
<span class="lg st-skipped">\u5DF2\u8DF3\u8FC7</span>
|
|
1810
|
-
<span class="lg st-cancelled">\u5DF2\u53D6\u6D88</span>
|
|
1811
|
-
<span class="lg st-blocked">\u53D7\u963B</span>
|
|
1812
|
-
<span class="lg st-failed">\u5931\u8D25</span>
|
|
1813
|
-
<span class="lg lg-loop">\u27F3 \u5FAA\u73AF\u5BB9\u5668</span>
|
|
1814
|
-
</div>
|
|
1815
|
-
</div>
|
|
1816
|
-
<div id="v3-node-panel" class="v3r-panel">
|
|
1817
|
-
<p class="muted">\u70B9\u4E00\u4E2A\u8282\u70B9\u770B\u8BE6\u60C5\u4E0E\u7EC8\u7AEF</p>
|
|
1818
|
-
</div>
|
|
1819
|
-
</div>`;let n=e.querySelector("#v3-graph"),a=e.querySelector("#v3-node-panel"),o=e.querySelector("#v3-runstatus"),i=null,r=!1,u=!1,c=null,p=null,f=null,h=null,y=null,g=!1;function v(O){c=O,y=null,g=!1,p&&q(p),P()}function M(O){y=O,g=!0,P()}function $(O){if(g&&y){let R=O.find(B=>B.id===y);if(R)return R}let A=O.filter(R=>R.status==="running");return A[A.length-1]??O[O.length-1]??null}function L(O,A,R){let z=new Map,b=se=>{if(z.has(se))return z.get(se);z.set(se,0);let ie=O.find(be=>be.id===se)?.depends.filter(be=>O.some(Me=>Me.id===be))??[],me=ie.length?1+Math.max(...ie.map(b)):0;return z.set(se,me),me},S=new Map,E=new Map,U=0;for(let se of O){let ie=b(se.id),me=S.get(ie)??0;S.set(ie,me+1),U=Math.max(U,me),E.set(se.id,{x:6+ie*138,y:6+me*42})}let ee=12+(z.size?Math.max(...z.values())*138+104:0),pe=12+U*42+30,he=[];for(let se of O){let ie=E.get(se.id);for(let me of se.depends){let be=E.get(me);if(!be)continue;let Me=be.x+104,le=be.y+30/2,ve=ie.x,$e=ie.y+30/2,Pe=(Me+ve)/2,Ge=A.get(se.id)?.status==="running"?" live":"";he.push(`<path class="v3r-edge${Ge}" d="M${Me},${le} C${Pe},${le} ${Pe},${$e} ${ve},${$e}" marker-end="url(#v3arrow-mini)"/>`)}}let ae=O.map(se=>{let ie=E.get(se.id),me=A.get(se.id),be=me?.status??"pending",Me=me?"":" ghost",le=me&&me.id===R?" sel":"",ve=me?` data-sel="${ze(me.id)}"`:"";return`<g class="v3r-node v3r-mini st-${be}${le}${Me}"${ve}${me?' style="cursor:pointer"':""}>
|
|
1820
|
-
<rect class="v3r-box" x="${ie.x}" y="${ie.y}" width="104" height="30" rx="8"/>
|
|
1821
|
-
<circle class="v3r-mini-dot" cx="${ie.x+13}" cy="${ie.y+30/2}" r="3.4"/>
|
|
1822
|
-
<text class="v3r-nid" x="${ie.x+24}" y="${ie.y+30/2+4}">${ze(ii(se.id,12))}</text>
|
|
1823
|
-
</g>`});return`<svg class="v3r-mini-svg" width="${ee}" height="${pe}" viewBox="0 0 ${ee} ${pe}">
|
|
1824
|
-
<defs><marker id="v3arrow-mini" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
|
1825
|
-
<path d="M0,0 L10,5 L0,10 z" fill="var(--faint, #8b98aa)"/></marker></defs>
|
|
1826
|
-
${he.join("")}${ae.join("")}
|
|
1827
|
-
</svg>`}function C(O,A){let R=O.loopState;if(!R)return'<p class="muted">loop \u672A\u5F00\u59CB</p>';let B=R.maxIterations,V=B!==void 0?B+R.granted:void 0,Z=new Map(R.decisions.map(E=>[E.iteration,E.decision])),G=(p?.nodes??[]).filter(E=>E.loop?.loopId===O.id),j=new Map;for(let E of G){let U=E.loop.iteration;(j.get(U)??j.set(U,[]).get(U)).push(E)}let z=[...j.entries()].sort((E,U)=>E[0]-U[0]).map(([E,U])=>{let ee=Z.get(E),pe=E===R.iteration,he=B!==void 0&&E>B,ae=ee?`<span class="v3r-verdict vd-${ee}">${nm[ee]}</span>`:pe&&O.status==="running"?'<span class="v3r-verdict vd-live">\u25B6 \u8FDB\u884C\u4E2D</span>':"",se=new Map(U.map(ie=>[ie.loop.bodyNodeId,ie]));return`<div class="v3r-round${pe?" cur":""}${ee?` vd-${ee}`:""}">
|
|
1828
|
-
<div class="v3r-round-head">
|
|
1829
|
-
<span class="rn">R${E}</span>
|
|
1830
|
-
${he?'<span class="v3r-granted-tag">\u2795 \u8FFD\u52A0\u8F6E</span>':""}
|
|
1831
|
-
${ae}
|
|
1832
|
-
</div>
|
|
1833
|
-
${L(R.bodyTemplate,se,A)}
|
|
1834
|
-
</div>`}).join(""),b=`<div class="v3r-loop-meter">
|
|
1835
|
-
<span class="num">\u7B2C <b>${R.iteration}</b>${V!==void 0?` / <b>${V}</b>`:""} \u8F6E</span>
|
|
1836
|
-
${R.granted>0?`<span class="v3r-granted-tag">\u542B\u4EBA\u5DE5\u8FFD\u52A0 +${R.granted}</span>`:""}
|
|
1837
|
-
${R.lastDecision==="exit"?'<span class="v3r-verdict vd-exit">\u2713 \u5DF2\u6536\u655B</span>':""}
|
|
1838
|
-
</div>`,S=O.status==="blocked"?`<div class="v3r-cta">\u26A0 \u8F6E\u6570\u8017\u5C3D\uFF0C\u7B49\u4EBA\u8FFD\u52A0 \u2014 \u98DE\u4E66\u5361\u7247\u70B9\u300C\u2795 \u8FFD\u52A0 1 \u8F6E\u300D\uFF0C\u6216 <code>botmux workflow grant ${ze(t)}</code></div>`:"";return`<div class="v3r-loop-sec">${b}<div class="v3r-rounds">${z}</div>${S}</div>`}function P(){let O=p?.nodes.find(j=>j.id===c)??null;if(!O){a.innerHTML='<p class="muted">\u70B9\u4E00\u4E2A\u8282\u70B9\u770B\u8BE6\u60C5\u4E0E\u7EC8\u7AEF</p>',f=null,h=null;return}f!==O.id&&(a.innerHTML=`
|
|
1839
|
-
<div id="v3-node-meta"></div>
|
|
1840
|
-
<div id="v3-inst-strip"></div>
|
|
1841
|
-
<div id="v3-term-slot" class="v3r-term-slot"></div>`,f=O.id,h=null);let A=O,R=null;if(O.isLoop){let j=(p?.nodes??[]).filter(b=>b.loop?.loopId===O.id),z=$(j);A=z,R=z?.id??null,y=R}let B=`<div class="v3r-panel-head">
|
|
1842
|
-
${O.isLoop?'<span class="v3r-loop-mark">\u27F3</span>':""}
|
|
1843
|
-
<span class="v3r-nodeid">${ze(O.id)}</span>
|
|
1844
|
-
<span class="v3r-pill st-${O.status}"><i class="dot"></i>${Ns[O.status]}</span>
|
|
1845
|
-
</div>`,V=O.errorClass?`<p class="v3r-err">\u539F\u56E0\uFF1A${ze(O.errorClass)}${O.errorCode?` (${ze(O.errorCode)})`:""}${O.status==="blocked"&&!O.isLoop?" \u2014 \u98DE\u4E66\u5361\u7247\u6216 <code>botmux workflow retry</code> \u53EF\u91CD\u8BD5":""}</p>`:"";a.querySelector("#v3-node-meta").innerHTML=`
|
|
1846
|
-
${B}
|
|
1847
|
-
${O.goal?`<p class="v3r-goal">${ze(O.goal)}</p>`:""}
|
|
1848
|
-
${O.depends.length?`<p class="v3r-deps">\u4F9D\u8D56 ${O.depends.map(j=>`<span class="v3r-dep">${ze(j)}</span>`).join("")}</p>`:""}
|
|
1849
|
-
${V}${O.isLoop?C(O,R):""}`,a.querySelector("#v3-inst-strip").innerHTML=O.isLoop&&A?`<div class="v3r-inst-strip">
|
|
1850
|
-
<span class="lbl">\u5B9E\u4F8B\u7EC8\u7AEF</span>
|
|
1851
|
-
<span class="v3r-nodeid sm">${ze(A.id)}</span>
|
|
1852
|
-
<span class="v3r-pill st-${A.status}"><i class="dot"></i>${Ns[A.status]}</span>
|
|
1853
|
-
<span class="muted">\u7B2C ${A.loop.iteration} \u8F6E \xB7 ${ze(A.loop.bodyNodeId)}${g?"":" \xB7 \u81EA\u52A8\u8DDF\u968F"}</span>
|
|
1854
|
-
</div>`:"";for(let j of a.querySelectorAll("#v3-node-meta [data-sel]"))j.addEventListener("click",z=>{z.stopPropagation(),M(j.getAttribute("data-sel"))});let Z=a.querySelector("#v3-term-slot");if(!A){Z.innerHTML="",h=null;return}let G=`${A.id}|${sm(A)}`;G!==h&&(gu(Z,t,A),h=G)}function H(O,A,R,B){let V=O.loopState,Z=V?.maxIterations,G=V&&Z!==void 0?Z+V.granted:void 0,j=V?`${Ns[O.status]} \xB7 \u7B2C${V.iteration}${G!==void 0?`/${G}`:""}\u8F6E`:`${Ns[O.status]} \xB7 loop`,z="";if(V&&G!==void 0&&G<=am){let b=R+Ho-13;for(let S=1;S<=G;S++){let E=A+14+(S-1)*15,U=S<V.iteration?"v3r-dot done":S===V.iteration?`v3r-dot cur${O.status==="running"?" live":""}`:"v3r-dot todo",ee=Z!==void 0&&S>Z?" grant":"";z+=`<circle class="${U}${ee}" cx="${E}" cy="${b}" r="3.6"/>`}V.lastDecision==="exit"?z+=`<text class="v3r-dots-verdict ok" x="${A+14+G*15+4}" y="${b+4}">\u2713</text>`:V.lastDecision==="exhausted"&&O.status==="blocked"&&(z+=`<text class="v3r-dots-verdict warn" x="${A+14+G*15+4}" y="${b+4}">\u26A0</text>`)}return`<g class="v3r-node v3r-loopnode st-${O.status}${B?" sel":""}" data-node="${ze(O.id)}">
|
|
1855
|
-
<rect class="v3r-cap" x="${A-4}" y="${R-4}" width="${qs+8}" height="${Ho+8}" rx="14"/>
|
|
1856
|
-
<rect class="v3r-box" x="${A}" y="${R}" width="${qs}" height="${Ho}" rx="10"/>
|
|
1857
|
-
<text class="v3r-spin" x="${A+14}" y="${R+21}">\u27F3</text>
|
|
1858
|
-
<text class="v3r-nid" x="${A+30}" y="${R+21}">${ze(ii(O.id,16))}</text>
|
|
1859
|
-
<text class="v3r-nstatus" x="${A+14}" y="${R+39}">${ze(j)}</text>
|
|
1860
|
-
${z}
|
|
1861
|
-
</g>`}function q(O){let A=O.nodes.filter(S=>!S.loop),R=rm(A),B=new Map;for(let S of A){let E=R.get(S.id)??0;(B.get(E)??B.set(E,[]).get(E)).push(S)}let V=new Map,Z=0;for(let[S,E]of B){let U=Do;for(let ee of E)V.set(ee.id,{x:Do+S*vu,y:U}),U+=ai(ee)+wu;Z=Math.max(Z,U-wu+Do)}let G=Do*2+(B.size===0?0:Math.max(...B.keys())*vu+qs),j=new Map(A.map(S=>[S.id,S])),z=[];for(let S of A){let E=V.get(S.id);if(E)for(let U of S.depends){let ee=V.get(U),pe=j.get(U);if(!ee||!pe)continue;let he=ee.x+qs,ae=ee.y+ai(pe)/2,se=E.x,ie=E.y+ai(S)/2,me=(he+se)/2,be=S.status==="running"?" live":"";z.push(`<path class="v3r-edge${be}" d="M${he},${ae} C${me},${ae} ${me},${ie} ${se},${ie}" marker-end="url(#v3arrow)"/>`)}}let b=A.map(S=>{let E=V.get(S.id),U=S.id===c;return S.isLoop?H(S,E.x,E.y,U):`<g class="v3r-node st-${S.status}${U?" sel":""}" data-node="${ze(S.id)}">
|
|
1862
|
-
<rect class="v3r-box" x="${E.x}" y="${E.y}" width="${qs}" height="${ri}" rx="10"/>
|
|
1863
|
-
<rect class="v3r-bar" x="${E.x}" y="${E.y+8}" width="3" height="${ri-16}" rx="1.5"/>
|
|
1864
|
-
<text class="v3r-nid" x="${E.x+14}" y="${E.y+20}">${ze(ii(S.id,18))}</text>
|
|
1865
|
-
<text class="v3r-nstatus" x="${E.x+14}" y="${E.y+37}">${Ns[S.status]}</text>
|
|
1866
|
-
</g>`});n.innerHTML=`<svg width="${G}" height="${Z}" viewBox="0 0 ${G} ${Z}" style="display:block">
|
|
1867
|
-
<defs><marker id="v3arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
1868
|
-
<path d="M0,0 L10,5 L0,10 z" fill="var(--faint, #8b98aa)"/></marker></defs>
|
|
1869
|
-
${z.join("")}${b.join("")}
|
|
1870
|
-
</svg>`;for(let S of n.querySelectorAll("[data-node]"))S.addEventListener("click",()=>v(S.getAttribute("data-node")))}async function I(){if(!(r||document.hidden))try{let O=await fetch(`/api/v3/runs/${encodeURIComponent(t)}`);if(!O.ok){if(O.status===404&&!u){u=!0;try{if((await fetch(`/api/workflows/runs/${encodeURIComponent(t)}/snapshot`)).ok&&!r){window.location.replace(bu(t,location.hash.split("?")[1]));return}}catch{}}r||(o.textContent=O.status===404?"not found":`HTTP ${O.status}`);return}let A=await O.json();if(r)return;if(p=A,o.textContent=A.runStatus,o.className=`v3r-pill rs-${A.runStatus}`,c===null&&A.nodes.length&&(c=A.nodes[0].id),q(A),P(),yu(A.runStatus)){i!==null&&window.clearTimeout(i),i=null;return}}catch{}}function N(){r||I().then(()=>{!r&&!yu(p?.runStatus)&&(i=window.setTimeout(N,ku))})}return N(),()=>{r=!0,i!==null&&window.clearTimeout(i)}}function rm(e){let t=new Map(e.map(i=>[i.id,i])),n=new Map,a=new Set;function o(i){if(n.has(i))return n.get(i);if(a.has(i))return 0;a.add(i);let u=(t.get(i)?.depends??[]).filter(p=>t.has(p)),c=u.length?1+Math.max(...u.map(o)):0;return a.delete(i),n.set(i,c),c}for(let i of e)o(i.id);return n}function ii(e,t){return e.length>t?e.slice(0,t-1)+"\u2026":e}function lm(){let e=[["",s("workflow.filter.nonTerminal")],["all",s("workflow.filter.all")],["pending",gn("pending")],["running",gn("running")],["waiting",gn("waiting")],["succeeded",gn("succeeded")],["failed",gn("failed")],["cancelled",gn("cancelled")]];return`
|
|
1871
|
-
<nav class="wf-subnav">
|
|
1872
|
-
<a href="#/legacy-workflow" class="active" data-i18n="workflow.subnav.runs">${D(s("workflow.subnav.runs"))}</a>
|
|
1873
|
-
<a href="#/workflows" data-i18n="workflow.subnav.v3">${D(s("workflow.subnav.v3"))}</a>
|
|
1874
|
-
</nav>
|
|
1875
|
-
<form id="wf-filters" class="filters">
|
|
1876
|
-
<input type="search" name="q" placeholder="${D(s("workflow.searchPlaceholder"))}" />
|
|
1877
|
-
<select name="status">
|
|
1878
|
-
${e.map(([t,n])=>`<option value="${D(t)}">${D(n)}</option>`).join("")}
|
|
1879
|
-
</select>
|
|
1880
|
-
<span id="wf-last-load" class="muted"></span>
|
|
1881
|
-
</form>
|
|
1882
|
-
<table>
|
|
1883
|
-
<thead><tr>
|
|
1884
|
-
<th>${D(s("workflow.table.run"))}</th><th>${D(s("workflow.table.workflow"))}</th><th>${D(s("workflow.table.status"))}</th>
|
|
1885
|
-
<th>${D(s("workflow.table.lastSeq"))}</th><th>${D(s("workflow.table.dangling"))}</th><th>${D(s("workflow.table.updated"))}</th>
|
|
1886
|
-
<th>${D(s("workflow.table.chatApp"))}</th>
|
|
1887
|
-
</tr></thead>
|
|
1888
|
-
<tbody id="wf-tbody"></tbody>
|
|
1889
|
-
</table>
|
|
1890
|
-
`}var um=5e3,cm=2e3,js=new Set(["succeeded","failed","cancelled"]);function D(e){return e.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}function dm(e){let t=new Date(e),a=Date.now()-e;return a<6e4?s("time.secondsAgo",{value:Math.max(1,Math.floor(a/1e3))}):a<36e5?s("time.minutesAgo",{value:Math.floor(a/6e4)}):a<864e5?s("time.hoursAgo",{value:Math.floor(a/36e5)}):t.toISOString().slice(0,19).replace("T"," ")}function Qt(e){return`<span class="${js.has(e)?"wf-status terminal":"wf-status live"} wf-status-${D(e)}">${D(gn(e))}</span>`}function gn(e){let t=`workflow.status.${e}`,n=s(t);return n===t?e:n}function Tu(e){let t=location.hash.match(/^#\/legacy-workflow\/([^?#]+)(?:\?([^#]*))?$/);if(t){let n=new URLSearchParams(t[2]??"");return fm(e,decodeURIComponent(t[1]),{focusAttemptId:n.get("attempt")??void 0})}return pm(e)}function pm(e){e.innerHTML=lm();let t=e.querySelector("#wf-tbody"),n=e.querySelector("#wf-filters"),a=e.querySelector("#wf-last-load"),o=[],i=null,r=!1,u=null,c=!1;function p(M){let L=(new FormData(n).get("q")??"").trim().toLowerCase();return L?M.filter(C=>C.runId.toLowerCase().includes(L)||C.workflowId.toLowerCase().includes(L)||(C.chatId??"").toLowerCase().includes(L)):M}function f(){let M=p(o);if(M.length===0){t.innerHTML=`<tr><td colspan="7" class="empty">${u?D(s("workflow.list.failedLoad",{error:u})):o.length===0?D(s("workflow.list.noRuns")):D(s("workflow.list.noFilterMatch"))}</td></tr>`;return}t.innerHTML=M.map($=>{let L=`${$.dEf}/${$.dAct}/${$.dWait}`,C=$.dEf+$.dAct+$.dWait>0?"wf-dangling has":"wf-dangling none",P=[];$.chatId&&P.push(D($.chatId)),$.larkAppId&&P.push(`<span class="muted">${D($.larkAppId)}</span>`);let H=P.length>0?P.join("<br/>"):"\u2014",q=hm($);return`<tr data-runid="${D($.runId)}">
|
|
1891
|
-
<td><a href="#/legacy-workflow/${encodeURIComponent($.runId)}"><code>${D($.runId)}</code></a></td>
|
|
1892
|
-
<td>${D($.workflowId)}</td>
|
|
1893
|
-
<td>${Qt($.status)}${$.failedNodeId?` <span class="muted">(${D($.failedNodeId)})</span>`:""}${q}</td>
|
|
1894
|
-
<td>${$.lastSeq}</td>
|
|
1895
|
-
<td class="${C}">${L}</td>
|
|
1896
|
-
<td title="${D(new Date($.updatedAt).toISOString())}">${dm($.updatedAt)}</td>
|
|
1897
|
-
<td>${H}</td>
|
|
1898
|
-
</tr>`}).join("")}function h(){u?(a.textContent=s("workflow.list.error",{error:u}),a.classList.add("error")):(a.textContent=s("workflow.list.loaded",{count:o.length,time:new Date().toLocaleTimeString()}),a.classList.remove("error"))}async function y(){if(!(c||r)&&!document.hidden){r=!0;try{let M=n.elements.namedItem("status")?.value??"",$=new URLSearchParams;M==="all"?$.set("all","1"):M&&$.set("status",M);let L="/api/workflows/runs"+($.toString()?`?${$}`:""),C=await fetch(L);C.ok?(o=(await C.json()).runs??[],u=null):(u=`HTTP ${C.status}`,o=[])}catch(M){u=M?.message??String(M),o=[]}finally{r=!1,c||(f(),h())}}}function g(){i!==null&&window.clearTimeout(i),i=window.setTimeout(async()=>{await y(),c||g()},um)}function v(){document.hidden||y()}return n.addEventListener("input",()=>{f()}),n.addEventListener("change",M=>{M.target.getAttribute("name")==="status"&&y()}),document.addEventListener("visibilitychange",v),y().then(()=>{c||g()}),()=>{c=!0,i!==null&&window.clearTimeout(i),document.removeEventListener("visibilitychange",v)}}function fm(e,t,n={}){e.innerHTML=`
|
|
1899
|
-
<div class="wf-detail-head">
|
|
1900
|
-
<a class="btn-link" href="#/legacy-workflow">${D(s("workflow.detail.back"))}</a>
|
|
1901
|
-
<div>
|
|
1902
|
-
<h2><code>${D(t)}</code></h2>
|
|
1903
|
-
<div id="wf-detail-subtitle" class="muted">${D(s("workflow.detail.loading"))}</div>
|
|
1904
|
-
</div>
|
|
1905
|
-
<button id="wf-cancel-run" type="button" class="contrast" hidden>${D(s("workflow.detail.cancel"))}</button>
|
|
1906
|
-
<span id="wf-detail-refresh" class="muted"></span>
|
|
1907
|
-
</div>
|
|
1908
|
-
<section id="wf-detail-error" class="hint-warn" hidden></section>
|
|
1909
|
-
<section id="wf-cancel-status" class="hint-ok" hidden></section>
|
|
1910
|
-
<section id="wf-summary" class="wf-summary-grid"></section>
|
|
1911
|
-
<section id="wf-dangling-panel"></section>
|
|
1912
|
-
<section class="wf-panel">
|
|
1913
|
-
<div class="wf-panel-title">
|
|
1914
|
-
<h3>${D(s("workflow.detail.parallel"))}</h3>
|
|
1915
|
-
<span id="wf-parallel-meta" class="muted"></span>
|
|
1916
|
-
</div>
|
|
1917
|
-
<div id="wf-parallel-view"></div>
|
|
1918
|
-
</section>
|
|
1919
|
-
<section class="wf-panel">
|
|
1920
|
-
<div class="wf-panel-title">
|
|
1921
|
-
<h3>${D(s("workflow.detail.nodes"))}</h3>
|
|
1922
|
-
</div>
|
|
1923
|
-
<div class="wf-table-scroll">
|
|
1924
|
-
<table>
|
|
1925
|
-
<thead><tr>
|
|
1926
|
-
<th>${D(s("workflow.detail.node"))}</th><th>${D(s("workflow.detail.nodeStatus"))}</th><th>${D(s("workflow.detail.activity"))}</th><th>${D(s("workflow.detail.activityStatus"))}</th>
|
|
1927
|
-
<th>${D(s("workflow.detail.attempts"))}</th><th>${D(s("workflow.detail.current"))}</th><th>${D(s("workflow.detail.detail"))}</th>
|
|
1928
|
-
</tr></thead>
|
|
1929
|
-
<tbody id="wf-node-tbody"></tbody>
|
|
1930
|
-
</table>
|
|
1931
|
-
</div>
|
|
1932
|
-
</section>
|
|
1933
|
-
<section class="wf-panel">
|
|
1934
|
-
<div class="wf-panel-title">
|
|
1935
|
-
<h3>${D(s("workflow.detail.nodeIO"))}</h3>
|
|
1936
|
-
</div>
|
|
1937
|
-
<div id="wf-io-list" class="wf-io-list"></div>
|
|
1938
|
-
</section>
|
|
1939
|
-
<section class="wf-panel">
|
|
1940
|
-
<div class="wf-panel-title">
|
|
1941
|
-
<h3>${D(s("workflow.detail.timeline"))}</h3>
|
|
1942
|
-
<button id="wf-load-older" type="button" hidden>${D(s("workflow.detail.loadOlder"))}</button>
|
|
1943
|
-
</div>
|
|
1944
|
-
<div class="wf-table-scroll wf-timeline-scroll">
|
|
1945
|
-
<table>
|
|
1946
|
-
<thead><tr>
|
|
1947
|
-
<th>${D(s("workflow.detail.seq"))}</th><th>${D(s("workflow.detail.event"))}</th><th>${D(s("workflow.detail.actor"))}</th><th>${D(s("workflow.detail.node"))}</th><th>${D(s("workflow.detail.activity"))}</th><th>${D(s("workflow.detail.error"))}</th><th>${D(s("workflow.detail.time"))}</th>
|
|
1948
|
-
</tr></thead>
|
|
1949
|
-
<tbody id="wf-event-tbody"></tbody>
|
|
1950
|
-
</table>
|
|
1951
|
-
</div>
|
|
1952
|
-
<div id="wf-event-meta" class="muted"></div>
|
|
1953
|
-
</section>
|
|
1954
|
-
`;let a=e.querySelector("#wf-detail-subtitle"),o=e.querySelector("#wf-detail-refresh"),i=e.querySelector("#wf-detail-error"),r=e.querySelector("#wf-cancel-status"),u=e.querySelector("#wf-summary"),c=e.querySelector("#wf-dangling-panel"),p=e.querySelector("#wf-parallel-view"),f=e.querySelector("#wf-parallel-meta"),h=e.querySelector("#wf-node-tbody"),y=e.querySelector("#wf-io-list"),g=e.querySelector(".wf-timeline-scroll"),v=e.querySelector("#wf-event-tbody"),M=e.querySelector("#wf-event-meta"),$=e.querySelector("#wf-cancel-run"),L=e.querySelector("#wf-load-older"),C=null,P=[],H=new Set,q=null,I=null,N=!1,O=0,A=null,R=!1,B=!1,V=!1,Z=new Set,G=new Map,j=new Map,z=new Map,b=new Set,S=new Map,E=new Set,U=new Map,ee=new Map,pe=0,he=n.focusAttemptId;function ae(K){if(!K){i.hidden=!0,i.textContent="";return}i.hidden=!1,i.textContent=K}function se(K){if(!K){r.hidden=!0,r.textContent="";return}r.hidden=!1,r.textContent=K}async function ie(){let K=await fetch(`/api/workflows/runs/${encodeURIComponent(t)}/snapshot`);if(K.status===404)throw new Error(s("workflow.detail.unknownRun"));if(!K.ok)throw new Error(s("workflow.detail.snapshotHttp",{status:K.status}));C=await K.json()}async function me(K){let Ae=await fetch(`/api/workflows/runs/${encodeURIComponent(t)}/events?${K}`);if(Ae.status===404)throw new Error(s("workflow.detail.unknownRun"));if(!Ae.ok)throw new Error(s("workflow.detail.eventsHttp",{status:Ae.status}));return await Ae.json()}function be(K,Ae){let fe=K.filter(re=>H.has(re.eventId)?!1:(H.add(re.eventId),!0));fe.length!==0&&(P=Ae==="prepend"?[...fe,...P]:[...P,...fe],P.sort((re,Be)=>Us(re.eventId)-Us(Be.eventId)))}async function Me(){await ie();let K=await me(new URLSearchParams({tail:"100"}));P=[],H=new Set,be(K.events,"append"),q=K.oldestSeq,I=K.newestSeq,N=K.hasOlder,O=K.totalCount,He()}async function le(){if(!(R||B||document.hidden)){B=!0;try{if(await ie(),I!==null){let K=await me(new URLSearchParams({afterSeq:String(I),limit:"200"}));be(K.events,"append"),K.newestSeq!==null&&(I=K.newestSeq),q===null&&K.oldestSeq!==null&&(q=K.oldestSeq),O=K.totalCount}else{let K=await me(new URLSearchParams({tail:"1"}));be(K.events,"append"),q=K.oldestSeq,I=K.newestSeq,N=K.hasOlder,O=K.totalCount}ae(null),He()}catch(K){ae(K?.message??String(K))}finally{B=!1}}}async function ve(){if(!(q===null||!N)){L.disabled=!0;try{let K=await me(new URLSearchParams({beforeSeq:String(q),limit:"100"}));be(K.events,"prepend"),K.oldestSeq!==null&&(q=K.oldestSeq),N=K.hasOlder,O=K.totalCount,ae(null),He()}catch(K){ae(K?.message??String(K))}finally{L.disabled=!1}}}async function $e(){if(!C||js.has(C.run.status)||V)return;if(!C.chatBinding?.larkAppId){ae(s("workflow.detail.cancelUnavailable",{runId:t}));return}let K=gm(C),Ae=s("workflow.detail.cancelConfirm",{runId:t,...K});if(window.confirm(Ae)){V=!0,$.disabled=!0;try{let fe=await fetch(`/api/workflows/runs/${encodeURIComponent(t)}/cancel`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({reason:"cancelled via dashboard"})});if(fe.status===401)throw new Error(s("workflow.detail.writeAccessCancel"));let re=await fe.json().catch(()=>({}));if(!fe.ok||!re.ok)throw new Error(re.hint??re.error??s("workflow.detail.cancelHttp",{status:fe.status}));se(re.pending?s("workflow.detail.cancelPending"):null),ae(null),await le()}catch(fe){ae(fe?.message??String(fe))}finally{V=!1,$.disabled=!1,He()}}}async function Pe(K,Ae){if(!E.has(K)){E.add(K),U.delete(K),He();try{let fe=await fetch(`/api/workflows/runs/${encodeURIComponent(t)}/attempts/${encodeURIComponent(Ae)}/${encodeURIComponent(K)}/resume`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({})});if(fe.status===401)throw new Error(s("workflow.detail.writeAccessResume"));let re=await fe.json().catch(()=>({}));if(!fe.ok||!re.ok||!re.resumeId||!re.url)throw new Error(re.hint??re.message??re.error??s("workflow.detail.resumeStartFailed",{status:fe.status}));S.set(K,{resumeId:re.resumeId,url:re.url})}catch(fe){let re=fe?.message??String(fe);U.set(K,re)}finally{E.delete(K),He()}}}async function Ge(K,Ae){if(!E.has(K)){E.add(K),U.delete(K),He();try{let fe=await fetch(`/api/workflows/runs/${encodeURIComponent(t)}/attempts/${encodeURIComponent(Ae)}/${encodeURIComponent(K)}/resume/end`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({reason:"ended_by_dashboard"})});if(fe.status===401)throw new Error(s("workflow.detail.writeAccessResume"));let re=await fe.json().catch(()=>({}));if(!fe.ok||!re.ok)if(re.error==="resume_not_running")S.delete(K);else throw new Error(re.hint??re.message??re.error??s("workflow.detail.resumeEndFailed",{status:fe.status}));else S.delete(K)}catch(fe){let re=fe?.message??String(fe);U.set(K,re)}finally{E.delete(K),He()}}}async function it(K,Ae){if(!b.has(K)){b.add(K),z.delete(K),He();try{let fe=j.get(K)?.trim()||void 0,re=await fetch(`/api/workflows/runs/${encodeURIComponent(t)}/${Ae}`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({comment:fe})});if(re.status===401)throw new Error(s("workflow.detail.writeAccessApproval"));let Be=await re.json().catch(()=>({}));if(!re.ok||!Be.ok)throw new Error(Be.hint??Be.message??Be.error??s("workflow.detail.actionHttp",{action:Ae,status:re.status}));let rt=Ae==="approve"?s("workflow.detail.approved"):s("workflow.detail.rejected");z.set(K,{kind:"ok",text:Be.alreadyTerminal?s("workflow.detail.alreadyTerminal",{label:rt}):Be.pending?s("workflow.detail.workflowContinue",{label:rt}):s("workflow.detail.workflowRefreshing",{label:rt})}),ae(null),await le()}catch(fe){let re=fe?.message??String(fe);z.set(K,{kind:"error",text:re}),ae(re)}finally{b.delete(K),He()}}}function He(){if(!C)return;pe=g.scrollTop;let K=C.run;js.has(K.status)&&se(null),a.innerHTML=`${D(K.workflowId??"?")} \xB7 ${Qt(K.status)} \xB7 lastSeq ${C.lastSeq}`,o.textContent=s("workflow.detail.refreshed",{time:new Date().toLocaleTimeString()}),$.hidden=js.has(K.status),$.disabled=V||!C.chatBinding?.larkAppId,$.textContent=C.chatBinding?.larkAppId?s("workflow.detail.cancel"):s("workflow.detail.cliCancelOnly"),$.title=C.chatBinding?.larkAppId?s("workflow.detail.cancelTitle"):s("workflow.detail.cliCancelTitle",{runId:t}),mm(u,C),bm(c,C),ym(p,f,C,P),Sm(h,C),Em(y,C,Z,G,{comments:j,statuses:z,resolving:b,onResolve:it},{sessions:S,pending:E,errors:U,onStart:Pe,onEnd:Ge},he,ee)&&(he=void 0),Zm(v,P),g.scrollTop=pe,L.hidden=!N,M.textContent=s("workflow.detail.eventsLoaded",{loaded:P.length,total:O})}function Xe(){if(A!==null&&window.clearTimeout(A),C&&js.has(C.run.status)){A=null;return}A=window.setTimeout(async()=>{await le(),R||Xe()},cm)}function Ye(){document.hidden||le().then(()=>{!R&&A===null&&Xe()})}return L.addEventListener("click",()=>{ve()}),$.addEventListener("click",()=>{$e()}),document.addEventListener("visibilitychange",Ye),Me().then(()=>{ae(null),R||Xe()}).catch(K=>{ae(K?.message??String(K)),a.textContent=s("workflow.detail.loadFailed")}),()=>{R=!0,A!==null&&window.clearTimeout(A),document.removeEventListener("visibilitychange",Ye)}}function mm(e,t){let n=t.run,a=[[s("workflow.summary.workflow"),D(n.workflowId??"?")],[s("workflow.summary.status"),Qt(n.status)],[s("workflow.summary.lastSeq"),String(t.lastSeq)],[s("workflow.summary.updated"),D(new Date(t.updatedAt).toLocaleString())],[s("workflow.summary.revision"),D(Po(n.revisionId))],[s("workflow.summary.initiator"),D(n.initiator??"-")]];n.failedNodeId&&a.push([s("workflow.summary.failedNode"),D(n.failedNodeId)]),n.cancelOriginEventId&&a.push([s("workflow.summary.cancelOrigin"),D(n.cancelOriginEventId)]),t.chatBinding&&(a.push([s("workflow.summary.chat"),`<code>${D(t.chatBinding.chatId)}</code>`]),a.push([s("workflow.summary.app"),`<code>${D(t.chatBinding.larkAppId)}</code>`])),e.innerHTML=a.map(([o,i])=>`<div class="wf-summary-item"><span>${o}</span><strong>${i}</strong></div>`).join("")}function hm(e){if(!e.errorCode)return"";let t=e.errorMessage?` \u2014 ${t0(e.errorMessage,96)}`:"";return`<div class="wf-run-error">
|
|
1955
|
-
<span class="muted error">${D(e.errorCode)}</span>${D(t)}
|
|
1956
|
-
</div>`}function gm(e){let t=e.dangling;return{total:new Set([...t.activities,...t.effectAttempted,...t.waits,...t.cancels]).size,effects:t.effectAttempted.length,activities:t.activities.length,waits:t.waits.length,cancels:t.cancels.length}}function bm(e,t){let n=t.dangling,a=[[s("workflow.dangling.activities"),n.activities],[s("workflow.dangling.effects"),n.effectAttempted],[s("workflow.dangling.waits"),n.waits],[s("workflow.dangling.cancels"),n.cancels]],o=new Set(a.flatMap(([,i])=>i)).size;if(e.className=o>0?"wf-panel wf-dangling-panel has":"wf-panel wf-dangling-panel",o===0){e.innerHTML=`<div class="wf-panel-title"><h3>${D(s("workflow.detail.dangling"))}</h3></div><div class="muted">${D(s("workflow.detail.noDangling"))}</div>`;return}e.innerHTML=`<div class="wf-panel-title"><h3>${D(s("workflow.detail.dangling"))}</h3><span class="wf-dangling has">${o}</span></div>
|
|
1957
|
-
<div class="wf-dangling-grid">
|
|
1958
|
-
${a.map(([i,r])=>`<div><strong>${i}</strong>${r.length===0?`<div class="muted">${D(s("workflow.detail.none"))}</div>`:`<ul>${r.map(u=>`<li><code>${D(u)}</code></li>`).join("")}</ul>`}</div>`).join("")}
|
|
1959
|
-
</div>`}function ym(e,t,n,a){let o=vm(a,n);if(o.length===0){t.textContent="",e.innerHTML=`<div class="empty">${D(s("workflow.detail.noParallelData"))}</div>`;return}let i=Date.now(),r=Math.min(...o.map(y=>y.startedAt)),u=Math.max(...o.map(y=>y.endedAt??i),r+1e3),c=Math.max(1,u-r),p=km(o,i),f=o.filter(y=>!y.endedAt&&(y.status==="running"||y.status==="effectAttempting")).length;t.textContent=s("workflow.detail.parallelMeta",{count:o.length,max:p,running:f});let h=o.sort((y,g)=>y.startedAt-g.startedAt||y.activityId.localeCompare(g.activityId)).map(y=>wm(y,r,c,i)).join("");e.innerHTML=`<div class="wf-parallel-axis">
|
|
1960
|
-
<span title="${D(new Date(r).toISOString())}">${D(Ro(r))}</span>
|
|
1961
|
-
<span title="${D(new Date(u).toISOString())}">${D(Ro(u))}</span>
|
|
1962
|
-
</div>
|
|
1963
|
-
<div class="wf-parallel-list">${h}</div>`}function vm(e,t){let n=new Map,a=new Map(t.activities.map(o=>[o.activityId,o.ownerNodeId]));for(let o of[...e].sort((i,r)=>Us(i.eventId)-Us(r.eventId))){let i=e0(o);if(!i)continue;let r=typeof i.activityId=="string"?i.activityId:void 0,u=typeof i.attemptId=="string"?i.attemptId:void 0;if(!r||!u)continue;let c=n.get(u);if(o.type==="attemptCreated"){let p=typeof i.attemptNumber=="number"?i.attemptNumber:void 0;c={nodeId:typeof i.nodeId=="string"?i.nodeId:a.get(r),activityId:r,attemptId:u,attemptNumber:p,status:"pending",startedAt:o.timestamp},n.set(u,c);continue}c||(c={nodeId:a.get(r),activityId:r,attemptId:u,status:"pending",startedAt:o.timestamp},n.set(u,c)),o.type==="activityRunning"?(c.status="running",c.runningAt=o.timestamp):o.type==="effectAttempted"?c.status="effectAttempting":o.type==="activityWaiting"||o.type==="waitCreated"?c.status="waiting":$m(o.type)&&(c.status=xm(o.type),c.endedAt=o.timestamp,c.endType=o.type)}return[...n.values()]}function wm(e,t,n,a){let o=e.endedAt??a,i=Eu((e.startedAt-t)/n*100,0,100),r=Eu((Math.max(o,e.startedAt+1)-e.startedAt)/n*100,.7,100-i),u=e.nodeId??e.activityId,c=e.attemptNumber!==void 0?`#${e.attemptNumber}`:Po(e.attemptId),p=[`${u} ${e.status}`,`${new Date(e.startedAt).toISOString()} \u2192 ${e.endedAt?new Date(e.endedAt).toISOString():s("workflow.detail.parallelNow")}`,e.endType?`end: ${e.endType}`:void 0].filter(Boolean).join(`
|
|
1964
|
-
`);return`<div class="wf-parallel-row">
|
|
1965
|
-
<div class="wf-parallel-label">
|
|
1966
|
-
<code>${D(u)}</code>
|
|
1967
|
-
<span class="muted">${D(e.activityId)} \xB7 ${D(c)}</span>
|
|
1968
|
-
</div>
|
|
1969
|
-
<div class="wf-parallel-track">
|
|
1970
|
-
<div class="wf-parallel-bar wf-parallel-${D(e.status)}" style="left:${i.toFixed(3)}%;width:${r.toFixed(3)}%;" title="${D(p)}">
|
|
1971
|
-
<span>${D(gn(e.status))}</span>
|
|
1972
|
-
</div>
|
|
1973
|
-
</div>
|
|
1974
|
-
</div>`}function km(e,t){let n=[];for(let i of e)n.push({time:i.startedAt,delta:1}),n.push({time:i.endedAt??t,delta:-1});n.sort((i,r)=>i.time-r.time||r.delta-i.delta);let a=0,o=0;for(let i of n)a+=i.delta,o=Math.max(o,a);return o}function $m(e){return e==="activitySucceeded"||e==="activityFailed"||e==="activityTimedOut"||e==="activityCanceled"}function xm(e){return e==="activitySucceeded"?"succeeded":e==="activityCanceled"?"cancelled":e==="activityTimedOut"?"timedOut":"failed"}function Sm(e,t){let n=new Map(t.activities.map(i=>[i.activityId,i])),a=new Set,o=[];for(let i of t.nodes){let r=(i.activityId?n.get(i.activityId):void 0)??t.activities.find(u=>u.ownerNodeId===i.nodeId);r&&a.add(r.activityId),o.push(xu(i,r))}for(let i of t.activities)a.has(i.activityId)||o.push(xu(void 0,i));e.innerHTML=o.length>0?o.join(""):`<tr><td colspan="7" class="empty">${D(s("workflow.detail.noNodes"))}</td></tr>`}function xu(e,t){let n=t?.attempts[t.attempts.length-1];return`<tr>
|
|
1975
|
-
<td>${e?`<code>${D(e.nodeId)}</code>`:'<span class="muted">-</span>'}</td>
|
|
1976
|
-
<td>${e?Qt(e.status):'<span class="muted">-</span>'}</td>
|
|
1977
|
-
<td>${t?`<code>${D(t.activityId)}</code>`:'<span class="muted">-</span>'}</td>
|
|
1978
|
-
<td>${t?Qt(t.status):'<span class="muted">-</span>'}</td>
|
|
1979
|
-
<td>${t?.attempts.length??0}</td>
|
|
1980
|
-
<td>${n?`<code>${D(n.attemptId)}</code>`:'<span class="muted">-</span>'}</td>
|
|
1981
|
-
<td>${n?Ym(n):`<span class="muted">${D(s("workflow.detail.idle"))}</span>`}</td>
|
|
1982
|
-
</tr>`}function Em(e,t,n,a,o,i,r,u){zm(e,n,a),Nm(e,o.comments);let c=!!(r&&t.attemptIO?.[r]?.terminal);c&&r&&n.add(li(r,s("workflow.detail.liveTerminal")));let p=Tm(t),f=new Set;if(u){for(let y of p){f.add(y.key);let g=u.get(y.key);g||(g=Lm(y.key),u.set(y.key,g),e.appendChild(g.article)),Cm(g,y,n,o,i,r)}for(let[y,g]of Array.from(u))f.has(y)||(g.article.remove(),u.delete(y));if(p.length===0){if(!e.querySelector(".wf-io-empty-placeholder")){let y=document.createElement("div");y.className="empty wf-io-empty-placeholder",y.textContent=s("workflow.detail.noNodeIO"),e.appendChild(y)}}else e.querySelector(".wf-io-empty-placeholder")?.remove()}else{let y=[];for(let g of p)y.push(Hm(g,n,o,i,r));e.innerHTML=y.length>0?y.join(""):`<div class="empty">${D(s("workflow.detail.noNodeIO"))}</div>`}Wm(e,a);let h=Um(e,r);return Gm(e,n),Vm(e,a),jm(e,o),Ru(e,i),h&&c}function Tm(e){let t=new Map(e.activities.map(o=>[o.activityId,o])),n=new Set,a=[];for(let o of e.nodes){let i=(o.activityId?t.get(o.activityId):void 0)??e.activities.find(r=>r.ownerNodeId===o.nodeId);if(!i){a.push({key:`node:${o.nodeId}`,node:o});continue}n.add(i.activityId),a.push({key:`activity:${i.activityId}`,node:o,activity:i,io:e.attemptIO?.[_o(i)?.attemptId??""]})}for(let o of e.activities)n.has(o.activityId)||a.push({key:`activity:${o.activityId}`,activity:o,io:e.attemptIO?.[_o(o)?.attemptId??""]});return a}function Lm(e){let t=document.createElement("article");t.className="wf-io-card",t.dataset.wfCardKey=e;let n=document.createElement("div");n.className="wf-io-card-head";let a=document.createElement("div");a.className="wf-io-terminal-slot";let o=document.createElement("div");return o.className="wf-io-grid",t.appendChild(n),t.appendChild(a),t.appendChild(o),{article:t,head:n,terminalSlot:a,grid:o,currentTerminalUrl:null}}function Cm(e,t,n,a,o,i){let r=_o(t.activity),u=t.node?.nodeId??t.activity?.ownerNodeId??t.activity?.activityId??"unknown",c=!!(r&&r.attemptId===i);e.article.classList.toggle("is-focused",c),r?e.article.dataset.wfAttemptCard=r.attemptId:delete e.article.dataset.wfAttemptCard;let p=_u(r,a);e.head.innerHTML=`
|
|
1983
|
-
<header>
|
|
1984
|
-
<div>
|
|
1985
|
-
<strong><code>${D(u)}</code></strong>
|
|
1986
|
-
<span class="muted">${t.activity?D(t.activity.activityId):D(s("workflow.detail.notDispatched"))}</span>
|
|
1987
|
-
</div>
|
|
1988
|
-
<div>${t.node?Qt(t.node.status):""} ${t.activity?Qt(t.activity.status):""}</div>
|
|
1989
|
-
</header>
|
|
1990
|
-
<div class="wf-io-meta">
|
|
1991
|
-
${r?`${D(s("workflow.detail.attempt"))} <code>${D(r.attemptId)}</code>`:D(s("workflow.detail.noAttempt"))}
|
|
1992
|
-
</div>
|
|
1993
|
-
${p}
|
|
1994
|
-
`;let f=Lu(r,t.activity,t.io?.terminal,o),h=f?.url??null;if(h!==e.currentTerminalUrl)f===null?e.terminalSlot.innerHTML="":e.terminalSlot.innerHTML=Cu(t.key,r,t.activity,t.io?.terminal,f,n,o),e.currentTerminalUrl=h;else if(f!==null&&t.io?.terminal){let g=e.terminalSlot.querySelector("details.wf-terminal-block > summary");if(g){let v=Iu(f.kind);g.innerHTML=`${D(v)} ${Hu(r,t.io.terminal)}`}r&&qm(e.terminalSlot,r,t.activity,t.io.terminal,f,o)}let y=r?.attemptId??t.activity?.activityId??t.node?.nodeId??"unknown";e.grid.innerHTML=`
|
|
1995
|
-
${jt(y,s("workflow.detail.authoredInput"),t.io?.input,n)}
|
|
1996
|
-
${jt(y,s("workflow.detail.resolvedInput"),t.io?.resolvedInput,n)}
|
|
1997
|
-
${jt(y,s("workflow.detail.output"),t.io?.output,n)}
|
|
1998
|
-
${jt(y,s("workflow.detail.executionLog"),t.io?.log,n)}
|
|
1999
|
-
${t.io?.waitPrompt?jt(y,s("workflow.detail.waitPrompt"),t.io.waitPrompt,n):""}
|
|
2000
|
-
`}function Lu(e,t,n,a){if(!n||n.error)return null;if(_m(e,n))return{kind:"live",url:Pm(n)};if(!e||!t||!Rm(e,n))return null;let o=Om();if(!o)return null;let i=a?.sessions.get(e.attemptId);return i?{kind:"resume",url:i.url,resumeId:i.resumeId,downloadUrl:Su(o,t.activityId,e.attemptId)}:{kind:"replay",url:Bm(o,t.activityId,e.attemptId,!!n.hasPtyLog),downloadUrl:Su(o,t.activityId,e.attemptId)}}function Cu(e,t,n,a,o,i,r){if(!a)return"";let u=Iu(o.kind),c=li(e,u),p=Hu(t,a),f=Im(o.kind),h=o.kind==="replay"||o.kind==="resume"?`<a class="btn-link" href="${D(o.downloadUrl)}" download>${D(s("workflow.detail.downloadFullLog"))}</a>`:"",y=t?Au(t,n,a,o,r):"",g=t?Du(t.attemptId,r):"";return`<details class="wf-io-block wf-terminal-block" data-io-key="${D(c)}"${i.has(c)?" open":""}>
|
|
2001
|
-
<summary>${D(u)} ${p}</summary>
|
|
2002
|
-
<div class="wf-terminal-actions">
|
|
2003
|
-
<a class="btn-link" href="${D(o.url)}" target="_blank" rel="noreferrer">${D(f)}</a>
|
|
2004
|
-
${h}
|
|
2005
|
-
${y}
|
|
2006
|
-
</div>
|
|
2007
|
-
${g}
|
|
2008
|
-
<iframe class="wf-terminal-frame" src="${D(o.url)}" title="${D(u)}" loading="lazy"></iframe>
|
|
2009
|
-
</details>`}function Iu(e){return e==="live"?s("workflow.detail.liveTerminal"):e==="resume"?s("workflow.detail.terminalResume"):s("workflow.detail.terminalReplay")}function Im(e){return e==="live"?s("workflow.detail.openTerminalNewTab"):e==="resume"?s("workflow.detail.openResumeNewTab"):s("workflow.detail.openReplayNewTab")}var Mu=new Set(["antigravity","codex-app","cursor","mira"]),Mm=new Set(["aiden","coco","claude-code","seed","relay","codex","mtr","hermes","pi","mir"]);function Am(e){return!!e&&(Mm.has(e)||Mu.has(e))}function Dm(e){return!!e&&Mu.has(e)}function Au(e,t,n,a,o){if(!o||a.kind==="live"||!t)return"";let i=a.kind==="resume",r=o.pending.has(e.attemptId),u=`data-wf-resume-attempt="${D(e.attemptId)}" data-wf-resume-activity="${D(t.activityId)}"`;return i?`<button type="button" class="btn-link" data-wf-resume-button="1" data-wf-resume-action="end" ${u}${r?" disabled":""}>${D(r?s("workflow.detail.resumeEnding"):s("workflow.detail.endResumeSession"))}</button>`:Am(n.cliId)?Dm(n.cliId)&&!n.cliSessionId?`<button type="button" class="btn-link" data-wf-resume-button="1" disabled title="${D(s("workflow.detail.resumeMissingCliSession"))}">${D(s("workflow.detail.resumeSession"))}</button>`:`<button type="button" class="btn-link" data-wf-resume-button="1" data-wf-resume-action="start" ${u}${r?" disabled":""}>${D(r?s("workflow.detail.resumeStarting"):s("workflow.detail.resumeSession"))}</button>`:`<button type="button" class="btn-link" data-wf-resume-button="1" disabled title="${D(s("workflow.detail.resumeUnsupportedCli",{cliId:n.cliId??"?"}))}">${D(s("workflow.detail.resumeSession"))}</button>`}function Du(e,t){if(!t)return"";let n=t.errors.get(e);return n?`<div class="hint-warn wf-resume-status" data-wf-resume-status="${D(e)}">${D(n)}</div>`:""}function Hm(e,t,n,a,o){let i=_o(e.activity),r=e.node?.nodeId??e.activity?.ownerNodeId??e.activity?.activityId??"unknown",u=i?.attemptId??e.activity?.activityId??e.node?.nodeId??"unknown",c=_u(i,n),p=i?.attemptId===o?" is-focused":"",f=i?` data-wf-attempt-card="${D(i.attemptId)}"`:"",h=Lu(i,e.activity,e.io?.terminal,a),y=h?Cu(u,i,e.activity,e.io?.terminal,h,t,a):"";return`<article class="wf-io-card${p}" data-wf-card-key="${D(e.key)}"${f}>
|
|
2010
|
-
<div class="wf-io-card-head">
|
|
2011
|
-
<header>
|
|
2012
|
-
<div>
|
|
2013
|
-
<strong><code>${D(r)}</code></strong>
|
|
2014
|
-
<span class="muted">${e.activity?D(e.activity.activityId):D(s("workflow.detail.notDispatched"))}</span>
|
|
2015
|
-
</div>
|
|
2016
|
-
<div>${e.node?Qt(e.node.status):""} ${e.activity?Qt(e.activity.status):""}</div>
|
|
2017
|
-
</header>
|
|
2018
|
-
<div class="wf-io-meta">
|
|
2019
|
-
${i?`${D(s("workflow.detail.attempt"))} <code>${D(i.attemptId)}</code>`:D(s("workflow.detail.noAttempt"))}
|
|
2020
|
-
</div>
|
|
2021
|
-
${c}
|
|
2022
|
-
</div>
|
|
2023
|
-
<div class="wf-io-terminal-slot">${y}</div>
|
|
2024
|
-
<div class="wf-io-grid">
|
|
2025
|
-
${jt(u,s("workflow.detail.authoredInput"),e.io?.input,t)}
|
|
2026
|
-
${jt(u,s("workflow.detail.resolvedInput"),e.io?.resolvedInput,t)}
|
|
2027
|
-
${jt(u,s("workflow.detail.output"),e.io?.output,t)}
|
|
2028
|
-
${jt(u,s("workflow.detail.executionLog"),e.io?.log,t)}
|
|
2029
|
-
${e.io?.waitPrompt?jt(u,s("workflow.detail.waitPrompt"),e.io.waitPrompt,t):""}
|
|
2030
|
-
</div>
|
|
2031
|
-
</article>`}function _o(e){return e?.attempts[e.attempts.length-1]}function Hu(e,t){let n=[];return t.error?n.push(s("workflow.detail.error")):n.push(t.status==="live"?s("workflow.detail.terminalLive"):s("workflow.detail.terminalClosedShort")),e?.status&&n.push(e.status),t.webPort>0&&n.push(`:${t.webPort}`),`<span class="muted">${D(n.join(" \xB7 "))}</span>`}function _m(e,t){return t.status==="live"&&t.webPort>0&&(e?.status==="pending"||e?.status==="running"||e?.status==="effectAttempting")}function Rm(e,t){return e.status==="succeeded"||e.status==="failed"||e.status==="cancelled"||e.status==="timedOut"?!!(t.sessionId||t.startedAt):!1}function Pm(e){return`http://${window.location.hostname||"127.0.0.1"}:${e.webPort}`}function Bm(e,t,n,a){let o=new URLSearchParams({runId:e,activityId:t,attemptId:n});return a&&o.set("hasPtyLog","1"),`/assets/terminal-replay.html?${o.toString()}`}function Su(e,t,n){return`/api/workflows/runs/${encodeURIComponent(e)}/attempts/${encodeURIComponent(t)}/${encodeURIComponent(n)}/terminal-log/raw?download=1`}function Om(){let e=window.location.hash.match(/^#\/legacy-workflow\/([^/?#]+)/);if(!e)return null;try{return decodeURIComponent(e[1])}catch{return null}}function _u(e,t){if(!Fm(e))return"";let n=e.attemptId,a=t.comments.get(n)??"",o=t.resolving.has(n),i=t.statuses.get(n),r=i?.kind==="error"?"hint-warn":"hint-ok";return`<div class="wf-approval-box" data-wf-approval="${D(n)}">
|
|
2032
|
-
<label>
|
|
2033
|
-
<span>${D(s("workflow.detail.approvalComment"))}</span>
|
|
2034
|
-
<textarea class="wf-approval-comment" data-wf-approval-comment="${D(n)}" rows="2" placeholder="${D(s("workflow.detail.optionalComment"))}"${o?" disabled":""}>${D(a)}</textarea>
|
|
2035
|
-
</label>
|
|
2036
|
-
<div class="wf-approval-actions">
|
|
2037
|
-
<button type="button" class="primary" data-wf-approval-action="approve" data-wf-attempt-id="${D(n)}"${o?" disabled":""}>${D(s("workflow.detail.approve"))}</button>
|
|
2038
|
-
<button type="button" data-wf-approval-action="reject" data-wf-attempt-id="${D(n)}"${o?" disabled":""}>${D(s("workflow.detail.reject"))}</button>
|
|
2039
|
-
${o?`<span class="muted">${D(s("workflow.detail.submitting"))}</span>`:""}
|
|
2040
|
-
</div>
|
|
2041
|
-
${i?`<div class="${r} wf-approval-status">${D(i.text)}</div>`:""}
|
|
2042
|
-
</div>`}function Fm(e){return!!e&&e.status==="waiting"&&e.wait?.waitKind==="human-gate"&&!e.wait.resolution}function Nm(e,t){e.querySelectorAll("textarea[data-wf-approval-comment]").forEach(n=>{let a=n.dataset.wfApprovalComment;a&&t.set(a,n.value)})}function Ru(e,t){e.querySelectorAll("button[data-wf-resume-action][data-wf-resume-attempt][data-wf-resume-activity]").forEach(n=>{n.dataset.wfResumeBound!=="1"&&(n.dataset.wfResumeBound="1",n.addEventListener("click",()=>{let a=n.dataset.wfResumeAttempt,o=n.dataset.wfResumeActivity,i=n.dataset.wfResumeAction;!a||!o||(i==="start"?t.onStart(a,o):i==="end"&&t.onEnd(a,o))}))})}function qm(e,t,n,a,o,i){let r=e.querySelector(".wf-terminal-actions");if(!r)return;let u=r.querySelector('button[data-wf-resume-button="1"]'),c=Au(t,n,a,o,i);u?u.outerHTML=c:c&&r.insertAdjacentHTML("beforeend",c);let p=e.querySelector("details.wf-terminal-block");if(p){let f=p.querySelector(".wf-resume-status"),h=Du(t.attemptId,i);f?f.outerHTML=h:h&&r.insertAdjacentHTML("afterend",h)}Ru(e,i)}function jm(e,t){e.querySelectorAll("textarea[data-wf-approval-comment]").forEach(n=>{let a=n.dataset.wfApprovalComment;a&&n.addEventListener("input",()=>{t.comments.set(a,n.value)})}),e.querySelectorAll("button[data-wf-approval-action][data-wf-attempt-id]").forEach(n=>{n.addEventListener("click",()=>{let a=n.dataset.wfAttemptId,o=n.dataset.wfApprovalAction;!a||o!=="approve"&&o!=="reject"||t.onResolve(a,o)})})}function jt(e,t,n,a){let o=li(e,t);return`<details class="wf-io-block" data-io-key="${D(o)}"${a.has(o)?" open":""}>
|
|
2043
|
-
<summary>${D(t)} ${Km(n)}</summary>
|
|
2044
|
-
${Jm(n)}
|
|
2045
|
-
</details>`}function li(e,t){return`${e}:${t}`}function Um(e,t){if(!t)return!1;for(let n of e.querySelectorAll("[data-wf-attempt-card]"))if(n.dataset.wfAttemptCard===t)return n.scrollIntoView({block:"center"}),!0;return!1}function zm(e,t,n){e.querySelectorAll("details.wf-io-block[data-io-key]").forEach(a=>{let o=a.dataset.ioKey;if(!o)return;a.open?t.add(o):t.delete(o);let i=a.querySelector(".wf-io-pre");i&&n.set(o,i.scrollTop)})}function Gm(e,t){e.querySelectorAll("details.wf-io-block[data-io-key]").forEach(n=>{n.dataset.ioToggleBound!=="1"&&(n.dataset.ioToggleBound="1",n.addEventListener("toggle",()=>{let a=n.dataset.ioKey;a&&(n.open?t.add(a):t.delete(a))}))})}function Wm(e,t){e.querySelectorAll("details.wf-io-block[data-io-key]").forEach(n=>{let a=n.dataset.ioKey;if(!a)return;let o=t.get(a);if(o===void 0)return;let i=n.querySelector(".wf-io-pre");i&&(i.scrollTop=o)})}function Vm(e,t){e.querySelectorAll("details.wf-io-block[data-io-key]").forEach(n=>{let a=n.dataset.ioKey;if(!a)return;let o=n.querySelector(".wf-io-pre");o&&o.dataset.ioScrollBound!=="1"&&(o.dataset.ioScrollBound="1",o.addEventListener("scroll",()=>{t.set(a,o.scrollTop)}))})}function Km(e){if(!e)return`<span class="muted">${D(s("workflow.detail.empty"))}</span>`;let t=[];return e.outputBytes!==void 0&&t.push(`${e.outputBytes}B`),e.truncated&&t.push(s("workflow.detail.truncated")),e.error&&t.push(s("workflow.detail.error")),e.outputHash&&t.push(Po(e.outputHash)),t.length?`<span class="muted">${D(t.join(" \xB7 "))}</span>`:""}function Jm(e){if(!e)return`<div class="muted wf-io-empty">${D(s("workflow.detail.noData"))}</div>`;let t=e.value!==void 0?JSON.stringify(e.value,null,2):e.text??"",n=e.error?`<div class="muted error">${D(e.error)}</div>`:"";return t?`${n}<pre class="wf-io-pre">${D(t)}</pre>`:`${n}<div class="muted wf-io-empty">${D(s("workflow.detail.noPreview"))}</div>`}function Ym(e){let t=[];if(e.effectAttempted&&t.push(`${D(s("workflow.detail.effect"))} ${D(e.effectAttempted.provider)}`),e.wait){let n=e.wait.resolution?`${e.wait.resolution.kind}${e.wait.resolution.resolution?":"+e.wait.resolution.resolution:""}`:s("workflow.detail.open");t.push(`${D(s("workflow.detail.wait"))} ${D(e.wait.waitKind)} ${D(n)}`),e.wait.deadlineAt!==void 0&&t.push(`${D(s("workflow.detail.deadline"))} ${D(Ro(e.wait.deadlineAt))}`)}if(e.error){let n=`${e.error.errorCode}${e.error.errorClass?` \xB7 ${e.error.errorClass}`:""}`;t.push(`<span class="muted error">${D(n)}</span>`),e.error.errorMessage&&t.push(`<span class="error wf-error-msg">${D(e.error.errorMessage)}</span>`)}return e.output&&t.push(`${D(s("workflow.detail.output"))} ${D(Po(e.output.outputHash))}`),e.runningMs!==void 0&&t.push(`${e.runningMs}ms`),t.length>0?t.join("<br/>"):'<span class="muted">-</span>'}function Zm(e,t){e.innerHTML=t.length>0?t.map(Qm).join(""):`<tr><td colspan="7" class="empty">${D(s("workflow.detail.noEvents"))}</td></tr>`}function Qm(e){let t=Xm(e.payload);return`<tr>
|
|
2046
|
-
<td>${Us(e.eventId)}</td>
|
|
2047
|
-
<td><code>${D(e.type)}</code></td>
|
|
2048
|
-
<td>${D(e.actor)}</td>
|
|
2049
|
-
<td>${t.nodeId?`<code>${D(t.nodeId)}</code>`:"-"}</td>
|
|
2050
|
-
<td>${t.activityId?`<code>${D(t.activityId)}</code>`:"-"}</td>
|
|
2051
|
-
<td>${t.errorCode?`<span class="muted error">${D(t.errorCode)}</span>`:"-"}</td>
|
|
2052
|
-
<td title="${D(new Date(e.timestamp).toISOString())}">${D(Ro(e.timestamp))}</td>
|
|
2053
|
-
</tr>`}function Us(e){let t=e.lastIndexOf("-");if(t<0)return 0;let n=Number(e.slice(t+1));return Number.isFinite(n)?n:0}function Xm(e){if(!e||typeof e!="object"||"ref"in e)return{};let t=e,n={};typeof t.nodeId=="string"&&(n.nodeId=t.nodeId),typeof t.activityId=="string"&&(n.activityId=t.activityId),typeof t.failedNodeId=="string"&&(n.nodeId=t.failedNodeId);let a=t.error;return a&&typeof a=="object"&&"errorCode"in a&&(n.errorCode=String(a.errorCode)),n}function e0(e){return!e.payload||typeof e.payload!="object"||"ref"in e.payload?null:e.payload}function Eu(e,t,n){return Math.min(n,Math.max(t,e))}function Po(e){return e?e.length>18?e.slice(0,10)+"..."+e.slice(-6):e:"-"}function t0(e,t){return e.length>t?e.slice(0,t-1)+"\u2026":e}function Ro(e){return new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}var Bo=78222186;function Pu(e){let t={maxWidth:e.style.maxWidth,padding:e.style.padding,flex:e.style.flex,minHeight:e.style.minHeight,display:e.style.display};e.style.maxWidth="none",e.style.padding="0",e.style.flex="1 1 auto",e.style.minHeight="0",e.style.display="flex";let n=!1,a,o="",i=y=>(y/1048576).toFixed(0);function r(){a&&(clearTimeout(a),a=void 0)}function u(){r(),e.innerHTML=`
|
|
2054
|
-
<iframe
|
|
2055
|
-
src="/game/index.html"
|
|
2056
|
-
title="HD2D Office"
|
|
2057
|
-
style="flex:1;width:100%;min-height:0;border:none;display:block;background:#0b0d12;"
|
|
2058
|
-
allow="autoplay"
|
|
2059
|
-
></iframe>`}function c(y){let g=y.total||Bo,v=g?Math.min(100,Math.round(y.received/g*100)):0,M=y.state==="downloading",$=y.state==="error";e.innerHTML=`
|
|
2060
|
-
<div style="margin:auto;text-align:center;max-width:440px;padding:32px;color:var(--fg,#e6e6e6);">
|
|
2061
|
-
<div style="font-size:18px;font-weight:600;margin-bottom:8px;">HD2D \u529E\u516C\u5BA4</div>
|
|
2062
|
-
<div style="font-size:13px;opacity:.7;line-height:1.7;margin-bottom:20px;">
|
|
2063
|
-
\u628A\u6BCF\u4E2A\u4F1A\u8BDD\u53D8\u6210\u529E\u516C\u5BA4\u91CC\u7684\u4E00\u4E2A\u673A\u5668\u4EBA\uFF0C\u5B9E\u65F6\u6620\u5C04\u5C4F\u5E55\u72B6\u6001\u3002<br>
|
|
2064
|
-
\u9996\u6B21\u8FDB\u5165\u9700\u4E0B\u8F7D\u7EA6 ${i(g)} MB \u6E38\u620F\u8D44\u6E90\uFF08\u4EC5\u4E00\u6B21\uFF0C\u4E4B\u540E\u672C\u5730\u7F13\u5B58\uFF09\u3002
|
|
2065
|
-
</div>
|
|
2066
|
-
${$?`<div style="color:#e06c75;font-size:12px;margin-bottom:14px;">\u4E0A\u6B21\u4E0B\u8F7D\u5931\u8D25\uFF1A${l(y.error??"\u672A\u77E5\u9519\u8BEF")}<br><span style="opacity:.7;">\u586B\u4EE3\u7406\u540E\u70B9\u91CD\u8BD5</span></div>`:""}
|
|
2067
|
-
${M?`
|
|
2068
|
-
<div style="background:rgba(127,127,127,.2);border-radius:6px;height:10px;overflow:hidden;margin-bottom:10px;">
|
|
2069
|
-
<div style="height:100%;width:${v}%;background:#4a9eff;transition:width .3s;"></div>
|
|
2070
|
-
</div>
|
|
2071
|
-
<div style="font-size:12px;opacity:.7;">\u4E0B\u8F7D\u4E2D\u2026 ${i(y.received)} / ${i(g)} MB\uFF08${v}%\uFF09</div>
|
|
2072
|
-
`:`
|
|
2073
|
-
<input id="hd2d-proxy" type="text" value="${l(o)}"
|
|
2074
|
-
placeholder="HTTP \u4EE3\u7406\uFF08\u53EF\u9009\uFF0C\u5982 http://127.0.0.1:7890\uFF09"
|
|
2075
|
-
style="width:100%;box-sizing:border-box;margin-bottom:12px;padding:8px 10px;border-radius:6px;border:1px solid rgba(127,127,127,.4);background:transparent;color:inherit;font-size:12px;" />
|
|
2076
|
-
<div style="font-size:11px;opacity:.5;margin-bottom:14px;text-align:left;">\u8FDE\u4E0D\u4E0A GitHub \u65F6\u586B\u4EE3\u7406\uFF08\u4EC5\u7528\u4E8E\u4E0B\u8F7D\u672C\u8D44\u6E90\uFF0C\u4F1A\u8BB0\u4F4F\uFF09\u3002\u7559\u7A7A\u8D70\u76F4\u8FDE/\u7CFB\u7EDF\u4EE3\u7406\u73AF\u5883\u53D8\u91CF\u3002</div>
|
|
2077
|
-
<button id="hd2d-load" style="cursor:pointer;border:none;border-radius:8px;padding:10px 22px;font-size:14px;font-weight:600;background:#4a9eff;color:#fff;">
|
|
2078
|
-
${$?"\u91CD\u8BD5":"\u52A0\u8F7D\u529E\u516C\u5BA4"}\uFF08\u7EA6 ${i(g)} MB\uFF09
|
|
2079
|
-
</button>
|
|
2080
|
-
`}
|
|
2081
|
-
</div>`;let L=e.querySelector("#hd2d-load");L&&(L.onclick=()=>{o=e.querySelector("#hd2d-proxy")?.value.trim()??"",f()})}function p(y){if(!n){if(typeof y.proxy=="string"&&(o=y.proxy),y.state==="ready"){u();return}c(y),y.state==="downloading"&&(a=setTimeout(()=>{h()},700))}}async function f(){c({state:"downloading",received:0,total:Bo});try{let y=await fetch("/api/game/download",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({proxy:o})});if(!y.ok)throw new Error(`HTTP ${y.status}`);p(await y.json())}catch(y){c({state:"error",received:0,total:Bo,error:y instanceof Error?y.message:String(y)})}}async function h(){if(!n)try{let y=await fetch("/api/game/status");if(!y.ok){c({state:"absent",received:0,total:Bo});return}p(await y.json())}catch{n||(a=setTimeout(()=>{h()},1500))}}return h(),()=>{n=!0,r(),e.innerHTML="",e.style.maxWidth=t.maxWidth,e.style.padding=t.padding,e.style.flex=t.flex,e.style.minHeight=t.minHeight,e.style.display=t.display}}function Bu(e){let t=Date.parse(e);if(!t)return e||"-";let n=Math.max(0,Math.floor((Date.now()-t)/1e3));if(n<60)return`${n}s ago`;let a=Math.floor(n/60);if(a<60)return`${a}m ago`;let o=Math.floor(a/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function n0(e){return e.chatId?.trim()||"__local__"}function Ou(e,t){if(e==="__local__")return"\u672A\u7ED1\u5B9A\u7FA4 / \u672C\u5730\u767D\u677F";let n=t.get(e);return n&&n!==e?`${n} (${e})`:e}function s0(e,t){let n=new Map;for(let a of e){let o=n0(a),i=n.get(o)??[];i.push(a),n.set(o,i)}return[...n.entries()].map(([a,o])=>({chatId:a,label:Ou(a,t),rows:o.sort((i,r)=>r.updatedAt.localeCompare(i.updatedAt))})).sort((a,o)=>a.label.localeCompare(o.label))}function Fu(e){return`display:block;text-decoration:none;color:inherit;border:1px solid ${e?"rgba(14,165,233,.75)":"var(--border)"};border-radius:14px;padding:13px 14px;margin:10px 0 10px 18px;background:${e?"linear-gradient(135deg, rgba(14,165,233,.16), rgba(59,130,246,.08))":"var(--surface-raised)"};box-shadow:${e?"0 10px 24px rgba(14,165,233,.13)":"0 4px 14px rgba(15,23,42,.04)"}`}function o0(e,t){let n=e.id===t;return`<a class="wb-item${n?" active":""}" data-whiteboard-id="${l(e.id)}" href="#/whiteboards/${encodeURIComponent(e.id)}" style="${Fu(n)}">
|
|
2082
|
-
<div style="display:flex;gap:8px;align-items:flex-start;justify-content:space-between">
|
|
2083
|
-
<div style="min-width:0">
|
|
2084
|
-
<strong style="display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">${l(e.title||e.id)}</strong>
|
|
2085
|
-
<span style="display:inline-block;margin-top:4px;font-size:11px;color:var(--muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace">${l(e.id)}</span>
|
|
2086
|
-
</div>
|
|
2087
|
-
<span style="font-size:11px;border:1px solid var(--border);border-radius:999px;padding:2px 7px;color:var(--muted);white-space:nowrap">${l(e.scope)}</span>
|
|
2088
|
-
</div>
|
|
2089
|
-
<div style="margin-top:9px;display:flex;gap:8px;align-items:center;color:var(--muted);font-size:12px"><span>${l(Bu(e.updatedAt))}</span><span>\xB7</span><span>log ${e.logCount}</span></div>
|
|
2090
|
-
</a>`}function a0(e){let t=e.row?.title||e.id;return`<div class="wb-delete-backdrop" data-delete-modal style="position:fixed;inset:0;background:rgba(0,0,0,.48);display:flex;align-items:center;justify-content:center;z-index:10000;padding:20px">
|
|
2091
|
-
<div role="dialog" aria-modal="true" aria-labelledby="wb-delete-title" style="width:min(520px,92vw);background:var(--surface);color:var(--fg);border:1px solid var(--border);border-radius:16px;box-shadow:0 18px 60px rgba(0,0,0,.35);padding:22px 24px">
|
|
2092
|
-
<div style="display:flex;gap:14px;align-items:flex-start">
|
|
2093
|
-
<div aria-hidden="true" style="width:36px;height:36px;border-radius:50%;display:grid;place-items:center;background:rgba(220,38,38,.14);color:#dc2626;font-weight:800">!</div>
|
|
2094
|
-
<div style="min-width:0;flex:1">
|
|
2095
|
-
<h3 id="wb-delete-title" style="margin:0 0 8px;font-size:18px">\u5220\u9664\u767D\u677F\uFF1F</h3>
|
|
2096
|
-
<p style="margin:0;color:var(--muted);line-height:1.6">\u5C06\u5220\u9664 <strong>${l(t)}</strong>\uFF08<code>${l(e.id)}</code>\uFF09\u7684 board\u3001log\u3001meta\uFF0C\u5E76\u6E05\u7406\u9ED8\u8BA4\u7ED1\u5B9A\u548C\u4F1A\u8BDD\u5F15\u7528\u3002\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002</p>
|
|
2097
|
-
</div>
|
|
2098
|
-
</div>
|
|
2099
|
-
<div class="actions" style="display:flex;justify-content:flex-end;gap:10px;margin-top:22px">
|
|
2100
|
-
<button type="button" data-delete-cancel>\u53D6\u6D88</button>
|
|
2101
|
-
<button type="button" class="danger" data-delete-confirm>\u786E\u8BA4\u5220\u9664</button>
|
|
2102
|
-
</div>
|
|
2103
|
-
</div>
|
|
2104
|
-
</div>`}function Oo(e,t){return`<div style="border:1px solid var(--border);border-radius:12px;padding:10px 12px;background:var(--surface-raised);min-width:0">
|
|
2105
|
-
<div style="font-size:11px;color:var(--muted);margin-bottom:5px">${l(e)}</div>
|
|
2106
|
-
<div style="font-size:13px;word-break:break-all">${l(t||"-")}</div>
|
|
2107
|
-
</div>`}function ui(e,t){let n=e?.row,a=n?.chatId?Ou(n.chatId,t):"\u672A\u7ED1\u5B9A\u7FA4 / \u672C\u5730\u767D\u677F";return e?`
|
|
2108
|
-
<div style="display:flex;justify-content:space-between;gap:16px;align-items:flex-start;margin-bottom:16px">
|
|
2109
|
-
<div style="min-width:0">
|
|
2110
|
-
<p class="eyebrow" style="margin:0 0 6px">WHITEBOARD</p>
|
|
2111
|
-
<h2 style="margin:0;font-size:22px;line-height:1.25">${l(n?.title||e.id)}</h2>
|
|
2112
|
-
<div style="margin-top:8px;color:var(--muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px">${l(e.id)}</div>
|
|
2113
|
-
</div>
|
|
2114
|
-
<button type="button" class="danger" data-delete-whiteboard>\u5220\u9664\u767D\u677F</button>
|
|
2115
|
-
</div>
|
|
2116
|
-
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-bottom:18px">
|
|
2117
|
-
${Oo("\u6240\u5C5E\u7FA4",a)}
|
|
2118
|
-
${Oo("\u8303\u56F4",n?.scope??"-")}
|
|
2119
|
-
${Oo("\u6700\u8FD1\u66F4\u65B0",n?.updatedAt?Bu(n.updatedAt):"-")}
|
|
2120
|
-
${Oo("\u6765\u6E90\u76EE\u5F55",n?.workingDir??"-")}
|
|
2121
|
-
</div>
|
|
2122
|
-
<details style="margin-bottom:18px;color:var(--muted)">
|
|
2123
|
-
<summary style="cursor:pointer">\u7BA1\u7406\u4FE1\u606F / \u6587\u4EF6\u8DEF\u5F84</summary>
|
|
2124
|
-
<code style="display:block;margin-top:8px;white-space:pre-wrap;word-break:break-all">${l(n?.path??"")}</code>
|
|
2125
|
-
</details>
|
|
2126
|
-
<section style="border:1px solid var(--border);border-radius:14px;background:var(--surface-raised);overflow:hidden">
|
|
2127
|
-
<div style="padding:12px 14px;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center">
|
|
2128
|
-
<strong>\u5F53\u524D\u72B6\u6001 board.md</strong><span style="color:var(--muted);font-size:12px">read / update</span>
|
|
2129
|
-
</div>
|
|
2130
|
-
<pre style="white-space:pre-wrap;max-height:70vh;overflow:auto;margin:0;padding:16px;line-height:1.65;background:transparent">${l(e.content||"\uFF08\u6682\u65E0\u5185\u5BB9\uFF09")}</pre>
|
|
2131
|
-
</section>`:'<p class="empty">\u9009\u62E9\u5DE6\u4FA7\u767D\u677F\u67E5\u770B meta \u548C board.md\u3002</p>'}function i0(e,t,n,a){let o=s0(t,n);return`<section class="page">
|
|
2132
|
-
<div class="page-heading">
|
|
2133
|
-
<div>
|
|
2134
|
-
<p class="eyebrow">Whiteboards</p>
|
|
2135
|
-
<h1>\u672C\u5730\u767D\u677F</h1>
|
|
2136
|
-
<p>\u6309\u7FA4\u5171\u4EAB\u7684\u672C\u5730\u6700\u65B0\u72B6\u6001\u767D\u677F\u3002\u5F00\u5173\u5173\u95ED\u65F6\u4EC5\u53EA\u8BFB\u5C55\u793A\u5386\u53F2\u767D\u677F\uFF0C\u4E0D\u6CE8\u5165 prompt\u3001\u4E0D\u5141\u8BB8 agent CLI \u8BFB\u5199\u3002</p>
|
|
2137
|
-
</div>
|
|
2138
|
-
<span class="pill ${e?"ok":"warn"}">${e?"Enabled":"Disabled"}</span>
|
|
2139
|
-
</div>
|
|
2140
|
-
${e?"":'<p class="hint-warn">\u767D\u677F\u80FD\u529B\u5F53\u524D\u5173\u95ED\uFF1A\u4E0D\u4F1A\u81EA\u52A8\u521B\u5EFA/\u7ED1\u5B9A\u767D\u677F\uFF0C\u4E5F\u4E0D\u4F1A\u6CE8\u5165\u5230 agent prompt\u3002\u5386\u53F2\u767D\u677F\u4EC5\u5728 dashboard \u4E2D\u53EA\u8BFB\u53EF\u89C1\uFF0C\u53EF\u5728\u6B64\u6E05\u7406\u3002</p>'}
|
|
2141
|
-
<div class="wb-split" style="display:grid;grid-template-columns:minmax(300px,400px) minmax(0,1fr);gap:18px;align-items:start">
|
|
2142
|
-
<article class="bd-card settings-card" style="padding:18px">
|
|
2143
|
-
<h3 class="bd-section-title" style="margin-bottom:12px">\u7FA4\u7EC4 / \u767D\u677F</h3>
|
|
2144
|
-
${o.length===0?'<p class="empty">\u6682\u65E0\u767D\u677F\u3002\u6253\u5F00\u80FD\u529B\u540E\uFF0C\u6BCF\u4E2A\u7FA4\u9996\u6B21\u9700\u8981\u767D\u677F\u65F6\u624D\u4F1A\u521B\u5EFA\u9ED8\u8BA4\u767D\u677F\u3002</p>':o.map(i=>`
|
|
2145
|
-
<details class="wb-group" open style="margin-bottom:14px">
|
|
2146
|
-
<summary style="cursor:pointer;font-weight:700;margin:12px 0 8px;display:flex;justify-content:space-between;gap:8px;align-items:center">
|
|
2147
|
-
<span style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis">${l(i.label)}</span><small style="border:1px solid var(--border);border-radius:999px;padding:1px 7px;color:var(--muted)">${i.rows.length}</small>
|
|
2148
|
-
</summary>
|
|
2149
|
-
${i.rows.map(r=>o0(r,a?.id)).join("")}
|
|
2150
|
-
</details>`).join("")}
|
|
2151
|
-
</article>
|
|
2152
|
-
<article class="bd-card settings-card" id="whiteboard-detail" style="padding:20px 22px">
|
|
2153
|
-
${ui(a,n)}
|
|
2154
|
-
</article>
|
|
2155
|
-
</div>
|
|
2156
|
-
</section>`}async function Nu(e){e.innerHTML='<div data-whiteboards-host><p class="empty">Loading whiteboards\u2026</p></div>';let t=e.querySelector("[data-whiteboards-host]");if(!t)return;let n=decodeURIComponent((location.hash.match(/^#\/whiteboards\/([^/]+)/)?.[1]??"").trim());try{let[a,o]=await Promise.all([fetch("/api/whiteboards"),fetch("/api/groups").catch(()=>null)]),i=await a.json().catch(()=>({}));if(!a.ok)throw new Error(i?.error??`HTTP ${a.status}`);let r=await r0(o),u=Array.isArray(i.whiteboards)?i.whiteboards:[],c=n?await qu(n,u):void 0;t.innerHTML=i0(i.enabled===!0,u,r,c),l0(t,u,r),ju(t,n)}catch(a){t.innerHTML=`<section class="page"><p class="hint-warn">\u52A0\u8F7D\u767D\u677F\u5931\u8D25\uFF1A${l(a?.message??String(a))}</p></section>`}}async function qu(e,t){let n=await fetch(`/api/whiteboards/${encodeURIComponent(e)}`),a=await n.json().catch(()=>({}));if(n.ok)return{id:e,content:String(a.content??""),row:t.find(o=>o.id===e)}}async function r0(e){let t=new Map;if(!e?.ok)return t;let n=await e.json().catch(()=>({})),a=Array.isArray(n.chats)?n.chats:[];for(let o of a)o.chatId&&t.set(String(o.chatId),String(o.name||o.chatId));return t}function l0(e,t,n){e.querySelectorAll(".wb-item[data-whiteboard-id]").forEach(a=>{a.addEventListener("click",async o=>{o.preventDefault();let i=a.dataset.whiteboardId;if(!i)return;let r=await qu(i,t);if(!r)return;for(let c of e.querySelectorAll(".wb-item[data-whiteboard-id]")){let p=c.dataset.whiteboardId===i;c.classList.toggle("active",p),c.setAttribute("style",Fu(p))}let u=e.querySelector("#whiteboard-detail");u&&(u.innerHTML=ui(r,n)),window.history.replaceState(null,"",`#/whiteboards/${encodeURIComponent(i)}`),ju(e,i)})})}function u0(e,t){let n=e.querySelector(`.wb-item[data-whiteboard-id="${CSS.escape(t)}"]`),a=n?.closest("details.wb-group");if(n?.remove(),a){let r=a.querySelectorAll(".wb-item[data-whiteboard-id]").length,u=a.querySelector("summary small");u&&(u.textContent=String(r)),r===0&&a.remove()}let o=e.querySelector("#whiteboard-detail");if(o&&(o.innerHTML=ui(void 0,new Map)),!e.querySelector(".wb-item[data-whiteboard-id]")){let r=e.querySelector(".wb-split article.bd-card");r&&(r.innerHTML='<h3 class="bd-section-title" style="margin-bottom:12px">\u7FA4\u7EC4 / \u767D\u677F</h3><p class="empty">\u6682\u65E0\u767D\u677F\u3002\u6253\u5F00\u80FD\u529B\u540E\uFF0C\u6BCF\u4E2A\u7FA4\u9996\u6B21\u9700\u8981\u767D\u677F\u65F6\u624D\u4F1A\u521B\u5EFA\u9ED8\u8BA4\u767D\u677F\u3002</p>')}}function ju(e,t){let n=e.querySelector("[data-delete-whiteboard]");!n||!t||n.addEventListener("click",async()=>{let a=e.querySelector(`.wb-item[data-whiteboard-id="${CSS.escape(t)}"]`),o={id:t,content:"",row:a?{id:t,title:a.querySelector("strong")?.textContent||t,scope:"",updatedAt:"",path:"",preview:"",logCount:0}:void 0};await c0(e,t,o)})}async function c0(e,t,n){e.querySelector("[data-delete-modal]")?.remove();let a=document.createElement("div");a.innerHTML=a0(n);let o=a.firstElementChild;document.body.appendChild(o);let i=()=>o.remove();o.querySelector("[data-delete-cancel]")?.addEventListener("click",i),o.addEventListener("click",r=>{r.target===o&&i()}),o.querySelector("[data-delete-confirm]")?.addEventListener("click",async()=>{let r=o.querySelector("[data-delete-confirm]");r&&(r.disabled=!0,r.textContent="\u5220\u9664\u4E2D\u2026");try{let u=await fetch(`/api/whiteboards/${encodeURIComponent(t)}`,{method:"DELETE"}),c=await u.json().catch(()=>({}));if(!u.ok||c.ok===!1)throw new Error(c?.error??`HTTP ${u.status}`);i(),u0(e,t),window.history.replaceState(null,"","#/whiteboards")}catch(u){i(),alert(`\u5220\u9664\u5931\u8D25\uFF1A${u?.message??String(u)}`)}})}var yi={};no(yi,{arrayReplaceAt:()=>bi,assign:()=>ps,escapeHtml:()=>en,escapeRE:()=>V0,fromCodePoint:()=>Ws,has:()=>P0,isMdAsciiPunct:()=>On,isPunctChar:()=>Bn,isSpace:()=>we,isString:()=>Yo,isValidEntityCode:()=>Zo,isWhiteSpace:()=>Pn,lib:()=>K0,normalizeReference:()=>Fn,unescapeAll:()=>Xt,unescapeMd:()=>q0});var Uo={};no(Uo,{decode:()=>zs,encode:()=>qo,format:()=>cs,parse:()=>Gs});var Uu={};function d0(e){let t=Uu[e];if(t)return t;t=Uu[e]=[];for(let n=0;n<128;n++){let a=String.fromCharCode(n);t.push(a)}for(let n=0;n<e.length;n++){let a=e.charCodeAt(n);t[a]="%"+("0"+a.toString(16).toUpperCase()).slice(-2)}return t}function Fo(e,t){typeof t!="string"&&(t=Fo.defaultChars);let n=d0(t);return e.replace(/(%[a-f0-9]{2})+/gi,function(a){let o="";for(let i=0,r=a.length;i<r;i+=3){let u=parseInt(a.slice(i+1,i+3),16);if(u<128){o+=n[u];continue}if((u&224)===192&&i+3<r){let c=parseInt(a.slice(i+4,i+6),16);if((c&192)===128){let p=u<<6&1984|c&63;p<128?o+="\uFFFD\uFFFD":o+=String.fromCharCode(p),i+=3;continue}}if((u&240)===224&&i+6<r){let c=parseInt(a.slice(i+4,i+6),16),p=parseInt(a.slice(i+7,i+9),16);if((c&192)===128&&(p&192)===128){let f=u<<12&61440|c<<6&4032|p&63;f<2048||f>=55296&&f<=57343?o+="\uFFFD\uFFFD\uFFFD":o+=String.fromCharCode(f),i+=6;continue}}if((u&248)===240&&i+9<r){let c=parseInt(a.slice(i+4,i+6),16),p=parseInt(a.slice(i+7,i+9),16),f=parseInt(a.slice(i+10,i+12),16);if((c&192)===128&&(p&192)===128&&(f&192)===128){let h=u<<18&1835008|c<<12&258048|p<<6&4032|f&63;h<65536||h>1114111?o+="\uFFFD\uFFFD\uFFFD\uFFFD":(h-=65536,o+=String.fromCharCode(55296+(h>>10),56320+(h&1023))),i+=9;continue}}o+="\uFFFD"}return o})}Fo.defaultChars=";/?:@&=+$,#";Fo.componentChars="";var zs=Fo;var zu={};function p0(e){let t=zu[e];if(t)return t;t=zu[e]=[];for(let n=0;n<128;n++){let a=String.fromCharCode(n);/^[0-9a-z]$/i.test(a)?t.push(a):t.push("%"+("0"+n.toString(16).toUpperCase()).slice(-2))}for(let n=0;n<e.length;n++)t[e.charCodeAt(n)]=e[n];return t}function No(e,t,n){typeof t!="string"&&(n=t,t=No.defaultChars),typeof n>"u"&&(n=!0);let a=p0(t),o="";for(let i=0,r=e.length;i<r;i++){let u=e.charCodeAt(i);if(n&&u===37&&i+2<r&&/^[0-9a-f]{2}$/i.test(e.slice(i+1,i+3))){o+=e.slice(i,i+3),i+=2;continue}if(u<128){o+=a[u];continue}if(u>=55296&&u<=57343){if(u>=55296&&u<=56319&&i+1<r){let c=e.charCodeAt(i+1);if(c>=56320&&c<=57343){o+=encodeURIComponent(e[i]+e[i+1]),i++;continue}}o+="%EF%BF%BD";continue}o+=encodeURIComponent(e[i])}return o}No.defaultChars=";/?:@&=+$,-_.!~*'()#";No.componentChars="-_.!~*'()";var qo=No;function cs(e){let t="";return t+=e.protocol||"",t+=e.slashes?"//":"",t+=e.auth?e.auth+"@":"",e.hostname&&e.hostname.indexOf(":")!==-1?t+="["+e.hostname+"]":t+=e.hostname||"",t+=e.port?":"+e.port:"",t+=e.pathname||"",t+=e.search||"",t+=e.hash||"",t}function jo(){this.protocol=null,this.slashes=null,this.auth=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.pathname=null}var f0=/^([a-z0-9.+-]+:)/i,m0=/:[0-9]*$/,h0=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,g0=["<",">",'"',"`"," ","\r",`
|
|
2157
|
-
`," "],b0=["{","}","|","\\","^","`"].concat(g0),y0=["'"].concat(b0),Gu=["%","/","?",";","#"].concat(y0),Wu=["/","?","#"],v0=255,Vu=/^[+a-z0-9A-Z_-]{0,63}$/,w0=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,Ku={javascript:!0,"javascript:":!0},Ju={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0};function k0(e,t){if(e&&e instanceof jo)return e;let n=new jo;return n.parse(e,t),n}jo.prototype.parse=function(e,t){let n,a,o,i=e;if(i=i.trim(),!t&&e.split("#").length===1){let p=h0.exec(i);if(p)return this.pathname=p[1],p[2]&&(this.search=p[2]),this}let r=f0.exec(i);if(r&&(r=r[0],n=r.toLowerCase(),this.protocol=r,i=i.substr(r.length)),(t||r||i.match(/^\/\/[^@\/]+@[^@\/]+/))&&(o=i.substr(0,2)==="//",o&&!(r&&Ku[r])&&(i=i.substr(2),this.slashes=!0)),!Ku[r]&&(o||r&&!Ju[r])){let p=-1;for(let v=0;v<Wu.length;v++)a=i.indexOf(Wu[v]),a!==-1&&(p===-1||a<p)&&(p=a);let f,h;p===-1?h=i.lastIndexOf("@"):h=i.lastIndexOf("@",p),h!==-1&&(f=i.slice(0,h),i=i.slice(h+1),this.auth=f),p=-1;for(let v=0;v<Gu.length;v++)a=i.indexOf(Gu[v]),a!==-1&&(p===-1||a<p)&&(p=a);p===-1&&(p=i.length),i[p-1]===":"&&p--;let y=i.slice(0,p);i=i.slice(p),this.parseHost(y),this.hostname=this.hostname||"";let g=this.hostname[0]==="["&&this.hostname[this.hostname.length-1]==="]";if(!g){let v=this.hostname.split(/\./);for(let M=0,$=v.length;M<$;M++){let L=v[M];if(L&&!L.match(Vu)){let C="";for(let P=0,H=L.length;P<H;P++)L.charCodeAt(P)>127?C+="x":C+=L[P];if(!C.match(Vu)){let P=v.slice(0,M),H=v.slice(M+1),q=L.match(w0);q&&(P.push(q[1]),H.unshift(q[2])),H.length&&(i=H.join(".")+i),this.hostname=P.join(".");break}}}}this.hostname.length>v0&&(this.hostname=""),g&&(this.hostname=this.hostname.substr(1,this.hostname.length-2))}let u=i.indexOf("#");u!==-1&&(this.hash=i.substr(u),i=i.slice(0,u));let c=i.indexOf("?");return c!==-1&&(this.search=i.substr(c),i=i.slice(0,c)),i&&(this.pathname=i),Ju[n]&&this.hostname&&!this.pathname&&(this.pathname=""),this};jo.prototype.parseHost=function(e){let t=m0.exec(e);t&&(t=t[0],t!==":"&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)};var Gs=k0;var ci={};no(ci,{Any:()=>zo,Cc:()=>Go,Cf:()=>Yu,P:()=>ds,S:()=>Wo,Z:()=>Vo});var zo=/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;var Go=/[\0-\x1F\x7F-\x9F]/;var Yu=/[\xAD\u0600-\u0605\u061C\u06DD\u070F\u0890\u0891\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD80D[\uDC30-\uDC3F]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/;var ds=/[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1B7D\u1B7E\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDEAD\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]/;var Wo=/[\$\+<->\^`\|~\xA2-\xA6\xA8\xA9\xAC\xAE-\xB1\xB4\xB8\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u03F6\u0482\u058D-\u058F\u0606-\u0608\u060B\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u07FE\u07FF\u0888\u09F2\u09F3\u09FA\u09FB\u0AF1\u0B70\u0BF3-\u0BFA\u0C7F\u0D4F\u0D79\u0E3F\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u166D\u17DB\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2044\u2052\u207A-\u207C\u208A-\u208C\u20A0-\u20C0\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F\u218A\u218B\u2190-\u2307\u230C-\u2328\u232B-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u2767\u2794-\u27C4\u27C7-\u27E5\u27F0-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2B73\u2B76-\u2B95\u2B97-\u2BFF\u2CE5-\u2CEA\u2E50\u2E51\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFF\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u309B\u309C\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u31EF\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA700-\uA716\uA720\uA721\uA789\uA78A\uA828-\uA82B\uA836-\uA839\uAA77-\uAA79\uAB5B\uAB6A\uAB6B\uFB29\uFBB2-\uFBC2\uFD40-\uFD4F\uFDCF\uFDFC-\uFDFF\uFE62\uFE64-\uFE66\uFE69\uFF04\uFF0B\uFF1C-\uFF1E\uFF3E\uFF40\uFF5C\uFF5E\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFFC\uFFFD]|\uD800[\uDD37-\uDD3F\uDD79-\uDD89\uDD8C-\uDD8E\uDD90-\uDD9C\uDDA0\uDDD0-\uDDFC]|\uD802[\uDC77\uDC78\uDEC8]|\uD805\uDF3F|\uD807[\uDFD5-\uDFF1]|\uD81A[\uDF3C-\uDF3F\uDF45]|\uD82F\uDC9C|\uD833[\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD64\uDD6A-\uDD6C\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDE00-\uDE41\uDE45\uDF00-\uDF56]|\uD835[\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85\uDE86]|\uD838[\uDD4F\uDEFF]|\uD83B[\uDCAC\uDCB0\uDD2E\uDEF0\uDEF1]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD0D-\uDDAD\uDDE6-\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFF]|\uD83D[\uDC00-\uDED7\uDEDC-\uDEEC\uDEF0-\uDEFC\uDF00-\uDF76\uDF7B-\uDFD9\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0\uDCB1\uDD00-\uDE53\uDE60-\uDE6D\uDE70-\uDE7C\uDE80-\uDE88\uDE90-\uDEBD\uDEBF-\uDEC5\uDECE-\uDEDB\uDEE0-\uDEE8\uDEF0-\uDEF8\uDF00-\uDF92\uDF94-\uDFCA]/;var Vo=/[ \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/;var Zu=new Uint16Array('\u1D41<\xD5\u0131\u028A\u049D\u057B\u05D0\u0675\u06DE\u07A2\u07D6\u080F\u0A4A\u0A91\u0DA1\u0E6D\u0F09\u0F26\u10CA\u1228\u12E1\u1415\u149D\u14C3\u14DF\u1525\0\0\0\0\0\0\u156B\u16CD\u198D\u1C12\u1DDD\u1F7E\u2060\u21B0\u228D\u23C0\u23FB\u2442\u2824\u2912\u2D08\u2E48\u2FCE\u3016\u32BA\u3639\u37AC\u38FE\u3A28\u3A71\u3AE0\u3B2E\u0800EMabcfglmnoprstu\\bfms\x7F\x84\x8B\x90\x95\x98\xA6\xB3\xB9\xC8\xCFlig\u803B\xC6\u40C6P\u803B&\u4026cute\u803B\xC1\u40C1reve;\u4102\u0100iyx}rc\u803B\xC2\u40C2;\u4410r;\uC000\u{1D504}rave\u803B\xC0\u40C0pha;\u4391acr;\u4100d;\u6A53\u0100gp\x9D\xA1on;\u4104f;\uC000\u{1D538}plyFunction;\u6061ing\u803B\xC5\u40C5\u0100cs\xBE\xC3r;\uC000\u{1D49C}ign;\u6254ilde\u803B\xC3\u40C3ml\u803B\xC4\u40C4\u0400aceforsu\xE5\xFB\xFE\u0117\u011C\u0122\u0127\u012A\u0100cr\xEA\xF2kslash;\u6216\u0176\xF6\xF8;\u6AE7ed;\u6306y;\u4411\u0180crt\u0105\u010B\u0114ause;\u6235noullis;\u612Ca;\u4392r;\uC000\u{1D505}pf;\uC000\u{1D539}eve;\u42D8c\xF2\u0113mpeq;\u624E\u0700HOacdefhilorsu\u014D\u0151\u0156\u0180\u019E\u01A2\u01B5\u01B7\u01BA\u01DC\u0215\u0273\u0278\u027Ecy;\u4427PY\u803B\xA9\u40A9\u0180cpy\u015D\u0162\u017Aute;\u4106\u0100;i\u0167\u0168\u62D2talDifferentialD;\u6145leys;\u612D\u0200aeio\u0189\u018E\u0194\u0198ron;\u410Cdil\u803B\xC7\u40C7rc;\u4108nint;\u6230ot;\u410A\u0100dn\u01A7\u01ADilla;\u40B8terDot;\u40B7\xF2\u017Fi;\u43A7rcle\u0200DMPT\u01C7\u01CB\u01D1\u01D6ot;\u6299inus;\u6296lus;\u6295imes;\u6297o\u0100cs\u01E2\u01F8kwiseContourIntegral;\u6232eCurly\u0100DQ\u0203\u020FoubleQuote;\u601Duote;\u6019\u0200lnpu\u021E\u0228\u0247\u0255on\u0100;e\u0225\u0226\u6237;\u6A74\u0180git\u022F\u0236\u023Aruent;\u6261nt;\u622FourIntegral;\u622E\u0100fr\u024C\u024E;\u6102oduct;\u6210nterClockwiseContourIntegral;\u6233oss;\u6A2Fcr;\uC000\u{1D49E}p\u0100;C\u0284\u0285\u62D3ap;\u624D\u0580DJSZacefios\u02A0\u02AC\u02B0\u02B4\u02B8\u02CB\u02D7\u02E1\u02E6\u0333\u048D\u0100;o\u0179\u02A5trahd;\u6911cy;\u4402cy;\u4405cy;\u440F\u0180grs\u02BF\u02C4\u02C7ger;\u6021r;\u61A1hv;\u6AE4\u0100ay\u02D0\u02D5ron;\u410E;\u4414l\u0100;t\u02DD\u02DE\u6207a;\u4394r;\uC000\u{1D507}\u0100af\u02EB\u0327\u0100cm\u02F0\u0322ritical\u0200ADGT\u0300\u0306\u0316\u031Ccute;\u40B4o\u0174\u030B\u030D;\u42D9bleAcute;\u42DDrave;\u4060ilde;\u42DCond;\u62C4ferentialD;\u6146\u0470\u033D\0\0\0\u0342\u0354\0\u0405f;\uC000\u{1D53B}\u0180;DE\u0348\u0349\u034D\u40A8ot;\u60DCqual;\u6250ble\u0300CDLRUV\u0363\u0372\u0382\u03CF\u03E2\u03F8ontourIntegra\xEC\u0239o\u0274\u0379\0\0\u037B\xBB\u0349nArrow;\u61D3\u0100eo\u0387\u03A4ft\u0180ART\u0390\u0396\u03A1rrow;\u61D0ightArrow;\u61D4e\xE5\u02CAng\u0100LR\u03AB\u03C4eft\u0100AR\u03B3\u03B9rrow;\u67F8ightArrow;\u67FAightArrow;\u67F9ight\u0100AT\u03D8\u03DErrow;\u61D2ee;\u62A8p\u0241\u03E9\0\0\u03EFrrow;\u61D1ownArrow;\u61D5erticalBar;\u6225n\u0300ABLRTa\u0412\u042A\u0430\u045E\u047F\u037Crrow\u0180;BU\u041D\u041E\u0422\u6193ar;\u6913pArrow;\u61F5reve;\u4311eft\u02D2\u043A\0\u0446\0\u0450ightVector;\u6950eeVector;\u695Eector\u0100;B\u0459\u045A\u61BDar;\u6956ight\u01D4\u0467\0\u0471eeVector;\u695Fector\u0100;B\u047A\u047B\u61C1ar;\u6957ee\u0100;A\u0486\u0487\u62A4rrow;\u61A7\u0100ct\u0492\u0497r;\uC000\u{1D49F}rok;\u4110\u0800NTacdfglmopqstux\u04BD\u04C0\u04C4\u04CB\u04DE\u04E2\u04E7\u04EE\u04F5\u0521\u052F\u0536\u0552\u055D\u0560\u0565G;\u414AH\u803B\xD0\u40D0cute\u803B\xC9\u40C9\u0180aiy\u04D2\u04D7\u04DCron;\u411Arc\u803B\xCA\u40CA;\u442Dot;\u4116r;\uC000\u{1D508}rave\u803B\xC8\u40C8ement;\u6208\u0100ap\u04FA\u04FEcr;\u4112ty\u0253\u0506\0\0\u0512mallSquare;\u65FBerySmallSquare;\u65AB\u0100gp\u0526\u052Aon;\u4118f;\uC000\u{1D53C}silon;\u4395u\u0100ai\u053C\u0549l\u0100;T\u0542\u0543\u6A75ilde;\u6242librium;\u61CC\u0100ci\u0557\u055Ar;\u6130m;\u6A73a;\u4397ml\u803B\xCB\u40CB\u0100ip\u056A\u056Fsts;\u6203onentialE;\u6147\u0280cfios\u0585\u0588\u058D\u05B2\u05CCy;\u4424r;\uC000\u{1D509}lled\u0253\u0597\0\0\u05A3mallSquare;\u65FCerySmallSquare;\u65AA\u0370\u05BA\0\u05BF\0\0\u05C4f;\uC000\u{1D53D}All;\u6200riertrf;\u6131c\xF2\u05CB\u0600JTabcdfgorst\u05E8\u05EC\u05EF\u05FA\u0600\u0612\u0616\u061B\u061D\u0623\u066C\u0672cy;\u4403\u803B>\u403Emma\u0100;d\u05F7\u05F8\u4393;\u43DCreve;\u411E\u0180eiy\u0607\u060C\u0610dil;\u4122rc;\u411C;\u4413ot;\u4120r;\uC000\u{1D50A};\u62D9pf;\uC000\u{1D53E}eater\u0300EFGLST\u0635\u0644\u064E\u0656\u065B\u0666qual\u0100;L\u063E\u063F\u6265ess;\u62DBullEqual;\u6267reater;\u6AA2ess;\u6277lantEqual;\u6A7Eilde;\u6273cr;\uC000\u{1D4A2};\u626B\u0400Aacfiosu\u0685\u068B\u0696\u069B\u069E\u06AA\u06BE\u06CARDcy;\u442A\u0100ct\u0690\u0694ek;\u42C7;\u405Eirc;\u4124r;\u610ClbertSpace;\u610B\u01F0\u06AF\0\u06B2f;\u610DizontalLine;\u6500\u0100ct\u06C3\u06C5\xF2\u06A9rok;\u4126mp\u0144\u06D0\u06D8ownHum\xF0\u012Fqual;\u624F\u0700EJOacdfgmnostu\u06FA\u06FE\u0703\u0707\u070E\u071A\u071E\u0721\u0728\u0744\u0778\u078B\u078F\u0795cy;\u4415lig;\u4132cy;\u4401cute\u803B\xCD\u40CD\u0100iy\u0713\u0718rc\u803B\xCE\u40CE;\u4418ot;\u4130r;\u6111rave\u803B\xCC\u40CC\u0180;ap\u0720\u072F\u073F\u0100cg\u0734\u0737r;\u412AinaryI;\u6148lie\xF3\u03DD\u01F4\u0749\0\u0762\u0100;e\u074D\u074E\u622C\u0100gr\u0753\u0758ral;\u622Bsection;\u62C2isible\u0100CT\u076C\u0772omma;\u6063imes;\u6062\u0180gpt\u077F\u0783\u0788on;\u412Ef;\uC000\u{1D540}a;\u4399cr;\u6110ilde;\u4128\u01EB\u079A\0\u079Ecy;\u4406l\u803B\xCF\u40CF\u0280cfosu\u07AC\u07B7\u07BC\u07C2\u07D0\u0100iy\u07B1\u07B5rc;\u4134;\u4419r;\uC000\u{1D50D}pf;\uC000\u{1D541}\u01E3\u07C7\0\u07CCr;\uC000\u{1D4A5}rcy;\u4408kcy;\u4404\u0380HJacfos\u07E4\u07E8\u07EC\u07F1\u07FD\u0802\u0808cy;\u4425cy;\u440Cppa;\u439A\u0100ey\u07F6\u07FBdil;\u4136;\u441Ar;\uC000\u{1D50E}pf;\uC000\u{1D542}cr;\uC000\u{1D4A6}\u0580JTaceflmost\u0825\u0829\u082C\u0850\u0863\u09B3\u09B8\u09C7\u09CD\u0A37\u0A47cy;\u4409\u803B<\u403C\u0280cmnpr\u0837\u083C\u0841\u0844\u084Dute;\u4139bda;\u439Bg;\u67EAlacetrf;\u6112r;\u619E\u0180aey\u0857\u085C\u0861ron;\u413Ddil;\u413B;\u441B\u0100fs\u0868\u0970t\u0500ACDFRTUVar\u087E\u08A9\u08B1\u08E0\u08E6\u08FC\u092F\u095B\u0390\u096A\u0100nr\u0883\u088FgleBracket;\u67E8row\u0180;BR\u0899\u089A\u089E\u6190ar;\u61E4ightArrow;\u61C6eiling;\u6308o\u01F5\u08B7\0\u08C3bleBracket;\u67E6n\u01D4\u08C8\0\u08D2eeVector;\u6961ector\u0100;B\u08DB\u08DC\u61C3ar;\u6959loor;\u630Aight\u0100AV\u08EF\u08F5rrow;\u6194ector;\u694E\u0100er\u0901\u0917e\u0180;AV\u0909\u090A\u0910\u62A3rrow;\u61A4ector;\u695Aiangle\u0180;BE\u0924\u0925\u0929\u62B2ar;\u69CFqual;\u62B4p\u0180DTV\u0937\u0942\u094CownVector;\u6951eeVector;\u6960ector\u0100;B\u0956\u0957\u61BFar;\u6958ector\u0100;B\u0965\u0966\u61BCar;\u6952ight\xE1\u039Cs\u0300EFGLST\u097E\u098B\u0995\u099D\u09A2\u09ADqualGreater;\u62DAullEqual;\u6266reater;\u6276ess;\u6AA1lantEqual;\u6A7Dilde;\u6272r;\uC000\u{1D50F}\u0100;e\u09BD\u09BE\u62D8ftarrow;\u61DAidot;\u413F\u0180npw\u09D4\u0A16\u0A1Bg\u0200LRlr\u09DE\u09F7\u0A02\u0A10eft\u0100AR\u09E6\u09ECrrow;\u67F5ightArrow;\u67F7ightArrow;\u67F6eft\u0100ar\u03B3\u0A0Aight\xE1\u03BFight\xE1\u03CAf;\uC000\u{1D543}er\u0100LR\u0A22\u0A2CeftArrow;\u6199ightArrow;\u6198\u0180cht\u0A3E\u0A40\u0A42\xF2\u084C;\u61B0rok;\u4141;\u626A\u0400acefiosu\u0A5A\u0A5D\u0A60\u0A77\u0A7C\u0A85\u0A8B\u0A8Ep;\u6905y;\u441C\u0100dl\u0A65\u0A6FiumSpace;\u605Flintrf;\u6133r;\uC000\u{1D510}nusPlus;\u6213pf;\uC000\u{1D544}c\xF2\u0A76;\u439C\u0480Jacefostu\u0AA3\u0AA7\u0AAD\u0AC0\u0B14\u0B19\u0D91\u0D97\u0D9Ecy;\u440Acute;\u4143\u0180aey\u0AB4\u0AB9\u0ABEron;\u4147dil;\u4145;\u441D\u0180gsw\u0AC7\u0AF0\u0B0Eative\u0180MTV\u0AD3\u0ADF\u0AE8ediumSpace;\u600Bhi\u0100cn\u0AE6\u0AD8\xEB\u0AD9eryThi\xEE\u0AD9ted\u0100GL\u0AF8\u0B06reaterGreate\xF2\u0673essLes\xF3\u0A48Line;\u400Ar;\uC000\u{1D511}\u0200Bnpt\u0B22\u0B28\u0B37\u0B3Areak;\u6060BreakingSpace;\u40A0f;\u6115\u0680;CDEGHLNPRSTV\u0B55\u0B56\u0B6A\u0B7C\u0BA1\u0BEB\u0C04\u0C5E\u0C84\u0CA6\u0CD8\u0D61\u0D85\u6AEC\u0100ou\u0B5B\u0B64ngruent;\u6262pCap;\u626DoubleVerticalBar;\u6226\u0180lqx\u0B83\u0B8A\u0B9Bement;\u6209ual\u0100;T\u0B92\u0B93\u6260ilde;\uC000\u2242\u0338ists;\u6204reater\u0380;EFGLST\u0BB6\u0BB7\u0BBD\u0BC9\u0BD3\u0BD8\u0BE5\u626Fqual;\u6271ullEqual;\uC000\u2267\u0338reater;\uC000\u226B\u0338ess;\u6279lantEqual;\uC000\u2A7E\u0338ilde;\u6275ump\u0144\u0BF2\u0BFDownHump;\uC000\u224E\u0338qual;\uC000\u224F\u0338e\u0100fs\u0C0A\u0C27tTriangle\u0180;BE\u0C1A\u0C1B\u0C21\u62EAar;\uC000\u29CF\u0338qual;\u62ECs\u0300;EGLST\u0C35\u0C36\u0C3C\u0C44\u0C4B\u0C58\u626Equal;\u6270reater;\u6278ess;\uC000\u226A\u0338lantEqual;\uC000\u2A7D\u0338ilde;\u6274ested\u0100GL\u0C68\u0C79reaterGreater;\uC000\u2AA2\u0338essLess;\uC000\u2AA1\u0338recedes\u0180;ES\u0C92\u0C93\u0C9B\u6280qual;\uC000\u2AAF\u0338lantEqual;\u62E0\u0100ei\u0CAB\u0CB9verseElement;\u620CghtTriangle\u0180;BE\u0CCB\u0CCC\u0CD2\u62EBar;\uC000\u29D0\u0338qual;\u62ED\u0100qu\u0CDD\u0D0CuareSu\u0100bp\u0CE8\u0CF9set\u0100;E\u0CF0\u0CF3\uC000\u228F\u0338qual;\u62E2erset\u0100;E\u0D03\u0D06\uC000\u2290\u0338qual;\u62E3\u0180bcp\u0D13\u0D24\u0D4Eset\u0100;E\u0D1B\u0D1E\uC000\u2282\u20D2qual;\u6288ceeds\u0200;EST\u0D32\u0D33\u0D3B\u0D46\u6281qual;\uC000\u2AB0\u0338lantEqual;\u62E1ilde;\uC000\u227F\u0338erset\u0100;E\u0D58\u0D5B\uC000\u2283\u20D2qual;\u6289ilde\u0200;EFT\u0D6E\u0D6F\u0D75\u0D7F\u6241qual;\u6244ullEqual;\u6247ilde;\u6249erticalBar;\u6224cr;\uC000\u{1D4A9}ilde\u803B\xD1\u40D1;\u439D\u0700Eacdfgmoprstuv\u0DBD\u0DC2\u0DC9\u0DD5\u0DDB\u0DE0\u0DE7\u0DFC\u0E02\u0E20\u0E22\u0E32\u0E3F\u0E44lig;\u4152cute\u803B\xD3\u40D3\u0100iy\u0DCE\u0DD3rc\u803B\xD4\u40D4;\u441Eblac;\u4150r;\uC000\u{1D512}rave\u803B\xD2\u40D2\u0180aei\u0DEE\u0DF2\u0DF6cr;\u414Cga;\u43A9cron;\u439Fpf;\uC000\u{1D546}enCurly\u0100DQ\u0E0E\u0E1AoubleQuote;\u601Cuote;\u6018;\u6A54\u0100cl\u0E27\u0E2Cr;\uC000\u{1D4AA}ash\u803B\xD8\u40D8i\u016C\u0E37\u0E3Cde\u803B\xD5\u40D5es;\u6A37ml\u803B\xD6\u40D6er\u0100BP\u0E4B\u0E60\u0100ar\u0E50\u0E53r;\u603Eac\u0100ek\u0E5A\u0E5C;\u63DEet;\u63B4arenthesis;\u63DC\u0480acfhilors\u0E7F\u0E87\u0E8A\u0E8F\u0E92\u0E94\u0E9D\u0EB0\u0EFCrtialD;\u6202y;\u441Fr;\uC000\u{1D513}i;\u43A6;\u43A0usMinus;\u40B1\u0100ip\u0EA2\u0EADncareplan\xE5\u069Df;\u6119\u0200;eio\u0EB9\u0EBA\u0EE0\u0EE4\u6ABBcedes\u0200;EST\u0EC8\u0EC9\u0ECF\u0EDA\u627Aqual;\u6AAFlantEqual;\u627Cilde;\u627Eme;\u6033\u0100dp\u0EE9\u0EEEuct;\u620Fortion\u0100;a\u0225\u0EF9l;\u621D\u0100ci\u0F01\u0F06r;\uC000\u{1D4AB};\u43A8\u0200Ufos\u0F11\u0F16\u0F1B\u0F1FOT\u803B"\u4022r;\uC000\u{1D514}pf;\u611Acr;\uC000\u{1D4AC}\u0600BEacefhiorsu\u0F3E\u0F43\u0F47\u0F60\u0F73\u0FA7\u0FAA\u0FAD\u1096\u10A9\u10B4\u10BEarr;\u6910G\u803B\xAE\u40AE\u0180cnr\u0F4E\u0F53\u0F56ute;\u4154g;\u67EBr\u0100;t\u0F5C\u0F5D\u61A0l;\u6916\u0180aey\u0F67\u0F6C\u0F71ron;\u4158dil;\u4156;\u4420\u0100;v\u0F78\u0F79\u611Cerse\u0100EU\u0F82\u0F99\u0100lq\u0F87\u0F8Eement;\u620Builibrium;\u61CBpEquilibrium;\u696Fr\xBB\u0F79o;\u43A1ght\u0400ACDFTUVa\u0FC1\u0FEB\u0FF3\u1022\u1028\u105B\u1087\u03D8\u0100nr\u0FC6\u0FD2gleBracket;\u67E9row\u0180;BL\u0FDC\u0FDD\u0FE1\u6192ar;\u61E5eftArrow;\u61C4eiling;\u6309o\u01F5\u0FF9\0\u1005bleBracket;\u67E7n\u01D4\u100A\0\u1014eeVector;\u695Dector\u0100;B\u101D\u101E\u61C2ar;\u6955loor;\u630B\u0100er\u102D\u1043e\u0180;AV\u1035\u1036\u103C\u62A2rrow;\u61A6ector;\u695Biangle\u0180;BE\u1050\u1051\u1055\u62B3ar;\u69D0qual;\u62B5p\u0180DTV\u1063\u106E\u1078ownVector;\u694FeeVector;\u695Cector\u0100;B\u1082\u1083\u61BEar;\u6954ector\u0100;B\u1091\u1092\u61C0ar;\u6953\u0100pu\u109B\u109Ef;\u611DndImplies;\u6970ightarrow;\u61DB\u0100ch\u10B9\u10BCr;\u611B;\u61B1leDelayed;\u69F4\u0680HOacfhimoqstu\u10E4\u10F1\u10F7\u10FD\u1119\u111E\u1151\u1156\u1161\u1167\u11B5\u11BB\u11BF\u0100Cc\u10E9\u10EEHcy;\u4429y;\u4428FTcy;\u442Ccute;\u415A\u0280;aeiy\u1108\u1109\u110E\u1113\u1117\u6ABCron;\u4160dil;\u415Erc;\u415C;\u4421r;\uC000\u{1D516}ort\u0200DLRU\u112A\u1134\u113E\u1149ownArrow\xBB\u041EeftArrow\xBB\u089AightArrow\xBB\u0FDDpArrow;\u6191gma;\u43A3allCircle;\u6218pf;\uC000\u{1D54A}\u0272\u116D\0\0\u1170t;\u621Aare\u0200;ISU\u117B\u117C\u1189\u11AF\u65A1ntersection;\u6293u\u0100bp\u118F\u119Eset\u0100;E\u1197\u1198\u628Fqual;\u6291erset\u0100;E\u11A8\u11A9\u6290qual;\u6292nion;\u6294cr;\uC000\u{1D4AE}ar;\u62C6\u0200bcmp\u11C8\u11DB\u1209\u120B\u0100;s\u11CD\u11CE\u62D0et\u0100;E\u11CD\u11D5qual;\u6286\u0100ch\u11E0\u1205eeds\u0200;EST\u11ED\u11EE\u11F4\u11FF\u627Bqual;\u6AB0lantEqual;\u627Dilde;\u627FTh\xE1\u0F8C;\u6211\u0180;es\u1212\u1213\u1223\u62D1rset\u0100;E\u121C\u121D\u6283qual;\u6287et\xBB\u1213\u0580HRSacfhiors\u123E\u1244\u1249\u1255\u125E\u1271\u1276\u129F\u12C2\u12C8\u12D1ORN\u803B\xDE\u40DEADE;\u6122\u0100Hc\u124E\u1252cy;\u440By;\u4426\u0100bu\u125A\u125C;\u4009;\u43A4\u0180aey\u1265\u126A\u126Fron;\u4164dil;\u4162;\u4422r;\uC000\u{1D517}\u0100ei\u127B\u1289\u01F2\u1280\0\u1287efore;\u6234a;\u4398\u0100cn\u128E\u1298kSpace;\uC000\u205F\u200ASpace;\u6009lde\u0200;EFT\u12AB\u12AC\u12B2\u12BC\u623Cqual;\u6243ullEqual;\u6245ilde;\u6248pf;\uC000\u{1D54B}ipleDot;\u60DB\u0100ct\u12D6\u12DBr;\uC000\u{1D4AF}rok;\u4166\u0AE1\u12F7\u130E\u131A\u1326\0\u132C\u1331\0\0\0\0\0\u1338\u133D\u1377\u1385\0\u13FF\u1404\u140A\u1410\u0100cr\u12FB\u1301ute\u803B\xDA\u40DAr\u0100;o\u1307\u1308\u619Fcir;\u6949r\u01E3\u1313\0\u1316y;\u440Eve;\u416C\u0100iy\u131E\u1323rc\u803B\xDB\u40DB;\u4423blac;\u4170r;\uC000\u{1D518}rave\u803B\xD9\u40D9acr;\u416A\u0100di\u1341\u1369er\u0100BP\u1348\u135D\u0100ar\u134D\u1350r;\u405Fac\u0100ek\u1357\u1359;\u63DFet;\u63B5arenthesis;\u63DDon\u0100;P\u1370\u1371\u62C3lus;\u628E\u0100gp\u137B\u137Fon;\u4172f;\uC000\u{1D54C}\u0400ADETadps\u1395\u13AE\u13B8\u13C4\u03E8\u13D2\u13D7\u13F3rrow\u0180;BD\u1150\u13A0\u13A4ar;\u6912ownArrow;\u61C5ownArrow;\u6195quilibrium;\u696Eee\u0100;A\u13CB\u13CC\u62A5rrow;\u61A5own\xE1\u03F3er\u0100LR\u13DE\u13E8eftArrow;\u6196ightArrow;\u6197i\u0100;l\u13F9\u13FA\u43D2on;\u43A5ing;\u416Ecr;\uC000\u{1D4B0}ilde;\u4168ml\u803B\xDC\u40DC\u0480Dbcdefosv\u1427\u142C\u1430\u1433\u143E\u1485\u148A\u1490\u1496ash;\u62ABar;\u6AEBy;\u4412ash\u0100;l\u143B\u143C\u62A9;\u6AE6\u0100er\u1443\u1445;\u62C1\u0180bty\u144C\u1450\u147Aar;\u6016\u0100;i\u144F\u1455cal\u0200BLST\u1461\u1465\u146A\u1474ar;\u6223ine;\u407Ceparator;\u6758ilde;\u6240ThinSpace;\u600Ar;\uC000\u{1D519}pf;\uC000\u{1D54D}cr;\uC000\u{1D4B1}dash;\u62AA\u0280cefos\u14A7\u14AC\u14B1\u14B6\u14BCirc;\u4174dge;\u62C0r;\uC000\u{1D51A}pf;\uC000\u{1D54E}cr;\uC000\u{1D4B2}\u0200fios\u14CB\u14D0\u14D2\u14D8r;\uC000\u{1D51B};\u439Epf;\uC000\u{1D54F}cr;\uC000\u{1D4B3}\u0480AIUacfosu\u14F1\u14F5\u14F9\u14FD\u1504\u150F\u1514\u151A\u1520cy;\u442Fcy;\u4407cy;\u442Ecute\u803B\xDD\u40DD\u0100iy\u1509\u150Drc;\u4176;\u442Br;\uC000\u{1D51C}pf;\uC000\u{1D550}cr;\uC000\u{1D4B4}ml;\u4178\u0400Hacdefos\u1535\u1539\u153F\u154B\u154F\u155D\u1560\u1564cy;\u4416cute;\u4179\u0100ay\u1544\u1549ron;\u417D;\u4417ot;\u417B\u01F2\u1554\0\u155BoWidt\xE8\u0AD9a;\u4396r;\u6128pf;\u6124cr;\uC000\u{1D4B5}\u0BE1\u1583\u158A\u1590\0\u15B0\u15B6\u15BF\0\0\0\0\u15C6\u15DB\u15EB\u165F\u166D\0\u1695\u169B\u16B2\u16B9\0\u16BEcute\u803B\xE1\u40E1reve;\u4103\u0300;Ediuy\u159C\u159D\u15A1\u15A3\u15A8\u15AD\u623E;\uC000\u223E\u0333;\u623Frc\u803B\xE2\u40E2te\u80BB\xB4\u0306;\u4430lig\u803B\xE6\u40E6\u0100;r\xB2\u15BA;\uC000\u{1D51E}rave\u803B\xE0\u40E0\u0100ep\u15CA\u15D6\u0100fp\u15CF\u15D4sym;\u6135\xE8\u15D3ha;\u43B1\u0100ap\u15DFc\u0100cl\u15E4\u15E7r;\u4101g;\u6A3F\u0264\u15F0\0\0\u160A\u0280;adsv\u15FA\u15FB\u15FF\u1601\u1607\u6227nd;\u6A55;\u6A5Clope;\u6A58;\u6A5A\u0380;elmrsz\u1618\u1619\u161B\u161E\u163F\u164F\u1659\u6220;\u69A4e\xBB\u1619sd\u0100;a\u1625\u1626\u6221\u0461\u1630\u1632\u1634\u1636\u1638\u163A\u163C\u163E;\u69A8;\u69A9;\u69AA;\u69AB;\u69AC;\u69AD;\u69AE;\u69AFt\u0100;v\u1645\u1646\u621Fb\u0100;d\u164C\u164D\u62BE;\u699D\u0100pt\u1654\u1657h;\u6222\xBB\xB9arr;\u637C\u0100gp\u1663\u1667on;\u4105f;\uC000\u{1D552}\u0380;Eaeiop\u12C1\u167B\u167D\u1682\u1684\u1687\u168A;\u6A70cir;\u6A6F;\u624Ad;\u624Bs;\u4027rox\u0100;e\u12C1\u1692\xF1\u1683ing\u803B\xE5\u40E5\u0180cty\u16A1\u16A6\u16A8r;\uC000\u{1D4B6};\u402Amp\u0100;e\u12C1\u16AF\xF1\u0288ilde\u803B\xE3\u40E3ml\u803B\xE4\u40E4\u0100ci\u16C2\u16C8onin\xF4\u0272nt;\u6A11\u0800Nabcdefiklnoprsu\u16ED\u16F1\u1730\u173C\u1743\u1748\u1778\u177D\u17E0\u17E6\u1839\u1850\u170D\u193D\u1948\u1970ot;\u6AED\u0100cr\u16F6\u171Ek\u0200ceps\u1700\u1705\u170D\u1713ong;\u624Cpsilon;\u43F6rime;\u6035im\u0100;e\u171A\u171B\u623Dq;\u62CD\u0176\u1722\u1726ee;\u62BDed\u0100;g\u172C\u172D\u6305e\xBB\u172Drk\u0100;t\u135C\u1737brk;\u63B6\u0100oy\u1701\u1741;\u4431quo;\u601E\u0280cmprt\u1753\u175B\u1761\u1764\u1768aus\u0100;e\u010A\u0109ptyv;\u69B0s\xE9\u170Cno\xF5\u0113\u0180ahw\u176F\u1771\u1773;\u43B2;\u6136een;\u626Cr;\uC000\u{1D51F}g\u0380costuvw\u178D\u179D\u17B3\u17C1\u17D5\u17DB\u17DE\u0180aiu\u1794\u1796\u179A\xF0\u0760rc;\u65EFp\xBB\u1371\u0180dpt\u17A4\u17A8\u17ADot;\u6A00lus;\u6A01imes;\u6A02\u0271\u17B9\0\0\u17BEcup;\u6A06ar;\u6605riangle\u0100du\u17CD\u17D2own;\u65BDp;\u65B3plus;\u6A04e\xE5\u1444\xE5\u14ADarow;\u690D\u0180ako\u17ED\u1826\u1835\u0100cn\u17F2\u1823k\u0180lst\u17FA\u05AB\u1802ozenge;\u69EBriangle\u0200;dlr\u1812\u1813\u1818\u181D\u65B4own;\u65BEeft;\u65C2ight;\u65B8k;\u6423\u01B1\u182B\0\u1833\u01B2\u182F\0\u1831;\u6592;\u65914;\u6593ck;\u6588\u0100eo\u183E\u184D\u0100;q\u1843\u1846\uC000=\u20E5uiv;\uC000\u2261\u20E5t;\u6310\u0200ptwx\u1859\u185E\u1867\u186Cf;\uC000\u{1D553}\u0100;t\u13CB\u1863om\xBB\u13CCtie;\u62C8\u0600DHUVbdhmptuv\u1885\u1896\u18AA\u18BB\u18D7\u18DB\u18EC\u18FF\u1905\u190A\u1910\u1921\u0200LRlr\u188E\u1890\u1892\u1894;\u6557;\u6554;\u6556;\u6553\u0280;DUdu\u18A1\u18A2\u18A4\u18A6\u18A8\u6550;\u6566;\u6569;\u6564;\u6567\u0200LRlr\u18B3\u18B5\u18B7\u18B9;\u655D;\u655A;\u655C;\u6559\u0380;HLRhlr\u18CA\u18CB\u18CD\u18CF\u18D1\u18D3\u18D5\u6551;\u656C;\u6563;\u6560;\u656B;\u6562;\u655Fox;\u69C9\u0200LRlr\u18E4\u18E6\u18E8\u18EA;\u6555;\u6552;\u6510;\u650C\u0280;DUdu\u06BD\u18F7\u18F9\u18FB\u18FD;\u6565;\u6568;\u652C;\u6534inus;\u629Flus;\u629Eimes;\u62A0\u0200LRlr\u1919\u191B\u191D\u191F;\u655B;\u6558;\u6518;\u6514\u0380;HLRhlr\u1930\u1931\u1933\u1935\u1937\u1939\u193B\u6502;\u656A;\u6561;\u655E;\u653C;\u6524;\u651C\u0100ev\u0123\u1942bar\u803B\xA6\u40A6\u0200ceio\u1951\u1956\u195A\u1960r;\uC000\u{1D4B7}mi;\u604Fm\u0100;e\u171A\u171Cl\u0180;bh\u1968\u1969\u196B\u405C;\u69C5sub;\u67C8\u016C\u1974\u197El\u0100;e\u1979\u197A\u6022t\xBB\u197Ap\u0180;Ee\u012F\u1985\u1987;\u6AAE\u0100;q\u06DC\u06DB\u0CE1\u19A7\0\u19E8\u1A11\u1A15\u1A32\0\u1A37\u1A50\0\0\u1AB4\0\0\u1AC1\0\0\u1B21\u1B2E\u1B4D\u1B52\0\u1BFD\0\u1C0C\u0180cpr\u19AD\u19B2\u19DDute;\u4107\u0300;abcds\u19BF\u19C0\u19C4\u19CA\u19D5\u19D9\u6229nd;\u6A44rcup;\u6A49\u0100au\u19CF\u19D2p;\u6A4Bp;\u6A47ot;\u6A40;\uC000\u2229\uFE00\u0100eo\u19E2\u19E5t;\u6041\xEE\u0693\u0200aeiu\u19F0\u19FB\u1A01\u1A05\u01F0\u19F5\0\u19F8s;\u6A4Don;\u410Ddil\u803B\xE7\u40E7rc;\u4109ps\u0100;s\u1A0C\u1A0D\u6A4Cm;\u6A50ot;\u410B\u0180dmn\u1A1B\u1A20\u1A26il\u80BB\xB8\u01ADptyv;\u69B2t\u8100\xA2;e\u1A2D\u1A2E\u40A2r\xE4\u01B2r;\uC000\u{1D520}\u0180cei\u1A3D\u1A40\u1A4Dy;\u4447ck\u0100;m\u1A47\u1A48\u6713ark\xBB\u1A48;\u43C7r\u0380;Ecefms\u1A5F\u1A60\u1A62\u1A6B\u1AA4\u1AAA\u1AAE\u65CB;\u69C3\u0180;el\u1A69\u1A6A\u1A6D\u42C6q;\u6257e\u0261\u1A74\0\0\u1A88rrow\u0100lr\u1A7C\u1A81eft;\u61BAight;\u61BB\u0280RSacd\u1A92\u1A94\u1A96\u1A9A\u1A9F\xBB\u0F47;\u64C8st;\u629Birc;\u629Aash;\u629Dnint;\u6A10id;\u6AEFcir;\u69C2ubs\u0100;u\u1ABB\u1ABC\u6663it\xBB\u1ABC\u02EC\u1AC7\u1AD4\u1AFA\0\u1B0Aon\u0100;e\u1ACD\u1ACE\u403A\u0100;q\xC7\xC6\u026D\u1AD9\0\0\u1AE2a\u0100;t\u1ADE\u1ADF\u402C;\u4040\u0180;fl\u1AE8\u1AE9\u1AEB\u6201\xEE\u1160e\u0100mx\u1AF1\u1AF6ent\xBB\u1AE9e\xF3\u024D\u01E7\u1AFE\0\u1B07\u0100;d\u12BB\u1B02ot;\u6A6Dn\xF4\u0246\u0180fry\u1B10\u1B14\u1B17;\uC000\u{1D554}o\xE4\u0254\u8100\xA9;s\u0155\u1B1Dr;\u6117\u0100ao\u1B25\u1B29rr;\u61B5ss;\u6717\u0100cu\u1B32\u1B37r;\uC000\u{1D4B8}\u0100bp\u1B3C\u1B44\u0100;e\u1B41\u1B42\u6ACF;\u6AD1\u0100;e\u1B49\u1B4A\u6AD0;\u6AD2dot;\u62EF\u0380delprvw\u1B60\u1B6C\u1B77\u1B82\u1BAC\u1BD4\u1BF9arr\u0100lr\u1B68\u1B6A;\u6938;\u6935\u0270\u1B72\0\0\u1B75r;\u62DEc;\u62DFarr\u0100;p\u1B7F\u1B80\u61B6;\u693D\u0300;bcdos\u1B8F\u1B90\u1B96\u1BA1\u1BA5\u1BA8\u622Arcap;\u6A48\u0100au\u1B9B\u1B9Ep;\u6A46p;\u6A4Aot;\u628Dr;\u6A45;\uC000\u222A\uFE00\u0200alrv\u1BB5\u1BBF\u1BDE\u1BE3rr\u0100;m\u1BBC\u1BBD\u61B7;\u693Cy\u0180evw\u1BC7\u1BD4\u1BD8q\u0270\u1BCE\0\0\u1BD2re\xE3\u1B73u\xE3\u1B75ee;\u62CEedge;\u62CFen\u803B\xA4\u40A4earrow\u0100lr\u1BEE\u1BF3eft\xBB\u1B80ight\xBB\u1BBDe\xE4\u1BDD\u0100ci\u1C01\u1C07onin\xF4\u01F7nt;\u6231lcty;\u632D\u0980AHabcdefhijlorstuwz\u1C38\u1C3B\u1C3F\u1C5D\u1C69\u1C75\u1C8A\u1C9E\u1CAC\u1CB7\u1CFB\u1CFF\u1D0D\u1D7B\u1D91\u1DAB\u1DBB\u1DC6\u1DCDr\xF2\u0381ar;\u6965\u0200glrs\u1C48\u1C4D\u1C52\u1C54ger;\u6020eth;\u6138\xF2\u1133h\u0100;v\u1C5A\u1C5B\u6010\xBB\u090A\u016B\u1C61\u1C67arow;\u690Fa\xE3\u0315\u0100ay\u1C6E\u1C73ron;\u410F;\u4434\u0180;ao\u0332\u1C7C\u1C84\u0100gr\u02BF\u1C81r;\u61CAtseq;\u6A77\u0180glm\u1C91\u1C94\u1C98\u803B\xB0\u40B0ta;\u43B4ptyv;\u69B1\u0100ir\u1CA3\u1CA8sht;\u697F;\uC000\u{1D521}ar\u0100lr\u1CB3\u1CB5\xBB\u08DC\xBB\u101E\u0280aegsv\u1CC2\u0378\u1CD6\u1CDC\u1CE0m\u0180;os\u0326\u1CCA\u1CD4nd\u0100;s\u0326\u1CD1uit;\u6666amma;\u43DDin;\u62F2\u0180;io\u1CE7\u1CE8\u1CF8\u40F7de\u8100\xF7;o\u1CE7\u1CF0ntimes;\u62C7n\xF8\u1CF7cy;\u4452c\u026F\u1D06\0\0\u1D0Arn;\u631Eop;\u630D\u0280lptuw\u1D18\u1D1D\u1D22\u1D49\u1D55lar;\u4024f;\uC000\u{1D555}\u0280;emps\u030B\u1D2D\u1D37\u1D3D\u1D42q\u0100;d\u0352\u1D33ot;\u6251inus;\u6238lus;\u6214quare;\u62A1blebarwedg\xE5\xFAn\u0180adh\u112E\u1D5D\u1D67ownarrow\xF3\u1C83arpoon\u0100lr\u1D72\u1D76ef\xF4\u1CB4igh\xF4\u1CB6\u0162\u1D7F\u1D85karo\xF7\u0F42\u026F\u1D8A\0\0\u1D8Ern;\u631Fop;\u630C\u0180cot\u1D98\u1DA3\u1DA6\u0100ry\u1D9D\u1DA1;\uC000\u{1D4B9};\u4455l;\u69F6rok;\u4111\u0100dr\u1DB0\u1DB4ot;\u62F1i\u0100;f\u1DBA\u1816\u65BF\u0100ah\u1DC0\u1DC3r\xF2\u0429a\xF2\u0FA6angle;\u69A6\u0100ci\u1DD2\u1DD5y;\u445Fgrarr;\u67FF\u0900Dacdefglmnopqrstux\u1E01\u1E09\u1E19\u1E38\u0578\u1E3C\u1E49\u1E61\u1E7E\u1EA5\u1EAF\u1EBD\u1EE1\u1F2A\u1F37\u1F44\u1F4E\u1F5A\u0100Do\u1E06\u1D34o\xF4\u1C89\u0100cs\u1E0E\u1E14ute\u803B\xE9\u40E9ter;\u6A6E\u0200aioy\u1E22\u1E27\u1E31\u1E36ron;\u411Br\u0100;c\u1E2D\u1E2E\u6256\u803B\xEA\u40EAlon;\u6255;\u444Dot;\u4117\u0100Dr\u1E41\u1E45ot;\u6252;\uC000\u{1D522}\u0180;rs\u1E50\u1E51\u1E57\u6A9Aave\u803B\xE8\u40E8\u0100;d\u1E5C\u1E5D\u6A96ot;\u6A98\u0200;ils\u1E6A\u1E6B\u1E72\u1E74\u6A99nters;\u63E7;\u6113\u0100;d\u1E79\u1E7A\u6A95ot;\u6A97\u0180aps\u1E85\u1E89\u1E97cr;\u4113ty\u0180;sv\u1E92\u1E93\u1E95\u6205et\xBB\u1E93p\u01001;\u1E9D\u1EA4\u0133\u1EA1\u1EA3;\u6004;\u6005\u6003\u0100gs\u1EAA\u1EAC;\u414Bp;\u6002\u0100gp\u1EB4\u1EB8on;\u4119f;\uC000\u{1D556}\u0180als\u1EC4\u1ECE\u1ED2r\u0100;s\u1ECA\u1ECB\u62D5l;\u69E3us;\u6A71i\u0180;lv\u1EDA\u1EDB\u1EDF\u43B5on\xBB\u1EDB;\u43F5\u0200csuv\u1EEA\u1EF3\u1F0B\u1F23\u0100io\u1EEF\u1E31rc\xBB\u1E2E\u0269\u1EF9\0\0\u1EFB\xED\u0548ant\u0100gl\u1F02\u1F06tr\xBB\u1E5Dess\xBB\u1E7A\u0180aei\u1F12\u1F16\u1F1Als;\u403Dst;\u625Fv\u0100;D\u0235\u1F20D;\u6A78parsl;\u69E5\u0100Da\u1F2F\u1F33ot;\u6253rr;\u6971\u0180cdi\u1F3E\u1F41\u1EF8r;\u612Fo\xF4\u0352\u0100ah\u1F49\u1F4B;\u43B7\u803B\xF0\u40F0\u0100mr\u1F53\u1F57l\u803B\xEB\u40EBo;\u60AC\u0180cip\u1F61\u1F64\u1F67l;\u4021s\xF4\u056E\u0100eo\u1F6C\u1F74ctatio\xEE\u0559nential\xE5\u0579\u09E1\u1F92\0\u1F9E\0\u1FA1\u1FA7\0\0\u1FC6\u1FCC\0\u1FD3\0\u1FE6\u1FEA\u2000\0\u2008\u205Allingdotse\xF1\u1E44y;\u4444male;\u6640\u0180ilr\u1FAD\u1FB3\u1FC1lig;\u8000\uFB03\u0269\u1FB9\0\0\u1FBDg;\u8000\uFB00ig;\u8000\uFB04;\uC000\u{1D523}lig;\u8000\uFB01lig;\uC000fj\u0180alt\u1FD9\u1FDC\u1FE1t;\u666Dig;\u8000\uFB02ns;\u65B1of;\u4192\u01F0\u1FEE\0\u1FF3f;\uC000\u{1D557}\u0100ak\u05BF\u1FF7\u0100;v\u1FFC\u1FFD\u62D4;\u6AD9artint;\u6A0D\u0100ao\u200C\u2055\u0100cs\u2011\u2052\u03B1\u201A\u2030\u2038\u2045\u2048\0\u2050\u03B2\u2022\u2025\u2027\u202A\u202C\0\u202E\u803B\xBD\u40BD;\u6153\u803B\xBC\u40BC;\u6155;\u6159;\u615B\u01B3\u2034\0\u2036;\u6154;\u6156\u02B4\u203E\u2041\0\0\u2043\u803B\xBE\u40BE;\u6157;\u615C5;\u6158\u01B6\u204C\0\u204E;\u615A;\u615D8;\u615El;\u6044wn;\u6322cr;\uC000\u{1D4BB}\u0880Eabcdefgijlnorstv\u2082\u2089\u209F\u20A5\u20B0\u20B4\u20F0\u20F5\u20FA\u20FF\u2103\u2112\u2138\u0317\u213E\u2152\u219E\u0100;l\u064D\u2087;\u6A8C\u0180cmp\u2090\u2095\u209Dute;\u41F5ma\u0100;d\u209C\u1CDA\u43B3;\u6A86reve;\u411F\u0100iy\u20AA\u20AErc;\u411D;\u4433ot;\u4121\u0200;lqs\u063E\u0642\u20BD\u20C9\u0180;qs\u063E\u064C\u20C4lan\xF4\u0665\u0200;cdl\u0665\u20D2\u20D5\u20E5c;\u6AA9ot\u0100;o\u20DC\u20DD\u6A80\u0100;l\u20E2\u20E3\u6A82;\u6A84\u0100;e\u20EA\u20ED\uC000\u22DB\uFE00s;\u6A94r;\uC000\u{1D524}\u0100;g\u0673\u061Bmel;\u6137cy;\u4453\u0200;Eaj\u065A\u210C\u210E\u2110;\u6A92;\u6AA5;\u6AA4\u0200Eaes\u211B\u211D\u2129\u2134;\u6269p\u0100;p\u2123\u2124\u6A8Arox\xBB\u2124\u0100;q\u212E\u212F\u6A88\u0100;q\u212E\u211Bim;\u62E7pf;\uC000\u{1D558}\u0100ci\u2143\u2146r;\u610Am\u0180;el\u066B\u214E\u2150;\u6A8E;\u6A90\u8300>;cdlqr\u05EE\u2160\u216A\u216E\u2173\u2179\u0100ci\u2165\u2167;\u6AA7r;\u6A7Aot;\u62D7Par;\u6995uest;\u6A7C\u0280adels\u2184\u216A\u2190\u0656\u219B\u01F0\u2189\0\u218Epro\xF8\u209Er;\u6978q\u0100lq\u063F\u2196les\xF3\u2088i\xED\u066B\u0100en\u21A3\u21ADrtneqq;\uC000\u2269\uFE00\xC5\u21AA\u0500Aabcefkosy\u21C4\u21C7\u21F1\u21F5\u21FA\u2218\u221D\u222F\u2268\u227Dr\xF2\u03A0\u0200ilmr\u21D0\u21D4\u21D7\u21DBrs\xF0\u1484f\xBB\u2024il\xF4\u06A9\u0100dr\u21E0\u21E4cy;\u444A\u0180;cw\u08F4\u21EB\u21EFir;\u6948;\u61ADar;\u610Firc;\u4125\u0180alr\u2201\u220E\u2213rts\u0100;u\u2209\u220A\u6665it\xBB\u220Alip;\u6026con;\u62B9r;\uC000\u{1D525}s\u0100ew\u2223\u2229arow;\u6925arow;\u6926\u0280amopr\u223A\u223E\u2243\u225E\u2263rr;\u61FFtht;\u623Bk\u0100lr\u2249\u2253eftarrow;\u61A9ightarrow;\u61AAf;\uC000\u{1D559}bar;\u6015\u0180clt\u226F\u2274\u2278r;\uC000\u{1D4BD}as\xE8\u21F4rok;\u4127\u0100bp\u2282\u2287ull;\u6043hen\xBB\u1C5B\u0AE1\u22A3\0\u22AA\0\u22B8\u22C5\u22CE\0\u22D5\u22F3\0\0\u22F8\u2322\u2367\u2362\u237F\0\u2386\u23AA\u23B4cute\u803B\xED\u40ED\u0180;iy\u0771\u22B0\u22B5rc\u803B\xEE\u40EE;\u4438\u0100cx\u22BC\u22BFy;\u4435cl\u803B\xA1\u40A1\u0100fr\u039F\u22C9;\uC000\u{1D526}rave\u803B\xEC\u40EC\u0200;ino\u073E\u22DD\u22E9\u22EE\u0100in\u22E2\u22E6nt;\u6A0Ct;\u622Dfin;\u69DCta;\u6129lig;\u4133\u0180aop\u22FE\u231A\u231D\u0180cgt\u2305\u2308\u2317r;\u412B\u0180elp\u071F\u230F\u2313in\xE5\u078Ear\xF4\u0720h;\u4131f;\u62B7ed;\u41B5\u0280;cfot\u04F4\u232C\u2331\u233D\u2341are;\u6105in\u0100;t\u2338\u2339\u621Eie;\u69DDdo\xF4\u2319\u0280;celp\u0757\u234C\u2350\u235B\u2361al;\u62BA\u0100gr\u2355\u2359er\xF3\u1563\xE3\u234Darhk;\u6A17rod;\u6A3C\u0200cgpt\u236F\u2372\u2376\u237By;\u4451on;\u412Ff;\uC000\u{1D55A}a;\u43B9uest\u803B\xBF\u40BF\u0100ci\u238A\u238Fr;\uC000\u{1D4BE}n\u0280;Edsv\u04F4\u239B\u239D\u23A1\u04F3;\u62F9ot;\u62F5\u0100;v\u23A6\u23A7\u62F4;\u62F3\u0100;i\u0777\u23AElde;\u4129\u01EB\u23B8\0\u23BCcy;\u4456l\u803B\xEF\u40EF\u0300cfmosu\u23CC\u23D7\u23DC\u23E1\u23E7\u23F5\u0100iy\u23D1\u23D5rc;\u4135;\u4439r;\uC000\u{1D527}ath;\u4237pf;\uC000\u{1D55B}\u01E3\u23EC\0\u23F1r;\uC000\u{1D4BF}rcy;\u4458kcy;\u4454\u0400acfghjos\u240B\u2416\u2422\u2427\u242D\u2431\u2435\u243Bppa\u0100;v\u2413\u2414\u43BA;\u43F0\u0100ey\u241B\u2420dil;\u4137;\u443Ar;\uC000\u{1D528}reen;\u4138cy;\u4445cy;\u445Cpf;\uC000\u{1D55C}cr;\uC000\u{1D4C0}\u0B80ABEHabcdefghjlmnoprstuv\u2470\u2481\u2486\u248D\u2491\u250E\u253D\u255A\u2580\u264E\u265E\u2665\u2679\u267D\u269A\u26B2\u26D8\u275D\u2768\u278B\u27C0\u2801\u2812\u0180art\u2477\u247A\u247Cr\xF2\u09C6\xF2\u0395ail;\u691Barr;\u690E\u0100;g\u0994\u248B;\u6A8Bar;\u6962\u0963\u24A5\0\u24AA\0\u24B1\0\0\0\0\0\u24B5\u24BA\0\u24C6\u24C8\u24CD\0\u24F9ute;\u413Amptyv;\u69B4ra\xEE\u084Cbda;\u43BBg\u0180;dl\u088E\u24C1\u24C3;\u6991\xE5\u088E;\u6A85uo\u803B\xAB\u40ABr\u0400;bfhlpst\u0899\u24DE\u24E6\u24E9\u24EB\u24EE\u24F1\u24F5\u0100;f\u089D\u24E3s;\u691Fs;\u691D\xEB\u2252p;\u61ABl;\u6939im;\u6973l;\u61A2\u0180;ae\u24FF\u2500\u2504\u6AABil;\u6919\u0100;s\u2509\u250A\u6AAD;\uC000\u2AAD\uFE00\u0180abr\u2515\u2519\u251Drr;\u690Crk;\u6772\u0100ak\u2522\u252Cc\u0100ek\u2528\u252A;\u407B;\u405B\u0100es\u2531\u2533;\u698Bl\u0100du\u2539\u253B;\u698F;\u698D\u0200aeuy\u2546\u254B\u2556\u2558ron;\u413E\u0100di\u2550\u2554il;\u413C\xEC\u08B0\xE2\u2529;\u443B\u0200cqrs\u2563\u2566\u256D\u257Da;\u6936uo\u0100;r\u0E19\u1746\u0100du\u2572\u2577har;\u6967shar;\u694Bh;\u61B2\u0280;fgqs\u258B\u258C\u0989\u25F3\u25FF\u6264t\u0280ahlrt\u2598\u25A4\u25B7\u25C2\u25E8rrow\u0100;t\u0899\u25A1a\xE9\u24F6arpoon\u0100du\u25AF\u25B4own\xBB\u045Ap\xBB\u0966eftarrows;\u61C7ight\u0180ahs\u25CD\u25D6\u25DErrow\u0100;s\u08F4\u08A7arpoon\xF3\u0F98quigarro\xF7\u21F0hreetimes;\u62CB\u0180;qs\u258B\u0993\u25FAlan\xF4\u09AC\u0280;cdgs\u09AC\u260A\u260D\u261D\u2628c;\u6AA8ot\u0100;o\u2614\u2615\u6A7F\u0100;r\u261A\u261B\u6A81;\u6A83\u0100;e\u2622\u2625\uC000\u22DA\uFE00s;\u6A93\u0280adegs\u2633\u2639\u263D\u2649\u264Bppro\xF8\u24C6ot;\u62D6q\u0100gq\u2643\u2645\xF4\u0989gt\xF2\u248C\xF4\u099Bi\xED\u09B2\u0180ilr\u2655\u08E1\u265Asht;\u697C;\uC000\u{1D529}\u0100;E\u099C\u2663;\u6A91\u0161\u2669\u2676r\u0100du\u25B2\u266E\u0100;l\u0965\u2673;\u696Alk;\u6584cy;\u4459\u0280;acht\u0A48\u2688\u268B\u2691\u2696r\xF2\u25C1orne\xF2\u1D08ard;\u696Bri;\u65FA\u0100io\u269F\u26A4dot;\u4140ust\u0100;a\u26AC\u26AD\u63B0che\xBB\u26AD\u0200Eaes\u26BB\u26BD\u26C9\u26D4;\u6268p\u0100;p\u26C3\u26C4\u6A89rox\xBB\u26C4\u0100;q\u26CE\u26CF\u6A87\u0100;q\u26CE\u26BBim;\u62E6\u0400abnoptwz\u26E9\u26F4\u26F7\u271A\u272F\u2741\u2747\u2750\u0100nr\u26EE\u26F1g;\u67ECr;\u61FDr\xEB\u08C1g\u0180lmr\u26FF\u270D\u2714eft\u0100ar\u09E6\u2707ight\xE1\u09F2apsto;\u67FCight\xE1\u09FDparrow\u0100lr\u2725\u2729ef\xF4\u24EDight;\u61AC\u0180afl\u2736\u2739\u273Dr;\u6985;\uC000\u{1D55D}us;\u6A2Dimes;\u6A34\u0161\u274B\u274Fst;\u6217\xE1\u134E\u0180;ef\u2757\u2758\u1800\u65CAnge\xBB\u2758ar\u0100;l\u2764\u2765\u4028t;\u6993\u0280achmt\u2773\u2776\u277C\u2785\u2787r\xF2\u08A8orne\xF2\u1D8Car\u0100;d\u0F98\u2783;\u696D;\u600Eri;\u62BF\u0300achiqt\u2798\u279D\u0A40\u27A2\u27AE\u27BBquo;\u6039r;\uC000\u{1D4C1}m\u0180;eg\u09B2\u27AA\u27AC;\u6A8D;\u6A8F\u0100bu\u252A\u27B3o\u0100;r\u0E1F\u27B9;\u601Arok;\u4142\u8400<;cdhilqr\u082B\u27D2\u2639\u27DC\u27E0\u27E5\u27EA\u27F0\u0100ci\u27D7\u27D9;\u6AA6r;\u6A79re\xE5\u25F2mes;\u62C9arr;\u6976uest;\u6A7B\u0100Pi\u27F5\u27F9ar;\u6996\u0180;ef\u2800\u092D\u181B\u65C3r\u0100du\u2807\u280Dshar;\u694Ahar;\u6966\u0100en\u2817\u2821rtneqq;\uC000\u2268\uFE00\xC5\u281E\u0700Dacdefhilnopsu\u2840\u2845\u2882\u288E\u2893\u28A0\u28A5\u28A8\u28DA\u28E2\u28E4\u0A83\u28F3\u2902Dot;\u623A\u0200clpr\u284E\u2852\u2863\u287Dr\u803B\xAF\u40AF\u0100et\u2857\u2859;\u6642\u0100;e\u285E\u285F\u6720se\xBB\u285F\u0100;s\u103B\u2868to\u0200;dlu\u103B\u2873\u2877\u287Bow\xEE\u048Cef\xF4\u090F\xF0\u13D1ker;\u65AE\u0100oy\u2887\u288Cmma;\u6A29;\u443Cash;\u6014asuredangle\xBB\u1626r;\uC000\u{1D52A}o;\u6127\u0180cdn\u28AF\u28B4\u28C9ro\u803B\xB5\u40B5\u0200;acd\u1464\u28BD\u28C0\u28C4s\xF4\u16A7ir;\u6AF0ot\u80BB\xB7\u01B5us\u0180;bd\u28D2\u1903\u28D3\u6212\u0100;u\u1D3C\u28D8;\u6A2A\u0163\u28DE\u28E1p;\u6ADB\xF2\u2212\xF0\u0A81\u0100dp\u28E9\u28EEels;\u62A7f;\uC000\u{1D55E}\u0100ct\u28F8\u28FDr;\uC000\u{1D4C2}pos\xBB\u159D\u0180;lm\u2909\u290A\u290D\u43BCtimap;\u62B8\u0C00GLRVabcdefghijlmoprstuvw\u2942\u2953\u297E\u2989\u2998\u29DA\u29E9\u2A15\u2A1A\u2A58\u2A5D\u2A83\u2A95\u2AA4\u2AA8\u2B04\u2B07\u2B44\u2B7F\u2BAE\u2C34\u2C67\u2C7C\u2CE9\u0100gt\u2947\u294B;\uC000\u22D9\u0338\u0100;v\u2950\u0BCF\uC000\u226B\u20D2\u0180elt\u295A\u2972\u2976ft\u0100ar\u2961\u2967rrow;\u61CDightarrow;\u61CE;\uC000\u22D8\u0338\u0100;v\u297B\u0C47\uC000\u226A\u20D2ightarrow;\u61CF\u0100Dd\u298E\u2993ash;\u62AFash;\u62AE\u0280bcnpt\u29A3\u29A7\u29AC\u29B1\u29CCla\xBB\u02DEute;\u4144g;\uC000\u2220\u20D2\u0280;Eiop\u0D84\u29BC\u29C0\u29C5\u29C8;\uC000\u2A70\u0338d;\uC000\u224B\u0338s;\u4149ro\xF8\u0D84ur\u0100;a\u29D3\u29D4\u666El\u0100;s\u29D3\u0B38\u01F3\u29DF\0\u29E3p\u80BB\xA0\u0B37mp\u0100;e\u0BF9\u0C00\u0280aeouy\u29F4\u29FE\u2A03\u2A10\u2A13\u01F0\u29F9\0\u29FB;\u6A43on;\u4148dil;\u4146ng\u0100;d\u0D7E\u2A0Aot;\uC000\u2A6D\u0338p;\u6A42;\u443Dash;\u6013\u0380;Aadqsx\u0B92\u2A29\u2A2D\u2A3B\u2A41\u2A45\u2A50rr;\u61D7r\u0100hr\u2A33\u2A36k;\u6924\u0100;o\u13F2\u13F0ot;\uC000\u2250\u0338ui\xF6\u0B63\u0100ei\u2A4A\u2A4Ear;\u6928\xED\u0B98ist\u0100;s\u0BA0\u0B9Fr;\uC000\u{1D52B}\u0200Eest\u0BC5\u2A66\u2A79\u2A7C\u0180;qs\u0BBC\u2A6D\u0BE1\u0180;qs\u0BBC\u0BC5\u2A74lan\xF4\u0BE2i\xED\u0BEA\u0100;r\u0BB6\u2A81\xBB\u0BB7\u0180Aap\u2A8A\u2A8D\u2A91r\xF2\u2971rr;\u61AEar;\u6AF2\u0180;sv\u0F8D\u2A9C\u0F8C\u0100;d\u2AA1\u2AA2\u62FC;\u62FAcy;\u445A\u0380AEadest\u2AB7\u2ABA\u2ABE\u2AC2\u2AC5\u2AF6\u2AF9r\xF2\u2966;\uC000\u2266\u0338rr;\u619Ar;\u6025\u0200;fqs\u0C3B\u2ACE\u2AE3\u2AEFt\u0100ar\u2AD4\u2AD9rro\xF7\u2AC1ightarro\xF7\u2A90\u0180;qs\u0C3B\u2ABA\u2AEAlan\xF4\u0C55\u0100;s\u0C55\u2AF4\xBB\u0C36i\xED\u0C5D\u0100;r\u0C35\u2AFEi\u0100;e\u0C1A\u0C25i\xE4\u0D90\u0100pt\u2B0C\u2B11f;\uC000\u{1D55F}\u8180\xAC;in\u2B19\u2B1A\u2B36\u40ACn\u0200;Edv\u0B89\u2B24\u2B28\u2B2E;\uC000\u22F9\u0338ot;\uC000\u22F5\u0338\u01E1\u0B89\u2B33\u2B35;\u62F7;\u62F6i\u0100;v\u0CB8\u2B3C\u01E1\u0CB8\u2B41\u2B43;\u62FE;\u62FD\u0180aor\u2B4B\u2B63\u2B69r\u0200;ast\u0B7B\u2B55\u2B5A\u2B5Flle\xEC\u0B7Bl;\uC000\u2AFD\u20E5;\uC000\u2202\u0338lint;\u6A14\u0180;ce\u0C92\u2B70\u2B73u\xE5\u0CA5\u0100;c\u0C98\u2B78\u0100;e\u0C92\u2B7D\xF1\u0C98\u0200Aait\u2B88\u2B8B\u2B9D\u2BA7r\xF2\u2988rr\u0180;cw\u2B94\u2B95\u2B99\u619B;\uC000\u2933\u0338;\uC000\u219D\u0338ghtarrow\xBB\u2B95ri\u0100;e\u0CCB\u0CD6\u0380chimpqu\u2BBD\u2BCD\u2BD9\u2B04\u0B78\u2BE4\u2BEF\u0200;cer\u0D32\u2BC6\u0D37\u2BC9u\xE5\u0D45;\uC000\u{1D4C3}ort\u026D\u2B05\0\0\u2BD6ar\xE1\u2B56m\u0100;e\u0D6E\u2BDF\u0100;q\u0D74\u0D73su\u0100bp\u2BEB\u2BED\xE5\u0CF8\xE5\u0D0B\u0180bcp\u2BF6\u2C11\u2C19\u0200;Ees\u2BFF\u2C00\u0D22\u2C04\u6284;\uC000\u2AC5\u0338et\u0100;e\u0D1B\u2C0Bq\u0100;q\u0D23\u2C00c\u0100;e\u0D32\u2C17\xF1\u0D38\u0200;Ees\u2C22\u2C23\u0D5F\u2C27\u6285;\uC000\u2AC6\u0338et\u0100;e\u0D58\u2C2Eq\u0100;q\u0D60\u2C23\u0200gilr\u2C3D\u2C3F\u2C45\u2C47\xEC\u0BD7lde\u803B\xF1\u40F1\xE7\u0C43iangle\u0100lr\u2C52\u2C5Ceft\u0100;e\u0C1A\u2C5A\xF1\u0C26ight\u0100;e\u0CCB\u2C65\xF1\u0CD7\u0100;m\u2C6C\u2C6D\u43BD\u0180;es\u2C74\u2C75\u2C79\u4023ro;\u6116p;\u6007\u0480DHadgilrs\u2C8F\u2C94\u2C99\u2C9E\u2CA3\u2CB0\u2CB6\u2CD3\u2CE3ash;\u62ADarr;\u6904p;\uC000\u224D\u20D2ash;\u62AC\u0100et\u2CA8\u2CAC;\uC000\u2265\u20D2;\uC000>\u20D2nfin;\u69DE\u0180Aet\u2CBD\u2CC1\u2CC5rr;\u6902;\uC000\u2264\u20D2\u0100;r\u2CCA\u2CCD\uC000<\u20D2ie;\uC000\u22B4\u20D2\u0100At\u2CD8\u2CDCrr;\u6903rie;\uC000\u22B5\u20D2im;\uC000\u223C\u20D2\u0180Aan\u2CF0\u2CF4\u2D02rr;\u61D6r\u0100hr\u2CFA\u2CFDk;\u6923\u0100;o\u13E7\u13E5ear;\u6927\u1253\u1A95\0\0\0\0\0\0\0\0\0\0\0\0\0\u2D2D\0\u2D38\u2D48\u2D60\u2D65\u2D72\u2D84\u1B07\0\0\u2D8D\u2DAB\0\u2DC8\u2DCE\0\u2DDC\u2E19\u2E2B\u2E3E\u2E43\u0100cs\u2D31\u1A97ute\u803B\xF3\u40F3\u0100iy\u2D3C\u2D45r\u0100;c\u1A9E\u2D42\u803B\xF4\u40F4;\u443E\u0280abios\u1AA0\u2D52\u2D57\u01C8\u2D5Alac;\u4151v;\u6A38old;\u69BClig;\u4153\u0100cr\u2D69\u2D6Dir;\u69BF;\uC000\u{1D52C}\u036F\u2D79\0\0\u2D7C\0\u2D82n;\u42DBave\u803B\xF2\u40F2;\u69C1\u0100bm\u2D88\u0DF4ar;\u69B5\u0200acit\u2D95\u2D98\u2DA5\u2DA8r\xF2\u1A80\u0100ir\u2D9D\u2DA0r;\u69BEoss;\u69BBn\xE5\u0E52;\u69C0\u0180aei\u2DB1\u2DB5\u2DB9cr;\u414Dga;\u43C9\u0180cdn\u2DC0\u2DC5\u01CDron;\u43BF;\u69B6pf;\uC000\u{1D560}\u0180ael\u2DD4\u2DD7\u01D2r;\u69B7rp;\u69B9\u0380;adiosv\u2DEA\u2DEB\u2DEE\u2E08\u2E0D\u2E10\u2E16\u6228r\xF2\u1A86\u0200;efm\u2DF7\u2DF8\u2E02\u2E05\u6A5Dr\u0100;o\u2DFE\u2DFF\u6134f\xBB\u2DFF\u803B\xAA\u40AA\u803B\xBA\u40BAgof;\u62B6r;\u6A56lope;\u6A57;\u6A5B\u0180clo\u2E1F\u2E21\u2E27\xF2\u2E01ash\u803B\xF8\u40F8l;\u6298i\u016C\u2E2F\u2E34de\u803B\xF5\u40F5es\u0100;a\u01DB\u2E3As;\u6A36ml\u803B\xF6\u40F6bar;\u633D\u0AE1\u2E5E\0\u2E7D\0\u2E80\u2E9D\0\u2EA2\u2EB9\0\0\u2ECB\u0E9C\0\u2F13\0\0\u2F2B\u2FBC\0\u2FC8r\u0200;ast\u0403\u2E67\u2E72\u0E85\u8100\xB6;l\u2E6D\u2E6E\u40B6le\xEC\u0403\u0269\u2E78\0\0\u2E7Bm;\u6AF3;\u6AFDy;\u443Fr\u0280cimpt\u2E8B\u2E8F\u2E93\u1865\u2E97nt;\u4025od;\u402Eil;\u6030enk;\u6031r;\uC000\u{1D52D}\u0180imo\u2EA8\u2EB0\u2EB4\u0100;v\u2EAD\u2EAE\u43C6;\u43D5ma\xF4\u0A76ne;\u660E\u0180;tv\u2EBF\u2EC0\u2EC8\u43C0chfork\xBB\u1FFD;\u43D6\u0100au\u2ECF\u2EDFn\u0100ck\u2ED5\u2EDDk\u0100;h\u21F4\u2EDB;\u610E\xF6\u21F4s\u0480;abcdemst\u2EF3\u2EF4\u1908\u2EF9\u2EFD\u2F04\u2F06\u2F0A\u2F0E\u402Bcir;\u6A23ir;\u6A22\u0100ou\u1D40\u2F02;\u6A25;\u6A72n\u80BB\xB1\u0E9Dim;\u6A26wo;\u6A27\u0180ipu\u2F19\u2F20\u2F25ntint;\u6A15f;\uC000\u{1D561}nd\u803B\xA3\u40A3\u0500;Eaceinosu\u0EC8\u2F3F\u2F41\u2F44\u2F47\u2F81\u2F89\u2F92\u2F7E\u2FB6;\u6AB3p;\u6AB7u\xE5\u0ED9\u0100;c\u0ECE\u2F4C\u0300;acens\u0EC8\u2F59\u2F5F\u2F66\u2F68\u2F7Eppro\xF8\u2F43urlye\xF1\u0ED9\xF1\u0ECE\u0180aes\u2F6F\u2F76\u2F7Approx;\u6AB9qq;\u6AB5im;\u62E8i\xED\u0EDFme\u0100;s\u2F88\u0EAE\u6032\u0180Eas\u2F78\u2F90\u2F7A\xF0\u2F75\u0180dfp\u0EEC\u2F99\u2FAF\u0180als\u2FA0\u2FA5\u2FAAlar;\u632Eine;\u6312urf;\u6313\u0100;t\u0EFB\u2FB4\xEF\u0EFBrel;\u62B0\u0100ci\u2FC0\u2FC5r;\uC000\u{1D4C5};\u43C8ncsp;\u6008\u0300fiopsu\u2FDA\u22E2\u2FDF\u2FE5\u2FEB\u2FF1r;\uC000\u{1D52E}pf;\uC000\u{1D562}rime;\u6057cr;\uC000\u{1D4C6}\u0180aeo\u2FF8\u3009\u3013t\u0100ei\u2FFE\u3005rnion\xF3\u06B0nt;\u6A16st\u0100;e\u3010\u3011\u403F\xF1\u1F19\xF4\u0F14\u0A80ABHabcdefhilmnoprstux\u3040\u3051\u3055\u3059\u30E0\u310E\u312B\u3147\u3162\u3172\u318E\u3206\u3215\u3224\u3229\u3258\u326E\u3272\u3290\u32B0\u32B7\u0180art\u3047\u304A\u304Cr\xF2\u10B3\xF2\u03DDail;\u691Car\xF2\u1C65ar;\u6964\u0380cdenqrt\u3068\u3075\u3078\u307F\u308F\u3094\u30CC\u0100eu\u306D\u3071;\uC000\u223D\u0331te;\u4155i\xE3\u116Emptyv;\u69B3g\u0200;del\u0FD1\u3089\u308B\u308D;\u6992;\u69A5\xE5\u0FD1uo\u803B\xBB\u40BBr\u0580;abcfhlpstw\u0FDC\u30AC\u30AF\u30B7\u30B9\u30BC\u30BE\u30C0\u30C3\u30C7\u30CAp;\u6975\u0100;f\u0FE0\u30B4s;\u6920;\u6933s;\u691E\xEB\u225D\xF0\u272El;\u6945im;\u6974l;\u61A3;\u619D\u0100ai\u30D1\u30D5il;\u691Ao\u0100;n\u30DB\u30DC\u6236al\xF3\u0F1E\u0180abr\u30E7\u30EA\u30EEr\xF2\u17E5rk;\u6773\u0100ak\u30F3\u30FDc\u0100ek\u30F9\u30FB;\u407D;\u405D\u0100es\u3102\u3104;\u698Cl\u0100du\u310A\u310C;\u698E;\u6990\u0200aeuy\u3117\u311C\u3127\u3129ron;\u4159\u0100di\u3121\u3125il;\u4157\xEC\u0FF2\xE2\u30FA;\u4440\u0200clqs\u3134\u3137\u313D\u3144a;\u6937dhar;\u6969uo\u0100;r\u020E\u020Dh;\u61B3\u0180acg\u314E\u315F\u0F44l\u0200;ips\u0F78\u3158\u315B\u109Cn\xE5\u10BBar\xF4\u0FA9t;\u65AD\u0180ilr\u3169\u1023\u316Esht;\u697D;\uC000\u{1D52F}\u0100ao\u3177\u3186r\u0100du\u317D\u317F\xBB\u047B\u0100;l\u1091\u3184;\u696C\u0100;v\u318B\u318C\u43C1;\u43F1\u0180gns\u3195\u31F9\u31FCht\u0300ahlrst\u31A4\u31B0\u31C2\u31D8\u31E4\u31EErrow\u0100;t\u0FDC\u31ADa\xE9\u30C8arpoon\u0100du\u31BB\u31BFow\xEE\u317Ep\xBB\u1092eft\u0100ah\u31CA\u31D0rrow\xF3\u0FEAarpoon\xF3\u0551ightarrows;\u61C9quigarro\xF7\u30CBhreetimes;\u62CCg;\u42DAingdotse\xF1\u1F32\u0180ahm\u320D\u3210\u3213r\xF2\u0FEAa\xF2\u0551;\u600Foust\u0100;a\u321E\u321F\u63B1che\xBB\u321Fmid;\u6AEE\u0200abpt\u3232\u323D\u3240\u3252\u0100nr\u3237\u323Ag;\u67EDr;\u61FEr\xEB\u1003\u0180afl\u3247\u324A\u324Er;\u6986;\uC000\u{1D563}us;\u6A2Eimes;\u6A35\u0100ap\u325D\u3267r\u0100;g\u3263\u3264\u4029t;\u6994olint;\u6A12ar\xF2\u31E3\u0200achq\u327B\u3280\u10BC\u3285quo;\u603Ar;\uC000\u{1D4C7}\u0100bu\u30FB\u328Ao\u0100;r\u0214\u0213\u0180hir\u3297\u329B\u32A0re\xE5\u31F8mes;\u62CAi\u0200;efl\u32AA\u1059\u1821\u32AB\u65B9tri;\u69CEluhar;\u6968;\u611E\u0D61\u32D5\u32DB\u32DF\u332C\u3338\u3371\0\u337A\u33A4\0\0\u33EC\u33F0\0\u3428\u3448\u345A\u34AD\u34B1\u34CA\u34F1\0\u3616\0\0\u3633cute;\u415Bqu\xEF\u27BA\u0500;Eaceinpsy\u11ED\u32F3\u32F5\u32FF\u3302\u330B\u330F\u331F\u3326\u3329;\u6AB4\u01F0\u32FA\0\u32FC;\u6AB8on;\u4161u\xE5\u11FE\u0100;d\u11F3\u3307il;\u415Frc;\u415D\u0180Eas\u3316\u3318\u331B;\u6AB6p;\u6ABAim;\u62E9olint;\u6A13i\xED\u1204;\u4441ot\u0180;be\u3334\u1D47\u3335\u62C5;\u6A66\u0380Aacmstx\u3346\u334A\u3357\u335B\u335E\u3363\u336Drr;\u61D8r\u0100hr\u3350\u3352\xEB\u2228\u0100;o\u0A36\u0A34t\u803B\xA7\u40A7i;\u403Bwar;\u6929m\u0100in\u3369\xF0nu\xF3\xF1t;\u6736r\u0100;o\u3376\u2055\uC000\u{1D530}\u0200acoy\u3382\u3386\u3391\u33A0rp;\u666F\u0100hy\u338B\u338Fcy;\u4449;\u4448rt\u026D\u3399\0\0\u339Ci\xE4\u1464ara\xEC\u2E6F\u803B\xAD\u40AD\u0100gm\u33A8\u33B4ma\u0180;fv\u33B1\u33B2\u33B2\u43C3;\u43C2\u0400;deglnpr\u12AB\u33C5\u33C9\u33CE\u33D6\u33DE\u33E1\u33E6ot;\u6A6A\u0100;q\u12B1\u12B0\u0100;E\u33D3\u33D4\u6A9E;\u6AA0\u0100;E\u33DB\u33DC\u6A9D;\u6A9Fe;\u6246lus;\u6A24arr;\u6972ar\xF2\u113D\u0200aeit\u33F8\u3408\u340F\u3417\u0100ls\u33FD\u3404lsetm\xE9\u336Ahp;\u6A33parsl;\u69E4\u0100dl\u1463\u3414e;\u6323\u0100;e\u341C\u341D\u6AAA\u0100;s\u3422\u3423\u6AAC;\uC000\u2AAC\uFE00\u0180flp\u342E\u3433\u3442tcy;\u444C\u0100;b\u3438\u3439\u402F\u0100;a\u343E\u343F\u69C4r;\u633Ff;\uC000\u{1D564}a\u0100dr\u344D\u0402es\u0100;u\u3454\u3455\u6660it\xBB\u3455\u0180csu\u3460\u3479\u349F\u0100au\u3465\u346Fp\u0100;s\u1188\u346B;\uC000\u2293\uFE00p\u0100;s\u11B4\u3475;\uC000\u2294\uFE00u\u0100bp\u347F\u348F\u0180;es\u1197\u119C\u3486et\u0100;e\u1197\u348D\xF1\u119D\u0180;es\u11A8\u11AD\u3496et\u0100;e\u11A8\u349D\xF1\u11AE\u0180;af\u117B\u34A6\u05B0r\u0165\u34AB\u05B1\xBB\u117Car\xF2\u1148\u0200cemt\u34B9\u34BE\u34C2\u34C5r;\uC000\u{1D4C8}tm\xEE\xF1i\xEC\u3415ar\xE6\u11BE\u0100ar\u34CE\u34D5r\u0100;f\u34D4\u17BF\u6606\u0100an\u34DA\u34EDight\u0100ep\u34E3\u34EApsilo\xEE\u1EE0h\xE9\u2EAFs\xBB\u2852\u0280bcmnp\u34FB\u355E\u1209\u358B\u358E\u0480;Edemnprs\u350E\u350F\u3511\u3515\u351E\u3523\u352C\u3531\u3536\u6282;\u6AC5ot;\u6ABD\u0100;d\u11DA\u351Aot;\u6AC3ult;\u6AC1\u0100Ee\u3528\u352A;\u6ACB;\u628Alus;\u6ABFarr;\u6979\u0180eiu\u353D\u3552\u3555t\u0180;en\u350E\u3545\u354Bq\u0100;q\u11DA\u350Feq\u0100;q\u352B\u3528m;\u6AC7\u0100bp\u355A\u355C;\u6AD5;\u6AD3c\u0300;acens\u11ED\u356C\u3572\u3579\u357B\u3326ppro\xF8\u32FAurlye\xF1\u11FE\xF1\u11F3\u0180aes\u3582\u3588\u331Bppro\xF8\u331Aq\xF1\u3317g;\u666A\u0680123;Edehlmnps\u35A9\u35AC\u35AF\u121C\u35B2\u35B4\u35C0\u35C9\u35D5\u35DA\u35DF\u35E8\u35ED\u803B\xB9\u40B9\u803B\xB2\u40B2\u803B\xB3\u40B3;\u6AC6\u0100os\u35B9\u35BCt;\u6ABEub;\u6AD8\u0100;d\u1222\u35C5ot;\u6AC4s\u0100ou\u35CF\u35D2l;\u67C9b;\u6AD7arr;\u697Bult;\u6AC2\u0100Ee\u35E4\u35E6;\u6ACC;\u628Blus;\u6AC0\u0180eiu\u35F4\u3609\u360Ct\u0180;en\u121C\u35FC\u3602q\u0100;q\u1222\u35B2eq\u0100;q\u35E7\u35E4m;\u6AC8\u0100bp\u3611\u3613;\u6AD4;\u6AD6\u0180Aan\u361C\u3620\u362Drr;\u61D9r\u0100hr\u3626\u3628\xEB\u222E\u0100;o\u0A2B\u0A29war;\u692Alig\u803B\xDF\u40DF\u0BE1\u3651\u365D\u3660\u12CE\u3673\u3679\0\u367E\u36C2\0\0\0\0\0\u36DB\u3703\0\u3709\u376C\0\0\0\u3787\u0272\u3656\0\0\u365Bget;\u6316;\u43C4r\xEB\u0E5F\u0180aey\u3666\u366B\u3670ron;\u4165dil;\u4163;\u4442lrec;\u6315r;\uC000\u{1D531}\u0200eiko\u3686\u369D\u36B5\u36BC\u01F2\u368B\0\u3691e\u01004f\u1284\u1281a\u0180;sv\u3698\u3699\u369B\u43B8ym;\u43D1\u0100cn\u36A2\u36B2k\u0100as\u36A8\u36AEppro\xF8\u12C1im\xBB\u12ACs\xF0\u129E\u0100as\u36BA\u36AE\xF0\u12C1rn\u803B\xFE\u40FE\u01EC\u031F\u36C6\u22E7es\u8180\xD7;bd\u36CF\u36D0\u36D8\u40D7\u0100;a\u190F\u36D5r;\u6A31;\u6A30\u0180eps\u36E1\u36E3\u3700\xE1\u2A4D\u0200;bcf\u0486\u36EC\u36F0\u36F4ot;\u6336ir;\u6AF1\u0100;o\u36F9\u36FC\uC000\u{1D565}rk;\u6ADA\xE1\u3362rime;\u6034\u0180aip\u370F\u3712\u3764d\xE5\u1248\u0380adempst\u3721\u374D\u3740\u3751\u3757\u375C\u375Fngle\u0280;dlqr\u3730\u3731\u3736\u3740\u3742\u65B5own\xBB\u1DBBeft\u0100;e\u2800\u373E\xF1\u092E;\u625Cight\u0100;e\u32AA\u374B\xF1\u105Aot;\u65ECinus;\u6A3Alus;\u6A39b;\u69CDime;\u6A3Bezium;\u63E2\u0180cht\u3772\u377D\u3781\u0100ry\u3777\u377B;\uC000\u{1D4C9};\u4446cy;\u445Brok;\u4167\u0100io\u378B\u378Ex\xF4\u1777head\u0100lr\u3797\u37A0eftarro\xF7\u084Fightarrow\xBB\u0F5D\u0900AHabcdfghlmoprstuw\u37D0\u37D3\u37D7\u37E4\u37F0\u37FC\u380E\u381C\u3823\u3834\u3851\u385D\u386B\u38A9\u38CC\u38D2\u38EA\u38F6r\xF2\u03EDar;\u6963\u0100cr\u37DC\u37E2ute\u803B\xFA\u40FA\xF2\u1150r\u01E3\u37EA\0\u37EDy;\u445Eve;\u416D\u0100iy\u37F5\u37FArc\u803B\xFB\u40FB;\u4443\u0180abh\u3803\u3806\u380Br\xF2\u13ADlac;\u4171a\xF2\u13C3\u0100ir\u3813\u3818sht;\u697E;\uC000\u{1D532}rave\u803B\xF9\u40F9\u0161\u3827\u3831r\u0100lr\u382C\u382E\xBB\u0957\xBB\u1083lk;\u6580\u0100ct\u3839\u384D\u026F\u383F\0\0\u384Arn\u0100;e\u3845\u3846\u631Cr\xBB\u3846op;\u630Fri;\u65F8\u0100al\u3856\u385Acr;\u416B\u80BB\xA8\u0349\u0100gp\u3862\u3866on;\u4173f;\uC000\u{1D566}\u0300adhlsu\u114B\u3878\u387D\u1372\u3891\u38A0own\xE1\u13B3arpoon\u0100lr\u3888\u388Cef\xF4\u382Digh\xF4\u382Fi\u0180;hl\u3899\u389A\u389C\u43C5\xBB\u13FAon\xBB\u389Aparrows;\u61C8\u0180cit\u38B0\u38C4\u38C8\u026F\u38B6\0\0\u38C1rn\u0100;e\u38BC\u38BD\u631Dr\xBB\u38BDop;\u630Eng;\u416Fri;\u65F9cr;\uC000\u{1D4CA}\u0180dir\u38D9\u38DD\u38E2ot;\u62F0lde;\u4169i\u0100;f\u3730\u38E8\xBB\u1813\u0100am\u38EF\u38F2r\xF2\u38A8l\u803B\xFC\u40FCangle;\u69A7\u0780ABDacdeflnoprsz\u391C\u391F\u3929\u392D\u39B5\u39B8\u39BD\u39DF\u39E4\u39E8\u39F3\u39F9\u39FD\u3A01\u3A20r\xF2\u03F7ar\u0100;v\u3926\u3927\u6AE8;\u6AE9as\xE8\u03E1\u0100nr\u3932\u3937grt;\u699C\u0380eknprst\u34E3\u3946\u394B\u3952\u395D\u3964\u3996app\xE1\u2415othin\xE7\u1E96\u0180hir\u34EB\u2EC8\u3959op\xF4\u2FB5\u0100;h\u13B7\u3962\xEF\u318D\u0100iu\u3969\u396Dgm\xE1\u33B3\u0100bp\u3972\u3984setneq\u0100;q\u397D\u3980\uC000\u228A\uFE00;\uC000\u2ACB\uFE00setneq\u0100;q\u398F\u3992\uC000\u228B\uFE00;\uC000\u2ACC\uFE00\u0100hr\u399B\u399Fet\xE1\u369Ciangle\u0100lr\u39AA\u39AFeft\xBB\u0925ight\xBB\u1051y;\u4432ash\xBB\u1036\u0180elr\u39C4\u39D2\u39D7\u0180;be\u2DEA\u39CB\u39CFar;\u62BBq;\u625Alip;\u62EE\u0100bt\u39DC\u1468a\xF2\u1469r;\uC000\u{1D533}tr\xE9\u39AEsu\u0100bp\u39EF\u39F1\xBB\u0D1C\xBB\u0D59pf;\uC000\u{1D567}ro\xF0\u0EFBtr\xE9\u39B4\u0100cu\u3A06\u3A0Br;\uC000\u{1D4CB}\u0100bp\u3A10\u3A18n\u0100Ee\u3980\u3A16\xBB\u397En\u0100Ee\u3992\u3A1E\xBB\u3990igzag;\u699A\u0380cefoprs\u3A36\u3A3B\u3A56\u3A5B\u3A54\u3A61\u3A6Airc;\u4175\u0100di\u3A40\u3A51\u0100bg\u3A45\u3A49ar;\u6A5Fe\u0100;q\u15FA\u3A4F;\u6259erp;\u6118r;\uC000\u{1D534}pf;\uC000\u{1D568}\u0100;e\u1479\u3A66at\xE8\u1479cr;\uC000\u{1D4CC}\u0AE3\u178E\u3A87\0\u3A8B\0\u3A90\u3A9B\0\0\u3A9D\u3AA8\u3AAB\u3AAF\0\0\u3AC3\u3ACE\0\u3AD8\u17DC\u17DFtr\xE9\u17D1r;\uC000\u{1D535}\u0100Aa\u3A94\u3A97r\xF2\u03C3r\xF2\u09F6;\u43BE\u0100Aa\u3AA1\u3AA4r\xF2\u03B8r\xF2\u09EBa\xF0\u2713is;\u62FB\u0180dpt\u17A4\u3AB5\u3ABE\u0100fl\u3ABA\u17A9;\uC000\u{1D569}im\xE5\u17B2\u0100Aa\u3AC7\u3ACAr\xF2\u03CEr\xF2\u0A01\u0100cq\u3AD2\u17B8r;\uC000\u{1D4CD}\u0100pt\u17D6\u3ADCr\xE9\u17D4\u0400acefiosu\u3AF0\u3AFD\u3B08\u3B0C\u3B11\u3B15\u3B1B\u3B21c\u0100uy\u3AF6\u3AFBte\u803B\xFD\u40FD;\u444F\u0100iy\u3B02\u3B06rc;\u4177;\u444Bn\u803B\xA5\u40A5r;\uC000\u{1D536}cy;\u4457pf;\uC000\u{1D56A}cr;\uC000\u{1D4CE}\u0100cm\u3B26\u3B29y;\u444El\u803B\xFF\u40FF\u0500acdefhiosw\u3B42\u3B48\u3B54\u3B58\u3B64\u3B69\u3B6D\u3B74\u3B7A\u3B80cute;\u417A\u0100ay\u3B4D\u3B52ron;\u417E;\u4437ot;\u417C\u0100et\u3B5D\u3B61tr\xE6\u155Fa;\u43B6r;\uC000\u{1D537}cy;\u4436grarr;\u61DDpf;\uC000\u{1D56B}cr;\uC000\u{1D4CF}\u0100jn\u3B85\u3B87;\u600Dj;\u600C'.split("").map(e=>e.charCodeAt(0)));var Qu=new Uint16Array("\u0200aglq \x1B\u026D\0\0p;\u4026os;\u4027t;\u403Et;\u403Cuot;\u4022".split("").map(e=>e.charCodeAt(0)));var di,$0=new Map([[0,65533],[128,8364],[130,8218],[131,402],[132,8222],[133,8230],[134,8224],[135,8225],[136,710],[137,8240],[138,352],[139,8249],[140,338],[142,381],[145,8216],[146,8217],[147,8220],[148,8221],[149,8226],[150,8211],[151,8212],[152,732],[153,8482],[154,353],[155,8250],[156,339],[158,382],[159,376]]),pi=(di=String.fromCodePoint)!==null&&di!==void 0?di:function(e){let t="";return e>65535&&(e-=65536,t+=String.fromCharCode(e>>>10&1023|55296),e=56320|e&1023),t+=String.fromCharCode(e),t};function fi(e){var t;return e>=55296&&e<=57343||e>1114111?65533:(t=$0.get(e))!==null&&t!==void 0?t:e}var Ke;(function(e){e[e.NUM=35]="NUM",e[e.SEMI=59]="SEMI",e[e.EQUALS=61]="EQUALS",e[e.ZERO=48]="ZERO",e[e.NINE=57]="NINE",e[e.LOWER_A=97]="LOWER_A",e[e.LOWER_F=102]="LOWER_F",e[e.LOWER_X=120]="LOWER_X",e[e.LOWER_Z=122]="LOWER_Z",e[e.UPPER_A=65]="UPPER_A",e[e.UPPER_F=70]="UPPER_F",e[e.UPPER_Z=90]="UPPER_Z"})(Ke||(Ke={}));var x0=32,bn;(function(e){e[e.VALUE_LENGTH=49152]="VALUE_LENGTH",e[e.BRANCH_LENGTH=16256]="BRANCH_LENGTH",e[e.JUMP_TABLE=127]="JUMP_TABLE"})(bn||(bn={}));function mi(e){return e>=Ke.ZERO&&e<=Ke.NINE}function S0(e){return e>=Ke.UPPER_A&&e<=Ke.UPPER_F||e>=Ke.LOWER_A&&e<=Ke.LOWER_F}function E0(e){return e>=Ke.UPPER_A&&e<=Ke.UPPER_Z||e>=Ke.LOWER_A&&e<=Ke.LOWER_Z||mi(e)}function T0(e){return e===Ke.EQUALS||E0(e)}var Ve;(function(e){e[e.EntityStart=0]="EntityStart",e[e.NumericStart=1]="NumericStart",e[e.NumericDecimal=2]="NumericDecimal",e[e.NumericHex=3]="NumericHex",e[e.NamedEntity=4]="NamedEntity"})(Ve||(Ve={}));var Ut;(function(e){e[e.Legacy=0]="Legacy",e[e.Strict=1]="Strict",e[e.Attribute=2]="Attribute"})(Ut||(Ut={}));var Ko=class{constructor(t,n,a){this.decodeTree=t,this.emitCodePoint=n,this.errors=a,this.state=Ve.EntityStart,this.consumed=1,this.result=0,this.treeIndex=0,this.excess=1,this.decodeMode=Ut.Strict}startEntity(t){this.decodeMode=t,this.state=Ve.EntityStart,this.result=0,this.treeIndex=0,this.excess=1,this.consumed=1}write(t,n){switch(this.state){case Ve.EntityStart:return t.charCodeAt(n)===Ke.NUM?(this.state=Ve.NumericStart,this.consumed+=1,this.stateNumericStart(t,n+1)):(this.state=Ve.NamedEntity,this.stateNamedEntity(t,n));case Ve.NumericStart:return this.stateNumericStart(t,n);case Ve.NumericDecimal:return this.stateNumericDecimal(t,n);case Ve.NumericHex:return this.stateNumericHex(t,n);case Ve.NamedEntity:return this.stateNamedEntity(t,n)}}stateNumericStart(t,n){return n>=t.length?-1:(t.charCodeAt(n)|x0)===Ke.LOWER_X?(this.state=Ve.NumericHex,this.consumed+=1,this.stateNumericHex(t,n+1)):(this.state=Ve.NumericDecimal,this.stateNumericDecimal(t,n))}addToNumericResult(t,n,a,o){if(n!==a){let i=a-n;this.result=this.result*Math.pow(o,i)+parseInt(t.substr(n,i),o),this.consumed+=i}}stateNumericHex(t,n){let a=n;for(;n<t.length;){let o=t.charCodeAt(n);if(mi(o)||S0(o))n+=1;else return this.addToNumericResult(t,a,n,16),this.emitNumericEntity(o,3)}return this.addToNumericResult(t,a,n,16),-1}stateNumericDecimal(t,n){let a=n;for(;n<t.length;){let o=t.charCodeAt(n);if(mi(o))n+=1;else return this.addToNumericResult(t,a,n,10),this.emitNumericEntity(o,2)}return this.addToNumericResult(t,a,n,10),-1}emitNumericEntity(t,n){var a;if(this.consumed<=n)return(a=this.errors)===null||a===void 0||a.absenceOfDigitsInNumericCharacterReference(this.consumed),0;if(t===Ke.SEMI)this.consumed+=1;else if(this.decodeMode===Ut.Strict)return 0;return this.emitCodePoint(fi(this.result),this.consumed),this.errors&&(t!==Ke.SEMI&&this.errors.missingSemicolonAfterCharacterReference(),this.errors.validateNumericCharacterReference(this.result)),this.consumed}stateNamedEntity(t,n){let{decodeTree:a}=this,o=a[this.treeIndex],i=(o&bn.VALUE_LENGTH)>>14;for(;n<t.length;n++,this.excess++){let r=t.charCodeAt(n);if(this.treeIndex=L0(a,o,this.treeIndex+Math.max(1,i),r),this.treeIndex<0)return this.result===0||this.decodeMode===Ut.Attribute&&(i===0||T0(r))?0:this.emitNotTerminatedNamedEntity();if(o=a[this.treeIndex],i=(o&bn.VALUE_LENGTH)>>14,i!==0){if(r===Ke.SEMI)return this.emitNamedEntityData(this.treeIndex,i,this.consumed+this.excess);this.decodeMode!==Ut.Strict&&(this.result=this.treeIndex,this.consumed+=this.excess,this.excess=0)}}return-1}emitNotTerminatedNamedEntity(){var t;let{result:n,decodeTree:a}=this,o=(a[n]&bn.VALUE_LENGTH)>>14;return this.emitNamedEntityData(n,o,this.consumed),(t=this.errors)===null||t===void 0||t.missingSemicolonAfterCharacterReference(),this.consumed}emitNamedEntityData(t,n,a){let{decodeTree:o}=this;return this.emitCodePoint(n===1?o[t]&~bn.VALUE_LENGTH:o[t+1],a),n===3&&this.emitCodePoint(o[t+2],a),a}end(){var t;switch(this.state){case Ve.NamedEntity:return this.result!==0&&(this.decodeMode!==Ut.Attribute||this.result===this.treeIndex)?this.emitNotTerminatedNamedEntity():0;case Ve.NumericDecimal:return this.emitNumericEntity(0,2);case Ve.NumericHex:return this.emitNumericEntity(0,3);case Ve.NumericStart:return(t=this.errors)===null||t===void 0||t.absenceOfDigitsInNumericCharacterReference(this.consumed),0;case Ve.EntityStart:return 0}}};function Xu(e){let t="",n=new Ko(e,a=>t+=pi(a));return function(o,i){let r=0,u=0;for(;(u=o.indexOf("&",u))>=0;){t+=o.slice(r,u),n.startEntity(i);let p=n.write(o,u+1);if(p<0){r=u+n.end();break}r=u+p,u=p===0?r+1:r}let c=t+o.slice(r);return t="",c}}function L0(e,t,n,a){let o=(t&bn.BRANCH_LENGTH)>>7,i=t&bn.JUMP_TABLE;if(o===0)return i!==0&&a===i?n:-1;if(i){let c=a-i;return c<0||c>=o?-1:e[n+c]-1}let r=n,u=r+o-1;for(;r<=u;){let c=r+u>>>1,p=e[c];if(p<a)r=c+1;else if(p>a)u=c-1;else return e[c+o]}return-1}var C0=Xu(Zu),nv=Xu(Qu);function yn(e,t=Ut.Legacy){return C0(e,t)}function Jo(e){for(let t=1;t<e.length;t++)e[t][0]+=e[t-1][0]+1;return e}var I0=new Map(Jo([[9,"	"],[0,"
"],[22,"!"],[0,"""],[0,"#"],[0,"$"],[0,"%"],[0,"&"],[0,"'"],[0,"("],[0,")"],[0,"*"],[0,"+"],[0,","],[1,"."],[0,"/"],[10,":"],[0,";"],[0,{v:"<",n:8402,o:"<⃒"}],[0,{v:"=",n:8421,o:"=⃥"}],[0,{v:">",n:8402,o:">⃒"}],[0,"?"],[0,"@"],[26,"["],[0,"\"],[0,"]"],[0,"^"],[0,"_"],[0,"`"],[5,{n:106,o:"fj"}],[20,"{"],[0,"|"],[0,"}"],[34," "],[0,"¡"],[0,"¢"],[0,"£"],[0,"¤"],[0,"¥"],[0,"¦"],[0,"§"],[0,"¨"],[0,"©"],[0,"ª"],[0,"«"],[0,"¬"],[0,"­"],[0,"®"],[0,"¯"],[0,"°"],[0,"±"],[0,"²"],[0,"³"],[0,"´"],[0,"µ"],[0,"¶"],[0,"·"],[0,"¸"],[0,"¹"],[0,"º"],[0,"»"],[0,"¼"],[0,"½"],[0,"¾"],[0,"¿"],[0,"À"],[0,"Á"],[0,"Â"],[0,"Ã"],[0,"Ä"],[0,"Å"],[0,"Æ"],[0,"Ç"],[0,"È"],[0,"É"],[0,"Ê"],[0,"Ë"],[0,"Ì"],[0,"Í"],[0,"Î"],[0,"Ï"],[0,"Ð"],[0,"Ñ"],[0,"Ò"],[0,"Ó"],[0,"Ô"],[0,"Õ"],[0,"Ö"],[0,"×"],[0,"Ø"],[0,"Ù"],[0,"Ú"],[0,"Û"],[0,"Ü"],[0,"Ý"],[0,"Þ"],[0,"ß"],[0,"à"],[0,"á"],[0,"â"],[0,"ã"],[0,"ä"],[0,"å"],[0,"æ"],[0,"ç"],[0,"è"],[0,"é"],[0,"ê"],[0,"ë"],[0,"ì"],[0,"í"],[0,"î"],[0,"ï"],[0,"ð"],[0,"ñ"],[0,"ò"],[0,"ó"],[0,"ô"],[0,"õ"],[0,"ö"],[0,"÷"],[0,"ø"],[0,"ù"],[0,"ú"],[0,"û"],[0,"ü"],[0,"ý"],[0,"þ"],[0,"ÿ"],[0,"Ā"],[0,"ā"],[0,"Ă"],[0,"ă"],[0,"Ą"],[0,"ą"],[0,"Ć"],[0,"ć"],[0,"Ĉ"],[0,"ĉ"],[0,"Ċ"],[0,"ċ"],[0,"Č"],[0,"č"],[0,"Ď"],[0,"ď"],[0,"Đ"],[0,"đ"],[0,"Ē"],[0,"ē"],[2,"Ė"],[0,"ė"],[0,"Ę"],[0,"ę"],[0,"Ě"],[0,"ě"],[0,"Ĝ"],[0,"ĝ"],[0,"Ğ"],[0,"ğ"],[0,"Ġ"],[0,"ġ"],[0,"Ģ"],[1,"Ĥ"],[0,"ĥ"],[0,"Ħ"],[0,"ħ"],[0,"Ĩ"],[0,"ĩ"],[0,"Ī"],[0,"ī"],[2,"Į"],[0,"į"],[0,"İ"],[0,"ı"],[0,"IJ"],[0,"ij"],[0,"Ĵ"],[0,"ĵ"],[0,"Ķ"],[0,"ķ"],[0,"ĸ"],[0,"Ĺ"],[0,"ĺ"],[0,"Ļ"],[0,"ļ"],[0,"Ľ"],[0,"ľ"],[0,"Ŀ"],[0,"ŀ"],[0,"Ł"],[0,"ł"],[0,"Ń"],[0,"ń"],[0,"Ņ"],[0,"ņ"],[0,"Ň"],[0,"ň"],[0,"ʼn"],[0,"Ŋ"],[0,"ŋ"],[0,"Ō"],[0,"ō"],[2,"Ő"],[0,"ő"],[0,"Œ"],[0,"œ"],[0,"Ŕ"],[0,"ŕ"],[0,"Ŗ"],[0,"ŗ"],[0,"Ř"],[0,"ř"],[0,"Ś"],[0,"ś"],[0,"Ŝ"],[0,"ŝ"],[0,"Ş"],[0,"ş"],[0,"Š"],[0,"š"],[0,"Ţ"],[0,"ţ"],[0,"Ť"],[0,"ť"],[0,"Ŧ"],[0,"ŧ"],[0,"Ũ"],[0,"ũ"],[0,"Ū"],[0,"ū"],[0,"Ŭ"],[0,"ŭ"],[0,"Ů"],[0,"ů"],[0,"Ű"],[0,"ű"],[0,"Ų"],[0,"ų"],[0,"Ŵ"],[0,"ŵ"],[0,"Ŷ"],[0,"ŷ"],[0,"Ÿ"],[0,"Ź"],[0,"ź"],[0,"Ż"],[0,"ż"],[0,"Ž"],[0,"ž"],[19,"ƒ"],[34,"Ƶ"],[63,"ǵ"],[65,"ȷ"],[142,"ˆ"],[0,"ˇ"],[16,"˘"],[0,"˙"],[0,"˚"],[0,"˛"],[0,"˜"],[0,"˝"],[51,"̑"],[127,"Α"],[0,"Β"],[0,"Γ"],[0,"Δ"],[0,"Ε"],[0,"Ζ"],[0,"Η"],[0,"Θ"],[0,"Ι"],[0,"Κ"],[0,"Λ"],[0,"Μ"],[0,"Ν"],[0,"Ξ"],[0,"Ο"],[0,"Π"],[0,"Ρ"],[1,"Σ"],[0,"Τ"],[0,"Υ"],[0,"Φ"],[0,"Χ"],[0,"Ψ"],[0,"Ω"],[7,"α"],[0,"β"],[0,"γ"],[0,"δ"],[0,"ε"],[0,"ζ"],[0,"η"],[0,"θ"],[0,"ι"],[0,"κ"],[0,"λ"],[0,"μ"],[0,"ν"],[0,"ξ"],[0,"ο"],[0,"π"],[0,"ρ"],[0,"ς"],[0,"σ"],[0,"τ"],[0,"υ"],[0,"φ"],[0,"χ"],[0,"ψ"],[0,"ω"],[7,"ϑ"],[0,"ϒ"],[2,"ϕ"],[0,"ϖ"],[5,"Ϝ"],[0,"ϝ"],[18,"ϰ"],[0,"ϱ"],[3,"ϵ"],[0,"϶"],[10,"Ё"],[0,"Ђ"],[0,"Ѓ"],[0,"Є"],[0,"Ѕ"],[0,"І"],[0,"Ї"],[0,"Ј"],[0,"Љ"],[0,"Њ"],[0,"Ћ"],[0,"Ќ"],[1,"Ў"],[0,"Џ"],[0,"А"],[0,"Б"],[0,"В"],[0,"Г"],[0,"Д"],[0,"Е"],[0,"Ж"],[0,"З"],[0,"И"],[0,"Й"],[0,"К"],[0,"Л"],[0,"М"],[0,"Н"],[0,"О"],[0,"П"],[0,"Р"],[0,"С"],[0,"Т"],[0,"У"],[0,"Ф"],[0,"Х"],[0,"Ц"],[0,"Ч"],[0,"Ш"],[0,"Щ"],[0,"Ъ"],[0,"Ы"],[0,"Ь"],[0,"Э"],[0,"Ю"],[0,"Я"],[0,"а"],[0,"б"],[0,"в"],[0,"г"],[0,"д"],[0,"е"],[0,"ж"],[0,"з"],[0,"и"],[0,"й"],[0,"к"],[0,"л"],[0,"м"],[0,"н"],[0,"о"],[0,"п"],[0,"р"],[0,"с"],[0,"т"],[0,"у"],[0,"ф"],[0,"х"],[0,"ц"],[0,"ч"],[0,"ш"],[0,"щ"],[0,"ъ"],[0,"ы"],[0,"ь"],[0,"э"],[0,"ю"],[0,"я"],[1,"ё"],[0,"ђ"],[0,"ѓ"],[0,"є"],[0,"ѕ"],[0,"і"],[0,"ї"],[0,"ј"],[0,"љ"],[0,"њ"],[0,"ћ"],[0,"ќ"],[1,"ў"],[0,"џ"],[7074," "],[0," "],[0," "],[0," "],[1," "],[0," "],[0," "],[0," "],[0,"​"],[0,"‌"],[0,"‍"],[0,"‎"],[0,"‏"],[0,"‐"],[2,"–"],[0,"—"],[0,"―"],[0,"‖"],[1,"‘"],[0,"’"],[0,"‚"],[1,"“"],[0,"”"],[0,"„"],[1,"†"],[0,"‡"],[0,"•"],[2,"‥"],[0,"…"],[9,"‰"],[0,"‱"],[0,"′"],[0,"″"],[0,"‴"],[0,"‵"],[3,"‹"],[0,"›"],[3,"‾"],[2,"⁁"],[1,"⁃"],[0,"⁄"],[10,"⁏"],[7,"⁗"],[7,{v:" ",n:8202,o:"  "}],[0,"⁠"],[0,"⁡"],[0,"⁢"],[0,"⁣"],[72,"€"],[46,"⃛"],[0,"⃜"],[37,"ℂ"],[2,"℅"],[4,"ℊ"],[0,"ℋ"],[0,"ℌ"],[0,"ℍ"],[0,"ℎ"],[0,"ℏ"],[0,"ℐ"],[0,"ℑ"],[0,"ℒ"],[0,"ℓ"],[1,"ℕ"],[0,"№"],[0,"℗"],[0,"℘"],[0,"ℙ"],[0,"ℚ"],[0,"ℛ"],[0,"ℜ"],[0,"ℝ"],[0,"℞"],[3,"™"],[1,"ℤ"],[2,"℧"],[0,"ℨ"],[0,"℩"],[2,"ℬ"],[0,"ℭ"],[1,"ℯ"],[0,"ℰ"],[0,"ℱ"],[1,"ℳ"],[0,"ℴ"],[0,"ℵ"],[0,"ℶ"],[0,"ℷ"],[0,"ℸ"],[12,"ⅅ"],[0,"ⅆ"],[0,"ⅇ"],[0,"ⅈ"],[10,"⅓"],[0,"⅔"],[0,"⅕"],[0,"⅖"],[0,"⅗"],[0,"⅘"],[0,"⅙"],[0,"⅚"],[0,"⅛"],[0,"⅜"],[0,"⅝"],[0,"⅞"],[49,"←"],[0,"↑"],[0,"→"],[0,"↓"],[0,"↔"],[0,"↕"],[0,"↖"],[0,"↗"],[0,"↘"],[0,"↙"],[0,"↚"],[0,"↛"],[1,{v:"↝",n:824,o:"↝̸"}],[0,"↞"],[0,"↟"],[0,"↠"],[0,"↡"],[0,"↢"],[0,"↣"],[0,"↤"],[0,"↥"],[0,"↦"],[0,"↧"],[1,"↩"],[0,"↪"],[0,"↫"],[0,"↬"],[0,"↭"],[0,"↮"],[1,"↰"],[0,"↱"],[0,"↲"],[0,"↳"],[1,"↵"],[0,"↶"],[0,"↷"],[2,"↺"],[0,"↻"],[0,"↼"],[0,"↽"],[0,"↾"],[0,"↿"],[0,"⇀"],[0,"⇁"],[0,"⇂"],[0,"⇃"],[0,"⇄"],[0,"⇅"],[0,"⇆"],[0,"⇇"],[0,"⇈"],[0,"⇉"],[0,"⇊"],[0,"⇋"],[0,"⇌"],[0,"⇍"],[0,"⇎"],[0,"⇏"],[0,"⇐"],[0,"⇑"],[0,"⇒"],[0,"⇓"],[0,"⇔"],[0,"⇕"],[0,"⇖"],[0,"⇗"],[0,"⇘"],[0,"⇙"],[0,"⇚"],[0,"⇛"],[1,"⇝"],[6,"⇤"],[0,"⇥"],[15,"⇵"],[7,"⇽"],[0,"⇾"],[0,"⇿"],[0,"∀"],[0,"∁"],[0,{v:"∂",n:824,o:"∂̸"}],[0,"∃"],[0,"∄"],[0,"∅"],[1,"∇"],[0,"∈"],[0,"∉"],[1,"∋"],[0,"∌"],[2,"∏"],[0,"∐"],[0,"∑"],[0,"−"],[0,"∓"],[0,"∔"],[1,"∖"],[0,"∗"],[0,"∘"],[1,"√"],[2,"∝"],[0,"∞"],[0,"∟"],[0,{v:"∠",n:8402,o:"∠⃒"}],[0,"∡"],[0,"∢"],[0,"∣"],[0,"∤"],[0,"∥"],[0,"∦"],[0,"∧"],[0,"∨"],[0,{v:"∩",n:65024,o:"∩︀"}],[0,{v:"∪",n:65024,o:"∪︀"}],[0,"∫"],[0,"∬"],[0,"∭"],[0,"∮"],[0,"∯"],[0,"∰"],[0,"∱"],[0,"∲"],[0,"∳"],[0,"∴"],[0,"∵"],[0,"∶"],[0,"∷"],[0,"∸"],[1,"∺"],[0,"∻"],[0,{v:"∼",n:8402,o:"∼⃒"}],[0,{v:"∽",n:817,o:"∽̱"}],[0,{v:"∾",n:819,o:"∾̳"}],[0,"∿"],[0,"≀"],[0,"≁"],[0,{v:"≂",n:824,o:"≂̸"}],[0,"≃"],[0,"≄"],[0,"≅"],[0,"≆"],[0,"≇"],[0,"≈"],[0,"≉"],[0,"≊"],[0,{v:"≋",n:824,o:"≋̸"}],[0,"≌"],[0,{v:"≍",n:8402,o:"≍⃒"}],[0,{v:"≎",n:824,o:"≎̸"}],[0,{v:"≏",n:824,o:"≏̸"}],[0,{v:"≐",n:824,o:"≐̸"}],[0,"≑"],[0,"≒"],[0,"≓"],[0,"≔"],[0,"≕"],[0,"≖"],[0,"≗"],[1,"≙"],[0,"≚"],[1,"≜"],[2,"≟"],[0,"≠"],[0,{v:"≡",n:8421,o:"≡⃥"}],[0,"≢"],[1,{v:"≤",n:8402,o:"≤⃒"}],[0,{v:"≥",n:8402,o:"≥⃒"}],[0,{v:"≦",n:824,o:"≦̸"}],[0,{v:"≧",n:824,o:"≧̸"}],[0,{v:"≨",n:65024,o:"≨︀"}],[0,{v:"≩",n:65024,o:"≩︀"}],[0,{v:"≪",n:new Map(Jo([[824,"≪̸"],[7577,"≪⃒"]]))}],[0,{v:"≫",n:new Map(Jo([[824,"≫̸"],[7577,"≫⃒"]]))}],[0,"≬"],[0,"≭"],[0,"≮"],[0,"≯"],[0,"≰"],[0,"≱"],[0,"≲"],[0,"≳"],[0,"≴"],[0,"≵"],[0,"≶"],[0,"≷"],[0,"≸"],[0,"≹"],[0,"≺"],[0,"≻"],[0,"≼"],[0,"≽"],[0,"≾"],[0,{v:"≿",n:824,o:"≿̸"}],[0,"⊀"],[0,"⊁"],[0,{v:"⊂",n:8402,o:"⊂⃒"}],[0,{v:"⊃",n:8402,o:"⊃⃒"}],[0,"⊄"],[0,"⊅"],[0,"⊆"],[0,"⊇"],[0,"⊈"],[0,"⊉"],[0,{v:"⊊",n:65024,o:"⊊︀"}],[0,{v:"⊋",n:65024,o:"⊋︀"}],[1,"⊍"],[0,"⊎"],[0,{v:"⊏",n:824,o:"⊏̸"}],[0,{v:"⊐",n:824,o:"⊐̸"}],[0,"⊑"],[0,"⊒"],[0,{v:"⊓",n:65024,o:"⊓︀"}],[0,{v:"⊔",n:65024,o:"⊔︀"}],[0,"⊕"],[0,"⊖"],[0,"⊗"],[0,"⊘"],[0,"⊙"],[0,"⊚"],[0,"⊛"],[1,"⊝"],[0,"⊞"],[0,"⊟"],[0,"⊠"],[0,"⊡"],[0,"⊢"],[0,"⊣"],[0,"⊤"],[0,"⊥"],[1,"⊧"],[0,"⊨"],[0,"⊩"],[0,"⊪"],[0,"⊫"],[0,"⊬"],[0,"⊭"],[0,"⊮"],[0,"⊯"],[0,"⊰"],[1,"⊲"],[0,"⊳"],[0,{v:"⊴",n:8402,o:"⊴⃒"}],[0,{v:"⊵",n:8402,o:"⊵⃒"}],[0,"⊶"],[0,"⊷"],[0,"⊸"],[0,"⊹"],[0,"⊺"],[0,"⊻"],[1,"⊽"],[0,"⊾"],[0,"⊿"],[0,"⋀"],[0,"⋁"],[0,"⋂"],[0,"⋃"],[0,"⋄"],[0,"⋅"],[0,"⋆"],[0,"⋇"],[0,"⋈"],[0,"⋉"],[0,"⋊"],[0,"⋋"],[0,"⋌"],[0,"⋍"],[0,"⋎"],[0,"⋏"],[0,"⋐"],[0,"⋑"],[0,"⋒"],[0,"⋓"],[0,"⋔"],[0,"⋕"],[0,"⋖"],[0,"⋗"],[0,{v:"⋘",n:824,o:"⋘̸"}],[0,{v:"⋙",n:824,o:"⋙̸"}],[0,{v:"⋚",n:65024,o:"⋚︀"}],[0,{v:"⋛",n:65024,o:"⋛︀"}],[2,"⋞"],[0,"⋟"],[0,"⋠"],[0,"⋡"],[0,"⋢"],[0,"⋣"],[2,"⋦"],[0,"⋧"],[0,"⋨"],[0,"⋩"],[0,"⋪"],[0,"⋫"],[0,"⋬"],[0,"⋭"],[0,"⋮"],[0,"⋯"],[0,"⋰"],[0,"⋱"],[0,"⋲"],[0,"⋳"],[0,"⋴"],[0,{v:"⋵",n:824,o:"⋵̸"}],[0,"⋶"],[0,"⋷"],[1,{v:"⋹",n:824,o:"⋹̸"}],[0,"⋺"],[0,"⋻"],[0,"⋼"],[0,"⋽"],[0,"⋾"],[6,"⌅"],[0,"⌆"],[1,"⌈"],[0,"⌉"],[0,"⌊"],[0,"⌋"],[0,"⌌"],[0,"⌍"],[0,"⌎"],[0,"⌏"],[0,"⌐"],[1,"⌒"],[0,"⌓"],[1,"⌕"],[0,"⌖"],[5,"⌜"],[0,"⌝"],[0,"⌞"],[0,"⌟"],[2,"⌢"],[0,"⌣"],[9,"⌭"],[0,"⌮"],[7,"⌶"],[6,"⌽"],[1,"⌿"],[60,"⍼"],[51,"⎰"],[0,"⎱"],[2,"⎴"],[0,"⎵"],[0,"⎶"],[37,"⏜"],[0,"⏝"],[0,"⏞"],[0,"⏟"],[2,"⏢"],[4,"⏧"],[59,"␣"],[164,"Ⓢ"],[55,"─"],[1,"│"],[9,"┌"],[3,"┐"],[3,"└"],[3,"┘"],[3,"├"],[7,"┤"],[7,"┬"],[7,"┴"],[7,"┼"],[19,"═"],[0,"║"],[0,"╒"],[0,"╓"],[0,"╔"],[0,"╕"],[0,"╖"],[0,"╗"],[0,"╘"],[0,"╙"],[0,"╚"],[0,"╛"],[0,"╜"],[0,"╝"],[0,"╞"],[0,"╟"],[0,"╠"],[0,"╡"],[0,"╢"],[0,"╣"],[0,"╤"],[0,"╥"],[0,"╦"],[0,"╧"],[0,"╨"],[0,"╩"],[0,"╪"],[0,"╫"],[0,"╬"],[19,"▀"],[3,"▄"],[3,"█"],[8,"░"],[0,"▒"],[0,"▓"],[13,"□"],[8,"▪"],[0,"▫"],[1,"▭"],[0,"▮"],[2,"▱"],[1,"△"],[0,"▴"],[0,"▵"],[2,"▸"],[0,"▹"],[3,"▽"],[0,"▾"],[0,"▿"],[2,"◂"],[0,"◃"],[6,"◊"],[0,"○"],[32,"◬"],[2,"◯"],[8,"◸"],[0,"◹"],[0,"◺"],[0,"◻"],[0,"◼"],[8,"★"],[0,"☆"],[7,"☎"],[49,"♀"],[1,"♂"],[29,"♠"],[2,"♣"],[1,"♥"],[0,"♦"],[3,"♪"],[2,"♭"],[0,"♮"],[0,"♯"],[163,"✓"],[3,"✗"],[8,"✠"],[21,"✶"],[33,"❘"],[25,"❲"],[0,"❳"],[84,"⟈"],[0,"⟉"],[28,"⟦"],[0,"⟧"],[0,"⟨"],[0,"⟩"],[0,"⟪"],[0,"⟫"],[0,"⟬"],[0,"⟭"],[7,"⟵"],[0,"⟶"],[0,"⟷"],[0,"⟸"],[0,"⟹"],[0,"⟺"],[1,"⟼"],[2,"⟿"],[258,"⤂"],[0,"⤃"],[0,"⤄"],[0,"⤅"],[6,"⤌"],[0,"⤍"],[0,"⤎"],[0,"⤏"],[0,"⤐"],[0,"⤑"],[0,"⤒"],[0,"⤓"],[2,"⤖"],[2,"⤙"],[0,"⤚"],[0,"⤛"],[0,"⤜"],[0,"⤝"],[0,"⤞"],[0,"⤟"],[0,"⤠"],[2,"⤣"],[0,"⤤"],[0,"⤥"],[0,"⤦"],[0,"⤧"],[0,"⤨"],[0,"⤩"],[0,"⤪"],[8,{v:"⤳",n:824,o:"⤳̸"}],[1,"⤵"],[0,"⤶"],[0,"⤷"],[0,"⤸"],[0,"⤹"],[2,"⤼"],[0,"⤽"],[7,"⥅"],[2,"⥈"],[0,"⥉"],[0,"⥊"],[0,"⥋"],[2,"⥎"],[0,"⥏"],[0,"⥐"],[0,"⥑"],[0,"⥒"],[0,"⥓"],[0,"⥔"],[0,"⥕"],[0,"⥖"],[0,"⥗"],[0,"⥘"],[0,"⥙"],[0,"⥚"],[0,"⥛"],[0,"⥜"],[0,"⥝"],[0,"⥞"],[0,"⥟"],[0,"⥠"],[0,"⥡"],[0,"⥢"],[0,"⥣"],[0,"⥤"],[0,"⥥"],[0,"⥦"],[0,"⥧"],[0,"⥨"],[0,"⥩"],[0,"⥪"],[0,"⥫"],[0,"⥬"],[0,"⥭"],[0,"⥮"],[0,"⥯"],[0,"⥰"],[0,"⥱"],[0,"⥲"],[0,"⥳"],[0,"⥴"],[0,"⥵"],[0,"⥶"],[1,"⥸"],[0,"⥹"],[1,"⥻"],[0,"⥼"],[0,"⥽"],[0,"⥾"],[0,"⥿"],[5,"⦅"],[0,"⦆"],[4,"⦋"],[0,"⦌"],[0,"⦍"],[0,"⦎"],[0,"⦏"],[0,"⦐"],[0,"⦑"],[0,"⦒"],[0,"⦓"],[0,"⦔"],[0,"⦕"],[0,"⦖"],[3,"⦚"],[1,"⦜"],[0,"⦝"],[6,"⦤"],[0,"⦥"],[0,"⦦"],[0,"⦧"],[0,"⦨"],[0,"⦩"],[0,"⦪"],[0,"⦫"],[0,"⦬"],[0,"⦭"],[0,"⦮"],[0,"⦯"],[0,"⦰"],[0,"⦱"],[0,"⦲"],[0,"⦳"],[0,"⦴"],[0,"⦵"],[0,"⦶"],[0,"⦷"],[1,"⦹"],[1,"⦻"],[0,"⦼"],[1,"⦾"],[0,"⦿"],[0,"⧀"],[0,"⧁"],[0,"⧂"],[0,"⧃"],[0,"⧄"],[0,"⧅"],[3,"⧉"],[3,"⧍"],[0,"⧎"],[0,{v:"⧏",n:824,o:"⧏̸"}],[0,{v:"⧐",n:824,o:"⧐̸"}],[11,"⧜"],[0,"⧝"],[0,"⧞"],[4,"⧣"],[0,"⧤"],[0,"⧥"],[5,"⧫"],[8,"⧴"],[1,"⧶"],[9,"⨀"],[0,"⨁"],[0,"⨂"],[1,"⨄"],[1,"⨆"],[5,"⨌"],[0,"⨍"],[2,"⨐"],[0,"⨑"],[0,"⨒"],[0,"⨓"],[0,"⨔"],[0,"⨕"],[0,"⨖"],[0,"⨗"],[10,"⨢"],[0,"⨣"],[0,"⨤"],[0,"⨥"],[0,"⨦"],[0,"⨧"],[1,"⨩"],[0,"⨪"],[2,"⨭"],[0,"⨮"],[0,"⨯"],[0,"⨰"],[0,"⨱"],[1,"⨳"],[0,"⨴"],[0,"⨵"],[0,"⨶"],[0,"⨷"],[0,"⨸"],[0,"⨹"],[0,"⨺"],[0,"⨻"],[0,"⨼"],[2,"⨿"],[0,"⩀"],[1,"⩂"],[0,"⩃"],[0,"⩄"],[0,"⩅"],[0,"⩆"],[0,"⩇"],[0,"⩈"],[0,"⩉"],[0,"⩊"],[0,"⩋"],[0,"⩌"],[0,"⩍"],[2,"⩐"],[2,"⩓"],[0,"⩔"],[0,"⩕"],[0,"⩖"],[0,"⩗"],[0,"⩘"],[1,"⩚"],[0,"⩛"],[0,"⩜"],[0,"⩝"],[1,"⩟"],[6,"⩦"],[3,"⩪"],[2,{v:"⩭",n:824,o:"⩭̸"}],[0,"⩮"],[0,"⩯"],[0,{v:"⩰",n:824,o:"⩰̸"}],[0,"⩱"],[0,"⩲"],[0,"⩳"],[0,"⩴"],[0,"⩵"],[1,"⩷"],[0,"⩸"],[0,"⩹"],[0,"⩺"],[0,"⩻"],[0,"⩼"],[0,{v:"⩽",n:824,o:"⩽̸"}],[0,{v:"⩾",n:824,o:"⩾̸"}],[0,"⩿"],[0,"⪀"],[0,"⪁"],[0,"⪂"],[0,"⪃"],[0,"⪄"],[0,"⪅"],[0,"⪆"],[0,"⪇"],[0,"⪈"],[0,"⪉"],[0,"⪊"],[0,"⪋"],[0,"⪌"],[0,"⪍"],[0,"⪎"],[0,"⪏"],[0,"⪐"],[0,"⪑"],[0,"⪒"],[0,"⪓"],[0,"⪔"],[0,"⪕"],[0,"⪖"],[0,"⪗"],[0,"⪘"],[0,"⪙"],[0,"⪚"],[2,"⪝"],[0,"⪞"],[0,"⪟"],[0,"⪠"],[0,{v:"⪡",n:824,o:"⪡̸"}],[0,{v:"⪢",n:824,o:"⪢̸"}],[1,"⪤"],[0,"⪥"],[0,"⪦"],[0,"⪧"],[0,"⪨"],[0,"⪩"],[0,"⪪"],[0,"⪫"],[0,{v:"⪬",n:65024,o:"⪬︀"}],[0,{v:"⪭",n:65024,o:"⪭︀"}],[0,"⪮"],[0,{v:"⪯",n:824,o:"⪯̸"}],[0,{v:"⪰",n:824,o:"⪰̸"}],[2,"⪳"],[0,"⪴"],[0,"⪵"],[0,"⪶"],[0,"⪷"],[0,"⪸"],[0,"⪹"],[0,"⪺"],[0,"⪻"],[0,"⪼"],[0,"⪽"],[0,"⪾"],[0,"⪿"],[0,"⫀"],[0,"⫁"],[0,"⫂"],[0,"⫃"],[0,"⫄"],[0,{v:"⫅",n:824,o:"⫅̸"}],[0,{v:"⫆",n:824,o:"⫆̸"}],[0,"⫇"],[0,"⫈"],[2,{v:"⫋",n:65024,o:"⫋︀"}],[0,{v:"⫌",n:65024,o:"⫌︀"}],[2,"⫏"],[0,"⫐"],[0,"⫑"],[0,"⫒"],[0,"⫓"],[0,"⫔"],[0,"⫕"],[0,"⫖"],[0,"⫗"],[0,"⫘"],[0,"⫙"],[0,"⫚"],[0,"⫛"],[8,"⫤"],[1,"⫦"],[0,"⫧"],[0,"⫨"],[0,"⫩"],[1,"⫫"],[0,"⫬"],[0,"⫭"],[0,"⫮"],[0,"⫯"],[0,"⫰"],[0,"⫱"],[0,"⫲"],[0,"⫳"],[9,{v:"⫽",n:8421,o:"⫽⃥"}],[44343,{n:new Map(Jo([[56476,"𝒜"],[1,"𝒞"],[0,"𝒟"],[2,"𝒢"],[2,"𝒥"],[0,"𝒦"],[2,"𝒩"],[0,"𝒪"],[0,"𝒫"],[0,"𝒬"],[1,"𝒮"],[0,"𝒯"],[0,"𝒰"],[0,"𝒱"],[0,"𝒲"],[0,"𝒳"],[0,"𝒴"],[0,"𝒵"],[0,"𝒶"],[0,"𝒷"],[0,"𝒸"],[0,"𝒹"],[1,"𝒻"],[1,"𝒽"],[0,"𝒾"],[0,"𝒿"],[0,"𝓀"],[0,"𝓁"],[0,"𝓂"],[0,"𝓃"],[1,"𝓅"],[0,"𝓆"],[0,"𝓇"],[0,"𝓈"],[0,"𝓉"],[0,"𝓊"],[0,"𝓋"],[0,"𝓌"],[0,"𝓍"],[0,"𝓎"],[0,"𝓏"],[52,"𝔄"],[0,"𝔅"],[1,"𝔇"],[0,"𝔈"],[0,"𝔉"],[0,"𝔊"],[2,"𝔍"],[0,"𝔎"],[0,"𝔏"],[0,"𝔐"],[0,"𝔑"],[0,"𝔒"],[0,"𝔓"],[0,"𝔔"],[1,"𝔖"],[0,"𝔗"],[0,"𝔘"],[0,"𝔙"],[0,"𝔚"],[0,"𝔛"],[0,"𝔜"],[1,"𝔞"],[0,"𝔟"],[0,"𝔠"],[0,"𝔡"],[0,"𝔢"],[0,"𝔣"],[0,"𝔤"],[0,"𝔥"],[0,"𝔦"],[0,"𝔧"],[0,"𝔨"],[0,"𝔩"],[0,"𝔪"],[0,"𝔫"],[0,"𝔬"],[0,"𝔭"],[0,"𝔮"],[0,"𝔯"],[0,"𝔰"],[0,"𝔱"],[0,"𝔲"],[0,"𝔳"],[0,"𝔴"],[0,"𝔵"],[0,"𝔶"],[0,"𝔷"],[0,"𝔸"],[0,"𝔹"],[1,"𝔻"],[0,"𝔼"],[0,"𝔽"],[0,"𝔾"],[1,"𝕀"],[0,"𝕁"],[0,"𝕂"],[0,"𝕃"],[0,"𝕄"],[1,"𝕆"],[3,"𝕊"],[0,"𝕋"],[0,"𝕌"],[0,"𝕍"],[0,"𝕎"],[0,"𝕏"],[0,"𝕐"],[1,"𝕒"],[0,"𝕓"],[0,"𝕔"],[0,"𝕕"],[0,"𝕖"],[0,"𝕗"],[0,"𝕘"],[0,"𝕙"],[0,"𝕚"],[0,"𝕛"],[0,"𝕜"],[0,"𝕝"],[0,"𝕞"],[0,"𝕟"],[0,"𝕠"],[0,"𝕡"],[0,"𝕢"],[0,"𝕣"],[0,"𝕤"],[0,"𝕥"],[0,"𝕦"],[0,"𝕧"],[0,"𝕨"],[0,"𝕩"],[0,"𝕪"],[0,"𝕫"]]))}],[8906,"ff"],[0,"fi"],[0,"fl"],[0,"ffi"],[0,"ffl"]]));var M0=new Map([[34,"""],[38,"&"],[39,"'"],[60,"<"],[62,">"]]),A0=String.prototype.codePointAt!=null?(e,t)=>e.codePointAt(t):(e,t)=>(e.charCodeAt(t)&64512)===55296?(e.charCodeAt(t)-55296)*1024+e.charCodeAt(t+1)-56320+65536:e.charCodeAt(t);function hi(e,t){return function(a){let o,i=0,r="";for(;o=e.exec(a);)i!==o.index&&(r+=a.substring(i,o.index)),r+=t.get(o[0].charCodeAt(0)),i=o.index+1;return r+a.substring(i)}}var ec=hi(/[&<>'"]/g,M0),tc=hi(/["&\u00A0]/g,new Map([[34,"""],[38,"&"],[160," "]])),nc=hi(/[&<>\u00A0]/g,new Map([[38,"&"],[60,"<"],[62,">"],[160," "]]));var sc;(function(e){e[e.XML=0]="XML",e[e.HTML=1]="HTML"})(sc||(sc={}));var oc;(function(e){e[e.UTF8=0]="UTF8",e[e.ASCII=1]="ASCII",e[e.Extensive=2]="Extensive",e[e.Attribute=3]="Attribute",e[e.Text=4]="Text"})(oc||(oc={}));function _0(e){return Object.prototype.toString.call(e)}function Yo(e){return _0(e)==="[object String]"}var R0=Object.prototype.hasOwnProperty;function P0(e,t){return R0.call(e,t)}function ps(e){return Array.prototype.slice.call(arguments,1).forEach(function(n){if(n){if(typeof n!="object")throw new TypeError(n+"must be object");Object.keys(n).forEach(function(a){e[a]=n[a]})}}),e}function bi(e,t,n){return[].concat(e.slice(0,t),n,e.slice(t+1))}function Zo(e){return!(e>=55296&&e<=57343||e>=64976&&e<=65007||(e&65535)===65535||(e&65535)===65534||e>=0&&e<=8||e===11||e>=14&&e<=31||e>=127&&e<=159||e>1114111)}function Ws(e){if(e>65535){e-=65536;let t=55296+(e>>10),n=56320+(e&1023);return String.fromCharCode(t,n)}return String.fromCharCode(e)}var rc=/\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g,B0=/&([a-z#][a-z0-9]{1,31});/gi,O0=new RegExp(rc.source+"|"+B0.source,"gi"),F0=/^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i;function N0(e,t){if(t.charCodeAt(0)===35&&F0.test(t)){let a=t[1].toLowerCase()==="x"?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return Zo(a)?Ws(a):e}let n=yn(e);return n!==e?n:e}function q0(e){return e.indexOf("\\")<0?e:e.replace(rc,"$1")}function Xt(e){return e.indexOf("\\")<0&&e.indexOf("&")<0?e:e.replace(O0,function(t,n,a){return n||N0(t,a)})}var j0=/[&<>"]/,U0=/[&<>"]/g,z0={"&":"&","<":"<",">":">",'"':"""};function G0(e){return z0[e]}function en(e){return j0.test(e)?e.replace(U0,G0):e}var W0=/[.?*+^$[\]\\(){}|-]/g;function V0(e){return e.replace(W0,"\\$&")}function we(e){switch(e){case 9:case 32:return!0}return!1}function Pn(e){if(e>=8192&&e<=8202)return!0;switch(e){case 9:case 10:case 11:case 12:case 13:case 32:case 160:case 5760:case 8239:case 8287:case 12288:return!0}return!1}function Bn(e){return ds.test(e)||Wo.test(e)}function On(e){switch(e){case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:case 47:case 58:case 59:case 60:case 61:case 62:case 63:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 124:case 125:case 126:return!0;default:return!1}}function Fn(e){return e=e.trim().replace(/\s+/g," "),"\u1E9E".toLowerCase()==="\u1E7E"&&(e=e.replace(/ẞ/g,"\xDF")),e.toLowerCase().toUpperCase()}var K0={mdurl:Uo,ucmicro:ci};var $i={};no($i,{parseLinkDestination:()=>wi,parseLinkLabel:()=>vi,parseLinkTitle:()=>ki});function vi(e,t,n){let a,o,i,r,u=e.posMax,c=e.pos;for(e.pos=t+1,a=1;e.pos<u;){if(i=e.src.charCodeAt(e.pos),i===93&&(a--,a===0)){o=!0;break}if(r=e.pos,e.md.inline.skipToken(e),i===91){if(r===e.pos-1)a++;else if(n)return e.pos=c,-1}}let p=-1;return o&&(p=e.pos),e.pos=c,p}function wi(e,t,n){let a,o=t,i={ok:!1,pos:0,str:""};if(e.charCodeAt(o)===60){for(o++;o<n;){if(a=e.charCodeAt(o),a===10||a===60)return i;if(a===62)return i.pos=o+1,i.str=Xt(e.slice(t+1,o)),i.ok=!0,i;if(a===92&&o+1<n){o+=2;continue}o++}return i}let r=0;for(;o<n&&(a=e.charCodeAt(o),!(a===32||a<32||a===127));){if(a===92&&o+1<n){if(e.charCodeAt(o+1)===32)break;o+=2;continue}if(a===40&&(r++,r>32))return i;if(a===41){if(r===0)break;r--}o++}return t===o||r!==0||(i.str=Xt(e.slice(t,o)),i.pos=o,i.ok=!0),i}function ki(e,t,n,a){let o,i=t,r={ok:!1,can_continue:!1,pos:0,str:"",marker:0};if(a)r.str=a.str,r.marker=a.marker;else{if(i>=n)return r;let u=e.charCodeAt(i);if(u!==34&&u!==39&&u!==40)return r;t++,i++,u===40&&(u=41),r.marker=u}for(;i<n;){if(o=e.charCodeAt(i),o===r.marker)return r.pos=i+1,r.str+=Xt(e.slice(t,i)),r.ok=!0,r;if(o===40&&r.marker===41)return r;o===92&&i+1<n&&i++,i++}return r.can_continue=!0,r.str+=Xt(e.slice(t,i)),r}var zt={};zt.code_inline=function(e,t,n,a,o){let i=e[t];return"<code"+o.renderAttrs(i)+">"+en(i.content)+"</code>"};zt.code_block=function(e,t,n,a,o){let i=e[t];return"<pre"+o.renderAttrs(i)+"><code>"+en(e[t].content)+`</code></pre>
|
|
2158
|
-
`};zt.fence=function(e,t,n,a,o){let i=e[t],r=i.info?Xt(i.info).trim():"",u="",c="";if(r){let f=r.split(/(\s+)/g);u=f[0],c=f.slice(2).join("")}let p;if(n.highlight?p=n.highlight(i.content,u,c)||en(i.content):p=en(i.content),p.indexOf("<pre")===0)return p+`
|
|
2159
|
-
`;if(r){let f=i.attrIndex("class"),h=i.attrs?i.attrs.slice():[];f<0?h.push(["class",n.langPrefix+u]):(h[f]=h[f].slice(),h[f][1]+=" "+n.langPrefix+u);let y={attrs:h};return`<pre><code${o.renderAttrs(y)}>${p}</code></pre>
|
|
2160
|
-
`}return`<pre><code${o.renderAttrs(i)}>${p}</code></pre>
|
|
2161
|
-
`};zt.image=function(e,t,n,a,o){let i=e[t];return i.attrs[i.attrIndex("alt")][1]=o.renderInlineAsText(i.children,n,a),o.renderToken(e,t,n)};zt.hardbreak=function(e,t,n){return n.xhtmlOut?`<br />
|
|
2162
|
-
`:`<br>
|
|
2163
|
-
`};zt.softbreak=function(e,t,n){return n.breaks?n.xhtmlOut?`<br />
|
|
2164
|
-
`:`<br>
|
|
2165
|
-
`:`
|
|
2166
|
-
`};zt.text=function(e,t){return en(e[t].content)};zt.html_block=function(e,t){return e[t].content};zt.html_inline=function(e,t){return e[t].content};function fs(){this.rules=ps({},zt)}fs.prototype.renderAttrs=function(t){let n,a,o;if(!t.attrs)return"";for(o="",n=0,a=t.attrs.length;n<a;n++)o+=" "+en(t.attrs[n][0])+'="'+en(t.attrs[n][1])+'"';return o};fs.prototype.renderToken=function(t,n,a){let o=t[n],i="";if(o.hidden)return"";o.block&&o.nesting!==-1&&n&&t[n-1].hidden&&(i+=`
|
|
2167
|
-
`),i+=(o.nesting===-1?"</":"<")+o.tag,i+=this.renderAttrs(o),o.nesting===0&&a.xhtmlOut&&(i+=" /");let r=!1;if(o.block&&(r=!0,o.nesting===1&&n+1<t.length)){let u=t[n+1];(u.type==="inline"||u.hidden||u.nesting===-1&&u.tag===o.tag)&&(r=!1)}return i+=r?`>
|
|
2168
|
-
`:">",i};fs.prototype.renderInline=function(e,t,n){let a="",o=this.rules;for(let i=0,r=e.length;i<r;i++){let u=e[i].type;typeof o[u]<"u"?a+=o[u](e,i,t,n,this):a+=this.renderToken(e,i,t)}return a};fs.prototype.renderInlineAsText=function(e,t,n){let a="";for(let o=0,i=e.length;o<i;o++)switch(e[o].type){case"text":a+=e[o].content;break;case"image":a+=this.renderInlineAsText(e[o].children,t,n);break;case"html_inline":case"html_block":a+=e[o].content;break;case"softbreak":case"hardbreak":a+=`
|
|
2169
|
-
`;break;default:}return a};fs.prototype.render=function(e,t,n){let a="",o=this.rules;for(let i=0,r=e.length;i<r;i++){let u=e[i].type;u==="inline"?a+=this.renderInline(e[i].children,t,n):typeof o[u]<"u"?a+=o[u](e,i,t,n,this):a+=this.renderToken(e,i,t,n)}return a};var lc=fs;function Mt(){this.__rules__=[],this.__cache__=null}Mt.prototype.__find__=function(e){for(let t=0;t<this.__rules__.length;t++)if(this.__rules__[t].name===e)return t;return-1};Mt.prototype.__compile__=function(){let e=this,t=[""];e.__rules__.forEach(function(n){n.enabled&&n.alt.forEach(function(a){t.indexOf(a)<0&&t.push(a)})}),e.__cache__={},t.forEach(function(n){e.__cache__[n]=[],e.__rules__.forEach(function(a){a.enabled&&(n&&a.alt.indexOf(n)<0||e.__cache__[n].push(a.fn))})})};Mt.prototype.at=function(e,t,n){let a=this.__find__(e),o=n||{};if(a===-1)throw new Error("Parser rule not found: "+e);this.__rules__[a].fn=t,this.__rules__[a].alt=o.alt||[],this.__cache__=null};Mt.prototype.before=function(e,t,n,a){let o=this.__find__(e),i=a||{};if(o===-1)throw new Error("Parser rule not found: "+e);this.__rules__.splice(o,0,{name:t,enabled:!0,fn:n,alt:i.alt||[]}),this.__cache__=null};Mt.prototype.after=function(e,t,n,a){let o=this.__find__(e),i=a||{};if(o===-1)throw new Error("Parser rule not found: "+e);this.__rules__.splice(o+1,0,{name:t,enabled:!0,fn:n,alt:i.alt||[]}),this.__cache__=null};Mt.prototype.push=function(e,t,n){let a=n||{};this.__rules__.push({name:e,enabled:!0,fn:t,alt:a.alt||[]}),this.__cache__=null};Mt.prototype.enable=function(e,t){Array.isArray(e)||(e=[e]);let n=[];return e.forEach(function(a){let o=this.__find__(a);if(o<0){if(t)return;throw new Error("Rules manager: invalid rule name "+a)}this.__rules__[o].enabled=!0,n.push(a)},this),this.__cache__=null,n};Mt.prototype.enableOnly=function(e,t){Array.isArray(e)||(e=[e]),this.__rules__.forEach(function(n){n.enabled=!1}),this.enable(e,t)};Mt.prototype.disable=function(e,t){Array.isArray(e)||(e=[e]);let n=[];return e.forEach(function(a){let o=this.__find__(a);if(o<0){if(t)return;throw new Error("Rules manager: invalid rule name "+a)}this.__rules__[o].enabled=!1,n.push(a)},this),this.__cache__=null,n};Mt.prototype.getRules=function(e){return this.__cache__===null&&this.__compile__(),this.__cache__[e]||[]};var Nn=Mt;function ms(e,t,n){this.type=e,this.tag=t,this.attrs=null,this.map=null,this.nesting=n,this.level=0,this.children=null,this.content="",this.markup="",this.info="",this.meta=null,this.block=!1,this.hidden=!1}ms.prototype.attrIndex=function(t){if(!this.attrs)return-1;let n=this.attrs;for(let a=0,o=n.length;a<o;a++)if(n[a][0]===t)return a;return-1};ms.prototype.attrPush=function(t){this.attrs?this.attrs.push(t):this.attrs=[t]};ms.prototype.attrSet=function(t,n){let a=this.attrIndex(t),o=[t,n];a<0?this.attrPush(o):this.attrs[a]=o};ms.prototype.attrGet=function(t){let n=this.attrIndex(t),a=null;return n>=0&&(a=this.attrs[n][1]),a};ms.prototype.attrJoin=function(t,n){let a=this.attrIndex(t);a<0?this.attrPush([t,n]):this.attrs[a][1]=this.attrs[a][1]+" "+n};var tn=ms;function uc(e,t,n){this.src=e,this.env=n,this.tokens=[],this.inlineMode=!1,this.md=t}uc.prototype.Token=tn;var cc=uc;var J0=/\r\n?|\n/g,Y0=/\0/g;function xi(e){let t;t=e.src.replace(J0,`
|
|
2170
|
-
`),t=t.replace(Y0,"\uFFFD"),e.src=t}function Si(e){let t;e.inlineMode?(t=new e.Token("inline","",0),t.content=e.src,t.map=[0,1],t.children=[],e.tokens.push(t)):e.md.block.parse(e.src,e.md,e.env,e.tokens)}function Ei(e){let t=e.tokens;for(let n=0,a=t.length;n<a;n++){let o=t[n];o.type==="inline"&&e.md.inline.parse(o.content,e.md,e.env,o.children)}}function Z0(e){return/^<a[>\s]/i.test(e)}function Q0(e){return/^<\/a\s*>/i.test(e)}function Ti(e){let t=e.tokens;if(e.md.options.linkify)for(let n=0,a=t.length;n<a;n++){if(t[n].type!=="inline"||!e.md.linkify.pretest(t[n].content))continue;let o=t[n].children,i=0;for(let r=o.length-1;r>=0;r--){let u=o[r];if(u.type==="link_close"){for(r--;o[r].level!==u.level&&o[r].type!=="link_open";)r--;continue}if(u.type==="html_inline"&&(Z0(u.content)&&i>0&&i--,Q0(u.content)&&i++),!(i>0)&&u.type==="text"&&e.md.linkify.test(u.content)){let c=u.content,p=e.md.linkify.match(c),f=[],h=u.level,y=0;p.length>0&&p[0].index===0&&r>0&&o[r-1].type==="text_special"&&(p=p.slice(1));for(let g=0;g<p.length;g++){let v=p[g].url,M=e.md.normalizeLink(v);if(!e.md.validateLink(M))continue;let $=p[g].text;p[g].schema?p[g].schema==="mailto:"&&!/^mailto:/i.test($)?$=e.md.normalizeLinkText("mailto:"+$).replace(/^mailto:/,""):$=e.md.normalizeLinkText($):$=e.md.normalizeLinkText("http://"+$).replace(/^http:\/\//,"");let L=p[g].index;if(L>y){let q=new e.Token("text","",0);q.content=c.slice(y,L),q.level=h,f.push(q)}let C=new e.Token("link_open","a",1);C.attrs=[["href",M]],C.level=h++,C.markup="linkify",C.info="auto",f.push(C);let P=new e.Token("text","",0);P.content=$,P.level=h,f.push(P);let H=new e.Token("link_close","a",-1);H.level=--h,H.markup="linkify",H.info="auto",f.push(H),y=p[g].lastIndex}if(y<c.length){let g=new e.Token("text","",0);g.content=c.slice(y),g.level=h,f.push(g)}t[n].children=o=bi(o,r,f)}}}}var dc=/\+-|\.\.|\?\?\?\?|!!!!|,,|--/,X0=/\((c|tm|r)\)/i,eh=/\((c|tm|r)\)/ig,th={c:"\xA9",r:"\xAE",tm:"\u2122"};function nh(e,t){return th[t.toLowerCase()]}function sh(e){let t=0;for(let n=e.length-1;n>=0;n--){let a=e[n];a.type==="text"&&!t&&(a.content=a.content.replace(eh,nh)),a.type==="link_open"&&a.info==="auto"&&t--,a.type==="link_close"&&a.info==="auto"&&t++}}function oh(e){let t=0;for(let n=e.length-1;n>=0;n--){let a=e[n];a.type==="text"&&!t&&dc.test(a.content)&&(a.content=a.content.replace(/\+-/g,"\xB1").replace(/\.{2,}/g,"\u2026").replace(/([?!])…/g,"$1..").replace(/([?!]){4,}/g,"$1$1$1").replace(/,{2,}/g,",").replace(/(^|[^-])---(?=[^-]|$)/mg,"$1\u2014").replace(/(^|\s)--(?=\s|$)/mg,"$1\u2013").replace(/(^|[^-\s])--(?=[^-\s]|$)/mg,"$1\u2013")),a.type==="link_open"&&a.info==="auto"&&t--,a.type==="link_close"&&a.info==="auto"&&t++}}function Li(e){let t;if(e.md.options.typographer)for(t=e.tokens.length-1;t>=0;t--)e.tokens[t].type==="inline"&&(X0.test(e.tokens[t].content)&&sh(e.tokens[t].children),dc.test(e.tokens[t].content)&&oh(e.tokens[t].children))}var ah=/['"]/,pc=/['"]/g,fc="\u2019";function Qo(e,t,n){return e.slice(0,t)+n+e.slice(t+1)}function ih(e,t){let n,a=[];for(let o=0;o<e.length;o++){let i=e[o],r=e[o].level;for(n=a.length-1;n>=0&&!(a[n].level<=r);n--);if(a.length=n+1,i.type!=="text")continue;let u=i.content,c=0,p=u.length;e:for(;c<p;){pc.lastIndex=c;let f=pc.exec(u);if(!f)break;let h=!0,y=!0;c=f.index+1;let g=f[0]==="'",v=32;if(f.index-1>=0)v=u.charCodeAt(f.index-1);else for(n=o-1;n>=0&&!(e[n].type==="softbreak"||e[n].type==="hardbreak");n--)if(e[n].content){v=e[n].content.charCodeAt(e[n].content.length-1);break}let M=32;if(c<p)M=u.charCodeAt(c);else for(n=o+1;n<e.length&&!(e[n].type==="softbreak"||e[n].type==="hardbreak");n++)if(e[n].content){M=e[n].content.charCodeAt(0);break}let $=On(v)||Bn(String.fromCharCode(v)),L=On(M)||Bn(String.fromCharCode(M)),C=Pn(v),P=Pn(M);if(P?h=!1:L&&(C||$||(h=!1)),C?y=!1:$&&(P||L||(y=!1)),M===34&&f[0]==='"'&&v>=48&&v<=57&&(y=h=!1),h&&y&&(h=$,y=L),!h&&!y){g&&(i.content=Qo(i.content,f.index,fc));continue}if(y)for(n=a.length-1;n>=0;n--){let H=a[n];if(a[n].level<r)break;if(H.single===g&&a[n].level===r){H=a[n];let q,I;g?(q=t.md.options.quotes[2],I=t.md.options.quotes[3]):(q=t.md.options.quotes[0],I=t.md.options.quotes[1]),i.content=Qo(i.content,f.index,I),e[H.token].content=Qo(e[H.token].content,H.pos,q),c+=I.length-1,H.token===o&&(c+=q.length-1),u=i.content,p=u.length,a.length=n;continue e}}h?a.push({token:o,pos:f.index,single:g,level:r}):y&&g&&(i.content=Qo(i.content,f.index,fc))}}}function Ci(e){if(e.md.options.typographer)for(let t=e.tokens.length-1;t>=0;t--)e.tokens[t].type!=="inline"||!ah.test(e.tokens[t].content)||ih(e.tokens[t].children,e)}function Ii(e){let t,n,a=e.tokens,o=a.length;for(let i=0;i<o;i++){if(a[i].type!=="inline")continue;let r=a[i].children,u=r.length;for(t=0;t<u;t++)r[t].type==="text_special"&&(r[t].type="text");for(t=n=0;t<u;t++)r[t].type==="text"&&t+1<u&&r[t+1].type==="text"?r[t+1].content=r[t].content+r[t+1].content:(t!==n&&(r[n]=r[t]),n++);t!==n&&(r.length=n)}}var Mi=[["normalize",xi],["block",Si],["inline",Ei],["linkify",Ti],["replacements",Li],["smartquotes",Ci],["text_join",Ii]];function Ai(){this.ruler=new Nn;for(let e=0;e<Mi.length;e++)this.ruler.push(Mi[e][0],Mi[e][1])}Ai.prototype.process=function(e){let t=this.ruler.getRules("");for(let n=0,a=t.length;n<a;n++)t[n](e)};Ai.prototype.State=cc;var mc=Ai;function Gt(e,t,n,a){this.src=e,this.md=t,this.env=n,this.tokens=a,this.bMarks=[],this.eMarks=[],this.tShift=[],this.sCount=[],this.bsCount=[],this.blkIndent=0,this.line=0,this.lineMax=0,this.tight=!1,this.ddIndent=-1,this.listIndent=-1,this.parentType="root",this.level=0;let o=this.src;for(let i=0,r=0,u=0,c=0,p=o.length,f=!1;r<p;r++){let h=o.charCodeAt(r);if(!f)if(we(h)){u++,h===9?c+=4-c%4:c++;continue}else f=!0;(h===10||r===p-1)&&(h!==10&&r++,this.bMarks.push(i),this.eMarks.push(r),this.tShift.push(u),this.sCount.push(c),this.bsCount.push(0),f=!1,u=0,c=0,i=r+1)}this.bMarks.push(o.length),this.eMarks.push(o.length),this.tShift.push(0),this.sCount.push(0),this.bsCount.push(0),this.lineMax=this.bMarks.length-1}Gt.prototype.push=function(e,t,n){let a=new tn(e,t,n);return a.block=!0,n<0&&this.level--,a.level=this.level,n>0&&this.level++,this.tokens.push(a),a};Gt.prototype.isEmpty=function(t){return this.bMarks[t]+this.tShift[t]>=this.eMarks[t]};Gt.prototype.skipEmptyLines=function(t){for(let n=this.lineMax;t<n&&!(this.bMarks[t]+this.tShift[t]<this.eMarks[t]);t++);return t};Gt.prototype.skipSpaces=function(t){for(let n=this.src.length;t<n;t++){let a=this.src.charCodeAt(t);if(!we(a))break}return t};Gt.prototype.skipSpacesBack=function(t,n){if(t<=n)return t;for(;t>n;)if(!we(this.src.charCodeAt(--t)))return t+1;return t};Gt.prototype.skipChars=function(t,n){for(let a=this.src.length;t<a&&this.src.charCodeAt(t)===n;t++);return t};Gt.prototype.skipCharsBack=function(t,n,a){if(t<=a)return t;for(;t>a;)if(n!==this.src.charCodeAt(--t))return t+1;return t};Gt.prototype.getLines=function(t,n,a,o){if(t>=n)return"";let i=new Array(n-t);for(let r=0,u=t;u<n;u++,r++){let c=0,p=this.bMarks[u],f=p,h;for(u+1<n||o?h=this.eMarks[u]+1:h=this.eMarks[u];f<h&&c<a;){let y=this.src.charCodeAt(f);if(we(y))y===9?c+=4-(c+this.bsCount[u])%4:c++;else if(f-p<this.tShift[u])c++;else break;f++}c>a?i[r]=new Array(c-a+1).join(" ")+this.src.slice(f,h):i[r]=this.src.slice(f,h)}return i.join("")};Gt.prototype.Token=tn;var hc=Gt;var rh=65536;function Di(e,t){let n=e.bMarks[t]+e.tShift[t],a=e.eMarks[t];return e.src.slice(n,a)}function gc(e){let t=[],n=e.length,a=0,o=e.charCodeAt(a),i=!1,r=0,u="";for(;a<n;)o===124&&(i?(u+=e.substring(r,a-1),r=a):(t.push(u+e.substring(r,a)),u="",r=a+1)),i=o===92,a++,o=e.charCodeAt(a);return t.push(u+e.substring(r)),t}function Hi(e,t,n,a){if(t+2>n)return!1;let o=t+1;if(e.sCount[o]<e.blkIndent||e.sCount[o]-e.blkIndent>=4)return!1;let i=e.bMarks[o]+e.tShift[o];if(i>=e.eMarks[o])return!1;let r=e.src.charCodeAt(i++);if(r!==124&&r!==45&&r!==58||i>=e.eMarks[o])return!1;let u=e.src.charCodeAt(i++);if(u!==124&&u!==45&&u!==58&&!we(u)||r===45&&we(u))return!1;for(;i<e.eMarks[o];){let H=e.src.charCodeAt(i);if(H!==124&&H!==45&&H!==58&&!we(H))return!1;i++}let c=Di(e,t+1),p=c.split("|"),f=[];for(let H=0;H<p.length;H++){let q=p[H].trim();if(!q){if(H===0||H===p.length-1)continue;return!1}if(!/^:?-+:?$/.test(q))return!1;q.charCodeAt(q.length-1)===58?f.push(q.charCodeAt(0)===58?"center":"right"):q.charCodeAt(0)===58?f.push("left"):f.push("")}if(c=Di(e,t).trim(),c.indexOf("|")===-1||e.sCount[t]-e.blkIndent>=4)return!1;p=gc(c),p.length&&p[0]===""&&p.shift(),p.length&&p[p.length-1]===""&&p.pop();let h=p.length;if(h===0||h!==f.length)return!1;if(a)return!0;let y=e.parentType;e.parentType="table";let g=e.md.block.ruler.getRules("blockquote"),v=e.push("table_open","table",1),M=[t,0];v.map=M;let $=e.push("thead_open","thead",1);$.map=[t,t+1];let L=e.push("tr_open","tr",1);L.map=[t,t+1];for(let H=0;H<p.length;H++){let q=e.push("th_open","th",1);f[H]&&(q.attrs=[["style","text-align:"+f[H]]]);let I=e.push("inline","",0);I.content=p[H].trim(),I.children=[],e.push("th_close","th",-1)}e.push("tr_close","tr",-1),e.push("thead_close","thead",-1);let C,P=0;for(o=t+2;o<n&&!(e.sCount[o]<e.blkIndent);o++){let H=!1;for(let I=0,N=g.length;I<N;I++)if(g[I](e,o,n,!0)){H=!0;break}if(H||(c=Di(e,o).trim(),!c)||e.sCount[o]-e.blkIndent>=4||(p=gc(c),p.length&&p[0]===""&&p.shift(),p.length&&p[p.length-1]===""&&p.pop(),P+=h-p.length,P>rh))break;if(o===t+2){let I=e.push("tbody_open","tbody",1);I.map=C=[t+2,0]}let q=e.push("tr_open","tr",1);q.map=[o,o+1];for(let I=0;I<h;I++){let N=e.push("td_open","td",1);f[I]&&(N.attrs=[["style","text-align:"+f[I]]]);let O=e.push("inline","",0);O.content=p[I]?p[I].trim():"",O.children=[],e.push("td_close","td",-1)}e.push("tr_close","tr",-1)}return C&&(e.push("tbody_close","tbody",-1),C[1]=o),e.push("table_close","table",-1),M[1]=o,e.parentType=y,e.line=o,!0}function _i(e,t,n){if(e.sCount[t]-e.blkIndent<4)return!1;let a=t+1,o=a;for(;a<n;){if(e.isEmpty(a)){a++;continue}if(e.sCount[a]-e.blkIndent>=4){a++,o=a;continue}break}e.line=o;let i=e.push("code_block","code",0);return i.content=e.getLines(t,o,4+e.blkIndent,!1)+`
|
|
2171
|
-
`,i.map=[t,e.line],!0}function Ri(e,t,n,a){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4||o+3>i)return!1;let r=e.src.charCodeAt(o);if(r!==126&&r!==96)return!1;let u=o;o=e.skipChars(o,r);let c=o-u;if(c<3)return!1;let p=e.src.slice(u,o),f=e.src.slice(o,i);if(r===96&&f.indexOf(String.fromCharCode(r))>=0)return!1;if(a)return!0;let h=t,y=!1;for(;h++,!(h>=n||(o=u=e.bMarks[h]+e.tShift[h],i=e.eMarks[h],o<i&&e.sCount[h]<e.blkIndent));)if(e.src.charCodeAt(o)===r&&!(e.sCount[h]-e.blkIndent>=4)&&(o=e.skipChars(o,r),!(o-u<c)&&(o=e.skipSpaces(o),!(o<i)))){y=!0;break}c=e.sCount[t],e.line=h+(y?1:0);let g=e.push("fence","code",0);return g.info=f,g.content=e.getLines(t+1,h,c,!0),g.markup=p,g.map=[t,e.line],!0}function Pi(e,t,n,a){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t],r=e.lineMax;if(e.sCount[t]-e.blkIndent>=4||e.src.charCodeAt(o)!==62)return!1;if(a)return!0;let u=[],c=[],p=[],f=[],h=e.md.block.ruler.getRules("blockquote"),y=e.parentType;e.parentType="blockquote";let g=!1,v;for(v=t;v<n;v++){let P=e.sCount[v]<e.blkIndent;if(o=e.bMarks[v]+e.tShift[v],i=e.eMarks[v],o>=i)break;if(e.src.charCodeAt(o++)===62&&!P){let q=e.sCount[v]+1,I,N;e.src.charCodeAt(o)===32?(o++,q++,N=!1,I=!0):e.src.charCodeAt(o)===9?(I=!0,(e.bsCount[v]+q)%4===3?(o++,q++,N=!1):N=!0):I=!1;let O=q;for(u.push(e.bMarks[v]),e.bMarks[v]=o;o<i;){let A=e.src.charCodeAt(o);if(we(A))A===9?O+=4-(O+e.bsCount[v]+(N?1:0))%4:O++;else break;o++}g=o>=i,c.push(e.bsCount[v]),e.bsCount[v]=e.sCount[v]+1+(I?1:0),p.push(e.sCount[v]),e.sCount[v]=O-q,f.push(e.tShift[v]),e.tShift[v]=o-e.bMarks[v];continue}if(g)break;let H=!1;for(let q=0,I=h.length;q<I;q++)if(h[q](e,v,n,!0)){H=!0;break}if(H){e.lineMax=v,e.blkIndent!==0&&(u.push(e.bMarks[v]),c.push(e.bsCount[v]),f.push(e.tShift[v]),p.push(e.sCount[v]),e.sCount[v]-=e.blkIndent);break}u.push(e.bMarks[v]),c.push(e.bsCount[v]),f.push(e.tShift[v]),p.push(e.sCount[v]),e.sCount[v]=-1}let M=e.blkIndent;e.blkIndent=0;let $=e.push("blockquote_open","blockquote",1);$.markup=">";let L=[t,0];$.map=L,e.md.block.tokenize(e,t,v);let C=e.push("blockquote_close","blockquote",-1);C.markup=">",e.lineMax=r,e.parentType=y,L[1]=e.line;for(let P=0;P<f.length;P++)e.bMarks[P+t]=u[P],e.tShift[P+t]=f[P],e.sCount[P+t]=p[P],e.bsCount[P+t]=c[P];return e.blkIndent=M,!0}function Bi(e,t,n,a){let o=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;let i=e.bMarks[t]+e.tShift[t],r=e.src.charCodeAt(i++);if(r!==42&&r!==45&&r!==95)return!1;let u=1;for(;i<o;){let p=e.src.charCodeAt(i++);if(p!==r&&!we(p))return!1;p===r&&u++}if(u<3)return!1;if(a)return!0;e.line=t+1;let c=e.push("hr","hr",0);return c.map=[t,e.line],c.markup=Array(u+1).join(String.fromCharCode(r)),!0}function bc(e,t){let n=e.eMarks[t],a=e.bMarks[t]+e.tShift[t],o=e.src.charCodeAt(a++);if(o!==42&&o!==45&&o!==43)return-1;if(a<n){let i=e.src.charCodeAt(a);if(!we(i))return-1}return a}function yc(e,t){let n=e.bMarks[t]+e.tShift[t],a=e.eMarks[t],o=n;if(o+1>=a)return-1;let i=e.src.charCodeAt(o++);if(i<48||i>57)return-1;for(;;){if(o>=a)return-1;if(i=e.src.charCodeAt(o++),i>=48&&i<=57){if(o-n>=10)return-1;continue}if(i===41||i===46)break;return-1}return o<a&&(i=e.src.charCodeAt(o),!we(i))?-1:o}function lh(e,t){let n=e.level+2;for(let a=t+2,o=e.tokens.length-2;a<o;a++)e.tokens[a].level===n&&e.tokens[a].type==="paragraph_open"&&(e.tokens[a+2].hidden=!0,e.tokens[a].hidden=!0,a+=2)}function Oi(e,t,n,a){let o,i,r,u,c=t,p=!0;if(e.sCount[c]-e.blkIndent>=4||e.listIndent>=0&&e.sCount[c]-e.listIndent>=4&&e.sCount[c]<e.blkIndent)return!1;let f=!1;a&&e.parentType==="paragraph"&&e.sCount[c]>=e.blkIndent&&(f=!0);let h,y,g;if((g=yc(e,c))>=0){if(h=!0,r=e.bMarks[c]+e.tShift[c],y=Number(e.src.slice(r,g-1)),f&&y!==1)return!1}else if((g=bc(e,c))>=0)h=!1;else return!1;if(f&&e.skipSpaces(g)>=e.eMarks[c])return!1;if(a)return!0;let v=e.src.charCodeAt(g-1),M=e.tokens.length;h?(u=e.push("ordered_list_open","ol",1),y!==1&&(u.attrs=[["start",y]])):u=e.push("bullet_list_open","ul",1);let $=[c,0];u.map=$,u.markup=String.fromCharCode(v);let L=!1,C=e.md.block.ruler.getRules("list"),P=e.parentType;for(e.parentType="list";c<n;){i=g,o=e.eMarks[c];let H=e.sCount[c]+g-(e.bMarks[c]+e.tShift[c]),q=H;for(;i<o;){let j=e.src.charCodeAt(i);if(j===9)q+=4-(q+e.bsCount[c])%4;else if(j===32)q++;else break;i++}let I=i,N;I>=o?N=1:N=q-H,N>4&&(N=1);let O=H+N;u=e.push("list_item_open","li",1),u.markup=String.fromCharCode(v);let A=[c,0];u.map=A,h&&(u.info=e.src.slice(r,g-1));let R=e.tight,B=e.tShift[c],V=e.sCount[c],Z=e.listIndent;if(e.listIndent=e.blkIndent,e.blkIndent=O,e.tight=!0,e.tShift[c]=I-e.bMarks[c],e.sCount[c]=q,I>=o&&e.isEmpty(c+1)?e.line=Math.min(e.line+2,n):e.md.block.tokenize(e,c,n,!0),(!e.tight||L)&&(p=!1),L=e.line-c>1&&e.isEmpty(e.line-1),e.blkIndent=e.listIndent,e.listIndent=Z,e.tShift[c]=B,e.sCount[c]=V,e.tight=R,u=e.push("list_item_close","li",-1),u.markup=String.fromCharCode(v),c=e.line,A[1]=c,c>=n||e.sCount[c]<e.blkIndent||e.sCount[c]-e.blkIndent>=4)break;let G=!1;for(let j=0,z=C.length;j<z;j++)if(C[j](e,c,n,!0)){G=!0;break}if(G)break;if(h){if(g=yc(e,c),g<0)break;r=e.bMarks[c]+e.tShift[c]}else if(g=bc(e,c),g<0)break;if(v!==e.src.charCodeAt(g-1))break}return h?u=e.push("ordered_list_close","ol",-1):u=e.push("bullet_list_close","ul",-1),u.markup=String.fromCharCode(v),$[1]=c,e.line=c,e.parentType=P,p&&lh(e,M),!0}function Fi(e,t,n,a){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t],r=t+1;if(e.sCount[t]-e.blkIndent>=4||e.src.charCodeAt(o)!==91)return!1;function u(C){let P=e.lineMax;if(C>=P||e.isEmpty(C))return null;let H=!1;if(e.sCount[C]-e.blkIndent>3&&(H=!0),e.sCount[C]<0&&(H=!0),!H){let N=e.md.block.ruler.getRules("reference"),O=e.parentType;e.parentType="reference";let A=!1;for(let R=0,B=N.length;R<B;R++)if(N[R](e,C,P,!0)){A=!0;break}if(e.parentType=O,A)return null}let q=e.bMarks[C]+e.tShift[C],I=e.eMarks[C];return e.src.slice(q,I+1)}let c=e.src.slice(o,i+1);i=c.length;let p=-1;for(o=1;o<i;o++){let C=c.charCodeAt(o);if(C===91)return!1;if(C===93){p=o;break}else if(C===10){let P=u(r);P!==null&&(c+=P,i=c.length,r++)}else if(C===92&&(o++,o<i&&c.charCodeAt(o)===10)){let P=u(r);P!==null&&(c+=P,i=c.length,r++)}}if(p<0||c.charCodeAt(p+1)!==58)return!1;for(o=p+2;o<i;o++){let C=c.charCodeAt(o);if(C===10){let P=u(r);P!==null&&(c+=P,i=c.length,r++)}else if(!we(C))break}let f=e.md.helpers.parseLinkDestination(c,o,i);if(!f.ok)return!1;let h=e.md.normalizeLink(f.str);if(!e.md.validateLink(h))return!1;o=f.pos;let y=o,g=r,v=o;for(;o<i;o++){let C=c.charCodeAt(o);if(C===10){let P=u(r);P!==null&&(c+=P,i=c.length,r++)}else if(!we(C))break}let M=e.md.helpers.parseLinkTitle(c,o,i);for(;M.can_continue;){let C=u(r);if(C===null)break;c+=C,o=i,i=c.length,r++,M=e.md.helpers.parseLinkTitle(c,o,i,M)}let $;for(o<i&&v!==o&&M.ok?($=M.str,o=M.pos):($="",o=y,r=g);o<i;){let C=c.charCodeAt(o);if(!we(C))break;o++}if(o<i&&c.charCodeAt(o)!==10&&$)for($="",o=y,r=g;o<i;){let C=c.charCodeAt(o);if(!we(C))break;o++}if(o<i&&c.charCodeAt(o)!==10)return!1;let L=Fn(c.slice(1,p));return L?(a||(typeof e.env.references>"u"&&(e.env.references={}),typeof e.env.references[L]>"u"&&(e.env.references[L]={title:$,href:h}),e.line=r),!0):!1}var vc=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"];var uh="[a-zA-Z_:][a-zA-Z0-9:._-]*",ch="[^\"'=<>`\\x00-\\x20]+",dh="'[^']*'",ph='"[^"]*"',fh="(?:"+ch+"|"+dh+"|"+ph+")",mh="(?:\\s+"+uh+"(?:\\s*=\\s*"+fh+")?)",wc="<[A-Za-z][A-Za-z0-9\\-]*"+mh+"*\\s*\\/?>",kc="<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>",hh="<!---?>|<!--(?:[^-]|-[^-]|--[^>])*-->",gh="<[?][\\s\\S]*?[?]>",bh="<![A-Za-z][^>]*>",yh="<!\\[CDATA\\[[\\s\\S]*?\\]\\]>",$c=new RegExp("^(?:"+wc+"|"+kc+"|"+hh+"|"+gh+"|"+bh+"|"+yh+")"),xc=new RegExp("^(?:"+wc+"|"+kc+")");var hs=[[/^<(script|pre|style|textarea)(?=(\s|>|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^<!--/,/-->/,!0],[/^<\?/,/\?>/,!0],[/^<![A-Z]/,/>/,!0],[/^<!\[CDATA\[/,/\]\]>/,!0],[new RegExp("^</?("+vc.join("|")+")(?=(\\s|/?>|$))","i"),/^$/,!0],[new RegExp(xc.source+"\\s*$"),/^$/,!1]];function Ni(e,t,n,a){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4||!e.md.options.html||e.src.charCodeAt(o)!==60)return!1;let r=e.src.slice(o,i),u=0;for(;u<hs.length&&!hs[u][0].test(r);u++);if(u===hs.length)return!1;if(a)return hs[u][2];let c=t+1;if(!hs[u][1].test(r)){for(;c<n&&!(e.sCount[c]<e.blkIndent);c++)if(o=e.bMarks[c]+e.tShift[c],i=e.eMarks[c],r=e.src.slice(o,i),hs[u][1].test(r)){r.length!==0&&c++;break}}e.line=c;let p=e.push("html_block","",0);return p.map=[t,c],p.content=e.getLines(t,c,e.blkIndent,!0),!0}function qi(e,t,n,a){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;let r=e.src.charCodeAt(o);if(r!==35||o>=i)return!1;let u=1;for(r=e.src.charCodeAt(++o);r===35&&o<i&&u<=6;)u++,r=e.src.charCodeAt(++o);if(u>6||o<i&&!we(r))return!1;if(a)return!0;i=e.skipSpacesBack(i,o);let c=e.skipCharsBack(i,35,o);c>o&&we(e.src.charCodeAt(c-1))&&(i=c),e.line=t+1;let p=e.push("heading_open","h"+String(u),1);p.markup="########".slice(0,u),p.map=[t,e.line];let f=e.push("inline","",0);f.content=e.src.slice(o,i).trim(),f.map=[t,e.line],f.children=[];let h=e.push("heading_close","h"+String(u),-1);return h.markup="########".slice(0,u),!0}function ji(e,t,n){let a=e.md.block.ruler.getRules("paragraph");if(e.sCount[t]-e.blkIndent>=4)return!1;let o=e.parentType;e.parentType="paragraph";let i=0,r,u=t+1;for(;u<n&&!e.isEmpty(u);u++){if(e.sCount[u]-e.blkIndent>3)continue;if(e.sCount[u]>=e.blkIndent){let g=e.bMarks[u]+e.tShift[u],v=e.eMarks[u];if(g<v&&(r=e.src.charCodeAt(g),(r===45||r===61)&&(g=e.skipChars(g,r),g=e.skipSpaces(g),g>=v))){i=r===61?1:2;break}}if(e.sCount[u]<0)continue;let y=!1;for(let g=0,v=a.length;g<v;g++)if(a[g](e,u,n,!0)){y=!0;break}if(y)break}if(!i)return!1;let c=e.getLines(t,u,e.blkIndent,!1).trim();e.line=u+1;let p=e.push("heading_open","h"+String(i),1);p.markup=String.fromCharCode(r),p.map=[t,e.line];let f=e.push("inline","",0);f.content=c,f.map=[t,e.line-1],f.children=[];let h=e.push("heading_close","h"+String(i),-1);return h.markup=String.fromCharCode(r),e.parentType=o,!0}function Ui(e,t,n){let a=e.md.block.ruler.getRules("paragraph"),o=e.parentType,i=t+1;for(e.parentType="paragraph";i<n&&!e.isEmpty(i);i++){if(e.sCount[i]-e.blkIndent>3||e.sCount[i]<0)continue;let p=!1;for(let f=0,h=a.length;f<h;f++)if(a[f](e,i,n,!0)){p=!0;break}if(p)break}let r=e.getLines(t,i,e.blkIndent,!1).trim();e.line=i;let u=e.push("paragraph_open","p",1);u.map=[t,e.line];let c=e.push("inline","",0);return c.content=r,c.map=[t,e.line],c.children=[],e.push("paragraph_close","p",-1),e.parentType=o,!0}var Xo=[["table",Hi,["paragraph","reference"]],["code",_i],["fence",Ri,["paragraph","reference","blockquote","list"]],["blockquote",Pi,["paragraph","reference","blockquote","list"]],["hr",Bi,["paragraph","reference","blockquote","list"]],["list",Oi,["paragraph","reference","blockquote"]],["reference",Fi],["html_block",Ni,["paragraph","reference","blockquote"]],["heading",qi,["paragraph","reference","blockquote"]],["lheading",ji],["paragraph",Ui]];function ea(){this.ruler=new Nn;for(let e=0;e<Xo.length;e++)this.ruler.push(Xo[e][0],Xo[e][1],{alt:(Xo[e][2]||[]).slice()})}ea.prototype.tokenize=function(e,t,n){let a=this.ruler.getRules(""),o=a.length,i=e.md.options.maxNesting,r=t,u=!1;for(;r<n&&(e.line=r=e.skipEmptyLines(r),!(r>=n||e.sCount[r]<e.blkIndent));){if(e.level>=i){e.line=n;break}let c=e.line,p=!1;for(let f=0;f<o;f++)if(p=a[f](e,r,n,!1),p){if(c>=e.line)throw new Error("block rule didn't increment state.line");break}if(!p)throw new Error("none of the block rules matched");e.tight=!u,e.isEmpty(e.line-1)&&(u=!0),r=e.line,r<n&&e.isEmpty(r)&&(u=!0,r++,e.line=r)}};ea.prototype.parse=function(e,t,n,a){if(!e)return;let o=new this.State(e,t,n,a);this.tokenize(o,o.line,o.lineMax)};ea.prototype.State=hc;var Sc=ea;function Vs(e,t,n,a){this.src=e,this.env=n,this.md=t,this.tokens=a,this.tokens_meta=Array(a.length),this.pos=0,this.posMax=this.src.length,this.level=0,this.pending="",this.pendingLevel=0,this.cache={},this.delimiters=[],this._prev_delimiters=[],this.backticks={},this.backticksScanned=!1,this.linkLevel=0}Vs.prototype.pushPending=function(){let e=new tn("text","",0);return e.content=this.pending,e.level=this.pendingLevel,this.tokens.push(e),this.pending="",e};Vs.prototype.push=function(e,t,n){this.pending&&this.pushPending();let a=new tn(e,t,n),o=null;return n<0&&(this.level--,this.delimiters=this._prev_delimiters.pop()),a.level=this.level,n>0&&(this.level++,this._prev_delimiters.push(this.delimiters),this.delimiters=[],o={delimiters:this.delimiters}),this.pendingLevel=this.level,this.tokens.push(a),this.tokens_meta.push(o),a};Vs.prototype.scanDelims=function(e,t){let n=this.posMax,a=this.src.charCodeAt(e),o=e>0?this.src.charCodeAt(e-1):32,i=e;for(;i<n&&this.src.charCodeAt(i)===a;)i++;let r=i-e,u=i<n?this.src.charCodeAt(i):32,c=On(o)||Bn(String.fromCharCode(o)),p=On(u)||Bn(String.fromCharCode(u)),f=Pn(o),h=Pn(u),y=!h&&(!p||f||c),g=!f&&(!c||h||p);return{can_open:y&&(t||!g||c),can_close:g&&(t||!y||p),length:r}};Vs.prototype.Token=tn;var Ec=Vs;function vh(e){switch(e){case 10:case 33:case 35:case 36:case 37:case 38:case 42:case 43:case 45:case 58:case 60:case 61:case 62:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 125:case 126:return!0;default:return!1}}function zi(e,t){let n=e.pos;for(;n<e.posMax&&!vh(e.src.charCodeAt(n));)n++;return n===e.pos?!1:(t||(e.pending+=e.src.slice(e.pos,n)),e.pos=n,!0)}var wh=/(?:^|[^a-z0-9.+-])([a-z][a-z0-9.+-]*)$/i;function Gi(e,t){if(!e.md.options.linkify||e.linkLevel>0)return!1;let n=e.pos,a=e.posMax;if(n+3>a||e.src.charCodeAt(n)!==58||e.src.charCodeAt(n+1)!==47||e.src.charCodeAt(n+2)!==47)return!1;let o=e.pending.match(wh);if(!o)return!1;let i=o[1],r=e.md.linkify.matchAtStart(e.src.slice(n-i.length));if(!r)return!1;let u=r.url;if(u.length<=i.length)return!1;let c=u.length;for(;c>0&&u.charCodeAt(c-1)===42;)c--;c!==u.length&&(u=u.slice(0,c));let p=e.md.normalizeLink(u);if(!e.md.validateLink(p))return!1;if(!t){e.pending=e.pending.slice(0,-i.length);let f=e.push("link_open","a",1);f.attrs=[["href",p]],f.markup="linkify",f.info="auto";let h=e.push("text","",0);h.content=e.md.normalizeLinkText(u);let y=e.push("link_close","a",-1);y.markup="linkify",y.info="auto"}return e.pos+=u.length-i.length,!0}function Wi(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==10)return!1;let a=e.pending.length-1,o=e.posMax;if(!t)if(a>=0&&e.pending.charCodeAt(a)===32)if(a>=1&&e.pending.charCodeAt(a-1)===32){let i=a-1;for(;i>=1&&e.pending.charCodeAt(i-1)===32;)i--;e.pending=e.pending.slice(0,i),e.push("hardbreak","br",0)}else e.pending=e.pending.slice(0,-1),e.push("softbreak","br",0);else e.push("softbreak","br",0);for(n++;n<o&&we(e.src.charCodeAt(n));)n++;return e.pos=n,!0}var Vi=[];for(let e=0;e<256;e++)Vi.push(0);"\\!\"#$%&'()*+,./:;<=>?@[]^_`{|}~-".split("").forEach(function(e){Vi[e.charCodeAt(0)]=1});function Ki(e,t){let n=e.pos,a=e.posMax;if(e.src.charCodeAt(n)!==92||(n++,n>=a))return!1;let o=e.src.charCodeAt(n);if(o===10){for(t||e.push("hardbreak","br",0),n++;n<a&&(o=e.src.charCodeAt(n),!!we(o));)n++;return e.pos=n,!0}let i=e.src[n];if(o>=55296&&o<=56319&&n+1<a){let u=e.src.charCodeAt(n+1);u>=56320&&u<=57343&&(i+=e.src[n+1],n++)}let r="\\"+i;if(!t){let u=e.push("text_special","",0);o<256&&Vi[o]!==0?u.content=i:u.content=r,u.markup=r,u.info="escape"}return e.pos=n+1,!0}function Ji(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==96)return!1;let o=n;n++;let i=e.posMax;for(;n<i&&e.src.charCodeAt(n)===96;)n++;let r=e.src.slice(o,n),u=r.length;if(e.backticksScanned&&(e.backticks[u]||0)<=o)return t||(e.pending+=r),e.pos+=u,!0;let c=n,p;for(;(p=e.src.indexOf("`",c))!==-1;){for(c=p+1;c<i&&e.src.charCodeAt(c)===96;)c++;let f=c-p;if(f===u){if(!t){let h=e.push("code_inline","code",0);h.markup=r,h.content=e.src.slice(n,p).replace(/\n/g," ").replace(/^ (.+) $/,"$1")}return e.pos=c,!0}e.backticks[f]=p}return e.backticksScanned=!0,t||(e.pending+=r),e.pos+=u,!0}function kh(e,t){let n=e.pos,a=e.src.charCodeAt(n);if(t||a!==126)return!1;let o=e.scanDelims(e.pos,!0),i=o.length,r=String.fromCharCode(a);if(i<2)return!1;let u;i%2&&(u=e.push("text","",0),u.content=r,i--);for(let c=0;c<i;c+=2)u=e.push("text","",0),u.content=r+r,e.delimiters.push({marker:a,length:0,token:e.tokens.length-1,end:-1,open:o.can_open,close:o.can_close});return e.pos+=o.length,!0}function Tc(e,t){let n,a=[],o=t.length;for(let i=0;i<o;i++){let r=t[i];if(r.marker!==126||r.end===-1)continue;let u=t[r.end];n=e.tokens[r.token],n.type="s_open",n.tag="s",n.nesting=1,n.markup="~~",n.content="",n=e.tokens[u.token],n.type="s_close",n.tag="s",n.nesting=-1,n.markup="~~",n.content="",e.tokens[u.token-1].type==="text"&&e.tokens[u.token-1].content==="~"&&a.push(u.token-1)}for(;a.length;){let i=a.pop(),r=i+1;for(;r<e.tokens.length&&e.tokens[r].type==="s_close";)r++;r--,i!==r&&(n=e.tokens[r],e.tokens[r]=e.tokens[i],e.tokens[i]=n)}}function $h(e){let t=e.tokens_meta,n=e.tokens_meta.length;Tc(e,e.delimiters);for(let a=0;a<n;a++)t[a]&&t[a].delimiters&&Tc(e,t[a].delimiters)}var Yi={tokenize:kh,postProcess:$h};function xh(e,t){let n=e.pos,a=e.src.charCodeAt(n);if(t||a!==95&&a!==42)return!1;let o=e.scanDelims(e.pos,a===42);for(let i=0;i<o.length;i++){let r=e.push("text","",0);r.content=String.fromCharCode(a),e.delimiters.push({marker:a,length:o.length,token:e.tokens.length-1,end:-1,open:o.can_open,close:o.can_close})}return e.pos+=o.length,!0}function Lc(e,t){let n=t.length;for(let a=n-1;a>=0;a--){let o=t[a];if(o.marker!==95&&o.marker!==42||o.end===-1)continue;let i=t[o.end],r=a>0&&t[a-1].end===o.end+1&&t[a-1].marker===o.marker&&t[a-1].token===o.token-1&&t[o.end+1].token===i.token+1,u=String.fromCharCode(o.marker),c=e.tokens[o.token];c.type=r?"strong_open":"em_open",c.tag=r?"strong":"em",c.nesting=1,c.markup=r?u+u:u,c.content="";let p=e.tokens[i.token];p.type=r?"strong_close":"em_close",p.tag=r?"strong":"em",p.nesting=-1,p.markup=r?u+u:u,p.content="",r&&(e.tokens[t[a-1].token].content="",e.tokens[t[o.end+1].token].content="",a--)}}function Sh(e){let t=e.tokens_meta,n=e.tokens_meta.length;Lc(e,e.delimiters);for(let a=0;a<n;a++)t[a]&&t[a].delimiters&&Lc(e,t[a].delimiters)}var Zi={tokenize:xh,postProcess:Sh};function Qi(e,t){let n,a,o,i,r="",u="",c=e.pos,p=!0;if(e.src.charCodeAt(e.pos)!==91)return!1;let f=e.pos,h=e.posMax,y=e.pos+1,g=e.md.helpers.parseLinkLabel(e,e.pos,!0);if(g<0)return!1;let v=g+1;if(v<h&&e.src.charCodeAt(v)===40){for(p=!1,v++;v<h&&(n=e.src.charCodeAt(v),!(!we(n)&&n!==10));v++);if(v>=h)return!1;if(c=v,o=e.md.helpers.parseLinkDestination(e.src,v,e.posMax),o.ok){for(r=e.md.normalizeLink(o.str),e.md.validateLink(r)?v=o.pos:r="",c=v;v<h&&(n=e.src.charCodeAt(v),!(!we(n)&&n!==10));v++);if(o=e.md.helpers.parseLinkTitle(e.src,v,e.posMax),v<h&&c!==v&&o.ok)for(u=o.str,v=o.pos;v<h&&(n=e.src.charCodeAt(v),!(!we(n)&&n!==10));v++);}(v>=h||e.src.charCodeAt(v)!==41)&&(p=!0),v++}if(p){if(typeof e.env.references>"u")return!1;if(v<h&&e.src.charCodeAt(v)===91?(c=v+1,v=e.md.helpers.parseLinkLabel(e,v),v>=0?a=e.src.slice(c,v++):v=g+1):v=g+1,a||(a=e.src.slice(y,g)),i=e.env.references[Fn(a)],!i)return e.pos=f,!1;r=i.href,u=i.title}if(!t){e.pos=y,e.posMax=g;let M=e.push("link_open","a",1),$=[["href",r]];M.attrs=$,u&&$.push(["title",u]),e.linkLevel++,e.md.inline.tokenize(e),e.linkLevel--,e.push("link_close","a",-1)}return e.pos=v,e.posMax=h,!0}function Xi(e,t){let n,a,o,i,r,u,c,p,f="",h=e.pos,y=e.posMax;if(e.src.charCodeAt(e.pos)!==33||e.src.charCodeAt(e.pos+1)!==91)return!1;let g=e.pos+2,v=e.md.helpers.parseLinkLabel(e,e.pos+1,!1);if(v<0)return!1;if(i=v+1,i<y&&e.src.charCodeAt(i)===40){for(i++;i<y&&(n=e.src.charCodeAt(i),!(!we(n)&&n!==10));i++);if(i>=y)return!1;for(p=i,u=e.md.helpers.parseLinkDestination(e.src,i,e.posMax),u.ok&&(f=e.md.normalizeLink(u.str),e.md.validateLink(f)?i=u.pos:f=""),p=i;i<y&&(n=e.src.charCodeAt(i),!(!we(n)&&n!==10));i++);if(u=e.md.helpers.parseLinkTitle(e.src,i,e.posMax),i<y&&p!==i&&u.ok)for(c=u.str,i=u.pos;i<y&&(n=e.src.charCodeAt(i),!(!we(n)&&n!==10));i++);else c="";if(i>=y||e.src.charCodeAt(i)!==41)return e.pos=h,!1;i++}else{if(typeof e.env.references>"u")return!1;if(i<y&&e.src.charCodeAt(i)===91?(p=i+1,i=e.md.helpers.parseLinkLabel(e,i),i>=0?o=e.src.slice(p,i++):i=v+1):i=v+1,o||(o=e.src.slice(g,v)),r=e.env.references[Fn(o)],!r)return e.pos=h,!1;f=r.href,c=r.title}if(!t){a=e.src.slice(g,v);let M=[];e.md.inline.parse(a,e.md,e.env,M);let $=e.push("image","img",0),L=[["src",f],["alt",""]];$.attrs=L,$.children=M,$.content=a,c&&L.push(["title",c])}return e.pos=i,e.posMax=y,!0}var Eh=/^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/,Th=/^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;function er(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==60)return!1;let a=e.pos,o=e.posMax;for(;;){if(++n>=o)return!1;let r=e.src.charCodeAt(n);if(r===60)return!1;if(r===62)break}let i=e.src.slice(a+1,n);if(Th.test(i)){let r=e.md.normalizeLink(i);if(!e.md.validateLink(r))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",r]],u.markup="autolink",u.info="auto";let c=e.push("text","",0);c.content=e.md.normalizeLinkText(i);let p=e.push("link_close","a",-1);p.markup="autolink",p.info="auto"}return e.pos+=i.length+2,!0}if(Eh.test(i)){let r=e.md.normalizeLink("mailto:"+i);if(!e.md.validateLink(r))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",r]],u.markup="autolink",u.info="auto";let c=e.push("text","",0);c.content=e.md.normalizeLinkText(i);let p=e.push("link_close","a",-1);p.markup="autolink",p.info="auto"}return e.pos+=i.length+2,!0}return!1}function Lh(e){return/^<a[>\s]/i.test(e)}function Ch(e){return/^<\/a\s*>/i.test(e)}function Ih(e){let t=e|32;return t>=97&&t<=122}function tr(e,t){if(!e.md.options.html)return!1;let n=e.posMax,a=e.pos;if(e.src.charCodeAt(a)!==60||a+2>=n)return!1;let o=e.src.charCodeAt(a+1);if(o!==33&&o!==63&&o!==47&&!Ih(o))return!1;let i=e.src.slice(a).match($c);if(!i)return!1;if(!t){let r=e.push("html_inline","",0);r.content=i[0],Lh(r.content)&&e.linkLevel++,Ch(r.content)&&e.linkLevel--}return e.pos+=i[0].length,!0}var Mh=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,Ah=/^&([a-z][a-z0-9]{1,31});/i;function nr(e,t){let n=e.pos,a=e.posMax;if(e.src.charCodeAt(n)!==38||n+1>=a)return!1;if(e.src.charCodeAt(n+1)===35){let i=e.src.slice(n).match(Mh);if(i){if(!t){let r=i[1][0].toLowerCase()==="x"?parseInt(i[1].slice(1),16):parseInt(i[1],10),u=e.push("text_special","",0);u.content=Zo(r)?Ws(r):Ws(65533),u.markup=i[0],u.info="entity"}return e.pos+=i[0].length,!0}}else{let i=e.src.slice(n).match(Ah);if(i){let r=yn(i[0]);if(r!==i[0]){if(!t){let u=e.push("text_special","",0);u.content=r,u.markup=i[0],u.info="entity"}return e.pos+=i[0].length,!0}}}return!1}function Cc(e){let t={},n=e.length;if(!n)return;let a=0,o=-2,i=[];for(let r=0;r<n;r++){let u=e[r];if(i.push(0),(e[a].marker!==u.marker||o!==u.token-1)&&(a=r),o=u.token,u.length=u.length||0,!u.close)continue;t.hasOwnProperty(u.marker)||(t[u.marker]=[-1,-1,-1,-1,-1,-1]);let c=t[u.marker][(u.open?3:0)+u.length%3],p=a-i[a]-1,f=p;for(;p>c;p-=i[p]+1){let h=e[p];if(h.marker===u.marker&&h.open&&h.end<0){let y=!1;if((h.close||u.open)&&(h.length+u.length)%3===0&&(h.length%3!==0||u.length%3!==0)&&(y=!0),!y){let g=p>0&&!e[p-1].open?i[p-1]+1:0;i[r]=r-p+g,i[p]=g,u.open=!1,h.end=r,h.close=!1,f=-1,o=-2;break}}}f!==-1&&(t[u.marker][(u.open?3:0)+(u.length||0)%3]=f)}}function sr(e){let t=e.tokens_meta,n=e.tokens_meta.length;Cc(e.delimiters);for(let a=0;a<n;a++)t[a]&&t[a].delimiters&&Cc(t[a].delimiters)}function or(e){let t,n,a=0,o=e.tokens,i=e.tokens.length;for(t=n=0;t<i;t++)o[t].nesting<0&&a--,o[t].level=a,o[t].nesting>0&&a++,o[t].type==="text"&&t+1<i&&o[t+1].type==="text"?o[t+1].content=o[t].content+o[t+1].content:(t!==n&&(o[n]=o[t]),n++);t!==n&&(o.length=n)}var ar=[["text",zi],["linkify",Gi],["newline",Wi],["escape",Ki],["backticks",Ji],["strikethrough",Yi.tokenize],["emphasis",Zi.tokenize],["link",Qi],["image",Xi],["autolink",er],["html_inline",tr],["entity",nr]],ir=[["balance_pairs",sr],["strikethrough",Yi.postProcess],["emphasis",Zi.postProcess],["fragments_join",or]];function Ks(){this.ruler=new Nn;for(let e=0;e<ar.length;e++)this.ruler.push(ar[e][0],ar[e][1]);this.ruler2=new Nn;for(let e=0;e<ir.length;e++)this.ruler2.push(ir[e][0],ir[e][1])}Ks.prototype.skipToken=function(e){let t=e.pos,n=this.ruler.getRules(""),a=n.length,o=e.md.options.maxNesting,i=e.cache;if(typeof i[t]<"u"){e.pos=i[t];return}let r=!1;if(e.level<o){for(let u=0;u<a;u++)if(e.level++,r=n[u](e,!0),e.level--,r){if(t>=e.pos)throw new Error("inline rule didn't increment state.pos");break}}else e.pos=e.posMax;r||e.pos++,i[t]=e.pos};Ks.prototype.tokenize=function(e){let t=this.ruler.getRules(""),n=t.length,a=e.posMax,o=e.md.options.maxNesting;for(;e.pos<a;){let i=e.pos,r=!1;if(e.level<o){for(let u=0;u<n;u++)if(r=t[u](e,!1),r){if(i>=e.pos)throw new Error("inline rule didn't increment state.pos");break}}if(r){if(e.pos>=a)break;continue}e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()};Ks.prototype.parse=function(e,t,n,a){let o=new this.State(e,t,n,a);this.tokenize(o);let i=this.ruler2.getRules(""),r=i.length;for(let u=0;u<r;u++)i[u](o)};Ks.prototype.State=Ec;var Ic=Ks;function Mc(e){let t={};e=e||{},t.src_Any=zo.source,t.src_Cc=Go.source,t.src_Z=Vo.source,t.src_P=ds.source,t.src_ZPCc=[t.src_Z,t.src_P,t.src_Cc].join("|"),t.src_ZCc=[t.src_Z,t.src_Cc].join("|");let n="[><\uFF5C]";return t.src_pseudo_letter="(?:(?!"+n+"|"+t.src_ZPCc+")"+t.src_Any+")",t.src_ip4="(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)",t.src_auth="(?:(?:(?!"+t.src_ZCc+"|[@/\\[\\]()]).)+@)?",t.src_port="(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?",t.src_host_terminator="(?=$|"+n+"|"+t.src_ZPCc+")(?!"+(e["---"]?"-(?!--)|":"-|")+"_|:\\d|\\.-|\\.(?!$|"+t.src_ZPCc+"))",t.src_path="(?:[/?#](?:(?!"+t.src_ZCc+"|"+n+`|[()[\\]{}.,"'?!\\-;]).|\\[(?:(?!`+t.src_ZCc+"|\\]).)*\\]|\\((?:(?!"+t.src_ZCc+"|[)]).)*\\)|\\{(?:(?!"+t.src_ZCc+'|[}]).)*\\}|\\"(?:(?!'+t.src_ZCc+`|["]).)+\\"|\\'(?:(?!`+t.src_ZCc+"|[']).)+\\'|\\'(?="+t.src_pseudo_letter+"|[-])|\\.{2,}[a-zA-Z0-9%/&]|\\.(?!"+t.src_ZCc+"|[.]|$)|"+(e["---"]?"\\-(?!--(?:[^-]|$))(?:-*)|":"\\-+|")+",(?!"+t.src_ZCc+"|$)|;(?!"+t.src_ZCc+"|$)|\\!+(?!"+t.src_ZCc+"|[!]|$)|\\?(?!"+t.src_ZCc+"|[?]|$))+|\\/)?",t.src_email_name='[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*',t.src_xn="xn--[a-z0-9\\-]{1,59}",t.src_domain_root="(?:"+t.src_xn+"|"+t.src_pseudo_letter+"{1,63})",t.src_domain="(?:"+t.src_xn+"|(?:"+t.src_pseudo_letter+")|(?:"+t.src_pseudo_letter+"(?:-|"+t.src_pseudo_letter+"){0,61}"+t.src_pseudo_letter+"))",t.src_host="(?:(?:(?:(?:"+t.src_domain+")\\.)*"+t.src_domain+"))",t.tpl_host_fuzzy="(?:"+t.src_ip4+"|(?:(?:(?:"+t.src_domain+")\\.)+(?:%TLDS%)))",t.tpl_host_no_ip_fuzzy="(?:(?:(?:"+t.src_domain+")\\.)+(?:%TLDS%))",t.src_host_strict=t.src_host+t.src_host_terminator,t.tpl_host_fuzzy_strict=t.tpl_host_fuzzy+t.src_host_terminator,t.src_host_port_strict=t.src_host+t.src_port+t.src_host_terminator,t.tpl_host_port_fuzzy_strict=t.tpl_host_fuzzy+t.src_port+t.src_host_terminator,t.tpl_host_port_no_ip_fuzzy_strict=t.tpl_host_no_ip_fuzzy+t.src_port+t.src_host_terminator,t.tpl_host_fuzzy_test="localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:"+t.src_ZPCc+"|>|$))",t.tpl_email_fuzzy="(^|"+n+'|"|\\(|'+t.src_ZCc+")("+t.src_email_name+"@"+t.tpl_host_fuzzy_strict+")",t.tpl_link_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`|\uFF5C]|"+t.src_ZPCc+"))((?![$+<=>^`|\uFF5C])"+t.tpl_host_port_fuzzy_strict+t.src_path+")",t.tpl_link_no_ip_fuzzy="(^|(?![.:/\\-_@])(?:[$+<=>^`|\uFF5C]|"+t.src_ZPCc+"))((?![$+<=>^`|\uFF5C])"+t.tpl_host_port_no_ip_fuzzy_strict+t.src_path+")",t}function rr(e){return Array.prototype.slice.call(arguments,1).forEach(function(n){n&&Object.keys(n).forEach(function(a){e[a]=n[a]})}),e}function na(e){return Object.prototype.toString.call(e)}function Dh(e){return na(e)==="[object String]"}function Hh(e){return na(e)==="[object Object]"}function _h(e){return na(e)==="[object RegExp]"}function Ac(e){return na(e)==="[object Function]"}function Rh(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}var Hc={fuzzyLink:!0,fuzzyEmail:!0,fuzzyIP:!1};function Ph(e){return Object.keys(e||{}).reduce(function(t,n){return t||Hc.hasOwnProperty(n)},!1)}var Bh={"http:":{validate:function(e,t,n){let a=e.slice(t);return n.re.http||(n.re.http=new RegExp("^\\/\\/"+n.re.src_auth+n.re.src_host_port_strict+n.re.src_path,"i")),n.re.http.test(a)?a.match(n.re.http)[0].length:0}},"https:":"http:","ftp:":"http:","//":{validate:function(e,t,n){let a=e.slice(t);return n.re.no_http||(n.re.no_http=new RegExp("^"+n.re.src_auth+"(?:localhost|(?:(?:"+n.re.src_domain+")\\.)+"+n.re.src_domain_root+")"+n.re.src_port+n.re.src_host_terminator+n.re.src_path,"i")),n.re.no_http.test(a)?t>=3&&e[t-3]===":"||t>=3&&e[t-3]==="/"?0:a.match(n.re.no_http)[0].length:0}},"mailto:":{validate:function(e,t,n){let a=e.slice(t);return n.re.mailto||(n.re.mailto=new RegExp("^"+n.re.src_email_name+"@"+n.re.src_host_strict,"i")),n.re.mailto.test(a)?a.match(n.re.mailto)[0].length:0}}},Oh="a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]",Fh="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|\u0440\u0444".split("|");function Nh(e){e.__index__=-1,e.__text_cache__=""}function qh(e){return function(t,n){let a=t.slice(n);return e.test(a)?a.match(e)[0].length:0}}function Dc(){return function(e,t){t.normalize(e)}}function ta(e){let t=e.re=Mc(e.__opts__),n=e.__tlds__.slice();e.onCompile(),e.__tlds_replaced__||n.push(Oh),n.push(t.src_xn),t.src_tlds=n.join("|");function a(u){return u.replace("%TLDS%",t.src_tlds)}t.email_fuzzy=RegExp(a(t.tpl_email_fuzzy),"i"),t.link_fuzzy=RegExp(a(t.tpl_link_fuzzy),"i"),t.link_no_ip_fuzzy=RegExp(a(t.tpl_link_no_ip_fuzzy),"i"),t.host_fuzzy_test=RegExp(a(t.tpl_host_fuzzy_test),"i");let o=[];e.__compiled__={};function i(u,c){throw new Error('(LinkifyIt) Invalid schema "'+u+'": '+c)}Object.keys(e.__schemas__).forEach(function(u){let c=e.__schemas__[u];if(c===null)return;let p={validate:null,link:null};if(e.__compiled__[u]=p,Hh(c)){_h(c.validate)?p.validate=qh(c.validate):Ac(c.validate)?p.validate=c.validate:i(u,c),Ac(c.normalize)?p.normalize=c.normalize:c.normalize?i(u,c):p.normalize=Dc();return}if(Dh(c)){o.push(u);return}i(u,c)}),o.forEach(function(u){e.__compiled__[e.__schemas__[u]]&&(e.__compiled__[u].validate=e.__compiled__[e.__schemas__[u]].validate,e.__compiled__[u].normalize=e.__compiled__[e.__schemas__[u]].normalize)}),e.__compiled__[""]={validate:null,normalize:Dc()};let r=Object.keys(e.__compiled__).filter(function(u){return u.length>0&&e.__compiled__[u]}).map(Rh).join("|");e.re.schema_test=RegExp("(^|(?!_)(?:[><\uFF5C]|"+t.src_ZPCc+"))("+r+")","i"),e.re.schema_search=RegExp("(^|(?!_)(?:[><\uFF5C]|"+t.src_ZPCc+"))("+r+")","ig"),e.re.schema_at_start=RegExp("^"+e.re.schema_search.source,"i"),e.re.pretest=RegExp("("+e.re.schema_test.source+")|("+e.re.host_fuzzy_test.source+")|@","i"),Nh(e)}function jh(e,t){let n=e.__index__,a=e.__last_index__,o=e.__text_cache__.slice(n,a);this.schema=e.__schema__.toLowerCase(),this.index=n+t,this.lastIndex=a+t,this.raw=o,this.text=o,this.url=o}function lr(e,t){let n=new jh(e,t);return e.__compiled__[n.schema].normalize(n,e),n}function ht(e,t){if(!(this instanceof ht))return new ht(e,t);t||Ph(e)&&(t=e,e={}),this.__opts__=rr({},Hc,t),this.__index__=-1,this.__last_index__=-1,this.__schema__="",this.__text_cache__="",this.__schemas__=rr({},Bh,e),this.__compiled__={},this.__tlds__=Fh,this.__tlds_replaced__=!1,this.re={},ta(this)}ht.prototype.add=function(t,n){return this.__schemas__[t]=n,ta(this),this};ht.prototype.set=function(t){return this.__opts__=rr(this.__opts__,t),this};ht.prototype.test=function(t){if(this.__text_cache__=t,this.__index__=-1,!t.length)return!1;let n,a,o,i,r,u,c,p,f;if(this.re.schema_test.test(t)){for(c=this.re.schema_search,c.lastIndex=0;(n=c.exec(t))!==null;)if(i=this.testSchemaAt(t,n[2],c.lastIndex),i){this.__schema__=n[2],this.__index__=n.index+n[1].length,this.__last_index__=n.index+n[0].length+i;break}}return this.__opts__.fuzzyLink&&this.__compiled__["http:"]&&(p=t.search(this.re.host_fuzzy_test),p>=0&&(this.__index__<0||p<this.__index__)&&(a=t.match(this.__opts__.fuzzyIP?this.re.link_fuzzy:this.re.link_no_ip_fuzzy))!==null&&(r=a.index+a[1].length,(this.__index__<0||r<this.__index__)&&(this.__schema__="",this.__index__=r,this.__last_index__=a.index+a[0].length))),this.__opts__.fuzzyEmail&&this.__compiled__["mailto:"]&&(f=t.indexOf("@"),f>=0&&(o=t.match(this.re.email_fuzzy))!==null&&(r=o.index+o[1].length,u=o.index+o[0].length,(this.__index__<0||r<this.__index__||r===this.__index__&&u>this.__last_index__)&&(this.__schema__="mailto:",this.__index__=r,this.__last_index__=u))),this.__index__>=0};ht.prototype.pretest=function(t){return this.re.pretest.test(t)};ht.prototype.testSchemaAt=function(t,n,a){return this.__compiled__[n.toLowerCase()]?this.__compiled__[n.toLowerCase()].validate(t,a,this):0};ht.prototype.match=function(t){let n=[],a=0;this.__index__>=0&&this.__text_cache__===t&&(n.push(lr(this,a)),a=this.__last_index__);let o=a?t.slice(a):t;for(;this.test(o);)n.push(lr(this,a)),o=o.slice(this.__last_index__),a+=this.__last_index__;return n.length?n:null};ht.prototype.matchAtStart=function(t){if(this.__text_cache__=t,this.__index__=-1,!t.length)return null;let n=this.re.schema_at_start.exec(t);if(!n)return null;let a=this.testSchemaAt(t,n[2],n[0].length);return a?(this.__schema__=n[2],this.__index__=n.index+n[1].length,this.__last_index__=n.index+n[0].length+a,lr(this,0)):null};ht.prototype.tlds=function(t,n){return t=Array.isArray(t)?t:[t],n?(this.__tlds__=this.__tlds__.concat(t).sort().filter(function(a,o,i){return a!==i[o-1]}).reverse(),ta(this),this):(this.__tlds__=t.slice(),this.__tlds_replaced__=!0,ta(this),this)};ht.prototype.normalize=function(t){t.schema||(t.url="http://"+t.url),t.schema==="mailto:"&&!/^mailto:/i.test(t.url)&&(t.url="mailto:"+t.url)};ht.prototype.onCompile=function(){};var _c=ht;var Uh=/^xn--/,zh=/[^\0-\x7F]/,Gh=/[\x2E\u3002\uFF0E\uFF61]/g,Wh={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},ur=35,Wt=Math.floor,cr=String.fromCharCode;function vn(e){throw new RangeError(Wh[e])}function Vh(e,t){let n=[],a=e.length;for(;a--;)n[a]=t(e[a]);return n}function Pc(e,t){let n=e.split("@"),a="";n.length>1&&(a=n[0]+"@",e=n[1]),e=e.replace(Gh,".");let o=e.split("."),i=Vh(o,t).join(".");return a+i}function Bc(e){let t=[],n=0,a=e.length;for(;n<a;){let o=e.charCodeAt(n++);if(o>=55296&&o<=56319&&n<a){let i=e.charCodeAt(n++);(i&64512)==56320?t.push(((o&1023)<<10)+(i&1023)+65536):(t.push(o),n--)}else t.push(o)}return t}var Kh=e=>String.fromCodePoint(...e),Jh=function(e){return e>=48&&e<58?26+(e-48):e>=65&&e<91?e-65:e>=97&&e<123?e-97:36},Rc=function(e,t){return e+22+75*(e<26)-((t!=0)<<5)},Oc=function(e,t,n){let a=0;for(e=n?Wt(e/700):e>>1,e+=Wt(e/t);e>ur*26>>1;a+=36)e=Wt(e/ur);return Wt(a+(ur+1)*e/(e+38))},Fc=function(e){let t=[],n=e.length,a=0,o=128,i=72,r=e.lastIndexOf("-");r<0&&(r=0);for(let u=0;u<r;++u)e.charCodeAt(u)>=128&&vn("not-basic"),t.push(e.charCodeAt(u));for(let u=r>0?r+1:0;u<n;){let c=a;for(let f=1,h=36;;h+=36){u>=n&&vn("invalid-input");let y=Jh(e.charCodeAt(u++));y>=36&&vn("invalid-input"),y>Wt((2147483647-a)/f)&&vn("overflow"),a+=y*f;let g=h<=i?1:h>=i+26?26:h-i;if(y<g)break;let v=36-g;f>Wt(2147483647/v)&&vn("overflow"),f*=v}let p=t.length+1;i=Oc(a-c,p,c==0),Wt(a/p)>2147483647-o&&vn("overflow"),o+=Wt(a/p),a%=p,t.splice(a++,0,o)}return String.fromCodePoint(...t)},Nc=function(e){let t=[];e=Bc(e);let n=e.length,a=128,o=0,i=72;for(let c of e)c<128&&t.push(cr(c));let r=t.length,u=r;for(r&&t.push("-");u<n;){let c=2147483647;for(let f of e)f>=a&&f<c&&(c=f);let p=u+1;c-a>Wt((2147483647-o)/p)&&vn("overflow"),o+=(c-a)*p,a=c;for(let f of e)if(f<a&&++o>2147483647&&vn("overflow"),f===a){let h=o;for(let y=36;;y+=36){let g=y<=i?1:y>=i+26?26:y-i;if(h<g)break;let v=h-g,M=36-g;t.push(cr(Rc(g+v%M,0))),h=Wt(v/M)}t.push(cr(Rc(h,0))),i=Oc(o,p,u===r),o=0,++u}++o,++a}return t.join("")},Yh=function(e){return Pc(e,function(t){return Uh.test(t)?Fc(t.slice(4).toLowerCase()):t})},Zh=function(e){return Pc(e,function(t){return zh.test(t)?"xn--"+Nc(t):t})},Qh={version:"2.3.1",ucs2:{decode:Bc,encode:Kh},decode:Fc,encode:Nc,toASCII:Zh,toUnicode:Yh};var dr=Qh;var qc={options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201C\u201D\u2018\u2019",highlight:null,maxNesting:100},components:{core:{},block:{},inline:{}}};var jc={options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201C\u201D\u2018\u2019",highlight:null,maxNesting:20},components:{core:{rules:["normalize","block","inline","text_join"]},block:{rules:["paragraph"]},inline:{rules:["text"],rules2:["balance_pairs","fragments_join"]}}};var Uc={options:{html:!0,xhtmlOut:!0,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201C\u201D\u2018\u2019",highlight:null,maxNesting:20},components:{core:{rules:["normalize","block","inline","text_join"]},block:{rules:["blockquote","code","fence","heading","hr","html_block","lheading","list","reference","paragraph"]},inline:{rules:["autolink","backticks","emphasis","entity","escape","html_inline","image","link","newline","text"],rules2:["balance_pairs","emphasis","fragments_join"]}}};var Xh={default:qc,zero:jc,commonmark:Uc},eg=/^(vbscript|javascript|file|data):/,tg=/^data:image\/(gif|png|jpeg|webp);/;function ng(e){let t=e.trim().toLowerCase();return eg.test(t)?tg.test(t):!0}var zc=["http:","https:","mailto:"];function sg(e){let t=Gs(e,!0);if(t.hostname&&(!t.protocol||zc.indexOf(t.protocol)>=0))try{t.hostname=dr.toASCII(t.hostname)}catch{}return qo(cs(t))}function og(e){let t=Gs(e,!0);if(t.hostname&&(!t.protocol||zc.indexOf(t.protocol)>=0))try{t.hostname=dr.toUnicode(t.hostname)}catch{}return zs(cs(t),zs.defaultChars+"%")}function vt(e,t){if(!(this instanceof vt))return new vt(e,t);t||Yo(e)||(t=e||{},e="default"),this.inline=new Ic,this.block=new Sc,this.core=new mc,this.renderer=new lc,this.linkify=new _c,this.validateLink=ng,this.normalizeLink=sg,this.normalizeLinkText=og,this.utils=yi,this.helpers=ps({},$i),this.options={},this.configure(e),t&&this.set(t)}vt.prototype.set=function(e){return ps(this.options,e),this};vt.prototype.configure=function(e){let t=this;if(Yo(e)){let n=e;if(e=Xh[n],!e)throw new Error('Wrong `markdown-it` preset "'+n+'", check name')}if(!e)throw new Error("Wrong `markdown-it` preset, can't be empty");return e.options&&t.set(e.options),e.components&&Object.keys(e.components).forEach(function(n){e.components[n].rules&&t[n].ruler.enableOnly(e.components[n].rules),e.components[n].rules2&&t[n].ruler2.enableOnly(e.components[n].rules2)}),this};vt.prototype.enable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(o){n=n.concat(this[o].ruler.enable(e,!0))},this),n=n.concat(this.inline.ruler2.enable(e,!0));let a=e.filter(function(o){return n.indexOf(o)<0});if(a.length&&!t)throw new Error("MarkdownIt. Failed to enable unknown rule(s): "+a);return this};vt.prototype.disable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(o){n=n.concat(this[o].ruler.disable(e,!0))},this),n=n.concat(this.inline.ruler2.disable(e,!0));let a=e.filter(function(o){return n.indexOf(o)<0});if(a.length&&!t)throw new Error("MarkdownIt. Failed to disable unknown rule(s): "+a);return this};vt.prototype.use=function(e){let t=[this].concat(Array.prototype.slice.call(arguments,1));return e.apply(e,t),this};vt.prototype.parse=function(e,t){if(typeof e!="string")throw new Error("Input data should be a String");let n=new this.core.State(e,this,t);return this.core.process(n),n.tokens};vt.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)};vt.prototype.parseInline=function(e,t){let n=new this.core.State(e,this,t);return n.inlineMode=!0,this.core.process(n),n.tokens};vt.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)};var pr=vt;var bs={bad:0,warn:1,info:2};function Se(e){return Number.isFinite(e)?Math.round(e).toLocaleString("en-US"):"-"}function Fe(e){return e==null||!Number.isFinite(e)?"-":e<1e3?`${Math.round(e)}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${Math.round(e/6e4)}m`}function ag(e){return e==="error"?"!":e==="running"?"~":"OK"}function gr(e,t){return t||(e?e.status==="unsupported_cli"?s("insights.unsupported"):e.status==="transcript_missing"?s("insights.noTranscript"):e.status==="parse_error"?s("insights.parseError"):e.status:"-")}function an(e){return String(e.title??"").replace(/^(?:@\S+\s*)+/,"").trim()||String(e.sessionId??"")}function Qc(e){return e==="bad"?s("insights.sevBad"):e==="warn"?s("insights.sevWarn"):s("insights.sevInfo")}function Xc(e,t){let n=s(e);return n===e?t:n}function ig(e){return Xc(`insights.suggestion.${e.id}.title`,e.title)}function kn(e){let t=`insights.phase.${e}`,n=s(t);return n===t?e:n}function Ys(e){return String(e||"unknown").replace(/[^a-z0-9_-]/gi,"-")}function nn(e){return`phase-${Ys(e)}`}function br(e){return!e||e.status!=="ok"?!1:e.agg.failedSpans>0||e.agg.slowSpans>0||e.suggestions.some(t=>t.severity!=="info")}function rg(e){return{session:{sessionId:e.sessionId,cliId:e.cliId,cliSessionId:e.cliSessionId,title:e.title,botName:e.botName,larkAppId:e.larkAppId,workingDir:e.workingDir,status:e.status,lastMessageAt:e.lastMessageAt},report:e.report}}function fr(e,t,n,a=new Set,o={}){let i=n.trim().toLowerCase();return e.filter(r=>{let u=r.session,c=r.report;return o.analyzableOnly&&c?.status!=="ok"||o.project&&Zs(r)!==o.project||o.sinceMs&&Number(u.lastMessageAt??u.spawnedAt??0)<o.sinceMs||a.size&&!a.has(yr(r))||t==="review"&&!br(c)||t==="failed"&&!(c?.status==="ok"&&c.agg.failedSpans>0)||t==="slow"&&!(c?.status==="ok"&&c.agg.slowSpans>0)?!1:i?`${an(u)} ${De(u)} ${u.cliId??""} ${u.workingDir??""} ${u.sessionId??""}`.toLowerCase().includes(i):!0})}function yr(e){return String(e.session.cliId??"unknown")}var Gc=["claude-code","seed","relay","aiden","codex","traex","antigravity"];function lg(e){let t=new Map;for(let n of e){let a=yr(n);t.set(a,(t.get(a)??0)+1)}return[...t.entries()].map(([n,a])=>({id:n,count:a})).sort((n,a)=>{let o=Gc.indexOf(n.id),i=Gc.indexOf(a.id);return(o<0?99:o)-(i<0?99:i)||n.id.localeCompare(a.id)})}function ug(e,t){let n=lg(e);if(n.length<=1)return"";let a=(o,i,r,u)=>`<button type="button" class="spanchip${u?" on":""}" data-clifilter="${l(o)}">${l(i)} <b>${r}</b></button>`;return[a("all",s("common.all"),e.length,t.size===0),...n.map(o=>a(o.id,o.id,o.count,t.has(o.id)))].join("")}function sn(e,t,n=""){return`<div class="card"><div class="cv">${l(t)}</div><div class="cl">${l(e)}</div>${n?`<div class="cs">${l(n)}</div>`:""}</div>`}var ed=["research","edit","run","delegate","discuss"];function cg(e){let t={totalSpans:0,failedSpans:0,slowSpans:0,failByTool:{},phase:{research:{count:0,ms:0},edit:{count:0,ms:0},run:{count:0,ms:0},delegate:{count:0,ms:0},discuss:{count:0,ms:0}},readWriteRatio:null,compactions:0,subagentCostShare:null},n=0,a=new Map;for(let i of e){let r=i.report;if(!r||r.status!=="ok")continue;n+=1;let u=r.agg;t.totalSpans+=u.totalSpans,t.failedSpans+=u.failedSpans,t.slowSpans+=u.slowSpans,t.compactions+=u.compactions;for(let[c,p]of Object.entries(u.failByTool??{}))t.failByTool[c]=(t.failByTool[c]??0)+p;for(let c of ed){let p=u.phase?.[c];p&&(t.phase[c].count+=p.count,t.phase[c].ms+=p.ms)}for(let c of r.suggestions??[]){let p=a.get(c.id);p?p.count+=1:a.set(c.id,{id:c.id,title:c.title,severity:c.severity,count:1,evidence:c.evidence??[],action:c.action})}}t.readWriteRatio=t.phase.edit.count>0?Number((t.phase.research.count/t.phase.edit.count).toFixed(2)):null;let o=Object.entries(t.failByTool).map(([i,r])=>({tool:i,count:r})).sort((i,r)=>r.count-i.count).slice(0,5);return{totalCount:e.length,analyzedCount:n,agg:t,topFailedTools:o,suggestions:[...a.values()]}}function vr(){return`<p class="insight-disclosure">\u2696\uFE0E ${l(s("insights.disclosure"))}</p>`}function dg(e){let t=e.agg,n=t.readWriteRatio===null?"-":t.readWriteRatio.toFixed(1),a=e.topFailedTools.slice(0,5),o=[...e.suggestions].sort((i,r)=>bs[i.severity]-bs[r.severity]||r.count-i.count).slice(0,6);return`
|
|
2172
|
-
<div class="cards insights-metrics">
|
|
2173
|
-
${sn(s("insights.metricSessions"),Se(e.totalCount),s("insights.metricAnalyzed",{count:e.analyzedCount}))}
|
|
2174
|
-
${sn(s("insights.metricSpans"),Se(t.totalSpans),s("insights.metricSafe"))}
|
|
2175
|
-
${sn(s("insights.metricFailed"),Se(t.failedSpans),a[0]?`${a[0].tool} \xD7${a[0].count}`:"")}
|
|
2176
|
-
${sn(s("insights.metricSlow"),Se(t.slowSpans))}
|
|
2177
|
-
${sn(s("insights.metricRw"),n,s("insights.metricCompactions",{count:t.compactions}))}
|
|
2178
|
-
</div>
|
|
2179
|
-
<div class="insights-overview-grid">
|
|
2180
|
-
<section class="block recblock">
|
|
2181
|
-
<h3>${l(s("insights.recommendations"))}</h3>
|
|
2182
|
-
<div class="reclist">
|
|
2183
|
-
${o.length?o.map(i=>`
|
|
2184
|
-
<div class="rec ${i.severity}">
|
|
2185
|
-
<div class="rectop"><b>${l(ig(i))}</b><span>${l(Qc(i.severity))}</span></div>
|
|
2186
|
-
<div class="recev">${l(s("insights.seenInSessions",{count:i.count}))}</div>
|
|
2187
|
-
</div>`).join(""):`<p class="mut">${l(s("insights.noRecommendations"))}</p>`}
|
|
2188
|
-
</div>
|
|
2189
|
-
</section>
|
|
2190
|
-
<section class="block">
|
|
2191
|
-
<h3>${l(s("insights.toolFailures"))}</h3>
|
|
2192
|
-
<div class="hbars">
|
|
2193
|
-
${a.length?a.map(i=>{let r=Math.max(4,Math.round(i.count/Math.max(1,a[0].count)*100));return`<div class="hbrow"><div class="hblabel">${l(i.tool)}</div><div class="hbtrack"><div class="hbfill" style="width:${r}%"></div></div><div class="hbval">${Se(i.count)}</div></div>`}).join(""):`<p class="mut">${l(s("insights.noFailures"))}</p>`}
|
|
2194
|
-
</div>
|
|
2195
|
-
</section>
|
|
2196
|
-
</div>
|
|
2197
|
-
${vr()}`}function td(e){let t=Object.entries(e??{}).filter(([,n])=>n.count>0||n.ms>0);return t.length?`<div class="mph">${t.map(([n,a])=>{let o=Math.max(1,a.ms||a.count);return`<i class="${nn(n)}" style="flex:${o}" title="${l(`${kn(n)} \xB7 ${a.count} \xB7 ${Fe(a.ms)}`)}"></i>`}).join("")}</div>`:""}function nd(e){return td(e.agg.phase)}function pg(e){let t=e.subagents??[];if(!t.length)return"";let n=t.reduce((o,i)=>o+i.durationMs,0),a=t.map(o=>`<div class="sublane${o.failures?" bad":""}">
|
|
2198
|
-
<div class="sublane-head">
|
|
2199
|
-
<span class="sublane-type">${l(o.agentType)}</span>
|
|
2200
|
-
<span class="sublane-task">${l(o.task?.text??"")}${o.task?.truncated?"\u2026":""}</span>
|
|
2201
|
-
</div>
|
|
2202
|
-
${td(o.phase)}
|
|
2203
|
-
<div class="sublane-stats">
|
|
2204
|
-
<span>${Se(o.spans)} ${l(s("insights.spansShort"))}</span>
|
|
2205
|
-
<span>${l(Fe(o.durationMs))}</span>
|
|
2206
|
-
${o.failures?`<span class="bad">${Se(o.failures)} ${l(s("insights.failedShort"))}</span>`:""}
|
|
2207
|
-
</div>
|
|
2208
|
-
</div>`).join("");return`<section class="block subagent-block">
|
|
2209
|
-
<h3>${l(s("insights.subagents"))} <span class="mut">\xB7 ${t.length} \xB7 ${l(Fe(n))}</span></h3>
|
|
2210
|
-
<p class="mut ins-hint">${l(s("insights.subagentsHint"))}</p>
|
|
2211
|
-
<div class="sublanes">${a}</div>
|
|
2212
|
-
</section>`}var sd=[{key:"overview",label:"insights.tabOverview"},{key:"sessions",label:"insights.tabSessions"},{key:"flow",label:"insights.tabFlow"},{key:"dist",label:"insights.tabDist"},{key:"hot",label:"insights.tabHot"}];function fg(e){return`<div class="insight-tabs" role="tablist">${sd.map(t=>`<button type="button" class="itab${t.key===e?" on":""}" data-itab="${t.key}" role="tab" aria-selected="${t.key===e}">${l(s(t.label))}</button>`).join("")}</div>`}function Zs(e){let t=String(e.session.workingDir??"").replace(/\/+$/,"");return t?t.split("/").pop()||t:""}function mg(e){let t=new Map;for(let n of e){let a=Zs(n);a&&t.set(a,(t.get(a)??0)+1)}return[...t.entries()].map(([n,a])=>({id:n,count:a})).sort((n,a)=>a.count-n.count||n.id.localeCompare(a.id))}var Wc=[{key:"all",label:"insights.timeAll",days:0},{key:"1d",label:"insights.time1d",days:1},{key:"7d",label:"insights.time7d",days:7},{key:"30d",label:"insights.time30d",days:30}];function qn(e){return ed.reduce((t,n)=>t+(e.agg.phase?.[n]?.ms??0),0)}function hg(e){return e.map(t=>t.report).filter(t=>!!t&&t.status==="ok")}function gg(e){if(!e.length)return 0;let t=[...e].sort((a,o)=>a-o),n=Math.floor(t.length/2);return t.length%2?t[n]:(t[n-1]+t[n])/2}function gs(e,t,n,a=Se,o){let i=n.map(f=>({label:f.label,count:t.filter(f.test).length})),r=Math.max(1,...i.map(f=>f.count)),u=Math.max(1,t.length),c=i.map(f=>{let h=Math.max(f.count?4:0,Math.round(f.count/r*100)),y=Math.round(f.count/u*100);return`<div class="hbrow"><div class="hblabel">${l(f.label)}</div><div class="hbtrack"><div class="hbfill" style="width:${h}%"></div></div><div class="hbval">${Se(f.count)}<small>${y}%</small></div></div>`}).join(""),p=o?`<button type="button" class="ihist-jump" data-distsort="${o}">${l(s("insights.viewSessions"))} \u203A</button>`:"";return`<section class="block ihist">
|
|
2213
|
-
<div class="ihist-head"><h3>${l(e)}</h3><span class="mut">${l(s("insights.distMedian",{v:a(gg(t))}))}</span>${p}</div>
|
|
2214
|
-
<div class="hbars">${c}</div>
|
|
2215
|
-
</section>`}function bg(e){let a=Date.now(),o=new Array(28).fill(0);for(let c of e){let p=Number(c.session.lastMessageAt??0);if(!p)continue;let f=Math.floor((a-p)/864e5);f>=0&&f<28&&o[27-f]++}let i=o.reduce((c,p)=>c+p,0);if(!i)return"";let r=Math.max(1,...o),u=o.map((c,p)=>{let f=new Date(a-(27-p)*864e5),h=`${f.getMonth()+1}-${f.getDate()} \xB7 ${c}`;return`<i class="trendbar" style="height:${c?Math.max(8,Math.round(c/r*100)):2}%" title="${l(h)}"></i>`}).join("");return`<section class="block trend-block">
|
|
2216
|
-
<div class="ihist-head"><h3>${l(s("insights.distTrend"))}</h3><span class="mut">${l(s("insights.distTrendSub"))} \xB7 ${i}</span></div>
|
|
2217
|
-
<div class="trend">${u}</div>
|
|
2218
|
-
</section>`}function yg(e){let t=hg(e);if(!t.length)return`<div class="insight-empty">${l(s("insights.distEmpty"))}</div>`;let n=t.map(c=>(c.hot?.files??[]).reduce((p,f)=>p+(f.added??0)+(f.removed??0),0)),a=t.map(c=>c.agg.totalSpans),o=t.map(c=>c.agg.failedSpans),i=t.map(c=>c.agg.slowSpans),r=t.map(c=>qn(c)/6e4),u=t.map(c=>c.agg.readWriteRatio).filter(c=>c!==null&&Number.isFinite(c));return`<p class="mut ins-hint">${l(s("insights.distHint"))}</p>
|
|
2219
|
-
<div class="ihist-grid">
|
|
2220
|
-
${bg(e)}
|
|
2221
|
-
${gs(s("insights.distSpans"),a,[{label:"0\u201310",test:c=>c<=10},{label:"11\u201350",test:c=>c>10&&c<=50},{label:"51\u2013200",test:c=>c>50&&c<=200},{label:"201\u2013500",test:c=>c>200&&c<=500},{label:"500+",test:c=>c>500}],Se,"spans")}
|
|
2222
|
-
${gs(s("insights.distFailed"),o,[{label:"0",test:c=>c===0},{label:"1\u20132",test:c=>c>=1&&c<=2},{label:"3\u20135",test:c=>c>=3&&c<=5},{label:"6\u201310",test:c=>c>=6&&c<=10},{label:"10+",test:c=>c>10}],Se,"fails")}
|
|
2223
|
-
${gs(s("insights.distSlow"),i,[{label:"0",test:c=>c===0},{label:"1\u20132",test:c=>c>=1&&c<=2},{label:"3\u20135",test:c=>c>=3&&c<=5},{label:"5+",test:c=>c>5}],Se,"slow")}
|
|
2224
|
-
${gs(s("insights.distAgentTime"),r,[{label:"<1m",test:c=>c<1},{label:"1\u20135m",test:c=>c>=1&&c<5},{label:"5\u201330m",test:c=>c>=5&&c<30},{label:"30m\u20132h",test:c=>c>=30&&c<120},{label:"2h+",test:c=>c>=120}],c=>`${Math.round(c)}m`,"agent")}
|
|
2225
|
-
${u.length?gs(s("insights.distRw"),u,[{label:"0",test:c=>c===0},{label:"0\u20131",test:c=>c>0&&c<1},{label:"1\u20133",test:c=>c>=1&&c<3},{label:"3+",test:c=>c>=3}],c=>c.toFixed(1)):""}
|
|
2226
|
-
${gs(s("insights.distChurn"),n,[{label:"0",test:c=>c===0},{label:"1\u2013100",test:c=>c>0&&c<=100},{label:"100\u20131k",test:c=>c>100&&c<=1e3},{label:"1k\u201310k",test:c=>c>1e3&&c<=1e4},{label:"10k+",test:c=>c>1e4}])}
|
|
2227
|
-
</div>
|
|
2228
|
-
${vr()}`}var wn=["research","edit","run","delegate","discuss"];function vg(e){let t=e.filter(c=>c.report&&c.report.status==="ok"&&c.report.agg);if(!t.length)return`<div class="insight-empty">${l(s("insights.distEmpty"))}</div>`;let n={};for(let c of wn)n[c]={count:0,ms:0};for(let c of t)for(let p of wn){let f=c.report.agg.phase?.[p];f&&(n[p].count+=f.count,n[p].ms+=f.ms)}let a=wn.reduce((c,p)=>c+n[p].count,0)||1,o=wn.reduce((c,p)=>c+n[p].ms,0)||1,i=wn.map((c,p)=>{let f=n[c],h=Math.round(f.count/a*100),y=Math.round(f.ms/o*100),g=p<wn.length-1?'<span class="flow-arrow">\u2192</span>':"";return`<div class="flow-node"><i class="flow-dot ${nn(c)}"></i>
|
|
2229
|
-
<strong>${l(kn(c))}</strong>
|
|
2230
|
-
<span class="flow-n">${Se(f.count)}<em> \xB7 ${h}%</em></span>
|
|
2231
|
-
<span class="flow-t">${l(Fe(f.ms))}<em> \xB7 ${y}%</em></span></div>${g}`}).join(""),r=wn.map(c=>{let p=n[c],f=p.count/a*100,h=p.ms/o*100;return`<div class="flow-brow">
|
|
2232
|
-
<span class="flow-blabel"><i class="${nn(c)}"></i>${l(kn(c))}</span>
|
|
2233
|
-
<span class="flow-btrack"><span class="flow-bfill ${nn(c)}" style="width:${Math.max(2,f).toFixed(1)}%"></span><em>${Math.round(f)}%</em></span>
|
|
2234
|
-
<span class="flow-btrack"><span class="flow-bfill ${nn(c)}" style="width:${Math.max(2,h).toFixed(1)}%"></span><em>${Math.round(h)}%</em></span>
|
|
2235
|
-
</div>`}).join(""),u=[...t].sort((c,p)=>qn(p.report)-qn(c.report)).slice(0,40).map(c=>`<button type="button" class="flow-sess" data-session-id="${l(String(c.session.sessionId))}">
|
|
2236
|
-
<span class="flow-stitle">${l(an(c.session))}</span>
|
|
2237
|
-
${nd(c.report)}
|
|
2238
|
-
<span class="flow-stime">${l(Fe(qn(c.report)))}</span></button>`).join("");return`<p class="mut ins-hint">${l(s("insights.flowHint"))}</p>
|
|
2239
|
-
<section class="block flow-pipe-block">
|
|
2240
|
-
<h3>${l(s("insights.flowPipeline"))}</h3>
|
|
2241
|
-
<p class="mut flow-sub">${l(s("insights.flowPipeSub"))}</p>
|
|
2242
|
-
<div class="flow-pipe">${i}</div>
|
|
2243
|
-
</section>
|
|
2244
|
-
<div class="insights-overview-grid">
|
|
2245
|
-
<section class="block">
|
|
2246
|
-
<h3>${l(s("insights.flowShares"))}</h3>
|
|
2247
|
-
<div class="flow-bhead"><span></span><span>${l(s("insights.flowActShare"))}</span><span>${l(s("insights.flowTimeShare"))}</span></div>
|
|
2248
|
-
<div class="flow-bars">${r}</div>
|
|
2249
|
-
</section>
|
|
2250
|
-
<section class="block">
|
|
2251
|
-
<h3>${l(s("insights.flowRhythm"))}</h3>
|
|
2252
|
-
<div class="flow-rhythm">${u}</div>
|
|
2253
|
-
<div class="rl-legend">${wn.map(c=>`<span class="rl-item"><i class="${nn(c)}"></i>${l(kn(c))}</span>`).join("")}</div>
|
|
2254
|
-
</section>
|
|
2255
|
-
</div>
|
|
2256
|
-
${vr()}`}function Vc(e,t){let n=e.filter($=>!!$.report&&$.report.status==="ok");if(!n.length)return`<div class="insight-empty">${l(s("insights.distEmpty"))}</div>`;let a=new Map,o=new Map,i=new Map,r=($,L,C,P,H)=>{let q=$.get(L);return q||(q={key:L,label:C,sessions:[],reads:0,edits:0,runs:0,fails:0,count:0},$.set(L,q)),q.sessions.some(I=>I.id===P)||q.sessions.push({id:P,title:H}),q};for(let $ of n){let L=String($.session.sessionId),C=an($.session),P=$.report.hot;for(let H of P?.files??[]){let q=r(a,`file:${H.path}`,H.path,L,C);q.reads+=H.reads,q.edits+=H.edits}for(let H of P?.cmds??[]){let q=r(o,`cmd:${H.cmd}`,H.cmd,L,C);q.runs+=H.runs,q.fails+=H.fails}for(let H of P?.errs??[]){let q=r(i,`err:${H.tool} ${H.result}`,`${H.tool} \xB7 ${ys(H.result)}`,L,C);q.count+=H.count}}let u=($,L)=>L.sessions.length-$.sessions.length,c=[...a.values()].sort(($,L)=>u($,L)||L.edits+L.reads-($.edits+$.reads)).slice(0,12),p=[...o.values()].sort(($,L)=>u($,L)||L.fails-$.fails||L.runs-$.runs).slice(0,12),f=[...i.values()].sort(($,L)=>u($,L)||L.count-$.count).slice(0,10),h=($,L,C)=>`
|
|
2257
|
-
<section class="block">
|
|
2258
|
-
<h3>${l($)}</h3>
|
|
2259
|
-
<div class="hotlist">${L.length?L.map(P=>{let H=t.has(P.key),q=H?`<div class="hot-sess">${P.sessions.map(I=>`<button type="button" class="hot-sesslink" data-session-id="${l(I.id)}">${l(I.title||I.id)}</button>`).join("")}</div>`:"";return`<div class="hotitem${H?" open":""}">
|
|
2260
|
-
<button type="button" class="hotrow" data-hotkey="${l(P.key)}" aria-expanded="${H}">
|
|
2261
|
-
<span class="hotlabel" title="${l(P.label)}">${l(P.label)}</span>
|
|
2262
|
-
<span class="hotmeta">${C(P)}</span>
|
|
2263
|
-
<span class="hotses">${P.sessions.length} ${l(s("insights.hotSessionsCol"))}</span>
|
|
2264
|
-
</button>${q}
|
|
2265
|
-
</div>`}).join(""):'<p class="mut">-</p>'}</div>
|
|
2266
|
-
</section>`,y=new Map;for(let $ of n){let L=Zs($);if(!L)continue;let C=y.get(L)??{sessions:0,fails:0};C.sessions+=1,C.fails+=$.report.agg.failedSpans,y.set(L,C)}let g=[...y.entries()].map(([$,L])=>({id:$,...L})).sort(($,L)=>L.fails-$.fails||L.sessions-$.sessions).slice(0,10),v=Math.max(1,...g.map($=>$.sessions)),M=[...n].filter($=>$.report.agg.slowSpans>0).sort(($,L)=>L.report.agg.slowSpans-$.report.agg.slowSpans).slice(0,8);return`<p class="mut ins-hint">${l(s("insights.hotHint"))}</p>
|
|
2267
|
-
<div class="hot-grid">
|
|
2268
|
-
${h(s("insights.hotFiles"),c,$=>`${l(s("insights.readsShort"))}${$.reads} \xB7 ${l(s("insights.editsShort"))}${$.edits}`)}
|
|
2269
|
-
${h(s("insights.hotCommands"),p,$=>`${$.runs}\xD7${$.fails?` \xB7 <span class="bad">${$.fails} ${l(s("insights.hotFailsCol"))}</span>`:""}`)}
|
|
2270
|
-
${h(s("insights.hotErrors"),f,$=>`${$.count}\xD7`)}
|
|
2271
|
-
<section class="block">
|
|
2272
|
-
<h3>${l(s("insights.hotProjects"))}</h3>
|
|
2273
|
-
<div class="hbars">${g.length?g.map($=>{let L=Math.max(4,Math.round($.sessions/v*100));return`<button type="button" class="hbrow hbrow-click" data-hotproject="${l($.id)}"><div class="hblabel">${l($.id)}</div><div class="hbtrack"><div class="hbfill" style="width:${L}%"></div></div><div class="hbval">${Se($.sessions)}<small>${$.fails} ${l(s("insights.hotFailsCol"))}</small></div></button>`}).join(""):'<p class="mut">-</p>'}</div>
|
|
2274
|
-
</section>
|
|
2275
|
-
<section class="block hot-sessions">
|
|
2276
|
-
<h3>${l(s("insights.hotSlowSessions"))}</h3>
|
|
2277
|
-
<div class="slist">${M.length?M.map($=>{let L=$.report.agg;return`<button type="button" class="srow" data-session-id="${l(String($.session.sessionId))}">
|
|
2278
|
-
<div class="srmain"><strong>${l(an($.session))}</strong>
|
|
2279
|
-
<small>${l(De($.session))} \xB7 ${l(String($.session.cliId??"-"))}</small></div>
|
|
2280
|
-
<div class="srstats"><b>${l(s("insights.hotSlowCol"))}<em>${Se(L.slowSpans)}</em></b><b>span<em>${Se(L.totalSpans)}</em></b></div>
|
|
2281
|
-
</button>`}).join(""):'<p class="mut">-</p>'}</div>
|
|
2282
|
-
</section>
|
|
2283
|
-
</div>`}var wg=[{key:"recent",label:"insights.sortRecent"},{key:"review",label:"insights.sortReview"},{key:"spans",label:"insights.sortSpans"},{key:"fails",label:"insights.sortFails"},{key:"slow",label:"insights.sortSlow"},{key:"agent",label:"insights.sortAgent"}];function kg(e,t){let n=`<span class="sesssort-label mut">${l(s("insights.sortLabel"))}</span>`+wg.map(o=>`<button type="button" class="spanchip${o.key===e?" on":""}" data-sesssort="${o.key}">${l(s(o.label))}</button>`).join(""),a='<span class="sesssort-sep"></span>'+[["card","insights.layoutCard"],["table","insights.layoutTable"]].map(([o,i])=>`<button type="button" class="spanchip${t===o?" on":""}" data-sesslayout="${o}">${l(s(i))}</button>`).join("");return n+a}function $g(e){return e?.status==="ok"?e.agg.failedSpans*6+e.agg.slowSpans*3+e.suggestions.filter(t=>t.severity==="bad").length*5:0}function xg(e,t){let n=o=>Number(o.session.lastMessageAt??0),a=o=>{let i=o.report,r=i?.status==="ok"?i.agg:null;switch(t){case"spans":return r?.totalSpans??-1;case"fails":return r?.failedSpans??-1;case"slow":return r?.slowSpans??-1;case"agent":return i?.status==="ok"?qn(i):-1;case"review":return $g(i);default:return 0}};return[...e].sort((o,i)=>t==="recent"?n(i)-n(o):a(i)-a(o)||n(i)-n(o))}function Sg(e,t,n=!1){if(!e.length)return`<div class="insight-empty">${l(s("insights.empty"))}</div>`;let a=(o,i,r=!1)=>`<b${r?' class="bad"':""}>${l(o)}<em>${l(i)}</em></b>`;return`<div class="slist${n?" wide":""}">${e.map(o=>{let i=o.session,r=o.report,u=r?.status==="ok",c=r?.agg,p=i.sessionId===t?" on":"",f=br(r)?" review":"",h=c?.phase?.research?.count??0,y=c?.phase?.edit?.count??0;return`<button type="button" class="srow${p}${f}" data-session-id="${l(String(i.sessionId))}">
|
|
2284
|
-
<div class="srmain">
|
|
2285
|
-
<strong>${l(an(i))}</strong>
|
|
2286
|
-
<small>${l(De(i))} \xB7 ${l(String(i.cliId??"-"))}${i.workingDir?` \xB7 ${l(Zs(o))}`:""} \xB7 ${l(at(i.lastMessageAt??i.spawnedAt??0))}</small>
|
|
2287
|
-
${u?nd(r):""}
|
|
2288
|
-
</div>
|
|
2289
|
-
${u?`<div class="srstats">
|
|
2290
|
-
${a(s("insights.spansShort"),Se(c.totalSpans))}
|
|
2291
|
-
${a(s("insights.failedShort"),Se(c.failedSpans),c.failedSpans>0)}
|
|
2292
|
-
${a(s("insights.slowShort"),Se(c.slowSpans))}
|
|
2293
|
-
${n?a(s("insights.readsShort"),Se(h))+a(s("insights.editsShort"),Se(y))+a(s("insights.durShort"),Fe(qn(r))):""}
|
|
2294
|
-
${a(s("insights.rwShort"),c.readWriteRatio!==null?c.readWriteRatio.toFixed(1):"-")}
|
|
2295
|
-
</div>`:`<div class="srmsg">${l(gr(r,o.error))}</div>`}
|
|
2296
|
-
</button>`}).join("")}</div>`}function Eg(e,t){if(!e.length)return`<div class="insight-empty">${l(s("insights.empty"))}</div>`;let n=`<div class="strow sthead">
|
|
2297
|
-
<span class="stc-title">${l(s("insights.colTitle"))}</span>
|
|
2298
|
-
<span class="stc-proj">${l(s("insights.colProject"))}</span>
|
|
2299
|
-
<span class="stc-num">${l(s("insights.spansShort"))}</span>
|
|
2300
|
-
<span class="stc-num">${l(s("insights.failedShort"))}</span>
|
|
2301
|
-
<span class="stc-num">${l(s("insights.slowShort"))}</span>
|
|
2302
|
-
<span class="stc-num">${l(s("insights.rwShort"))}</span>
|
|
2303
|
-
<span class="stc-num">${l(s("insights.durShort"))}</span>
|
|
2304
|
-
<span class="stc-num">${l(s("insights.colTime"))}</span>
|
|
2305
|
-
</div>`,a=e.map(o=>{let i=o.session,r=o.report,u=r?.status==="ok",c=r?.agg,p=i.sessionId===t?" on":"",f=br(r)?" review":"",h=u?`<span class="stc-num">${Se(c.totalSpans)}</span>
|
|
2306
|
-
<span class="stc-num${c.failedSpans?" bad":""}">${Se(c.failedSpans)}</span>
|
|
2307
|
-
<span class="stc-num">${Se(c.slowSpans)}</span>
|
|
2308
|
-
<span class="stc-num">${c.readWriteRatio!==null?c.readWriteRatio.toFixed(1):"-"}</span>
|
|
2309
|
-
<span class="stc-num">${l(Fe(qn(r)))}</span>`:`<span class="stc-msg">${l(gr(r,o.error))}</span>`;return`<button type="button" class="strow${p}${f}${u?"":" nostat"}" data-session-id="${l(String(i.sessionId))}">
|
|
2310
|
-
<span class="stc-title"><strong>${l(an(i))}</strong><small>${l(De(i))} \xB7 ${l(String(i.cliId??"-"))}</small></span>
|
|
2311
|
-
<span class="stc-proj">${l(i.workingDir?Zs(o):"-")}</span>
|
|
2312
|
-
${h}
|
|
2313
|
-
<span class="stc-num stc-time">${l(at(i.lastMessageAt??i.spawnedAt??0))}</span>
|
|
2314
|
-
</button>`}).join("");return`<div class="stable">${n}${a}</div>`}function od(e){let t=`insights.intent.${e}`,n=s(t);return n===t?e:n}function ys(e){let t=`insights.result.${e}`,n=s(t);return n===t?e:n}function jn(e){let t=`insights.tag.${e}`,n=s(t);return n===t?e:n}function on(e,t){let n=`insights.${e}.${t.id}`,a=s(n,t.params);return a===n?t.id:a}var Tg=e=>on("turnHeadline",e),Kc={"shell command":"insights.struct.shell","file edit":"insights.struct.fileEdit","read/search":"insights.struct.readSearch","agent task":"insights.struct.agentTask","tool input":"insights.struct.toolInput","tool result":"insights.struct.toolResult","tool error":"insights.struct.toolError","patch failed":"insights.struct.patchFailed","patch applied":"insights.struct.patchApplied"};function Jc(e){if(!e)return"";let t=e.match(/^exit (-?\d+)$/);return t?s("insights.struct.exit",{code:t[1]}):Kc[e]?Xc(Kc[e],e):e}var Js=new Set(["tool_error","test_failed","typecheck_failed","lint_failed","command_failed","timeout","no_output"]);function Lg(e){return e.status==="error"||!!e.result&&Js.has(e.result.category)}function wr(e,t){return e&&e.kind!=="unknown"?od(e.kind):t}function ad(e){return wr(e.intent,e.tool)}function mr(e){return e?[e.kind!=="unknown"?od(e.kind):"",e.subject,e.detail].filter(Boolean).join(" \xB7 "):""}var Cg=["failure","retry","read_write_imbalance","slow"];function Ig(e){for(let t of Cg)if(e.includes(t)){let n=s(`insights.advice.${t}`);if(n!==`insights.advice.${t}`)return n}return""}function Mg(e,t){let n=e.spans??[],a=t?(e.recommendations??[]).find(i=>i.id===t)??null:null;if(!a)return{rec:null,spanIdx:new Set,turnIdx:new Set};let o=(a.evidence?.spanIndexes??[]).filter(i=>Number.isInteger(i)&&i>=0&&i<n.length);return{rec:a,spanIdx:new Set(o),turnIdx:new Set(a.evidence?.turnIndexes??[])}}function Ag(e,t){let n=e.recommendations??[];return n.length?`<div class="reclist">${[...n].sort((o,i)=>bs[o.severity]-bs[i.severity]).map(o=>{let i=o.id===t,r=(o.evidence?.spanIndexes?.length??0)>0||(o.evidence?.turnIndexes?.length??0)>0,u=on("impact",o.impact),c=on("why",o.why),p=o.nextActions.map(h=>`<li>${l(on("action",h))}</li>`).join(""),f=r?`<span class="rec-cta">${l(i?s("insights.diagActive"):s("insights.diagShow"))}</span>`:"";return`<button type="button" class="rec ${o.severity}${r?" rec-clickable":""}${i?" active":""}" data-rec="${l(o.id)}">
|
|
2315
|
-
<div class="rectop"><b>${l(on("rec",{id:o.id,params:{}}))}</b><span>${l(Qc(o.severity))}</span></div>
|
|
2316
|
-
${u?`<div class="rec-impact">${l(u)}</div>`:""}
|
|
2317
|
-
${p?`<ul class="rec-actions">${p}</ul>`:""}
|
|
2318
|
-
${c?`<div class="rec-why">${l(c)}</div>`:""}
|
|
2319
|
-
${f}
|
|
2320
|
-
</button>`}).join("")}</div>`:`<p class="mut">${l(s("insights.noRecommendations"))}</p>`}function Dg(e,t){let n=`${ad(e)}${e.intent?.subject?` ${e.intent.subject}`:""}${e.result?` \u2192 ${ys(e.result.category)}`:""} \xB7 ${Fe(e.durationMs)}`;return`<i class="op ph-${l(Ys(e.phase))}${Lg(e)?" bad":""}${t?" cur":""}" title="${l(n)}"></i>`}function id(e,t,n,a,o=!0){let i=e[t],r=i.intent?.subject?`<code class="span-subj">${l(i.intent.subject)}</code>`:"",u=i.result,c=u&&Js.has(u.category)?`<span class="span-res rc-bad">${l(ys(u.category))}${u.exitCode!==void 0?` \xB7 exit ${u.exitCode}`:""}</span>`:"",f=(i.tags??[]).filter(g=>g!=="normal"&&g!=="diagnostic").map(g=>`<span class="span-tag tg-${l(g)}">${l(jn(g))}</span>`).join(""),h=o?`<span class="span-detail-btn" aria-hidden="true">${l(a?s("insights.dCollapse"):s("insights.dDetail"))}</span>`:"",y=o?` data-span-idx="${t}" role="button" tabindex="0" aria-expanded="${a}"`:"";return`<div class="spanrow ph-${l(Ys(i.phase))}${i.status==="error"?" error":""}${n?" hot":""}${a?" open":""}">
|
|
2321
|
-
<div class="sprow-line${o?" clickable":""}"${y}>
|
|
2322
|
-
<span class="span-turn" title="${l(`${s("insights.dStart")} ${Fe(i.relStartMs)}`)}">#${l(String(i.turnIndex??0))}</span>
|
|
2323
|
-
<span class="spanst ${l(i.status)}">${l(ag(i.status))}</span>
|
|
2324
|
-
<b class="span-what">${l(ad(i))}</b>${r}
|
|
2325
|
-
${c}
|
|
2326
|
-
<span class="span-tags">${f}</span>
|
|
2327
|
-
<span class="span-dur">${l(Fe(i.durationMs))}</span>
|
|
2328
|
-
${h}
|
|
2329
|
-
</div>
|
|
2330
|
-
${o&&a?Hg(e,t):""}
|
|
2331
|
-
</div>`}function oa(e,t){return t?.text?`<div class="span-io"><span class="span-io-label">${l(e)}</span><pre class="span-io-text">${l(t.text)}${t.truncated?`
|
|
2332
|
-
\u2026`:""}</pre></div>`:""}function Hg(e,t){let n=e[t],a=n.detail,o=a?.evidence??n.evidence,i=o?`${oa(s("insights.dCommand"),o.command)}${oa(s("insights.dCmdOutput"),o.output)}`:"",r=[[s("insights.dPhase"),kn(n.phase)],[s("insights.dStart"),Fe(n.relStartMs)],[s("insights.dDur"),Fe(n.durationMs)]],u=mr(n.intent);u&&r.push([s("insights.dIntent"),u]),n.result&&r.push([s("insights.dResult"),`${ys(n.result.category)}${n.result.exitCode!==void 0?` \xB7 exit ${n.result.exitCode}`:""}`]),n.inputSummary&&r.push([s("insights.dIn"),Jc(n.inputSummary)]),n.outputSummary&&r.push([s("insights.dOut"),Jc(n.outputSummary)]);let c=(n.tags??[]).filter(v=>v!=="normal");c.length&&r.push([s("insights.dTags"),c.map(jn).join("\u3001")]);let p=a?.context?.previousIntent?mr(a.context.previousIntent):"",f=a?.context?.nextIntent?mr(a.context.nextIntent):"",h=p||f?`<div class="span-flank">${p?`<span class="sf-prev">\u2191 ${l(p)}</span>`:""}${f?`<span class="sf-next">\u2193 ${l(f)}</span>`:""}</div>`:"",g=e.map((v,M)=>({sp:v,i:M})).filter(v=>v.sp.turnIndex===n.turnIndex).sort((v,M)=>(v.sp.relStartMs??0)-(M.sp.relStartMs??0)).map(v=>Dg(v.sp,v.i===t)).join("");return`<div class="spandetail">
|
|
2333
|
-
<dl class="span-kv">${r.map(([v,M])=>`<div><dt>${l(v)}</dt><dd>${l(M)}</dd></div>`).join("")}</dl>
|
|
2334
|
-
${i}
|
|
2335
|
-
${h}
|
|
2336
|
-
<div class="span-ctx"><span class="span-ctx-label">${l(s("insights.dTurnContext",{turn:n.turnIndex}))}</span><div class="opstrip">${g}</div></div>
|
|
2337
|
-
</div>`}var Yc=["failure","slow","retry","read_write_imbalance"];function _g(e){let t=e.workSummary;if(!t||!t.fileChanges?.length&&!t.commandsRun?.length)return"";let n=t.fileChanges??[],a=t.commandsRun??[],o=n.length?n.map(r=>{let u=r.added||r.removed?`<span class="ws-stat"><span class="ws-add">+${r.added??0}</span><span class="ws-del">\u2212${r.removed??0}</span></span>`:r.edits?`<span class="ws-stat ws-stat-edits">${l(s("insights.wsEdits",{n:r.edits}))}</span>`:"";return`<div class="ws-row"><code class="ws-path" title="${l(r.path)}">${l(r.path)}</code><span class="ws-meta">${l(s("insights.wsReads",{n:r.reads}))}</span>${u}</div>`}).join(""):`<p class="mut">${l(s("insights.wsNoFiles"))}</p>`,i=a.length?a.map(r=>{let u=r.failures>0;return`<div class="ws-row${u?" bad":""}"><code class="ws-cmd" title="${l(r.command.text)}">${l(r.command.text)}${r.command.truncated?"\u2026":""}</code><span class="ws-meta">${r.count>1?`<span class="ws-x">\xD7${r.count}</span>`:""}${u?`<span class="ws-fail">${l(s("insights.wsFail",{n:r.failures}))}</span>`:""}</span></div>`}).join(""):`<p class="mut">${l(s("insights.wsNoCmds"))}</p>`;return`<div class="worksum">
|
|
2338
|
-
<section class="ws-panel"><h4>${l(s("insights.wsFiles",{n:n.length}))}</h4><div class="ws-list">${o}</div></section>
|
|
2339
|
-
<section class="ws-panel"><h4>${l(s("insights.wsCmds",{n:a.length}))}</h4><div class="ws-list">${i}</div></section>
|
|
2340
|
-
</div>`}function Rg(e,t,n,a){let o=e.spans??[],i=_g(e);if(!o.length)return`${i}<p class="mut">${l(s("insights.noSpans"))}</p>`;let r=[...o.keys()].sort((g,v)=>(o[g].relStartMs??0)-(o[v].relStartMs??0)),u=new Map;for(let g of r)for(let v of o[g].tags??[])Yc.includes(v)&&u.set(v,(u.get(v)??0)+1);let c=(g,v,M)=>`<button type="button" class="spanchip${g==="all"?"":` tg-${l(g)}`}${n===g?" on":""}" data-spanfilter="${l(g)}">${l(v)} <b>${M}</b></button>`,p=[c("all",s("insights.spanAll"),r.length),...Yc.filter(g=>u.has(g)).map(g=>c(g,jn(g),u.get(g)))].join(""),f=n==="all"?r:r.filter(g=>o[g].tags?.includes(n)),h=t.rec?`<div class="ev-reason">${l(on("why",t.rec.why))}</div>`:"",y=f.length?f.map(g=>id(o,g,t.spanIdx.has(g),a.has(g))).join(""):`<p class="mut">${l(s("insights.evNoFlags"))}</p>`;return`<div class="evidence">${i}${h}<div class="spanfilter">${p}</div><div class="spantable">${y}</div></div>`}function hr(e){if(!e)return`<section class="insight-detail"><p class="mut">${l(s("insights.selectSession"))}</p></section>`;let t=e.session;return`<section class="insight-detail">
|
|
2341
|
-
<div class="shead">
|
|
2342
|
-
<h2>${l(an(t))}</h2>
|
|
2343
|
-
<div class="smeta">${l(De(t))} \xB7 ${l(String(t.cliId??"-"))} \xB7 <code>${l(String(t.sessionId??""))}</code></div>
|
|
2344
|
-
</div>
|
|
2345
|
-
<div id="insight-detail-body"><p class="mut">${l(s("insights.detailLoading"))}</p></div>
|
|
2346
|
-
</section>`}function kr(e){return e.replace(/<(mentions|attachments|available_bots|system-reminder|quoted_messages|sender)\b[\s\S]*?<\/\1>/g," ").replace(/<botmux_reminder>[\s\S]*?<\/botmux_reminder>/g," ").replace(/<\/?(user_message|local-command-[a-z]+)>/g," ").replace(/<sender\b[^>]*\/?>/g," ").replace(/<mention\b[^>]*\/?>/g," ").replace(/\[用户引用了消息[\s\S]*?\]/g," ").replace(/\[来自[^\]]*@mention\]/g," ").replace(/\[(图片|文件)\s*\d+\][^\n]*/g," ").replace(/[ \t]+/g," ").replace(/ *\n */g,`
|
|
2347
|
-
`).replace(/\n{3,}/g,`
|
|
2348
|
-
|
|
2349
|
-
`).trim()}var aa=new pr({html:!1,linkify:!0,breaks:!0});aa.validateLink=e=>/^(https?:|mailto:)/i.test(e.trim());var Zc=aa.renderer.rules.link_open;aa.renderer.rules.link_open=(e,t,n,a,o)=>(e[t].attrSet("target","_blank"),e[t].attrSet("rel","noopener noreferrer nofollow"),Zc?Zc(e,t,n,a,o):o.renderToken(e,t,n));function ia(e){try{return aa.render(e).trim()||`<p>${l(e)}</p>`}catch{return`<p>${l(e)}</p>`}}function Pg(e){let t=e.status==="error"||!!e.result&&Js.has(e.result.category),a=`${wr(e.intent,String(e.label.params.tool??e.kind))}${e.intent?.subject?` ${e.intent.subject}`:""}${e.result?` \u2192 ${ys(e.result.category)}`:""} \xB7 ${Fe(e.durationMs)}`;return`<i class="op ph-${l(Ys(e.phase))}${t?" bad":""}" title="${l(a)}"></i>`}function $r(e){if(!e?.kind)return"";if(e.kind==="a2a_agent"){let n=e.agentName||e.senderName;return`<span class="tp-label tp-src tp-src-a2a">\u{1F91D} ${n?`${l(n)} \xB7 a2a`:"a2a"}</span>`}return e.kind==="system"?`<span class="tp-label tp-src tp-src-system">\u2699\uFE0F ${l(s("insights.senderSystem"))}</span>`:`<span class="tp-label tp-src tp-src-user">\u{1F464} ${(e.senderName?l(e.senderName):"")||l(s("insights.turnPrompt"))}</span>`}function xr(e){let t=(e?.mentionedNames??[]).filter(Boolean);return t.length?`<span class="tp-mentions">${l(s("insights.srcMentions"))} ${t.map(n=>"@"+l(n)).join(" ")}</span>`:""}function Bg(e,t,n){let a=t?.source,o=$r(a)||`<span class="tp-label">${l(s("insights.turnPrompt"))}</span>`,i=xr(a),r=t?.text?kr(t.text)||t.text:"",u=t?.truncated,c=n?`<pre class="tp-raw modal-raw">${l(r)}${u?`
|
|
2350
|
-
\u2026`:""}</pre>`:`<div class="md-body modal-md">${ia(r+(u?" \u2026":""))}</div>`;return`<div class="modal-backdrop" data-modal-close></div>
|
|
2351
|
-
<div class="modal-panel" role="dialog" aria-modal="true" aria-label="${l(s("insights.turnPrompt"))}">
|
|
2352
|
-
<div class="modal-head">
|
|
2353
|
-
<div class="modal-who">${o}${i}<span class="modal-turnno">#${l(String(e))}</span></div>
|
|
2354
|
-
<div class="modal-acts">
|
|
2355
|
-
<button type="button" class="tp-toggle" data-modal-raw>${l(n?s("insights.turnPromptRendered"):s("insights.turnPromptRaw"))}</button>
|
|
2356
|
-
<button type="button" class="modal-close" data-modal-close aria-label="${l(s("insights.modalClose"))}">\xD7</button>
|
|
2357
|
-
</div>
|
|
2358
|
-
</div>
|
|
2359
|
-
<div class="modal-body">${c}${u?`<p class="modal-trunc mut">${l(s("insights.promptTruncated"))}</p>`:""}</div>
|
|
2360
|
-
</div>`}function Og(e,t,n,a,o,i,r,u){let c=o.has(n.turnIndex),p=a.turnIdx.has(n.turnIndex)?" hot":"",f=n.metrics,h=n.severity!=="info"?Ig(n.tags):"",y=n.events.map(Pg).join(""),g=n.prompt?.text?kr(n.prompt.text)||n.prompt.text:"",v=r.has(n.turnIndex),M=u.has(n.turnIndex),$=n.prompt?.truncated?" \u2026":"",L=M?`<pre class="tp-raw">${l(g)}${n.prompt?.truncated?`
|
|
2361
|
-
\u2026`:""}</pre>`:`<div class="md-body">${ia(g+$)}</div>`,C=$r(n.prompt?.source)||`<span class="tp-label">${l(s("insights.turnPrompt"))}</span>`,P=xr(n.prompt?.source),H=g?`<div class="turn-prompt">
|
|
2362
|
-
${C}
|
|
2363
|
-
<div class="tp-body">
|
|
2364
|
-
<div class="tp-md${v?" expanded":""}">${L}</div>
|
|
2365
|
-
<div class="tp-actions">
|
|
2366
|
-
${P}
|
|
2367
|
-
<button type="button" class="tp-toggle" data-prompt-expand="${l(String(n.turnIndex))}">${l(v?s("insights.turnPromptCollapse"):s("insights.turnPromptExpand"))}</button>
|
|
2368
|
-
<button type="button" class="tp-toggle" data-prompt-raw="${l(String(n.turnIndex))}">${l(M?s("insights.turnPromptRendered"):s("insights.turnPromptRaw"))}</button>
|
|
2369
|
-
<button type="button" class="tp-toggle" data-prompt-full="${l(String(n.turnIndex))}">${l(s("insights.turnPromptFull"))}</button>
|
|
2370
|
-
</div>
|
|
2371
|
-
</div>
|
|
2372
|
-
</div>`:"",q=(O,A,R=!1)=>`<span class="tm${R?" bad":""}"><i>${l(O)}</i><b>${l(A)}</b></span>`,I=`${s("insights.mEdits")}${f.edits} ${s("insights.mRuns")}${f.runs}${f.failures?` \xB7 ${s("insights.mFailures")}${f.failures}`:""} \xB7 ${Fe(f.durationMs)}`,N=c?`<div class="turn-detail">
|
|
2373
|
-
<div class="turn-metrics">${q(s("insights.mReads"),String(f.reads))}${q(s("insights.mEdits"),String(f.edits))}${q(s("insights.mRuns"),String(f.runs))}${f.failures?q(s("insights.mFailures"),String(f.failures),!0):""}${q(s("insights.mDur"),Fe(f.durationMs))}</div>
|
|
2374
|
-
<div class="spantable">${n.events.map(O=>id(t,O.spanIndex,!1,i.has(O.spanIndex),!0)).join("")}</div>
|
|
2375
|
-
</div>`:"";return`<div class="turnrow sev-${l(n.severity)}${p}${n.severity!=="info"?" flagged":""}${c?" open":""}" data-turn-card="${l(String(n.turnIndex))}">
|
|
2376
|
-
<div class="turnline">
|
|
2377
|
-
<span class="turn-no">#${l(String(n.turnIndex))}</span>
|
|
2378
|
-
<b class="turn-headline">${l(Tg(n.headline))}</b>
|
|
2379
|
-
<div class="opstrip turn-strip">${y}</div>
|
|
2380
|
-
<span class="turn-mini">${l(I)}</span>
|
|
2381
|
-
<button type="button" class="turn-expand-btn" data-turn="${l(String(n.turnIndex))}" aria-expanded="${c}">${l(c?s("insights.turnCollapse"):s("insights.turnExpand",{count:n.events.length}))}</button>
|
|
2382
|
-
</div>
|
|
2383
|
-
${H}
|
|
2384
|
-
${h?`<div class="turn-advice">${l(h)}</div>`:""}
|
|
2385
|
-
${N}
|
|
2386
|
-
</div>`}function sa(e){return e.prompt?.source?.kind??"user"}function Fg(e,t,n,a,o,i,r,u){let c=e.spans??[],p=e.turnTimeline??[];if(!p.length)return`<p class="mut">${l(s("insights.noSpans"))}</p>`;let f=e.recommendations??[],h=f.some(A=>(A.evidence?.turnIndexes?.length??0)>0),y={user:0,a2a_agent:0,system:0};for(let A of p)y[sa(A)]++;let g=(A,R,B,V="")=>`<button type="button" class="spanchip${V}${u===A?" on":""}" data-ledgersender="${A}">${l(R)} <b>${B}</b></button>`,M=`<div class="spanfilter ledgersender">${[g("all",s("insights.spanAll"),y.user+y.a2a_agent),...y.user?[g("user",`\u{1F464} ${s("insights.senderHuman")}`,y.user)]:[],...y.a2a_agent?[g("a2a_agent",`\u{1F91D} ${s("insights.senderA2A")}`,y.a2a_agent)]:[],...y.system?[g("system",`\u2699\uFE0F ${s("insights.senderSystem")}`,y.system," spanchip-sys")]:[]].join("")}</div>`,$=u==="all"?p.filter(A=>sa(A)!=="system"):p.filter(A=>sa(A)===u),L=$.filter(A=>A.severity!=="info").length,C=(A,R)=>`<button type="button" class="spanchip${o===A?" on":""}" data-ledgersort="${A}">${l(R)}</button>`,P=h?`<div class="spanfilter ledgersort">${C("normal",s("insights.ledgerNormal"))}${C("grouped",s("insights.ledgerGrouped"))}</div>`:"",H=`${M}${P}`,q=`<p class="turn-sum mut">${l(s("insights.turnSummary",{total:$.length,flagged:L}))}</p>`,I=e.meta?.capped?`<p class="turn-hidden mut">${l(s("insights.turnsCapped",{shown:String(e.meta.spansReturned??c.length),total:String(e.meta.spansTotal??c.length)}))}</p>`:"",N=A=>Og(e,c,A,t,n,a,i,r);if(!$.length)return`<div class="turnlist">${H}<p class="mut">${l(s("insights.evNoFlags"))}</p></div>`;if(o==="grouped"&&h){let A=[...f].sort((j,z)=>bs[j.severity]-bs[z.severity]),R=new Map($.map(j=>[j.turnIndex,j])),B=new Map;for(let j of A)for(let z of j.evidence?.turnIndexes??[])R.has(z)&&!B.has(z)&&B.set(z,j.id);let V=(j,z,b)=>`<div class="turn-group-head sev-${l(j)}"><b>${l(z)}</b><span>${l(s("insights.ledgerGroupCount",{count:b}))}</span></div>`,Z=[];for(let j of A){let z=$.filter(b=>B.get(b.turnIndex)===j.id).sort((b,S)=>b.turnIndex-S.turnIndex);z.length&&Z.push(`<div class="turn-group">${V(j.severity,on("rec",{id:j.id,params:{}}),z.length)}${z.map(N).join("")}</div>`)}let G=$.filter(j=>!B.has(j.turnIndex)).sort((j,z)=>j.turnIndex-z.turnIndex);return G.length&&Z.push(`<div class="turn-group">${V("info",s("insights.ledgerOther"),G.length)}${G.map(N).join("")}</div>`),`<div class="turnlist">${q}${H}${Z.join("")}${I}</div>`}let O=[...$].sort((A,R)=>A.turnIndex-R.turnIndex);return`<div class="turnlist">${q}${H}${O.map(N).join("")}${I}</div>`}function Ng(e){let t=[];for(let n of e)if(n.role==="agent"){let a=t[t.length-1];a&&a.kind==="ops"&&a.turnIndex===n.turnIndex?a.msgs.push(n):t.push({kind:"ops",turnIndex:n.turnIndex,msgs:[n]})}else t.push({kind:"prompt",msg:n});return t}function rd(e,t){let n=t.get(e);return n?.length?n.map(a=>`<span class="cbub-rec" title="${l(on("rec",{id:a,params:{}}))}">\u{1F4A1} ${l(on("rec",{id:a,params:{}}))}</span>`).join(""):""}function qg(e,t){let n=e.role==="user"?"right":"left",a=$r(e.source)||`<span class="tp-label">${l(s("insights.turnPrompt"))}</span>`,o=e.text?kr(e.text)||e.text:"",i=e.severity&&e.severity!=="info"?` sev-${l(e.severity)}`:"";return`<div class="cbub cbub-${n} role-${l(e.role)}${i}">
|
|
2387
|
-
<div class="cbub-head">${a}${xr(e.source)}<span class="cbub-turn">#${l(String(e.turnIndex))}</span>${rd(e.turnIndex,t)}</div>
|
|
2388
|
-
<div class="cbub-body"><div class="md-body">${o?ia(o+(e.truncated?" \u2026":"")):`<p class="mut">${l(s("insights.replayNoText"))}</p>`}</div></div>
|
|
2389
|
-
${e.truncated?`<div class="cbub-foot"><button type="button" class="tp-toggle" data-convo-full="${l(String(e.turnIndex))}">${l(s("insights.turnPromptFull"))}</button></div>`:""}
|
|
2390
|
-
</div>`}function jg(e,t){let n=e.event;if(!n)return"";let a=n.status==="error"||!!n.result&&Js.has(n.result.category),o=n.intent?.subject?`<code class="span-subj">${l(n.intent.subject)}</code>`:"",i=wr(n.intent,String(n.label?.params?.tool??n.kind)),r=n.result&&Js.has(n.result.category)?`<span class="span-res rc-bad">${l(ys(n.result.category))}${n.result.exitCode!==void 0?` \xB7 exit ${n.result.exitCode}`:""}</span>`:"",u=n.evidence,c=!!(u?.command?.text||u?.output?.text),p=t&&u?`${oa(s("insights.dCommand"),u.command)}${oa(s("insights.dCmdOutput"),u.output)}`:"",h=(e.tags??[]).filter(y=>y!=="normal"&&y!=="diagnostic").map(y=>`<span class="span-tag tg-${l(y)}">${l(jn(y))}</span>`).join("");return`<div class="cop${a?" bad":""}${t?" open":""}">
|
|
2391
|
-
<div class="cop-line${c?" clickable":""}"${c?` data-convo-op="${l(e.id)}" role="button" tabindex="0"`:""}>
|
|
2392
|
-
<i class="op ph-${l(Ys(n.phase))}${a?" bad":""}"></i>
|
|
2393
|
-
<b class="span-what">${l(i)}</b>${o}${r}
|
|
2394
|
-
<span class="span-tags">${h}</span>
|
|
2395
|
-
<span class="span-dur">${l(Fe(n.durationMs))}</span>
|
|
2396
|
-
${c?`<span class="span-detail-btn" aria-hidden="true">${l(t?s("insights.dCollapse"):s("insights.dDetail"))}</span>`:""}
|
|
2397
|
-
</div>
|
|
2398
|
-
${p?`<div class="spandetail">${p}</div>`:""}
|
|
2399
|
-
</div>`}function Ug(e,t,n){let a=e.msgs.filter(c=>c.text&&!c.event),o=e.msgs.filter(c=>c.event),i=e.msgs.some(c=>c.severity==="bad")?" sev-bad":e.msgs.some(c=>c.severity==="warn")?" sev-warn":"",r=a.map(c=>`<div class="cbub-say"><div class="md-body">${ia(c.text)}</div></div>`).join(""),u=o.map(c=>jg(c,t.has(c.id))).join("");return`<div class="cbub cbub-left role-agent cbub-ops${i}">
|
|
2400
|
-
<div class="cbub-head"><span class="tp-label tp-src tp-src-system">\u{1F916} ${l(s("insights.replayAgent"))}</span><span class="cbub-turn">#${l(String(e.turnIndex))}</span>${o.length?`<span class="cbub-opcount">${l(s("insights.replayOps",{count:o.length}))}</span>`:""}${rd(e.turnIndex,n)}</div>
|
|
2401
|
-
${r?`<div class="cbub-saywrap">${r}</div>`:""}
|
|
2402
|
-
${u?`<div class="cbub-ops-list">${u}</div>`:""}
|
|
2403
|
-
</div>`}function zg(e,t){if(!e.messages.length)return e.loading?`<p class="mut">${l(s("insights.detailLoading"))}</p>`:`<p class="mut">${l(s("insights.replayEmpty"))}</p>`;let a=Ng(e.messages).map(i=>i.kind==="prompt"?qg(i.msg,t):Ug(i,e.openOps,t)).join(""),o=e.hasMore?`<div class="convo-more"><button type="button" class="primary convo-loadmore"${e.loading?" disabled":""}>${l(e.loading?s("insights.detailLoading"):s("insights.replayLoadMore",{shown:e.messages.length,total:e.total}))}</button></div>`:`<p class="convo-more mut">${l(s("insights.replayAllLoaded",{total:e.total}))}</p>`;return`${a}${o}`}var Gg=[{key:"all",label:"spanAll"},{key:"user",label:"senderHuman"},{key:"a2a_agent",label:"senderA2A"},{key:"system",label:"senderSystem"}],Wg=[{key:"all",label:"spanAll"},{key:"failure",label:"tag.failure"},{key:"slow",label:"tag.slow"}];function Vg(e,t){let n=Gg.map(o=>`<button type="button" class="spanchip${e.role===o.key?" on":""}" data-convo-role="${o.key}">${l(o.label.includes(".")?jn(o.label.split(".")[1]):s("insights."+o.label))}</button>`).join(""),a=Wg.map(o=>`<button type="button" class="spanchip${e.tag===o.key?" on":""}" data-convo-tag="${o.key}">${l(o.label.includes(".")?jn(o.label.split(".")[1]):s("insights."+o.label))}</button>`).join("");return`<div class="convo">
|
|
2404
|
-
<div class="convo-controls">
|
|
2405
|
-
<input type="search" class="convo-search" placeholder="${l(s("insights.replaySearch"))}" value="${l(e.q)}">
|
|
2406
|
-
<div class="convo-filters">
|
|
2407
|
-
<div class="spanfilter convo-rolefilter"><span class="convo-flabel">${l(s("insights.replayBy"))}</span>${n}</div>
|
|
2408
|
-
<div class="spanfilter convo-tagfilter"><span class="convo-flabel">${l(s("insights.replayState"))}</span>${a}</div>
|
|
2409
|
-
</div>
|
|
2410
|
-
</div>
|
|
2411
|
-
<div class="convothread">${zg(e,t)}</div>
|
|
2412
|
-
</div>`}function Kg(e){let t=new Map;for(let o of e.events??[])o.phase&&t.set(o.phase,(t.get(o.phase)??0)+(o.durationMs??0)+1);let n="discuss",a=-1;for(let[o,i]of t)i>a&&(a=i,n=o);return n}function Jg(e,t,n){let a=[...e.turnTimeline??[]].sort((u,c)=>u.turnIndex-c.turnIndex);if(a.length<2)return"";let o=t.turnIdx.size>0,i=a.map(u=>{let c=u.metrics,p=Kg(u),f=(u.tags??[]).includes("failure")||(u.events??[]).some(H=>H.status==="error"),h=(u.tags??[]).includes("slow"),y=n.has(u.turnIndex),g=t.turnIdx.has(u.turnIndex),v=["railnode",nn(p),g?"hot":"",o&&!g?"dim":""].filter(Boolean).join(" "),M=`#${u.turnIndex} \xB7 ${kn(p)} \xB7 ${s("insights.mReads")}${c.reads} ${s("insights.mEdits")}${c.edits} ${s("insights.mRuns")}${c.runs}${c.failures?` \xB7 ${s("insights.mFailures")}${c.failures}`:""} \xB7 ${Fe(c.durationMs)}`,$=`${f?'<i class="rb rb-fail"></i>':""}${h?'<i class="rb rb-slow"></i>':""}${y?'<i class="rb rb-rec"></i>':""}`,L=`<button type="button" class="${v}" data-rail-turn="${l(String(u.turnIndex))}" data-tip="${l(M)}"><span>${l(String(u.turnIndex))}</span>${$}</button>`,C=(u.events??[]).filter(H=>H.kind==="delegate").length,P=C?`<span class="railbranch" data-tip="${l(`#${u.turnIndex} \xB7 ${s("insights.railSubagents",{n:C})}`)}">${'<i class="rbr-sub"></i>'.repeat(Math.min(C,4))}</span>`:"";return L+P}).join(""),r=[...["research","edit","run","delegate","discuss"].map(u=>`<span class="rl-item"><i class="${nn(u)}"></i>${l(kn(u))}</span>`),`<span class="rl-item rl-sep"><i class="rbr-sub"></i>${l(s("insights.railSubagent"))}</span>`].join("");return`<section class="block turnrail-block">
|
|
2413
|
-
<div class="turnrail-head"><h3>${l(s("insights.turnRail"))}</h3><span class="turnrail-legend">${r}</span></div>
|
|
2414
|
-
<div class="turnrail">${i}</div>
|
|
2415
|
-
</section>`}function Yg(e){let t=(e.spans??[]).map((r,u)=>({s:r,i:u,start:r.relStartMs??0,dur:Math.max(r.durationMs??0,0)})).filter(r=>Number.isFinite(r.start)).sort((r,u)=>r.start-u.start);if(t.length<2)return"";let n=Math.max(t.reduce((r,u)=>r+u.dur,0),1),a=0,o=t.map(r=>{let u=a/n*100,c=Math.max(r.dur/n*100,.3);a+=r.dur;let p=r.s.status==="error"||(r.s.tags??[]).includes("failure"),f=(r.s.tags??[]).includes("slow"),h=["gbar",nn(r.s.phase),p?"gbar-fail":"",f?"gbar-slow":""].filter(Boolean).join(" "),y=r.s.status==="error"?` \xB7 ${jn("failure")}`:"",g=`#${r.i} \xB7 ${r.s.tool} \xB7 ${kn(r.s.phase)} \xB7 ${Fe(r.s.durationMs)}${y}`;return`<button type="button" class="${h}" style="left:${u.toFixed(3)}%;width:${c.toFixed(3)}%" data-gantt-span="${r.i}" data-tip="${l(g)}"></button>`}).join(""),i=t[t.length-1].start+t[t.length-1].dur-t[0].start;return`<section class="block gantt-block">
|
|
2416
|
-
<div class="turnrail-head"><h3>${l(s("insights.gantt"))}</h3><span class="gantt-cap">${l(s("insights.ganttCaption",{span:t.length,dur:Fe(i),active:Fe(n)}))}</span></div>
|
|
2417
|
-
<div class="gantt"><div class="gtrack">${o}</div></div>
|
|
2418
|
-
</section>`}function Zg(e){let t=(e.turnTimeline??[]).map(g=>g.context&&Number.isFinite(g.context.contextTokens)?{turn:g.turnIndex,v:g.context.contextTokens}:null).filter(g=>g!==null).sort((g,v)=>g.turn-v.turn);if(t.length<2)return"";let n=Math.max(...t.map(g=>g.v),1),a=100,o=40,i=t.length,r=g=>g/(i-1)*a,u=g=>o-1-g/n*(o-2),c=t.map((g,v)=>`${r(v).toFixed(2)},${u(g.v).toFixed(2)}`).join(" "),p=`0,${o} ${c} ${a},${o}`,f=a/i,h=t.map((g,v)=>`<rect class="ctxhit" x="${Math.max(0,r(v)-f/2).toFixed(2)}" y="0" width="${f.toFixed(2)}" height="${o}" data-tip="${l(`${s("insights.ctxTurn",{n:g.turn})} \xB7 ${Se(g.v)} tok`)}"></rect>`).join(""),y=Se(Math.round(n/2));return`<section class="block ctxcurve-block">
|
|
2419
|
-
<div class="turnrail-head"><h3>${l(s("insights.ctxCurve"))}</h3><span class="gantt-cap">${l(s("insights.ctxCaption",{peak:Se(n),turns:t.length}))}</span></div>
|
|
2420
|
-
<div class="ctxchart">
|
|
2421
|
-
<div class="ctxyaxis"><span>${l(Se(n))}</span><span>${l(y)}</span><span>0 tok</span></div>
|
|
2422
|
-
<div class="ctxplot">
|
|
2423
|
-
<svg class="ctxcurve" viewBox="0 0 ${a} ${o}" preserveAspectRatio="none" role="img" aria-label="${l(s("insights.ctxCurve"))}">
|
|
2424
|
-
<polygon class="ctxarea" points="${p}"/>
|
|
2425
|
-
<polyline class="ctxline" points="${c}"/>
|
|
2426
|
-
${h}
|
|
2427
|
-
</svg>
|
|
2428
|
-
<div class="ctxxaxis"><span>${l(s("insights.ctxTurn",{n:t[0].turn}))}</span><span>${l(s("insights.ctxTurn",{n:t[t.length-1].turn}))}</span></div>
|
|
2429
|
-
</div>
|
|
2430
|
-
</div>
|
|
2431
|
-
</section>`}function Qg(e,t){e.addEventListener("mousemove",n=>{let a=n.target.closest("[data-tip]");if(!a){t.hidden=!0;return}t.textContent=a.getAttribute("data-tip")||"",t.hidden=!1;let o=14,i=t.getBoundingClientRect(),r=n.clientX+o,u=n.clientY+o;r+i.width>window.innerWidth&&(r=n.clientX-i.width-o),u+i.height>window.innerHeight&&(u=n.clientY-i.height-o),t.style.left=`${Math.max(4,r)}px`,t.style.top=`${Math.max(4,u)}px`}),e.addEventListener("mouseleave",()=>{t.hidden=!0})}function Xg(e,t){if(e.status!=="ok")return`<p class="mut">${l(gr(e))}</p>`;let n=e.agg,a=Mg(e,t.activeId),o=new Map;for(let c of e.recommendations??[])for(let p of c.evidence?.turnIndexes??[]){let f=o.get(p)??[];f.includes(c.id)||f.push(c.id),o.set(p,f)}let i=[e.meta?.asOf?s("sessions.insightAsOf",{asOf:String(e.meta.asOf)}):"",e.meta?.partial?s("sessions.insightPartial"):"",e.meta?.capped?s("sessions.insightCapped",{shown:String(e.meta.spansReturned??e.spans?.length??0),total:String(e.meta.spansTotal??e.spans?.length??0)}):""].filter(Boolean).join(" \xB7 "),r=e.spans?.length??0,u=e.turnTimeline?.length??0;return`
|
|
2432
|
-
<div class="cards insight-detail-metrics">
|
|
2433
|
-
${sn(s("insights.metricSpans"),Se(n.totalSpans))}
|
|
2434
|
-
${sn(s("insights.metricFailed"),Se(n.failedSpans))}
|
|
2435
|
-
${sn(s("insights.metricSlow"),Se(n.slowSpans))}
|
|
2436
|
-
${sn(s("insights.metricRw"),n.readWriteRatio===null?"-":n.readWriteRatio.toFixed(1))}
|
|
2437
|
-
</div>
|
|
2438
|
-
${i?`<p class="insight-meta">${l(i)}</p>`:""}
|
|
2439
|
-
<section class="block recblock">
|
|
2440
|
-
<h3>${l(s("insights.recommendations"))}</h3>
|
|
2441
|
-
${Ag(e,t.activeId)}
|
|
2442
|
-
</section>
|
|
2443
|
-
${Jg(e,a,o)}
|
|
2444
|
-
${Yg(e)}
|
|
2445
|
-
${pg(e)}
|
|
2446
|
-
${Zg(e)}
|
|
2447
|
-
<div class="detailtabs">
|
|
2448
|
-
<div class="detailtabbar" role="tablist" aria-label="${l(s("insights.detailTabs"))}">
|
|
2449
|
-
<button type="button" role="tab" data-tab="spans" class="${t.tab==="spans"?"on":""}">${l(s("insights.trace"))} <b>${r}</b></button>
|
|
2450
|
-
<button type="button" role="tab" data-tab="ledger" class="${t.tab==="ledger"?"on":""}">${l(s("insights.ledger"))} <b>${u}</b></button>
|
|
2451
|
-
<button type="button" role="tab" data-tab="convo" class="${t.tab==="convo"?"on":""}">${l(s("insights.replay"))}</button>
|
|
2452
|
-
</div>
|
|
2453
|
-
<div class="detailtabbody">
|
|
2454
|
-
<div class="insight-tab-panel" data-panel="spans"${t.tab==="spans"?"":" hidden"}>${Rg(e,a,t.spanFilter,t.openSpans)}</div>
|
|
2455
|
-
<div class="insight-tab-panel" data-panel="ledger"${t.tab==="ledger"?"":" hidden"}>${Fg(e,a,t.openTurns,t.openSpans,t.ledgerSort,t.openPrompts,t.rawPrompts,t.ledgerSender)}</div>
|
|
2456
|
-
<div class="insight-tab-panel" data-panel="convo"${t.tab==="convo"?"":" hidden"}>${Vg(t.convo,o)}</div>
|
|
2457
|
-
</div>
|
|
2458
|
-
</div>`}async function eb(e){let t=await fetch(`/api/sessions/${encodeURIComponent(e)}/insight?detail=spans`,{cache:"no-store"}),n=await t.json().catch(()=>({}));if(!t.ok||n?.ok===!1)throw new Error(String(n?.error??t.status));return n.report}function tb(){let e=typeof location<"u"&&location.hash||"",t=e.indexOf("?");if(t<0)return{};let n={};for(let[a,o]of new URLSearchParams(e.slice(t+1)))n[a]=o;return n}function nb(e){let t=new URLSearchParams;for(let[a,o]of Object.entries(e))o&&t.set(a,o);let n=t.toString();return"#/insights"+(n?`?${n}`:"")}var sb=["all","review","failed","slow"],ob=["overview","sessions","flow","dist","hot"],ab=["recent","review","spans","fails","slow","agent"];function ld(e){let t=tb(),n=null,a=[],o=sb.includes(t.filter)?t.filter:"all",i=new Set((t.cli??"").split(",").filter(Boolean)),r=t.q??"",u=null,c=t.sess??null,p=null,f=null,h="spans",y="all",g=new Set,v=new Set,M="normal",$="all",L=new Set,C=new Set,P=()=>({messages:[],total:0,hasMore:!1,nextOffset:0,loading:!1,q:"",role:"all",tag:"all",openOps:new Set}),H=P(),q=null,I=!1,N=null,O=0,A=!1,R=ob.includes(t.tab)?t.tab:"overview",B=t.project??"",V=t.time??"all",Z=t.noise==="1",G=ab.includes(t.sort)?t.sort:"recent",j=t.layout==="table"?"table":"card",z=new Set,b=!1,S="",E=0;e.innerHTML=`
|
|
2459
|
-
<section class="page insights-page">
|
|
2460
|
-
<div class="page-heading">
|
|
2461
|
-
<div>
|
|
2462
|
-
<p class="eyebrow">${l(s("nav.insights"))}</p>
|
|
2463
|
-
<h1>${l(s("insights.title"))}</h1>
|
|
2464
|
-
<p>${l(s("insights.subtitle"))}</p>
|
|
2465
|
-
</div>
|
|
2466
|
-
<div class="insight-head-acts">
|
|
2467
|
-
<button type="button" id="insight-palette-open" class="ins-clear">${l(s("insights.paletteOpen"))}</button>
|
|
2468
|
-
<button type="button" id="insight-refresh" class="primary">${l(s("insights.refresh"))}</button>
|
|
2469
|
-
</div>
|
|
2470
|
-
</div>
|
|
2471
|
-
<form id="insight-filters" class="filters insights-filters">
|
|
2472
|
-
<input type="search" name="q" placeholder="${l(s("insights.search"))}">
|
|
2473
|
-
<select id="insight-project" class="ins-select" aria-label="${l(s("insights.projectAll"))}"></select>
|
|
2474
|
-
<select id="insight-time" class="ins-select" aria-label="${l(s("insights.timeAll"))}">
|
|
2475
|
-
${Wc.map(_=>`<option value="${_.key}">${l(s(_.label))}</option>`).join("")}
|
|
2476
|
-
</select>
|
|
2477
|
-
<div class="segmented" role="group" aria-label="${l(s("insights.filter"))}">
|
|
2478
|
-
<button type="button" data-filter="all">${l(s("insights.filterAll"))}</button>
|
|
2479
|
-
<button type="button" data-filter="review">${l(s("insights.filterReview"))}</button>
|
|
2480
|
-
<button type="button" data-filter="failed">${l(s("insights.filterFailed"))}</button>
|
|
2481
|
-
<button type="button" data-filter="slow">${l(s("insights.filterSlow"))}</button>
|
|
2482
|
-
</div>
|
|
2483
|
-
<div id="insight-cli-filter" class="spanfilter cli-filter" role="group" aria-label="${l(s("insights.filter"))}"></div>
|
|
2484
|
-
<label class="ins-toggle"><input type="checkbox" id="insight-noise"> ${l(s("insights.showAll"))}</label>
|
|
2485
|
-
<button type="button" id="insight-clear" class="ins-clear">${l(s("insights.clear"))}</button>
|
|
2486
|
-
</form>
|
|
2487
|
-
<div id="insight-tabbar">${fg(R)}</div>
|
|
2488
|
-
<div id="insight-status" class="insight-page-status"></div>
|
|
2489
|
-
<div class="insight-panel" role="tabpanel" data-tabpanel="overview"><div id="insight-overview"></div></div>
|
|
2490
|
-
<div class="insight-panel" role="tabpanel" data-tabpanel="sessions" hidden>
|
|
2491
|
-
<div id="insight-list-view">
|
|
2492
|
-
<div class="insight-list-head">
|
|
2493
|
-
<span id="insight-list-subtitle"></span>
|
|
2494
|
-
<div class="sesssort" id="insight-sort"></div>
|
|
2495
|
-
</div>
|
|
2496
|
-
<div id="insight-list"></div>
|
|
2497
|
-
</div>
|
|
2498
|
-
<div id="insight-detail-view" hidden>
|
|
2499
|
-
<button type="button" id="insight-back" class="ins-back">\u2190 ${l(s("insights.backToList"))}</button>
|
|
2500
|
-
<div id="insight-detail">${hr(void 0)}</div>
|
|
2501
|
-
</div>
|
|
2502
|
-
</div>
|
|
2503
|
-
<div class="insight-panel" role="tabpanel" data-tabpanel="flow" hidden><div id="insight-flow"></div></div>
|
|
2504
|
-
<div class="insight-panel" role="tabpanel" data-tabpanel="dist" hidden><div id="insight-dist"></div></div>
|
|
2505
|
-
<div class="insight-panel" role="tabpanel" data-tabpanel="hot" hidden><div id="insight-hot"></div></div>
|
|
2506
|
-
<div id="insight-modal" class="insight-modal" hidden></div>
|
|
2507
|
-
<div id="insight-palette" class="insight-palette" hidden></div>
|
|
2508
|
-
<div id="insight-tip" class="ins-tip" role="tooltip" hidden></div>
|
|
2509
|
-
</section>`;let U=e.querySelector("#insight-status"),ee=e.querySelector("#insight-overview"),pe=e.querySelector("#insight-list"),he=e.querySelector("#insight-list-subtitle"),ae=e.querySelector("#insight-detail"),se=e.querySelector("input[name=q]");se.value=r;let ie=e.querySelector("#insight-refresh"),me=[...e.querySelectorAll("[data-filter]")],be=e.querySelector("#insight-cli-filter"),Me=e.querySelector("#insight-flow"),le=e.querySelector("#insight-dist"),ve=e.querySelector("#insight-hot"),$e=e.querySelector("#insight-project"),Pe=e.querySelector("#insight-time"),Ge=e.querySelector("#insight-noise"),it=e.querySelector("#insight-clear"),He=e.querySelector("#insight-tabbar"),Xe=[...e.querySelectorAll(".insight-panel")],Ye=e.querySelector("#insight-palette"),K=e.querySelector("#insight-palette-open"),Ae=e.querySelector("#insight-list-view"),fe=e.querySelector("#insight-detail-view"),re=e.querySelector("#insight-back"),Be=e.querySelector("#insight-sort");function rt(){let _=u!==null;Ae.hidden=_,fe.hidden=!_}function wt(){let _=Wc.find(oe=>oe.key===V),te=_&&_.days>0?Date.now()-_.days*864e5:void 0;return{project:B||void 0,sinceMs:te,analyzableOnly:!Z}}function kt(){let _={};R!=="overview"&&(_.tab=R),o!=="all"&&(_.filter=o),r.trim()&&(_.q=r.trim()),B&&(_.project=B),V!=="all"&&(_.time=V),i.size&&(_.cli=[...i].join(",")),G!=="recent"&&(_.sort=G),j!=="card"&&(_.layout=j),Z&&(_.noise="1"),u&&(_.sess=u);try{history.replaceState(null,"",nb(_))}catch{}}function et(){let _=S.trim().toLowerCase(),te=sd.map(ue=>({type:"tab",key:ue.key,label:s(ue.label),sub:s("insights.paletteTabs")})).filter(ue=>!_||ue.label.toLowerCase().includes(_)),oe=a.filter(ue=>{let J=ue.session;return!_||`${an(J)} ${De(J)} ${J.cliId??""}`.toLowerCase().includes(_)}).slice(0,20).map(ue=>({type:"session",key:String(ue.session.sessionId),label:an(ue.session),sub:`${De(ue.session)} \xB7 ${ue.session.cliId??"-"}`}));return[...te,...oe]}function xn(_,te){$t(),_==="tab"?(R=te,u=null,Ee()):(R="sessions",At(),Rt(te))}function ot(){let _=Ye.querySelector(".palette-list");if(!_)return;let te=et();E>=te.length&&(E=Math.max(0,te.length-1)),_.innerHTML=te.length?te.map((oe,ue)=>`<button type="button" class="palette-item${ue===E?" on":""}" data-pal-type="${oe.type}" data-pal-key="${l(oe.key)}" data-pal-i="${ue}">
|
|
2510
|
-
<span class="pal-label">${l(oe.label)}</span><span class="pal-sub">${l(oe.sub)}</span>
|
|
2511
|
-
</button>`).join(""):`<p class="mut palette-empty">${l(s("insights.paletteEmpty"))}</p>`,_.querySelectorAll(".palette-item").forEach(oe=>oe.addEventListener("click",()=>xn(oe.dataset.palType??"tab",oe.dataset.palKey??""))),_.querySelector(".palette-item.on")?.scrollIntoView({block:"nearest"})}function Ze(){if(!b){Ye.hidden=!0,Ye.innerHTML="",document.body.classList.remove("insight-modal-open");return}Ye.hidden=!1,document.body.classList.add("insight-modal-open"),Ye.innerHTML=`<div class="modal-backdrop" data-pal-close></div>
|
|
2512
|
-
<div class="palette-panel" role="dialog" aria-modal="true">
|
|
2513
|
-
<input type="search" class="palette-input" placeholder="${l(s("insights.palettePlaceholder"))}" value="${l(S)}">
|
|
2514
|
-
<div class="palette-list"></div>
|
|
2515
|
-
</div>`;let _=Ye.querySelector(".palette-input");_&&(_.focus(),_.oninput=()=>{S=_.value,E=0,ot()}),Ye.querySelectorAll("[data-pal-close]").forEach(te=>te.addEventListener("click",$t)),ot()}function Vt(){b=!0,S="",E=0,Ze()}function $t(){b=!1,Ze()}function Wn(){let _=fr(a,o,r,i,{...wt(),project:void 0}),te=mg(_),oe=B;$e.innerHTML=`<option value="">${l(s("insights.projectAll"))}</option>`+te.map(ue=>`<option value="${l(ue.id)}"${ue.id===oe?" selected":""}>${l(ue.id)} (${ue.count})</option>`).join(""),oe&&!te.some(ue=>ue.id===oe)&&(B="",$e.value="")}function At(){for(let _ of Xe)_.hidden=_.dataset.tabpanel!==R;for(let _ of He.querySelectorAll("[data-itab]")){let te=_.dataset.itab===R;_.classList.toggle("on",te),_.setAttribute("aria-selected",String(te))}}function xt(_,te=!1){for(let oe of _.querySelectorAll("[data-session-id]"))oe.onclick=()=>{te&&R!=="sessions"&&(R="sessions",At(),Ee()),Rt(oe.dataset.sessionId??"")}}function Dt(){return xg(fr(a,o,r,i,wt()),G)}function Ee(){if(A)return;let _=fr(a,o,r,new Set,wt()),te=new Set(_.map(yr));for(let J of[...i])te.has(J)||i.delete(J);be.innerHTML=ug(_,i),Wn(),Ge.checked=Z,Pe.value=V;let oe=Dt();me.forEach(J=>J.classList.toggle("active",J.dataset.filter===o)),ee.innerHTML=n?dg(cg(oe)):"",he.textContent=s("insights.listCount",{shown:oe.length,total:a.length}),Be.innerHTML=kg(G,j),pe.innerHTML=!oe.length&&!Z?`<div class="insight-empty">${l(s("insights.empty"))}<br><span class="mut">${l(s("insights.emptyAnalyzableHint"))}</span></div>`:j==="table"?Eg(oe,u):Sg(oe,u,!0);let ue=oe.find(J=>J.session.sessionId===u)??a.find(J=>J.session.sessionId===u);(!u||!ue)&&(ae.innerHTML=hr(void 0)),xt(pe),rt(),Me.innerHTML=n?vg(oe):"",xt(Me,!0),le.innerHTML=n?yg(oe):"",ve.innerHTML=n?Vc(oe,z):"",xt(ve,!0),At(),kt()}function _e(){let _=ae.querySelector("#insight-detail-body");if(!_||!f)return;let te=`.insight-tab-panel[data-panel="${h}"] .spantable, .insight-tab-panel[data-panel="${h}"] .turnlist, .insight-tab-panel[data-panel="${h}"] .convothread`,oe=_.querySelector(te)?.scrollTop??0,ue=window.scrollY;_.innerHTML=Xg(f,{activeId:p,tab:h,spanFilter:y,openSpans:g,openTurns:v,ledgerSort:M,openPrompts:L,rawPrompts:C,ledgerSender:$,convo:H}),vs(_);let J=_.querySelector(te);J&&(J.scrollTop=oe),window.scrollY!==ue&&window.scrollTo({top:ue})}async function Ht(_){if(!u||H.loading)return;_&&(H.messages=[],H.nextOffset=0,H.hasMore=!1),H.loading=!0,h==="convo"&&_e();let te=new URLSearchParams({detail:"conversation",offset:String(H.nextOffset),limit:"40"});H.q&&te.set("q",H.q),H.role!=="all"&&te.set("role",H.role),H.tag!=="all"&&te.set("tag",H.tag);let oe=u;try{let J=await(await fetch(`/api/sessions/${encodeURIComponent(oe)}/insight?${te.toString()}`,{cache:"no-store"})).json().catch(()=>({}));if(A||oe!==u)return;let ce=J?.conversation;ce&&(H.messages=_?ce.messages??[]:[...H.messages,...ce.messages??[]],H.total=ce.total??H.messages.length,H.hasMore=!!ce.hasMore,H.nextOffset=ce.nextOffset??H.nextOffset+(ce.messages?.length??0))}catch{}H.loading=!1,h==="convo"&&_e()}function dt(){let _=e.querySelector("#insight-modal");if(_){if(q===null){_.hidden=!0,_.innerHTML="",document.body.classList.remove("insight-modal-open");return}_.hidden=!1,document.body.classList.add("insight-modal-open"),_.innerHTML=N?Bg(q,N,I):`<div class="modal-backdrop" data-modal-close></div><div class="modal-panel"><div class="modal-body"><p class="mut">${l(s("insights.detailLoading"))}</p></div></div>`,_.querySelectorAll("[data-modal-close]").forEach(te=>te.addEventListener("click",Vn)),_.querySelector("[data-modal-raw]")?.addEventListener("click",()=>{I=!I,dt()})}}function Vn(){q=null,I=!1,N=null,dt()}async function _t(_){if(!u)return;q=_,I=!1,N=null;let te=++O,oe=u;dt();try{let J=await(await fetch(`/api/sessions/${encodeURIComponent(oe)}/insight/turn/${_}?offset=0&limit=40000`,{cache:"no-store"})).json().catch(()=>({}));if(te!==O||A)return;N=J?.turn?.prompt??{text:"",truncated:!1}}catch{if(te!==O)return;N={text:s("insights.unavailable"),truncated:!1}}dt()}function vs(_){let te=_.querySelector(".detailtabbar");te?.addEventListener("click",J=>{let ce=J.target.closest("button[data-tab]");ce&&(h=ce.dataset.tab||"spans",te.querySelectorAll("button[data-tab]").forEach(ge=>ge.classList.toggle("on",ge.dataset.tab===h)),_.querySelectorAll(".insight-tab-panel").forEach(ge=>{ge.hidden=ge.dataset.panel!==h}),h==="convo"&&!H.messages.length&&!H.loading&&Ht(!0))});for(let J of _.querySelectorAll(".reclist [data-rec]"))J.addEventListener("click",()=>{let ce=J.dataset.rec||null;p=p===ce?null:ce,_e()});for(let J of _.querySelectorAll(".turnrail [data-rail-turn]"))J.addEventListener("click",()=>{let ce=Number(J.dataset.railTurn),ge=f?.turnTimeline?.find(Bt=>Bt.turnIndex===ce);h="ledger",M="normal",ge&&sa(ge)==="system"&&($="system"),v.add(ce),_e(),ae.querySelector(`.insight-tab-panel[data-panel="ledger"] [data-turn-card="${ce}"]`)?.scrollIntoView({behavior:"smooth",block:"center"})});for(let J of _.querySelectorAll(".gantt [data-gantt-span]"))J.addEventListener("click",()=>{let ce=Number(J.dataset.ganttSpan);h="spans",y="all",g.add(ce),_e(),ae.querySelector(`.insight-tab-panel[data-panel="spans"] .sprow-line[data-span-idx="${ce}"]`)?.closest(".spanrow")?.scrollIntoView({behavior:"smooth",block:"center"})});let oe=e.querySelector("#insight-tip");if(oe)for(let J of _.querySelectorAll(".turnrail, .gtrack, .ctxcurve"))Qg(J,oe);for(let J of _.querySelectorAll(".spanfilter [data-spanfilter]"))J.addEventListener("click",()=>{y=J.dataset.spanfilter||"all",_e()});for(let J of _.querySelectorAll(".sprow-line[data-span-idx]")){let ce=()=>{let ge=Number(J.dataset.spanIdx);g.has(ge)?g.delete(ge):g.add(ge),_e()};J.addEventListener("click",ce),J.addEventListener("keydown",ge=>{(ge.key==="Enter"||ge.key===" ")&&(ge.preventDefault(),ce())})}for(let J of _.querySelectorAll(".turn-expand-btn[data-turn]"))J.addEventListener("click",()=>{let ce=Number(J.dataset.turn);v.has(ce)?v.delete(ce):v.add(ce),_e()});for(let J of _.querySelectorAll(".ledgersort [data-ledgersort]"))J.addEventListener("click",()=>{M=J.dataset.ledgersort==="grouped"?"grouped":"normal",_e()});for(let J of _.querySelectorAll(".ledgersender [data-ledgersender]"))J.addEventListener("click",()=>{$=J.dataset.ledgersender||"all",_e()});for(let J of _.querySelectorAll(".tp-toggle[data-prompt-expand]"))J.addEventListener("click",()=>{let ce=Number(J.dataset.promptExpand);L.has(ce)?L.delete(ce):L.add(ce),_e()});for(let J of _.querySelectorAll(".tp-toggle[data-prompt-raw]"))J.addEventListener("click",()=>{let ce=Number(J.dataset.promptRaw);C.has(ce)?C.delete(ce):C.add(ce),_e()});for(let J of _.querySelectorAll(".tp-toggle[data-prompt-full]"))J.addEventListener("click",()=>{_t(Number(J.dataset.promptFull))});let ue=_.querySelector(".convo-search");ue?.addEventListener("keydown",J=>{if(J.key!=="Enter")return;J.preventDefault();let ce=ue.value.trim();ce!==H.q&&(H.q=ce,Ht(!0))});for(let J of _.querySelectorAll(".convo-rolefilter [data-convo-role]"))J.addEventListener("click",()=>{let ce=J.dataset.convoRole||"all";ce!==H.role&&(H.role=ce,Ht(!0))});for(let J of _.querySelectorAll(".convo-tagfilter [data-convo-tag]"))J.addEventListener("click",()=>{let ce=J.dataset.convoTag||"all";ce!==H.tag&&(H.tag=ce,Ht(!0))});_.querySelector(".convo-loadmore")?.addEventListener("click",()=>{Ht(!1)});for(let J of _.querySelectorAll(".cbub [data-convo-full]"))J.addEventListener("click",()=>{_t(Number(J.dataset.convoFull))});for(let J of _.querySelectorAll(".cop-line[data-convo-op]")){let ce=()=>{let ge=J.dataset.convoOp;H.openOps.has(ge)?H.openOps.delete(ge):H.openOps.add(ge),_e()};J.addEventListener("click",ce),J.addEventListener("keydown",ge=>{(ge.key==="Enter"||ge.key===" ")&&(ge.preventDefault(),ce())})}}async function Rt(_){u=_,rt(),kt(),p=null,h="spans",y="all",g=new Set,v=new Set,M="normal",$="all",L=new Set,C=new Set,H=P(),q=null,I=!1,N=null,dt(),f=null;let te=a.find(ue=>ue.session.sessionId===_);ae.innerHTML=hr(te);for(let ue of pe.querySelectorAll("[data-session-id]"))ue.classList.toggle("on",ue.dataset.sessionId===_);let oe=ae.querySelector("#insight-detail-body");if(oe)try{let ue=await eb(_);!A&&ue&&(f=ue,_e())}catch(ue){A||(oe.innerHTML=`<p class="mut">${l(String(ue))}</p>`)}}async function St(){ie.disabled=!0,U.textContent=s("insights.loading");try{let te=await fetch("/api/insights/summary?limit=200",{cache:"no-store"}),oe=await te.json().catch(()=>({}));!te.ok||oe?.ok===!1||!oe.overview?(n=null,a=[],U.textContent=`${s("insights.unavailable")}: ${String(oe?.error??te.status)}`):(n=oe.overview,a=n.sessions.map(rg),U.textContent=s("insights.loaded",{count:n.meta.analyzedSessions}))}catch(te){n=null,a=[],U.textContent=`${s("insights.unavailable")}: ${String(te)}`}if(A)return;u&&!a.some(te=>te.session.sessionId===u)&&(u=null),Ee(),ie.disabled=!1;let _=c;c=null,_&&!u&&a.some(te=>te.session.sessionId===_)&&Rt(_)}se.oninput=()=>{r=se.value,Ee()},ie.onclick=()=>{St()},He.addEventListener("click",_=>{let te=_.target.closest("[data-itab]");te&&(R=te.dataset.itab||"overview",Ee())}),re.addEventListener("click",()=>{u=null,rt(),Ee()}),Be.addEventListener("click",_=>{let te=_.target.closest("[data-sesslayout]");if(te){j=te.dataset.sesslayout==="table"?"table":"card",Ee();return}let oe=_.target.closest("[data-sesssort]");oe&&(G=oe.dataset.sesssort||"recent",Ee())}),le.addEventListener("click",_=>{let te=_.target.closest("[data-distsort]");te&&(G=te.dataset.distsort||"recent",R="sessions",u=null,Ee())}),ve.addEventListener("click",_=>{let te=_.target,oe=te.closest("[data-hotkey]");if(oe){let J=oe.dataset.hotkey||"";z.has(J)?z.delete(J):z.add(J),ve.innerHTML=Vc(Dt(),z),xt(ve,!0);return}let ue=te.closest("[data-hotproject]");ue&&(B=ue.dataset.hotproject||"",R="sessions",u=null,Ee())}),$e.addEventListener("change",()=>{B=$e.value,Ee()}),Pe.addEventListener("change",()=>{V=Pe.value,Ee()}),Ge.addEventListener("change",()=>{Z=Ge.checked,Ee()}),it.addEventListener("click",()=>{r="",se.value="",o="all",i.clear(),B="",V="all",Z=!1,Ee()});for(let _ of me)_.onclick=()=>{o=_.dataset.filter||"all",Ee()};be.addEventListener("click",_=>{let te=_.target.closest("[data-clifilter]");if(!te)return;let oe=te.dataset.clifilter||"all";oe==="all"?i.clear():i.has(oe)?i.delete(oe):i.add(oe),Ee()}),K.addEventListener("click",Vt);let Pt=_=>{if((_.key==="k"||_.key==="K")&&(_.metaKey||_.ctrlKey)){_.preventDefault(),b?$t():Vt();return}if(b){if(_.isComposing||_.keyCode===229)return;let te=et();if(_.key==="Escape")_.preventDefault(),$t();else if(_.key==="ArrowDown")_.preventDefault(),E=Math.min(te.length-1,E+1),ot();else if(_.key==="ArrowUp")_.preventDefault(),E=Math.max(0,E-1),ot();else if(_.key==="Enter"){_.preventDefault();let oe=te[E];oe&&xn(oe.type,oe.key)}return}_.key==="Escape"&&q!==null&&Vn()};return document.addEventListener("keydown",Pt),bt().then(()=>{A||Ee()}),St(),()=>{A=!0,document.removeEventListener("keydown",Pt),document.body.classList.remove("insight-modal-open")}}var $n=null,ra=null,la="glm-5.1",cd=[];function Qs(){ra!==null&&(window.clearInterval(ra),ra=null)}function Er(){return $n||($n=document.createElement("dialog"),$n.className="onboarding-dialog",document.body.appendChild($n),$n.addEventListener("close",Qs),$n)}function ib(e){return e.status==="waiting_for_scan"?s("botOnboarding.waiting"):e.status==="verifying"?s("botOnboarding.verifying"):e.status==="configuring_permissions"?e.permissionStatusMsg?`${s("botOnboarding.configuringPermissions")} ${e.permissionStatusMsg}`:s("botOnboarding.configuringPermissions"):e.status==="waiting_for_platform_scan"?s("botOnboarding.platformScanHint"):e.status==="needs_owner"?s("botOnboarding.needsOwner"):e.status==="completed"?s("botOnboarding.completed"):e.status==="failed"?`${s("botOnboarding.failed")}: ${l(e.message??e.error??"unknown")}`:s("botOnboarding.starting")}function rb(e){if(e.status!=="completed"&&e.status!=="needs_owner"||!e.permission)return"";let t=e.permission;if(t.ok){let a=[s("botOnboarding.permissionOk",{count:t.scopeCount??0})];t.skippedScopeCount&&t.skippedScopeCount>0&&a.push(s("botOnboarding.permissionSkipped",{count:t.skippedScopeCount})),t.versionId&&a.push(s("botOnboarding.permissionVersion",{version:l(t.versionId)}));let o=`<p class="hint-ok">\u2705 ${a.join(" ")}</p>`;return t.scopeWarning&&(o+=`<p class="hint-warn">\u26A0\uFE0F ${l(t.scopeWarning)}</p>`),o}let n=(e.remainingSteps??[]).map(a=>`<li><a href="${l(a.url)}" target="_blank" rel="noopener">${l(a.title)}</a></li>`).join("");return`<p class="hint-warn">\u26A0\uFE0F ${s("botOnboarding.permissionManual")}${t.message?`\uFF08${l(t.message)}\uFF09`:""}</p>`+(n?`<ol class="onboarding-steps">${n}</ol>`:"")}function lb(e,t){if(e.status!=="needs_owner")return"";let n=t?`<p class="form-error">${l(t)}</p>`:"";return`<form id="ob-owner-form" class="onboarding-form">
|
|
1
|
+
import{a as g,b as H}from"./chunks/chunk-76J7PNZI.js";import{a as U,j as q,k as A,l as d,m as r,n as i,o as I,r as _,t as B,x as z,y as v}from"./chunks/chunk-JXLHRRJD.js";import"./chunks/chunk-7SZRL6FY.js";var p=null,w=null,x="glm-5.1",N=[];function h(){w!==null&&(window.clearInterval(w),w=null)}function S(){return p||(p=document.createElement("dialog"),p.className="onboarding-dialog",document.body.appendChild(p),p.addEventListener("close",h),p)}function de(e){return e.status==="waiting_for_scan"?r("botOnboarding.waiting"):e.status==="verifying"?r("botOnboarding.verifying"):e.status==="configuring_permissions"?e.permissionStatusMsg?`${r("botOnboarding.configuringPermissions")} ${e.permissionStatusMsg}`:r("botOnboarding.configuringPermissions"):e.status==="waiting_for_platform_scan"?r("botOnboarding.platformScanHint"):e.status==="needs_owner"?r("botOnboarding.needsOwner"):e.status==="completed"?r("botOnboarding.completed"):e.status==="failed"?`${r("botOnboarding.failed")}: ${i(e.message??e.error??"unknown")}`:r("botOnboarding.starting")}function ce(e){if(e.status!=="completed"&&e.status!=="needs_owner"||!e.permission)return"";let t=e.permission;if(t.ok){let o=[r("botOnboarding.permissionOk",{count:t.scopeCount??0})];t.skippedScopeCount&&t.skippedScopeCount>0&&o.push(r("botOnboarding.permissionSkipped",{count:t.skippedScopeCount})),t.versionId&&o.push(r("botOnboarding.permissionVersion",{version:i(t.versionId)}));let a=`<p class="hint-ok">\u2705 ${o.join(" ")}</p>`;return t.scopeWarning&&(a+=`<p class="hint-warn">\u26A0\uFE0F ${i(t.scopeWarning)}</p>`),a}let n=(e.remainingSteps??[]).map(o=>`<li><a href="${i(o.url)}" target="_blank" rel="noopener">${i(o.title)}</a></li>`).join("");return`<p class="hint-warn">\u26A0\uFE0F ${r("botOnboarding.permissionManual")}${t.message?`\uFF08${i(t.message)}\uFF09`:""}</p>`+(n?`<ol class="onboarding-steps">${n}</ol>`:"")}function ue(e,t){if(e.status!=="needs_owner")return"";let n=t?`<p class="form-error">${i(t)}</p>`:"";return`<form id="ob-owner-form" class="onboarding-form">
|
|
2516
2
|
<label class="onboarding-field">
|
|
2517
|
-
<span>${
|
|
2518
|
-
<input id="ob-owner" type="text" placeholder="${
|
|
3
|
+
<span>${r("botOnboarding.ownerLabel")}</span>
|
|
4
|
+
<input id="ob-owner" type="text" placeholder="${r("botOnboarding.ownerPlaceholder")}" autocomplete="off" spellcheck="false">
|
|
2519
5
|
</label>
|
|
2520
|
-
<p class="hint-warn">${
|
|
6
|
+
<p class="hint-warn">${r("botOnboarding.ownerHint")}</p>
|
|
2521
7
|
${n}
|
|
2522
8
|
<menu class="onboarding-actions">
|
|
2523
|
-
<button type="submit" class="primary">${
|
|
9
|
+
<button type="submit" class="primary">${r("botOnboarding.ownerSubmit")}</button>
|
|
2524
10
|
</menu>
|
|
2525
|
-
</form>`}function
|
|
2526
|
-
<img class="qr-image" src="${e.qrDataUrl}" alt="${
|
|
2527
|
-
${e.qrUrl?`<a class="onboarding-link" href="${
|
|
2528
|
-
</div>`:"",
|
|
2529
|
-
<img class="qr-image" src="${e.platformQrDataUrl}" alt="${
|
|
2530
|
-
</div>`:"",
|
|
11
|
+
</form>`}function u(e,t){let n=S(),o=e.status==="waiting_for_scan"&&e.qrDataUrl?`<div class="qr-card">
|
|
12
|
+
<img class="qr-image" src="${e.qrDataUrl}" alt="${r("botOnboarding.qrAlt")}">
|
|
13
|
+
${e.qrUrl?`<a class="onboarding-link" href="${i(e.qrUrl)}" target="_blank" rel="noopener">${r("botOnboarding.openLink")}</a>`:""}
|
|
14
|
+
</div>`:"",a=e.status==="waiting_for_platform_scan"&&e.platformQrDataUrl?`<div class="qr-card">
|
|
15
|
+
<img class="qr-image" src="${e.platformQrDataUrl}" alt="${r("botOnboarding.platformQrAlt")}">
|
|
16
|
+
</div>`:"",s=e.appId?`<p><b>App ID:</b> <code>${i(e.appId)}</code>`+(e.cliId?` \uFF5C <b>CLI:</b> <code>${i(e.cliId)}</code>`:"")+(e.workingDir?` \uFF5C <b>${r("botOnboarding.metaDir")}:</b> <code>${i(e.workingDir)}</code>`:"")+"</p>":"",c=e.status==="completed"?`<p class="hint-ok">${r("botOnboarding.restartHint")}</p>`:"";n.innerHTML=`<article>
|
|
2531
17
|
<header>
|
|
2532
|
-
<h3>${
|
|
2533
|
-
<p>${
|
|
18
|
+
<h3>${r("botOnboarding.title")}</h3>
|
|
19
|
+
<p>${r("botOnboarding.intro")}</p>
|
|
2534
20
|
</header>
|
|
2535
|
-
<p class="onboarding-status status-${e.status}">${
|
|
2536
|
-
${a}
|
|
21
|
+
<p class="onboarding-status status-${e.status}">${de(e)}</p>
|
|
2537
22
|
${o}
|
|
2538
|
-
${
|
|
2539
|
-
${
|
|
2540
|
-
${
|
|
2541
|
-
${
|
|
2542
|
-
|
|
2543
|
-
|
|
23
|
+
${a}
|
|
24
|
+
${s}
|
|
25
|
+
${ce(e)}
|
|
26
|
+
${ue(e,t)}
|
|
27
|
+
${c}
|
|
28
|
+
<form method="dialog"><button>${r("botOnboarding.close")}</button></form>
|
|
29
|
+
</article>`,e.status==="needs_owner"&&n.querySelector("#ob-owner-form")?.addEventListener("submit",l=>{l.preventDefault();let k=n.querySelector("#ob-owner")?.value??"";pe(e,k)})}async function pe(e,t){if(!t.trim()){u(e,r("botOnboarding.ownerEmpty"));return}try{let n=await fetch(`/api/bot-onboarding/${encodeURIComponent(e.id)}/owner`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({owner:t.trim()})}),o=await n.json();if(!n.ok){u(e,o?.message??o?.error??r("botOnboarding.ownerInvalid"));return}o?.job&&u(o.job)}catch(n){u(e,n instanceof Error?n.message:String(n))}}async function me(){try{let e=await fetch("/api/cli-options"),t=await e.json();if(e.ok&&Array.isArray(t?.options))return typeof t.ttadkModelDefault=="string"&&t.ttadkModelDefault.trim()&&(x=t.ttadkModelDefault.trim()),Array.isArray(t.ttadkModelSuggestions)&&(N=t.ttadkModelSuggestions.filter(n=>typeof n=="string")),t.options}catch{}return[{id:"claude-code",label:"Claude"}]}function K(e){let t=p;if(!t)return;let n=t.querySelector("#ob-cli"),o=t.querySelector("#ob-model"),a=t.querySelector("#ob-model-suggestions");if(!n||!o)return;let s=e.find(l=>l.id===n.value),c=s?.gateway==="ttadk",y=c&&s?.acceptsModel!==!1;if(c&&!y){o.value="",o.disabled=!0,o.placeholder=r("botOnboarding.modelTtadkCocoPlaceholder");return}o.disabled=!1,y?(a&&(a.innerHTML=N.map(l=>`<option value="${i(l)}"></option>`).join("")),o.placeholder=r("botOnboarding.modelTtadkPlaceholder").replace("{model}",x),o.value.trim()||(o.value=x)):(a&&(a.innerHTML=""),o.placeholder=r("botOnboarding.modelPlaceholder"),o.value.trim()===x&&(o.value=""))}function M(e,t){let n=S(),o=e.map(l=>`<option value="${i(l.id)}">${i(l.label)}\uFF08${i(l.id)}\uFF09</option>`).join(""),a=t?`<p class="form-error">${i(t)}</p>`:"";n.innerHTML=`<article>
|
|
2544
30
|
<header>
|
|
2545
|
-
<h3>${
|
|
2546
|
-
<p>${
|
|
31
|
+
<h3>${r("botOnboarding.title")}</h3>
|
|
32
|
+
<p>${r("botOnboarding.intro")}</p>
|
|
2547
33
|
</header>
|
|
2548
34
|
<form id="onboarding-form" class="onboarding-form">
|
|
2549
35
|
<label class="onboarding-field">
|
|
2550
|
-
<span>${
|
|
2551
|
-
<select id="ob-cli">${
|
|
36
|
+
<span>${r("botOnboarding.cliLabel")}</span>
|
|
37
|
+
<select id="ob-cli">${o}</select>
|
|
2552
38
|
</label>
|
|
2553
39
|
<label class="onboarding-field">
|
|
2554
|
-
<span>${
|
|
2555
|
-
<input id="ob-dir" type="text" value="~" placeholder="${
|
|
40
|
+
<span>${r("botOnboarding.dirLabel")}</span>
|
|
41
|
+
<input id="ob-dir" type="text" value="~" placeholder="${r("botOnboarding.dirPlaceholder")}" autocomplete="off" spellcheck="false">
|
|
2556
42
|
</label>
|
|
2557
43
|
<label class="onboarding-field">
|
|
2558
|
-
<span>${
|
|
2559
|
-
<input id="ob-model" type="text" list="ob-model-suggestions" placeholder="${
|
|
44
|
+
<span>${r("botOnboarding.modelLabel")}</span>
|
|
45
|
+
<input id="ob-model" type="text" list="ob-model-suggestions" placeholder="${r("botOnboarding.modelPlaceholder")}" autocomplete="off" spellcheck="false">
|
|
2560
46
|
<datalist id="ob-model-suggestions"></datalist>
|
|
2561
47
|
</label>
|
|
2562
|
-
${
|
|
48
|
+
${a}
|
|
2563
49
|
<menu class="onboarding-actions">
|
|
2564
|
-
<button type="button" id="ob-cancel">${
|
|
2565
|
-
<button type="submit" class="primary">${
|
|
50
|
+
<button type="button" id="ob-cancel">${r("botOnboarding.cancel")}</button>
|
|
51
|
+
<button type="submit" class="primary">${r("botOnboarding.startScan")}</button>
|
|
2566
52
|
</menu>
|
|
2567
53
|
</form>
|
|
2568
|
-
</article>`;let i=n.querySelector("#onboarding-form");n.querySelector("#ob-cancel")?.addEventListener("click",()=>n.close()),n.querySelector("#ob-cli")?.addEventListener("change",()=>ud(e)),ud(e),i?.addEventListener("submit",c=>{c.preventDefault();let p=n.querySelector("#ob-cli")?.value??"",f=n.querySelector("#ob-dir")?.value??"",h=n.querySelector("#ob-model")?.value??"";db({cliId:p,workingDir:f,model:h},e)})}async function db(e,t){Qs(),rn({id:"",status:"starting"});try{let n=await fetch("/api/bot-onboarding/start",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({cliId:e.cliId,workingDir:e.workingDir.trim(),model:e.model.trim()||void 0})}),a=await n.json();if(n.status===400){Sr(t,a?.message??a?.error??"invalid_input");return}if(!n.ok||!a?.job?.id)throw new Error(a?.error??`http_${n.status}`);rn(a.job),ra=window.setInterval(()=>{pb(a.job.id).catch(o=>{Qs(),rn({id:a.job.id,status:"failed",message:o instanceof Error?o.message:String(o)})})},1200)}catch(n){rn({id:"",status:"failed",message:n instanceof Error?n.message:String(n)})}}async function pb(e){let t=await fetch(`/api/bot-onboarding/${encodeURIComponent(e)}`),n=await t.json();if(!t.ok||!n?.job)throw new Error(n?.error??`http_${t.status}`);rn(n.job),(n.job.status==="completed"||n.job.status==="failed"||n.job.status==="needs_owner")&&Qs()}async function fb(){Qs();let e=Er();Sr([{id:"claude-code",label:"Claude"}]),e.open||e.showModal();let t=await cb();e.open&&e.querySelector("#onboarding-form")&&Sr(t)}function dd(){let e=document.getElementById("add-bot-btn");e&&(e.onclick=()=>{fb()})}var mb={monitor:'<rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/>',sun:'<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>',moon:'<path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/>',cpu:'<path d="M12 20v2"/><path d="M12 2v2"/><path d="M17 20v2"/><path d="M17 2v2"/><path d="M2 12h2"/><path d="M2 17h2"/><path d="M2 7h2"/><path d="M20 12h2"/><path d="M20 17h2"/><path d="M20 7h2"/><path d="M7 20v2"/><path d="M7 2v2"/><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="8" y="8" width="8" height="8" rx="1"/>',sparkles:'<path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"/><path d="M20 2v4"/><path d="M22 4h-4"/><circle cx="4" cy="20" r="2"/>',zap:'<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>',terminal:'<path d="M12 19h8"/><path d="m4 17 6-6-6-6"/>',keyRound:'<path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"/><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"/>',network:'<rect x="16" y="16" width="6" height="6" rx="1"/><rect x="2" y="16" width="6" height="6" rx="1"/><rect x="9" y="2" width="6" height="6" rx="1"/><path d="M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"/><path d="M12 12V8"/>',swords:'<polyline points="14.5 17.5 3 6 3 3 6 3 17.5 14.5"/><line x1="13" x2="19" y1="19" y2="13"/><line x1="16" x2="20" y1="16" y2="20"/><line x1="19" x2="21" y1="21" y2="19"/><polyline points="14.5 6.5 18 3 21 3 21 6 17.5 9.5"/><line x1="5" x2="9" y1="14" y2="18"/><line x1="7" x2="4" y1="17" y2="20"/><line x1="3" x2="5" y1="19" y2="21"/>',flame:'<path d="M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4"/>',ball:'<path d="M11 7a16 16 20 0 1 10.98 4.362"/><path d="M12 12a13 13 0 0 1-8.66 5"/><path d="M16.83 13.634a16 16 0 0 1-9.267 7.328"/><path d="M20.66 17A13 13 0 0 0 12 12a13 13 0 0 1 0-10"/><path d="M8.17 15.366a16 16 0 0 1-1.713-11.69"/><circle cx="12" cy="12" r="10"/>',chevron:'<path d="m6 9 6 6 6-6"/>'},fd=[{labelKey:"theme.base",options:[{value:"system",labelKey:"status.system",icon:"monitor"},{value:"light",labelKey:"status.light",icon:"sun"},{value:"dark",labelKey:"status.dark",icon:"moon"}]},{labelKey:"theme.skins",options:[{value:"cyber",labelKey:"skin.cyber",icon:"cpu"},{value:"genshin",labelKey:"skin.genshin",icon:"sparkles"},{value:"fallout",labelKey:"skin.fallout",icon:"zap"},{value:"prts",labelKey:"skin.prts",icon:"terminal"},{value:"bluearchive",labelKey:"skin.bluearchive",icon:"keyRound"},{value:"zzz",labelKey:"skin.zzz",icon:"network"},{value:"dragonball",labelKey:"skin.dragonball",icon:"flame"},{value:"ikun",labelKey:"skin.ikun",icon:"ball"}]}],pd=fd.flatMap(e=>e.options),Un=!1;function Tr(e){return`<svg class="tm-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${mb[e]??""}</svg>`}function hb(e){return e.replace(/[&<>"]/g,t=>({"&":"&","<":"<",">":">",'"':"""})[t])}function md(){let e=document.getElementById("theme-menu"),t=document.getElementById("theme-menu-btn"),n=document.getElementById("theme-menu-pop");if(!e||!t||!n)return;n.innerHTML=fd.map(o=>`<div class="tm-group" data-label-key="${o.labelKey}"></div>`+o.options.map(i=>`<button type="button" class="tm-item" role="option" data-value="${i.value}"><span class="tm-ic">${Tr(i.icon)}</span><span class="tm-label" data-label-key="${i.labelKey}"></span></button>`).join("")).join("");let a=o=>{Un=o,n.hidden=!Un,t.setAttribute("aria-expanded",String(Un)),e.classList.toggle("open",Un)};t.addEventListener("click",o=>{o.stopPropagation(),a(!Un)}),n.addEventListener("click",o=>{let i=o.target.closest(".tm-item");i&&(Qe.setTheme(i.dataset.value??"system"),a(!1))}),document.addEventListener("click",o=>{Un&&!e.contains(o.target)&&a(!1)}),document.addEventListener("keydown",o=>{o.key==="Escape"&&Un&&a(!1)}),Lr()}function Lr(){let e=document.getElementById("theme-menu-btn");if(!e)return;let t=pd.find(n=>n.value===Qe.theme)??pd[0];e.innerHTML=`<span class="tm-ic">${Tr(t.icon)}</span><span class="tm-current">${hb(s(t.labelKey))}</span><span class="tm-chev">${Tr("chevron")}</span>`,document.querySelectorAll("#theme-menu-pop [data-label-key]").forEach(n=>{n.textContent=s(n.dataset.labelKey??"")}),document.querySelectorAll("#theme-menu-pop .tm-item").forEach(n=>{n.classList.toggle("active",n.dataset.value===Qe.theme)})}var Je=document.getElementById("root"),Gn=!0,vd=!1,wd=["roles","role-profiles","bot-defaults","skills","team","connectors","insights","whiteboards"],Cr=!1;function gb(){if(Cr)return;Cr=!0;let e=document.createElement("div");e.id="auth-expired-overlay",e.style.cssText="position:fixed;inset:0;background:rgba(0,0,0,.65);display:flex;align-items:center;justify-content:center;z-index:9999",e.innerHTML='<div style="background:var(--surface);color:var(--fg);border:1px solid var(--border);border-radius:12px;padding:36px 40px;max-width:460px;width:90vw;text-align:center;box-shadow:0 12px 40px rgba(0,0,0,.35)"><h2 style="margin:0 0 14px;font-size:19px;color:var(--fg)">\u8BBF\u95EE\u94FE\u63A5\u5DF2\u5931\u6548</h2><p style="margin:0 0 24px;line-height:1.7;color:var(--muted,#8f959e);font-size:14px">\u5F53\u524D\u94FE\u63A5/\u8BBF\u95EE\u5DF2\u5931\u6548\uFF0C\u8BF7\u4F7F\u7528\u6700\u65B0\u6388\u6743\u94FE\u63A5\u91CD\u65B0\u8FDB\u5165\uFF08\u8FD0\u884C botmux dashboard \u83B7\u53D6\uFF09\u3002</p><button id="auth-expired-dismiss" type="button" style="padding:8px 22px;background:var(--accent);color:var(--on-accent);border:none;border-radius:8px;cursor:pointer;font-size:14px">\u77E5\u9053\u4E86</button></div>',document.body.appendChild(e);let t=()=>{e.remove(),Cr=!1};e.querySelector("#auth-expired-dismiss")?.addEventListener("click",t),e.addEventListener("click",n=>{n.target===e&&t()})}var Ir;function bb(){let e=document.getElementById("readonly-toast");e||(e=document.createElement("div"),e.id="readonly-toast",e.style.cssText="position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:9999;background:var(--fg,#1f2329);color:var(--bg,#fff);padding:10px 18px;border-radius:8px;font-size:13px;box-shadow:0 8px 24px rgba(0,0,0,.25)",document.body.appendChild(e)),e.textContent="\u5F53\u524D\u662F\u53EA\u8BFB\u8BBF\u95EE\uFF0C\u6B64\u64CD\u4F5C\u9700\u8981\u6388\u6743\u94FE\u63A5\uFF08\u8FD0\u884C botmux dashboard \u83B7\u53D6\uFF09",e.style.display="block",Ir&&window.clearTimeout(Ir),Ir=window.setTimeout(()=>{e.style.display="none"},4e3)}var yb=window.fetch.bind(window);window.fetch=async function(...t){let n=await yb(...t);if(n.status===401){let a=(t[1]?.method??"GET").toUpperCase();(a==="GET"||a==="HEAD")&&!vd?gb():bb()}return n};var Mr="";function ua(){let e=document.getElementById("attention-strip");if(!e)return;let t=[...ke.sessions.values()].map(o=>({s:o,reason:fn(o)})).filter(o=>!!o.reason).sort((o,i)=>ct(o.s)-ct(i.s));if(t.length===0){e.hidden=!0,e.innerHTML="",Mr="";return}let n=t[0],a=`
|
|
54
|
+
</article>`;let s=n.querySelector("#onboarding-form");n.querySelector("#ob-cancel")?.addEventListener("click",()=>n.close()),n.querySelector("#ob-cli")?.addEventListener("change",()=>K(e)),K(e),s?.addEventListener("submit",l=>{l.preventDefault();let k=n.querySelector("#ob-cli")?.value??"",se=n.querySelector("#ob-dir")?.value??"",le=n.querySelector("#ob-model")?.value??"";ge({cliId:k,workingDir:se,model:le},e)})}async function ge(e,t){h(),u({id:"",status:"starting"});try{let n=await fetch("/api/bot-onboarding/start",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({cliId:e.cliId,workingDir:e.workingDir.trim(),model:e.model.trim()||void 0})}),o=await n.json();if(n.status===400){M(t,o?.message??o?.error??"invalid_input");return}if(!n.ok||!o?.job?.id)throw new Error(o?.error??`http_${n.status}`);u(o.job),w=window.setInterval(()=>{fe(o.job.id).catch(a=>{h(),u({id:o.job.id,status:"failed",message:a instanceof Error?a.message:String(a)})})},1200)}catch(n){u({id:"",status:"failed",message:n instanceof Error?n.message:String(n)})}}async function fe(e){let t=await fetch(`/api/bot-onboarding/${encodeURIComponent(e)}`),n=await t.json();if(!t.ok||!n?.job)throw new Error(n?.error??`http_${t.status}`);u(n.job),(n.job.status==="completed"||n.job.status==="failed"||n.job.status==="needs_owner")&&h()}async function be(){h();let e=S();M([{id:"claude-code",label:"Claude"}]),e.open||e.showModal();let t=await me();e.open&&e.querySelector("#onboarding-form")&&M(t)}function W(){let e=document.getElementById("add-bot-btn");e&&(e.onclick=()=>{be()})}var he={monitor:'<rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/>',sun:'<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>',moon:'<path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/>',cpu:'<path d="M12 20v2"/><path d="M12 2v2"/><path d="M17 20v2"/><path d="M17 2v2"/><path d="M2 12h2"/><path d="M2 17h2"/><path d="M2 7h2"/><path d="M20 12h2"/><path d="M20 17h2"/><path d="M20 7h2"/><path d="M7 20v2"/><path d="M7 2v2"/><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="8" y="8" width="8" height="8" rx="1"/>',sparkles:'<path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"/><path d="M20 2v4"/><path d="M22 4h-4"/><circle cx="4" cy="20" r="2"/>',zap:'<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>',terminal:'<path d="M12 19h8"/><path d="m4 17 6-6-6-6"/>',keyRound:'<path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"/><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"/>',network:'<rect x="16" y="16" width="6" height="6" rx="1"/><rect x="2" y="16" width="6" height="6" rx="1"/><rect x="9" y="2" width="6" height="6" rx="1"/><path d="M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"/><path d="M12 12V8"/>',swords:'<polyline points="14.5 17.5 3 6 3 3 6 3 17.5 14.5"/><line x1="13" x2="19" y1="19" y2="13"/><line x1="16" x2="20" y1="16" y2="20"/><line x1="19" x2="21" y1="21" y2="19"/><polyline points="14.5 6.5 18 3 21 3 21 6 17.5 9.5"/><line x1="5" x2="9" y1="14" y2="18"/><line x1="7" x2="4" y1="17" y2="20"/><line x1="3" x2="5" y1="19" y2="21"/>',flame:'<path d="M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4"/>',ball:'<path d="M11 7a16 16 20 0 1 10.98 4.362"/><path d="M12 12a13 13 0 0 1-8.66 5"/><path d="M16.83 13.634a16 16 0 0 1-9.267 7.328"/><path d="M20.66 17A13 13 0 0 0 12 12a13 13 0 0 1 0-10"/><path d="M8.17 15.366a16 16 0 0 1-1.713-11.69"/><circle cx="12" cy="12" r="10"/>',chevron:'<path d="m6 9 6 6 6-6"/>'},F=[{labelKey:"theme.base",options:[{value:"system",labelKey:"status.system",icon:"monitor"},{value:"light",labelKey:"status.light",icon:"sun"},{value:"dark",labelKey:"status.dark",icon:"moon"}]},{labelKey:"theme.skins",options:[{value:"cyber",labelKey:"skin.cyber",icon:"cpu"},{value:"genshin",labelKey:"skin.genshin",icon:"sparkles"},{value:"fallout",labelKey:"skin.fallout",icon:"zap"},{value:"prts",labelKey:"skin.prts",icon:"terminal"},{value:"bluearchive",labelKey:"skin.bluearchive",icon:"keyRound"},{value:"zzz",labelKey:"skin.zzz",icon:"network"},{value:"dragonball",labelKey:"skin.dragonball",icon:"flame"},{value:"ikun",labelKey:"skin.ikun",icon:"ball"}]}],J=F.flatMap(e=>e.options),f=!1;function L(e){return`<svg class="tm-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${he[e]??""}</svg>`}function ye(e){return e.replace(/[&<>"]/g,t=>({"&":"&","<":"<",">":">",'"':"""})[t])}function G(){let e=document.getElementById("theme-menu"),t=document.getElementById("theme-menu-btn"),n=document.getElementById("theme-menu-pop");if(!e||!t||!n)return;n.innerHTML=F.map(a=>`<div class="tm-group" data-label-key="${a.labelKey}"></div>`+a.options.map(s=>`<button type="button" class="tm-item" role="option" data-value="${s.value}"><span class="tm-ic">${L(s.icon)}</span><span class="tm-label" data-label-key="${s.labelKey}"></span></button>`).join("")).join("");let o=a=>{f=a,n.hidden=!f,t.setAttribute("aria-expanded",String(f)),e.classList.toggle("open",f)};t.addEventListener("click",a=>{a.stopPropagation(),o(!f)}),n.addEventListener("click",a=>{let s=a.target.closest(".tm-item");s&&(d.setTheme(s.dataset.value??"system"),o(!1))}),document.addEventListener("click",a=>{f&&!e.contains(a.target)&&o(!1)}),document.addEventListener("keydown",a=>{a.key==="Escape"&&f&&o(!1)}),$()}function $(){let e=document.getElementById("theme-menu-btn");if(!e)return;let t=J.find(n=>n.value===d.theme)??J[0];e.innerHTML=`<span class="tm-ic">${L(t.icon)}</span><span class="tm-current">${ye(r(t.labelKey))}</span><span class="tm-chev">${L("chevron")}</span>`,document.querySelectorAll("#theme-menu-pop [data-label-key]").forEach(n=>{n.textContent=r(n.dataset.labelKey??"")}),document.querySelectorAll("#theme-menu-pop .tm-item").forEach(n=>{n.classList.toggle("active",n.dataset.value===d.theme)})}var ve=[{id:"legacy-workflow",routePrefix:"#/legacy-workflow",load:async()=>{let e=await import("./chunks/workflows-UB7OPYGI.js");return t=>e.renderWorkflowsPage(t)}},{id:"workflows",routePrefix:"#/workflows",rerenderOnUiChange:!1,load:async()=>{let e=await import("./chunks/v3-page-FVPUL665.js");return t=>e.renderV3RunsPage(t)}},{id:"groups",routePrefix:"#/groups",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/groups-page-C54PVKYP.js");return t=>e.renderGroupsPage(t)}},{id:"settings",routePrefix:"#/settings",rerenderOnUiChange:!1,load:async()=>{let e=await import("./chunks/settings-page-OSBZNCXL.js");return t=>e.renderSettingsPage(t)}},{id:"bot-defaults",routePrefix:"#/bot-defaults",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/bot-defaults-page-3EV7K6LJ.js");return t=>e.renderBotDefaultsPage(t)}},{id:"skills",routePrefix:"#/skills",rerenderOnUiChange:!1,load:async()=>{let e=await import("./chunks/skills-page-Y3VUAOYG.js");return t=>e.renderSkillsPage(t)}},{id:"connectors",routePrefix:"#/connectors",rerenderOnUiChange:!1,load:async()=>{let e=await import("./chunks/connectors-XPZKEHF6.js");return t=>e.renderConnectorsPage(t)}},{id:"team-manage",routePrefix:"#/team/manage",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/team-federation-page-CRH3WZPH.js");return t=>e.renderTeamManagePage(t)}},{id:"team",routePrefix:"#/team",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/team-federation-page-CRH3WZPH.js");return t=>e.renderTeamFederationPage(t)}},{id:"roles-profile",routePrefix:"#/roles/profile",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/roles-page-APUDLPVM.js");return t=>e.renderRoleProfilesPage(t)}},{id:"roles",routePrefix:"#/roles",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/roles-page-APUDLPVM.js");return t=>e.renderRolesPage(t)}},{id:"schedules",routePrefix:"#/schedules",rerenderOnUiChange:!1,load:async()=>{let e=await import("./chunks/schedules-WG2UKHSO.js");return t=>e.renderSchedulesPage(t)}},{id:"whiteboards",routePrefix:"#/whiteboards",rerenderOnUiChange:!1,load:async()=>{let e=await import("./chunks/whiteboards-page-HLCTYSSV.js");return t=>e.renderWhiteboardsPage(t)}},{id:"sessions",routePrefix:"#/sessions",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/sessions-page-F3U5NFPD.js");return t=>e.renderSessionsPage(t)}},{id:"office",routePrefix:"#/office",rerenderOnUiChange:!1,load:async()=>{let e=await import("./chunks/office-page-6DXYOG55.js");return t=>e.renderOfficePage(t)}},{id:"insights",routePrefix:"#/insights",rerenderOnUiChange:!0,load:async()=>{let e=await import("./chunks/insights-page-BBQYR7WY.js");return t=>e.renderInsightsPage(t)}}];function Q(e){return ve.find(t=>t.exact?e===t.routePrefix:e.startsWith(t.routePrefix))}async function V(){let e=await import("./chunks/overview-page-5PJCAMID.js");return t=>e.renderOverviewPage(t)}function Y(){return{seq:0,pageDispose:null,rerenderOnUiChange:!0}}function Z(e){let t=++e.seq;return e.pageDispose&&(e.pageDispose(),e.pageDispose=null),t}function X(e,t){return t===e.seq}async function j(e,t,n,o,a={}){let s=await o();if(!X(e,t))return!1;let c=s(n);return X(e,t)?(e.pageDispose=typeof c=="function"?c:null,e.rerenderOnUiChange=a.rerenderOnUiChange??!0,!0):(typeof c=="function"&&c(),!1)}var E=document.getElementById("root"),b=!0,re=!1,ae=["roles","role-profiles","bot-defaults","skills","team","connectors","insights","whiteboards"],P=!1;function we(){if(P)return;P=!0;let e=document.createElement("div");e.id="auth-expired-overlay",e.style.cssText="position:fixed;inset:0;background:rgba(0,0,0,.65);display:flex;align-items:center;justify-content:center;z-index:9999",e.innerHTML='<div style="background:var(--surface);color:var(--fg);border:1px solid var(--border);border-radius:12px;padding:36px 40px;max-width:460px;width:90vw;text-align:center;box-shadow:0 12px 40px rgba(0,0,0,.35)"><h2 style="margin:0 0 14px;font-size:19px;color:var(--fg)">\u8BBF\u95EE\u94FE\u63A5\u5DF2\u5931\u6548</h2><p style="margin:0 0 24px;line-height:1.7;color:var(--muted,#8f959e);font-size:14px">\u5F53\u524D\u94FE\u63A5/\u8BBF\u95EE\u5DF2\u5931\u6548\uFF0C\u8BF7\u4F7F\u7528\u6700\u65B0\u6388\u6743\u94FE\u63A5\u91CD\u65B0\u8FDB\u5165\uFF08\u8FD0\u884C botmux dashboard \u83B7\u53D6\uFF09\u3002</p><button id="auth-expired-dismiss" type="button" style="padding:8px 22px;background:var(--accent);color:var(--on-accent);border:none;border-radius:8px;cursor:pointer;font-size:14px">\u77E5\u9053\u4E86</button></div>',document.body.appendChild(e);let t=()=>{e.remove(),P=!1};e.querySelector("#auth-expired-dismiss")?.addEventListener("click",t),e.addEventListener("click",n=>{n.target===e&&t()})}var T;function xe(){let e=document.getElementById("readonly-toast");e||(e=document.createElement("div"),e.id="readonly-toast",e.style.cssText="position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:9999;background:var(--fg,#1f2329);color:var(--bg,#fff);padding:10px 18px;border-radius:8px;font-size:13px;box-shadow:0 8px 24px rgba(0,0,0,.25)",document.body.appendChild(e)),e.textContent="\u5F53\u524D\u662F\u53EA\u8BFB\u8BBF\u95EE\uFF0C\u6B64\u64CD\u4F5C\u9700\u8981\u6388\u6743\u94FE\u63A5\uFF08\u8FD0\u884C botmux dashboard \u83B7\u53D6\uFF09",e.style.display="block",T&&window.clearTimeout(T),T=window.setTimeout(()=>{e.style.display="none"},4e3)}var Oe=window.fetch.bind(window);window.fetch=async function(...t){let n=await Oe(...t);if(n.status===401){let o=(t[1]?.method??"GET").toUpperCase();(o==="GET"||o==="HEAD")&&!re?we():xe()}return n};var D="";function O(){let e=document.getElementById("attention-strip");if(!e)return;let t=[...g.sessions.values()].map(a=>({s:a,reason:z(a)})).filter(a=>!!a.reason).sort((a,s)=>v(a.s)-v(s.s));if(t.length===0){e.hidden=!0,e.innerHTML="",D="";return}let n=t[0],o=`
|
|
2569
55
|
<span class="attention-strip-ic" aria-hidden="true">!</span>
|
|
2570
|
-
<b>${
|
|
2571
|
-
<span class="attention-strip-longest">${
|
|
2572
|
-
<a class="attention-strip-go" href="#/sessions">${
|
|
56
|
+
<b>${i(r("strip.pending",{count:t.length}))}</b>
|
|
57
|
+
<span class="attention-strip-longest">${i(r("strip.longest",{time:I(v(n.s)),bot:B(n.s),reason:n.reason}))}</span>
|
|
58
|
+
<a class="attention-strip-go" href="#/sessions">${i(r("strip.handle"))}</a>`;e.hidden=!1,o!==D&&(D=o,e.innerHTML=o)}g.on(O);_().then(O);async function ke(){try{let e=await fetch("/api/settings");if(e.ok){let t=await e.json();b=!!t.authed,d.authed=b,re=!!(t.settings&&t.settings.publicReadOnly);let n=U(t.lang);n&&d.setLocale(n)}}catch{}}async function Me(e){if(b)try{await fetch("/api/settings",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({lang:e})})}catch{}}function Se(){for(let t of ae){let n=document.querySelector(`.sidebar-nav a[data-route="${t}"]`);n&&(n.style.display=b?"":"none")}let e=document.getElementById("add-bot-btn");e&&(e.style.display=b?"":"none")}async function Le(){if(b)try{let e=await fetch("/api/update/status");if(!e.ok)return;let t=await e.json(),n=document.querySelector('.sidebar-nav a[data-route="settings"]');if(!n)return;let o=t.behind===!0;n.classList.toggle("nav-has-update",o),o?n.title=r("update.navBadgeTitle",{version:`v${t.latest}`}):n.removeAttribute("title")}catch{}}function $e(e){e.innerHTML='<section class="auth-required" style="max-width:520px;margin:64px auto;text-align:center;background:var(--surface);color:var(--fg);border:1px solid var(--border);border-radius:14px;padding:40px 36px;box-shadow:0 8px 28px rgba(0,0,0,.12)"><h2 style="margin:0 0 12px;font-size:20px;color:var(--fg)">\u6B64\u9875\u9700\u8981\u6388\u6743\u94FE\u63A5</h2><p style="margin:0 0 24px;line-height:1.7;color:var(--muted);font-size:14px">\u4F60\u5F53\u524D\u662F\u53EA\u8BFB\u8BBF\u95EE\uFF0C\u7BA1\u7406\u9875\uFF08\u7FA4\u89D2\u8272 / Profiles / Bot \u914D\u7F6E / \u56E2\u961F / Webhook\uFF09\u9700\u8981\u6388\u6743\u94FE\u63A5\u3002\u8FD0\u884C <code>botmux dashboard</code> \u83B7\u53D6\u6700\u65B0\u94FE\u63A5\u540E\u5373\u53EF\u7BA1\u7406\u3002</p><a href="#/" style="display:inline-block;padding:8px 22px;background:var(--accent);color:var(--on-accent);border-radius:8px;text-decoration:none;font-size:14px">\u8FD4\u56DE\u603B\u89C8</a></section>'}var m=Y();function ee(e){for(let t of document.querySelectorAll(".sidebar-nav a")){let n=t.getAttribute("href")??"#/",o=e||"#/",a=n===o||n!=="#/"&&(o.startsWith(`${n}?`)||o.startsWith(`${n}/`));t.classList.toggle("active",a)}}async function C(){let e=Z(m),t=location.hash||"#/";if(!b&&ae.some(n=>t.startsWith("#/"+n))){$e(E),m.rerenderOnUiChange=!0,ee(t);return}if(t.startsWith("#/v3")){window.location.replace(`#/workflows${t.slice(4)}`);return}else if(/^#\/workflows(?:\/|-)catalog(?:[/?].*)?$/.test(t)){window.location.replace("#/workflows");return}if(t.startsWith("#/role-profiles")){window.location.replace(`#/roles/profile${t.slice(15)}`);return}try{let n=Q(t);await j(m,e,E,n?n.load:V,{rerenderOnUiChange:n?n.rerenderOnUiChange:!1})}catch(n){if(e!==m.seq)return;E.innerHTML=`<section class="page"><div class="empty">Dashboard route failed: ${i(String(n))}</div></section>`,m.pageDispose=null,m.rerenderOnUiChange=!0}finally{e===m.seq&&ee(t)}}var R=document.getElementById("status");function ie(){R&&(R.textContent=g.online?r("status.live"):r("status.disconnected"),R.className="connection-status "+(g.online?"online":"offline"))}g.on(ie);function te(){document.querySelectorAll("[data-i18n]").forEach(e=>{e.textContent=r(e.dataset.i18n??"")}),document.querySelectorAll("[data-locale]").forEach(e=>{e.classList.toggle("active",e.dataset.locale===d.locale)}),$(),ie()}function Ee(){document.querySelectorAll("[data-locale]").forEach(e=>{e.onclick=()=>{let t=e.dataset.locale;d.setLocale(t),Me(t)}}),G(),Te()}var ne="botmux.ownerAvatar.v1";function oe(e,t){let n=document.querySelector(".brand-mark");!n||!e||(n.innerHTML=`<img class="brand-owner-img" src="${i(e)}" alt="" decoding="async" referrerpolicy="no-referrer" onerror="this.remove()">`,t&&(n.title=t))}function Pe(){try{let e=JSON.parse(window.localStorage.getItem(ne)??"null");e?.avatarUrl&&oe(String(e.avatarUrl),e.name?String(e.name):void 0)}catch{}fetch("/api/owner-profile").then(e=>e.ok?e.json():null).then(e=>{if(!(!e?.ok||!e.avatarUrl)){oe(String(e.avatarUrl),e.name?String(e.name):void 0);try{window.localStorage.setItem(ne,JSON.stringify({avatarUrl:e.avatarUrl,name:e.name??""}))}catch{}}}).catch(()=>{})}function Te(){let e=document.getElementById("sidebar-toggle");if(!e)return;let t=q(window.localStorage),n=()=>{document.documentElement.dataset.sidebar=t,e.title=r(t==="collapsed"?"nav.sidebarExpand":"nav.sidebarCollapse")};n(),e.addEventListener("click",()=>{t=t==="collapsed"?"expanded":"collapsed",A(window.localStorage,t),n()})}(async()=>{d.init(),Ee(),W(),d.on(()=>{te(),O(),m.rerenderOnUiChange&&C()}),te(),O(),await ke(),Se(),Le(),Pe();try{await H()}catch(e){console.error("botmux dashboard bootstrap failed",e),g.setOnline(!1)}window.addEventListener("hashchange",()=>{C()}),C()})();export{we as showAuthExpiredOverlay,xe as showReadOnlyToast};
|