botmux 2.9.1 → 2.9.3

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 +645 -314
  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 +2248 -83
  329. package/dist/worker.js.map +1 -1
  330. package/package.json +12 -5
@@ -0,0 +1,481 @@
1
+ // src/core/dashboard-ipc-server.ts
2
+ import { createServer } from 'node:http';
3
+ import { existsSync, statSync } from 'node:fs';
4
+ import { resolve } from 'node:path';
5
+ import { logger } from '../utils/logger.js';
6
+ import * as sessionStore from '../services/session-store.js';
7
+ import * as scheduleStore from '../services/schedule-store.js';
8
+ import * as groupsStore from '../services/groups-store.js';
9
+ import { createGroupWithBots } from '../services/group-creator.js';
10
+ import * as oncallStore from '../services/oncall-store.js';
11
+ import * as chatFirstSeenStore from '../services/chat-first-seen-store.js';
12
+ import * as scheduler from './scheduler.js';
13
+ import { listActiveSessions, findActiveBySessionId, closeSession, getActiveSessionsRegistry } from './worker-pool.js';
14
+ import { getChatMode, replyMessage, sendMessage } from '../im/lark/client.js';
15
+ import { resumeSession } from './session-manager.js';
16
+ import { getCliDisplayName } from '../im/lark/card-builder.js';
17
+ import { locateLimiter } from './dashboard-locate.js';
18
+ import { dashboardEventBus } from './dashboard-events.js';
19
+ import { expandHome } from './session-manager.js';
20
+ import { composeRowFromActive, composeRowFromClosed, feishuChatLink, setBotName as setRowsBotName, getBotName, } from './dashboard-rows.js';
21
+ const routes = [];
22
+ /** Register a handler. Path supports `:name` segments captured into the params object. */
23
+ export function ipcRoute(method, path, handler) {
24
+ const keys = [];
25
+ const pattern = new RegExp('^' + path.replace(/:([a-zA-Z]+)/g, (_, k) => { keys.push(k); return '([^/]+)'; }) + '$');
26
+ routes.push({ method: method.toUpperCase(), pattern, keys, handler });
27
+ }
28
+ export function jsonRes(res, status, body) {
29
+ res.writeHead(status, { 'content-type': 'application/json' });
30
+ res.end(JSON.stringify(body));
31
+ }
32
+ export async function readJsonBody(req) {
33
+ const chunks = [];
34
+ for await (const c of req)
35
+ chunks.push(c);
36
+ if (chunks.length === 0)
37
+ return {};
38
+ return JSON.parse(Buffer.concat(chunks).toString('utf8'));
39
+ }
40
+ ipcRoute('GET', '/__health', (_req, res) => {
41
+ jsonRes(res, 200, { ok: true });
42
+ });
43
+ export { composeRowFromActive, composeRowFromClosed };
44
+ // Re-export setBotName for backwards-compatible imports (daemon.ts). Both
45
+ // callers (this module's cachedBotName + dashboard-rows' cachedBotName) need
46
+ // to be primed; here we forward to the rows module which is the canonical
47
+ // holder.
48
+ export function setBotName(name) { setRowsBotName(name); }
49
+ // The daemon's own larkAppId, primed at startup. Required for the groups
50
+ // endpoints below which proxy calls into groups-store on this bot's behalf.
51
+ let cachedLarkAppId = '';
52
+ export function setLarkAppId(id) { cachedLarkAppId = id; }
53
+ ipcRoute('GET', '/api/sessions', (_req, res) => {
54
+ // Active first (live state), closed appended (historical)
55
+ const active = listActiveSessions().map(composeRowFromActive);
56
+ const activeIds = new Set(active.map(r => r.sessionId));
57
+ const closed = sessionStore.listSessions()
58
+ .filter(s => s.status === 'closed' && !activeIds.has(s.sessionId))
59
+ .map(composeRowFromClosed);
60
+ jsonRes(res, 200, { sessions: [...active, ...closed] });
61
+ });
62
+ ipcRoute('GET', '/api/sessions/:sessionId', (_req, res, params) => {
63
+ const ds = findActiveBySessionId(params.sessionId);
64
+ if (ds)
65
+ return jsonRes(res, 200, { session: composeRowFromActive(ds) });
66
+ const closed = sessionStore.listSessions().find(s => s.sessionId === params.sessionId);
67
+ if (closed)
68
+ return jsonRes(res, 200, { session: composeRowFromClosed(closed) });
69
+ jsonRes(res, 404, { error: 'not_found' });
70
+ });
71
+ ipcRoute('POST', '/api/sessions/:sessionId/close', async (_req, res, params) => {
72
+ const r = await closeSession(params.sessionId);
73
+ jsonRes(res, 200, r);
74
+ });
75
+ /**
76
+ * Reactivate a closed session — counterpart to `/close`. Used by both the
77
+ * "▶️ 恢复会话" card button (via card-handler) and the `botmux resume <id>`
78
+ * CLI command (via this HTTP route). The CLI route also drops a notice into
79
+ * the original Lark thread so users see why the session is alive again.
80
+ */
81
+ ipcRoute('POST', '/api/sessions/:sessionId/resume', async (_req, res, params) => {
82
+ const sessionId = params.sessionId;
83
+ const reg = getActiveSessionsRegistry();
84
+ if (!reg)
85
+ return jsonRes(res, 503, { ok: false, error: 'registry_unavailable' });
86
+ const result = resumeSession(sessionId, reg);
87
+ if (!result.ok) {
88
+ const status = result.error === 'not_found' ? 404 : 409;
89
+ return jsonRes(res, status, { ok: false, error: result.error, activeSessionId: result.activeSessionId });
90
+ }
91
+ const ds = result.ds;
92
+ // Tell the dashboard the row flipped back to active (mirror of session.update
93
+ // emitted by closeSession). Use `null` for closedAt — `undefined` would be
94
+ // dropped by JSON.stringify on the SSE wire and the aggregator's spread
95
+ // (`{...cur, ...patch}`) would leave the stale closedAt in place.
96
+ dashboardEventBus.publish({
97
+ type: 'session.update',
98
+ body: {
99
+ sessionId,
100
+ patch: { status: 'active', closedAt: null },
101
+ },
102
+ });
103
+ // Notify the original chat so humans see why the session is alive again.
104
+ // Routing follows session.scope — thread-scope replies into the thread root
105
+ // (reply_in_thread=true), chat-scope posts a plain message to the chat (any
106
+ // reply_in_thread call would silently get rejected or land on a stale root).
107
+ const cliId = ds.session.cliId;
108
+ const cliName = getCliDisplayName(cliId ?? 'claude-code');
109
+ const notice = JSON.stringify({ text: `🔄 会话已通过命令行恢复,发条消息继续与 ${cliName} 对话。` });
110
+ if (ds.larkAppId) {
111
+ if (ds.scope === 'chat' && ds.chatId) {
112
+ getChatMode(ds.larkAppId, ds.chatId, { forceRefresh: true })
113
+ .then((mode) => mode === 'topic' && ds.session.rootMessageId
114
+ ? replyMessage(ds.larkAppId, ds.session.rootMessageId, notice, 'text', true)
115
+ : sendMessage(ds.larkAppId, ds.chatId, notice, 'text'))
116
+ .catch(err => logger.debug(`[resume] failed to post chat-scope resume notice: ${err}`));
117
+ }
118
+ else if (ds.session.rootMessageId) {
119
+ replyMessage(ds.larkAppId, ds.session.rootMessageId, notice, 'text', true)
120
+ .catch(err => logger.debug(`[resume] failed to post thread-scope resume notice: ${err}`));
121
+ }
122
+ }
123
+ jsonRes(res, 200, {
124
+ ok: true,
125
+ sessionId,
126
+ title: ds.session.title,
127
+ chatId: ds.chatId,
128
+ rootMessageId: ds.session.rootMessageId,
129
+ workingDir: ds.session.workingDir,
130
+ cliId,
131
+ });
132
+ });
133
+ ipcRoute('POST', '/api/sessions/:sessionId/locate', async (_req, res, params) => {
134
+ const sid = params.sessionId;
135
+ const acq = locateLimiter.tryAcquire(sid);
136
+ if (!acq.ok) {
137
+ res.writeHead(429, {
138
+ 'content-type': 'application/json',
139
+ 'retry-after': String(Math.ceil(acq.retryAfterMs / 1000)),
140
+ });
141
+ res.end(JSON.stringify({ ok: false, error: 'rate_limited', retryAfterMs: acq.retryAfterMs }));
142
+ return;
143
+ }
144
+ // Resolve owning session (active first, then closed-store fallback). The
145
+ // locate marker is a bare @-mention of the session's owner — no other text,
146
+ // no AppLink redirect on the frontend. The notification on the user's
147
+ // device is enough to navigate them back to the topic.
148
+ const ds = findActiveBySessionId(sid);
149
+ const closed = ds ? null : sessionStore.getSession(sid);
150
+ const ctx = ds
151
+ ? {
152
+ larkAppId: ds.larkAppId,
153
+ rootMessageId: ds.session.rootMessageId,
154
+ ownerOpenId: ds.session.ownerOpenId,
155
+ }
156
+ : closed
157
+ ? {
158
+ larkAppId: closed.larkAppId ?? '',
159
+ rootMessageId: closed.rootMessageId,
160
+ ownerOpenId: closed.ownerOpenId,
161
+ }
162
+ : null;
163
+ if (!ctx || !ctx.larkAppId) {
164
+ return jsonRes(res, 404, { ok: false, error: 'session_not_found' });
165
+ }
166
+ if (!ctx.ownerOpenId) {
167
+ return jsonRes(res, 422, { ok: false, error: 'no_owner' });
168
+ }
169
+ try {
170
+ const messageId = await replyMessage(ctx.larkAppId, ctx.rootMessageId, `<at user_id="${ctx.ownerOpenId}"></at>`, 'text', true);
171
+ jsonRes(res, 200, { ok: true, messageId });
172
+ }
173
+ catch (err) {
174
+ jsonRes(res, 502, { ok: false, error: String(err) });
175
+ }
176
+ });
177
+ function composeScheduleRow(t) {
178
+ return {
179
+ id: t.id,
180
+ name: t.name,
181
+ parsed: t.parsed,
182
+ prompt: t.prompt,
183
+ workingDir: t.workingDir,
184
+ chatId: t.chatId,
185
+ rootMessageId: t.rootMessageId,
186
+ larkAppId: t.larkAppId,
187
+ botName: getBotName(),
188
+ enabled: t.enabled,
189
+ createdAt: t.createdAt,
190
+ lastRunAt: t.lastRunAt,
191
+ nextRunAt: t.nextRunAt,
192
+ lastStatus: t.lastStatus,
193
+ lastError: t.lastError,
194
+ repeat: t.repeat,
195
+ feishuChatLink: feishuChatLink(t.chatId),
196
+ };
197
+ }
198
+ ipcRoute('GET', '/api/schedules', (_req, res) => {
199
+ // Filter to tasks owned by this daemon's bot (multi-bot setups run one
200
+ // daemon per bot — each only manages its own schedules). belongsToOwner
201
+ // falls through to "all tasks" when no owner filter is configured (tests).
202
+ const all = scheduleStore.listTasks().filter(t => scheduler.belongsToOwner(t));
203
+ jsonRes(res, 200, { schedules: all.map(composeScheduleRow) });
204
+ });
205
+ ipcRoute('POST', '/api/schedules/:id/run', (_req, res, p) => jsonRes(res, 200, scheduler.runNow(p.id)));
206
+ ipcRoute('POST', '/api/schedules/:id/pause', (_req, res, p) => jsonRes(res, 200, scheduler.setEnabled(p.id, false)));
207
+ ipcRoute('POST', '/api/schedules/:id/resume', (_req, res, p) => jsonRes(res, 200, scheduler.setEnabled(p.id, true)));
208
+ // ─── Groups (Phase B) ──────────────────────────────────────────────────────
209
+ ipcRoute('GET', '/api/groups', async (_req, res) => {
210
+ if (!cachedLarkAppId)
211
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
212
+ try {
213
+ const chats = await groupsStore.listChats(cachedLarkAppId);
214
+ // Stamp a firstSeenAt timestamp for every chat (preserve existing values,
215
+ // backfill new ones with Date.now()). Lark doesn't expose chat create_time
216
+ // anywhere, so the dashboard sorts by this client-side proxy instead.
217
+ const seenMap = chatFirstSeenStore.markSeenBulk(chats.map(c => c.chatId));
218
+ // Annotate each chat with its oncall binding (if any) so the dashboard
219
+ // matrix can show toggle state without a second round-trip.
220
+ const enriched = chats.map(c => {
221
+ const oncall = oncallStore.getOncallStatus(cachedLarkAppId, c.chatId);
222
+ return { ...c, oncallChat: oncall ?? null, firstSeenAt: seenMap.get(c.chatId) ?? null };
223
+ });
224
+ jsonRes(res, 200, { chats: enriched });
225
+ }
226
+ catch (e) {
227
+ jsonRes(res, 502, { error: String(e) });
228
+ }
229
+ });
230
+ ipcRoute('GET', '/api/groups/:chatId/membership', async (_req, res, p) => {
231
+ if (!cachedLarkAppId)
232
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
233
+ try {
234
+ const inChat = await groupsStore.isInChat(cachedLarkAppId, p.chatId);
235
+ jsonRes(res, 200, { inChat });
236
+ }
237
+ catch (e) {
238
+ jsonRes(res, 502, { error: String(e) });
239
+ }
240
+ });
241
+ ipcRoute('POST', '/api/groups/:chatId/add-bots', async (req, res, p) => {
242
+ if (!cachedLarkAppId)
243
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
244
+ let body;
245
+ try {
246
+ body = await readJsonBody(req);
247
+ }
248
+ catch {
249
+ return jsonRes(res, 400, { error: 'bad_json' });
250
+ }
251
+ if (!Array.isArray(body.larkAppIds) || !body.larkAppIds.every(x => typeof x === 'string')) {
252
+ return jsonRes(res, 400, { error: 'larkAppIds_required' });
253
+ }
254
+ try {
255
+ const result = await groupsStore.addBotToChat(cachedLarkAppId, p.chatId, body.larkAppIds);
256
+ jsonRes(res, 200, { result });
257
+ }
258
+ catch (e) {
259
+ jsonRes(res, 502, { error: String(e) });
260
+ }
261
+ });
262
+ // Disband (delete) a chat from this bot's identity. Public route picks an
263
+ // in-chat bot as the executor; this just performs the call.
264
+ ipcRoute('POST', '/api/groups/:chatId/disband', async (_req, res, p) => {
265
+ if (!cachedLarkAppId)
266
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
267
+ const r = await groupsStore.disbandChat(cachedLarkAppId, p.chatId);
268
+ jsonRes(res, 200, r);
269
+ });
270
+ // Make this bot leave the chat. Always works on a member bot per Lark docs.
271
+ ipcRoute('POST', '/api/groups/:chatId/leave', async (_req, res, p) => {
272
+ if (!cachedLarkAppId)
273
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
274
+ const r = await groupsStore.leaveChat(cachedLarkAppId, p.chatId);
275
+ jsonRes(res, 200, r);
276
+ });
277
+ // ─── Oncall bindings (dashboard) ───────────────────────────────────────────
278
+ // PUT /api/oncall/:chatId body: {workingDir} — bind or update workingDir
279
+ // DELETE /api/oncall/:chatId — unbind
280
+ //
281
+ // Auth: dashboard's loopback token is the gate. No per-chat owner concept —
282
+ // allowedUsers governs who can operate via Lark too (see canOperate).
283
+ ipcRoute('PUT', '/api/oncall/:chatId', async (req, res, p) => {
284
+ if (!cachedLarkAppId)
285
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
286
+ let body;
287
+ try {
288
+ body = await readJsonBody(req);
289
+ }
290
+ catch {
291
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
292
+ }
293
+ const workingDir = typeof body.workingDir === 'string' ? body.workingDir.trim() : '';
294
+ if (!workingDir)
295
+ return jsonRes(res, 400, { ok: false, error: 'workingDir_required' });
296
+ // Same validation as /oncall bind in Lark — exists + is a directory.
297
+ const resolvedPath = resolve(expandHome(workingDir));
298
+ if (!existsSync(resolvedPath)) {
299
+ return jsonRes(res, 400, { ok: false, error: `目录不存在:${resolvedPath}` });
300
+ }
301
+ let isDir = false;
302
+ try {
303
+ isDir = statSync(resolvedPath).isDirectory();
304
+ }
305
+ catch (e) {
306
+ return jsonRes(res, 400, { ok: false, error: `无法读取路径:${resolvedPath}(${e?.message ?? e})` });
307
+ }
308
+ if (!isDir)
309
+ return jsonRes(res, 400, { ok: false, error: `路径不是目录:${resolvedPath}` });
310
+ const r = await oncallStore.bindOncall(cachedLarkAppId, p.chatId, workingDir);
311
+ if (!r.ok)
312
+ return jsonRes(res, 400, r);
313
+ jsonRes(res, 200, { ok: true, entry: r.entry, created: r.created, resolvedPath });
314
+ });
315
+ ipcRoute('DELETE', '/api/oncall/:chatId', async (_req, res, p) => {
316
+ if (!cachedLarkAppId)
317
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
318
+ // Idempotent: always succeeds. unbindOncall writes a tombstone into
319
+ // defaultOncallAutoboundChats so the auto-bind judge won't reinstate this
320
+ // chat on the next observation, even if it had no prior binding.
321
+ const r = await oncallStore.unbindOncall(cachedLarkAppId, p.chatId);
322
+ if (!r.ok)
323
+ return jsonRes(res, 400, r);
324
+ jsonRes(res, 200, { ok: true, wasBound: r.wasBound });
325
+ });
326
+ // ─── Per-bot defaultOncall (dashboard) ─────────────────────────────────────
327
+ // GET /api/bot-default-oncall → returns this daemon's current config
328
+ // PUT /api/bot-default-oncall body: { enabled, workingDir }
329
+ //
330
+ // Forward-only policy: enabling does not backfill or distinguish "old vs new"
331
+ // chats. Any group the bot is in — present or future — auto-binds on its
332
+ // next observed topic if it has no existing oncall binding and is not in
333
+ // the tombstone list. `since` is stamped purely as informational metadata
334
+ // (UI shows "上次启用时间").
335
+ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
336
+ if (!cachedLarkAppId)
337
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
338
+ const { defaultOncall, autoboundChats } = oncallStore.getBotDefaultOncall(cachedLarkAppId);
339
+ jsonRes(res, 200, {
340
+ larkAppId: cachedLarkAppId,
341
+ botName: getBotName(),
342
+ defaultOncall: defaultOncall ?? { enabled: false, workingDir: '', since: 0 },
343
+ autoboundChatCount: autoboundChats.length,
344
+ });
345
+ });
346
+ ipcRoute('PUT', '/api/bot-default-oncall', async (req, res) => {
347
+ if (!cachedLarkAppId)
348
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
349
+ let body;
350
+ try {
351
+ body = await readJsonBody(req);
352
+ }
353
+ catch {
354
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
355
+ }
356
+ const enabled = body.enabled === true;
357
+ const workingDir = typeof body.workingDir === 'string' ? body.workingDir.trim() : '';
358
+ // Validate workingDir when enabling. Allow blank workingDir only when
359
+ // disabling — the on-disk record keeps the last value so the UI can
360
+ // round-trip after a disable.
361
+ let resolvedPath = '';
362
+ if (enabled) {
363
+ if (!workingDir)
364
+ return jsonRes(res, 400, { ok: false, error: 'workingDir_required' });
365
+ resolvedPath = resolve(expandHome(workingDir));
366
+ if (!existsSync(resolvedPath)) {
367
+ return jsonRes(res, 400, { ok: false, error: `目录不存在:${resolvedPath}` });
368
+ }
369
+ let isDir = false;
370
+ try {
371
+ isDir = statSync(resolvedPath).isDirectory();
372
+ }
373
+ catch (e) {
374
+ return jsonRes(res, 400, { ok: false, error: `无法读取路径:${resolvedPath}(${e?.message ?? e})` });
375
+ }
376
+ if (!isDir)
377
+ return jsonRes(res, 400, { ok: false, error: `路径不是目录:${resolvedPath}` });
378
+ }
379
+ const r = await oncallStore.updateBotDefaultOncall(cachedLarkAppId, { enabled, workingDir });
380
+ if (!r.ok)
381
+ return jsonRes(res, 400, r);
382
+ jsonRes(res, 200, { ok: true, defaultOncall: r.defaultOncall, resolvedPath: resolvedPath || undefined });
383
+ });
384
+ // Create a brand-new chat with this bot as creator/owner and `larkAppIds` as
385
+ // initial bot members. The dashboard's public route picks any online daemon
386
+ // to act as creator, then forwards here.
387
+ ipcRoute('POST', '/api/groups/create', async (req, res) => {
388
+ if (!cachedLarkAppId)
389
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
390
+ let body;
391
+ try {
392
+ body = await readJsonBody(req);
393
+ }
394
+ catch {
395
+ return jsonRes(res, 400, { error: 'bad_json' });
396
+ }
397
+ const name = typeof body.name === 'string' && body.name.trim() ? body.name.trim() : undefined;
398
+ if (!Array.isArray(body.larkAppIds) || !body.larkAppIds.every(x => typeof x === 'string')) {
399
+ return jsonRes(res, 400, { error: 'larkAppIds_required' });
400
+ }
401
+ // userOpenIds, transferOwnerTo, notifyOwnerOpenId are optional; pre-validated
402
+ // upstream by the dashboard route. All open_ids MUST be in the calling bot's
403
+ // app scope (caller is responsible — Lark open_ids are app-scoped, see
404
+ // dashboard/operator-selector.ts).
405
+ const userIds = Array.isArray(body.userOpenIds) && body.userOpenIds.every(x => typeof x === 'string')
406
+ ? body.userOpenIds
407
+ : [];
408
+ const transferTo = typeof body.transferOwnerTo === 'string' && body.transferOwnerTo.trim()
409
+ ? body.transferOwnerTo.trim()
410
+ : null;
411
+ const notifyTo = typeof body.notifyOwnerOpenId === 'string' && body.notifyOwnerOpenId.trim()
412
+ ? body.notifyOwnerOpenId.trim()
413
+ : null;
414
+ try {
415
+ const r = await createGroupWithBots({
416
+ creatorLarkAppId: cachedLarkAppId,
417
+ larkAppIds: body.larkAppIds,
418
+ name,
419
+ userOpenIds: userIds,
420
+ transferOwnerTo: transferTo ?? undefined,
421
+ notifyOwnerOpenId: notifyTo ?? undefined,
422
+ });
423
+ jsonRes(res, 200, r);
424
+ }
425
+ catch (e) {
426
+ jsonRes(res, 502, { ok: false, error: String(e.message ?? e) });
427
+ }
428
+ });
429
+ // ─── SSE event stream ──────────────────────────────────────────────────────
430
+ ipcRoute('GET', '/api/events', (_req, res) => {
431
+ res.writeHead(200, {
432
+ 'content-type': 'text/event-stream',
433
+ 'cache-control': 'no-cache, no-transform',
434
+ 'connection': 'keep-alive',
435
+ });
436
+ // Initial flush so the client sees the connection alive immediately.
437
+ res.write('retry: 5000\n\n');
438
+ const off = dashboardEventBus.subscribe(ev => {
439
+ res.write(`event: ${ev.type}\ndata: ${JSON.stringify(ev.body)}\n\n`);
440
+ });
441
+ const hb = setInterval(() => {
442
+ res.write(`event: heartbeat\ndata: ${JSON.stringify({ ts: Date.now() })}\n\n`);
443
+ }, 15_000);
444
+ res.on('close', () => { off(); clearInterval(hb); });
445
+ });
446
+ export function startIpcServer(opts) {
447
+ return new Promise((resolve, reject) => {
448
+ const server = createServer(async (req, res) => {
449
+ try {
450
+ const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
451
+ for (const r of routes) {
452
+ if (r.method !== req.method)
453
+ continue;
454
+ const m = r.pattern.exec(url.pathname);
455
+ if (!m)
456
+ continue;
457
+ const params = {};
458
+ r.keys.forEach((k, i) => { params[k] = decodeURIComponent(m[i + 1]); });
459
+ await r.handler(req, res, params);
460
+ return;
461
+ }
462
+ jsonRes(res, 404, { error: 'not_found', path: url.pathname });
463
+ }
464
+ catch (err) {
465
+ logger.error('[dashboard-ipc] handler error', err);
466
+ if (!res.headersSent)
467
+ jsonRes(res, 500, { error: String(err) });
468
+ }
469
+ });
470
+ server.listen(opts.port, opts.host, () => {
471
+ const addr = server.address();
472
+ const port = typeof addr === 'object' && addr ? addr.port : opts.port;
473
+ resolve({
474
+ port,
475
+ close: () => new Promise(r => server.close(() => r())),
476
+ });
477
+ });
478
+ server.once('error', reject);
479
+ });
480
+ }
481
+ //# sourceMappingURL=dashboard-ipc-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-ipc-server.js","sourceRoot":"","sources":["../../src/core/dashboard-ipc-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Per-sessionId 30s rate limiter for the dashboard locate action.
3
+ * The slot is consumed on attempt, not on success — a 404 still burns the
4
+ * slot. This keeps the rate limit useful against sessionId enumeration via
5
+ * fast spam and matches the design spec.
6
+ */
7
+ export declare class LocateRateLimiter {
8
+ private windowMs;
9
+ private last;
10
+ constructor(windowMs: number);
11
+ tryAcquire(sessionId: string): {
12
+ ok: true;
13
+ } | {
14
+ ok: false;
15
+ retryAfterMs: number;
16
+ };
17
+ }
18
+ /** Module singleton — process-wide rate limit shared across all routes. */
19
+ export declare const locateLimiter: LocateRateLimiter;
20
+ //# sourceMappingURL=dashboard-locate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-locate.d.ts","sourceRoot":"","sources":["../../src/core/dashboard-locate.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,qBAAa,iBAAiB;IAEhB,OAAO,CAAC,QAAQ;IAD5B,OAAO,CAAC,IAAI,CAA6B;gBACrB,QAAQ,EAAE,MAAM;IAEpC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;CASlF;AAED,2EAA2E;AAC3E,eAAO,MAAM,aAAa,mBAAgC,CAAC"}
@@ -0,0 +1,26 @@
1
+ // src/core/dashboard-locate.ts
2
+ /**
3
+ * Per-sessionId 30s rate limiter for the dashboard locate action.
4
+ * The slot is consumed on attempt, not on success — a 404 still burns the
5
+ * slot. This keeps the rate limit useful against sessionId enumeration via
6
+ * fast spam and matches the design spec.
7
+ */
8
+ export class LocateRateLimiter {
9
+ windowMs;
10
+ last = new Map();
11
+ constructor(windowMs) {
12
+ this.windowMs = windowMs;
13
+ }
14
+ tryAcquire(sessionId) {
15
+ const now = Date.now();
16
+ const last = this.last.get(sessionId);
17
+ if (last !== undefined && now - last < this.windowMs) {
18
+ return { ok: false, retryAfterMs: this.windowMs - (now - last) };
19
+ }
20
+ this.last.set(sessionId, now);
21
+ return { ok: true };
22
+ }
23
+ }
24
+ /** Module singleton — process-wide rate limit shared across all routes. */
25
+ export const locateLimiter = new LocateRateLimiter(30_000);
26
+ //# sourceMappingURL=dashboard-locate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-locate.js","sourceRoot":"","sources":["../../src/core/dashboard-locate.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IAER;IADZ,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,YAAoB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAG,CAAC;IAExC,UAAU,CAAC,SAAiB;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,IAAI,KAAK,SAAS,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;QACnE,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;CACF;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { DaemonSession } from './types.js';
2
+ import type { Session } from '../types.js';
3
+ import type { CliId } from '../adapters/cli/types.js';
4
+ export interface SessionRow {
5
+ sessionId: string;
6
+ larkAppId: string;
7
+ botName: string;
8
+ cliId: CliId | 'unknown';
9
+ status: 'starting' | 'working' | 'idle' | 'analyzing' | 'closed';
10
+ adopt: boolean;
11
+ spawnedAt: number;
12
+ lastMessageAt: number;
13
+ closedAt?: number;
14
+ workingDir?: string;
15
+ chatId: string;
16
+ rootMessageId: string;
17
+ threadId?: string;
18
+ title?: string;
19
+ ownerOpenId?: string;
20
+ webPort: number | null;
21
+ cliVersion?: string;
22
+ hasHistory?: boolean;
23
+ feishuChatLink: string;
24
+ }
25
+ export declare function feishuChatLink(chatId: string): string;
26
+ export declare function setBotName(name: string): void;
27
+ export declare function getBotName(): string;
28
+ export declare function sessionLastActivityAtMs(s: Session): number;
29
+ export declare function composeRowFromActive(ds: DaemonSession): SessionRow;
30
+ export declare function composeRowFromClosed(s: Session): SessionRow;
31
+ //# sourceMappingURL=dashboard-rows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-rows.d.ts","sourceRoot":"","sources":["../../src/core/dashboard-rows.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEtD,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACjE,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAA0B;AACxE,wBAAgB,UAAU,IAAI,MAAM,CAA0B;AAY9D,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAE1D;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,aAAa,GAAG,UAAU,CAyBlE;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,GAAG,UAAU,CAmB3D"}