botmux 2.9.1 → 2.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/README.en.md +140 -76
  2. package/README.md +134 -75
  3. package/dist/adapters/backend/pty-backend.d.ts +6 -0
  4. package/dist/adapters/backend/pty-backend.d.ts.map +1 -1
  5. package/dist/adapters/backend/pty-backend.js +10 -0
  6. package/dist/adapters/backend/pty-backend.js.map +1 -1
  7. package/dist/adapters/backend/session-backend-selector.d.ts +11 -0
  8. package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -0
  9. package/dist/adapters/backend/session-backend-selector.js +26 -0
  10. package/dist/adapters/backend/session-backend-selector.js.map +1 -0
  11. package/dist/adapters/backend/tmux-backend.d.ts +80 -3
  12. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  13. package/dist/adapters/backend/tmux-backend.js +301 -49
  14. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  15. package/dist/adapters/backend/tmux-pipe-backend.d.ts +100 -0
  16. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -0
  17. package/dist/adapters/backend/tmux-pipe-backend.js +473 -0
  18. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -0
  19. package/dist/adapters/cli/aiden.d.ts.map +1 -1
  20. package/dist/adapters/cli/aiden.js +5 -0
  21. package/dist/adapters/cli/aiden.js.map +1 -1
  22. package/dist/adapters/cli/claude-code.d.ts +40 -1
  23. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  24. package/dist/adapters/cli/claude-code.js +470 -49
  25. package/dist/adapters/cli/claude-code.js.map +1 -1
  26. package/dist/adapters/cli/coco.d.ts.map +1 -1
  27. package/dist/adapters/cli/coco.js +191 -9
  28. package/dist/adapters/cli/coco.js.map +1 -1
  29. package/dist/adapters/cli/codex.d.ts.map +1 -1
  30. package/dist/adapters/cli/codex.js +94 -17
  31. package/dist/adapters/cli/codex.js.map +1 -1
  32. package/dist/adapters/cli/shared-hints.d.ts +2 -2
  33. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  34. package/dist/adapters/cli/shared-hints.js +7 -5
  35. package/dist/adapters/cli/shared-hints.js.map +1 -1
  36. package/dist/adapters/cli/types.d.ts +38 -1
  37. package/dist/adapters/cli/types.d.ts.map +1 -1
  38. package/dist/autostart.d.ts +14 -0
  39. package/dist/autostart.d.ts.map +1 -0
  40. package/dist/autostart.js +357 -0
  41. package/dist/autostart.js.map +1 -0
  42. package/dist/bot-registry.d.ts +29 -3
  43. package/dist/bot-registry.d.ts.map +1 -1
  44. package/dist/bot-registry.js +91 -12
  45. package/dist/bot-registry.js.map +1 -1
  46. package/dist/cli/arg-utils.d.ts +11 -0
  47. package/dist/cli/arg-utils.d.ts.map +1 -0
  48. package/dist/cli/arg-utils.js +25 -0
  49. package/dist/cli/arg-utils.js.map +1 -0
  50. package/dist/cli/create-group-resolver.d.ts +32 -0
  51. package/dist/cli/create-group-resolver.d.ts.map +1 -0
  52. package/dist/cli/create-group-resolver.js +70 -0
  53. package/dist/cli/create-group-resolver.js.map +1 -0
  54. package/dist/cli/quoted-render.d.ts +30 -0
  55. package/dist/cli/quoted-render.d.ts.map +1 -0
  56. package/dist/cli/quoted-render.js +29 -0
  57. package/dist/cli/quoted-render.js.map +1 -0
  58. package/dist/cli.js +916 -272
  59. package/dist/cli.js.map +1 -1
  60. package/dist/config.d.ts +6 -0
  61. package/dist/config.d.ts.map +1 -1
  62. package/dist/config.js +18 -8
  63. package/dist/config.js.map +1 -1
  64. package/dist/core/command-handler.d.ts +43 -0
  65. package/dist/core/command-handler.d.ts.map +1 -1
  66. package/dist/core/command-handler.js +167 -64
  67. package/dist/core/command-handler.js.map +1 -1
  68. package/dist/core/dashboard-events.d.ts +57 -0
  69. package/dist/core/dashboard-events.d.ts.map +1 -0
  70. package/dist/core/dashboard-events.js +23 -0
  71. package/dist/core/dashboard-events.js.map +1 -0
  72. package/dist/core/dashboard-ipc-server.d.ts +43 -0
  73. package/dist/core/dashboard-ipc-server.d.ts.map +1 -0
  74. package/dist/core/dashboard-ipc-server.js +481 -0
  75. package/dist/core/dashboard-ipc-server.js.map +1 -0
  76. package/dist/core/dashboard-locate.d.ts +20 -0
  77. package/dist/core/dashboard-locate.d.ts.map +1 -0
  78. package/dist/core/dashboard-locate.js +26 -0
  79. package/dist/core/dashboard-locate.js.map +1 -0
  80. package/dist/core/dashboard-rows.d.ts +31 -0
  81. package/dist/core/dashboard-rows.d.ts.map +1 -0
  82. package/dist/core/dashboard-rows.js +65 -0
  83. package/dist/core/dashboard-rows.js.map +1 -0
  84. package/dist/core/inherit-peer.d.ts +14 -0
  85. package/dist/core/inherit-peer.d.ts.map +1 -0
  86. package/dist/core/inherit-peer.js +32 -0
  87. package/dist/core/inherit-peer.js.map +1 -0
  88. package/dist/core/scheduler.d.ts +24 -0
  89. package/dist/core/scheduler.d.ts.map +1 -1
  90. package/dist/core/scheduler.js +93 -2
  91. package/dist/core/scheduler.js.map +1 -1
  92. package/dist/core/session-activity.d.ts +3 -0
  93. package/dist/core/session-activity.d.ts.map +1 -0
  94. package/dist/core/session-activity.js +20 -0
  95. package/dist/core/session-activity.js.map +1 -0
  96. package/dist/core/session-discovery.d.ts +39 -0
  97. package/dist/core/session-discovery.d.ts.map +1 -1
  98. package/dist/core/session-discovery.js +114 -21
  99. package/dist/core/session-discovery.js.map +1 -1
  100. package/dist/core/session-manager.d.ts +72 -0
  101. package/dist/core/session-manager.d.ts.map +1 -1
  102. package/dist/core/session-manager.js +396 -106
  103. package/dist/core/session-manager.js.map +1 -1
  104. package/dist/core/types.d.ts +27 -2
  105. package/dist/core/types.d.ts.map +1 -1
  106. package/dist/core/types.js +14 -3
  107. package/dist/core/types.js.map +1 -1
  108. package/dist/core/worker-pool.d.ts +72 -3
  109. package/dist/core/worker-pool.d.ts.map +1 -1
  110. package/dist/core/worker-pool.js +459 -38
  111. package/dist/core/worker-pool.js.map +1 -1
  112. package/dist/daemon.d.ts.map +1 -1
  113. package/dist/daemon.js +601 -309
  114. package/dist/daemon.js.map +1 -1
  115. package/dist/dashboard/aggregator.d.ts +41 -0
  116. package/dist/dashboard/aggregator.d.ts.map +1 -0
  117. package/dist/dashboard/aggregator.js +125 -0
  118. package/dist/dashboard/aggregator.js.map +1 -0
  119. package/dist/dashboard/auth.d.ts +23 -0
  120. package/dist/dashboard/auth.d.ts.map +1 -0
  121. package/dist/dashboard/auth.js +66 -0
  122. package/dist/dashboard/auth.js.map +1 -0
  123. package/dist/dashboard/operator-selector.d.ts +20 -0
  124. package/dist/dashboard/operator-selector.d.ts.map +1 -0
  125. package/dist/dashboard/operator-selector.js +39 -0
  126. package/dist/dashboard/operator-selector.js.map +1 -0
  127. package/dist/dashboard/registry.d.ts +35 -0
  128. package/dist/dashboard/registry.d.ts.map +1 -0
  129. package/dist/dashboard/registry.js +74 -0
  130. package/dist/dashboard/registry.js.map +1 -0
  131. package/dist/dashboard/web/app.d.ts +2 -0
  132. package/dist/dashboard/web/app.d.ts.map +1 -0
  133. package/dist/dashboard/web/app.js +45 -0
  134. package/dist/dashboard/web/app.js.map +1 -0
  135. package/dist/dashboard/web/bot-defaults.d.ts +2 -0
  136. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -0
  137. package/dist/dashboard/web/bot-defaults.js +201 -0
  138. package/dist/dashboard/web/bot-defaults.js.map +1 -0
  139. package/dist/dashboard/web/groups.d.ts +16 -0
  140. package/dist/dashboard/web/groups.d.ts.map +1 -0
  141. package/dist/dashboard/web/groups.js +584 -0
  142. package/dist/dashboard/web/groups.js.map +1 -0
  143. package/dist/dashboard/web/schedules.d.ts +2 -0
  144. package/dist/dashboard/web/schedules.d.ts.map +1 -0
  145. package/dist/dashboard/web/schedules.js +105 -0
  146. package/dist/dashboard/web/schedules.js.map +1 -0
  147. package/dist/dashboard/web/sessions.d.ts +2 -0
  148. package/dist/dashboard/web/sessions.d.ts.map +1 -0
  149. package/dist/dashboard/web/sessions.js +374 -0
  150. package/dist/dashboard/web/sessions.js.map +1 -0
  151. package/dist/dashboard/web/store.d.ts +23 -0
  152. package/dist/dashboard/web/store.d.ts.map +1 -0
  153. package/dist/dashboard/web/store.js +82 -0
  154. package/dist/dashboard/web/store.js.map +1 -0
  155. package/dist/dashboard-web/app.js +263 -0
  156. package/dist/dashboard-web/index.html +23 -0
  157. package/dist/dashboard-web/style.css +93 -0
  158. package/dist/dashboard.d.ts +2 -0
  159. package/dist/dashboard.d.ts.map +1 -0
  160. package/dist/dashboard.js +639 -0
  161. package/dist/dashboard.js.map +1 -0
  162. package/dist/im/lark/card-builder.d.ts +18 -1
  163. package/dist/im/lark/card-builder.d.ts.map +1 -1
  164. package/dist/im/lark/card-builder.js +70 -9
  165. package/dist/im/lark/card-builder.js.map +1 -1
  166. package/dist/im/lark/card-handler.d.ts.map +1 -1
  167. package/dist/im/lark/card-handler.js +123 -109
  168. package/dist/im/lark/card-handler.js.map +1 -1
  169. package/dist/im/lark/client.d.ts +35 -0
  170. package/dist/im/lark/client.d.ts.map +1 -1
  171. package/dist/im/lark/client.js +114 -11
  172. package/dist/im/lark/client.js.map +1 -1
  173. package/dist/im/lark/event-dispatcher.d.ts +88 -6
  174. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  175. package/dist/im/lark/event-dispatcher.js +398 -62
  176. package/dist/im/lark/event-dispatcher.js.map +1 -1
  177. package/dist/im/lark/forwarded-renderer.d.ts +23 -0
  178. package/dist/im/lark/forwarded-renderer.d.ts.map +1 -0
  179. package/dist/im/lark/forwarded-renderer.js +105 -0
  180. package/dist/im/lark/forwarded-renderer.js.map +1 -0
  181. package/dist/im/lark/md-card.d.ts +73 -0
  182. package/dist/im/lark/md-card.d.ts.map +1 -0
  183. package/dist/im/lark/md-card.js +332 -0
  184. package/dist/im/lark/md-card.js.map +1 -0
  185. package/dist/im/lark/merge-forward.d.ts +32 -0
  186. package/dist/im/lark/merge-forward.d.ts.map +1 -0
  187. package/dist/im/lark/merge-forward.js +110 -0
  188. package/dist/im/lark/merge-forward.js.map +1 -0
  189. package/dist/im/lark/message-parser.d.ts +9 -3
  190. package/dist/im/lark/message-parser.d.ts.map +1 -1
  191. package/dist/im/lark/message-parser.js +48 -13
  192. package/dist/im/lark/message-parser.js.map +1 -1
  193. package/dist/im/lark/quote-hint.d.ts +18 -0
  194. package/dist/im/lark/quote-hint.d.ts.map +1 -0
  195. package/dist/im/lark/quote-hint.js +23 -0
  196. package/dist/im/lark/quote-hint.js.map +1 -0
  197. package/dist/services/bridge-fallback-gate.d.ts +42 -0
  198. package/dist/services/bridge-fallback-gate.d.ts.map +1 -0
  199. package/dist/services/bridge-fallback-gate.js +12 -0
  200. package/dist/services/bridge-fallback-gate.js.map +1 -0
  201. package/dist/services/bridge-rotation-policy.d.ts +139 -0
  202. package/dist/services/bridge-rotation-policy.d.ts.map +1 -0
  203. package/dist/services/bridge-rotation-policy.js +125 -0
  204. package/dist/services/bridge-rotation-policy.js.map +1 -0
  205. package/dist/services/bridge-turn-queue.d.ts +154 -0
  206. package/dist/services/bridge-turn-queue.d.ts.map +1 -0
  207. package/dist/services/bridge-turn-queue.js +316 -0
  208. package/dist/services/bridge-turn-queue.js.map +1 -0
  209. package/dist/services/chat-first-seen-store.d.ts +27 -0
  210. package/dist/services/chat-first-seen-store.d.ts.map +1 -0
  211. package/dist/services/chat-first-seen-store.js +114 -0
  212. package/dist/services/chat-first-seen-store.js.map +1 -0
  213. package/dist/services/claude-transcript.d.ts +268 -0
  214. package/dist/services/claude-transcript.d.ts.map +1 -0
  215. package/dist/services/claude-transcript.js +798 -0
  216. package/dist/services/claude-transcript.js.map +1 -0
  217. package/dist/services/coco-transcript.d.ts +35 -0
  218. package/dist/services/coco-transcript.d.ts.map +1 -0
  219. package/dist/services/coco-transcript.js +192 -0
  220. package/dist/services/coco-transcript.js.map +1 -0
  221. package/dist/services/codex-bridge-queue.d.ts +56 -0
  222. package/dist/services/codex-bridge-queue.d.ts.map +1 -0
  223. package/dist/services/codex-bridge-queue.js +150 -0
  224. package/dist/services/codex-bridge-queue.js.map +1 -0
  225. package/dist/services/codex-transcript.d.ts +84 -0
  226. package/dist/services/codex-transcript.d.ts.map +1 -0
  227. package/dist/services/codex-transcript.js +298 -0
  228. package/dist/services/codex-transcript.js.map +1 -0
  229. package/dist/services/group-creator.d.ts +23 -0
  230. package/dist/services/group-creator.d.ts.map +1 -0
  231. package/dist/services/group-creator.js +75 -0
  232. package/dist/services/group-creator.js.map +1 -0
  233. package/dist/services/groups-store.d.ts +98 -0
  234. package/dist/services/groups-store.d.ts.map +1 -0
  235. package/dist/services/groups-store.js +213 -0
  236. package/dist/services/groups-store.js.map +1 -0
  237. package/dist/services/oncall-store.d.ts +80 -8
  238. package/dist/services/oncall-store.d.ts.map +1 -1
  239. package/dist/services/oncall-store.js +265 -55
  240. package/dist/services/oncall-store.js.map +1 -1
  241. package/dist/services/project-scanner.d.ts +1 -2
  242. package/dist/services/project-scanner.d.ts.map +1 -1
  243. package/dist/services/project-scanner.js +118 -68
  244. package/dist/services/project-scanner.js.map +1 -1
  245. package/dist/services/schedule-store.d.ts +5 -0
  246. package/dist/services/schedule-store.d.ts.map +1 -1
  247. package/dist/services/schedule-store.js +77 -1
  248. package/dist/services/schedule-store.js.map +1 -1
  249. package/dist/services/session-store.d.ts +22 -0
  250. package/dist/services/session-store.d.ts.map +1 -1
  251. package/dist/services/session-store.js +62 -4
  252. package/dist/services/session-store.js.map +1 -1
  253. package/dist/setup/bots-store.d.ts +3 -0
  254. package/dist/setup/bots-store.d.ts.map +1 -0
  255. package/dist/setup/bots-store.js +24 -0
  256. package/dist/setup/bots-store.js.map +1 -0
  257. package/dist/setup/detect-platform.d.ts +14 -0
  258. package/dist/setup/detect-platform.d.ts.map +1 -0
  259. package/dist/setup/detect-platform.js +139 -0
  260. package/dist/setup/detect-platform.js.map +1 -0
  261. package/dist/setup/ensure-fonts.d.ts +13 -0
  262. package/dist/setup/ensure-fonts.d.ts.map +1 -0
  263. package/dist/setup/ensure-fonts.js +225 -0
  264. package/dist/setup/ensure-fonts.js.map +1 -0
  265. package/dist/setup/ensure-tmux.d.ts +60 -0
  266. package/dist/setup/ensure-tmux.d.ts.map +1 -0
  267. package/dist/setup/ensure-tmux.js +236 -0
  268. package/dist/setup/ensure-tmux.js.map +1 -0
  269. package/dist/setup/index.d.ts +9 -0
  270. package/dist/setup/index.d.ts.map +1 -0
  271. package/dist/setup/index.js +46 -0
  272. package/dist/setup/index.js.map +1 -0
  273. package/dist/setup/lark-scopes.json +301 -0
  274. package/dist/setup/register-app.d.ts +52 -0
  275. package/dist/setup/register-app.d.ts.map +1 -0
  276. package/dist/setup/register-app.js +91 -0
  277. package/dist/setup/register-app.js.map +1 -0
  278. package/dist/setup/verify-permissions.d.ts +115 -0
  279. package/dist/setup/verify-permissions.d.ts.map +1 -0
  280. package/dist/setup/verify-permissions.js +207 -0
  281. package/dist/setup/verify-permissions.js.map +1 -0
  282. package/dist/skills/definitions.d.ts +4 -0
  283. package/dist/skills/definitions.d.ts.map +1 -1
  284. package/dist/skills/definitions.js +133 -19
  285. package/dist/skills/definitions.js.map +1 -1
  286. package/dist/skills/installer.d.ts +3 -1
  287. package/dist/skills/installer.d.ts.map +1 -1
  288. package/dist/skills/installer.js +18 -3
  289. package/dist/skills/installer.js.map +1 -1
  290. package/dist/types.d.ts +44 -0
  291. package/dist/types.d.ts.map +1 -1
  292. package/dist/utils/bot-routing.d.ts +6 -0
  293. package/dist/utils/bot-routing.d.ts.map +1 -0
  294. package/dist/utils/bot-routing.js +50 -0
  295. package/dist/utils/bot-routing.js.map +1 -0
  296. package/dist/utils/file-lock.d.ts +2 -0
  297. package/dist/utils/file-lock.d.ts.map +1 -0
  298. package/dist/utils/file-lock.js +114 -0
  299. package/dist/utils/file-lock.js.map +1 -0
  300. package/dist/utils/font-installer.js +1 -1
  301. package/dist/utils/font-installer.js.map +1 -1
  302. package/dist/utils/idle-detector.d.ts +6 -0
  303. package/dist/utils/idle-detector.d.ts.map +1 -1
  304. package/dist/utils/idle-detector.js +25 -4
  305. package/dist/utils/idle-detector.js.map +1 -1
  306. package/dist/utils/logger.d.ts +10 -0
  307. package/dist/utils/logger.d.ts.map +1 -1
  308. package/dist/utils/logger.js +60 -8
  309. package/dist/utils/logger.js.map +1 -1
  310. package/dist/utils/render-dimensions.d.ts +48 -0
  311. package/dist/utils/render-dimensions.d.ts.map +1 -0
  312. package/dist/utils/render-dimensions.js +55 -0
  313. package/dist/utils/render-dimensions.js.map +1 -0
  314. package/dist/utils/screen-analyzer.d.ts.map +1 -1
  315. package/dist/utils/screen-analyzer.js +24 -0
  316. package/dist/utils/screen-analyzer.js.map +1 -1
  317. package/dist/utils/screenshot-renderer.d.ts.map +1 -1
  318. package/dist/utils/screenshot-renderer.js +67 -23
  319. package/dist/utils/screenshot-renderer.js.map +1 -1
  320. package/dist/utils/terminal-renderer.d.ts +16 -0
  321. package/dist/utils/terminal-renderer.d.ts.map +1 -1
  322. package/dist/utils/terminal-renderer.js +40 -23
  323. package/dist/utils/terminal-renderer.js.map +1 -1
  324. package/dist/utils/transient-snapshot.d.ts +28 -0
  325. package/dist/utils/transient-snapshot.d.ts.map +1 -0
  326. package/dist/utils/transient-snapshot.js +96 -0
  327. package/dist/utils/transient-snapshot.js.map +1 -0
  328. package/dist/worker.js +2220 -83
  329. package/dist/worker.js.map +1 -1
  330. package/package.json +12 -5
