@stoneforge/quarry 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 (330) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +160 -0
  3. package/dist/api/index.d.ts +8 -0
  4. package/dist/api/index.d.ts.map +1 -0
  5. package/dist/api/index.js +8 -0
  6. package/dist/api/index.js.map +1 -0
  7. package/dist/api/quarry-api.d.ts +268 -0
  8. package/dist/api/quarry-api.d.ts.map +1 -0
  9. package/dist/api/quarry-api.js +3905 -0
  10. package/dist/api/quarry-api.js.map +1 -0
  11. package/dist/api/types.d.ts +1359 -0
  12. package/dist/api/types.d.ts.map +1 -0
  13. package/dist/api/types.js +204 -0
  14. package/dist/api/types.js.map +1 -0
  15. package/dist/bin/sf.d.ts +3 -0
  16. package/dist/bin/sf.d.ts.map +1 -0
  17. package/dist/bin/sf.js +9 -0
  18. package/dist/bin/sf.js.map +1 -0
  19. package/dist/cli/commands/admin.d.ts +11 -0
  20. package/dist/cli/commands/admin.d.ts.map +1 -0
  21. package/dist/cli/commands/admin.js +465 -0
  22. package/dist/cli/commands/admin.js.map +1 -0
  23. package/dist/cli/commands/alias.d.ts +8 -0
  24. package/dist/cli/commands/alias.d.ts.map +1 -0
  25. package/dist/cli/commands/alias.js +70 -0
  26. package/dist/cli/commands/alias.js.map +1 -0
  27. package/dist/cli/commands/channel.d.ts +13 -0
  28. package/dist/cli/commands/channel.d.ts.map +1 -0
  29. package/dist/cli/commands/channel.js +680 -0
  30. package/dist/cli/commands/channel.js.map +1 -0
  31. package/dist/cli/commands/completion.d.ts +8 -0
  32. package/dist/cli/commands/completion.d.ts.map +1 -0
  33. package/dist/cli/commands/completion.js +87 -0
  34. package/dist/cli/commands/completion.js.map +1 -0
  35. package/dist/cli/commands/config.d.ts +12 -0
  36. package/dist/cli/commands/config.d.ts.map +1 -0
  37. package/dist/cli/commands/config.js +242 -0
  38. package/dist/cli/commands/config.js.map +1 -0
  39. package/dist/cli/commands/crud.d.ts +64 -0
  40. package/dist/cli/commands/crud.d.ts.map +1 -0
  41. package/dist/cli/commands/crud.js +805 -0
  42. package/dist/cli/commands/crud.js.map +1 -0
  43. package/dist/cli/commands/dep.d.ts +16 -0
  44. package/dist/cli/commands/dep.d.ts.map +1 -0
  45. package/dist/cli/commands/dep.js +499 -0
  46. package/dist/cli/commands/dep.js.map +1 -0
  47. package/dist/cli/commands/document.d.ts +12 -0
  48. package/dist/cli/commands/document.d.ts.map +1 -0
  49. package/dist/cli/commands/document.js +1039 -0
  50. package/dist/cli/commands/document.js.map +1 -0
  51. package/dist/cli/commands/embeddings.d.ts +12 -0
  52. package/dist/cli/commands/embeddings.d.ts.map +1 -0
  53. package/dist/cli/commands/embeddings.js +273 -0
  54. package/dist/cli/commands/embeddings.js.map +1 -0
  55. package/dist/cli/commands/entity.d.ts +16 -0
  56. package/dist/cli/commands/entity.d.ts.map +1 -0
  57. package/dist/cli/commands/entity.js +522 -0
  58. package/dist/cli/commands/entity.js.map +1 -0
  59. package/dist/cli/commands/gc.d.ts +10 -0
  60. package/dist/cli/commands/gc.d.ts.map +1 -0
  61. package/dist/cli/commands/gc.js +257 -0
  62. package/dist/cli/commands/gc.js.map +1 -0
  63. package/dist/cli/commands/help.d.ts +11 -0
  64. package/dist/cli/commands/help.d.ts.map +1 -0
  65. package/dist/cli/commands/help.js +169 -0
  66. package/dist/cli/commands/help.js.map +1 -0
  67. package/dist/cli/commands/history.d.ts +9 -0
  68. package/dist/cli/commands/history.d.ts.map +1 -0
  69. package/dist/cli/commands/history.js +160 -0
  70. package/dist/cli/commands/history.js.map +1 -0
  71. package/dist/cli/commands/identity.d.ts +18 -0
  72. package/dist/cli/commands/identity.d.ts.map +1 -0
  73. package/dist/cli/commands/identity.js +698 -0
  74. package/dist/cli/commands/identity.js.map +1 -0
  75. package/dist/cli/commands/inbox.d.ts +20 -0
  76. package/dist/cli/commands/inbox.d.ts.map +1 -0
  77. package/dist/cli/commands/inbox.js +493 -0
  78. package/dist/cli/commands/inbox.js.map +1 -0
  79. package/dist/cli/commands/init.d.ts +20 -0
  80. package/dist/cli/commands/init.d.ts.map +1 -0
  81. package/dist/cli/commands/init.js +144 -0
  82. package/dist/cli/commands/init.js.map +1 -0
  83. package/dist/cli/commands/install.d.ts +9 -0
  84. package/dist/cli/commands/install.d.ts.map +1 -0
  85. package/dist/cli/commands/install.js +200 -0
  86. package/dist/cli/commands/install.js.map +1 -0
  87. package/dist/cli/commands/library.d.ts +12 -0
  88. package/dist/cli/commands/library.d.ts.map +1 -0
  89. package/dist/cli/commands/library.js +665 -0
  90. package/dist/cli/commands/library.js.map +1 -0
  91. package/dist/cli/commands/message.d.ts +11 -0
  92. package/dist/cli/commands/message.d.ts.map +1 -0
  93. package/dist/cli/commands/message.js +608 -0
  94. package/dist/cli/commands/message.js.map +1 -0
  95. package/dist/cli/commands/plan.d.ts +17 -0
  96. package/dist/cli/commands/plan.d.ts.map +1 -0
  97. package/dist/cli/commands/plan.js +698 -0
  98. package/dist/cli/commands/plan.js.map +1 -0
  99. package/dist/cli/commands/playbook.d.ts +12 -0
  100. package/dist/cli/commands/playbook.d.ts.map +1 -0
  101. package/dist/cli/commands/playbook.js +730 -0
  102. package/dist/cli/commands/playbook.js.map +1 -0
  103. package/dist/cli/commands/reset.d.ts +12 -0
  104. package/dist/cli/commands/reset.d.ts.map +1 -0
  105. package/dist/cli/commands/reset.js +306 -0
  106. package/dist/cli/commands/reset.js.map +1 -0
  107. package/dist/cli/commands/serve.d.ts +11 -0
  108. package/dist/cli/commands/serve.d.ts.map +1 -0
  109. package/dist/cli/commands/serve.js +106 -0
  110. package/dist/cli/commands/serve.js.map +1 -0
  111. package/dist/cli/commands/stats.d.ts +8 -0
  112. package/dist/cli/commands/stats.d.ts.map +1 -0
  113. package/dist/cli/commands/stats.js +82 -0
  114. package/dist/cli/commands/stats.js.map +1 -0
  115. package/dist/cli/commands/sync.d.ts +14 -0
  116. package/dist/cli/commands/sync.d.ts.map +1 -0
  117. package/dist/cli/commands/sync.js +370 -0
  118. package/dist/cli/commands/sync.js.map +1 -0
  119. package/dist/cli/commands/task.d.ts +25 -0
  120. package/dist/cli/commands/task.d.ts.map +1 -0
  121. package/dist/cli/commands/task.js +1153 -0
  122. package/dist/cli/commands/task.js.map +1 -0
  123. package/dist/cli/commands/team.d.ts +13 -0
  124. package/dist/cli/commands/team.d.ts.map +1 -0
  125. package/dist/cli/commands/team.js +471 -0
  126. package/dist/cli/commands/team.js.map +1 -0
  127. package/dist/cli/commands/workflow.d.ts +16 -0
  128. package/dist/cli/commands/workflow.d.ts.map +1 -0
  129. package/dist/cli/commands/workflow.js +753 -0
  130. package/dist/cli/commands/workflow.js.map +1 -0
  131. package/dist/cli/completion.d.ts +28 -0
  132. package/dist/cli/completion.d.ts.map +1 -0
  133. package/dist/cli/completion.js +295 -0
  134. package/dist/cli/completion.js.map +1 -0
  135. package/dist/cli/db.d.ts +38 -0
  136. package/dist/cli/db.d.ts.map +1 -0
  137. package/dist/cli/db.js +90 -0
  138. package/dist/cli/db.js.map +1 -0
  139. package/dist/cli/formatter.d.ts +87 -0
  140. package/dist/cli/formatter.d.ts.map +1 -0
  141. package/dist/cli/formatter.js +464 -0
  142. package/dist/cli/formatter.js.map +1 -0
  143. package/dist/cli/index.d.ts +33 -0
  144. package/dist/cli/index.d.ts.map +1 -0
  145. package/dist/cli/index.js +38 -0
  146. package/dist/cli/index.js.map +1 -0
  147. package/dist/cli/parser.d.ts +45 -0
  148. package/dist/cli/parser.d.ts.map +1 -0
  149. package/dist/cli/parser.js +256 -0
  150. package/dist/cli/parser.js.map +1 -0
  151. package/dist/cli/plugin-loader.d.ts +39 -0
  152. package/dist/cli/plugin-loader.d.ts.map +1 -0
  153. package/dist/cli/plugin-loader.js +165 -0
  154. package/dist/cli/plugin-loader.js.map +1 -0
  155. package/dist/cli/plugin-registry.d.ts +50 -0
  156. package/dist/cli/plugin-registry.d.ts.map +1 -0
  157. package/dist/cli/plugin-registry.js +206 -0
  158. package/dist/cli/plugin-registry.js.map +1 -0
  159. package/dist/cli/plugin-types.d.ts +106 -0
  160. package/dist/cli/plugin-types.d.ts.map +1 -0
  161. package/dist/cli/plugin-types.js +103 -0
  162. package/dist/cli/plugin-types.js.map +1 -0
  163. package/dist/cli/runner.d.ts +35 -0
  164. package/dist/cli/runner.d.ts.map +1 -0
  165. package/dist/cli/runner.js +340 -0
  166. package/dist/cli/runner.js.map +1 -0
  167. package/dist/cli/suggest.d.ts +15 -0
  168. package/dist/cli/suggest.d.ts.map +1 -0
  169. package/dist/cli/suggest.js +49 -0
  170. package/dist/cli/suggest.js.map +1 -0
  171. package/dist/cli/types.d.ts +138 -0
  172. package/dist/cli/types.d.ts.map +1 -0
  173. package/dist/cli/types.js +63 -0
  174. package/dist/cli/types.js.map +1 -0
  175. package/dist/config/config.d.ts +86 -0
  176. package/dist/config/config.d.ts.map +1 -0
  177. package/dist/config/config.js +348 -0
  178. package/dist/config/config.js.map +1 -0
  179. package/dist/config/defaults.d.ts +66 -0
  180. package/dist/config/defaults.d.ts.map +1 -0
  181. package/dist/config/defaults.js +114 -0
  182. package/dist/config/defaults.js.map +1 -0
  183. package/dist/config/duration.d.ts +75 -0
  184. package/dist/config/duration.d.ts.map +1 -0
  185. package/dist/config/duration.js +190 -0
  186. package/dist/config/duration.js.map +1 -0
  187. package/dist/config/env.d.ts +67 -0
  188. package/dist/config/env.d.ts.map +1 -0
  189. package/dist/config/env.js +207 -0
  190. package/dist/config/env.js.map +1 -0
  191. package/dist/config/file.d.ts +97 -0
  192. package/dist/config/file.d.ts.map +1 -0
  193. package/dist/config/file.js +365 -0
  194. package/dist/config/file.js.map +1 -0
  195. package/dist/config/index.d.ts +35 -0
  196. package/dist/config/index.d.ts.map +1 -0
  197. package/dist/config/index.js +41 -0
  198. package/dist/config/index.js.map +1 -0
  199. package/dist/config/merge.d.ts +53 -0
  200. package/dist/config/merge.d.ts.map +1 -0
  201. package/dist/config/merge.js +226 -0
  202. package/dist/config/merge.js.map +1 -0
  203. package/dist/config/types.d.ts +257 -0
  204. package/dist/config/types.d.ts.map +1 -0
  205. package/dist/config/types.js +72 -0
  206. package/dist/config/types.js.map +1 -0
  207. package/dist/config/validation.d.ts +55 -0
  208. package/dist/config/validation.d.ts.map +1 -0
  209. package/dist/config/validation.js +251 -0
  210. package/dist/config/validation.js.map +1 -0
  211. package/dist/http/index.d.ts +8 -0
  212. package/dist/http/index.d.ts.map +1 -0
  213. package/dist/http/index.js +12 -0
  214. package/dist/http/index.js.map +1 -0
  215. package/dist/http/sync-handlers.d.ts +162 -0
  216. package/dist/http/sync-handlers.d.ts.map +1 -0
  217. package/dist/http/sync-handlers.js +271 -0
  218. package/dist/http/sync-handlers.js.map +1 -0
  219. package/dist/index.d.ts +25 -0
  220. package/dist/index.d.ts.map +1 -0
  221. package/dist/index.js +69 -0
  222. package/dist/index.js.map +1 -0
  223. package/dist/server/index.d.ts +34 -0
  224. package/dist/server/index.d.ts.map +1 -0
  225. package/dist/server/index.js +3329 -0
  226. package/dist/server/index.js.map +1 -0
  227. package/dist/server/static.d.ts +18 -0
  228. package/dist/server/static.d.ts.map +1 -0
  229. package/dist/server/static.js +71 -0
  230. package/dist/server/static.js.map +1 -0
  231. package/dist/server/ws/broadcaster.d.ts +8 -0
  232. package/dist/server/ws/broadcaster.d.ts.map +1 -0
  233. package/dist/server/ws/broadcaster.js +7 -0
  234. package/dist/server/ws/broadcaster.js.map +1 -0
  235. package/dist/server/ws/handler.d.ts +55 -0
  236. package/dist/server/ws/handler.d.ts.map +1 -0
  237. package/dist/server/ws/handler.js +160 -0
  238. package/dist/server/ws/handler.js.map +1 -0
  239. package/dist/services/blocked-cache.d.ts +297 -0
  240. package/dist/services/blocked-cache.d.ts.map +1 -0
  241. package/dist/services/blocked-cache.js +755 -0
  242. package/dist/services/blocked-cache.js.map +1 -0
  243. package/dist/services/dependency.d.ts +205 -0
  244. package/dist/services/dependency.d.ts.map +1 -0
  245. package/dist/services/dependency.js +566 -0
  246. package/dist/services/dependency.js.map +1 -0
  247. package/dist/services/embeddings/fusion.d.ts +33 -0
  248. package/dist/services/embeddings/fusion.d.ts.map +1 -0
  249. package/dist/services/embeddings/fusion.js +34 -0
  250. package/dist/services/embeddings/fusion.js.map +1 -0
  251. package/dist/services/embeddings/index.d.ts +12 -0
  252. package/dist/services/embeddings/index.d.ts.map +1 -0
  253. package/dist/services/embeddings/index.js +10 -0
  254. package/dist/services/embeddings/index.js.map +1 -0
  255. package/dist/services/embeddings/local-provider.d.ts +31 -0
  256. package/dist/services/embeddings/local-provider.d.ts.map +1 -0
  257. package/dist/services/embeddings/local-provider.js +80 -0
  258. package/dist/services/embeddings/local-provider.js.map +1 -0
  259. package/dist/services/embeddings/service.d.ts +76 -0
  260. package/dist/services/embeddings/service.d.ts.map +1 -0
  261. package/dist/services/embeddings/service.js +153 -0
  262. package/dist/services/embeddings/service.js.map +1 -0
  263. package/dist/services/embeddings/types.d.ts +70 -0
  264. package/dist/services/embeddings/types.d.ts.map +1 -0
  265. package/dist/services/embeddings/types.js +8 -0
  266. package/dist/services/embeddings/types.js.map +1 -0
  267. package/dist/services/id-length-cache.d.ts +156 -0
  268. package/dist/services/id-length-cache.d.ts.map +1 -0
  269. package/dist/services/id-length-cache.js +197 -0
  270. package/dist/services/id-length-cache.js.map +1 -0
  271. package/dist/services/inbox.d.ts +147 -0
  272. package/dist/services/inbox.d.ts.map +1 -0
  273. package/dist/services/inbox.js +428 -0
  274. package/dist/services/inbox.js.map +1 -0
  275. package/dist/services/index.d.ts +10 -0
  276. package/dist/services/index.d.ts.map +1 -0
  277. package/dist/services/index.js +10 -0
  278. package/dist/services/index.js.map +1 -0
  279. package/dist/services/priority-service.d.ts +145 -0
  280. package/dist/services/priority-service.d.ts.map +1 -0
  281. package/dist/services/priority-service.js +272 -0
  282. package/dist/services/priority-service.js.map +1 -0
  283. package/dist/services/search-utils.d.ts +47 -0
  284. package/dist/services/search-utils.d.ts.map +1 -0
  285. package/dist/services/search-utils.js +83 -0
  286. package/dist/services/search-utils.js.map +1 -0
  287. package/dist/sync/hash.d.ts +48 -0
  288. package/dist/sync/hash.d.ts.map +1 -0
  289. package/dist/sync/hash.js +136 -0
  290. package/dist/sync/hash.js.map +1 -0
  291. package/dist/sync/index.d.ts +11 -0
  292. package/dist/sync/index.d.ts.map +1 -0
  293. package/dist/sync/index.js +16 -0
  294. package/dist/sync/index.js.map +1 -0
  295. package/dist/sync/merge.d.ts +80 -0
  296. package/dist/sync/merge.d.ts.map +1 -0
  297. package/dist/sync/merge.js +310 -0
  298. package/dist/sync/merge.js.map +1 -0
  299. package/dist/sync/serialization.d.ts +132 -0
  300. package/dist/sync/serialization.d.ts.map +1 -0
  301. package/dist/sync/serialization.js +306 -0
  302. package/dist/sync/serialization.js.map +1 -0
  303. package/dist/sync/service.d.ts +102 -0
  304. package/dist/sync/service.d.ts.map +1 -0
  305. package/dist/sync/service.js +493 -0
  306. package/dist/sync/service.js.map +1 -0
  307. package/dist/sync/types.d.ts +275 -0
  308. package/dist/sync/types.d.ts.map +1 -0
  309. package/dist/sync/types.js +76 -0
  310. package/dist/sync/types.js.map +1 -0
  311. package/dist/systems/identity.d.ts +479 -0
  312. package/dist/systems/identity.d.ts.map +1 -0
  313. package/dist/systems/identity.js +817 -0
  314. package/dist/systems/identity.js.map +1 -0
  315. package/dist/systems/index.d.ts +8 -0
  316. package/dist/systems/index.d.ts.map +1 -0
  317. package/dist/systems/index.js +29 -0
  318. package/dist/systems/index.js.map +1 -0
  319. package/package.json +121 -0
  320. package/web/assets/charts-vendor-D1YcbGux.js +55 -0
  321. package/web/assets/dnd-vendor-DmxE-_ZH.js +5 -0
  322. package/web/assets/editor-vendor-BxraAWts.js +279 -0
  323. package/web/assets/index-B77vv208.js +341 -0
  324. package/web/assets/index-CF_XnVLh.css +1 -0
  325. package/web/assets/router-vendor-BCKpRBrB.js +41 -0
  326. package/web/assets/ui-vendor-DUahGnbT.js +45 -0
  327. package/web/assets/utils-vendor-CfYKiENT.js +813 -0
  328. package/web/favicon.ico +0 -0
  329. package/web/index.html +23 -0
  330. package/web/logo.png +0 -0
