@revealui/ai 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 (397) hide show
  1. package/LICENSE +22 -0
  2. package/LICENSE.commercial +112 -0
  3. package/README.md +314 -0
  4. package/dist/a2a/card.d.ts +26 -0
  5. package/dist/a2a/card.d.ts.map +1 -0
  6. package/dist/a2a/card.js +173 -0
  7. package/dist/a2a/handler.d.ts +26 -0
  8. package/dist/a2a/handler.d.ts.map +1 -0
  9. package/dist/a2a/handler.js +170 -0
  10. package/dist/a2a/index.d.ts +10 -0
  11. package/dist/a2a/index.d.ts.map +1 -0
  12. package/dist/a2a/index.js +9 -0
  13. package/dist/a2a/task-store.d.ts +42 -0
  14. package/dist/a2a/task-store.d.ts.map +1 -0
  15. package/dist/a2a/task-store.js +99 -0
  16. package/dist/audit/emitter.d.ts +34 -0
  17. package/dist/audit/emitter.d.ts.map +1 -0
  18. package/dist/audit/emitter.js +34 -0
  19. package/dist/audit/index.d.ts +44 -0
  20. package/dist/audit/index.d.ts.map +1 -0
  21. package/dist/audit/index.js +48 -0
  22. package/dist/audit/observer.d.ts +108 -0
  23. package/dist/audit/observer.d.ts.map +1 -0
  24. package/dist/audit/observer.js +271 -0
  25. package/dist/audit/policy.d.ts +70 -0
  26. package/dist/audit/policy.d.ts.map +1 -0
  27. package/dist/audit/policy.js +209 -0
  28. package/dist/audit/store.d.ts +42 -0
  29. package/dist/audit/store.d.ts.map +1 -0
  30. package/dist/audit/store.js +80 -0
  31. package/dist/audit/types.d.ts +169 -0
  32. package/dist/audit/types.d.ts.map +1 -0
  33. package/dist/audit/types.js +80 -0
  34. package/dist/client/hooks/index.d.ts +22 -0
  35. package/dist/client/hooks/index.d.ts.map +1 -0
  36. package/dist/client/hooks/index.js +21 -0
  37. package/dist/client/hooks/useAgentContext.d.ts +30 -0
  38. package/dist/client/hooks/useAgentContext.d.ts.map +1 -0
  39. package/dist/client/hooks/useAgentContext.js +161 -0
  40. package/dist/client/hooks/useAgentEvents.d.ts +126 -0
  41. package/dist/client/hooks/useAgentEvents.d.ts.map +1 -0
  42. package/dist/client/hooks/useAgentEvents.js +232 -0
  43. package/dist/client/hooks/useAgentStream.d.ts +44 -0
  44. package/dist/client/hooks/useAgentStream.d.ts.map +1 -0
  45. package/dist/client/hooks/useAgentStream.js +101 -0
  46. package/dist/client/hooks/useEpisodicMemory.d.ts +25 -0
  47. package/dist/client/hooks/useEpisodicMemory.d.ts.map +1 -0
  48. package/dist/client/hooks/useEpisodicMemory.js +174 -0
  49. package/dist/client/hooks/useWorkingMemory.d.ts +57 -0
  50. package/dist/client/hooks/useWorkingMemory.d.ts.map +1 -0
  51. package/dist/client/hooks/useWorkingMemory.js +276 -0
  52. package/dist/client/index.d.ts +14 -0
  53. package/dist/client/index.d.ts.map +1 -0
  54. package/dist/client/index.js +13 -0
  55. package/dist/embeddings/index.d.ts +51 -0
  56. package/dist/embeddings/index.d.ts.map +1 -0
  57. package/dist/embeddings/index.js +73 -0
  58. package/dist/index.d.ts +83 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +103 -0
  61. package/dist/inference/context-assembly.d.ts +27 -0
  62. package/dist/inference/context-assembly.d.ts.map +1 -0
  63. package/dist/inference/context-assembly.js +81 -0
  64. package/dist/inference/overflow-compressor.d.ts +17 -0
  65. package/dist/inference/overflow-compressor.d.ts.map +1 -0
  66. package/dist/inference/overflow-compressor.js +40 -0
  67. package/dist/inference/runRag.d.ts +35 -0
  68. package/dist/inference/runRag.d.ts.map +1 -0
  69. package/dist/inference/runRag.js +53 -0
  70. package/dist/ingestion/bm25.d.ts +29 -0
  71. package/dist/ingestion/bm25.d.ts.map +1 -0
  72. package/dist/ingestion/bm25.js +161 -0
  73. package/dist/ingestion/cms-indexer.d.ts +39 -0
  74. package/dist/ingestion/cms-indexer.d.ts.map +1 -0
  75. package/dist/ingestion/cms-indexer.js +74 -0
  76. package/dist/ingestion/file-parsers.d.ts +51 -0
  77. package/dist/ingestion/file-parsers.d.ts.map +1 -0
  78. package/dist/ingestion/file-parsers.js +247 -0
  79. package/dist/ingestion/hybrid-search.d.ts +22 -0
  80. package/dist/ingestion/hybrid-search.d.ts.map +1 -0
  81. package/dist/ingestion/hybrid-search.js +63 -0
  82. package/dist/ingestion/index.d.ts +9 -0
  83. package/dist/ingestion/index.d.ts.map +1 -0
  84. package/dist/ingestion/index.js +8 -0
  85. package/dist/ingestion/pipeline.d.ts +35 -0
  86. package/dist/ingestion/pipeline.d.ts.map +1 -0
  87. package/dist/ingestion/pipeline.js +114 -0
  88. package/dist/ingestion/rag-vector-service.d.ts +34 -0
  89. package/dist/ingestion/rag-vector-service.d.ts.map +1 -0
  90. package/dist/ingestion/rag-vector-service.js +98 -0
  91. package/dist/ingestion/reranker.d.ts +10 -0
  92. package/dist/ingestion/reranker.d.ts.map +1 -0
  93. package/dist/ingestion/reranker.js +41 -0
  94. package/dist/ingestion/text-splitter.d.ts +25 -0
  95. package/dist/ingestion/text-splitter.d.ts.map +1 -0
  96. package/dist/ingestion/text-splitter.js +119 -0
  97. package/dist/llm/cache-utils.d.ts +146 -0
  98. package/dist/llm/cache-utils.d.ts.map +1 -0
  99. package/dist/llm/cache-utils.js +204 -0
  100. package/dist/llm/client.d.ts +134 -0
  101. package/dist/llm/client.d.ts.map +1 -0
  102. package/dist/llm/client.js +497 -0
  103. package/dist/llm/key-validator.d.ts +25 -0
  104. package/dist/llm/key-validator.d.ts.map +1 -0
  105. package/dist/llm/key-validator.js +101 -0
  106. package/dist/llm/provider-health.d.ts +40 -0
  107. package/dist/llm/provider-health.d.ts.map +1 -0
  108. package/dist/llm/provider-health.js +97 -0
  109. package/dist/llm/providers/anthropic.d.ts +31 -0
  110. package/dist/llm/providers/anthropic.d.ts.map +1 -0
  111. package/dist/llm/providers/anthropic.js +248 -0
  112. package/dist/llm/providers/base.d.ts +111 -0
  113. package/dist/llm/providers/base.d.ts.map +1 -0
  114. package/dist/llm/providers/base.js +6 -0
  115. package/dist/llm/providers/groq.d.ts +23 -0
  116. package/dist/llm/providers/groq.d.ts.map +1 -0
  117. package/dist/llm/providers/groq.js +27 -0
  118. package/dist/llm/providers/ollama.d.ts +27 -0
  119. package/dist/llm/providers/ollama.d.ts.map +1 -0
  120. package/dist/llm/providers/ollama.js +48 -0
  121. package/dist/llm/providers/openai.d.ts +19 -0
  122. package/dist/llm/providers/openai.d.ts.map +1 -0
  123. package/dist/llm/providers/openai.js +245 -0
  124. package/dist/llm/providers/vultr.d.ts +18 -0
  125. package/dist/llm/providers/vultr.d.ts.map +1 -0
  126. package/dist/llm/providers/vultr.js +168 -0
  127. package/dist/llm/response-cache.d.ts +166 -0
  128. package/dist/llm/response-cache.d.ts.map +1 -0
  129. package/dist/llm/response-cache.js +233 -0
  130. package/dist/llm/semantic-cache.d.ts +179 -0
  131. package/dist/llm/semantic-cache.d.ts.map +1 -0
  132. package/dist/llm/semantic-cache.js +306 -0
  133. package/dist/llm/server.d.ts +14 -0
  134. package/dist/llm/server.d.ts.map +1 -0
  135. package/dist/llm/server.js +15 -0
  136. package/dist/llm/token-counter.d.ts +48 -0
  137. package/dist/llm/token-counter.d.ts.map +1 -0
  138. package/dist/llm/token-counter.js +77 -0
  139. package/dist/llm/workspace-provider-config.d.ts +38 -0
  140. package/dist/llm/workspace-provider-config.d.ts.map +1 -0
  141. package/dist/llm/workspace-provider-config.js +47 -0
  142. package/dist/memory/agent/context-manager.d.ts +148 -0
  143. package/dist/memory/agent/context-manager.d.ts.map +1 -0
  144. package/dist/memory/agent/context-manager.js +284 -0
  145. package/dist/memory/agent/index.d.ts +7 -0
  146. package/dist/memory/agent/index.d.ts.map +1 -0
  147. package/dist/memory/agent/index.js +6 -0
  148. package/dist/memory/crdt/index.d.ts +13 -0
  149. package/dist/memory/crdt/index.d.ts.map +1 -0
  150. package/dist/memory/crdt/index.js +12 -0
  151. package/dist/memory/crdt/lww-register.d.ts +108 -0
  152. package/dist/memory/crdt/lww-register.d.ts.map +1 -0
  153. package/dist/memory/crdt/lww-register.js +169 -0
  154. package/dist/memory/crdt/or-set.d.ts +141 -0
  155. package/dist/memory/crdt/or-set.d.ts.map +1 -0
  156. package/dist/memory/crdt/or-set.js +291 -0
  157. package/dist/memory/crdt/pn-counter.d.ts +116 -0
  158. package/dist/memory/crdt/pn-counter.d.ts.map +1 -0
  159. package/dist/memory/crdt/pn-counter.js +174 -0
  160. package/dist/memory/crdt/vector-clock.d.ts +115 -0
  161. package/dist/memory/crdt/vector-clock.d.ts.map +1 -0
  162. package/dist/memory/crdt/vector-clock.js +179 -0
  163. package/dist/memory/errors/index.d.ts +56 -0
  164. package/dist/memory/errors/index.d.ts.map +1 -0
  165. package/dist/memory/errors/index.js +85 -0
  166. package/dist/memory/index.d.ts +21 -0
  167. package/dist/memory/index.d.ts.map +1 -0
  168. package/dist/memory/index.js +20 -0
  169. package/dist/memory/persistence/crdt-persistence.d.ts +85 -0
  170. package/dist/memory/persistence/crdt-persistence.d.ts.map +1 -0
  171. package/dist/memory/persistence/crdt-persistence.js +204 -0
  172. package/dist/memory/persistence/index.d.ts +7 -0
  173. package/dist/memory/persistence/index.d.ts.map +1 -0
  174. package/dist/memory/persistence/index.js +6 -0
  175. package/dist/memory/preferences/index.d.ts +7 -0
  176. package/dist/memory/preferences/index.d.ts.map +1 -0
  177. package/dist/memory/preferences/index.js +6 -0
  178. package/dist/memory/preferences/user-preferences-manager.d.ts +133 -0
  179. package/dist/memory/preferences/user-preferences-manager.d.ts.map +1 -0
  180. package/dist/memory/preferences/user-preferences-manager.js +342 -0
  181. package/dist/memory/services/index.d.ts +8 -0
  182. package/dist/memory/services/index.d.ts.map +1 -0
  183. package/dist/memory/services/index.js +6 -0
  184. package/dist/memory/services/node-id-service.d.ts +75 -0
  185. package/dist/memory/services/node-id-service.d.ts.map +1 -0
  186. package/dist/memory/services/node-id-service.js +190 -0
  187. package/dist/memory/stores/episodic-memory.d.ts +182 -0
  188. package/dist/memory/stores/episodic-memory.d.ts.map +1 -0
  189. package/dist/memory/stores/episodic-memory.js +378 -0
  190. package/dist/memory/stores/index.d.ts +16 -0
  191. package/dist/memory/stores/index.d.ts.map +1 -0
  192. package/dist/memory/stores/index.js +15 -0
  193. package/dist/memory/stores/procedural-memory.d.ts +89 -0
  194. package/dist/memory/stores/procedural-memory.d.ts.map +1 -0
  195. package/dist/memory/stores/procedural-memory.js +152 -0
  196. package/dist/memory/stores/semantic-memory.d.ts +92 -0
  197. package/dist/memory/stores/semantic-memory.d.ts.map +1 -0
  198. package/dist/memory/stores/semantic-memory.js +155 -0
  199. package/dist/memory/stores/working-memory.d.ts +225 -0
  200. package/dist/memory/stores/working-memory.d.ts.map +1 -0
  201. package/dist/memory/stores/working-memory.js +336 -0
  202. package/dist/memory/utils/deep-clone.d.ts +10 -0
  203. package/dist/memory/utils/deep-clone.d.ts.map +1 -0
  204. package/dist/memory/utils/deep-clone.js +9 -0
  205. package/dist/memory/utils/index.d.ts +8 -0
  206. package/dist/memory/utils/index.d.ts.map +1 -0
  207. package/dist/memory/utils/index.js +7 -0
  208. package/dist/memory/utils/logger.d.ts +21 -0
  209. package/dist/memory/utils/logger.d.ts.map +1 -0
  210. package/dist/memory/utils/logger.js +62 -0
  211. package/dist/memory/utils/sql-helpers.d.ts +97 -0
  212. package/dist/memory/utils/sql-helpers.d.ts.map +1 -0
  213. package/dist/memory/utils/sql-helpers.js +214 -0
  214. package/dist/memory/utils/validation.d.ts +62 -0
  215. package/dist/memory/utils/validation.d.ts.map +1 -0
  216. package/dist/memory/utils/validation.js +244 -0
  217. package/dist/memory/vector/index.d.ts +12 -0
  218. package/dist/memory/vector/index.d.ts.map +1 -0
  219. package/dist/memory/vector/index.js +14 -0
  220. package/dist/memory/vector/vector-memory-service.d.ts +88 -0
  221. package/dist/memory/vector/vector-memory-service.d.ts.map +1 -0
  222. package/dist/memory/vector/vector-memory-service.js +335 -0
  223. package/dist/observability/logger.d.ts +79 -0
  224. package/dist/observability/logger.d.ts.map +1 -0
  225. package/dist/observability/logger.js +165 -0
  226. package/dist/observability/metrics.d.ts +43 -0
  227. package/dist/observability/metrics.d.ts.map +1 -0
  228. package/dist/observability/metrics.js +197 -0
  229. package/dist/observability/query.d.ts +150 -0
  230. package/dist/observability/query.d.ts.map +1 -0
  231. package/dist/observability/query.js +339 -0
  232. package/dist/observability/types.d.ts +140 -0
  233. package/dist/observability/types.d.ts.map +1 -0
  234. package/dist/observability/types.js +6 -0
  235. package/dist/orchestration/agent.d.ts +98 -0
  236. package/dist/orchestration/agent.d.ts.map +1 -0
  237. package/dist/orchestration/agent.js +6 -0
  238. package/dist/orchestration/defaults.d.ts +21 -0
  239. package/dist/orchestration/defaults.d.ts.map +1 -0
  240. package/dist/orchestration/defaults.js +22 -0
  241. package/dist/orchestration/memory-integration.d.ts +58 -0
  242. package/dist/orchestration/memory-integration.d.ts.map +1 -0
  243. package/dist/orchestration/memory-integration.js +130 -0
  244. package/dist/orchestration/orchestrator.d.ts +67 -0
  245. package/dist/orchestration/orchestrator.d.ts.map +1 -0
  246. package/dist/orchestration/orchestrator.js +174 -0
  247. package/dist/orchestration/runtime.d.ts +82 -0
  248. package/dist/orchestration/runtime.d.ts.map +1 -0
  249. package/dist/orchestration/runtime.js +251 -0
  250. package/dist/orchestration/streaming-runtime.d.ts +36 -0
  251. package/dist/orchestration/streaming-runtime.d.ts.map +1 -0
  252. package/dist/orchestration/streaming-runtime.js +175 -0
  253. package/dist/orchestration/ticket-agent.d.ts +70 -0
  254. package/dist/orchestration/ticket-agent.d.ts.map +1 -0
  255. package/dist/orchestration/ticket-agent.js +146 -0
  256. package/dist/skills/activation/index.d.ts +7 -0
  257. package/dist/skills/activation/index.d.ts.map +1 -0
  258. package/dist/skills/activation/index.js +6 -0
  259. package/dist/skills/activation/skill-activator.d.ts +68 -0
  260. package/dist/skills/activation/skill-activator.d.ts.map +1 -0
  261. package/dist/skills/activation/skill-activator.js +224 -0
  262. package/dist/skills/catalog/catalog-search.d.ts +55 -0
  263. package/dist/skills/catalog/catalog-search.d.ts.map +1 -0
  264. package/dist/skills/catalog/catalog-search.js +111 -0
  265. package/dist/skills/catalog/catalog-types.d.ts +81 -0
  266. package/dist/skills/catalog/catalog-types.d.ts.map +1 -0
  267. package/dist/skills/catalog/catalog-types.js +66 -0
  268. package/dist/skills/catalog/index.d.ts +9 -0
  269. package/dist/skills/catalog/index.d.ts.map +1 -0
  270. package/dist/skills/catalog/index.js +7 -0
  271. package/dist/skills/catalog/vercel-catalog.d.ts +42 -0
  272. package/dist/skills/catalog/vercel-catalog.d.ts.map +1 -0
  273. package/dist/skills/catalog/vercel-catalog.js +189 -0
  274. package/dist/skills/compat/index.d.ts +9 -0
  275. package/dist/skills/compat/index.d.ts.map +1 -0
  276. package/dist/skills/compat/index.js +8 -0
  277. package/dist/skills/compat/skill-enhancer.d.ts +37 -0
  278. package/dist/skills/compat/skill-enhancer.d.ts.map +1 -0
  279. package/dist/skills/compat/skill-enhancer.js +76 -0
  280. package/dist/skills/compat/tool-mapper.d.ts +61 -0
  281. package/dist/skills/compat/tool-mapper.d.ts.map +1 -0
  282. package/dist/skills/compat/tool-mapper.js +168 -0
  283. package/dist/skills/compat/vercel-compat.d.ts +33 -0
  284. package/dist/skills/compat/vercel-compat.d.ts.map +1 -0
  285. package/dist/skills/compat/vercel-compat.js +132 -0
  286. package/dist/skills/index.d.ts +40 -0
  287. package/dist/skills/index.d.ts.map +1 -0
  288. package/dist/skills/index.js +47 -0
  289. package/dist/skills/integration/agent-skill-provider.d.ts +94 -0
  290. package/dist/skills/integration/agent-skill-provider.d.ts.map +1 -0
  291. package/dist/skills/integration/agent-skill-provider.js +161 -0
  292. package/dist/skills/integration/index.d.ts +7 -0
  293. package/dist/skills/integration/index.d.ts.map +1 -0
  294. package/dist/skills/integration/index.js +6 -0
  295. package/dist/skills/loader/github-loader.d.ts +61 -0
  296. package/dist/skills/loader/github-loader.d.ts.map +1 -0
  297. package/dist/skills/loader/github-loader.js +176 -0
  298. package/dist/skills/loader/index.d.ts +10 -0
  299. package/dist/skills/loader/index.d.ts.map +1 -0
  300. package/dist/skills/loader/index.js +9 -0
  301. package/dist/skills/loader/local-loader.d.ts +56 -0
  302. package/dist/skills/loader/local-loader.d.ts.map +1 -0
  303. package/dist/skills/loader/local-loader.js +186 -0
  304. package/dist/skills/loader/vercel-loader.d.ts +64 -0
  305. package/dist/skills/loader/vercel-loader.d.ts.map +1 -0
  306. package/dist/skills/loader/vercel-loader.js +313 -0
  307. package/dist/skills/loader/vercel-types.d.ts +64 -0
  308. package/dist/skills/loader/vercel-types.d.ts.map +1 -0
  309. package/dist/skills/loader/vercel-types.js +55 -0
  310. package/dist/skills/parser/index.d.ts +7 -0
  311. package/dist/skills/parser/index.d.ts.map +1 -0
  312. package/dist/skills/parser/index.js +6 -0
  313. package/dist/skills/parser/skill-md-parser.d.ts +64 -0
  314. package/dist/skills/parser/skill-md-parser.d.ts.map +1 -0
  315. package/dist/skills/parser/skill-md-parser.js +242 -0
  316. package/dist/skills/registry/index.d.ts +7 -0
  317. package/dist/skills/registry/index.d.ts.map +1 -0
  318. package/dist/skills/registry/index.js +6 -0
  319. package/dist/skills/registry/skill-registry.d.ts +133 -0
  320. package/dist/skills/registry/skill-registry.d.ts.map +1 -0
  321. package/dist/skills/registry/skill-registry.js +373 -0
  322. package/dist/skills/types.d.ts +216 -0
  323. package/dist/skills/types.d.ts.map +1 -0
  324. package/dist/skills/types.js +176 -0
  325. package/dist/templates/agent-spec.d.ts +138 -0
  326. package/dist/templates/agent-spec.d.ts.map +1 -0
  327. package/dist/templates/agent-spec.js +138 -0
  328. package/dist/templates/index.d.ts +56 -0
  329. package/dist/templates/index.d.ts.map +1 -0
  330. package/dist/templates/index.js +58 -0
  331. package/dist/templates/prompt-spec.d.ts +140 -0
  332. package/dist/templates/prompt-spec.d.ts.map +1 -0
  333. package/dist/templates/prompt-spec.js +210 -0
  334. package/dist/templates/skill-spec.d.ts +106 -0
  335. package/dist/templates/skill-spec.d.ts.map +1 -0
  336. package/dist/templates/skill-spec.js +119 -0
  337. package/dist/tools/base.d.ts +74 -0
  338. package/dist/tools/base.d.ts.map +1 -0
  339. package/dist/tools/base.js +6 -0
  340. package/dist/tools/cms/collection-tools.d.ts +36 -0
  341. package/dist/tools/cms/collection-tools.d.ts.map +1 -0
  342. package/dist/tools/cms/collection-tools.js +178 -0
  343. package/dist/tools/cms/factory.d.ts +89 -0
  344. package/dist/tools/cms/factory.d.ts.map +1 -0
  345. package/dist/tools/cms/factory.js +462 -0
  346. package/dist/tools/cms/global-tools.d.ts +21 -0
  347. package/dist/tools/cms/global-tools.d.ts.map +1 -0
  348. package/dist/tools/cms/global-tools.js +92 -0
  349. package/dist/tools/cms/index.d.ts +11 -0
  350. package/dist/tools/cms/index.d.ts.map +1 -0
  351. package/dist/tools/cms/index.js +11 -0
  352. package/dist/tools/cms/media-tools.d.ts +31 -0
  353. package/dist/tools/cms/media-tools.d.ts.map +1 -0
  354. package/dist/tools/cms/media-tools.js +140 -0
  355. package/dist/tools/cms/user-tools.d.ts +31 -0
  356. package/dist/tools/cms/user-tools.d.ts.map +1 -0
  357. package/dist/tools/cms/user-tools.js +135 -0
  358. package/dist/tools/deduplicator.d.ts +19 -0
  359. package/dist/tools/deduplicator.d.ts.map +1 -0
  360. package/dist/tools/deduplicator.js +53 -0
  361. package/dist/tools/document-summarizer.d.ts +11 -0
  362. package/dist/tools/document-summarizer.d.ts.map +1 -0
  363. package/dist/tools/document-summarizer.js +82 -0
  364. package/dist/tools/mcp-adapter.d.ts +66 -0
  365. package/dist/tools/mcp-adapter.d.ts.map +1 -0
  366. package/dist/tools/mcp-adapter.js +152 -0
  367. package/dist/tools/memory/index.d.ts +3 -0
  368. package/dist/tools/memory/index.d.ts.map +1 -0
  369. package/dist/tools/memory/index.js +1 -0
  370. package/dist/tools/memory/store-memory.d.ts +39 -0
  371. package/dist/tools/memory/store-memory.d.ts.map +1 -0
  372. package/dist/tools/memory/store-memory.js +94 -0
  373. package/dist/tools/registry.d.ts +14 -0
  374. package/dist/tools/registry.d.ts.map +1 -0
  375. package/dist/tools/registry.js +48 -0
  376. package/dist/tools/ticket-tools.d.ts +31 -0
  377. package/dist/tools/ticket-tools.d.ts.map +1 -0
  378. package/dist/tools/ticket-tools.js +74 -0
  379. package/dist/tools/web/duck-duck-go.d.ts +52 -0
  380. package/dist/tools/web/duck-duck-go.d.ts.map +1 -0
  381. package/dist/tools/web/duck-duck-go.js +202 -0
  382. package/dist/tools/web/exa.d.ts +34 -0
  383. package/dist/tools/web/exa.d.ts.map +1 -0
  384. package/dist/tools/web/exa.js +80 -0
  385. package/dist/tools/web/index.d.ts +6 -0
  386. package/dist/tools/web/index.d.ts.map +1 -0
  387. package/dist/tools/web/index.js +4 -0
  388. package/dist/tools/web/scraper.d.ts +9 -0
  389. package/dist/tools/web/scraper.d.ts.map +1 -0
  390. package/dist/tools/web/scraper.js +118 -0
  391. package/dist/tools/web/tavily.d.ts +32 -0
  392. package/dist/tools/web/tavily.d.ts.map +1 -0
  393. package/dist/tools/web/tavily.js +73 -0
  394. package/dist/tools/web/types.d.ts +31 -0
  395. package/dist/tools/web/types.d.ts.map +1 -0
  396. package/dist/tools/web/types.js +9 -0
  397. package/package.json +143 -0
