reflectt-node 0.1.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 (486) hide show
  1. package/LICENSE +178 -0
  2. package/README.md +188 -0
  3. package/dist/activationEvents.d.ts +110 -0
  4. package/dist/activationEvents.d.ts.map +1 -0
  5. package/dist/activationEvents.js +378 -0
  6. package/dist/activationEvents.js.map +1 -0
  7. package/dist/activity-signal.d.ts +30 -0
  8. package/dist/activity-signal.d.ts.map +1 -0
  9. package/dist/activity-signal.js +93 -0
  10. package/dist/activity-signal.js.map +1 -0
  11. package/dist/alert-integrity.d.ts +100 -0
  12. package/dist/alert-integrity.d.ts.map +1 -0
  13. package/dist/alert-integrity.js +333 -0
  14. package/dist/alert-integrity.js.map +1 -0
  15. package/dist/alert-preflight.d.ts +40 -0
  16. package/dist/alert-preflight.d.ts.map +1 -0
  17. package/dist/alert-preflight.js +235 -0
  18. package/dist/alert-preflight.js.map +1 -0
  19. package/dist/analytics.d.ts +131 -0
  20. package/dist/analytics.d.ts.map +1 -0
  21. package/dist/analytics.js +371 -0
  22. package/dist/analytics.js.map +1 -0
  23. package/dist/artifact-mirror.d.ts +26 -0
  24. package/dist/artifact-mirror.d.ts.map +1 -0
  25. package/dist/artifact-mirror.js +170 -0
  26. package/dist/artifact-mirror.js.map +1 -0
  27. package/dist/artifact-resolver.d.ts +48 -0
  28. package/dist/artifact-resolver.d.ts.map +1 -0
  29. package/dist/artifact-resolver.js +164 -0
  30. package/dist/artifact-resolver.js.map +1 -0
  31. package/dist/assignment.d.ts +116 -0
  32. package/dist/assignment.d.ts.map +1 -0
  33. package/dist/assignment.js +475 -0
  34. package/dist/assignment.js.map +1 -0
  35. package/dist/auditLedger.d.ts +50 -0
  36. package/dist/auditLedger.d.ts.map +1 -0
  37. package/dist/auditLedger.js +136 -0
  38. package/dist/auditLedger.js.map +1 -0
  39. package/dist/boardHealthWorker.d.ts +134 -0
  40. package/dist/boardHealthWorker.d.ts.map +1 -0
  41. package/dist/boardHealthWorker.js +882 -0
  42. package/dist/boardHealthWorker.js.map +1 -0
  43. package/dist/bootstrap-team.d.ts +42 -0
  44. package/dist/bootstrap-team.d.ts.map +1 -0
  45. package/dist/bootstrap-team.js +111 -0
  46. package/dist/bootstrap-team.js.map +1 -0
  47. package/dist/buildInfo.d.ts +17 -0
  48. package/dist/buildInfo.d.ts.map +1 -0
  49. package/dist/buildInfo.js +56 -0
  50. package/dist/buildInfo.js.map +1 -0
  51. package/dist/calendar-events.d.ts +133 -0
  52. package/dist/calendar-events.d.ts.map +1 -0
  53. package/dist/calendar-events.js +615 -0
  54. package/dist/calendar-events.js.map +1 -0
  55. package/dist/calendar-ical.d.ts +41 -0
  56. package/dist/calendar-ical.d.ts.map +1 -0
  57. package/dist/calendar-ical.js +413 -0
  58. package/dist/calendar-ical.js.map +1 -0
  59. package/dist/calendar-reminder-engine.d.ts +10 -0
  60. package/dist/calendar-reminder-engine.d.ts.map +1 -0
  61. package/dist/calendar-reminder-engine.js +143 -0
  62. package/dist/calendar-reminder-engine.js.map +1 -0
  63. package/dist/calendar.d.ts +75 -0
  64. package/dist/calendar.d.ts.map +1 -0
  65. package/dist/calendar.js +391 -0
  66. package/dist/calendar.js.map +1 -0
  67. package/dist/canvas-multiplexer.d.ts +44 -0
  68. package/dist/canvas-multiplexer.d.ts.map +1 -0
  69. package/dist/canvas-multiplexer.js +150 -0
  70. package/dist/canvas-multiplexer.js.map +1 -0
  71. package/dist/canvas-slots.d.ts +83 -0
  72. package/dist/canvas-slots.d.ts.map +1 -0
  73. package/dist/canvas-slots.js +144 -0
  74. package/dist/canvas-slots.js.map +1 -0
  75. package/dist/canvas-types.d.ts +56 -0
  76. package/dist/canvas-types.d.ts.map +1 -0
  77. package/dist/canvas-types.js +54 -0
  78. package/dist/canvas-types.js.map +1 -0
  79. package/dist/cf-keepalive.d.ts +40 -0
  80. package/dist/cf-keepalive.d.ts.map +1 -0
  81. package/dist/cf-keepalive.js +153 -0
  82. package/dist/cf-keepalive.js.map +1 -0
  83. package/dist/changeFeed.d.ts +38 -0
  84. package/dist/changeFeed.d.ts.map +1 -0
  85. package/dist/changeFeed.js +324 -0
  86. package/dist/changeFeed.js.map +1 -0
  87. package/dist/channels.d.ts +28 -0
  88. package/dist/channels.d.ts.map +1 -0
  89. package/dist/channels.js +23 -0
  90. package/dist/channels.js.map +1 -0
  91. package/dist/chat-approval-detector.d.ts +47 -0
  92. package/dist/chat-approval-detector.d.ts.map +1 -0
  93. package/dist/chat-approval-detector.js +224 -0
  94. package/dist/chat-approval-detector.js.map +1 -0
  95. package/dist/chat.d.ts +119 -0
  96. package/dist/chat.d.ts.map +1 -0
  97. package/dist/chat.js +666 -0
  98. package/dist/chat.js.map +1 -0
  99. package/dist/cli.d.ts +3 -0
  100. package/dist/cli.d.ts.map +1 -0
  101. package/dist/cli.js +1142 -0
  102. package/dist/cli.js.map +1 -0
  103. package/dist/cloud.d.ts +45 -0
  104. package/dist/cloud.d.ts.map +1 -0
  105. package/dist/cloud.js +962 -0
  106. package/dist/cloud.js.map +1 -0
  107. package/dist/config.d.ts +17 -0
  108. package/dist/config.d.ts.map +1 -0
  109. package/dist/config.js +33 -0
  110. package/dist/config.js.map +1 -0
  111. package/dist/connectivity.d.ts +59 -0
  112. package/dist/connectivity.d.ts.map +1 -0
  113. package/dist/connectivity.js +173 -0
  114. package/dist/connectivity.js.map +1 -0
  115. package/dist/contacts.d.ts +59 -0
  116. package/dist/contacts.d.ts.map +1 -0
  117. package/dist/contacts.js +183 -0
  118. package/dist/contacts.js.map +1 -0
  119. package/dist/content.d.ts +130 -0
  120. package/dist/content.d.ts.map +1 -0
  121. package/dist/content.js +186 -0
  122. package/dist/content.js.map +1 -0
  123. package/dist/context-budget.d.ts +87 -0
  124. package/dist/context-budget.d.ts.map +1 -0
  125. package/dist/context-budget.js +459 -0
  126. package/dist/context-budget.js.map +1 -0
  127. package/dist/continuity-loop.d.ts +55 -0
  128. package/dist/continuity-loop.d.ts.map +1 -0
  129. package/dist/continuity-loop.js +267 -0
  130. package/dist/continuity-loop.js.map +1 -0
  131. package/dist/dashboard.d.ts +6 -0
  132. package/dist/dashboard.d.ts.map +1 -0
  133. package/dist/dashboard.js +2348 -0
  134. package/dist/dashboard.js.map +1 -0
  135. package/dist/db.d.ts +44 -0
  136. package/dist/db.d.ts.map +1 -0
  137. package/dist/db.js +648 -0
  138. package/dist/db.js.map +1 -0
  139. package/dist/doctor.d.ts +30 -0
  140. package/dist/doctor.d.ts.map +1 -0
  141. package/dist/doctor.js +159 -0
  142. package/dist/doctor.js.map +1 -0
  143. package/dist/duplicateClosureGuard.d.ts +31 -0
  144. package/dist/duplicateClosureGuard.d.ts.map +1 -0
  145. package/dist/duplicateClosureGuard.js +83 -0
  146. package/dist/duplicateClosureGuard.js.map +1 -0
  147. package/dist/embeddings.d.ts +13 -0
  148. package/dist/embeddings.d.ts.map +1 -0
  149. package/dist/embeddings.js +78 -0
  150. package/dist/embeddings.js.map +1 -0
  151. package/dist/escalation.d.ts +80 -0
  152. package/dist/escalation.d.ts.map +1 -0
  153. package/dist/escalation.js +213 -0
  154. package/dist/escalation.js.map +1 -0
  155. package/dist/events.d.ts +130 -0
  156. package/dist/events.d.ts.map +1 -0
  157. package/dist/events.js +382 -0
  158. package/dist/events.js.map +1 -0
  159. package/dist/executionSweeper.d.ts +97 -0
  160. package/dist/executionSweeper.d.ts.map +1 -0
  161. package/dist/executionSweeper.js +875 -0
  162. package/dist/executionSweeper.js.map +1 -0
  163. package/dist/experiments.d.ts +47 -0
  164. package/dist/experiments.d.ts.map +1 -0
  165. package/dist/experiments.js +133 -0
  166. package/dist/experiments.js.map +1 -0
  167. package/dist/feedback.d.ts +179 -0
  168. package/dist/feedback.d.ts.map +1 -0
  169. package/dist/feedback.js +397 -0
  170. package/dist/feedback.js.map +1 -0
  171. package/dist/files.d.ts +52 -0
  172. package/dist/files.d.ts.map +1 -0
  173. package/dist/files.js +172 -0
  174. package/dist/files.js.map +1 -0
  175. package/dist/format-duration.d.ts +19 -0
  176. package/dist/format-duration.d.ts.map +1 -0
  177. package/dist/format-duration.js +33 -0
  178. package/dist/format-duration.js.map +1 -0
  179. package/dist/github-actor-auth.d.ts +20 -0
  180. package/dist/github-actor-auth.d.ts.map +1 -0
  181. package/dist/github-actor-auth.js +54 -0
  182. package/dist/github-actor-auth.js.map +1 -0
  183. package/dist/github-ci.d.ts +16 -0
  184. package/dist/github-ci.d.ts.map +1 -0
  185. package/dist/github-ci.js +37 -0
  186. package/dist/github-ci.js.map +1 -0
  187. package/dist/github-identity.d.ts +30 -0
  188. package/dist/github-identity.d.ts.map +1 -0
  189. package/dist/github-identity.js +96 -0
  190. package/dist/github-identity.js.map +1 -0
  191. package/dist/github-reviews.d.ts +24 -0
  192. package/dist/github-reviews.d.ts.map +1 -0
  193. package/dist/github-reviews.js +56 -0
  194. package/dist/github-reviews.js.map +1 -0
  195. package/dist/health.d.ts +391 -0
  196. package/dist/health.d.ts.map +1 -0
  197. package/dist/health.js +1841 -0
  198. package/dist/health.js.map +1 -0
  199. package/dist/host-keepalive.d.ts +22 -0
  200. package/dist/host-keepalive.d.ts.map +1 -0
  201. package/dist/host-keepalive.js +126 -0
  202. package/dist/host-keepalive.js.map +1 -0
  203. package/dist/host-registry.d.ts +43 -0
  204. package/dist/host-registry.d.ts.map +1 -0
  205. package/dist/host-registry.js +93 -0
  206. package/dist/host-registry.js.map +1 -0
  207. package/dist/inbox.d.ts +87 -0
  208. package/dist/inbox.d.ts.map +1 -0
  209. package/dist/inbox.js +410 -0
  210. package/dist/inbox.js.map +1 -0
  211. package/dist/index.d.ts +2 -0
  212. package/dist/index.d.ts.map +1 -0
  213. package/dist/index.js +306 -0
  214. package/dist/index.js.map +1 -0
  215. package/dist/insight-mutation.d.ts +32 -0
  216. package/dist/insight-mutation.d.ts.map +1 -0
  217. package/dist/insight-mutation.js +160 -0
  218. package/dist/insight-mutation.js.map +1 -0
  219. package/dist/insight-promotion.d.ts +89 -0
  220. package/dist/insight-promotion.d.ts.map +1 -0
  221. package/dist/insight-promotion.js +278 -0
  222. package/dist/insight-promotion.js.map +1 -0
  223. package/dist/insight-task-bridge.d.ts +77 -0
  224. package/dist/insight-task-bridge.d.ts.map +1 -0
  225. package/dist/insight-task-bridge.js +556 -0
  226. package/dist/insight-task-bridge.js.map +1 -0
  227. package/dist/insights.d.ts +222 -0
  228. package/dist/insights.d.ts.map +1 -0
  229. package/dist/insights.js +871 -0
  230. package/dist/insights.js.map +1 -0
  231. package/dist/intake-pipeline.d.ts +74 -0
  232. package/dist/intake-pipeline.d.ts.map +1 -0
  233. package/dist/intake-pipeline.js +199 -0
  234. package/dist/intake-pipeline.js.map +1 -0
  235. package/dist/intensity.d.ts +31 -0
  236. package/dist/intensity.d.ts.map +1 -0
  237. package/dist/intensity.js +94 -0
  238. package/dist/intensity.js.map +1 -0
  239. package/dist/knowledge-auto-index.d.ts +37 -0
  240. package/dist/knowledge-auto-index.d.ts.map +1 -0
  241. package/dist/knowledge-auto-index.js +149 -0
  242. package/dist/knowledge-auto-index.js.map +1 -0
  243. package/dist/knowledge-docs.d.ts +45 -0
  244. package/dist/knowledge-docs.d.ts.map +1 -0
  245. package/dist/knowledge-docs.js +188 -0
  246. package/dist/knowledge-docs.js.map +1 -0
  247. package/dist/lane-config.d.ts +25 -0
  248. package/dist/lane-config.d.ts.map +1 -0
  249. package/dist/lane-config.js +105 -0
  250. package/dist/lane-config.js.map +1 -0
  251. package/dist/lineage.d.ts +86 -0
  252. package/dist/lineage.d.ts.map +1 -0
  253. package/dist/lineage.js +303 -0
  254. package/dist/lineage.js.map +1 -0
  255. package/dist/logStore.d.ts +25 -0
  256. package/dist/logStore.d.ts.map +1 -0
  257. package/dist/logStore.js +83 -0
  258. package/dist/logStore.js.map +1 -0
  259. package/dist/manage.d.ts +12 -0
  260. package/dist/manage.d.ts.map +1 -0
  261. package/dist/manage.js +253 -0
  262. package/dist/manage.js.map +1 -0
  263. package/dist/mcp.d.ts +5 -0
  264. package/dist/mcp.d.ts.map +1 -0
  265. package/dist/mcp.js +604 -0
  266. package/dist/mcp.js.map +1 -0
  267. package/dist/memory.d.ts +47 -0
  268. package/dist/memory.d.ts.map +1 -0
  269. package/dist/memory.js +149 -0
  270. package/dist/memory.js.map +1 -0
  271. package/dist/mention-ack.d.ts +80 -0
  272. package/dist/mention-ack.d.ts.map +1 -0
  273. package/dist/mention-ack.js +175 -0
  274. package/dist/mention-ack.js.map +1 -0
  275. package/dist/messageRouter.d.ts +60 -0
  276. package/dist/messageRouter.d.ts.map +1 -0
  277. package/dist/messageRouter.js +309 -0
  278. package/dist/messageRouter.js.map +1 -0
  279. package/dist/mutationAlert.d.ts +44 -0
  280. package/dist/mutationAlert.d.ts.map +1 -0
  281. package/dist/mutationAlert.js +174 -0
  282. package/dist/mutationAlert.js.map +1 -0
  283. package/dist/noise-budget.d.ts +136 -0
  284. package/dist/noise-budget.d.ts.map +1 -0
  285. package/dist/noise-budget.js +340 -0
  286. package/dist/noise-budget.js.map +1 -0
  287. package/dist/notifications.d.ts +67 -0
  288. package/dist/notifications.d.ts.map +1 -0
  289. package/dist/notifications.js +253 -0
  290. package/dist/notifications.js.map +1 -0
  291. package/dist/openclaw.d.ts +34 -0
  292. package/dist/openclaw.d.ts.map +1 -0
  293. package/dist/openclaw.js +208 -0
  294. package/dist/openclaw.js.map +1 -0
  295. package/dist/pause-controls.d.ts +31 -0
  296. package/dist/pause-controls.d.ts.map +1 -0
  297. package/dist/pause-controls.js +130 -0
  298. package/dist/pause-controls.js.map +1 -0
  299. package/dist/pidlock.d.ts +25 -0
  300. package/dist/pidlock.d.ts.map +1 -0
  301. package/dist/pidlock.js +179 -0
  302. package/dist/pidlock.js.map +1 -0
  303. package/dist/policy.d.ts +139 -0
  304. package/dist/policy.d.ts.map +1 -0
  305. package/dist/policy.js +264 -0
  306. package/dist/policy.js.map +1 -0
  307. package/dist/polls.d.ts +47 -0
  308. package/dist/polls.d.ts.map +1 -0
  309. package/dist/polls.js +162 -0
  310. package/dist/polls.js.map +1 -0
  311. package/dist/portability.d.ts +55 -0
  312. package/dist/portability.d.ts.map +1 -0
  313. package/dist/portability.js +292 -0
  314. package/dist/portability.js.map +1 -0
  315. package/dist/pr-integrity.d.ts +45 -0
  316. package/dist/pr-integrity.d.ts.map +1 -0
  317. package/dist/pr-integrity.js +124 -0
  318. package/dist/pr-integrity.js.map +1 -0
  319. package/dist/prAutoMerge.d.ts +62 -0
  320. package/dist/prAutoMerge.d.ts.map +1 -0
  321. package/dist/prAutoMerge.js +493 -0
  322. package/dist/prAutoMerge.js.map +1 -0
  323. package/dist/preflight.d.ts +66 -0
  324. package/dist/preflight.d.ts.map +1 -0
  325. package/dist/preflight.js +864 -0
  326. package/dist/preflight.js.map +1 -0
  327. package/dist/presence.d.ts +98 -0
  328. package/dist/presence.d.ts.map +1 -0
  329. package/dist/presence.js +347 -0
  330. package/dist/presence.js.map +1 -0
  331. package/dist/provisioning.d.ts +101 -0
  332. package/dist/provisioning.d.ts.map +1 -0
  333. package/dist/provisioning.js +430 -0
  334. package/dist/provisioning.js.map +1 -0
  335. package/dist/reflection-automation.d.ts +59 -0
  336. package/dist/reflection-automation.d.ts.map +1 -0
  337. package/dist/reflection-automation.js +350 -0
  338. package/dist/reflection-automation.js.map +1 -0
  339. package/dist/reflections.d.ts +65 -0
  340. package/dist/reflections.d.ts.map +1 -0
  341. package/dist/reflections.js +306 -0
  342. package/dist/reflections.js.map +1 -0
  343. package/dist/release.d.ts +67 -0
  344. package/dist/release.d.ts.map +1 -0
  345. package/dist/release.js +275 -0
  346. package/dist/release.js.map +1 -0
  347. package/dist/request-tracker.d.ts +36 -0
  348. package/dist/request-tracker.d.ts.map +1 -0
  349. package/dist/request-tracker.js +109 -0
  350. package/dist/request-tracker.js.map +1 -0
  351. package/dist/research.d.ts +75 -0
  352. package/dist/research.d.ts.map +1 -0
  353. package/dist/research.js +171 -0
  354. package/dist/research.js.map +1 -0
  355. package/dist/routing-approvals.d.ts +73 -0
  356. package/dist/routing-approvals.d.ts.map +1 -0
  357. package/dist/routing-approvals.js +88 -0
  358. package/dist/routing-approvals.js.map +1 -0
  359. package/dist/routing-override.d.ts +94 -0
  360. package/dist/routing-override.d.ts.map +1 -0
  361. package/dist/routing-override.js +290 -0
  362. package/dist/routing-override.js.map +1 -0
  363. package/dist/scope-routing.d.ts +18 -0
  364. package/dist/scope-routing.d.ts.map +1 -0
  365. package/dist/scope-routing.js +29 -0
  366. package/dist/scope-routing.js.map +1 -0
  367. package/dist/secrets.d.ts +77 -0
  368. package/dist/secrets.d.ts.map +1 -0
  369. package/dist/secrets.js +287 -0
  370. package/dist/secrets.js.map +1 -0
  371. package/dist/server.d.ts +3 -0
  372. package/dist/server.d.ts.map +1 -0
  373. package/dist/server.js +10887 -0
  374. package/dist/server.js.map +1 -0
  375. package/dist/service-probe.d.ts +53 -0
  376. package/dist/service-probe.d.ts.map +1 -0
  377. package/dist/service-probe.js +225 -0
  378. package/dist/service-probe.js.map +1 -0
  379. package/dist/shared-workspace-api.d.ts +73 -0
  380. package/dist/shared-workspace-api.d.ts.map +1 -0
  381. package/dist/shared-workspace-api.js +281 -0
  382. package/dist/shared-workspace-api.js.map +1 -0
  383. package/dist/shipped-heartbeat.d.ts +91 -0
  384. package/dist/shipped-heartbeat.d.ts.map +1 -0
  385. package/dist/shipped-heartbeat.js +272 -0
  386. package/dist/shipped-heartbeat.js.map +1 -0
  387. package/dist/starter-team.d.ts +23 -0
  388. package/dist/starter-team.d.ts.map +1 -0
  389. package/dist/starter-team.js +88 -0
  390. package/dist/starter-team.js.map +1 -0
  391. package/dist/suppression-ledger.d.ts +73 -0
  392. package/dist/suppression-ledger.d.ts.map +1 -0
  393. package/dist/suppression-ledger.js +125 -0
  394. package/dist/suppression-ledger.js.map +1 -0
  395. package/dist/system-loop-state.d.ts +4 -0
  396. package/dist/system-loop-state.d.ts.map +1 -0
  397. package/dist/system-loop-state.js +40 -0
  398. package/dist/system-loop-state.js.map +1 -0
  399. package/dist/taskCommentIngest.d.ts +43 -0
  400. package/dist/taskCommentIngest.d.ts.map +1 -0
  401. package/dist/taskCommentIngest.js +59 -0
  402. package/dist/taskCommentIngest.js.map +1 -0
  403. package/dist/taskPrecheck.d.ts +20 -0
  404. package/dist/taskPrecheck.d.ts.map +1 -0
  405. package/dist/taskPrecheck.js +329 -0
  406. package/dist/taskPrecheck.js.map +1 -0
  407. package/dist/taskStateSync.d.ts +8 -0
  408. package/dist/taskStateSync.d.ts.map +1 -0
  409. package/dist/taskStateSync.js +79 -0
  410. package/dist/taskStateSync.js.map +1 -0
  411. package/dist/tasks.d.ts +140 -0
  412. package/dist/tasks.d.ts.map +1 -0
  413. package/dist/tasks.js +1281 -0
  414. package/dist/tasks.js.map +1 -0
  415. package/dist/team-config.d.ts +24 -0
  416. package/dist/team-config.d.ts.map +1 -0
  417. package/dist/team-config.js +221 -0
  418. package/dist/team-config.js.map +1 -0
  419. package/dist/team-doctor.d.ts +22 -0
  420. package/dist/team-doctor.d.ts.map +1 -0
  421. package/dist/team-doctor.js +270 -0
  422. package/dist/team-doctor.js.map +1 -0
  423. package/dist/team-pulse.d.ts +52 -0
  424. package/dist/team-pulse.d.ts.map +1 -0
  425. package/dist/team-pulse.js +176 -0
  426. package/dist/team-pulse.js.map +1 -0
  427. package/dist/telemetry.d.ts +74 -0
  428. package/dist/telemetry.d.ts.map +1 -0
  429. package/dist/telemetry.js +256 -0
  430. package/dist/telemetry.js.map +1 -0
  431. package/dist/test-task-filter.d.ts +21 -0
  432. package/dist/test-task-filter.d.ts.map +1 -0
  433. package/dist/test-task-filter.js +48 -0
  434. package/dist/test-task-filter.js.map +1 -0
  435. package/dist/types.d.ts +126 -0
  436. package/dist/types.d.ts.map +1 -0
  437. package/dist/types.js +4 -0
  438. package/dist/types.js.map +1 -0
  439. package/dist/usage-tracking.d.ts +101 -0
  440. package/dist/usage-tracking.d.ts.map +1 -0
  441. package/dist/usage-tracking.js +325 -0
  442. package/dist/usage-tracking.js.map +1 -0
  443. package/dist/vector-store.d.ts +87 -0
  444. package/dist/vector-store.d.ts.map +1 -0
  445. package/dist/vector-store.js +247 -0
  446. package/dist/vector-store.js.map +1 -0
  447. package/dist/watchdog/idleNudgeLane.d.ts +22 -0
  448. package/dist/watchdog/idleNudgeLane.d.ts.map +1 -0
  449. package/dist/watchdog/idleNudgeLane.js +98 -0
  450. package/dist/watchdog/idleNudgeLane.js.map +1 -0
  451. package/dist/webhooks.d.ts +103 -0
  452. package/dist/webhooks.d.ts.map +1 -0
  453. package/dist/webhooks.js +398 -0
  454. package/dist/webhooks.js.map +1 -0
  455. package/dist/working-contract.d.ts +42 -0
  456. package/dist/working-contract.d.ts.map +1 -0
  457. package/dist/working-contract.js +228 -0
  458. package/dist/working-contract.js.map +1 -0
  459. package/dist/ws-heartbeat.d.ts +66 -0
  460. package/dist/ws-heartbeat.d.ts.map +1 -0
  461. package/dist/ws-heartbeat.js +174 -0
  462. package/dist/ws-heartbeat.js.map +1 -0
  463. package/package.json +87 -0
  464. package/plugins/reflectt-channel/README.md +96 -0
  465. package/plugins/reflectt-channel/index.ts +789 -0
  466. package/plugins/reflectt-channel/openclaw.plugin.json +23 -0
  467. package/plugins/reflectt-channel/package.json +23 -0
  468. package/plugins/reflectt-channel/src/channel.ts +433 -0
  469. package/plugins/reflectt-channel/src/types.ts +29 -0
  470. package/public/avatars/echo.png +0 -0
  471. package/public/avatars/harmony.png +0 -0
  472. package/public/avatars/kai.png +0 -0
  473. package/public/avatars/link.png +0 -0
  474. package/public/avatars/pixel.png +0 -0
  475. package/public/avatars/rhythm.png +0 -0
  476. package/public/avatars/ryan.png +0 -0
  477. package/public/avatars/sage.png +0 -0
  478. package/public/avatars/scout.png +0 -0
  479. package/public/avatars/spark.png +0 -0
  480. package/public/dashboard-animations.css +381 -0
  481. package/public/dashboard.js +3479 -0
  482. package/public/docs.md +1062 -0
  483. package/public/file-upload-mock.html +1097 -0
  484. package/public/og-card.png +0 -0
  485. package/public/ui-kit.html +318 -0
  486. package/public/widget/feedback.js +194 -0
