@fluxra-ai/fluxra-cli 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 (265) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +274 -0
  3. package/bin/fluxra +6 -0
  4. package/dist/cli/command-context.d.ts +17 -0
  5. package/dist/cli/command-context.d.ts.map +1 -0
  6. package/dist/cli/command-context.js +26 -0
  7. package/dist/cli/command-context.js.map +1 -0
  8. package/dist/cli/commands/auth/index.d.ts +3 -0
  9. package/dist/cli/commands/auth/index.d.ts.map +1 -0
  10. package/dist/cli/commands/auth/index.js +165 -0
  11. package/dist/cli/commands/auth/index.js.map +1 -0
  12. package/dist/cli/commands/chat/index.d.ts +3 -0
  13. package/dist/cli/commands/chat/index.d.ts.map +1 -0
  14. package/dist/cli/commands/chat/index.js +1201 -0
  15. package/dist/cli/commands/chat/index.js.map +1 -0
  16. package/dist/cli/commands/config/index.d.ts +3 -0
  17. package/dist/cli/commands/config/index.d.ts.map +1 -0
  18. package/dist/cli/commands/config/index.js +66 -0
  19. package/dist/cli/commands/config/index.js.map +1 -0
  20. package/dist/cli/commands/help.d.ts +7 -0
  21. package/dist/cli/commands/help.d.ts.map +1 -0
  22. package/dist/cli/commands/help.js +106 -0
  23. package/dist/cli/commands/help.js.map +1 -0
  24. package/dist/cli/commands/local/doctor.d.ts +26 -0
  25. package/dist/cli/commands/local/doctor.d.ts.map +1 -0
  26. package/dist/cli/commands/local/doctor.js +265 -0
  27. package/dist/cli/commands/local/doctor.js.map +1 -0
  28. package/dist/cli/commands/local/export.d.ts +41 -0
  29. package/dist/cli/commands/local/export.d.ts.map +1 -0
  30. package/dist/cli/commands/local/export.js +83 -0
  31. package/dist/cli/commands/local/export.js.map +1 -0
  32. package/dist/cli/commands/local/index.d.ts +6 -0
  33. package/dist/cli/commands/local/index.d.ts.map +1 -0
  34. package/dist/cli/commands/local/index.js +116 -0
  35. package/dist/cli/commands/local/index.js.map +1 -0
  36. package/dist/cli/commands/local/inspect.d.ts +42 -0
  37. package/dist/cli/commands/local/inspect.d.ts.map +1 -0
  38. package/dist/cli/commands/local/inspect.js +125 -0
  39. package/dist/cli/commands/local/inspect.js.map +1 -0
  40. package/dist/cli/commands/mcp.d.ts +8 -0
  41. package/dist/cli/commands/mcp.d.ts.map +1 -0
  42. package/dist/cli/commands/mcp.js +253 -0
  43. package/dist/cli/commands/mcp.js.map +1 -0
  44. package/dist/cli/commands/profile/index.d.ts +3 -0
  45. package/dist/cli/commands/profile/index.d.ts.map +1 -0
  46. package/dist/cli/commands/profile/index.js +114 -0
  47. package/dist/cli/commands/profile/index.js.map +1 -0
  48. package/dist/cli/commands/schema.d.ts +7 -0
  49. package/dist/cli/commands/schema.d.ts.map +1 -0
  50. package/dist/cli/commands/schema.js +33 -0
  51. package/dist/cli/commands/schema.js.map +1 -0
  52. package/dist/cli/errors.d.ts +16 -0
  53. package/dist/cli/errors.d.ts.map +1 -0
  54. package/dist/cli/errors.js +15 -0
  55. package/dist/cli/errors.js.map +1 -0
  56. package/dist/cli/fluxra.d.ts +9 -0
  57. package/dist/cli/fluxra.d.ts.map +1 -0
  58. package/dist/cli/fluxra.js +55 -0
  59. package/dist/cli/fluxra.js.map +1 -0
  60. package/dist/cli/helpers.d.ts +13 -0
  61. package/dist/cli/helpers.d.ts.map +1 -0
  62. package/dist/cli/helpers.js +32 -0
  63. package/dist/cli/helpers.js.map +1 -0
  64. package/dist/cli/output.d.ts +14 -0
  65. package/dist/cli/output.d.ts.map +1 -0
  66. package/dist/cli/output.js +55 -0
  67. package/dist/cli/output.js.map +1 -0
  68. package/dist/cli/version.d.ts +6 -0
  69. package/dist/cli/version.d.ts.map +1 -0
  70. package/dist/cli/version.js +8 -0
  71. package/dist/cli/version.js.map +1 -0
  72. package/dist/core/auth/auth-service.d.ts +35 -0
  73. package/dist/core/auth/auth-service.d.ts.map +1 -0
  74. package/dist/core/auth/auth-service.js +116 -0
  75. package/dist/core/auth/auth-service.js.map +1 -0
  76. package/dist/core/config/global-config.d.ts +38 -0
  77. package/dist/core/config/global-config.d.ts.map +1 -0
  78. package/dist/core/config/global-config.js +75 -0
  79. package/dist/core/config/global-config.js.map +1 -0
  80. package/dist/core/errors/error-model.d.ts +48 -0
  81. package/dist/core/errors/error-model.d.ts.map +1 -0
  82. package/dist/core/errors/error-model.js +152 -0
  83. package/dist/core/errors/error-model.js.map +1 -0
  84. package/dist/core/filesystem/paths.d.ts +45 -0
  85. package/dist/core/filesystem/paths.d.ts.map +1 -0
  86. package/dist/core/filesystem/paths.js +77 -0
  87. package/dist/core/filesystem/paths.js.map +1 -0
  88. package/dist/core/http/auth-api.d.ts +71 -0
  89. package/dist/core/http/auth-api.d.ts.map +1 -0
  90. package/dist/core/http/auth-api.js +91 -0
  91. package/dist/core/http/auth-api.js.map +1 -0
  92. package/dist/core/http/block-api.d.ts +37 -0
  93. package/dist/core/http/block-api.d.ts.map +1 -0
  94. package/dist/core/http/block-api.js +36 -0
  95. package/dist/core/http/block-api.js.map +1 -0
  96. package/dist/core/http/chat-api.d.ts +41 -0
  97. package/dist/core/http/chat-api.d.ts.map +1 -0
  98. package/dist/core/http/chat-api.js +88 -0
  99. package/dist/core/http/chat-api.js.map +1 -0
  100. package/dist/core/http/conversation-management-api.d.ts +65 -0
  101. package/dist/core/http/conversation-management-api.d.ts.map +1 -0
  102. package/dist/core/http/conversation-management-api.js +59 -0
  103. package/dist/core/http/conversation-management-api.js.map +1 -0
  104. package/dist/core/http/directory-api.d.ts +32 -0
  105. package/dist/core/http/directory-api.d.ts.map +1 -0
  106. package/dist/core/http/directory-api.js +36 -0
  107. package/dist/core/http/directory-api.js.map +1 -0
  108. package/dist/core/http/directory-profile-api.d.ts +32 -0
  109. package/dist/core/http/directory-profile-api.d.ts.map +1 -0
  110. package/dist/core/http/directory-profile-api.js +39 -0
  111. package/dist/core/http/directory-profile-api.js.map +1 -0
  112. package/dist/core/http/http-client.d.ts +41 -0
  113. package/dist/core/http/http-client.d.ts.map +1 -0
  114. package/dist/core/http/http-client.js +127 -0
  115. package/dist/core/http/http-client.js.map +1 -0
  116. package/dist/core/http/message-api.d.ts +55 -0
  117. package/dist/core/http/message-api.d.ts.map +1 -0
  118. package/dist/core/http/message-api.js +64 -0
  119. package/dist/core/http/message-api.js.map +1 -0
  120. package/dist/core/http/rate-limit.d.ts +22 -0
  121. package/dist/core/http/rate-limit.d.ts.map +1 -0
  122. package/dist/core/http/rate-limit.js +66 -0
  123. package/dist/core/http/rate-limit.js.map +1 -0
  124. package/dist/core/http/token-lifecycle.d.ts +18 -0
  125. package/dist/core/http/token-lifecycle.d.ts.map +1 -0
  126. package/dist/core/http/token-lifecycle.js +73 -0
  127. package/dist/core/http/token-lifecycle.js.map +1 -0
  128. package/dist/core/locking/profile-lock.d.ts +32 -0
  129. package/dist/core/locking/profile-lock.d.ts.map +1 -0
  130. package/dist/core/locking/profile-lock.js +104 -0
  131. package/dist/core/locking/profile-lock.js.map +1 -0
  132. package/dist/core/profiles/profile-service.d.ts +35 -0
  133. package/dist/core/profiles/profile-service.d.ts.map +1 -0
  134. package/dist/core/profiles/profile-service.js +119 -0
  135. package/dist/core/profiles/profile-service.js.map +1 -0
  136. package/dist/core/profiles/profile-types.d.ts +28 -0
  137. package/dist/core/profiles/profile-types.d.ts.map +1 -0
  138. package/dist/core/profiles/profile-types.js +13 -0
  139. package/dist/core/profiles/profile-types.js.map +1 -0
  140. package/dist/core/secrets/secrets-service.d.ts +25 -0
  141. package/dist/core/secrets/secrets-service.d.ts.map +1 -0
  142. package/dist/core/secrets/secrets-service.js +67 -0
  143. package/dist/core/secrets/secrets-service.js.map +1 -0
  144. package/dist/core/secrets/secrets-types.d.ts +29 -0
  145. package/dist/core/secrets/secrets-types.d.ts.map +1 -0
  146. package/dist/core/secrets/secrets-types.js +33 -0
  147. package/dist/core/secrets/secrets-types.js.map +1 -0
  148. package/dist/core/sqlite/chat-schema.d.ts +14 -0
  149. package/dist/core/sqlite/chat-schema.d.ts.map +1 -0
  150. package/dist/core/sqlite/chat-schema.js +172 -0
  151. package/dist/core/sqlite/chat-schema.js.map +1 -0
  152. package/dist/core/sqlite/core-schema.d.ts +14 -0
  153. package/dist/core/sqlite/core-schema.d.ts.map +1 -0
  154. package/dist/core/sqlite/core-schema.js +54 -0
  155. package/dist/core/sqlite/core-schema.js.map +1 -0
  156. package/dist/core/sqlite/database.d.ts +40 -0
  157. package/dist/core/sqlite/database.d.ts.map +1 -0
  158. package/dist/core/sqlite/database.js +68 -0
  159. package/dist/core/sqlite/database.js.map +1 -0
  160. package/dist/core/sqlite/migrations.d.ts +22 -0
  161. package/dist/core/sqlite/migrations.d.ts.map +1 -0
  162. package/dist/core/sqlite/migrations.js +64 -0
  163. package/dist/core/sqlite/migrations.js.map +1 -0
  164. package/dist/modules/chat/inbox/conversation-service.d.ts +35 -0
  165. package/dist/modules/chat/inbox/conversation-service.d.ts.map +1 -0
  166. package/dist/modules/chat/inbox/conversation-service.js +54 -0
  167. package/dist/modules/chat/inbox/conversation-service.js.map +1 -0
  168. package/dist/modules/chat/inbox/history-service.d.ts +25 -0
  169. package/dist/modules/chat/inbox/history-service.d.ts.map +1 -0
  170. package/dist/modules/chat/inbox/history-service.js +57 -0
  171. package/dist/modules/chat/inbox/history-service.js.map +1 -0
  172. package/dist/modules/chat/inbox/index.d.ts +9 -0
  173. package/dist/modules/chat/inbox/index.d.ts.map +1 -0
  174. package/dist/modules/chat/inbox/index.js +9 -0
  175. package/dist/modules/chat/inbox/index.js.map +1 -0
  176. package/dist/modules/chat/inbox/read-service.d.ts +36 -0
  177. package/dist/modules/chat/inbox/read-service.d.ts.map +1 -0
  178. package/dist/modules/chat/inbox/read-service.js +91 -0
  179. package/dist/modules/chat/inbox/read-service.js.map +1 -0
  180. package/dist/modules/chat/inbox/search-service.d.ts +20 -0
  181. package/dist/modules/chat/inbox/search-service.d.ts.map +1 -0
  182. package/dist/modules/chat/inbox/search-service.js +23 -0
  183. package/dist/modules/chat/inbox/search-service.js.map +1 -0
  184. package/dist/modules/chat/inbox/unread-service.d.ts +38 -0
  185. package/dist/modules/chat/inbox/unread-service.d.ts.map +1 -0
  186. package/dist/modules/chat/inbox/unread-service.js +65 -0
  187. package/dist/modules/chat/inbox/unread-service.js.map +1 -0
  188. package/dist/modules/chat/render/message-render.d.ts +35 -0
  189. package/dist/modules/chat/render/message-render.d.ts.map +1 -0
  190. package/dist/modules/chat/render/message-render.js +129 -0
  191. package/dist/modules/chat/render/message-render.js.map +1 -0
  192. package/dist/modules/chat/send/conversation-service.d.ts +53 -0
  193. package/dist/modules/chat/send/conversation-service.d.ts.map +1 -0
  194. package/dist/modules/chat/send/conversation-service.js +110 -0
  195. package/dist/modules/chat/send/conversation-service.js.map +1 -0
  196. package/dist/modules/chat/send/directory-cache-service.d.ts +37 -0
  197. package/dist/modules/chat/send/directory-cache-service.d.ts.map +1 -0
  198. package/dist/modules/chat/send/directory-cache-service.js +49 -0
  199. package/dist/modules/chat/send/directory-cache-service.js.map +1 -0
  200. package/dist/modules/chat/send/send-service.d.ts +36 -0
  201. package/dist/modules/chat/send/send-service.d.ts.map +1 -0
  202. package/dist/modules/chat/send/send-service.js +113 -0
  203. package/dist/modules/chat/send/send-service.js.map +1 -0
  204. package/dist/modules/chat/store/conversation-repo.d.ts +53 -0
  205. package/dist/modules/chat/store/conversation-repo.d.ts.map +1 -0
  206. package/dist/modules/chat/store/conversation-repo.js +75 -0
  207. package/dist/modules/chat/store/conversation-repo.js.map +1 -0
  208. package/dist/modules/chat/store/directory-cache-repo.d.ts +41 -0
  209. package/dist/modules/chat/store/directory-cache-repo.d.ts.map +1 -0
  210. package/dist/modules/chat/store/directory-cache-repo.js +64 -0
  211. package/dist/modules/chat/store/directory-cache-repo.js.map +1 -0
  212. package/dist/modules/chat/store/job-repo.d.ts +72 -0
  213. package/dist/modules/chat/store/job-repo.d.ts.map +1 -0
  214. package/dist/modules/chat/store/job-repo.js +140 -0
  215. package/dist/modules/chat/store/job-repo.js.map +1 -0
  216. package/dist/modules/chat/store/message-repo.d.ts +98 -0
  217. package/dist/modules/chat/store/message-repo.d.ts.map +1 -0
  218. package/dist/modules/chat/store/message-repo.js +231 -0
  219. package/dist/modules/chat/store/message-repo.js.map +1 -0
  220. package/dist/modules/chat/store/outbox-repo.d.ts +73 -0
  221. package/dist/modules/chat/store/outbox-repo.d.ts.map +1 -0
  222. package/dist/modules/chat/store/outbox-repo.js +112 -0
  223. package/dist/modules/chat/store/outbox-repo.js.map +1 -0
  224. package/dist/modules/chat/store/read-state-repo.d.ts +83 -0
  225. package/dist/modules/chat/store/read-state-repo.d.ts.map +1 -0
  226. package/dist/modules/chat/store/read-state-repo.js +210 -0
  227. package/dist/modules/chat/store/read-state-repo.js.map +1 -0
  228. package/dist/modules/chat/store/sync-state-repo.d.ts +45 -0
  229. package/dist/modules/chat/store/sync-state-repo.d.ts.map +1 -0
  230. package/dist/modules/chat/store/sync-state-repo.js +67 -0
  231. package/dist/modules/chat/store/sync-state-repo.js.map +1 -0
  232. package/dist/modules/chat/sync/backfill.d.ts +13 -0
  233. package/dist/modules/chat/sync/backfill.d.ts.map +1 -0
  234. package/dist/modules/chat/sync/backfill.js +37 -0
  235. package/dist/modules/chat/sync/backfill.js.map +1 -0
  236. package/dist/modules/chat/sync/cron-manager.d.ts +50 -0
  237. package/dist/modules/chat/sync/cron-manager.d.ts.map +1 -0
  238. package/dist/modules/chat/sync/cron-manager.js +164 -0
  239. package/dist/modules/chat/sync/cron-manager.js.map +1 -0
  240. package/dist/modules/chat/sync/index.d.ts +8 -0
  241. package/dist/modules/chat/sync/index.d.ts.map +1 -0
  242. package/dist/modules/chat/sync/index.js +7 -0
  243. package/dist/modules/chat/sync/index.js.map +1 -0
  244. package/dist/modules/chat/sync/job-logger.d.ts +44 -0
  245. package/dist/modules/chat/sync/job-logger.d.ts.map +1 -0
  246. package/dist/modules/chat/sync/job-logger.js +139 -0
  247. package/dist/modules/chat/sync/job-logger.js.map +1 -0
  248. package/dist/modules/chat/sync/sync-service.d.ts +14 -0
  249. package/dist/modules/chat/sync/sync-service.d.ts.map +1 -0
  250. package/dist/modules/chat/sync/sync-service.js +174 -0
  251. package/dist/modules/chat/sync/sync-service.js.map +1 -0
  252. package/dist/modules/chat/sync/sync-status.d.ts +14 -0
  253. package/dist/modules/chat/sync/sync-status.d.ts.map +1 -0
  254. package/dist/modules/chat/sync/sync-status.js +77 -0
  255. package/dist/modules/chat/sync/sync-status.js.map +1 -0
  256. package/dist/modules/chat/sync/sync-types.d.ts +80 -0
  257. package/dist/modules/chat/sync/sync-types.d.ts.map +1 -0
  258. package/dist/modules/chat/sync/sync-types.js +5 -0
  259. package/dist/modules/chat/sync/sync-types.js.map +1 -0
  260. package/dist/modules/chat/sync/watch-mode.d.ts +45 -0
  261. package/dist/modules/chat/sync/watch-mode.d.ts.map +1 -0
  262. package/dist/modules/chat/sync/watch-mode.js +161 -0
  263. package/dist/modules/chat/sync/watch-mode.js.map +1 -0
  264. package/package.json +67 -0
  265. package/tool-schema.json +1039 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Outbox repository - manage failed/pending message sends