@@ -0,0 +1,428 @@
1
+ /**
2
+ * Inbox Service - Unified notification inbox management
3
+ *
4
+ * Provides CRUD operations for inbox items:
5
+ * - addToInbox: Add a new notification to an entity's inbox
6
+ * - getInbox: Get inbox items for an entity with optional filtering
7
+ * - getInboxPaginated: Get inbox items with pagination and total count
8
+ * - markAsRead: Mark an inbox item as read
9
+ * - markAsUnread: Mark an inbox item as unread
10
+ * - markAllAsRead: Mark all unread items as read for an entity
11
+ * - archive: Archive an inbox item
12
+ *
13
+ * The service does NOT integrate with MessageService - that is handled
14
+ * in a separate integration layer (Phase 4).
15
+ */
16
+ import { InboxStatus, validateInboxSourceType, createTimestamp, NotFoundError, ConflictError, ValidationError, ErrorCode, } from '@stoneforge/core';
17
+ // ============================================================================
18
+ // ID Generation
19
+ // ============================================================================
20
+ /**
21
+ * Generate a unique inbox item ID
22
+ * Uses a simple format: inbox-{timestamp}-{random}
23
+ */
24
+ function generateInboxItemId() {
25
+ const timestamp = Date.now().toString(36);
26
+ const random = Math.random().toString(36).substring(2, 8);
27
+ return `inbox-${timestamp}-${random}`;
28
+ }
29
+ // ============================================================================
30
+ // InboxService Class
31
+ // ============================================================================
32
+ /**
33
+ * Service for managing inbox items
34
+ */
35
+ export class InboxService {
36
+ db;
37
+ constructor(db) {
38
+ this.db = db;
39
+ }
40
+ // --------------------------------------------------------------------------
41
+ // Schema Initialization
42
+ // --------------------------------------------------------------------------
43
+ /**
44
+ * Initialize the inbox_items table schema
45
+ * Should be called during database setup
46
+ *
47
+ * Note: In production, use migrations instead of this method.
48
+ * This is provided for testing and standalone service usage.
49
+ */
50
+ initSchema() {
51
+ this.db.exec(`
52
+ CREATE TABLE IF NOT EXISTS inbox_items (
53
+ id TEXT PRIMARY KEY,
54
+ recipient_id TEXT NOT NULL,
55
+ message_id TEXT NOT NULL,
56
+ channel_id TEXT NOT NULL,
57
+ source_type TEXT NOT NULL CHECK (source_type IN ('direct', 'mention')),
58
+ status TEXT NOT NULL DEFAULT 'unread' CHECK (status IN ('unread', 'read', 'archived')),
59
+ read_at TEXT,
60
+ created_at TEXT NOT NULL,
61
+ UNIQUE(recipient_id, message_id)
62
+ )
63
+ `);
64
+ // Create indexes for efficient lookups
65
+ this.db.exec(`
66
+ CREATE INDEX IF NOT EXISTS idx_inbox_recipient_status
67
+ ON inbox_items(recipient_id, status)
68
+ `);
69
+ this.db.exec(`
70
+ CREATE INDEX IF NOT EXISTS idx_inbox_recipient_created
71
+ ON inbox_items(recipient_id, created_at DESC)
72
+ `);
73
+ this.db.exec(`
74
+ CREATE INDEX IF NOT EXISTS idx_inbox_message
75
+ ON inbox_items(message_id)
76
+ `);
77
+ this.db.exec(`
78
+ CREATE INDEX IF NOT EXISTS idx_inbox_recipient_channel
79
+ ON inbox_items(recipient_id, channel_id)
80
+ `);
81
+ }
82
+ // --------------------------------------------------------------------------
83
+ // Create
84
+ // --------------------------------------------------------------------------
85
+ /**
86
+ * Add a new item to an entity's inbox
87
+ *
88
+ * @param input - Inbox item creation input
89
+ * @returns The created inbox item
90
+ * @throws ValidationError if input is invalid
91
+ * @throws ConflictError if inbox item already exists for this recipient/message
92
+ */
93
+ addToInbox(input) {
94
+ // Validate inputs
95
+ if (!input.recipientId || typeof input.recipientId !== 'string') {
96
+ throw new ValidationError('recipientId is required', ErrorCode.MISSING_REQUIRED_FIELD, { field: 'recipientId', value: input.recipientId });
97
+ }
98
+ if (!input.messageId || typeof input.messageId !== 'string') {
99
+ throw new ValidationError('messageId is required', ErrorCode.MISSING_REQUIRED_FIELD, { field: 'messageId', value: input.messageId });
100
+ }
101
+ if (!input.channelId || typeof input.channelId !== 'string') {
102
+ throw new ValidationError('channelId is required', ErrorCode.MISSING_REQUIRED_FIELD, { field: 'channelId', value: input.channelId });
103
+ }
104
+ validateInboxSourceType(input.sourceType);
105
+ const id = generateInboxItemId();
106
+ const now = createTimestamp();
107
+ const inboxItem = {
108
+ id,
109
+ recipientId: input.recipientId,
110
+ messageId: input.messageId,
111
+ channelId: input.channelId,
112
+ sourceType: input.sourceType,
113
+ status: InboxStatus.UNREAD,
114
+ readAt: null,
115
+ createdAt: now,
116
+ };
117
+ // Insert into database
118
+ try {
119
+ this.db.run(`INSERT INTO inbox_items (id, recipient_id, message_id, channel_id, source_type, status, read_at, created_at)
120
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
121
+ inboxItem.id,
122
+ inboxItem.recipientId,
123
+ inboxItem.messageId,
124
+ inboxItem.channelId,
125
+ inboxItem.sourceType,
126
+ inboxItem.status,
127
+ inboxItem.readAt,
128
+ inboxItem.createdAt,
129
+ ]);
130
+ }
131
+ catch (error) {
132
+ // Check for duplicate key error
133
+ if (error instanceof Error && error.message.includes('UNIQUE constraint failed')) {
134
+ throw new ConflictError(`Inbox item already exists for recipient ${input.recipientId} and message ${input.messageId}`, ErrorCode.ALREADY_EXISTS, { recipientId: input.recipientId, messageId: input.messageId });
135
+ }
136
+ throw error;
137
+ }
138
+ return inboxItem;
139
+ }
140
+ // --------------------------------------------------------------------------
141
+ // Read
142
+ // --------------------------------------------------------------------------
143
+ /**
144
+ * Get inbox items for a recipient with optional filtering
145
+ *
146
+ * @param recipientId - Entity to get inbox for
147
+ * @param filter - Optional filter criteria
148
+ * @returns Array of inbox items
149
+ */
150
+ getInbox(recipientId, filter) {
151
+ const { sql, params } = this.buildFilterQuery(recipientId, filter);
152
+ const rows = this.db.query(sql, params);
153
+ return rows.map((row) => this.rowToInboxItem(row));
154
+ }
155
+ /**
156
+ * Get inbox items with pagination info
157
+ *
158
+ * @param recipientId - Entity to get inbox for
159
+ * @param filter - Optional filter criteria (limit and offset used for pagination)
160
+ * @returns Object with items and total count
161
+ */
162
+ getInboxPaginated(recipientId, filter) {
163
+ // Get total count first (without limit/offset)
164
+ const countFilter = { ...filter, limit: undefined, offset: undefined };
165
+ const { sql: countSql, params: countParams } = this.buildFilterQuery(recipientId, countFilter, true);
166
+ const countResult = this.db.queryOne(countSql, countParams);
167
+ const total = countResult?.count ?? 0;
168
+ // Get paginated items
169
+ const items = this.getInbox(recipientId, filter);
170
+ return { items, total };
171
+ }
172
+ /**
173
+ * Get the count of unread inbox items for a recipient
174
+ *
175
+ * @param recipientId - Entity to get unread count for
176
+ * @returns Number of unread items
177
+ */
178
+ getUnreadCount(recipientId) {
179
+ const result = this.db.queryOne(`SELECT COUNT(*) as count FROM inbox_items
180
+ WHERE recipient_id = ? AND status = ?`, [recipientId, InboxStatus.UNREAD]);
181
+ return result?.count ?? 0;
182
+ }
183
+ /**
184
+ * Get a single inbox item by ID
185
+ *
186
+ * @param id - Inbox item ID
187
+ * @returns The inbox item or null if not found
188
+ */
189
+ getInboxItem(id) {
190
+ const row = this.db.queryOne(`SELECT id, recipient_id, message_id, channel_id, source_type, status, read_at, created_at
191
+ FROM inbox_items WHERE id = ?`, [id]);
192
+ return row ? this.rowToInboxItem(row) : null;
193
+ }
194
+ // --------------------------------------------------------------------------
195
+ // Update
196
+ // --------------------------------------------------------------------------
197
+ /**
198
+ * Mark an inbox item as read
199
+ *
200
+ * @param itemId - Inbox item ID to mark as read
201
+ * @returns The updated inbox item
202
+ * @throws NotFoundError if inbox item doesn't exist
203
+ */
204
+ markAsRead(itemId) {
205
+ const now = createTimestamp();
206
+ const result = this.db.run(`UPDATE inbox_items
207
+ SET status = ?, read_at = ?
208
+ WHERE id = ? AND status = ?`, [InboxStatus.READ, now, itemId, InboxStatus.UNREAD]);
209
+ if (result.changes === 0) {
210
+ // Check if item exists
211
+ const existing = this.getInboxItem(itemId);
212
+ if (!existing) {
213
+ throw new NotFoundError(`Inbox item not found: ${itemId}`, ErrorCode.NOT_FOUND, { id: itemId });
214
+ }
215
+ // Item exists but was already read or archived - return as-is
216
+ return existing;
217
+ }
218
+ return this.getInboxItem(itemId);
219
+ }
220
+ /**
221
+ * Mark multiple inbox items as read in a single operation.
222
+ *
223
+ * @param itemIds - Inbox item IDs to mark as read
224
+ * @returns Number of items actually marked as read
225
+ */
226
+ markAsReadBatch(itemIds) {
227
+ if (itemIds.length === 0)
228
+ return 0;
229
+ const now = createTimestamp();
230
+ const placeholders = itemIds.map(() => '?').join(', ');
231
+ const result = this.db.run(`UPDATE inbox_items
232
+ SET status = ?, read_at = ?
233
+ WHERE id IN (${placeholders}) AND status = ?`, [InboxStatus.READ, now, ...itemIds, InboxStatus.UNREAD]);
234
+ return result.changes;
235
+ }
236
+ /**
237
+ * Mark an inbox item as unread
238
+ *
239
+ * @param itemId - Inbox item ID to mark as unread
240
+ * @returns The updated inbox item
241
+ * @throws NotFoundError if inbox item doesn't exist
242
+ */
243
+ markAsUnread(itemId) {
244
+ const result = this.db.run(`UPDATE inbox_items
245
+ SET status = ?, read_at = NULL
246
+ WHERE id = ? AND status != ?`, [InboxStatus.UNREAD, itemId, InboxStatus.ARCHIVED]);
247
+ if (result.changes === 0) {
248
+ // Check if item exists
249
+ const existing = this.getInboxItem(itemId);
250
+ if (!existing) {
251
+ throw new NotFoundError(`Inbox item not found: ${itemId}`, ErrorCode.NOT_FOUND, { id: itemId });
252
+ }
253
+ // Item exists but was already unread or archived - return as-is
254
+ return existing;
255
+ }
256
+ return this.getInboxItem(itemId);
257
+ }
258
+ /**
259
+ * Mark all unread inbox items as read for a recipient
260
+ *
261
+ * @param recipientId - Entity to mark all items as read for
262
+ * @returns Number of items marked as read
263
+ */
264
+ markAllAsRead(recipientId) {
265
+ const now = createTimestamp();
266
+ const result = this.db.run(`UPDATE inbox_items
267
+ SET status = ?, read_at = ?
268
+ WHERE recipient_id = ? AND status = ?`, [InboxStatus.READ, now, recipientId, InboxStatus.UNREAD]);
269
+ return result.changes;
270
+ }
271
+ /**
272
+ * Archive an inbox item
273
+ *
274
+ * @param itemId - Inbox item ID to archive
275
+ * @returns The updated inbox item
276
+ * @throws NotFoundError if inbox item doesn't exist
277
+ */
278
+ archive(itemId) {
279
+ const result = this.db.run(`UPDATE inbox_items
280
+ SET status = ?
281
+ WHERE id = ?`, [InboxStatus.ARCHIVED, itemId]);
282
+ if (result.changes === 0) {
283
+ throw new NotFoundError(`Inbox item not found: ${itemId}`, ErrorCode.NOT_FOUND, { id: itemId });
284
+ }
285
+ return this.getInboxItem(itemId);
286
+ }
287
+ // --------------------------------------------------------------------------
288
+ // Query
289
+ // --------------------------------------------------------------------------
290
+ /**
291
+ * Get inbox items for a specific channel
292
+ *
293
+ * @param recipientId - Entity to get inbox for
294
+ * @param channelId - Channel to filter by
295
+ * @returns Array of inbox items for the channel
296
+ */
297
+ getInboxByChannel(recipientId, channelId) {
298
+ return this.getInbox(recipientId, { channelId });
299
+ }
300
+ // --------------------------------------------------------------------------
301
+ // Delete (for internal use / cascade)
302
+ // --------------------------------------------------------------------------
303
+ /**
304
+ * Delete inbox items by message ID (for cascade deletion)
305
+ *
306
+ * @param messageId - Message ID to delete inbox items for
307
+ * @returns Number of items deleted
308
+ */
309
+ deleteByMessage(messageId) {
310
+ const result = this.db.run(`DELETE FROM inbox_items WHERE message_id = ?`, [messageId]);
311
+ return result.changes;
312
+ }
313
+ /**
314
+ * Delete all inbox items for a recipient
315
+ *
316
+ * @param recipientId - Entity to delete inbox items for
317
+ * @returns Number of items deleted
318
+ */
319
+ deleteByRecipient(recipientId) {
320
+ const result = this.db.run(`DELETE FROM inbox_items WHERE recipient_id = ?`, [recipientId]);
321
+ return result.changes;
322
+ }
323
+ // --------------------------------------------------------------------------
324
+ // Private Helpers
325
+ // --------------------------------------------------------------------------
326
+ /**
327
+ * Build a SQL query from filter options
328
+ */
329
+ buildFilterQuery(recipientId, filter, countOnly = false) {
330
+ const conditions = ['recipient_id = ?'];
331
+ const params = [recipientId];
332
+ if (filter) {
333
+ // Status filter
334
+ if (filter.status !== undefined) {
335
+ const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
336
+ if (statuses.length === 1) {
337
+ conditions.push('status = ?');
338
+ params.push(statuses[0]);
339
+ }
340
+ else if (statuses.length > 1) {
341
+ const placeholders = statuses.map(() => '?').join(',');
342
+ conditions.push(`status IN (${placeholders})`);
343
+ params.push(...statuses);
344
+ }
345
+ }
346
+ // Source type filter
347
+ if (filter.sourceType !== undefined) {
348
+ const types = Array.isArray(filter.sourceType) ? filter.sourceType : [filter.sourceType];
349
+ if (types.length === 1) {
350
+ conditions.push('source_type = ?');
351
+ params.push(types[0]);
352
+ }
353
+ else if (types.length > 1) {
354
+ const placeholders = types.map(() => '?').join(',');
355
+ conditions.push(`source_type IN (${placeholders})`);
356
+ params.push(...types);
357
+ }
358
+ }
359
+ // Channel filter
360
+ if (filter.channelId !== undefined) {
361
+ conditions.push('channel_id = ?');
362
+ params.push(filter.channelId);
363
+ }
364
+ // After timestamp filter
365
+ if (filter.after !== undefined) {
366
+ conditions.push('created_at > ?');
367
+ params.push(filter.after);
368
+ }
369
+ // Before timestamp filter
370
+ if (filter.before !== undefined) {
371
+ conditions.push('created_at < ?');
372
+ params.push(filter.before);
373
+ }
374
+ }
375
+ const whereClause = conditions.join(' AND ');
376
+ if (countOnly) {
377
+ return {
378
+ sql: `SELECT COUNT(*) as count FROM inbox_items WHERE ${whereClause}`,
379
+ params,
380
+ };
381
+ }
382
+ let sql = `SELECT id, recipient_id, message_id, channel_id, source_type, status, read_at, created_at
383
+ FROM inbox_items
384
+ WHERE ${whereClause}
385
+ ORDER BY created_at DESC`;
386
+ // Pagination
387
+ if (filter?.limit !== undefined) {
388
+ sql += ` LIMIT ?`;
389
+ params.push(filter.limit);
390
+ // OFFSET only works with LIMIT in SQLite
391
+ if (filter?.offset !== undefined) {
392
+ sql += ` OFFSET ?`;
393
+ params.push(filter.offset);
394
+ }
395
+ }
396
+ else if (filter?.offset !== undefined) {
397
+ // If only offset is specified, use a large limit
398
+ sql += ` LIMIT -1 OFFSET ?`;
399
+ params.push(filter.offset);
400
+ }
401
+ return { sql, params };
402
+ }
403
+ /**
404
+ * Convert a database row to an InboxItem object
405
+ */
406
+ rowToInboxItem(row) {
407
+ return {
408
+ id: row.id,
409
+ recipientId: row.recipient_id,
410
+ messageId: row.message_id,
411
+ channelId: row.channel_id,
412
+ sourceType: row.source_type,
413
+ status: row.status,
414
+ readAt: row.read_at,
415
+ createdAt: row.created_at,
416
+ };
417
+ }
418
+ }
419
+ // ============================================================================
420
+ // Factory Function
421
+ // ============================================================================
422
+ /**
423
+ * Create a new InboxService instance
424
+ */
425
+ export function createInboxService(db) {
426
+ return new InboxService(db);
427
+ }
428
+ //# sourceMappingURL=inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/services/inbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Stoneforge Services
3
+ */
4
+ export * from './dependency.js';
5
+ export * from './priority-service.js';
6
+ export * from './id-length-cache.js';
7
+ export * from './inbox.js';
8
+ export * from './search-utils.js';
9
+ export * from './embeddings/index.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Stoneforge Services
3
+ */
4
+ export * from './dependency.js';
5
+ export * from './priority-service.js';
6
+ export * from './id-length-cache.js';
7
+ export * from './inbox.js';
8
+ export * from './search-utils.js';
9
+ export * from './embeddings/index.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Priority Service - Dependency-based priority calculation and complexity inheritance
3
+ *
4
+ * Provides:
5
+ * - Effective Priority: Computes a task's priority based on what depends on it
6
+ * (tasks blocking high-priority work inherit that urgency)
7
+ * - Aggregate Complexity: Computes total effort including dependent task complexity
8
+ */
9
+ import type { StorageBackend } from '@stoneforge/storage';
10
+ import type { ElementId, Task, Priority, Complexity } from '@stoneforge/core';
11
+ /**
12
+ * Result of effective priority calculation
13
+ */
14
+ export interface EffectivePriorityResult {
15
+ /** The task's own/explicit priority */
16
+ basePriority: Priority;
17
+ /** The computed effective priority (may be higher due to dependents) */
18
+ effectivePriority: Priority;
19
+ /** IDs of high-priority tasks that depend on this task */
20
+ dependentInfluencers: ElementId[];
21
+ /** Whether the effective priority differs from base priority */
22
+ isInfluenced: boolean;
23
+ }
24
+ /**
25
+ * Result of aggregate complexity calculation
26
+ */
27
+ export interface AggregateComplexityResult {
28
+ /** The task's own complexity */
29
+ baseComplexity: Complexity;
30
+ /** Total complexity including blocked dependencies */
31
+ aggregateComplexity: number;
32
+ /** Number of dependent tasks included in calculation */
33
+ dependentCount: number;
34
+ /** Breakdown by dependency */
35
+ dependentComplexities: Array<{
36
+ id: ElementId;
37
+ complexity: Complexity;
38
+ }>;
39
+ }
40
+ /**
41
+ * Task with calculated priority and complexity
42
+ */
43
+ export interface TaskWithEffectivePriority extends Task {
44
+ /** Computed effective priority based on dependents */
45
+ effectivePriority: Priority;
46
+ /** Whether this task's priority was influenced by dependents */
47
+ priorityInfluenced: boolean;
48
+ /** Aggregate complexity including dependent tasks */
49
+ aggregateComplexity?: number;
50
+ }
51
+ /**
52
+ * Configuration for priority calculation
53
+ */
54
+ export interface PriorityCalculationConfig {
55
+ /** Maximum depth for traversing dependency chain (default: 10) */
56
+ maxDepth: number;
57
+ /** Whether to include complexity aggregation (default: false) */
58
+ includeComplexity: boolean;
59
+ }
60
+ /**
61
+ * Default priority calculation configuration
62
+ */
63
+ export declare const DEFAULT_PRIORITY_CONFIG: PriorityCalculationConfig;
64
+ /**
65
+ * Service for computing dependency-based priority and complexity
66
+ */
67
+ export declare class PriorityService {
68
+ private readonly db;
69
+ constructor(db: StorageBackend);
70
+ /**
71
+ * Calculate the effective priority of a task based on its dependents.
72
+ *
73
+ * A task that blocks high-priority tasks should inherit that urgency.
74
+ * The effective priority is the minimum (highest urgency) of:
75
+ * - The task's own priority
76
+ * - The priorities of all tasks that directly or transitively depend on it
77
+ *
78
+ * @param taskId - The task to calculate effective priority for
79
+ * @param config - Optional configuration
80
+ * @returns EffectivePriorityResult with calculation details
81
+ */
82
+ calculateEffectivePriority(taskId: ElementId, config?: PriorityCalculationConfig): EffectivePriorityResult;
83
+ /**
84
+ * Calculate effective priorities for multiple tasks efficiently
85
+ *
86
+ * @param taskIds - Array of task IDs to calculate priorities for
87
+ * @param config - Optional configuration
88
+ * @returns Map of taskId to EffectivePriorityResult
89
+ */
90
+ calculateEffectivePriorities(taskIds: ElementId[], config?: PriorityCalculationConfig): Map<ElementId, EffectivePriorityResult>;
91
+ /**
92
+ * Calculate the aggregate complexity of a task including its blockers.
93
+ *
94
+ * This represents the total effort needed before this task can be considered
95
+ * truly "done" - including all tasks it's waiting on.
96
+ *
97
+ * Note: This calculates complexity of tasks that THIS task depends on (blockers),
98
+ * not tasks that depend on it.
99
+ *
100
+ * @param taskId - The task to calculate aggregate complexity for
101
+ * @param config - Optional configuration
102
+ * @returns AggregateComplexityResult with calculation details
103
+ */
104
+ calculateAggregateComplexity(taskId: ElementId, config?: PriorityCalculationConfig): AggregateComplexityResult;
105
+ /**
106
+ * Enhance an array of tasks with effective priority (for sorting)
107
+ *
108
+ * @param tasks - Array of tasks to enhance
109
+ * @param config - Optional configuration
110
+ * @returns Array of tasks with effectivePriority field
111
+ */
112
+ enhanceTasksWithEffectivePriority(tasks: Task[], config?: PriorityCalculationConfig): TaskWithEffectivePriority[];
113
+ /**
114
+ * Sort tasks by effective priority (highest priority first)
115
+ *
116
+ * @param tasks - Array of tasks with effective priority
117
+ * @returns Sorted array (mutates in place and returns reference)
118
+ */
119
+ sortByEffectivePriority(tasks: TaskWithEffectivePriority[]): TaskWithEffectivePriority[];
120
+ /**
121
+ * Get a task's priority and complexity from the database
122
+ */
123
+ private getTaskPriority;
124
+ /**
125
+ * Collect priorities of all tasks that depend on a given task (transitively).
126
+ *
127
+ * blockedId = the element waiting, blockerId = the element doing the blocking.
128
+ * To find tasks blocked by current.id, query WHERE blocker_id = current.id,
129
+ * then read blocked_id to get the dependent tasks.
130
+ */
131
+ private collectDependentPriorities;
132
+ /**
133
+ * Collect complexities of all tasks that this task depends on (blockers, transitively).
134
+ *
135
+ * blockedId = the element waiting, blockerId = the element doing the blocking.
136
+ * To find tasks that block current.id, query WHERE blocked_id = current.id,
137
+ * then read blocker_id to get the blocking tasks.
138
+ */
139
+ private collectBlockerComplexities;
140
+ }
141
+ /**
142
+ * Create a new PriorityService instance
143
+ */
144
+ export declare function createPriorityService(db: StorageBackend): PriorityService;
145
+ //# sourceMappingURL=priority-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority-service.d.ts","sourceRoot":"","sources":["../../src/services/priority-service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA2B9E;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,uCAAuC;IACvC,YAAY,EAAE,QAAQ,CAAC;IACvB,wEAAwE;IACxE,iBAAiB,EAAE,QAAQ,CAAC;IAC5B,0DAA0D;IAC1D,oBAAoB,EAAE,SAAS,EAAE,CAAC;IAClC,gEAAgE;IAChE,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,gCAAgC;IAChC,cAAc,EAAE,UAAU,CAAC;IAC3B,sDAAsD;IACtD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,cAAc,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,qBAAqB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,SAAS,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CACzE;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,IAAI;IACrD,sDAAsD;IACtD,iBAAiB,EAAE,QAAQ,CAAC;IAC5B,gEAAgE;IAChE,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qDAAqD;IACrD,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,yBAGrC,CAAC;AAMF;;GAEG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,cAAc;IAM/C;;;;;;;;;;;OAWG;IACH,0BAA0B,CACxB,MAAM,EAAE,SAAS,EACjB,MAAM,GAAE,yBAAmD,GAC1D,uBAAuB;IAuC1B;;;;;;OAMG;IACH,4BAA4B,CAC1B,OAAO,EAAE,SAAS,EAAE,EACpB,MAAM,GAAE,yBAAmD,GAC1D,GAAG,CAAC,SAAS,EAAE,uBAAuB,CAAC;IAc1C;;;;;;;;;;;;OAYG;IACH,4BAA4B,CAC1B,MAAM,EAAE,SAAS,EACjB,MAAM,GAAE,yBAAmD,GAC1D,yBAAyB;IAsC5B;;;;;;OAMG;IACH,iCAAiC,CAC/B,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,GAAE,yBAAmD,GAC1D,yBAAyB,EAAE;IAsB9B;;;;;OAKG;IACH,uBAAuB,CAAC,KAAK,EAAE,yBAAyB,EAAE,GAAG,yBAAyB,EAAE;IAexF;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IAuClC;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;CAsCnC;AAMD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,cAAc,GAAG,eAAe,CAEzE"}