botmux 2.88.1 → 2.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.en.md +3 -3
  2. package/README.md +3 -3
  3. package/dist/bot-registry.d.ts +2 -0
  4. package/dist/bot-registry.d.ts.map +1 -1
  5. package/dist/bot-registry.js +4 -0
  6. package/dist/bot-registry.js.map +1 -1
  7. package/dist/cli/dashboard-endpoint.d.ts.map +1 -1
  8. package/dist/cli/dashboard-endpoint.js +9 -3
  9. package/dist/cli/dashboard-endpoint.js.map +1 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +11 -3
  12. package/dist/cli.js.map +1 -1
  13. package/dist/core/command-handler.d.ts.map +1 -1
  14. package/dist/core/command-handler.js +9 -1
  15. package/dist/core/command-handler.js.map +1 -1
  16. package/dist/core/dashboard-command/groups.d.ts +20 -0
  17. package/dist/core/dashboard-command/groups.d.ts.map +1 -0
  18. package/dist/core/dashboard-command/groups.js +52 -0
  19. package/dist/core/dashboard-command/groups.js.map +1 -0
  20. package/dist/core/dashboard-command/index.d.ts +30 -0
  21. package/dist/core/dashboard-command/index.d.ts.map +1 -0
  22. package/dist/core/dashboard-command/index.js +81 -0
  23. package/dist/core/dashboard-command/index.js.map +1 -0
  24. package/dist/core/dashboard-command/overview.d.ts +29 -0
  25. package/dist/core/dashboard-command/overview.d.ts.map +1 -0
  26. package/dist/core/dashboard-command/overview.js +61 -0
  27. package/dist/core/dashboard-command/overview.js.map +1 -0
  28. package/dist/core/dashboard-command/owner-gate.d.ts +41 -0
  29. package/dist/core/dashboard-command/owner-gate.d.ts.map +1 -0
  30. package/dist/core/dashboard-command/owner-gate.js +40 -0
  31. package/dist/core/dashboard-command/owner-gate.js.map +1 -0
  32. package/dist/core/dashboard-command/schedules.d.ts +20 -0
  33. package/dist/core/dashboard-command/schedules.d.ts.map +1 -0
  34. package/dist/core/dashboard-command/schedules.js +47 -0
  35. package/dist/core/dashboard-command/schedules.js.map +1 -0
  36. package/dist/core/dashboard-command/sessions.d.ts +22 -0
  37. package/dist/core/dashboard-command/sessions.d.ts.map +1 -0
  38. package/dist/core/dashboard-command/sessions.js +43 -0
  39. package/dist/core/dashboard-command/sessions.js.map +1 -0
  40. package/dist/core/dashboard-command/settings.d.ts +21 -0
  41. package/dist/core/dashboard-command/settings.d.ts.map +1 -0
  42. package/dist/core/dashboard-command/settings.js +55 -0
  43. package/dist/core/dashboard-command/settings.js.map +1 -0
  44. package/dist/core/dashboard-command/stub.d.ts +16 -0
  45. package/dist/core/dashboard-command/stub.d.ts.map +1 -0
  46. package/dist/core/dashboard-command/stub.js +28 -0
  47. package/dist/core/dashboard-command/stub.js.map +1 -0
  48. package/dist/core/dashboard-command/workflows.d.ts +20 -0
  49. package/dist/core/dashboard-command/workflows.d.ts.map +1 -0
  50. package/dist/core/dashboard-command/workflows.js +45 -0
  51. package/dist/core/dashboard-command/workflows.js.map +1 -0
  52. package/dist/core/passthrough-commands.d.ts.map +1 -1
  53. package/dist/core/passthrough-commands.js +1 -1
  54. package/dist/core/passthrough-commands.js.map +1 -1
  55. package/dist/core/skills/discovery.d.ts +16 -0
  56. package/dist/core/skills/discovery.d.ts.map +1 -1
  57. package/dist/core/skills/discovery.js +48 -2
  58. package/dist/core/skills/discovery.js.map +1 -1
  59. package/dist/core/worker-pool.d.ts.map +1 -1
  60. package/dist/core/worker-pool.js +9 -2
  61. package/dist/core/worker-pool.js.map +1 -1
  62. package/dist/daemon-internal-client-wrapper.d.ts +41 -0
  63. package/dist/daemon-internal-client-wrapper.d.ts.map +1 -0
  64. package/dist/daemon-internal-client-wrapper.js +65 -0
  65. package/dist/daemon-internal-client-wrapper.js.map +1 -0
  66. package/dist/dashboard/aggregator.d.ts +12 -0
  67. package/dist/dashboard/aggregator.d.ts.map +1 -1
  68. package/dist/dashboard/aggregator.js +16 -0
  69. package/dist/dashboard/aggregator.js.map +1 -1
  70. package/dist/dashboard/auth.d.ts +7 -0
  71. package/dist/dashboard/auth.d.ts.map +1 -1
  72. package/dist/dashboard/auth.js +21 -0
  73. package/dist/dashboard/auth.js.map +1 -1
  74. package/dist/dashboard/card-model-types.d.ts +50 -0
  75. package/dist/dashboard/card-model-types.d.ts.map +1 -0
  76. package/dist/dashboard/card-model-types.js +9 -0
  77. package/dist/dashboard/card-model-types.js.map +1 -0
  78. package/dist/dashboard/daemon-internal-api.d.ts +90 -0
  79. package/dist/dashboard/daemon-internal-api.d.ts.map +1 -0
  80. package/dist/dashboard/daemon-internal-api.js +534 -0
  81. package/dist/dashboard/daemon-internal-api.js.map +1 -0
  82. package/dist/dashboard/daemon-internal-auth.d.ts +124 -0
  83. package/dist/dashboard/daemon-internal-auth.d.ts.map +1 -0
  84. package/dist/dashboard/daemon-internal-auth.js +188 -0
  85. package/dist/dashboard/daemon-internal-auth.js.map +1 -0
  86. package/dist/dashboard/daemon-internal-client.d.ts +67 -0
  87. package/dist/dashboard/daemon-internal-client.d.ts.map +1 -0
  88. package/dist/dashboard/daemon-internal-client.js +157 -0
  89. package/dist/dashboard/daemon-internal-client.js.map +1 -0
  90. package/dist/dashboard/dashboard-admins.d.ts +8 -0
  91. package/dist/dashboard/dashboard-admins.d.ts.map +1 -0
  92. package/dist/dashboard/dashboard-admins.js +15 -0
  93. package/dist/dashboard/dashboard-admins.js.map +1 -0
  94. package/dist/dashboard/federation-spoke-api.d.ts +3 -0
  95. package/dist/dashboard/federation-spoke-api.d.ts.map +1 -1
  96. package/dist/dashboard/federation-spoke-api.js +11 -8
  97. package/dist/dashboard/federation-spoke-api.js.map +1 -1
  98. package/dist/dashboard/groups-action-helpers.d.ts +69 -0
  99. package/dist/dashboard/groups-action-helpers.d.ts.map +1 -0
  100. package/dist/dashboard/groups-action-helpers.js +141 -0
  101. package/dist/dashboard/groups-action-helpers.js.map +1 -0
  102. package/dist/dashboard/groups-card-model.d.ts +120 -0
  103. package/dist/dashboard/groups-card-model.d.ts.map +1 -0
  104. package/dist/dashboard/groups-card-model.js +175 -0
  105. package/dist/dashboard/groups-card-model.js.map +1 -0
  106. package/dist/dashboard/schedule-card-model.d.ts +172 -0
  107. package/dist/dashboard/schedule-card-model.d.ts.map +1 -0
  108. package/dist/dashboard/schedule-card-model.js +290 -0
  109. package/dist/dashboard/schedule-card-model.js.map +1 -0
  110. package/dist/dashboard/session-card-model.d.ts +83 -0
  111. package/dist/dashboard/session-card-model.d.ts.map +1 -0
  112. package/dist/dashboard/session-card-model.js +196 -0
  113. package/dist/dashboard/session-card-model.js.map +1 -0
  114. package/dist/dashboard/settings-card-model.d.ts +73 -0
  115. package/dist/dashboard/settings-card-model.d.ts.map +1 -0
  116. package/dist/dashboard/settings-card-model.js +94 -0
  117. package/dist/dashboard/settings-card-model.js.map +1 -0
  118. package/dist/dashboard/settings-owner-resolver.d.ts +32 -0
  119. package/dist/dashboard/settings-owner-resolver.d.ts.map +1 -0
  120. package/dist/dashboard/settings-owner-resolver.js +43 -0
  121. package/dist/dashboard/settings-owner-resolver.js.map +1 -0
  122. package/dist/dashboard/settings-write-applier.d.ts +84 -0
  123. package/dist/dashboard/settings-write-applier.d.ts.map +1 -0
  124. package/dist/dashboard/settings-write-applier.js +119 -0
  125. package/dist/dashboard/settings-write-applier.js.map +1 -0
  126. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  127. package/dist/dashboard/web/i18n.js +60 -2
  128. package/dist/dashboard/web/i18n.js.map +1 -1
  129. package/dist/dashboard/web/insights.d.ts.map +1 -1
  130. package/dist/dashboard/web/insights.js +514 -68
  131. package/dist/dashboard/web/insights.js.map +1 -1
  132. package/dist/dashboard/web/skills.d.ts.map +1 -1
  133. package/dist/dashboard/web/skills.js +1 -1
  134. package/dist/dashboard/web/skills.js.map +1 -1
  135. package/dist/dashboard/web/whiteboards.js +3 -3
  136. package/dist/dashboard/workflow-api.d.ts.map +1 -1
  137. package/dist/dashboard/workflow-api.js +38 -119
  138. package/dist/dashboard/workflow-api.js.map +1 -1
  139. package/dist/dashboard/workflow-card-model.d.ts +127 -0
  140. package/dist/dashboard/workflow-card-model.d.ts.map +1 -0
  141. package/dist/dashboard/workflow-card-model.js +186 -0
  142. package/dist/dashboard/workflow-card-model.js.map +1 -0
  143. package/dist/dashboard/workflows-action-helpers.d.ts +105 -0
  144. package/dist/dashboard/workflows-action-helpers.d.ts.map +1 -0
  145. package/dist/dashboard/workflows-action-helpers.js +196 -0
  146. package/dist/dashboard/workflows-action-helpers.js.map +1 -0
  147. package/dist/dashboard-web/app.js +883 -795
  148. package/dist/dashboard-web/style.css +105 -3
  149. package/dist/dashboard.js +196 -269
  150. package/dist/dashboard.js.map +1 -1
  151. package/dist/i18n/en.d.ts.map +1 -1
  152. package/dist/i18n/en.js +266 -0
  153. package/dist/i18n/en.js.map +1 -1
  154. package/dist/i18n/zh.d.ts.map +1 -1
  155. package/dist/i18n/zh.js +266 -0
  156. package/dist/i18n/zh.js.map +1 -1
  157. package/dist/im/lark/card-builder.d.ts +2 -0
  158. package/dist/im/lark/card-builder.d.ts.map +1 -1
  159. package/dist/im/lark/card-builder.js +2 -1
  160. package/dist/im/lark/card-builder.js.map +1 -1
  161. package/dist/im/lark/card-handler.d.ts +54 -2
  162. package/dist/im/lark/card-handler.d.ts.map +1 -1
  163. package/dist/im/lark/card-handler.js +127 -1
  164. package/dist/im/lark/card-handler.js.map +1 -1
  165. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  166. package/dist/im/lark/event-dispatcher.js +22 -0
  167. package/dist/im/lark/event-dispatcher.js.map +1 -1
  168. package/dist/im/lark/groups-card.d.ts +90 -0
  169. package/dist/im/lark/groups-card.d.ts.map +1 -0
  170. package/dist/im/lark/groups-card.js +832 -0
  171. package/dist/im/lark/groups-card.js.map +1 -0
  172. package/dist/im/lark/overview-card.d.ts +101 -0
  173. package/dist/im/lark/overview-card.d.ts.map +1 -0
  174. package/dist/im/lark/overview-card.js +475 -0
  175. package/dist/im/lark/overview-card.js.map +1 -0
  176. package/dist/im/lark/schedules-card.d.ts +96 -0
  177. package/dist/im/lark/schedules-card.d.ts.map +1 -0
  178. package/dist/im/lark/schedules-card.js +892 -0
  179. package/dist/im/lark/schedules-card.js.map +1 -0
  180. package/dist/im/lark/sessions-card.d.ts +117 -0
  181. package/dist/im/lark/sessions-card.d.ts.map +1 -0
  182. package/dist/im/lark/sessions-card.js +870 -0
  183. package/dist/im/lark/sessions-card.js.map +1 -0
  184. package/dist/im/lark/settings-card.d.ts +125 -0
  185. package/dist/im/lark/settings-card.d.ts.map +1 -0
  186. package/dist/im/lark/settings-card.js +433 -0
  187. package/dist/im/lark/settings-card.js.map +1 -0
  188. package/dist/im/lark/workflows-card.d.ts +102 -0
  189. package/dist/im/lark/workflows-card.d.ts.map +1 -0
  190. package/dist/im/lark/workflows-card.js +737 -0
  191. package/dist/im/lark/workflows-card.js.map +1 -0
  192. package/dist/services/insight/classify.d.ts +2 -0
  193. package/dist/services/insight/classify.d.ts.map +1 -1
  194. package/dist/services/insight/classify.js +25 -0
  195. package/dist/services/insight/classify.js.map +1 -1
  196. package/dist/services/insight/claude-span-reader.d.ts.map +1 -1
  197. package/dist/services/insight/claude-span-reader.js +7 -4
  198. package/dist/services/insight/claude-span-reader.js.map +1 -1
  199. package/dist/services/insight/report.d.ts.map +1 -1
  200. package/dist/services/insight/report.js +102 -23
  201. package/dist/services/insight/report.js.map +1 -1
  202. package/dist/services/insight/subagent-reader.d.ts +19 -0
  203. package/dist/services/insight/subagent-reader.d.ts.map +1 -0
  204. package/dist/services/insight/subagent-reader.js +111 -0
  205. package/dist/services/insight/subagent-reader.js.map +1 -0
  206. package/dist/services/insight/types.d.ts +43 -0
  207. package/dist/services/insight/types.d.ts.map +1 -1
  208. package/dist/services/insight/types.js.map +1 -1
  209. package/dist/skills/definitions.d.ts +8 -0
  210. package/dist/skills/definitions.d.ts.map +1 -1
  211. package/dist/skills/definitions.js +8 -2
  212. package/dist/skills/definitions.js.map +1 -1
  213. package/dist/skills/installer.d.ts +15 -0
  214. package/dist/skills/installer.d.ts.map +1 -1
  215. package/dist/skills/installer.js +39 -1
  216. package/dist/skills/installer.js.map +1 -1
  217. package/package.json +1 -1
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `/dashboard groups` sub-handler.
3
+ *
4
+ * The command-level admin gate has already passed. This handler fetches the
5
+ * global groups matrix, builds the Feishu list card, and DMs the invoking
6
+ * admin. Per-row detail cards carry add-bot, leave-bot, oncall, and role
7
+ * actions through card callbacks.
8
+ */
9
+ import type { LarkMessage } from '../../types.js';
10
+ import { type Locale } from '../../i18n/index.js';
11
+ import type { DaemonClient } from '../../dashboard/daemon-internal-client.js';
12
+ import type { CommandHandlerDeps } from '../command-handler.js';
13
+ /** Optional injection seam for tests. */
14
+ export interface DashboardGroupsCommandDeps {
15
+ createClient?: (larkAppId: string) => DaemonClient;
16
+ sendUserMessage?: (larkAppId: string, openId: string, content: string, msgType?: string) => Promise<string>;
17
+ locale?: Locale;
18
+ }
19
+ export declare function handleDashboardGroups(_message: LarkMessage, _args: string, rootId: string, _chatId: string, deps: CommandHandlerDeps, larkAppId: string | undefined, adminOpenId: string, testDeps?: DashboardGroupsCommandDeps): Promise<void>;
20
+ //# sourceMappingURL=groups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../../src/core/dashboard-command/groups.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAInE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAK9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,yCAAyC;AACzC,MAAM,WAAW,0BAA0B;IACzC,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,CAAC;IACnD,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5G,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,0BAA+B,GACxC,OAAO,CAAC,IAAI,CAAC,CA0Df"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `/dashboard groups` sub-handler.
3
+ *
4
+ * The command-level admin gate has already passed. This handler fetches the
5
+ * global groups matrix, builds the Feishu list card, and DMs the invoking
6
+ * admin. Per-row detail cards carry add-bot, leave-bot, oncall, and role
7
+ * actions through card callbacks.
8
+ */
9
+ import { localeForBot, t } from '../../i18n/index.js';
10
+ import { buildGroupsCard } from '../../im/lark/groups-card.js';
11
+ import { createDaemonClientFor } from '../../daemon-internal-client-wrapper.js';
12
+ import { sendUserMessage as defaultSendUserMessage } from '../../im/lark/client.js';
13
+ export async function handleDashboardGroups(_message, _args, rootId, _chatId, deps, larkAppId, adminOpenId, testDeps = {}) {
14
+ if (!larkAppId)
15
+ return;
16
+ const locale = testDeps.locale ?? localeForBot(larkAppId);
17
+ const client = (testDeps.createClient ?? createDaemonClientFor)(larkAppId);
18
+ let snap;
19
+ try {
20
+ snap = await client.request({ method: 'GET', path: '/__daemon/groups-matrix?scope=global' });
21
+ }
22
+ catch (e) {
23
+ await deps.sessionReply(rootId, t('card.dashboard.groups.list_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
24
+ return;
25
+ }
26
+ if (snap.status !== 200) {
27
+ const reason = String(snap.body?.error ?? `http_${snap.status}`);
28
+ await deps.sessionReply(rootId, t('card.dashboard.groups.list_failed', { reason }, locale), undefined, larkAppId);
29
+ return;
30
+ }
31
+ const body = snap.body ?? {};
32
+ const matrix = {
33
+ chats: body.chats ?? [],
34
+ bots: body.bots ?? [],
35
+ };
36
+ // invokerOpenId = adminOpenId so subsequent clicks still pass the invoker lock.
37
+ const cardJson = buildGroupsCard(matrix, {
38
+ invokerOpenId: adminOpenId,
39
+ locale,
40
+ page: 1,
41
+ scope: 'global',
42
+ });
43
+ const sendUserMessage = testDeps.sendUserMessage ?? defaultSendUserMessage;
44
+ try {
45
+ await sendUserMessage(larkAppId, adminOpenId, cardJson, 'interactive');
46
+ await deps.sessionReply(rootId, t('card.dashboard.groups.dm_sent', undefined, locale), undefined, larkAppId);
47
+ }
48
+ catch (e) {
49
+ await deps.sessionReply(rootId, t('card.dashboard.groups.dm_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
50
+ }
51
+ }
52
+ //# sourceMappingURL=groups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groups.js","sourceRoot":"","sources":["../../../src/core/dashboard-command/groups.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,YAAY,EAAE,CAAC,EAAe,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,eAAe,IAAI,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAepF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAqB,EACrB,KAAa,EACb,MAAc,EACd,OAAe,EACf,IAAwB,EACxB,SAA6B,EAC7B,WAAmB,EACnB,WAAuC,EAAE;IAEzC,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,MAAM,MAAM,GAAW,QAAQ,CAAC,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;IAElE,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,qBAAqB,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3E,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sCAAsC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,mCAAmC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EACnF,SAAS,EAAE,SAAS,CACrB,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,MAAM,CAAE,IAAI,CAAC,IAAY,EAAE,KAAK,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1E,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,mCAAmC,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAC1D,SAAS,EAAE,SAAS,CACrB,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAI,IAAI,CAAC,IAGjB,IAAI,EAAE,CAAC;IACT,MAAM,MAAM,GAAG;QACb,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;KACtB,CAAC;IACF,gFAAgF;IAChF,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE;QACvC,aAAa,EAAE,WAAW;QAC1B,MAAM;QACN,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,IAAI,sBAAsB,CAAC;IAC3E,IAAI,CAAC;QACH,MAAM,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,+BAA+B,EAAE,SAAS,EAAE,MAAM,CAAC,EACrD,SAAS,EAAE,SAAS,CACrB,CAAC;IACJ,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,iCAAiC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EACjF,SAAS,EAAE,SAAS,CACrB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `/dashboard <module>` command-group entry.
3
+ *
4
+ * The entire command group is restricted to the bot's resolved `allowedUsers`,
5
+ * matching `/botconfig`. Any subcommand that bypasses this gate is a security
6
+ * regression. Empty args default to `overview`; successful cards are DM'd to
7
+ * the invoking admin and the topic receives only a short confirmation.
8
+ */
9
+ import type { LarkMessage } from '../../types.js';
10
+ import type { CommandHandlerDeps } from '../command-handler.js';
11
+ import { type EnsureDashboardOwnerDeps } from './owner-gate.js';
12
+ import { type DashboardSettingsCommandDeps } from './settings.js';
13
+ import { type DashboardSessionsCommandDeps } from './sessions.js';
14
+ import { type DashboardSchedulesCommandDeps } from './schedules.js';
15
+ import { type DashboardOverviewCommandDeps } from './overview.js';
16
+ import { type DashboardWorkflowsCommandDeps } from './workflows.js';
17
+ import { type DashboardGroupsCommandDeps } from './groups.js';
18
+ /** Optional test seam. Production omits these overrides. */
19
+ export interface DashboardCommandDeps extends EnsureDashboardOwnerDeps {
20
+ /** Override for `sendUserMessage` (DM to invoking admin). Production omits. */
21
+ sendUserMessage?: (larkAppId: string, openId: string, content: string, msgType?: string) => Promise<string>;
22
+ settings?: DashboardSettingsCommandDeps;
23
+ sessions?: DashboardSessionsCommandDeps;
24
+ schedules?: DashboardSchedulesCommandDeps;
25
+ overview?: DashboardOverviewCommandDeps;
26
+ workflows?: DashboardWorkflowsCommandDeps;
27
+ groups?: DashboardGroupsCommandDeps;
28
+ }
29
+ export declare function handleDashboardCommand(message: LarkMessage, args: string, rootId: string, _chatId: string, deps: CommandHandlerDeps, larkAppId?: string, testDeps?: DashboardCommandDeps): Promise<void>;
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/dashboard-command/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE,OAAO,EAAwB,KAAK,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAOtF,OAAO,EAA2B,KAAK,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAA2B,KAAK,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAA4B,KAAK,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC9F,OAAO,EAA2B,KAAK,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAA4B,KAAK,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC9F,OAAO,EAAyB,KAAK,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAErF,4DAA4D;AAC5D,MAAM,WAAW,oBAAqB,SAAQ,wBAAwB;IACpE,+EAA+E;IAC/E,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5G,QAAQ,CAAC,EAAE,4BAA4B,CAAC;IACxC,QAAQ,CAAC,EAAE,4BAA4B,CAAC;IACxC,SAAS,CAAC,EAAE,6BAA6B,CAAC;IAC1C,QAAQ,CAAC,EAAE,4BAA4B,CAAC;IACxC,SAAS,CAAC,EAAE,6BAA6B,CAAC;IAC1C,MAAM,CAAC,EAAE,0BAA0B,CAAC;CACrC;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,kBAAkB,EACxB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,GAAE,oBAAyB,GAClC,OAAO,CAAC,IAAI,CAAC,CA2Ef"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * `/dashboard <module>` command-group entry.
3
+ *
4
+ * The entire command group is restricted to the bot's resolved `allowedUsers`,
5
+ * matching `/botconfig`. Any subcommand that bypasses this gate is a security
6
+ * regression. Empty args default to `overview`; successful cards are DM'd to
7
+ * the invoking admin and the topic receives only a short confirmation.
8
+ */
9
+ import { localeForBot, t } from '../../i18n/index.js';
10
+ import { sendUserMessage as defaultSendUserMessage } from '../../im/lark/client.js';
11
+ import { ensureDashboardOwner } from './owner-gate.js';
12
+ import { DASHBOARD_MODULES, buildHelpText, buildStubText, } from './stub.js';
13
+ import { handleDashboardSettings } from './settings.js';
14
+ import { handleDashboardSessions } from './sessions.js';
15
+ import { handleDashboardSchedules } from './schedules.js';
16
+ import { handleDashboardOverview } from './overview.js';
17
+ import { handleDashboardWorkflows } from './workflows.js';
18
+ import { handleDashboardGroups } from './groups.js';
19
+ export async function handleDashboardCommand(message, args, rootId, _chatId, deps, larkAppId, testDeps = {}) {
20
+ const loc = localeForBot(larkAppId);
21
+ // Integral admin gate — applies to ALL subcommands. It intentionally
22
+ // matches `/botconfig`: any resolved allowedUsers entry can use dashboard,
23
+ // but open-mode bots with no allowedUsers still fail closed.
24
+ const gate = await ensureDashboardOwner(message, larkAppId, testDeps);
25
+ if (!gate.ok) {
26
+ // Admin gate failure: reply in the topic (we don't have an admin DM target).
27
+ await deps.sessionReply(rootId, t('card.dashboard.owner_only', undefined, loc), undefined, larkAppId);
28
+ return;
29
+ }
30
+ // Every admin-gated response goes to the invoking admin's DM. The
31
+ // topic receives only a short confirmation, sharing the `/card` idiom
32
+ // (cmd.config.card_dmd: "configuration card sent to your DM").
33
+ const sendUserMessage = testDeps.sendUserMessage ?? defaultSendUserMessage;
34
+ const reply = async (text, msgType = 'text') => {
35
+ if (!larkAppId) {
36
+ await deps.sessionReply(rootId, text, msgType === 'interactive' ? 'interactive' : undefined, larkAppId);
37
+ return;
38
+ }
39
+ try {
40
+ await sendUserMessage(larkAppId, gate.adminOpenId, text, msgType);
41
+ await deps.sessionReply(rootId, t('card.dashboard.dm_sent', undefined, loc), undefined, larkAppId);
42
+ }
43
+ catch (e) {
44
+ await deps.sessionReply(rootId, t('card.dashboard.dm_failed', { reason: e?.message ?? String(e) }, loc), undefined, larkAppId);
45
+ }
46
+ };
47
+ // ─── Dispatch (admin-only zone) ───
48
+ const trimmedArgs = args.trim();
49
+ const rawSub = trimmedArgs.split(/\s+/)[0] || 'overview';
50
+ const sub = rawSub.toLowerCase();
51
+ const subArgs = trimmedArgs ? trimmedArgs.slice(rawSub.length).trimStart() : '';
52
+ if (sub === 'help') {
53
+ await reply(buildHelpText(loc));
54
+ return;
55
+ }
56
+ if (sub === 'settings') {
57
+ return handleDashboardSettings(message, subArgs, rootId, _chatId, deps, larkAppId, gate.adminOpenId, testDeps.settings);
58
+ }
59
+ if (sub === 'sessions') {
60
+ return handleDashboardSessions(message, subArgs, rootId, _chatId, deps, larkAppId, gate.adminOpenId, testDeps.sessions);
61
+ }
62
+ if (sub === 'schedules') {
63
+ return handleDashboardSchedules(message, subArgs, rootId, _chatId, deps, larkAppId, gate.adminOpenId, testDeps.schedules);
64
+ }
65
+ if (sub === 'workflows') {
66
+ return handleDashboardWorkflows(message, subArgs, rootId, _chatId, deps, larkAppId, gate.adminOpenId, testDeps.workflows);
67
+ }
68
+ if (sub === 'groups') {
69
+ return handleDashboardGroups(message, subArgs, rootId, _chatId, deps, larkAppId, gate.adminOpenId, testDeps.groups);
70
+ }
71
+ if (sub === 'overview') {
72
+ return handleDashboardOverview(message, subArgs, rootId, _chatId, deps, larkAppId, gate.adminOpenId, testDeps.overview);
73
+ }
74
+ if (DASHBOARD_MODULES.includes(sub)) {
75
+ await reply(buildStubText(sub, loc));
76
+ return;
77
+ }
78
+ // Unknown module — show help with an "unknown module" preface.
79
+ await reply(buildHelpText(loc, { unknownModule: sub }));
80
+ }
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/dashboard-command/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * `/dashboard overview` real sub-handler.
3
+ *
4
+ * Pipeline (mirrors `/dashboard sessions` / `/dashboard schedules`):
5
+ * 1. Admin gate has ALREADY run in `handleDashboardCommand`; this function
6
+ * is called with `adminOpenId` already resolved.
7
+ * 2. Fetch the live overview snapshot via Route B
8
+ * (`GET /__daemon/overview-snapshot?scope=global`). `/dashboard` is
9
+ * a Bot admin tool panel — list modules surface cross-bot under
10
+ * `?scope=global` so the first-open view matches refresh/drilldown.
11
+ * 3. Project through `buildOverviewCard` (counts + settings summary line)
12
+ * with section buttons routed to the goto handlers (which also send
13
+ * `?scope=global`).
14
+ * 4. DM the card to the admin; topic only gets a short `dm_sent` line.
15
+ *
16
+ * Read-only — no buttons mutate state from the overview surface itself.
17
+ */
18
+ import type { LarkMessage } from '../../types.js';
19
+ import { type Locale } from '../../i18n/index.js';
20
+ import type { DaemonClient } from '../../dashboard/daemon-internal-client.js';
21
+ import type { CommandHandlerDeps } from '../command-handler.js';
22
+ /** Optional injection seam for tests. */
23
+ export interface DashboardOverviewCommandDeps {
24
+ createClient?: (larkAppId: string) => DaemonClient;
25
+ sendUserMessage?: (larkAppId: string, openId: string, content: string, msgType?: string) => Promise<string>;
26
+ locale?: Locale;
27
+ }
28
+ export declare function handleDashboardOverview(_message: LarkMessage, _args: string, rootId: string, _chatId: string, deps: CommandHandlerDeps, larkAppId: string | undefined, adminOpenId: string, testDeps?: DashboardOverviewCommandDeps): Promise<void>;
29
+ //# sourceMappingURL=overview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overview.d.ts","sourceRoot":"","sources":["../../../src/core/dashboard-command/overview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAInE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAI9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,yCAAyC;AACzC,MAAM,WAAW,4BAA4B;IAC3C,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,CAAC;IACnD,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5G,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAQD,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,4BAAiC,GAC1C,OAAO,CAAC,IAAI,CAAC,CA+Df"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * `/dashboard overview` real sub-handler.
3
+ *
4
+ * Pipeline (mirrors `/dashboard sessions` / `/dashboard schedules`):
5
+ * 1. Admin gate has ALREADY run in `handleDashboardCommand`; this function
6
+ * is called with `adminOpenId` already resolved.
7
+ * 2. Fetch the live overview snapshot via Route B
8
+ * (`GET /__daemon/overview-snapshot?scope=global`). `/dashboard` is
9
+ * a Bot admin tool panel — list modules surface cross-bot under
10
+ * `?scope=global` so the first-open view matches refresh/drilldown.
11
+ * 3. Project through `buildOverviewCard` (counts + settings summary line)
12
+ * with section buttons routed to the goto handlers (which also send
13
+ * `?scope=global`).
14
+ * 4. DM the card to the admin; topic only gets a short `dm_sent` line.
15
+ *
16
+ * Read-only — no buttons mutate state from the overview surface itself.
17
+ */
18
+ import { localeForBot, t } from '../../i18n/index.js';
19
+ import { buildOverviewCard } from '../../im/lark/overview-card.js';
20
+ import { createDaemonClientFor } from '../../daemon-internal-client-wrapper.js';
21
+ import { sendUserMessage as defaultSendUserMessage } from '../../im/lark/client.js';
22
+ export async function handleDashboardOverview(_message, _args, rootId, _chatId, deps, larkAppId, adminOpenId, testDeps = {}) {
23
+ if (!larkAppId)
24
+ return;
25
+ const locale = testDeps.locale ?? localeForBot(larkAppId);
26
+ const client = (testDeps.createClient ?? createDaemonClientFor)(larkAppId);
27
+ let snap;
28
+ try {
29
+ // `/dashboard` first-open MUST match the refresh-callback view:
30
+ // list modules are global under `?scope=global`.
31
+ snap = await client.request({ method: 'GET', path: '/__daemon/overview-snapshot?scope=global' });
32
+ }
33
+ catch (e) {
34
+ await deps.sessionReply(rootId, t('card.dashboard.overview.overview_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
35
+ return;
36
+ }
37
+ if (snap.status !== 200) {
38
+ const reason = String(snap.body?.error ?? `http_${snap.status}`);
39
+ await deps.sessionReply(rootId, t('card.dashboard.overview.overview_failed', { reason }, locale), undefined, larkAppId);
40
+ return;
41
+ }
42
+ const body = snap.body;
43
+ if (!body || typeof body !== 'object' || !body.settings) {
44
+ await deps.sessionReply(rootId, t('card.dashboard.overview.overview_failed', { reason: 'malformed_body' }, locale), undefined, larkAppId);
45
+ return;
46
+ }
47
+ const cardJson = buildOverviewCard({
48
+ sessions: body.sessions ?? [],
49
+ schedules: body.schedules ?? [],
50
+ settings: body.settings,
51
+ }, { invokerOpenId: adminOpenId, locale });
52
+ const sendUserMessage = testDeps.sendUserMessage ?? defaultSendUserMessage;
53
+ try {
54
+ await sendUserMessage(larkAppId, adminOpenId, cardJson, 'interactive');
55
+ await deps.sessionReply(rootId, t('card.dashboard.overview.dm_sent', undefined, locale), undefined, larkAppId);
56
+ }
57
+ catch (e) {
58
+ await deps.sessionReply(rootId, t('card.dashboard.overview.dm_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
59
+ }
60
+ }
61
+ //# sourceMappingURL=overview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overview.js","sourceRoot":"","sources":["../../../src/core/dashboard-command/overview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `/dashboard` command-group admin gate.
3
+ *
4
+ * Single source of truth for verifying that a sender is allowed to use any
5
+ * `/dashboard <module>` subcommand. The entire `/dashboard` group is
6
+ * restricted to the bot's resolved `allowedUsers`, matching `/botconfig`;
7
+ * help / stub / unknown subcommands MUST go through this check before they
8
+ * can produce any output.
9
+ *
10
+ * Why a dedicated helper instead of inlining the lookup in command dispatch:
11
+ * - Command entry and card-callback paths must share the same admin model.
12
+ * If one path treats only allowedUsers[0] as privileged while another
13
+ * accepts all allowedUsers, `/dashboard` drifts away from `/botconfig`.
14
+ * - Empty allowedUsers deliberately fails closed. Other botmux commands may
15
+ * have open-mode fallbacks, but dashboard exposes operational controls.
16
+ */
17
+ import type { LarkMessage } from '../../types.js';
18
+ import { type DashboardAdminLookupDeps } from '../../dashboard/dashboard-admins.js';
19
+ export type DashboardAdminCheck = {
20
+ ok: true;
21
+ adminOpenId: string;
22
+ } | {
23
+ ok: false;
24
+ reason: 'no_dashboard_admin' | 'missing_sender' | 'not_dashboard_admin';
25
+ };
26
+ /** Backward-compatible type alias for older tests/imports. */
27
+ export type DashboardOwnerCheck = DashboardAdminCheck;
28
+ /** Optional injection seam — tests provide mock admin lookup. */
29
+ export interface EnsureDashboardOwnerDeps extends DashboardAdminLookupDeps {
30
+ }
31
+ /**
32
+ * Decide whether `message.senderId` is a per-bot dashboard admin.
33
+ *
34
+ * Per-bot admin gate:
35
+ * - Each `/dashboard` invocation is scoped to the bot that received it.
36
+ * - Any resolved `allowedUsers` entry can operate, matching `/botconfig`.
37
+ * - Empty `allowedUsers` still fails closed; dashboard is never opened by
38
+ * botmux's generic open-mode `canOperate` fallback.
39
+ */
40
+ export declare function ensureDashboardOwner(message: LarkMessage, larkAppId: string | undefined, deps?: EnsureDashboardOwnerDeps): Promise<DashboardAdminCheck>;
41
+ //# sourceMappingURL=owner-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-gate.d.ts","sourceRoot":"","sources":["../../../src/core/dashboard-command/owner-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,qCAAqC,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,oBAAoB,GAAG,gBAAgB,GAAG,qBAAqB,CAAA;CAAE,CAAC;AAE3F,8DAA8D;AAC9D,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEtD,iEAAiE;AACjE,MAAM,WAAW,wBAAyB,SAAQ,wBAAwB;CAAG;AAE7E;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,IAAI,GAAE,wBAA6B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAQ9B"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `/dashboard` command-group admin gate.
3
+ *
4
+ * Single source of truth for verifying that a sender is allowed to use any
5
+ * `/dashboard <module>` subcommand. The entire `/dashboard` group is
6
+ * restricted to the bot's resolved `allowedUsers`, matching `/botconfig`;
7
+ * help / stub / unknown subcommands MUST go through this check before they
8
+ * can produce any output.
9
+ *
10
+ * Why a dedicated helper instead of inlining the lookup in command dispatch:
11
+ * - Command entry and card-callback paths must share the same admin model.
12
+ * If one path treats only allowedUsers[0] as privileged while another
13
+ * accepts all allowedUsers, `/dashboard` drifts away from `/botconfig`.
14
+ * - Empty allowedUsers deliberately fails closed. Other botmux commands may
15
+ * have open-mode fallbacks, but dashboard exposes operational controls.
16
+ */
17
+ import { resolveDashboardAdminOpenIds, } from '../../dashboard/dashboard-admins.js';
18
+ /**
19
+ * Decide whether `message.senderId` is a per-bot dashboard admin.
20
+ *
21
+ * Per-bot admin gate:
22
+ * - Each `/dashboard` invocation is scoped to the bot that received it.
23
+ * - Any resolved `allowedUsers` entry can operate, matching `/botconfig`.
24
+ * - Empty `allowedUsers` still fails closed; dashboard is never opened by
25
+ * botmux's generic open-mode `canOperate` fallback.
26
+ */
27
+ export async function ensureDashboardOwner(message, larkAppId, deps = {}) {
28
+ if (!larkAppId)
29
+ return { ok: false, reason: 'no_dashboard_admin' };
30
+ const admins = resolveDashboardAdminOpenIds(larkAppId, deps);
31
+ if (admins.length === 0)
32
+ return { ok: false, reason: 'no_dashboard_admin' };
33
+ const senderId = message.senderId;
34
+ if (!senderId)
35
+ return { ok: false, reason: 'missing_sender' };
36
+ if (!admins.includes(senderId))
37
+ return { ok: false, reason: 'not_dashboard_admin' };
38
+ return { ok: true, adminOpenId: senderId };
39
+ }
40
+ //# sourceMappingURL=owner-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-gate.js","sourceRoot":"","sources":["../../../src/core/dashboard-command/owner-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EACL,4BAA4B,GAE7B,MAAM,qCAAqC,CAAC;AAY7C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAoB,EACpB,SAA6B,EAC7B,OAAiC,EAAE;IAEnC,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IACnE,MAAM,MAAM,GAAG,4BAA4B,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC7D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IAC5E,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;IACpF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `/dashboard schedules` sub-handler.
3
+ *
4
+ * The command-level admin gate has already passed. This handler fetches the
5
+ * global schedules list, builds the Feishu list card, and DMs the invoking
6
+ * admin. Per-schedule actions are handled by card callbacks from the detail
7
+ * view.
8
+ */
9
+ import type { LarkMessage } from '../../types.js';
10
+ import { type Locale } from '../../i18n/index.js';
11
+ import type { DaemonClient } from '../../dashboard/daemon-internal-client.js';
12
+ import type { CommandHandlerDeps } from '../command-handler.js';
13
+ export interface DashboardSchedulesCommandDeps {
14
+ createClient?: (larkAppId: string) => DaemonClient;
15
+ sendUserMessage?: (larkAppId: string, openId: string, content: string, msgType?: string) => Promise<string>;
16
+ locale?: Locale;
17
+ nowMs?: () => number;
18
+ }
19
+ export declare function handleDashboardSchedules(_message: LarkMessage, _args: string, rootId: string, _chatId: string, deps: CommandHandlerDeps, larkAppId: string | undefined, adminOpenId: string, testDeps?: DashboardSchedulesCommandDeps): Promise<void>;
20
+ //# sourceMappingURL=schedules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../../src/core/dashboard-command/schedules.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAInE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,WAAW,6BAA6B;IAC5C,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,CAAC;IACnD,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,6BAAkC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAsDf"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * `/dashboard schedules` sub-handler.
3
+ *
4
+ * The command-level admin gate has already passed. This handler fetches the
5
+ * global schedules list, builds the Feishu list card, and DMs the invoking
6
+ * admin. Per-schedule actions are handled by card callbacks from the detail
7
+ * view.
8
+ */
9
+ import { localeForBot, t } from '../../i18n/index.js';
10
+ import { buildSchedulesCard } from '../../im/lark/schedules-card.js';
11
+ import { createDaemonClientFor } from '../../daemon-internal-client-wrapper.js';
12
+ import { sendUserMessage as defaultSendUserMessage } from '../../im/lark/client.js';
13
+ export async function handleDashboardSchedules(_message, _args, rootId, _chatId, deps, larkAppId, adminOpenId, testDeps = {}) {
14
+ if (!larkAppId)
15
+ return;
16
+ const locale = testDeps.locale ?? localeForBot(larkAppId);
17
+ const client = (testDeps.createClient ?? createDaemonClientFor)(larkAppId);
18
+ let snap;
19
+ try {
20
+ // `/dashboard` is a global tool panel: show schedules from any bot while
21
+ // keeping write routing on the row owner.
22
+ snap = await client.request({ method: 'GET', path: '/__daemon/schedules-list?scope=global' });
23
+ }
24
+ catch (e) {
25
+ await deps.sessionReply(rootId, t('card.dashboard.schedules.list_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
26
+ return;
27
+ }
28
+ if (snap.status !== 200) {
29
+ const reason = String(snap.body?.error ?? `http_${snap.status}`);
30
+ await deps.sessionReply(rootId, t('card.dashboard.schedules.list_failed', { reason }, locale), undefined, larkAppId);
31
+ return;
32
+ }
33
+ const tasks = (snap.body?.schedules) ?? [];
34
+ const nowMs = testDeps.nowMs ? testDeps.nowMs() : Date.now();
35
+ // Thread global scope through callbacks so refresh/page/detail/back/actions
36
+ // keep the global view and route writes to the row's true owner.
37
+ const cardJson = buildSchedulesCard(tasks, { invokerOpenId: adminOpenId, locale, page: 1, scope: 'global' }, nowMs);
38
+ const sendUserMessage = testDeps.sendUserMessage ?? defaultSendUserMessage;
39
+ try {
40
+ await sendUserMessage(larkAppId, adminOpenId, cardJson, 'interactive');
41
+ await deps.sessionReply(rootId, t('card.dashboard.schedules.dm_sent', undefined, locale), undefined, larkAppId);
42
+ }
43
+ catch (e) {
44
+ await deps.sessionReply(rootId, t('card.dashboard.schedules.dm_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
45
+ }
46
+ }
47
+ //# sourceMappingURL=schedules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedules.js","sourceRoot":"","sources":["../../../src/core/dashboard-command/schedules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `/dashboard sessions` sub-handler.
3
+ *
4
+ * The command-level admin gate has already passed. This handler fetches the
5
+ * global sessions list, builds the Feishu list card, and DMs the invoking
6
+ * admin. Per-session actions are handled by card callbacks from the detail
7
+ * view.
8
+ */
9
+ import type { LarkMessage } from '../../types.js';
10
+ import { type Locale } from '../../i18n/index.js';
11
+ import type { DaemonClient } from '../../dashboard/daemon-internal-client.js';
12
+ import type { CommandHandlerDeps } from '../command-handler.js';
13
+ /** Optional injection seam for tests. */
14
+ export interface DashboardSessionsCommandDeps {
15
+ createClient?: (larkAppId: string) => DaemonClient;
16
+ sendUserMessage?: (larkAppId: string, openId: string, content: string, msgType?: string) => Promise<string>;
17
+ locale?: Locale;
18
+ /** Override `Date.now()` so tests are deterministic. */
19
+ nowMs?: () => number;
20
+ }
21
+ export declare function handleDashboardSessions(_message: LarkMessage, _args: string, rootId: string, _chatId: string, deps: CommandHandlerDeps, larkAppId: string | undefined, adminOpenId: string, testDeps?: DashboardSessionsCommandDeps): Promise<void>;
22
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/core/dashboard-command/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAInE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,yCAAyC;AACzC,MAAM,WAAW,4BAA4B;IAC3C,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,CAAC;IACnD,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,4BAAiC,GAC1C,OAAO,CAAC,IAAI,CAAC,CAkDf"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `/dashboard sessions` sub-handler.
3
+ *
4
+ * The command-level admin gate has already passed. This handler fetches the
5
+ * global sessions list, builds the Feishu list card, and DMs the invoking
6
+ * admin. Per-session actions are handled by card callbacks from the detail
7
+ * view.
8
+ */
9
+ import { localeForBot, t } from '../../i18n/index.js';
10
+ import { buildSessionsCard } from '../../im/lark/sessions-card.js';
11
+ import { createDaemonClientFor } from '../../daemon-internal-client-wrapper.js';
12
+ import { sendUserMessage as defaultSendUserMessage } from '../../im/lark/client.js';
13
+ export async function handleDashboardSessions(_message, _args, rootId, _chatId, deps, larkAppId, adminOpenId, testDeps = {}) {
14
+ if (!larkAppId)
15
+ return;
16
+ const locale = testDeps.locale ?? localeForBot(larkAppId);
17
+ const client = (testDeps.createClient ?? createDaemonClientFor)(larkAppId);
18
+ let snap;
19
+ try {
20
+ snap = await client.request({ method: 'GET', path: '/__daemon/sessions-list?scope=global' });
21
+ }
22
+ catch (e) {
23
+ await deps.sessionReply(rootId, t('card.dashboard.sessions.list_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
24
+ return;
25
+ }
26
+ if (snap.status !== 200) {
27
+ await deps.sessionReply(rootId, t('card.dashboard.sessions.list_failed', { reason: `http_${snap.status}` }, locale), undefined, larkAppId);
28
+ return;
29
+ }
30
+ const rows = (snap.body?.sessions) ?? [];
31
+ const nowMs = testDeps.nowMs ? testDeps.nowMs() : Date.now();
32
+ // invokerOpenId = adminOpenId so subsequent clicks still pass the invoker lock.
33
+ const cardJson = buildSessionsCard(rows, { invokerOpenId: adminOpenId, locale, page: 1, scope: 'global' }, nowMs);
34
+ const sendUserMessage = testDeps.sendUserMessage ?? defaultSendUserMessage;
35
+ try {
36
+ await sendUserMessage(larkAppId, adminOpenId, cardJson, 'interactive');
37
+ await deps.sessionReply(rootId, t('card.dashboard.sessions.dm_sent', undefined, locale), undefined, larkAppId);
38
+ }
39
+ catch (e) {
40
+ await deps.sessionReply(rootId, t('card.dashboard.sessions.dm_failed', { reason: e?.message ?? String(e) }, locale), undefined, larkAppId);
41
+ }
42
+ }
43
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/core/dashboard-command/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,YAAY,EAAE,CAAC,EAAe,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,eAAe,IAAI,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAcpF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAqB,EACrB,KAAa,EACb,MAAc,EACd,OAAe,EACf,IAAwB,EACxB,SAA6B,EAC7B,WAAmB,EACnB,WAAyC,EAAE;IAE3C,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,MAAM,MAAM,GAAW,QAAQ,CAAC,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;IAElE,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,qBAAqB,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3E,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sCAAsC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,qCAAqC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EACrF,SAAS,EAAE,SAAS,CACrB,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACxB,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,qCAAqC,EAAE,EAAE,MAAM,EAAE,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,EACnF,SAAS,EAAE,SAAS,CACrB,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,CAAE,IAAI,CAAC,IAAiD,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IACvF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7D,gFAAgF;IAChF,MAAM,QAAQ,GAAG,iBAAiB,CAChC,IAAI,EACJ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAChE,KAAK,CACN,CAAC;IAEF,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,IAAI,sBAAsB,CAAC;IAC3E,IAAI,CAAC;QACH,MAAM,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,iCAAiC,EAAE,SAAS,EAAE,MAAM,CAAC,EACvD,SAAS,EAAE,SAAS,CACrB,CAAC;IACJ,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,IAAI,CAAC,YAAY,CACrB,MAAM,EACN,CAAC,CAAC,mCAAmC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EACnF,SAAS,EAAE,SAAS,CACrB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `/dashboard settings` sub-handler.
3
+ *
4
+ * The command-level admin gate has already passed. This handler fetches the
5
+ * live settings snapshot, projects it into a Feishu card, and DMs the invoking
6
+ * admin. The topic receives only a confirmation line. The card builder never
7
+ * receives sender union identity; `invokerOpenId` is the admin open_id used by
8
+ * callback invoker-lock.
9
+ */
10
+ import type { LarkMessage } from '../../types.js';
11
+ import { type Locale } from '../../i18n/index.js';
12
+ import type { DaemonClient } from '../../dashboard/daemon-internal-client.js';
13
+ import type { CommandHandlerDeps } from '../command-handler.js';
14
+ /** Optional injection seam for tests. */
15
+ export interface DashboardSettingsCommandDeps {
16
+ createClient?: (larkAppId: string) => DaemonClient;
17
+ sendUserMessage?: (larkAppId: string, openId: string, content: string, msgType?: string) => Promise<string>;
18
+ locale?: Locale;
19
+ }
20
+ export declare function handleDashboardSettings(message: LarkMessage, _args: string, rootId: string, _chatId: string, deps: CommandHandlerDeps, larkAppId: string | undefined, adminOpenId: string, testDeps?: DashboardSettingsCommandDeps): Promise<void>;
21
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/core/dashboard-command/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAC9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,yCAAyC;AACzC,MAAM,WAAW,4BAA4B;IAC3C,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,YAAY,CAAC;IACnD,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5G,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,4BAAiC,GAC1C,OAAO,CAAC,IAAI,CAAC,CA6Df"}