3
+ */
4
+ /**
5
+ * Enqueue a message to outbox
6
+ */
7
+ export function enqueueMessage(db, message) {
8
+ db.prepare(`
9
+ INSERT INTO outbox (
10
+ id, conversation_id, recipient_agent_id, content, type, in_reply_to, mentions,
11
+ status, retry_count, created_at
12
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', 0, datetime('now'))
13
+ `).run(message.id, message.conversationId || null, message.recipientAgentId || null, message.content, message.type || 'text', message.inReplyTo || null, message.mentions ? JSON.stringify(message.mentions) : null);
14
+ }
15
+ /**
16
+ * Get pending messages from outbox
17
+ */
18
+ export function getPendingMessages(db) {
19
+ return db.prepare(`
20
+ SELECT * FROM outbox WHERE status = 'pending' ORDER BY created_at ASC
21
+ `).all();
22
+ }
23
+ /**
24
+ * Get all outbox entries
25
+ */
26
+ export function getAllOutboxEntries(db) {
27
+ return db.prepare(`
28
+ SELECT * FROM outbox ORDER BY created_at DESC
29
+ `).all();
30
+ }
31
+ /**
32
+ * Mark an outbox entry as sent
33
+ */
34
+ export function markMessageSent(db, outboxId, remoteMessageId) {
35
+ db.prepare(`
36
+ UPDATE outbox SET
37
+ status = 'sent',
38
+ remote_message_id = ?,
39
+ sent_at = datetime('now'),
40
+ last_error = NULL
41
+ WHERE id = ?
42
+ `).run(remoteMessageId, outboxId);
43
+ }
44
+ /**
45
+ * Mark an outbox entry as failed
46
+ */
47
+ export function markMessageFailed(db, outboxId, error) {
48
+ db.prepare(`
49
+ UPDATE outbox SET
50
+ status = 'failed',
51
+ retry_count = retry_count + 1,
52
+ last_error = ?
53
+ WHERE id = ?
54
+ `).run(error, outboxId);
55
+ }
56
+ /**
57
+ * Get retryable messages (retry_count < maxRetries)
58
+ */
59
+ export function getRetryableMessages(db, maxRetries) {
60
+ return db.prepare(`
61
+ SELECT * FROM outbox
62
+ WHERE status IN ('pending', 'failed') AND retry_count < ?
63
+ ORDER BY created_at ASC
64
+ `).all(maxRetries);
65
+ }
66
+ /**
67
+ * Reset a failed message to pending for retry
68
+ */
69
+ export function resetMessageForRetry(db, outboxId) {
70
+ db.prepare(`
71
+ UPDATE outbox SET
72
+ status = 'pending',
73
+ last_error = NULL
74
+ WHERE id = ?
75
+ `).run(outboxId);
76
+ }
77
+ /**
78
+ * Delete an outbox entry
79
+ */
80
+ export function deleteOutboxEntry(db, outboxId) {
81
+ db.prepare('DELETE FROM outbox WHERE id = ?').run(outboxId);
82
+ }
83
+ /**
84
+ * Get outbox statistics
85
+ */
86
+ export function getOutboxStats(db) {
87
+ const row = db.prepare(`
88
+ SELECT
89
+ SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
90
+ SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed,
91
+ SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END) as sent,
92
+ SUM(retry_count) as totalRetries
93
+ FROM outbox
94
+ `).get();
95
+ return {
96
+ pending: row.pending || 0,
97
+ failed: row.failed || 0,
98
+ sent: row.sent || 0,
99
+ totalRetries: row.totalRetries || 0,
100
+ };
101
+ }
102
+ /**
103
+ * Clean up old sent entries (older than specified hours)
104
+ */
105
+ export function cleanupOldOutboxEntries(db, olderThanHours = 24) {
106
+ const result = db.prepare(`
107
+ DELETE FROM outbox
108
+ WHERE status = 'sent' AND sent_at < datetime('now', ?)
109
+ `).run(`-${olderThanHours} hours`);
110
+ return result.changes;
111
+ }
112
+ //# sourceMappingURL=outbox-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-repo.js","sourceRoot":"","sources":["../../../../src/modules/chat/store/outbox-repo.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoBH;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,EAAqB,EACrB,OAQC;IAED,EAAE,CAAC,OAAO,CAAC;;;;;GAKV,CAAC,CAAC,GAAG,CACJ,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,cAAc,IAAI,IAAI,EAC9B,OAAO,CAAC,gBAAgB,IAAI,IAAI,EAChC,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,IAAI,IAAI,MAAM,EACtB,OAAO,CAAC,SAAS,IAAI,IAAI,EACzB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAC3D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAqB;IACtD,OAAO,EAAE,CAAC,OAAO,CAAC;;GAEjB,CAAC,CAAC,GAAG,EAAmB,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAqB;IACvD,OAAO,EAAE,CAAC,OAAO,CAAC;;GAEjB,CAAC,CAAC,GAAG,EAAmB,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,EAAqB,EACrB,QAAgB,EAChB,eAAuB;IAEvB,EAAE,CAAC,OAAO,CAAC;;;;;;;GAOV,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAqB,EACrB,QAAgB,EAChB,KAAa;IAEb,EAAE,CAAC,OAAO,CAAC;;;;;;GAMV,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,EAAqB,EACrB,UAAkB;IAElB,OAAO,EAAE,CAAC,OAAO,CAAC;;;;GAIjB,CAAC,CAAC,GAAG,CAAC,UAAU,CAAkB,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,EAAqB,EACrB,QAAgB;IAEhB,EAAE,CAAC,OAAO,CAAC;;;;;GAKV,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAqB,EAAE,QAAgB;IACvE,EAAE,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAqB;IAMlD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;GAOtB,CAAC,CAAC,GAAG,EAAyG,CAAC;IAEhH,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,CAAC;QACzB,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC;QACvB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;QACnB,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,CAAC;KACpC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,EAAqB,EACrB,iBAAyB,EAAE;IAE3B,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC;;;GAGzB,CAAC,CAAC,GAAG,CAAC,IAAI,cAAc,QAAQ,CAAC,CAAC;IAEnC,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Read state repository - managing read/unread tracking
3
+ */
4
+ import Database from 'better-sqlite3';
5
+ /**
6
+ * Get unread message count by conversation
7
+ */
8
+ export declare function getUnreadByConversation(db: Database.Database): Array<{
9
+ conversation_id: string;
10
+ unread_count: number;
11
+ last_message_at: string;
12
+ }>;
13
+ /**
14
+ * Mark all messages in a conversation as read
15
+ */
16
+ export declare function markConversationRead(db: Database.Database, conversationId: string): number;
17
+ /**
18
+ * Mark specific messages as read
19
+ */
20
+ export declare function markMessagesRead(db: Database.Database, messageIds: string[]): number;
21
+ /**
22
+ * Get unread summary for all conversations
23
+ */
24
+ export declare function getUnreadSummary(db: Database.Database): Array<{
25
+ conversation_id: string;
26
+ conversation_type: string;
27
+ conversation_name: string | null;
28
+ unread_count: number;
29
+ last_unread_at: string;
30
+ last_sender: string;
31
+ has_mention: boolean;
32
+ }>;
33
+ /**
34
+ * Get unread messages that mention the current agent
35
+ */
36
+ export declare function getUnreadMentions(db: Database.Database, options?: {
37
+ conversationId?: string;
38
+ limit?: number;
39
+ }): Array<{
40
+ message_id: string;
41
+ conversation_id: string;
42
+ sender_id: string;
43
+ content: string | null;
44
+ remote_created_at: string;
45
+ conversation_type: string;
46
+ conversation_name: string | null;
47
+ }>;
48
+ /**
49
+ * Get unread message count with mention filter
50
+ */
51
+ export declare function getUnreadCountByMention(db: Database.Database, conversationId?: string): number;
52
+ /**
53
+ * Get detailed unread statistics for a specific conversation
54
+ */
55
+ export declare function getConversationUnreadStats(db: Database.Database, conversationId: string): {
56
+ totalUnread: number;
57
+ mentionedUnread: number;
58
+ firstUnreadAt: string | null;
59
+ lastUnreadAt: string | null;
60
+ uniqueSenders: number;
61
+ } | null;
62
+ /**
63
+ * Get unread messages with surrounding history context
64
+ * Returns N messages before each unread message
65
+ */
66
+ export declare function getUnreadWithHistory(db: Database.Database, options?: {
67
+ conversationId?: string;
68
+ historyBefore?: number;
69
+ limit?: number;
70
+ }): Array<{
71
+ message_id: string;
72
+ conversation_id: string;
73
+ sender_id: string;
74
+ content: string | null;
75
+ type: string;
76
+ status: string;
77
+ remote_created_at: string;
78
+ is_read: number;
79
+ is_mentioned: number;
80
+ conversation_type: string;
81
+ conversation_name: string | null;
82
+ }>;
83
+ //# sourceMappingURL=read-state-repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-state-repo.d.ts","sourceRoot":"","sources":["../../../../src/modules/chat/store/read-state-repo.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GACpB,KAAK,CAAC;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC,CASnF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,cAAc,EAAE,MAAM,GACrB,MAAM,CAUR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,UAAU,EAAE,MAAM,EAAE,GACnB,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,CAAC,QAAQ,GACpB,KAAK,CAAC;IACP,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC,CA4BD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxD,KAAK,CAAC;IACP,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC,CA+BD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAiBR;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,cAAc,EAAE,MAAM,GACrB;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CA8BP;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,GAAE;IACP,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,GACL,KAAK,CAAC;IACP,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC,CAwGD"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Read state repository - managing read/unread tracking
3
+ */
4
+ /**
5
+ * Get unread message count by conversation
6
+ */
7
+ export function getUnreadByConversation(db) {
8
+ return db.prepare(`
9
+ SELECT m.conversation_id, COUNT(*) as unread_count, MAX(m.remote_created_at) as last_message_at
10
+ FROM message_local_state ml
11
+ JOIN messages m ON m.message_id = ml.message_id
12
+ WHERE ml.is_read = 0 AND m.sender_id != 'me'
13
+ GROUP BY m.conversation_id
14
+ ORDER BY last_message_at DESC
15
+ `).all();
16
+ }
17
+ /**
18
+ * Mark all messages in a conversation as read
19
+ */
20
+ export function markConversationRead(db, conversationId) {
21
+ const result = db.prepare(`
22
+ UPDATE message_local_state
23
+ SET is_read = 1, read_at = datetime('now'), updated_at = datetime('now')
24
+ WHERE message_id IN (
25
+ SELECT message_id FROM messages WHERE conversation_id = ?
26
+ ) AND is_read = 0
27
+ `).run(conversationId);
28
+ return result.changes;
29
+ }
30
+ /**
31
+ * Mark specific messages as read
32
+ */
33
+ export function markMessagesRead(db, messageIds) {
34
+ if (messageIds.length === 0) {
35
+ return 0;
36
+ }
37
+ const placeholders = messageIds.map(() => '?').join(',');
38
+ const query = `
39
+ UPDATE message_local_state
40
+ SET is_read = 1, read_at = datetime('now'), updated_at = datetime('now')
41
+ WHERE message_id IN (${placeholders}) AND is_read = 0
42
+ `;
43
+ const result = db.prepare(query).run(...messageIds);
44
+ return result.changes;
45
+ }
46
+ /**
47
+ * Get unread summary for all conversations
48
+ */
49
+ export function getUnreadSummary(db) {
50
+ return db.prepare(`
51
+ SELECT
52
+ c.conversation_id,
53
+ c.type as conversation_type,
54
+ c.name as conversation_name,
55
+ COUNT(ml.message_id) as unread_count,
56
+ MAX(m.remote_created_at) as last_unread_at,
57
+ (SELECT m2.sender_id FROM messages m2
58
+ JOIN message_local_state ml2 ON m2.message_id = ml2.message_id
59
+ WHERE m2.conversation_id = c.conversation_id AND ml2.is_read = 0
60
+ ORDER BY m2.remote_created_at DESC LIMIT 1) as last_sender,
61
+ MAX(CASE WHEN ml.is_mentioned = 1 THEN 1 ELSE 0 END) as has_mention
62
+ FROM conversations c
63
+ JOIN messages m ON m.conversation_id = c.conversation_id
64
+ JOIN message_local_state ml ON m.message_id = ml.message_id
65
+ WHERE ml.is_read = 0 AND m.sender_id != 'me'
66
+ GROUP BY c.conversation_id
67
+ ORDER BY last_unread_at DESC
68
+ `).all();
69
+ }
70
+ /**
71
+ * Get unread messages that mention the current agent
72
+ */
73
+ export function getUnreadMentions(db, options = {}) {
74
+ const limit = options.limit || 50;
75
+ let query = `
76
+ SELECT m.message_id, m.conversation_id, m.sender_id, m.content, m.remote_created_at,
77
+ c.type as conversation_type, c.name as conversation_name
78
+ FROM message_local_state ml
79
+ JOIN messages m ON m.message_id = ml.message_id
80
+ JOIN conversations c ON c.conversation_id = m.conversation_id
81
+ WHERE ml.is_read = 0 AND ml.is_mentioned = 1 AND m.sender_id != 'me'
82
+ `;
83
+ const params = [];
84
+ if (options.conversationId) {
85
+ query += ` AND m.conversation_id = ?`;
86
+ params.push(options.conversationId);
87
+ }
88
+ query += ` ORDER BY m.remote_created_at DESC LIMIT ?`;
89
+ params.push(limit);
90
+ return db.prepare(query).all(...params);
91
+ }
92
+ /**
93
+ * Get unread message count with mention filter
94
+ */
95
+ export function getUnreadCountByMention(db, conversationId) {
96
+ let query = `
97
+ SELECT COUNT(*) as count
98
+ FROM message_local_state ml
99
+ JOIN messages m ON m.message_id = ml.message_id
100
+ WHERE ml.is_read = 0 AND ml.is_mentioned = 1 AND m.sender_id != 'me'
101
+ `;
102
+ const params = [];
103
+ if (conversationId) {
104
+ query += ` AND m.conversation_id = ?`;
105
+ params.push(conversationId);
106
+ }
107
+ const row = db.prepare(query).get(...params);
108
+ return row.count;
109
+ }
110
+ /**
111
+ * Get detailed unread statistics for a specific conversation
112
+ */
113
+ export function getConversationUnreadStats(db, conversationId) {
114
+ const row = db.prepare(`
115
+ SELECT
116
+ COUNT(*) as totalUnread,
117
+ SUM(CASE WHEN ml.is_mentioned = 1 THEN 1 ELSE 0 END) as mentionedUnread,
118
+ MIN(m.remote_created_at) as firstUnreadAt,
119
+ MAX(m.remote_created_at) as lastUnreadAt,
120
+ COUNT(DISTINCT m.sender_id) as uniqueSenders
121
+ FROM message_local_state ml
122
+ JOIN messages m ON m.message_id = ml.message_id
123
+ WHERE ml.is_read = 0 AND m.conversation_id = ? AND m.sender_id != 'me'
124
+ `).get(conversationId);
125
+ if (row.totalUnread === 0) {
126
+ return null;
127
+ }
128
+ return {
129
+ totalUnread: row.totalUnread,
130
+ mentionedUnread: row.mentionedUnread,
131
+ firstUnreadAt: row.firstUnreadAt,
132
+ lastUnreadAt: row.lastUnreadAt,
133
+ uniqueSenders: row.uniqueSenders,
134
+ };
135
+ }
136
+ /**
137
+ * Get unread messages with surrounding history context
138
+ * Returns N messages before each unread message
139
+ */
140
+ export function getUnreadWithHistory(db, options = {}) {
141
+ const historyBefore = options.historyBefore || 10;
142
+ const limit = options.limit || 100;
143
+ // First, get unread message IDs
144
+ let unreadQuery = `
145
+ SELECT m.message_id, m.remote_created_at
146
+ FROM message_local_state ml
147
+ JOIN messages m ON m.message_id = ml.message_id
148
+ WHERE ml.is_read = 0 AND m.sender_id != 'me'
149
+ `;
150
+ const unreadParams = [];
151
+ if (options.conversationId) {
152
+ unreadQuery += ` AND m.conversation_id = ?`;
153
+ unreadParams.push(options.conversationId);
154
+ }
155
+ unreadQuery += ` ORDER BY m.remote_created_at ASC`;
156
+ const unreadMessages = db.prepare(unreadQuery).all(...unreadParams);
157
+ if (unreadMessages.length === 0) {
158
+ return [];
159
+ }
160
+ // Get the earliest unread message's timestamp
161
+ const earliestUnread = unreadMessages[0].remote_created_at;
162
+ // Fetch messages: history before earliest unread + all unread
163
+ let query = `
164
+ SELECT m.message_id, m.conversation_id, m.sender_id, m.content, m.type, m.status,
165
+ m.remote_created_at, ml.is_read, ml.is_mentioned,
166
+ c.type as conversation_type, c.name as conversation_name
167
+ FROM messages m
168
+ JOIN message_local_state ml ON m.message_id = ml.message_id
169
+ JOIN conversations c ON c.conversation_id = m.conversation_id
170
+ WHERE m.remote_created_at < ? AND m.sender_id != 'me'
171
+ `;
172
+ const params = [earliestUnread];
173
+ if (options.conversationId) {
174
+ query += ` AND m.conversation_id = ?`;
175
+ params.push(options.conversationId);
176
+ }
177
+ query += ` ORDER BY m.remote_created_at DESC LIMIT ?`;
178
+ params.push(historyBefore);
179
+ const historyMessages = db.prepare(query).all(...params);
180
+ // Now get the unread messages
181
+ let unreadFullQuery = `
182
+ SELECT m.message_id, m.conversation_id, m.sender_id, m.content, m.type, m.status,
183
+ m.remote_created_at, ml.is_read, ml.is_mentioned,
184
+ c.type as conversation_type, c.name as conversation_name
185
+ FROM message_local_state ml
186
+ JOIN messages m ON m.message_id = ml.message_id
187
+ JOIN conversations c ON c.conversation_id = m.conversation_id
188
+ WHERE ml.is_read = 0 AND m.sender_id != 'me'
189
+ `;
190
+ const unreadFullParams = [];
191
+ if (options.conversationId) {
192
+ unreadFullQuery += ` AND m.conversation_id = ?`;
193
+ unreadFullParams.push(options.conversationId);
194
+ }
195
+ unreadFullQuery += ` ORDER BY m.remote_created_at ASC LIMIT ?`;
196
+ unreadFullParams.push(limit);
197
+ const unreadFullMessages = db.prepare(unreadFullQuery).all(...unreadFullParams);
198
+ // Combine and deduplicate
199
+ const allMessages = [...historyMessages, ...unreadFullMessages];
200
+ const seen = new Set();
201
+ const deduplicated = allMessages.filter((msg) => {
202
+ if (seen.has(msg.message_id))
203
+ return false;
204
+ seen.add(msg.message_id);
205
+ return true;
206
+ });
207
+ // Sort by timestamp
208
+ return deduplicated.sort((a, b) => new Date(a.remote_created_at).getTime() - new Date(b.remote_created_at).getTime());
209
+ }
210
+ //# sourceMappingURL=read-state-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-state-repo.js","sourceRoot":"","sources":["../../../../src/modules/chat/store/read-state-repo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Sync state repository - persistence for sync cursors and timing
3
+ */
4
+ import Database from 'better-sqlite3';
5
+ export interface SyncStateRecord {
6
+ id: number;
7
+ last_sync_attempt: string | null;
8
+ last_sync_success: string | null;
9
+ last_sync_error: string | null;
10
+ global_cursor: string | null;
11
+ next_poll_after: string | null;
12
+ min_poll_interval: number;
13
+ total_messages_synced: number;
14
+ total_conversations_synced: number;
15
+ updated_at: string;
16
+ }
17
+ /**
18
+ * Initialize sync state if not exists
19
+ */
20
+ export declare function initializeSyncState(db: Database.Database): void;
21
+ /**
22
+ * Get current sync state
23
+ */
24
+ export declare function getSyncState(db: Database.Database): SyncStateRecord;
25
+ /**
26
+ * Update sync state after a sync attempt
27
+ */
28
+ export declare function updateSyncState(db: Database.Database, updates: {
29
+ success?: boolean;
30
+ error?: string;
31
+ globalCursor?: string;
32
+ nextPollAfter?: string;
33
+ minPollInterval?: number;
34
+ messagesSynced?: number;
35
+ conversationsSynced?: number;
36
+ }): void;
37
+ /**
38
+ * Check if we can poll now (respecting rate limits)
39
+ */
40
+ export declare function canPollNow(db: Database.Database): boolean;
41
+ /**
42
+ * Get next allowed poll time
43
+ */
44
+ export declare function getNextPollTime(db: Database.Database): Date | null;
45
+ //# sourceMappingURL=sync-state-repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-state-repo.d.ts","sourceRoot":"","sources":["../../../../src/modules/chat/store/sync-state-repo.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,0BAA0B,EAAE,MAAM,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAS/D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,eAAe,CAInE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,EAAE;IACP,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,GACA,IAAI,CAgCN;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAWzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,CAQlE"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Sync state repository - persistence for sync cursors and timing
3
+ */
4
+ /**
5
+ * Initialize sync state if not exists
6
+ */
7
+ export function initializeSyncState(db) {
8
+ const existing = db.prepare('SELECT id FROM sync_state WHERE id = 1').get();
9
+ if (!existing) {
10
+ db.prepare(`
11
+ INSERT INTO sync_state (id, min_poll_interval, total_messages_synced, total_conversations_synced)
12
+ VALUES (1, 1, 0, 0)
13
+ `).run();
14
+ }
15
+ }
16
+ /**
17
+ * Get current sync state
18
+ */
19
+ export function getSyncState(db) {
20
+ initializeSyncState(db);
21
+ return db.prepare('SELECT * FROM sync_state WHERE id = 1').get();
22
+ }
23
+ /**
24
+ * Update sync state after a sync attempt
25
+ */
26
+ export function updateSyncState(db, updates) {
27
+ initializeSyncState(db);
28
+ const currentState = getSyncState(db);
29
+ const now = new Date().toISOString();
30
+ const stmt = db.prepare(`
31
+ UPDATE sync_state SET
32
+ last_sync_attempt = ?,
33
+ last_sync_success = COALESCE(?, last_sync_success),
34
+ last_sync_error = COALESCE(?, last_sync_error),
35
+ global_cursor = COALESCE(?, global_cursor),
36
+ next_poll_after = COALESCE(?, next_poll_after),
37
+ min_poll_interval = COALESCE(?, min_poll_interval),
38
+ total_messages_synced = total_messages_synced + COALESCE(?, 0),
39
+ total_conversations_synced = total_conversations_synced + COALESCE(?, 0),
40
+ updated_at = ?
41
+ WHERE id = 1
42
+ `);
43
+ stmt.run(now, updates.success ? now : null, updates.error || null, updates.globalCursor || null, updates.nextPollAfter || null, updates.minPollInterval || null, updates.messagesSynced || 0, updates.conversationsSynced || 0, now);
44
+ }
45
+ /**
46
+ * Check if we can poll now (respecting rate limits)
47
+ */
48
+ export function canPollNow(db) {
49
+ const state = getSyncState(db);
50
+ if (!state.next_poll_after) {
51
+ return true;
52
+ }
53
+ const nextPollAfter = new Date(state.next_poll_after);
54
+ const now = new Date();
55
+ return now >= nextPollAfter;
56
+ }
57
+ /**
58
+ * Get next allowed poll time
59
+ */
60
+ export function getNextPollTime(db) {
61
+ const state = getSyncState(db);
62
+ if (!state.next_poll_after) {
63
+ return null;
64
+ }
65
+ return new Date(state.next_poll_after);
66
+ }
67
+ //# sourceMappingURL=sync-state-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-state-repo.js","sourceRoot":"","sources":["../../../../src/modules/chat/store/sync-state-repo.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiBH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAqB;IACvD,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC,GAAG,EAAE,CAAC;IAE5E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,EAAE,CAAC,OAAO,CAAC;;;KAGV,CAAC,CAAC,GAAG,EAAE,CAAC;IACX,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAExB,OAAO,EAAE,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,GAAG,EAAqB,CAAC;AACtF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,EAAqB,EACrB,OAQC;IAED,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAExB,MAAM,YAAY,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;IAEtC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;;GAYvB,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CACN,GAAG,EACH,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAC5B,OAAO,CAAC,KAAK,IAAI,IAAI,EACrB,OAAO,CAAC,YAAY,IAAI,IAAI,EAC5B,OAAO,CAAC,aAAa,IAAI,IAAI,EAC7B,OAAO,CAAC,eAAe,IAAI,IAAI,EAC/B,OAAO,CAAC,cAAc,IAAI,CAAC,EAC3B,OAAO,CAAC,mBAAmB,IAAI,CAAC,EAChC,GAAG,CACJ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,EAAqB;IAC9C,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;IAE/B,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,OAAO,GAAG,IAAI,aAAa,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAAqB;IACnD,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;IAE/B,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Conversation backfill logic — fetch metadata for missing conversations
3
+ */
4
+ import Database from 'better-sqlite3';
5
+ export interface BackfillResult {
6
+ inserted: boolean;
7
+ updated: boolean;
8
+ }
9
+ /**
10
+ * Backfill conversation metadata from the remote API
11
+ */
12
+ export declare function backfillConversation(accessToken: string, conversationId: string, chatDb: Database.Database): Promise<BackfillResult>;
13
+ //# sourceMappingURL=backfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backfill.d.ts","sourceRoot":"","sources":["../../../../src/modules/chat/sync/backfill.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAItC,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,QAAQ,CAAC,QAAQ,GACxB,OAAO,CAAC,cAAc,CAAC,CAkCzB"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Conversation backfill logic — fetch metadata for missing conversations
3
+ */
4
+ import { getConversation } from '../../../core/http/chat-api.js';
5
+ import { upsertConversation, upsertParticipants } from '../store/conversation-repo.js';
6
+ /**
7
+ * Backfill conversation metadata from the remote API
8
+ */
9
+ export async function backfillConversation(accessToken, conversationId, chatDb) {
10
+ // Check if already exists
11
+ const existing = chatDb.prepare('SELECT conversation_id FROM conversations WHERE conversation_id = ?').get(conversationId);
12
+ if (existing) {
13
+ // Conversation already exists, nothing to backfill
14
+ return { inserted: false, updated: false };
15
+ }
16
+ // Fetch from remote
17
+ const response = await getConversation(accessToken, conversationId);
18
+ const conv = response.data;
19
+ // Upsert conversation
20
+ upsertConversation(chatDb, {
21
+ conversation_id: conv.conversation_id,
22
+ type: conv.type || 'group',
23
+ name: conv.name || null,
24
+ created_by: conv.creator_id || '',
25
+ created_at: conv.created_at,
26
+ updated_at: conv.updated_at,
27
+ });
28
+ // Upsert participants if available
29
+ if (conv.members && conv.members.length > 0) {
30
+ upsertParticipants(chatDb, conv.conversation_id, conv.members.map(m => ({
31
+ agent_id: m.agent_id,
32
+ role: m.role || 'member',
33
+ })));
34
+ }
35
+ return { inserted: true, updated: false };
36
+ }
37
+ //# sourceMappingURL=backfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backfill.js","sourceRoot":"","sources":["../../../../src/modules/chat/sync/backfill.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAOvF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB,EACnB,cAAsB,EACtB,MAAyB;IAEzB,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAC7B,qEAAqE,CACtE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEtB,IAAI,QAAQ,EAAE,CAAC;QACb,mDAAmD;QACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,oBAAoB;IACpB,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAE3B,sBAAsB;IACtB,kBAAkB,CAAC,MAAM,EAAE;QACzB,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,IAAI,EAAG,IAAI,CAAC,IAA2B,IAAI,OAAO;QAClD,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;QACvB,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;QACjC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC,CAAC;IAEH,mCAAmC;IACnC,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtE,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,IAAI,EAAG,CAAC,CAAC,IAAqC,IAAI,QAAQ;SAC3D,CAAC,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Cron manager - install/uninstall cron entries for background sync
3
+ */
4
+ import Database from 'better-sqlite3';
5
+ export interface CronInstallOptions {
6
+ profileName: string;
7
+ schedule?: string;
8
+ command?: string;
9
+ }
10
+ export interface CronStatus {
11
+ installed: boolean;
12
+ schedule: string;
13
+ profileName: string;
14
+ lastRun: string | null;
15
+ lastSuccess: string | null;
16
+ lastError: string | null;
17
+ }
18
+ /**
19
+ * Check if cron is installed for a profile
20
+ */
21
+ export declare function isCronInstalled(db: Database.Database, profileName: string): boolean;
22
+ /**
23
+ * Install cron for a profile
24
+ */
25
+ export declare function installCron(db: Database.Database, options: CronInstallOptions): {
26
+ success: boolean;
27
+ schedule: string;
28
+ };
29
+ /**
30
+ * Uninstall cron for a profile
31
+ */
32
+ export declare function uninstallCron(db: Database.Database, profileName: string): {
33
+ success: boolean;
34
+ };
35
+ /**
36
+ * Get cron status for a profile
37
+ */
38
+ export declare function getCronStatus(db: Database.Database, profileName: string): CronStatus;
39
+ /**
40
+ * Detect cron conflicts (duplicate entries)
41
+ */
42
+ export declare function detectCronConflicts(db: Database.Database, profileName: string): string[];
43
+ /**
44
+ * List all installed cron entries
45
+ */
46
+ export declare function listInstalledCrons(): Array<{
47
+ profileName: string;
48
+ schedule: string;
49
+ }>;
50
+ //# sourceMappingURL=cron-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-manager.d.ts","sourceRoot":"","sources":["../../../../src/modules/chat/sync/cron-manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAKtC,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AA+CD;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAGnF;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,EAAE,kBAAkB,GAC1B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAiCxC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAqB9F;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,GAClB,UAAU,CAYZ;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBxF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBrF"}