@@ -0,0 +1,584 @@
1
+ // Groups & Bots page: chat × bot membership matrix + add-bots modal.
2
+ // The aggregator at /api/groups fans out to all online daemons and merges chats
3
+ // by chatId; the dashboard displays this as a matrix where each cell shows
4
+ // whether a bot is a member of a given chat.
5
+ let cache = { chats: [], bots: [] };
6
+ const PAGE_HTML = `
7
+ <form id="g-filters" class="filters">
8
+ <input type="search" name="q" placeholder="search chat name / id / owner" />
9
+ <label><input type="checkbox" name="missing"> missing-bot only</label>
10
+ <button type="button" id="g-refresh">Refresh</button>
11
+ <button type="button" id="g-create">+ Create new group</button>
12
+ </form>
13
+ <table>
14
+ <thead id="g-head"></thead>
15
+ <tbody id="g-body"></tbody>
16
+ </table>
17
+ <dialog id="g-drawer"></dialog>
18
+ `;
19
+ function escapeHtml(s) {
20
+ return s.replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
21
+ }
22
+ async function loadGroups() {
23
+ const r = await fetch('/api/groups');
24
+ cache = await r.json();
25
+ }
26
+ /** Fetch /api/groups once and return the parsed payload without mutating
27
+ * `cache` — used by refreshUntilSeen so we can decide whether to commit. */
28
+ async function fetchGroups() {
29
+ const r = await fetch('/api/groups');
30
+ return r.json();
31
+ }
32
+ /** True iff every expected bot id appears in the row's memberBots with
33
+ * inChat:true. Used by refreshUntilSeen to defer committing a canonical
34
+ * snapshot until all invited bots have caught up Lark-side. Exported so
35
+ * tests can exercise the predicate without spinning up jsdom. */
36
+ export function allExpectedInChat(row, expectedBotIds) {
37
+ if (expectedBotIds.size === 0)
38
+ return true;
39
+ const members = (row?.memberBots ?? []);
40
+ for (const id of expectedBotIds) {
41
+ if (!members.some(m => m.larkAppId === id && m.inChat))
42
+ return false;
43
+ }
44
+ return true;
45
+ }
46
+ /** Render the bot-picker checkboxes shared by "Create new group" and
47
+ * "Add bots". Always iterates `bots` in its given order (the aggregator
48
+ * hands cache.bots back sorted by botIndex), so both modals show the
49
+ * same order. `excludeIds` removes bots that are already in the chat
50
+ * for the Add-bots flow. Exported for tests. */
51
+ export function renderBotCheckboxes(bots, excludeIds) {
52
+ return bots
53
+ .filter(b => !excludeIds || !excludeIds.has(b.larkAppId))
54
+ .map(b => `
55
+ <label class="checkbox-row">
56
+ <input type="checkbox" name="bot" value="${escapeHtml(b.larkAppId)}">
57
+ ${escapeHtml(b.botName ?? b.larkAppId)} <small>(${escapeHtml(b.larkAppId)})</small>
58
+ </label>
59
+ `).join('');
60
+ }
61
+ export async function renderGroupsPage(root) {
62
+ root.innerHTML = PAGE_HTML;
63
+ const head = root.querySelector('#g-head');
64
+ const body = root.querySelector('#g-body');
65
+ const form = root.querySelector('#g-filters');
66
+ const refreshBtn = root.querySelector('#g-refresh');
67
+ const drawer = root.querySelector('#g-drawer');
68
+ refreshBtn.onclick = async () => {
69
+ refreshBtn.disabled = true;
70
+ try {
71
+ await loadGroups();
72
+ rerender();
73
+ }
74
+ finally {
75
+ refreshBtn.disabled = false;
76
+ }
77
+ };
78
+ const createBtn = root.querySelector('#g-create');
79
+ createBtn.onclick = () => openCreateModal();
80
+ await loadGroups();
81
+ function openCreateModal() {
82
+ const allBots = cache.bots;
83
+ if (allBots.length === 0) {
84
+ alert('No bots online. Restart the daemon first.');
85
+ return;
86
+ }
87
+ drawer.innerHTML = `
88
+ <article>
89
+ <header><h3>Create new group</h3></header>
90
+ <p>Pick bots to invite. The dashboard auto-selects an online daemon as the chat creator/owner; the rest are added as members in the same call.</p>
91
+ <form id="g-createform">
92
+ <label class="form-row">
93
+ <span>Group name <small>(optional)</small></span>
94
+ <input type="text" name="name" placeholder="e.g. AI ChangeLog" maxlength="60">
95
+ </label>
96
+ <fieldset>
97
+ <legend>Bots</legend>
98
+ ${renderBotCheckboxes(allBots)}
99
+ </fieldset>
100
+ <div class="actions">
101
+ <button type="submit">Create</button>
102
+ <button type="button" id="g-create-cancel">Cancel</button>
103
+ </div>
104
+ </form>
105
+ </article>`;
106
+ drawer.showModal();
107
+ drawer.querySelector('#g-create-cancel').onclick = () => drawer.close();
108
+ drawer.querySelector('#g-createform').onsubmit = async (ev) => {
109
+ ev.preventDefault();
110
+ const fd = new FormData(ev.target);
111
+ const name = (fd.get('name') ?? '').trim();
112
+ const ids = fd.getAll('bot');
113
+ if (ids.length === 0) {
114
+ alert('Pick at least one bot.');
115
+ return;
116
+ }
117
+ const submitBtn = ev.target.querySelector('button[type=submit]');
118
+ if (submitBtn) {
119
+ submitBtn.disabled = true;
120
+ submitBtn.textContent = 'Creating...';
121
+ }
122
+ try {
123
+ const r = await fetch('/api/groups/create', {
124
+ method: 'POST',
125
+ headers: { 'content-type': 'application/json' },
126
+ body: JSON.stringify({ name: name || undefined, larkAppIds: ids }),
127
+ });
128
+ const respBody = await r.json();
129
+ if (respBody.ok && respBody.chatId) {
130
+ renderCreateSuccess(respBody);
131
+ // Lark's chat.list has eventual consistency: the chat we just
132
+ // created via /api/groups/create often doesn't appear in the next
133
+ // /api/groups response for a few seconds. Without intervention the
134
+ // background refresh would overwrite cache with a stale snapshot
135
+ // and the new group would silently vanish from the matrix until
136
+ // the user hit Refresh manually.
137
+ //
138
+ // Optimistic insert: render the new group instantly using the
139
+ // creator's larkAppId + the form's selected bot ids minus any
140
+ // invalidBotIds Lark rejected. The refresh poll below keeps
141
+ // re-fetching until Lark confirms ALL expected bots show inChat,
142
+ // then commits the canonical response; until then we keep the
143
+ // optimistic row. Stopping on first sight of just `chatId` would
144
+ // commit a partial-membership snapshot — see Codex review.
145
+ const invalidBotIds = Array.isArray(respBody.invalidBotIds) ? respBody.invalidBotIds : [];
146
+ const validIds = ids.filter(id => !invalidBotIds.includes(id));
147
+ const expectedBotIds = new Set(validIds);
148
+ if (typeof respBody.creator === 'string' && respBody.creator)
149
+ expectedBotIds.add(respBody.creator);
150
+ injectOptimisticChat(respBody.chatId, name || respBody.chatId, validIds, respBody.creator);
151
+ rerender();
152
+ void refreshUntilSeen(respBody.chatId, expectedBotIds).catch(() => { });
153
+ }
154
+ else {
155
+ alert(`Failed: ${respBody.error ?? r.status}`);
156
+ drawer.close();
157
+ }
158
+ }
159
+ catch (e) {
160
+ alert('Network error: ' + e);
161
+ drawer.close();
162
+ }
163
+ };
164
+ function injectOptimisticChat(chatId, displayName, memberIds, creator) {
165
+ const inChatSet = new Set(memberIds);
166
+ if (creator)
167
+ inChatSet.add(creator);
168
+ const memberBots = cache.bots.map((b) => ({
169
+ larkAppId: b.larkAppId,
170
+ botName: b.botName,
171
+ inChat: inChatSet.has(b.larkAppId),
172
+ oncallChat: null,
173
+ }));
174
+ const optimistic = {
175
+ chatId,
176
+ name: displayName,
177
+ ownerId: creator ?? null,
178
+ memberBots,
179
+ };
180
+ // Drop any duplicate (defensive — shouldn't fire, but cheap) and
181
+ // prepend so the new row lands at the top of the matrix.
182
+ cache.chats = [optimistic, ...cache.chats.filter((c) => c.chatId !== chatId)];
183
+ }
184
+ async function refreshUntilSeen(chatId, expectedBotIds) {
185
+ // Total budget ≈ 0.6 + 5*1.2 = ~6.6s. Commit only when the row is
186
+ // present AND every expected bot reports inChat:true — otherwise we'd
187
+ // overwrite our optimistic ✓ marks with a partial canonical snapshot
188
+ // (creator daemon often lags vs. invitee daemons on Lark's side).
189
+ // If the budget runs out the optimistic row stays put; next manual
190
+ // Refresh will reconcile.
191
+ const delays = [600, 1200, 1200, 1200, 1200, 1200];
192
+ for (const d of delays) {
193
+ await new Promise(r => setTimeout(r, d));
194
+ let next;
195
+ try {
196
+ next = await fetchGroups();
197
+ }
198
+ catch {
199
+ continue;
200
+ }
201
+ const row = (next.chats ?? []).find((c) => c.chatId === chatId);
202
+ if (row && allExpectedInChat(row, expectedBotIds)) {
203
+ cache = next;
204
+ rerender();
205
+ return;
206
+ }
207
+ }
208
+ }
209
+ }
210
+ function renderCreateSuccess(resp) {
211
+ const chatId = String(resp.chatId);
212
+ const appLink = `https://applink.feishu.cn/client/chat/open?openChatId=${encodeURIComponent(chatId)}`;
213
+ const invalidBots = (resp.invalidBotIds ?? []);
214
+ const invalidUsers = (resp.invalidUserIds ?? []);
215
+ const auto = resp.autoInvitedOpenId;
216
+ const rejected = !!resp.autoInviteRejected;
217
+ const ownerTo = resp.ownerTransferredTo;
218
+ const transferErr = resp.transferError;
219
+ const notifyMsgId = resp.notifyMessageId;
220
+ const notifyErr = resp.notifyError;
221
+ let inviteNote;
222
+ if (auto) {
223
+ const transferLine = ownerTo
224
+ ? `<br><small>群主已从机器人转让给你。</small>`
225
+ : transferErr
226
+ ? `<br><small class="hint-warn-inline">⚠ 自动转让群主失败(${escapeHtml(transferErr)}),你现在是成员但群主仍是机器人。</small>`
227
+ : '';
228
+ const notifyLine = notifyMsgId
229
+ ? `<br><small>机器人已在群里 @ 了你(消息 id <code>${escapeHtml(notifyMsgId)}</code>),看飞书通知就能进群。</small>`
230
+ : notifyErr
231
+ ? `<br><small class="hint-warn-inline">⚠ 自动 @ 通知失败(${escapeHtml(notifyErr)}),新群可能不会主动出现在你侧边栏,建议从下面按钮跳进去。</small>`
232
+ : '';
233
+ inviteNote = `<p class="hint-ok">已自动邀请你(<code>${escapeHtml(auto)}</code>)作为成员。${transferLine}${notifyLine}</p>`;
234
+ }
235
+ else if (rejected) {
236
+ inviteNote = `<p class="hint-warn">飞书拒绝了自动邀请(你的 open_id 在创建者 bot 的 scope 下不可用)。<strong>你目前不是新群成员</strong>,需要让群里的某个机器人手动把你加进来。</p>`;
237
+ }
238
+ else {
239
+ inviteNote = `<p class="hint-warn">没在 dashboard 缓存里找到 ownerOpenId,<strong>没有自动邀请你</strong>。点开下面链接前,先让群里任一机器人手动把你加进去。</p>`;
240
+ }
241
+ const invalidNote = [
242
+ invalidBots.length ? `<li>无效 bot id: <code>${invalidBots.map(escapeHtml).join(', ')}</code></li>` : '',
243
+ invalidUsers.length ? `<li>无效用户 open_id: <code>${invalidUsers.map(escapeHtml).join(', ')}</code></li>` : '',
244
+ ].filter(Boolean).join('');
245
+ drawer.innerHTML = `
246
+ <article>
247
+ <header><h3>群创建成功</h3></header>
248
+ <p><b>chatId:</b> <code>${escapeHtml(chatId)}</code> <button type="button" data-copy="${escapeHtml(chatId)}">copy</button></p>
249
+ <p><b>创建者:</b> <code>${escapeHtml(resp.creator ?? '?')}</code></p>
250
+ ${inviteNote}
251
+ ${invalidNote ? `<ul>${invalidNote}</ul>` : ''}
252
+ <div class="actions">
253
+ <a class="btn-link primary" href="${appLink}" target="_blank" rel="noopener">↗ 打开新群</a>
254
+ <button type="button" id="g-create-close">关闭</button>
255
+ </div>
256
+ </article>`;
257
+ drawer.querySelectorAll('[data-copy]').forEach(b => {
258
+ b.onclick = () => {
259
+ navigator.clipboard.writeText(b.dataset.copy ?? '');
260
+ b.textContent = 'copied';
261
+ setTimeout(() => { b.textContent = 'copy'; }, 800);
262
+ };
263
+ });
264
+ drawer.querySelector('#g-create-close').onclick = () => drawer.close();
265
+ }
266
+ function renderHead() {
267
+ head.innerHTML = `<tr>
268
+ <th>chat</th>
269
+ ${cache.bots.map(b => `<th>${escapeHtml(b.botName ?? b.larkAppId)}</th>`).join('')}
270
+ <th>actions</th>
271
+ </tr>`;
272
+ }
273
+ function rerender() {
274
+ renderHead();
275
+ const f = new FormData(form);
276
+ const q = (f.get('q') ?? '').toLowerCase();
277
+ const onlyMissing = !!f.get('missing');
278
+ const filtered = cache.chats
279
+ .filter(c => !q ||
280
+ (c.name ?? '').toLowerCase().includes(q) ||
281
+ c.chatId.toLowerCase().includes(q) ||
282
+ (c.ownerId ?? '').toLowerCase().includes(q))
283
+ .filter(c => !onlyMissing || c.memberBots.some((m) => !m.inChat));
284
+ if (filtered.length === 0) {
285
+ body.innerHTML = `<tr><td colspan="${cache.bots.length + 2}" class="empty">No chats match the filter.</td></tr>`;
286
+ return;
287
+ }
288
+ body.innerHTML = filtered.map(c => `<tr data-chat="${escapeHtml(c.chatId)}">
289
+ <td>
290
+ <strong>${escapeHtml(c.name ?? c.chatId)}</strong><br>
291
+ <small><code>${escapeHtml(c.chatId)}</code></small>
292
+ </td>
293
+ ${cache.bots.map(b => {
294
+ const m = c.memberBots.find((m) => m.larkAppId === b.larkAppId);
295
+ const cell = !m ? '?' : m.error ? '!' : m.inChat ? '✓' : '✗';
296
+ const cls = !m ? 'cell-unknown' : m.error ? 'cell-error' : m.inChat ? 'cell-in' : 'cell-out';
297
+ return `<td class="${cls}" title="${escapeHtml(m?.error ?? '')}">${cell}</td>`;
298
+ }).join('')}
299
+ <td>
300
+ <button class="add-bots" type="button">Add bots</button>
301
+ <button class="manage-chat" type="button">Manage</button>
302
+ </td>
303
+ </tr>`).join('');
304
+ }
305
+ rerender();
306
+ body.addEventListener('click', async (e) => {
307
+ const btn = e.target.closest('button.add-bots');
308
+ if (!btn)
309
+ return;
310
+ const tr = btn.closest('tr[data-chat]');
311
+ const chatId = tr.dataset.chat;
312
+ const chat = cache.chats.find(c => c.chatId === chatId);
313
+ if (!chat)
314
+ return;
315
+ // Iterate cache.bots (botIndex-sorted by the aggregator) so this modal's
316
+ // order matches "Create new group" exactly. memberBots is only used to
317
+ // compute which bots to hide as already-in-chat.
318
+ const inChatSet = new Set(chat.memberBots.filter((m) => m.inChat).map((m) => m.larkAppId));
319
+ const missing = cache.bots.filter((b) => !inChatSet.has(b.larkAppId));
320
+ if (!missing.length) {
321
+ alert('All configured bots are already in this chat.');
322
+ return;
323
+ }
324
+ drawer.innerHTML = `
325
+ <article>
326
+ <header><h3>Add bots to ${escapeHtml(chat.name ?? chat.chatId)}</h3></header>
327
+ <p>Select bots to add. The dashboard will pick a bot that's already in the chat as the proxy.</p>
328
+ <form id="g-addform">
329
+ ${renderBotCheckboxes(cache.bots, inChatSet)}
330
+ <div class="actions">
331
+ <button type="submit">Confirm add</button>
332
+ <button type="button" id="g-cancel">Cancel</button>
333
+ </div>
334
+ </form>
335
+ </article>`;
336
+ drawer.showModal();
337
+ drawer.querySelector('#g-cancel').onclick = () => drawer.close();
338
+ drawer.querySelector('#g-addform').onsubmit = async (ev) => {
339
+ ev.preventDefault();
340
+ const fd = new FormData(ev.target);
341
+ const ids = fd.getAll('bot');
342
+ if (ids.length === 0) {
343
+ alert('Pick at least one bot.');
344
+ return;
345
+ }
346
+ try {
347
+ const r = await fetch(`/api/groups/${encodeURIComponent(chatId)}/add-bots`, {
348
+ method: 'POST',
349
+ headers: { 'content-type': 'application/json' },
350
+ body: JSON.stringify({ larkAppIds: ids }),
351
+ });
352
+ const respBody = await r.json();
353
+ if (respBody.error === 'no_proxy_bot') {
354
+ alert('No bot is currently in this chat — add one manually in Feishu first, then retry.');
355
+ }
356
+ else if (respBody.result) {
357
+ const lines = respBody.result.map((x) => `${x.id}: ${x.ok ? 'OK' : `failed (${x.error ?? 'unknown'})`}`).join('\n');
358
+ alert(lines);
359
+ // Refresh after change
360
+ await loadGroups();
361
+ rerender();
362
+ }
363
+ else {
364
+ alert(`Unexpected response: ${JSON.stringify(respBody)}`);
365
+ }
366
+ }
367
+ catch (e) {
368
+ alert('Network error: ' + e);
369
+ }
370
+ finally {
371
+ drawer.close();
372
+ }
373
+ };
374
+ });
375
+ body.addEventListener('click', async (e) => {
376
+ const btn = e.target.closest('button.manage-chat');
377
+ if (!btn)
378
+ return;
379
+ const tr = btn.closest('tr[data-chat]');
380
+ const chatId = tr.dataset.chat;
381
+ const chat = cache.chats.find(c => c.chatId === chatId);
382
+ if (!chat)
383
+ return;
384
+ openManageDrawer(chat);
385
+ });
386
+ function openManageDrawer(chat) {
387
+ const inChat = chat.memberBots.filter((m) => m.inChat);
388
+ // Lark `owner_id` returns app_id format for bot owners (string match works).
389
+ // For user owners it'll be an open_id which won't match any larkAppId.
390
+ const ownerAppId = typeof chat.ownerId === 'string' ? chat.ownerId : '';
391
+ drawer.innerHTML = `
392
+ <article>
393
+ <header><h3>Manage ${escapeHtml(chat.name ?? chat.chatId)}</h3></header>
394
+ <p><b>chatId:</b> <code>${escapeHtml(chat.chatId)}</code></p>
395
+ <p><b>owner:</b> <code>${escapeHtml(chat.ownerId ?? '(unknown)')}</code></p>
396
+
397
+ <fieldset>
398
+ <legend>Oncall 模式</legend>
399
+ <p><small>开启后:群内任何成员都能 @ 机器人提问,新话题直接用绑定目录启动 CLI;仅 allowedUsers 仍可执行 /cd /restart 等命令。</small></p>
400
+ ${inChat.length === 0
401
+ ? `<p class="empty">没有机器人在群里</p>`
402
+ : inChat.map((m) => {
403
+ const enabled = !!m.oncallChat;
404
+ const wd = m.oncallChat?.workingDir ?? '';
405
+ return `
406
+ <div class="oncall-row" data-bot="${escapeHtml(m.larkAppId)}">
407
+ <label class="checkbox-row">
408
+ <input type="checkbox" data-action="toggle" ${enabled ? 'checked' : ''}>
409
+ <strong>${escapeHtml(m.botName ?? m.larkAppId)}</strong>
410
+ <small>(${escapeHtml(m.larkAppId)})</small>
411
+ </label>
412
+ <div class="oncall-row-body">
413
+ <input type="text" data-input="workingDir" placeholder="e.g. /root/iserver/botmux"
414
+ value="${escapeHtml(wd)}" ${enabled ? '' : 'disabled'}>
415
+ <button type="button" data-action="save">Save</button>
416
+ <span class="oncall-status" data-status></span>
417
+ </div>
418
+ </div>
419
+ `;
420
+ }).join('')}
421
+ </fieldset>
422
+
423
+ <fieldset>
424
+ <legend>选择机器人退出群聊</legend>
425
+ ${inChat.length === 0
426
+ ? `<p class="empty">没有机器人在群里</p>`
427
+ : inChat.map((m) => `
428
+ <label class="checkbox-row">
429
+ <input type="checkbox" name="leave-bot" value="${escapeHtml(m.larkAppId)}">
430
+ ${escapeHtml(m.botName ?? m.larkAppId)}
431
+ <small>${m.larkAppId === ownerAppId ? '· 群主' : ''}</small>
432
+ </label>
433
+ `).join('')}
434
+ </fieldset>
435
+
436
+ <div class="actions">
437
+ <button id="g-leave-btn" type="button" ${inChat.length === 0 ? 'disabled' : ''}>选中机器人退出群聊</button>
438
+ <button id="g-disband-btn" type="button" class="contrast" ${inChat.length === 0 ? 'disabled' : ''}>解散群聊</button>
439
+ </div>
440
+ <p class="hint-warn"><small>解散群聊仅当某个在群机器人是群主时才会成功。否则飞书会返回错误,建议改用「退出群聊」。</small></p>
441
+ <form method="dialog"><button>关闭</button></form>
442
+ </article>`;
443
+ drawer.showModal();
444
+ // Oncall row interactions: toggle enables/disables the input; Save commits.
445
+ drawer.querySelectorAll('.oncall-row').forEach(row => {
446
+ const appId = row.dataset.bot;
447
+ const cb = row.querySelector('input[data-action=toggle]');
448
+ const input = row.querySelector('input[data-input=workingDir]');
449
+ const saveBtn = row.querySelector('button[data-action=save]');
450
+ const statusEl = row.querySelector('[data-status]');
451
+ cb.addEventListener('change', () => {
452
+ input.disabled = !cb.checked;
453
+ if (cb.checked)
454
+ input.focus();
455
+ });
456
+ saveBtn.addEventListener('click', async () => {
457
+ statusEl.textContent = '';
458
+ statusEl.className = 'oncall-status';
459
+ const want = cb.checked;
460
+ const wd = input.value.trim();
461
+ if (want && !wd) {
462
+ statusEl.textContent = '请填工作目录';
463
+ statusEl.classList.add('hint-warn-inline');
464
+ return;
465
+ }
466
+ saveBtn.disabled = true;
467
+ try {
468
+ const url = `/api/groups/${encodeURIComponent(chat.chatId)}/oncall/${encodeURIComponent(appId)}`;
469
+ const r = want
470
+ ? await fetch(url, {
471
+ method: 'PUT',
472
+ headers: { 'content-type': 'application/json' },
473
+ body: JSON.stringify({ workingDir: wd }),
474
+ })
475
+ : await fetch(url, { method: 'DELETE' });
476
+ const body = await r.json().catch(() => ({}));
477
+ if (r.ok && body.ok) {
478
+ statusEl.textContent = want
479
+ ? `✓ 已绑定 → ${body.resolvedPath ?? wd}`
480
+ : '✓ 已解绑';
481
+ statusEl.classList.add('hint-ok');
482
+ // Refresh aggregator cache + matrix; drawer state stays as-is
483
+ // (current row reflects the just-saved values).
484
+ try {
485
+ await loadGroups();
486
+ rerender();
487
+ }
488
+ catch { /* tolerate */ }
489
+ }
490
+ else {
491
+ statusEl.textContent = `✗ ${body.error ?? r.status}`;
492
+ statusEl.classList.add('hint-warn-inline');
493
+ }
494
+ }
495
+ catch (e) {
496
+ statusEl.textContent = `✗ ${e?.message ?? e}`;
497
+ statusEl.classList.add('hint-warn-inline');
498
+ }
499
+ finally {
500
+ saveBtn.disabled = false;
501
+ }
502
+ });
503
+ });
504
+ drawer.querySelector('#g-leave-btn').onclick = async () => {
505
+ const checked = [...drawer.querySelectorAll('input[name=leave-bot]:checked')]
506
+ .map(i => i.value);
507
+ if (checked.length === 0) {
508
+ alert('至少选一个机器人');
509
+ return;
510
+ }
511
+ if (!confirm(`确定让 ${checked.length} 个机器人退出群聊?该 bot 在此群的会话会一并关闭。`))
512
+ return;
513
+ try {
514
+ const r = await fetch(`/api/groups/${encodeURIComponent(chat.chatId)}/leave`, {
515
+ method: 'POST',
516
+ headers: { 'content-type': 'application/json' },
517
+ body: JSON.stringify({ larkAppIds: checked }),
518
+ });
519
+ const respBody = await r.json();
520
+ const lines = (respBody.result ?? []).map((x) => {
521
+ if (!x.ok)
522
+ return `${x.larkAppId}: 失败 (${x.error ?? 'unknown'})`;
523
+ const closed = (x.closedSessions ?? []);
524
+ const failed = closed.filter(c => !c.ok).length;
525
+ const ok = closed.length - failed;
526
+ const note = closed.length === 0
527
+ ? ''
528
+ : failed === 0 ? `(关闭 ${ok} 个会话)` : `(关闭 ${ok} 个,${failed} 个失败)`;
529
+ return `${x.larkAppId}: OK${note}`;
530
+ }).join('\n');
531
+ alert(lines || `Unexpected: ${JSON.stringify(respBody)}`);
532
+ await loadGroups();
533
+ rerender();
534
+ }
535
+ catch (e) {
536
+ alert('Network error: ' + e);
537
+ }
538
+ finally {
539
+ drawer.close();
540
+ }
541
+ };
542
+ drawer.querySelector('#g-disband-btn').onclick = async () => {
543
+ if (inChat.length === 0)
544
+ return;
545
+ if (!confirm(`确定解散群聊「${chat.name ?? chat.chatId}」?此操作不可恢复,本群所有机器人会话也会一并关闭。`))
546
+ return;
547
+ // Try the owner bot first (highest success probability), then fall back
548
+ // to other in-chat bots in case our ownerId match was wrong (e.g. owner
549
+ // is a user, but a creator-bot with operate_as_owner scope is in chat).
550
+ const ordered = [...inChat].sort((a, b) => (b.larkAppId === ownerAppId ? 1 : 0) - (a.larkAppId === ownerAppId ? 1 : 0));
551
+ const errs = [];
552
+ for (const m of ordered) {
553
+ try {
554
+ const r = await fetch(`/api/groups/${encodeURIComponent(chat.chatId)}/disband`, {
555
+ method: 'POST',
556
+ headers: { 'content-type': 'application/json' },
557
+ body: JSON.stringify({ larkAppId: m.larkAppId }),
558
+ });
559
+ const respBody = await r.json();
560
+ if (respBody.ok) {
561
+ const closed = (respBody.closedSessions ?? []);
562
+ const failed = closed.filter(c => !c.ok).length;
563
+ const ok = closed.length - failed;
564
+ const closedNote = closed.length === 0
565
+ ? ''
566
+ : failed === 0 ? `\n关闭了 ${ok} 个会话。` : `\n关闭了 ${ok} 个会话,${failed} 个会话关闭失败。`;
567
+ alert(`已解散(由 ${m.botName ?? m.larkAppId} 执行)${closedNote}`);
568
+ await loadGroups();
569
+ rerender();
570
+ drawer.close();
571
+ return;
572
+ }
573
+ errs.push(`${m.botName ?? m.larkAppId}: ${respBody.error ?? r.status}`);
574
+ }
575
+ catch (e) {
576
+ errs.push(`${m.botName ?? m.larkAppId}: ${e}`);
577
+ }
578
+ }
579
+ alert(`所有在群机器人均无法解散:\n${errs.join('\n')}\n\n建议改用「退出群聊」。`);
580
+ };
581
+ }
582
+ form.addEventListener('input', rerender);
583
+ }
584
+ //# sourceMappingURL=groups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groups.js","sourceRoot":"","sources":["../../../src/dashboard/web/groups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function renderSchedulesPage(root: HTMLElement): void;
2
+ //# sourceMappingURL=schedules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../../src/dashboard/web/schedules.ts"],"names":[],"mappings":"AAkCA,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,QAoEpD"}