@@ -0,0 +1,342 @@
1
+ /**
2
+ * User Preferences Manager
3
+ *
4
+ * Manages user preferences with CRDT support for conflict-free updates
5
+ * from multiple devices. Uses LWWRegister for last-writer-wins semantics.
6
+ */
7
+ import { UserPreferencesSchema } from '@revealui/contracts/entities';
8
+ import { eq, users } from '@revealui/db/schema';
9
+ import { LWWRegister } from '../crdt/lww-register.js';
10
+ import { DatabaseConnectionError, DatabaseConstraintError, DatabaseOperationError, NotFoundError, ValidationError, } from '../errors/index.js';
11
+ import { deepClone } from '../utils/deep-clone.js';
12
+ import { createLogger } from '../utils/logger.js';
13
+ import { findUserById } from '../utils/sql-helpers.js';
14
+ // =============================================================================
15
+ // User Preferences Manager
16
+ // =============================================================================
17
+ /**
18
+ * Manages user preferences with CRDT support.
19
+ *
20
+ * Note: This implementation stores CRDT state directly in users.preferences JSONB field.
21
+ * All preferences must be in CRDT format - legacy format is not supported.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const manager = new UserPreferencesManager('user-123', 'node-abc', db)
26
+ * await manager.load()
27
+ *
28
+ * await manager.updatePreferences({ theme: 'dark' })
29
+ * const prefs = manager.getPreferences()
30
+ *
31
+ * await manager.save()
32
+ * ```
33
+ */
34
+ export class UserPreferencesManager {
35
+ preferences;
36
+ userId;
37
+ nodeId;
38
+ db;
39
+ logger = createLogger('[UserPreferences]');
40
+ /**
41
+ * Creates a new UserPreferencesManager.
42
+ *
43
+ * @param userId - User identifier
44
+ * @param nodeId - Node identifier (for CRDT operations)
45
+ * @param db - Database client
46
+ */
47
+ constructor(userId, nodeId, db) {
48
+ this.userId = userId;
49
+ this.nodeId = nodeId;
50
+ this.db = db;
51
+ // Initialize with default preferences
52
+ const defaultPrefs = {
53
+ theme: 'system',
54
+ language: 'en',
55
+ timezone: 'UTC',
56
+ };
57
+ this.preferences = new LWWRegister(nodeId, defaultPrefs);
58
+ }
59
+ /**
60
+ * Gets the current preferences.
61
+ *
62
+ * @returns Current user preferences
63
+ */
64
+ getPreferences() {
65
+ return this.preferences.get();
66
+ }
67
+ /**
68
+ * Updates preferences with partial data.
69
+ * Merges with existing preferences.
70
+ *
71
+ * @param updates - Partial preferences updates
72
+ */
73
+ updatePreferences(updates) {
74
+ const current = this.preferences.get();
75
+ const merged = {
76
+ ...current,
77
+ ...updates,
78
+ // Deep merge for nested objects
79
+ notifications: updates.notifications
80
+ ? { ...current.notifications, ...updates.notifications }
81
+ : current.notifications,
82
+ editor: updates.editor ? { ...current.editor, ...updates.editor } : current.editor,
83
+ ai: updates.ai ? { ...current.ai, ...updates.ai } : current.ai,
84
+ };
85
+ // Validate before setting
86
+ const validationResult = UserPreferencesSchema.safeParse(merged);
87
+ if (!validationResult.success) {
88
+ throw new ValidationError(`Invalid preferences: ${validationResult.error.message}`);
89
+ }
90
+ this.preferences.set(validationResult.data);
91
+ }
92
+ /**
93
+ * Sets entire preferences object.
94
+ *
95
+ * @param preferences - Complete preferences object
96
+ */
97
+ setPreferences(preferences) {
98
+ // Validate before setting
99
+ const validationResult = UserPreferencesSchema.safeParse(preferences);
100
+ if (!validationResult.success) {
101
+ throw new ValidationError(`Invalid preferences: ${validationResult.error.message}`);
102
+ }
103
+ this.preferences.set(validationResult.data);
104
+ }
105
+ /**
106
+ * Gets a specific preference value.
107
+ *
108
+ * @param key - Preference key (supports dot notation for nested keys)
109
+ * @returns Preference value or undefined
110
+ */
111
+ getPreference(key) {
112
+ const prefs = this.preferences.get();
113
+ const keys = key.split('.');
114
+ let value = prefs;
115
+ for (const k of keys) {
116
+ if (value && typeof value === 'object' && k in value) {
117
+ value = value[k];
118
+ }
119
+ else {
120
+ return undefined;
121
+ }
122
+ }
123
+ return value;
124
+ }
125
+ /**
126
+ * Sets a specific preference value.
127
+ *
128
+ * @param key - Preference key (supports dot notation for nested keys)
129
+ * @param value - Preference value
130
+ */
131
+ setPreference(key, value) {
132
+ // Deep clone to avoid mutations
133
+ const prefs = deepClone(this.preferences.get());
134
+ const keys = key.split('.');
135
+ const lastKey = keys[keys.length - 1];
136
+ if (!lastKey) {
137
+ throw new ValidationError(`Invalid preference key: "${key}"`);
138
+ }
139
+ const parentKeys = keys.slice(0, -1);
140
+ // Navigate to parent object in cloned structure
141
+ let parent = prefs;
142
+ for (const k of parentKeys) {
143
+ if (!(k in parent) || typeof parent[k] !== 'object' || parent[k] === null) {
144
+ parent[k] = {};
145
+ }
146
+ parent = parent[k];
147
+ }
148
+ // Set the value in cloned structure
149
+ parent[lastKey] = value;
150
+ // Validate and set
151
+ const validationResult = UserPreferencesSchema.safeParse(prefs);
152
+ if (!validationResult.success) {
153
+ throw new ValidationError(`Invalid preferences after update: ${validationResult.error.message}`);
154
+ }
155
+ this.preferences.set(validationResult.data);
156
+ }
157
+ /**
158
+ * Merges another UserPreferencesManager into this one.
159
+ * Uses CRDT merge for conflict resolution.
160
+ *
161
+ * @param other - UserPreferencesManager to merge
162
+ * @returns New merged UserPreferencesManager
163
+ */
164
+ merge(other) {
165
+ const merged = new UserPreferencesManager(this.userId, this.nodeId, this.db);
166
+ merged.preferences = this.preferences.merge(other.preferences);
167
+ return merged;
168
+ }
169
+ /**
170
+ * Loads preferences from database.
171
+ * Stores CRDT state directly in users.preferences JSONB field.
172
+ * Requires preferences to be in CRDT format.
173
+ *
174
+ * @throws DatabaseConnectionError if database connection fails
175
+ * @throws DatabaseOperationError if database operation fails
176
+ * @throws ValidationError if preferences are not in CRDT format
177
+ */
178
+ async load() {
179
+ try {
180
+ // Load user record (using raw SQL for Neon HTTP compatibility)
181
+ const user = await findUserById(this.db, this.userId);
182
+ if (!user) {
183
+ // User doesn't exist, use defaults
184
+ return;
185
+ }
186
+ // Check if preferences exist
187
+ if (user.preferences && typeof user.preferences === 'object' && user.preferences !== null) {
188
+ const prefsRecord = user.preferences;
189
+ // Check for CRDT state in _crdt field
190
+ if (prefsRecord._crdt && typeof prefsRecord._crdt === 'object') {
191
+ const crdtData = prefsRecord._crdt;
192
+ const lwwData = crdtData.lww_register;
193
+ if (lwwData && 'value' in lwwData) {
194
+ const validationResult = UserPreferencesSchema.safeParse(lwwData.value);
195
+ if (validationResult.success) {
196
+ this.preferences = LWWRegister.fromData(lwwData);
197
+ return;
198
+ }
199
+ }
200
+ }
201
+ // Preferences exist but are not in CRDT format
202
+ // Per legacy code removal policy, we do not support legacy format
203
+ throw new ValidationError(`User preferences for ${this.userId} are not in valid CRDT format. ` +
204
+ `Expected CRDT structure with _crdt.lww_register.value, but got: ${JSON.stringify(user.preferences).substring(0, 100)}. ` +
205
+ `All preferences must be stored in CRDT format.`);
206
+ }
207
+ }
208
+ catch (error) {
209
+ // Handle specific error types
210
+ if (error instanceof ValidationError) {
211
+ throw error;
212
+ }
213
+ // Database errors
214
+ if (error instanceof Error) {
215
+ const errorMessage = error.message.toLowerCase();
216
+ if (errorMessage.includes('connection') ||
217
+ errorMessage.includes('timeout') ||
218
+ errorMessage.includes('econnrefused') ||
219
+ errorMessage.includes('connect econnrefused')) {
220
+ this.logger.error(`Database connection error loading preferences for user ${this.userId}:`, error);
221
+ throw new DatabaseConnectionError('Failed to load user preferences', error);
222
+ }
223
+ if (errorMessage.includes('violates') ||
224
+ errorMessage.includes('constraint') ||
225
+ errorMessage.includes('foreign key')) {
226
+ this.logger.error(`Database constraint error loading preferences for user ${this.userId}:`, error);
227
+ throw new DatabaseConstraintError('Failed to load user preferences', error);
228
+ }
229
+ }
230
+ // Generic database operation error
231
+ this.logger.error(`Failed to load preferences for user ${this.userId}:`, error);
232
+ throw new DatabaseOperationError('Failed to load user preferences', error instanceof Error ? error : new Error(String(error)));
233
+ }
234
+ }
235
+ /**
236
+ * Saves preferences to database.
237
+ * Stores CRDT state directly in users.preferences JSONB field.
238
+ *
239
+ * @throws NotFoundError if user does not exist
240
+ * @throws DatabaseConnectionError if database connection fails
241
+ * @throws DatabaseConstraintError if database constraint violation occurs
242
+ * @throws DatabaseOperationError if database operation fails
243
+ */
244
+ async save() {
245
+ try {
246
+ // Store CRDT state in users.preferences JSONB field
247
+ // Structure: { _crdt: { lww_register: {...} } }
248
+ const crdtData = this.preferences.toData();
249
+ const preferencesValue = {
250
+ // biome-ignore lint/style/useNamingConvention: _crdt is the CRDT state storage key — internal convention that must not be renamed
251
+ _crdt: {
252
+ lww_register: crdtData,
253
+ },
254
+ };
255
+ // Check if user exists (using raw SQL for Neon HTTP compatibility)
256
+ const existingUser = await findUserById(this.db, this.userId);
257
+ if (!existingUser) {
258
+ throw new NotFoundError(`User ${this.userId}`);
259
+ }
260
+ // Update users table with CRDT state in preferences JSONB
261
+ await this.db
262
+ .update(users)
263
+ .set({
264
+ preferences: preferencesValue,
265
+ updatedAt: new Date(),
266
+ })
267
+ .where(eq(users.id, this.userId));
268
+ }
269
+ catch (error) {
270
+ // Handle specific error types (re-throw as-is)
271
+ if (error instanceof NotFoundError ||
272
+ error instanceof DatabaseConnectionError ||
273
+ error instanceof DatabaseConstraintError ||
274
+ error instanceof DatabaseOperationError) {
275
+ throw error;
276
+ }
277
+ // Handle database errors
278
+ if (error instanceof Error) {
279
+ const errorMessage = error.message.toLowerCase();
280
+ if (errorMessage.includes('connection') ||
281
+ errorMessage.includes('timeout') ||
282
+ errorMessage.includes('econnrefused') ||
283
+ errorMessage.includes('connect econnrefused')) {
284
+ this.logger.error(`Database connection error saving preferences for user ${this.userId}:`, error);
285
+ throw new DatabaseConnectionError('Failed to save user preferences', error);
286
+ }
287
+ if (errorMessage.includes('violates') ||
288
+ errorMessage.includes('constraint') ||
289
+ errorMessage.includes('foreign key') ||
290
+ errorMessage.includes('duplicate')) {
291
+ this.logger.error(`Database constraint error saving preferences for user ${this.userId}:`, error);
292
+ throw new DatabaseConstraintError('Failed to save user preferences', error);
293
+ }
294
+ }
295
+ // Generic database operation error
296
+ this.logger.error(`Failed to save preferences for user ${this.userId}:`, error);
297
+ throw new DatabaseOperationError('Failed to save user preferences', error instanceof Error ? error : new Error(String(error)));
298
+ }
299
+ }
300
+ /**
301
+ * Serializes preferences to plain object.
302
+ *
303
+ * @returns Serialized data
304
+ */
305
+ toData() {
306
+ return this.preferences.toData();
307
+ }
308
+ /**
309
+ * Deserializes preferences from plain object.
310
+ *
311
+ * @param data - Serialized data
312
+ * @param userId - User identifier
313
+ * @param nodeId - Node identifier
314
+ * @param db - Database client
315
+ * @returns New UserPreferencesManager instance
316
+ */
317
+ static fromData(data, userId, nodeId, db) {
318
+ const manager = new UserPreferencesManager(userId, nodeId, db);
319
+ manager.preferences = LWWRegister.fromData(data);
320
+ return manager;
321
+ }
322
+ /**
323
+ * Creates a copy of this UserPreferencesManager.
324
+ *
325
+ * @returns New UserPreferencesManager with same state
326
+ */
327
+ clone() {
328
+ return UserPreferencesManager.fromData(this.toData(), this.userId, this.nodeId, this.db);
329
+ }
330
+ /**
331
+ * Gets the user ID.
332
+ */
333
+ getUserId() {
334
+ return this.userId;
335
+ }
336
+ /**
337
+ * Gets the node ID.
338
+ */
339
+ getNodeId() {
340
+ return this.nodeId;
341
+ }
342
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Services
3
+ *
4
+ * Business logic services for memory operations.
5
+ */
6
+ export type { EntityType } from './node-id-service.js';
7
+ export { NodeIdService } from './node-id-service.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/memory/services/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Services
3
+ *
4
+ * Business logic services for memory operations.
5
+ */
6
+ export { NodeIdService } from './node-id-service.js';
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Node ID Service
3
+ *
4
+ * Provides deterministic node IDs for CRDT operations using a hybrid approach:
5
+ * - Primary: SHA-256 hash of entity ID (fast, deterministic, no DB lookup)
6
+ * - Fallback: Database table for collision resolution and manual management
7
+ *
8
+ * This ensures:
9
+ * - Same entity always gets same node ID (deterministic)
10
+ * - Collision-resistant (SHA-256 + DB fallback)
11
+ * - Fast (hash is primary, DB only on collision)
12
+ */
13
+ import type { Database } from '@revealui/db/client';
14
+ export type EntityType = 'session' | 'user';
15
+ /**
16
+ * Node ID Service
17
+ */
18
+ export declare class NodeIdService {
19
+ private db;
20
+ constructor(db: Database);
21
+ /**
22
+ * Gets or creates a node ID for an entity.
23
+ *
24
+ * Strategy:
25
+ * 1. Generate SHA-256 hash of entityId
26
+ * 2. Check database for existing mapping
27
+ * 3. If exists, return stored nodeId
28
+ * 4. If not, create new mapping with UUID
29
+ * 5. Handle collisions (same hash, different entityId)
30
+ *
31
+ * @param entityType - Type of entity ('session' or 'user')
32
+ * @param entityId - Entity identifier (sessionId or userId)
33
+ * @returns Node ID (UUID string)
34
+ */
35
+ getNodeId(entityType: EntityType, entityId: string): Promise<string>;
36
+ /**
37
+ * Resolves a hash collision (same hash, different entityId).
38
+ *
39
+ * Strategy: Generate a new hash using entityType + entityId to ensure uniqueness.
40
+ *
41
+ * @param hash - Original hash that collided
42
+ * @param entityType - Type of entity
43
+ * @param entityId - Entity identifier
44
+ * @param attempt - Current collision resolution attempt (default: 1)
45
+ * @returns Node ID (UUID string)
46
+ * @throws Error if max collision attempts exceeded
47
+ */
48
+ private resolveCollision;
49
+ /**
50
+ * Generates SHA-256 hash of entity ID.
51
+ *
52
+ * @param entityId - Entity identifier
53
+ * @returns Hexadecimal hash string (64 characters)
54
+ */
55
+ private hashEntityId;
56
+ /**
57
+ * Validates input parameters.
58
+ *
59
+ * @param entityType - Type of entity
60
+ * @param entityId - Entity identifier
61
+ * @throws Error if inputs are invalid
62
+ */
63
+ private validateInputs;
64
+ /**
65
+ * Retry wrapper for database operations with exponential backoff.
66
+ *
67
+ * @param operation - Async operation to retry
68
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
69
+ * @param baseDelay - Base delay in milliseconds for exponential backoff (default: 100)
70
+ * @returns Result of the operation
71
+ * @throws Error if all retries fail
72
+ */
73
+ private withRetry;
74
+ }
75
+ //# sourceMappingURL=node-id-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-id-service.d.ts","sourceRoot":"","sources":["../../../src/memory/services/node-id-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAInD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,MAAM,CAAA;AAE3C;;GAEG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAEhC;;;;;;;;;;;;;OAaG;IACG,SAAS,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoC1E;;;;;;;;;;;OAWG;YACW,gBAAgB;IAsD9B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAmBtB;;;;;;;;OAQG;YACW,SAAS;CAuCxB"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Node ID Service
3
+ *
4
+ * Provides deterministic node IDs for CRDT operations using a hybrid approach:
5
+ * - Primary: SHA-256 hash of entity ID (fast, deterministic, no DB lookup)
6
+ * - Fallback: Database table for collision resolution and manual management
7
+ *
8
+ * This ensures:
9
+ * - Same entity always gets same node ID (deterministic)
10
+ * - Collision-resistant (SHA-256 + DB fallback)
11
+ * - Fast (hash is primary, DB only on collision)
12
+ */
13
+ import { createHash, randomUUID } from 'node:crypto';
14
+ import { logger } from '@revealui/core/utils/logger';
15
+ import { nodeIdMappings } from '@revealui/db/schema';
16
+ import { findNodeIdMappingByHash } from '../utils/sql-helpers.js';
17
+ /**
18
+ * Node ID Service
19
+ */
20
+ export class NodeIdService {
21
+ db;
22
+ constructor(db) {
23
+ this.db = db;
24
+ }
25
+ /**
26
+ * Gets or creates a node ID for an entity.
27
+ *
28
+ * Strategy:
29
+ * 1. Generate SHA-256 hash of entityId
30
+ * 2. Check database for existing mapping
31
+ * 3. If exists, return stored nodeId
32
+ * 4. If not, create new mapping with UUID
33
+ * 5. Handle collisions (same hash, different entityId)
34
+ *
35
+ * @param entityType - Type of entity ('session' or 'user')
36
+ * @param entityId - Entity identifier (sessionId or userId)
37
+ * @returns Node ID (UUID string)
38
+ */
39
+ async getNodeId(entityType, entityId) {
40
+ return this.withRetry(async () => {
41
+ // Validate inputs
42
+ this.validateInputs(entityType, entityId);
43
+ // Generate SHA-256 hash
44
+ const hash = this.hashEntityId(entityId);
45
+ // Check database for existing mapping (using raw SQL for Neon HTTP compatibility)
46
+ const existing = await findNodeIdMappingByHash(this.db, hash);
47
+ if (existing) {
48
+ // Verify entityId matches (collision detection)
49
+ if (existing.entityId !== entityId || existing.entityType !== entityType) {
50
+ // Collision detected - resolve it
51
+ return this.resolveCollision(hash, entityType, entityId, 1);
52
+ }
53
+ // Return existing node ID
54
+ return existing.nodeId;
55
+ }
56
+ // No existing mapping - create new one
57
+ const newNodeId = randomUUID();
58
+ await this.db.insert(nodeIdMappings).values({
59
+ id: hash,
60
+ entityType,
61
+ entityId,
62
+ nodeId: newNodeId,
63
+ createdAt: new Date(),
64
+ updatedAt: new Date(),
65
+ });
66
+ return newNodeId;
67
+ });
68
+ }
69
+ /**
70
+ * Resolves a hash collision (same hash, different entityId).
71
+ *
72
+ * Strategy: Generate a new hash using entityType + entityId to ensure uniqueness.
73
+ *
74
+ * @param hash - Original hash that collided
75
+ * @param entityType - Type of entity
76
+ * @param entityId - Entity identifier
77
+ * @param attempt - Current collision resolution attempt (default: 1)
78
+ * @returns Node ID (UUID string)
79
+ * @throws Error if max collision attempts exceeded
80
+ */
81
+ async resolveCollision(hash, entityType, entityId, attempt = 1) {
82
+ const MaxCollisionAttempts = 10;
83
+ if (attempt > MaxCollisionAttempts) {
84
+ throw new Error(`Failed to resolve node ID collision after ${MaxCollisionAttempts} attempts. ` +
85
+ `This is extremely rare. Please contact support.`);
86
+ }
87
+ // Log collision for monitoring
88
+ logger.warn('Node ID collision detected', {
89
+ attempt,
90
+ maxAttempts: MaxCollisionAttempts,
91
+ hash,
92
+ entityType,
93
+ entityId,
94
+ });
95
+ // Generate collision-resistant hash using entityType + entityId
96
+ const collisionHash = this.hashEntityId(`${entityType}:${entityId}:${attempt}`);
97
+ // Check if collision hash already exists (using raw SQL for Neon HTTP compatibility)
98
+ const existing = await findNodeIdMappingByHash(this.db, collisionHash);
99
+ if (existing) {
100
+ // Verify this is actually our entity (not another collision)
101
+ if (existing.entityId === entityId && existing.entityType === entityType) {
102
+ // This is our mapping - use it
103
+ return existing.nodeId;
104
+ }
105
+ // Another collision - recurse with incremented attempt
106
+ return this.resolveCollision(collisionHash, entityType, entityId, attempt + 1);
107
+ }
108
+ // Create new mapping with collision hash
109
+ const newNodeId = randomUUID();
110
+ await this.db.insert(nodeIdMappings).values({
111
+ id: collisionHash,
112
+ entityType,
113
+ entityId,
114
+ nodeId: newNodeId,
115
+ createdAt: new Date(),
116
+ updatedAt: new Date(),
117
+ });
118
+ return newNodeId;
119
+ }
120
+ /**
121
+ * Generates SHA-256 hash of entity ID.
122
+ *
123
+ * @param entityId - Entity identifier
124
+ * @returns Hexadecimal hash string (64 characters)
125
+ */
126
+ hashEntityId(entityId) {
127
+ return createHash('sha256').update(entityId).digest('hex');
128
+ }
129
+ /**
130
+ * Validates input parameters.
131
+ *
132
+ * @param entityType - Type of entity
133
+ * @param entityId - Entity identifier
134
+ * @throws Error if inputs are invalid
135
+ */
136
+ validateInputs(entityType, entityId) {
137
+ if (entityType !== 'session' && entityType !== 'user') {
138
+ throw new Error(`Invalid entityType: ${entityType}. Must be 'session' or 'user'`);
139
+ }
140
+ if (!entityId || typeof entityId !== 'string' || entityId.trim().length === 0) {
141
+ throw new Error(`Invalid entityId: must be a non-empty string`);
142
+ }
143
+ // Additional validation: entityId should be reasonable length
144
+ // Very long entityIds might indicate an attack or data corruption
145
+ const MaxEntityIdLength = 1000;
146
+ if (entityId.length > MaxEntityIdLength) {
147
+ throw new Error(`Invalid entityId: length ${entityId.length} exceeds maximum of ${MaxEntityIdLength} characters`);
148
+ }
149
+ }
150
+ /**
151
+ * Retry wrapper for database operations with exponential backoff.
152
+ *
153
+ * @param operation - Async operation to retry
154
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
155
+ * @param baseDelay - Base delay in milliseconds for exponential backoff (default: 100)
156
+ * @returns Result of the operation
157
+ * @throws Error if all retries fail
158
+ */
159
+ async withRetry(operation, maxRetries = 3, baseDelay = 100) {
160
+ let lastError = null;
161
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
162
+ try {
163
+ return await operation();
164
+ }
165
+ catch (error) {
166
+ lastError = error instanceof Error ? error : new Error(String(error));
167
+ // Don't retry on validation errors
168
+ if (lastError.message.includes('Invalid')) {
169
+ throw lastError;
170
+ }
171
+ // Don't retry on collision resolution limit exceeded
172
+ if (lastError.message.includes('Failed to resolve node ID collision')) {
173
+ throw lastError;
174
+ }
175
+ // Exponential backoff: 100ms, 200ms, 400ms
176
+ if (attempt < maxRetries - 1) {
177
+ const delay = baseDelay * 2 ** attempt;
178
+ logger.warn('Database operation failed, retrying', {
179
+ attempt: attempt + 1,
180
+ maxRetries,
181
+ delay,
182
+ error: lastError.message,
183
+ });
184
+ await new Promise((resolve) => setTimeout(resolve, delay));
185
+ }
186
+ }
187
+ }
188
+ throw new Error(`Database operation failed after ${maxRetries} attempts: ${lastError?.message}`);
189
+ }
190
+ }