package/dist/chat.js ADDED
@@ -0,0 +1,666 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) Reflectt AI
3
+ import { promises as fs } from 'fs';
4
+ import { join } from 'path';
5
+ import { eventBus } from './events.js';
6
+ import { DATA_DIR, LEGACY_DATA_DIR } from './config.js';
7
+ import { CHANNEL_DEFINITIONS, DEFAULT_CHAT_CHANNELS } from './channels.js';
8
+ import { getDb, importJsonlIfNeeded, safeJsonParse, safeJsonStringify } from './db.js';
9
+ import { suppressionLedger } from './suppression-ledger.js';
10
+ // OpenClaw integration pending — chat works standalone for now
11
+ const MESSAGES_FILE = join(DATA_DIR, 'messages.jsonl');
12
+ const LEGACY_MESSAGES_FILE = join(LEGACY_DATA_DIR, 'messages.jsonl');
13
+ // All reads go directly to SQLite — no in-memory message cache.
14
+ // JSONL file is kept as an append-only audit trail.
15
+ function importMessages(db, records) {
16
+ const byId = new Map();
17
+ for (const record of records) {
18
+ if (!record || typeof record !== 'object')
19
+ continue;
20
+ const message = record;
21
+ if (typeof message.id !== 'string' || message.id.length === 0)
22
+ continue;
23
+ const deleteUpdate = Boolean(message.metadata?.deleteUpdate);
24
+ if (deleteUpdate) {
25
+ byId.delete(message.id);
26
+ continue;
27
+ }
28
+ if (typeof message.from !== 'string' || typeof message.content !== 'string')
29
+ continue;
30
+ byId.set(message.id, {
31
+ id: message.id,
32
+ from: message.from,
33
+ to: message.to,
34
+ content: message.content,
35
+ timestamp: Number(message.timestamp) || Date.now(),
36
+ channel: message.channel || 'general',
37
+ reactions: message.reactions || {},
38
+ threadId: message.threadId,
39
+ metadata: message.metadata,
40
+ });
41
+ }
42
+ if (byId.size === 0)
43
+ return 0;
44
+ const upsert = db.prepare(`
45
+ INSERT OR REPLACE INTO chat_messages (
46
+ id, "from", "to", content, timestamp, channel, reactions, thread_id, metadata, attachments
47
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
48
+ `);
49
+ const insertMany = db.transaction((messages) => {
50
+ for (const msg of messages) {
51
+ upsert.run(msg.id, msg.from, msg.to ?? null, msg.content, msg.timestamp, msg.channel || 'general', safeJsonStringify(msg.reactions), msg.threadId ?? null, safeJsonStringify(msg.metadata), msg.attachments?.length ? safeJsonStringify(msg.attachments) : null);
52
+ }
53
+ });
54
+ const messages = Array.from(byId.values());
55
+ insertMany(messages);
56
+ return messages.length;
57
+ }
58
+ /** Convert a SQLite row to an AgentMessage */
59
+ function rowToMessage(row) {
60
+ return {
61
+ id: row.id,
62
+ from: row.from,
63
+ to: row.to ?? undefined,
64
+ content: row.content,
65
+ timestamp: row.timestamp,
66
+ channel: row.channel || 'general',
67
+ reactions: safeJsonParse(row.reactions) || {},
68
+ threadId: row.thread_id ?? undefined,
69
+ metadata: safeJsonParse(row.metadata),
70
+ ...(row.attachments ? { attachments: safeJsonParse(row.attachments) ?? undefined } : {}),
71
+ };
72
+ }
73
+ class ChatManager {
74
+ rooms = new Map();
75
+ subscribers = new Set();
76
+ initialized = false;
77
+ constructor() {
78
+ // OpenClaw listener disabled for now — chat works standalone
79
+ // TODO: re-enable when OpenClaw connection is configured
80
+ // openclawClient.on('message', ...)
81
+ // Create default rooms/channels
82
+ for (const channel of CHANNEL_DEFINITIONS) {
83
+ this.createRoom(channel.id, channel.name);
84
+ }
85
+ // Run one-time JSONL → SQLite migration
86
+ this.migrateJsonl().catch(err => {
87
+ console.error('[Chat] Failed to migrate JSONL:', err);
88
+ });
89
+ }
90
+ async migrateJsonl() {
91
+ try {
92
+ await fs.mkdir(DATA_DIR, { recursive: true });
93
+ const db = getDb();
94
+ importJsonlIfNeeded(db, MESSAGES_FILE, 'chat_messages', importMessages);
95
+ importJsonlIfNeeded(db, LEGACY_MESSAGES_FILE, 'chat_messages', importMessages);
96
+ // All queries now go directly to SQLite — no in-memory array.
97
+ const countRow = db.prepare('SELECT COUNT(*) as count FROM chat_messages').get();
98
+ console.log(`[Chat] SQLite has ${countRow.count} messages (all queries go to DB, no in-memory cache)`);
99
+ }
100
+ finally {
101
+ this.initialized = true;
102
+ }
103
+ }
104
+ writeMessageToDb(message) {
105
+ const db = getDb();
106
+ const meta = (message.metadata || {});
107
+ const dedupKey = typeof meta.dedup_key === 'string' ? meta.dedup_key : null;
108
+ const upsert = db.prepare(`
109
+ INSERT OR REPLACE INTO chat_messages (
110
+ id, "from", "to", content, timestamp, channel, reactions, thread_id, metadata, dedup_key, attachments
111
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
112
+ `);
113
+ upsert.run(message.id, message.from, message.to ?? null, message.content, message.timestamp, message.channel || 'general', safeJsonStringify(message.reactions), message.threadId ?? null, safeJsonStringify(message.metadata), dedupKey, message.attachments?.length ? safeJsonStringify(message.attachments) : null);
114
+ }
115
+ deleteMessageFromDb(messageId) {
116
+ const db = getDb();
117
+ db.prepare('DELETE FROM chat_messages WHERE id = ?').run(messageId);
118
+ }
119
+ async appendAuditRecord(record) {
120
+ try {
121
+ await fs.mkdir(DATA_DIR, { recursive: true });
122
+ await fs.appendFile(MESSAGES_FILE, JSON.stringify(record) + '\n', 'utf-8');
123
+ }
124
+ catch (err) {
125
+ console.error('[Chat] Failed to append audit record:', err);
126
+ }
127
+ }
128
+ async persistMessage(message) {
129
+ try {
130
+ this.writeMessageToDb(message);
131
+ await this.appendAuditRecord(message);
132
+ }
133
+ catch (err) {
134
+ console.error('[Chat] Failed to persist message:', err);
135
+ }
136
+ }
137
+ createRoom(id, name) {
138
+ const room = {
139
+ id,
140
+ name,
141
+ participants: [],
142
+ createdAt: Date.now(),
143
+ };
144
+ this.rooms.set(id, room);
145
+ return room;
146
+ }
147
+ getRoom(id) {
148
+ return this.rooms.get(id);
149
+ }
150
+ listRooms() {
151
+ return Array.from(this.rooms.values());
152
+ }
153
+ // ── Noise Budget State ──
154
+ // Per-channel message counts in rolling windows
155
+ channelBudgetCounters = new Map();
156
+ // Duplicate suppression: hash → timestamp of last send
157
+ recentMessageHashes = new Map();
158
+ // Suppression stats tracking
159
+ suppressionStats = { total: 0, byCategory: new Map(), since: Date.now() };
160
+ // Digest batching: queued system reminders per channel
161
+ digestQueue = new Map();
162
+ digestTimers = new Map();
163
+ // Configurable limits
164
+ static CHANNEL_BUDGET_WINDOW_MS = 60 * 60 * 1000; // 1 hour
165
+ static CHANNEL_BUDGET_MAX = {
166
+ general: 30, // max 30 messages per hour in #general
167
+ shipping: 20,
168
+ reviews: 20,
169
+ blockers: 15,
170
+ _default: 40,
171
+ };
172
+ static DEDUP_WINDOW_MS = 5 * 60 * 1000; // 5 minute dedup window (non-system)
173
+ static SYSTEM_DEDUP_WINDOW_MS = 30 * 60 * 1000; // 30 minute dedup window (system messages)
174
+ static DIGEST_BATCH_DELAY_MS = 30 * 1000; // 30s digest batching window
175
+ static SYSTEM_REMINDER_PATTERNS = [
176
+ /^⚠️ Working contract warning/,
177
+ /^⚠️ \[Product Enforcement\]/,
178
+ /^🔄.*Auto-requeued/,
179
+ /^⚠️ SLA breach/,
180
+ /^⚠️ Ready-queue floor/,
181
+ /^🪞 Reflection nudge/,
182
+ /^\[SHIP\]/,
183
+ /^🚨 CRITICAL/,
184
+ /^✅ Auto-closed/,
185
+ ];
186
+ /**
187
+ * Check if message is within per-channel budget
188
+ */
189
+ checkChannelBudget(channel) {
190
+ const now = Date.now();
191
+ const counter = this.channelBudgetCounters.get(channel);
192
+ const maxBudget = ChatManager.CHANNEL_BUDGET_MAX[channel] ?? ChatManager.CHANNEL_BUDGET_MAX._default;
193
+ if (!counter || now - counter.windowStart > ChatManager.CHANNEL_BUDGET_WINDOW_MS) {
194
+ // New window
195
+ this.channelBudgetCounters.set(channel, { count: 1, windowStart: now });
196
+ return { allowed: true };
197
+ }
198
+ if (counter.count >= maxBudget) {
199
+ return { allowed: false, reason: `Channel #${channel} budget exceeded (${counter.count}/${maxBudget} per hour)` };
200
+ }
201
+ counter.count++;
202
+ return { allowed: true };
203
+ }
204
+ /**
205
+ * Check for duplicate messages within suppression window.
206
+ * System messages use a 30-minute window; others use 5 minutes.
207
+ * Callers can pass an explicit dedup_key in metadata to control dedup grouping.
208
+ */
209
+ checkDuplicate(from, channel, content, dedupKey) {
210
+ const now = Date.now();
211
+ const isSystem = from === 'system';
212
+ const windowMs = isSystem ? ChatManager.SYSTEM_DEDUP_WINDOW_MS : ChatManager.DEDUP_WINDOW_MS;
213
+ // Clean expired entries (use the longer window to avoid premature cleanup)
214
+ const maxWindow = ChatManager.SYSTEM_DEDUP_WINDOW_MS;
215
+ for (const [key, ts] of this.recentMessageHashes) {
216
+ if (now - ts > maxWindow)
217
+ this.recentMessageHashes.delete(key);
218
+ }
219
+ // Hash: explicit dedup_key if provided, otherwise from + channel + normalized content
220
+ let hash;
221
+ if (dedupKey) {
222
+ hash = `dedup:${channel}:${dedupKey}`;
223
+ }
224
+ else {
225
+ // Normalize: strip timestamps, task IDs, agent-specific names, counts
226
+ const normalized = content
227
+ .replace(/\d{10,}/g, '') // strip epoch timestamps
228
+ .replace(/task-\S+/g, 'TASK') // normalize task IDs
229
+ .replace(/@\w+/g, '@AGENT') // normalize @mentions
230
+ .replace(/\d+\/\d+/g, 'N/M') // normalize counts like "0/2"
231
+ .replace(/\(need \d+ more\)/g, '') // normalize "need N more"
232
+ .trim().slice(0, 200);
233
+ hash = `${from}:${channel}:${normalized}`;
234
+ }
235
+ const lastSent = this.recentMessageHashes.get(hash);
236
+ if (lastSent && (now - lastSent) < windowMs) {
237
+ // Track suppression stats
238
+ this.suppressionStats.total++;
239
+ const category = isSystem ? 'system' : from;
240
+ this.suppressionStats.byCategory.set(category, (this.suppressionStats.byCategory.get(category) || 0) + 1);
241
+ return true; // duplicate
242
+ }
243
+ this.recentMessageHashes.set(hash, now);
244
+ return false;
245
+ }
246
+ /**
247
+ * Get suppression statistics
248
+ */
249
+ getSuppressionStats() {
250
+ return {
251
+ total: this.suppressionStats.total,
252
+ byCategory: Object.fromEntries(this.suppressionStats.byCategory),
253
+ since: this.suppressionStats.since,
254
+ activeHashes: this.recentMessageHashes.size,
255
+ };
256
+ }
257
+ /**
258
+ * Check if message is a system reminder eligible for digest batching
259
+ */
260
+ isSystemReminder(content) {
261
+ return ChatManager.SYSTEM_REMINDER_PATTERNS.some(p => p.test(content));
262
+ }
263
+ /**
264
+ * Queue a system reminder for digest batching
265
+ * Returns true if queued (caller should skip sending), false if digest should flush now
266
+ */
267
+ queueForDigest(channel, from, content) {
268
+ const queue = this.digestQueue.get(channel) || [];
269
+ queue.push({ content, from, queuedAt: Date.now() });
270
+ this.digestQueue.set(channel, queue);
271
+ // If timer already running, just add to queue
272
+ if (this.digestTimers.has(channel))
273
+ return true;
274
+ // Start digest timer
275
+ const timer = setTimeout(() => {
276
+ this.flushDigest(channel);
277
+ this.digestTimers.delete(channel);
278
+ }, ChatManager.DIGEST_BATCH_DELAY_MS);
279
+ timer.unref();
280
+ this.digestTimers.set(channel, timer);
281
+ return true;
282
+ }
283
+ /**
284
+ * Flush queued digest messages into a single batched message
285
+ */
286
+ flushDigest(channel) {
287
+ const queue = this.digestQueue.get(channel);
288
+ if (!queue || queue.length === 0)
289
+ return;
290
+ this.digestQueue.delete(channel);
291
+ if (queue.length === 1) {
292
+ // Single message — send as-is
293
+ void this.sendMessage({ from: queue[0].from, channel, content: queue[0].content });
294
+ return;
295
+ }
296
+ // Batch multiple reminders into a single digest
297
+ const summary = `📋 **System digest** (${queue.length} reminders):\n` +
298
+ queue.map((q, i) => `${i + 1}. ${q.content.split('\n')[0].slice(0, 120)}`).join('\n');
299
+ void this.sendMessage({
300
+ from: 'system',
301
+ channel,
302
+ content: summary,
303
+ metadata: { digest: true, batchedCount: queue.length },
304
+ });
305
+ }
306
+ async sendMessage(message) {
307
+ const channel = message.channel || 'general';
308
+ // ── Noise Budget Checks ──
309
+ // Skip budget checks for direct messages (has `to` field) and metadata.bypass_budget
310
+ const bypassBudget = message.metadata?.bypass_budget === true || message.to;
311
+ if (!bypassBudget) {
312
+ // 1. Duplicate suppression (supports explicit dedup_key from metadata)
313
+ const dedupKey = message.metadata?.dedup_key;
314
+ if (this.checkDuplicate(message.from, channel, message.content, dedupKey)) {
315
+ console.log(`[Chat/NoiseBudget] Suppressed duplicate from ${message.from} in #${channel}`);
316
+ // Return a synthetic message so callers don't break
317
+ return {
318
+ ...message,
319
+ id: `msg-${Date.now()}-suppressed`,
320
+ timestamp: Date.now(),
321
+ channel,
322
+ reactions: {},
323
+ };
324
+ }
325
+ // 2. System reminder digest batching
326
+ if (this.isSystemReminder(message.content)) {
327
+ if (this.queueForDigest(channel, message.from, message.content)) {
328
+ console.log(`[Chat/NoiseBudget] Queued system reminder for digest in #${channel}`);
329
+ return {
330
+ ...message,
331
+ id: `msg-${Date.now()}-queued`,
332
+ timestamp: Date.now(),
333
+ channel,
334
+ reactions: {},
335
+ };
336
+ }
337
+ }
338
+ // 3. Per-channel budget — DISABLED
339
+ // Was silently dropping messages after 30/hr with a fake success response.
340
+ // Dedup + watchdog are sufficient noise controls.
341
+ // const budget = this.checkChannelBudget(channel)
342
+ // if (!budget.allowed) { ... }
343
+ }
344
+ // ── Persistent suppression ledger (dedup_key) ──
345
+ // For system/automated messages, compute a dedup_key and check the persistent ledger
346
+ const msgMeta = (message.metadata || {});
347
+ const category = typeof msgMeta.category === 'string' ? msgMeta.category : 'general';
348
+ const isSystemSource = message.from === 'system'
349
+ || typeof msgMeta.category === 'string'
350
+ || msgMeta.digest === true;
351
+ let dedupKey;
352
+ if (isSystemSource && !bypassBudget) {
353
+ const check = suppressionLedger.check({
354
+ category,
355
+ channel,
356
+ from: message.from,
357
+ content: message.content,
358
+ });
359
+ dedupKey = check.dedup_key;
360
+ if (check.isDuplicate) {
361
+ console.log(`[Chat/SuppressionLedger] Suppressed duplicate (key=${dedupKey}) from ${message.from} in #${channel}`);
362
+ return {
363
+ ...message,
364
+ id: `msg-${Date.now()}-ledger-suppressed`,
365
+ timestamp: Date.now(),
366
+ channel,
367
+ reactions: {},
368
+ metadata: { ...msgMeta, dedup_key: dedupKey, suppressed: true },
369
+ };
370
+ }
371
+ }
372
+ const fullMessage = {
373
+ ...message,
374
+ id: `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
375
+ timestamp: Date.now(),
376
+ channel,
377
+ reactions: message.reactions || {},
378
+ threadId: message.threadId,
379
+ metadata: dedupKey ? { ...msgMeta, dedup_key: dedupKey } : message.metadata,
380
+ };
381
+ // Persist to SQLite + JSONL audit
382
+ await this.persistMessage(fullMessage);
383
+ // Notify local subscribers
384
+ this.notifySubscribers(fullMessage);
385
+ // Emit event to event bus
386
+ eventBus.emitMessagePosted(fullMessage);
387
+ // Route to agent inboxes (auto-routing)
388
+ this.routeToInboxes(fullMessage);
389
+ // TODO: Send via OpenClaw when connected
390
+ return fullMessage;
391
+ }
392
+ /**
393
+ * Route message to agent inboxes
394
+ * This is called automatically when a message is posted
395
+ */
396
+ routeToInboxes(message) {
397
+ // Import here to avoid circular dependency at module level
398
+ import('./inbox.js')
399
+ .then(({ inboxManager }) => {
400
+ const agents = this.getKnownAgents();
401
+ inboxManager.routeMessage(message, agents);
402
+ })
403
+ .catch(err => {
404
+ console.error('[Chat] Failed to route message to inboxes:', err);
405
+ });
406
+ }
407
+ /**
408
+ * Get list of all known agents from SQLite.
409
+ */
410
+ getKnownAgents() {
411
+ const db = getDb();
412
+ const rows = db.prepare(`
413
+ SELECT DISTINCT "from" as agent FROM chat_messages
414
+ UNION
415
+ SELECT DISTINCT "to" as agent FROM chat_messages WHERE "to" IS NOT NULL
416
+ `).all();
417
+ return rows.map(r => r.agent).filter((v) => Boolean(v));
418
+ }
419
+ handleIncomingMessage(message) {
420
+ // Persist to DB (INSERT OR REPLACE handles dedup)
421
+ this.writeMessageToDb(message);
422
+ this.notifySubscribers(message);
423
+ }
424
+ hydrateRows(rows) {
425
+ return rows.map((row) => ({
426
+ id: row.id,
427
+ from: row.from,
428
+ to: row.to ?? undefined,
429
+ content: row.content,
430
+ timestamp: row.timestamp,
431
+ channel: row.channel || 'general',
432
+ reactions: safeJsonParse(row.reactions) || {},
433
+ threadId: row.thread_id ?? undefined,
434
+ metadata: safeJsonParse(row.metadata),
435
+ }));
436
+ }
437
+ getMessages(options) {
438
+ const db = getDb();
439
+ const conditions = [];
440
+ const params = [];
441
+ if (options?.from) {
442
+ conditions.push('"from" = ?');
443
+ params.push(options.from);
444
+ }
445
+ if (options?.excludeFrom) {
446
+ conditions.push('"from" != ?');
447
+ params.push(options.excludeFrom);
448
+ }
449
+ if (options?.to) {
450
+ conditions.push('"to" = ?');
451
+ params.push(options.to);
452
+ }
453
+ if (options?.channel) {
454
+ conditions.push('channel = ?');
455
+ params.push(options.channel);
456
+ }
457
+ if (options?.since) {
458
+ conditions.push('timestamp >= ?');
459
+ params.push(options.since);
460
+ }
461
+ if (options?.before) {
462
+ conditions.push('timestamp < ?');
463
+ params.push(options.before);
464
+ }
465
+ if (options?.after) {
466
+ conditions.push('timestamp > ?');
467
+ params.push(options.after);
468
+ }
469
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
470
+ const limit = options?.limit !== undefined ? options.limit : 20;
471
+ // Fetch newest-first for efficiency, then return ascending.
472
+ const sql = limit > 0
473
+ ? `SELECT * FROM (SELECT * FROM chat_messages ${where} ORDER BY timestamp DESC LIMIT ?) ORDER BY timestamp ASC`
474
+ : `SELECT * FROM chat_messages ${where} ORDER BY timestamp ASC`;
475
+ if (limit > 0)
476
+ params.push(limit);
477
+ const rows = db.prepare(sql).all(...params);
478
+ const messages = rows.map(rowToMessage);
479
+ return this.addReplyCounts(messages);
480
+ }
481
+ addReplyCounts(messages) {
482
+ if (messages.length === 0)
483
+ return messages;
484
+ const db = getDb();
485
+ const ids = messages.map(m => m.id);
486
+ // Build `IN (?, ?, ...)` safely.
487
+ const placeholders = ids.map(() => '?').join(',');
488
+ const rows = db.prepare(`
489
+ SELECT thread_id as id, COUNT(*) as c
490
+ FROM chat_messages
491
+ WHERE thread_id IN (${placeholders})
492
+ GROUP BY thread_id
493
+ `).all(...ids);
494
+ const map = new Map(rows.map(r => [r.id, r.c]));
495
+ return messages.map(m => ({ ...m, replyCount: map.get(m.id) ?? 0 }));
496
+ }
497
+ getThread(messageId) {
498
+ const db = getDb();
499
+ const parentRow = db.prepare('SELECT * FROM chat_messages WHERE id = ?').get(messageId);
500
+ if (!parentRow)
501
+ return null;
502
+ const parent = rowToMessage(parentRow);
503
+ const replyRows = db.prepare('SELECT * FROM chat_messages WHERE thread_id = ? ORDER BY timestamp ASC').all(messageId);
504
+ const replies = replyRows.map(rowToMessage);
505
+ return this.addReplyCounts([parent, ...replies]);
506
+ }
507
+ subscribe(callback) {
508
+ this.subscribers.add(callback);
509
+ return () => this.subscribers.delete(callback);
510
+ }
511
+ notifySubscribers(message) {
512
+ this.subscribers.forEach(callback => {
513
+ try {
514
+ callback(message);
515
+ }
516
+ catch (err) {
517
+ console.error('[Chat] Subscriber error:', err);
518
+ }
519
+ });
520
+ }
521
+ getChannels() {
522
+ const db = getDb();
523
+ const rows = db.prepare(`
524
+ SELECT COALESCE(channel, 'general') as channel, COUNT(*) as count, MAX(timestamp) as lastActivity
525
+ FROM chat_messages
526
+ GROUP BY COALESCE(channel, 'general')
527
+ ORDER BY lastActivity DESC
528
+ `).all();
529
+ // Include default channels even if empty
530
+ const channelMap = new Map();
531
+ DEFAULT_CHAT_CHANNELS.forEach(ch => channelMap.set(ch, { count: 0, lastActivity: 0 }));
532
+ for (const row of rows) {
533
+ channelMap.set(row.channel, { count: row.count, lastActivity: row.lastActivity });
534
+ }
535
+ return Array.from(channelMap.entries())
536
+ .map(([channel, data]) => ({ channel, ...data }))
537
+ .sort((a, b) => b.lastActivity - a.lastActivity);
538
+ }
539
+ async addReaction(messageId, emoji, from) {
540
+ const db = getDb();
541
+ const row = db.prepare('SELECT * FROM chat_messages WHERE id = ?').get(messageId);
542
+ if (!row)
543
+ return null;
544
+ const message = rowToMessage(row);
545
+ // Initialize reactions if needed
546
+ if (!message.reactions)
547
+ message.reactions = {};
548
+ if (!message.reactions[emoji])
549
+ message.reactions[emoji] = [];
550
+ const agents = message.reactions[emoji];
551
+ const index = agents.indexOf(from);
552
+ if (index >= 0) {
553
+ agents.splice(index, 1);
554
+ if (agents.length === 0)
555
+ delete message.reactions[emoji];
556
+ }
557
+ else {
558
+ agents.push(from);
559
+ }
560
+ this.writeMessageToDb(message);
561
+ await this.appendAuditRecord(message);
562
+ this.notifySubscribers(message);
563
+ eventBus.emit({
564
+ id: `evt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
565
+ type: 'message_posted',
566
+ timestamp: Date.now(),
567
+ data: { ...message, reactionUpdate: true },
568
+ });
569
+ return message;
570
+ }
571
+ getReactions(messageId) {
572
+ const db = getDb();
573
+ const row = db.prepare('SELECT reactions FROM chat_messages WHERE id = ?').get(messageId);
574
+ if (!row)
575
+ return null;
576
+ return safeJsonParse(row.reactions) || {};
577
+ }
578
+ async editMessage(messageId, editor, content) {
579
+ const trimmed = content.trim();
580
+ if (!trimmed)
581
+ return { ok: false, error: 'invalid_content' };
582
+ const db = getDb();
583
+ const row = db.prepare('SELECT * FROM chat_messages WHERE id = ?').get(messageId);
584
+ if (!row) {
585
+ return { ok: false, error: 'not_found' };
586
+ }
587
+ const message = rowToMessage(row);
588
+ if (message.from !== editor) {
589
+ return { ok: false, error: 'forbidden' };
590
+ }
591
+ message.content = trimmed;
592
+ message.metadata = {
593
+ ...(message.metadata || {}),
594
+ editedAt: Date.now(),
595
+ editedBy: editor,
596
+ };
597
+ this.writeMessageToDb(message);
598
+ await this.appendAuditRecord(message);
599
+ // No in-memory cache to update.
600
+ this.notifySubscribers(message);
601
+ eventBus.emit({
602
+ id: `evt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
603
+ type: 'message_posted',
604
+ timestamp: Date.now(),
605
+ data: { ...message, editUpdate: true },
606
+ });
607
+ return { ok: true, message };
608
+ }
609
+ async deleteMessage(messageId, actor) {
610
+ const db = getDb();
611
+ const row = db.prepare('SELECT * FROM chat_messages WHERE id = ?').get(messageId);
612
+ if (!row) {
613
+ return { ok: false, error: 'not_found' };
614
+ }
615
+ const message = rowToMessage(row);
616
+ if (message.from !== actor) {
617
+ return { ok: false, error: 'forbidden' };
618
+ }
619
+ this.deleteMessageFromDb(messageId);
620
+ await this.appendAuditRecord({
621
+ id: messageId,
622
+ from: actor,
623
+ content: '',
624
+ timestamp: Date.now(),
625
+ channel: message.channel || 'general',
626
+ metadata: {
627
+ deleteUpdate: true,
628
+ deletedBy: actor,
629
+ },
630
+ });
631
+ eventBus.emit({
632
+ id: `evt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
633
+ type: 'message_posted',
634
+ timestamp: Date.now(),
635
+ data: { id: messageId, deleteUpdate: true },
636
+ });
637
+ return { ok: true };
638
+ }
639
+ search(query, options) {
640
+ const db = getDb();
641
+ const likePattern = `%${query}%`;
642
+ const limit = options?.limit ?? 50;
643
+ const rows = db.prepare(`
644
+ SELECT * FROM chat_messages
645
+ WHERE content LIKE ? COLLATE NOCASE
646
+ OR "from" LIKE ? COLLATE NOCASE
647
+ OR channel LIKE ? COLLATE NOCASE
648
+ ORDER BY timestamp DESC
649
+ LIMIT ?
650
+ `).all(likePattern, likePattern, likePattern, limit);
651
+ // Return in chronological order
652
+ return rows.map(rowToMessage).reverse();
653
+ }
654
+ getStats() {
655
+ const db = getDb();
656
+ const totalRow = db.prepare('SELECT COUNT(*) as count FROM chat_messages').get();
657
+ return {
658
+ totalMessages: totalRow?.count ?? 0,
659
+ rooms: this.rooms.size,
660
+ subscribers: this.subscribers.size,
661
+ initialized: this.initialized,
662
+ };
663
+ }
664
+ }
665
+ export const chatManager = new ChatManager();
666
+ //# sourceMappingURL=chat.js.map