@ixo/common 1.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 (328) hide show
  1. package/.eslintrc.js +9 -0
  2. package/.prettierignore +3 -0
  3. package/.prettierrc.cjs +4 -0
  4. package/.turbo/turbo-build.log +4 -0
  5. package/CHANGELOG.md +76 -0
  6. package/README.md +245 -0
  7. package/dist/ai/checkpointer/index.d.ts +2 -0
  8. package/dist/ai/checkpointer/index.d.ts.map +1 -0
  9. package/dist/ai/checkpointer/index.js +2 -0
  10. package/dist/ai/checkpointer/index.js.map +1 -0
  11. package/dist/ai/index.d.ts +9 -0
  12. package/dist/ai/index.d.ts.map +1 -0
  13. package/dist/ai/index.js +9 -0
  14. package/dist/ai/index.js.map +1 -0
  15. package/dist/ai/models/index.d.ts +2 -0
  16. package/dist/ai/models/index.d.ts.map +1 -0
  17. package/dist/ai/models/index.js +2 -0
  18. package/dist/ai/models/index.js.map +1 -0
  19. package/dist/ai/models/openai.d.ts +10 -0
  20. package/dist/ai/models/openai.d.ts.map +1 -0
  21. package/dist/ai/models/openai.js +38 -0
  22. package/dist/ai/models/openai.js.map +1 -0
  23. package/dist/ai/models/openai.test.d.ts +2 -0
  24. package/dist/ai/models/openai.test.d.ts.map +1 -0
  25. package/dist/ai/models/openai.test.js +58 -0
  26. package/dist/ai/models/openai.test.js.map +1 -0
  27. package/dist/ai/nodes/create-fake-node.d.ts +2 -0
  28. package/dist/ai/nodes/create-fake-node.d.ts.map +1 -0
  29. package/dist/ai/nodes/create-fake-node.js +2 -0
  30. package/dist/ai/nodes/create-fake-node.js.map +1 -0
  31. package/dist/ai/nodes/find-docs/find-docs.prompt.d.ts +3 -0
  32. package/dist/ai/nodes/find-docs/find-docs.prompt.d.ts.map +1 -0
  33. package/dist/ai/nodes/find-docs/find-docs.prompt.js +61 -0
  34. package/dist/ai/nodes/find-docs/find-docs.prompt.js.map +1 -0
  35. package/dist/ai/nodes/find-docs/index.d.ts +3 -0
  36. package/dist/ai/nodes/find-docs/index.d.ts.map +1 -0
  37. package/dist/ai/nodes/find-docs/index.js +3 -0
  38. package/dist/ai/nodes/find-docs/index.js.map +1 -0
  39. package/dist/ai/nodes/find-docs/node.d.ts +17 -0
  40. package/dist/ai/nodes/find-docs/node.d.ts.map +1 -0
  41. package/dist/ai/nodes/find-docs/node.js +46 -0
  42. package/dist/ai/nodes/find-docs/node.js.map +1 -0
  43. package/dist/ai/nodes/generic-chat/generic-chat.node.d.ts +12 -0
  44. package/dist/ai/nodes/generic-chat/generic-chat.node.d.ts.map +1 -0
  45. package/dist/ai/nodes/generic-chat/generic-chat.node.js +34 -0
  46. package/dist/ai/nodes/generic-chat/generic-chat.node.js.map +1 -0
  47. package/dist/ai/nodes/generic-chat/generic-chat.prompt.d.ts +10 -0
  48. package/dist/ai/nodes/generic-chat/generic-chat.prompt.d.ts.map +1 -0
  49. package/dist/ai/nodes/generic-chat/generic-chat.prompt.js +58 -0
  50. package/dist/ai/nodes/generic-chat/generic-chat.prompt.js.map +1 -0
  51. package/dist/ai/nodes/generic-chat/index.d.ts +2 -0
  52. package/dist/ai/nodes/generic-chat/index.d.ts.map +1 -0
  53. package/dist/ai/nodes/generic-chat/index.js +2 -0
  54. package/dist/ai/nodes/generic-chat/index.js.map +1 -0
  55. package/dist/ai/nodes/index.d.ts +4 -0
  56. package/dist/ai/nodes/index.d.ts.map +1 -0
  57. package/dist/ai/nodes/index.js +4 -0
  58. package/dist/ai/nodes/index.js.map +1 -0
  59. package/dist/ai/semantic-router-factory/create-semantic-router.d.ts +7 -0
  60. package/dist/ai/semantic-router-factory/create-semantic-router.d.ts.map +1 -0
  61. package/dist/ai/semantic-router-factory/create-semantic-router.js +71 -0
  62. package/dist/ai/semantic-router-factory/create-semantic-router.js.map +1 -0
  63. package/dist/ai/semantic-router-factory/create-semantic-router.test.d.ts +2 -0
  64. package/dist/ai/semantic-router-factory/create-semantic-router.test.d.ts.map +1 -0
  65. package/dist/ai/semantic-router-factory/create-semantic-router.test.js +68 -0
  66. package/dist/ai/semantic-router-factory/create-semantic-router.test.js.map +1 -0
  67. package/dist/ai/semantic-router-factory/index.d.ts +4 -0
  68. package/dist/ai/semantic-router-factory/index.d.ts.map +1 -0
  69. package/dist/ai/semantic-router-factory/index.js +4 -0
  70. package/dist/ai/semantic-router-factory/index.js.map +1 -0
  71. package/dist/ai/semantic-router-factory/semantic-router-prompt.d.ts +2 -0
  72. package/dist/ai/semantic-router-factory/semantic-router-prompt.d.ts.map +1 -0
  73. package/dist/ai/semantic-router-factory/semantic-router-prompt.js +169 -0
  74. package/dist/ai/semantic-router-factory/semantic-router-prompt.js.map +1 -0
  75. package/dist/ai/semantic-router-factory/validate-routes.d.ts +2 -0
  76. package/dist/ai/semantic-router-factory/validate-routes.d.ts.map +1 -0
  77. package/dist/ai/semantic-router-factory/validate-routes.js +16 -0
  78. package/dist/ai/semantic-router-factory/validate-routes.js.map +1 -0
  79. package/dist/ai/tools/action-caller.d.ts +14 -0
  80. package/dist/ai/tools/action-caller.d.ts.map +1 -0
  81. package/dist/ai/tools/action-caller.js +12 -0
  82. package/dist/ai/tools/action-caller.js.map +1 -0
  83. package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.d.ts +25 -0
  84. package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.d.ts.map +1 -0
  85. package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.js +46 -0
  86. package/dist/ai/tools/ask-ixo-guru/ask-ixo-guru.js.map +1 -0
  87. package/dist/ai/tools/ask-ixo-guru/index.d.ts +2 -0
  88. package/dist/ai/tools/ask-ixo-guru/index.d.ts.map +1 -0
  89. package/dist/ai/tools/ask-ixo-guru/index.js +2 -0
  90. package/dist/ai/tools/ask-ixo-guru/index.js.map +1 -0
  91. package/dist/ai/tools/browser-tool-caller.d.ts +14 -0
  92. package/dist/ai/tools/browser-tool-caller.d.ts.map +1 -0
  93. package/dist/ai/tools/browser-tool-caller.js +12 -0
  94. package/dist/ai/tools/browser-tool-caller.js.map +1 -0
  95. package/dist/ai/tools/frontend-tool-caller.d.ts +10 -0
  96. package/dist/ai/tools/frontend-tool-caller.d.ts.map +1 -0
  97. package/dist/ai/tools/frontend-tool-caller.js +50 -0
  98. package/dist/ai/tools/frontend-tool-caller.js.map +1 -0
  99. package/dist/ai/tools/index.d.ts +11 -0
  100. package/dist/ai/tools/index.d.ts.map +1 -0
  101. package/dist/ai/tools/index.js +11 -0
  102. package/dist/ai/tools/index.js.map +1 -0
  103. package/dist/ai/tools/log-action-to-matrix.d.ts +13 -0
  104. package/dist/ai/tools/log-action-to-matrix.d.ts.map +1 -0
  105. package/dist/ai/tools/log-action-to-matrix.js +14 -0
  106. package/dist/ai/tools/log-action-to-matrix.js.map +1 -0
  107. package/dist/ai/tools/parser-action-tool.d.ts +8 -0
  108. package/dist/ai/tools/parser-action-tool.d.ts.map +1 -0
  109. package/dist/ai/tools/parser-action-tool.js +40 -0
  110. package/dist/ai/tools/parser-action-tool.js.map +1 -0
  111. package/dist/ai/tools/parser-browser-tool.d.ts +8 -0
  112. package/dist/ai/tools/parser-browser-tool.d.ts.map +1 -0
  113. package/dist/ai/tools/parser-browser-tool.js +38 -0
  114. package/dist/ai/tools/parser-browser-tool.js.map +1 -0
  115. package/dist/ai/tools/retriever-tool/index.d.ts +2 -0
  116. package/dist/ai/tools/retriever-tool/index.d.ts.map +1 -0
  117. package/dist/ai/tools/retriever-tool/index.js +2 -0
  118. package/dist/ai/tools/retriever-tool/index.js.map +1 -0
  119. package/dist/ai/tools/retriever-tool/retriever-tool.d.ts +18 -0
  120. package/dist/ai/tools/retriever-tool/retriever-tool.d.ts.map +1 -0
  121. package/dist/ai/tools/retriever-tool/retriever-tool.js +62 -0
  122. package/dist/ai/tools/retriever-tool/retriever-tool.js.map +1 -0
  123. package/dist/ai/tools/retriever-tool/retriever-tool.test.d.ts +2 -0
  124. package/dist/ai/tools/retriever-tool/retriever-tool.test.d.ts.map +1 -0
  125. package/dist/ai/tools/retriever-tool/retriever-tool.test.js +119 -0
  126. package/dist/ai/tools/retriever-tool/retriever-tool.test.js.map +1 -0
  127. package/dist/ai/tools/scrape-web-page.d.ts +7 -0
  128. package/dist/ai/tools/scrape-web-page.d.ts.map +1 -0
  129. package/dist/ai/tools/scrape-web-page.js +65 -0
  130. package/dist/ai/tools/scrape-web-page.js.map +1 -0
  131. package/dist/ai/tools/web-search-tool.d.ts +10 -0
  132. package/dist/ai/tools/web-search-tool.d.ts.map +1 -0
  133. package/dist/ai/tools/web-search-tool.js +30 -0
  134. package/dist/ai/tools/web-search-tool.js.map +1 -0
  135. package/dist/ai/types.d.ts +4 -0
  136. package/dist/ai/types.d.ts.map +1 -0
  137. package/dist/ai/types.js +2 -0
  138. package/dist/ai/types.js.map +1 -0
  139. package/dist/ai/utils/__tests__/chunk-arr.test.d.ts +2 -0
  140. package/dist/ai/utils/__tests__/chunk-arr.test.d.ts.map +1 -0
  141. package/dist/ai/utils/__tests__/chunk-arr.test.js +37 -0
  142. package/dist/ai/utils/__tests__/chunk-arr.test.js.map +1 -0
  143. package/dist/ai/utils/__tests__/doc-relevance-checker.test.d.ts +2 -0
  144. package/dist/ai/utils/__tests__/doc-relevance-checker.test.d.ts.map +1 -0
  145. package/dist/ai/utils/__tests__/doc-relevance-checker.test.js +80 -0
  146. package/dist/ai/utils/__tests__/doc-relevance-checker.test.js.map +1 -0
  147. package/dist/ai/utils/__tests__/doc-splitter.test.d.ts +2 -0
  148. package/dist/ai/utils/__tests__/doc-splitter.test.d.ts.map +1 -0
  149. package/dist/ai/utils/__tests__/doc-splitter.test.js +35 -0
  150. package/dist/ai/utils/__tests__/doc-splitter.test.js.map +1 -0
  151. package/dist/ai/utils/__tests__/filter-similarity-search-results.test.d.ts +2 -0
  152. package/dist/ai/utils/__tests__/filter-similarity-search-results.test.d.ts.map +1 -0
  153. package/dist/ai/utils/__tests__/filter-similarity-search-results.test.js +47 -0
  154. package/dist/ai/utils/__tests__/filter-similarity-search-results.test.js.map +1 -0
  155. package/dist/ai/utils/__tests__/json-to-yaml.test.d.ts +2 -0
  156. package/dist/ai/utils/__tests__/json-to-yaml.test.d.ts.map +1 -0
  157. package/dist/ai/utils/__tests__/json-to-yaml.test.js +63 -0
  158. package/dist/ai/utils/__tests__/json-to-yaml.test.js.map +1 -0
  159. package/dist/ai/utils/__tests__/stringify-docs.test.d.ts +2 -0
  160. package/dist/ai/utils/__tests__/stringify-docs.test.d.ts.map +1 -0
  161. package/dist/ai/utils/__tests__/stringify-docs.test.js +54 -0
  162. package/dist/ai/utils/__tests__/stringify-docs.test.js.map +1 -0
  163. package/dist/ai/utils/chunk-arr.d.ts +3 -0
  164. package/dist/ai/utils/chunk-arr.d.ts.map +1 -0
  165. package/dist/ai/utils/chunk-arr.js +13 -0
  166. package/dist/ai/utils/chunk-arr.js.map +1 -0
  167. package/dist/ai/utils/doc-relevance-checker.d.ts +10 -0
  168. package/dist/ai/utils/doc-relevance-checker.d.ts.map +1 -0
  169. package/dist/ai/utils/doc-relevance-checker.js +37 -0
  170. package/dist/ai/utils/doc-relevance-checker.js.map +1 -0
  171. package/dist/ai/utils/doc-splitter.d.ts +3 -0
  172. package/dist/ai/utils/doc-splitter.d.ts.map +1 -0
  173. package/dist/ai/utils/doc-splitter.js +20 -0
  174. package/dist/ai/utils/doc-splitter.js.map +1 -0
  175. package/dist/ai/utils/filter-similarity-search-results.d.ts +4 -0
  176. package/dist/ai/utils/filter-similarity-search-results.d.ts.map +1 -0
  177. package/dist/ai/utils/filter-similarity-search-results.js +11 -0
  178. package/dist/ai/utils/filter-similarity-search-results.js.map +1 -0
  179. package/dist/ai/utils/generate-questions-from-chunks.d.ts +15 -0
  180. package/dist/ai/utils/generate-questions-from-chunks.d.ts.map +1 -0
  181. package/dist/ai/utils/generate-questions-from-chunks.js +101 -0
  182. package/dist/ai/utils/generate-questions-from-chunks.js.map +1 -0
  183. package/dist/ai/utils/index.d.ts +11 -0
  184. package/dist/ai/utils/index.d.ts.map +1 -0
  185. package/dist/ai/utils/index.js +11 -0
  186. package/dist/ai/utils/index.js.map +1 -0
  187. package/dist/ai/utils/json-to-yaml.d.ts +2 -0
  188. package/dist/ai/utils/json-to-yaml.d.ts.map +1 -0
  189. package/dist/ai/utils/json-to-yaml.js +25 -0
  190. package/dist/ai/utils/json-to-yaml.js.map +1 -0
  191. package/dist/ai/utils/load-file.d.ts +3 -0
  192. package/dist/ai/utils/load-file.d.ts.map +1 -0
  193. package/dist/ai/utils/load-file.js +133 -0
  194. package/dist/ai/utils/load-file.js.map +1 -0
  195. package/dist/ai/utils/stringify-docs.d.ts +3 -0
  196. package/dist/ai/utils/stringify-docs.d.ts.map +1 -0
  197. package/dist/ai/utils/stringify-docs.js +6 -0
  198. package/dist/ai/utils/stringify-docs.js.map +1 -0
  199. package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.d.ts +35 -0
  200. package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.d.ts.map +1 -0
  201. package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.js +55 -0
  202. package/dist/ai/utils/transformGraphStateMessageToListMessageResponse.js.map +1 -0
  203. package/dist/ai/utils/verify-matrix-openId-token.d.ts +6 -0
  204. package/dist/ai/utils/verify-matrix-openId-token.d.ts.map +1 -0
  205. package/dist/ai/utils/verify-matrix-openId-token.js +36 -0
  206. package/dist/ai/utils/verify-matrix-openId-token.js.map +1 -0
  207. package/dist/index.d.ts +4 -0
  208. package/dist/index.d.ts.map +1 -0
  209. package/dist/index.js +4 -0
  210. package/dist/index.js.map +1 -0
  211. package/dist/services/env/env-service.test.d.ts +2 -0
  212. package/dist/services/env/env-service.test.d.ts.map +1 -0
  213. package/dist/services/env/env-service.test.js +99 -0
  214. package/dist/services/env/env-service.test.js.map +1 -0
  215. package/dist/services/env/env.service.d.ts +11 -0
  216. package/dist/services/env/env.service.d.ts.map +1 -0
  217. package/dist/services/env/env.service.js +42 -0
  218. package/dist/services/env/env.service.js.map +1 -0
  219. package/dist/services/env/index.d.ts +2 -0
  220. package/dist/services/env/index.d.ts.map +1 -0
  221. package/dist/services/env/index.js +2 -0
  222. package/dist/services/env/index.js.map +1 -0
  223. package/dist/services/index.d.ts +5 -0
  224. package/dist/services/index.d.ts.map +1 -0
  225. package/dist/services/index.js +5 -0
  226. package/dist/services/index.js.map +1 -0
  227. package/dist/services/memory-engine/memory-engine.service.d.ts +35 -0
  228. package/dist/services/memory-engine/memory-engine.service.d.ts.map +1 -0
  229. package/dist/services/memory-engine/memory-engine.service.js +295 -0
  230. package/dist/services/memory-engine/memory-engine.service.js.map +1 -0
  231. package/dist/services/memory-engine/types.d.ts +88 -0
  232. package/dist/services/memory-engine/types.d.ts.map +1 -0
  233. package/dist/services/memory-engine/types.js +2 -0
  234. package/dist/services/memory-engine/types.js.map +1 -0
  235. package/dist/services/session-manager/dto.d.ts +40 -0
  236. package/dist/services/session-manager/dto.d.ts.map +1 -0
  237. package/dist/services/session-manager/dto.js +170 -0
  238. package/dist/services/session-manager/dto.js.map +1 -0
  239. package/dist/services/session-manager/errors.d.ts +22 -0
  240. package/dist/services/session-manager/errors.d.ts.map +1 -0
  241. package/dist/services/session-manager/errors.js +41 -0
  242. package/dist/services/session-manager/errors.js.map +1 -0
  243. package/dist/services/session-manager/index.d.ts +4 -0
  244. package/dist/services/session-manager/index.d.ts.map +1 -0
  245. package/dist/services/session-manager/index.js +4 -0
  246. package/dist/services/session-manager/index.js.map +1 -0
  247. package/dist/services/session-manager/session-manager.service.d.ts +40 -0
  248. package/dist/services/session-manager/session-manager.service.d.ts.map +1 -0
  249. package/dist/services/session-manager/session-manager.service.js +251 -0
  250. package/dist/services/session-manager/session-manager.service.js.map +1 -0
  251. package/dist/utils/get-user-subscription.d.ts +21 -0
  252. package/dist/utils/get-user-subscription.d.ts.map +1 -0
  253. package/dist/utils/get-user-subscription.js +44 -0
  254. package/dist/utils/get-user-subscription.js.map +1 -0
  255. package/dist/utils/index.d.ts +2 -0
  256. package/dist/utils/index.d.ts.map +1 -0
  257. package/dist/utils/index.js +2 -0
  258. package/dist/utils/index.js.map +1 -0
  259. package/docs/ai-module.md +84 -0
  260. package/docs/services.md +168 -0
  261. package/docs/tools.md +325 -0
  262. package/jest.config.js +6 -0
  263. package/package.json +81 -0
  264. package/src/ai/checkpointer/index.ts +1 -0
  265. package/src/ai/index.ts +8 -0
  266. package/src/ai/models/index.ts +1 -0
  267. package/src/ai/models/openai.test.ts +72 -0
  268. package/src/ai/models/openai.ts +54 -0
  269. package/src/ai/nodes/create-fake-node.ts +1 -0
  270. package/src/ai/nodes/find-docs/find-docs.prompt.ts +61 -0
  271. package/src/ai/nodes/find-docs/index.ts +2 -0
  272. package/src/ai/nodes/find-docs/node.ts +83 -0
  273. package/src/ai/nodes/generic-chat/generic-chat.node.ts +58 -0
  274. package/src/ai/nodes/generic-chat/generic-chat.prompt.ts +66 -0
  275. package/src/ai/nodes/generic-chat/index.ts +1 -0
  276. package/src/ai/nodes/index.ts +3 -0
  277. package/src/ai/semantic-router-factory/create-semantic-router.test.ts +98 -0
  278. package/src/ai/semantic-router-factory/create-semantic-router.ts +136 -0
  279. package/src/ai/semantic-router-factory/index.ts +3 -0
  280. package/src/ai/semantic-router-factory/semantic-router-prompt.ts +168 -0
  281. package/src/ai/semantic-router-factory/validate-routes.ts +26 -0
  282. package/src/ai/tools/action-caller.ts +37 -0
  283. package/src/ai/tools/ask-ixo-guru/ask-ixo-guru.ts +73 -0
  284. package/src/ai/tools/ask-ixo-guru/index.ts +1 -0
  285. package/src/ai/tools/browser-tool-caller.ts +37 -0
  286. package/src/ai/tools/frontend-tool-caller.ts +86 -0
  287. package/src/ai/tools/index.ts +10 -0
  288. package/src/ai/tools/log-action-to-matrix.ts +30 -0
  289. package/src/ai/tools/parser-action-tool.ts +61 -0
  290. package/src/ai/tools/parser-browser-tool.ts +55 -0
  291. package/src/ai/tools/retriever-tool/index.ts +1 -0
  292. package/src/ai/tools/retriever-tool/retriever-tool.test.ts +156 -0
  293. package/src/ai/tools/retriever-tool/retriever-tool.ts +107 -0
  294. package/src/ai/tools/scrape-web-page.ts +75 -0
  295. package/src/ai/tools/web-search-tool.ts +38 -0
  296. package/src/ai/types.ts +6 -0
  297. package/src/ai/utils/__tests__/chunk-arr.test.ts +46 -0
  298. package/src/ai/utils/__tests__/doc-relevance-checker.test.ts +90 -0
  299. package/src/ai/utils/__tests__/doc-splitter.test.ts +42 -0
  300. package/src/ai/utils/__tests__/filter-similarity-search-results.test.ts +57 -0
  301. package/src/ai/utils/__tests__/json-to-yaml.test.ts +70 -0
  302. package/src/ai/utils/__tests__/stringify-docs.test.ts +61 -0
  303. package/src/ai/utils/chunk-arr.ts +13 -0
  304. package/src/ai/utils/doc-relevance-checker.ts +58 -0
  305. package/src/ai/utils/doc-splitter.ts +28 -0
  306. package/src/ai/utils/filter-similarity-search-results.ts +15 -0
  307. package/src/ai/utils/generate-questions-from-chunks.ts +114 -0
  308. package/src/ai/utils/index.ts +10 -0
  309. package/src/ai/utils/json-to-yaml.ts +32 -0
  310. package/src/ai/utils/load-file.ts +170 -0
  311. package/src/ai/utils/stringify-docs.ts +14 -0
  312. package/src/ai/utils/transformGraphStateMessageToListMessageResponse.ts +108 -0
  313. package/src/ai/utils/verify-matrix-openId-token.ts +46 -0
  314. package/src/index.ts +3 -0
  315. package/src/services/env/env-service.test.ts +153 -0
  316. package/src/services/env/env.service.ts +65 -0
  317. package/src/services/env/index.ts +1 -0
  318. package/src/services/index.ts +4 -0
  319. package/src/services/memory-engine/memory-engine.service.ts +486 -0
  320. package/src/services/memory-engine/types.ts +208 -0
  321. package/src/services/session-manager/dto.ts +120 -0
  322. package/src/services/session-manager/errors.ts +56 -0
  323. package/src/services/session-manager/index.ts +3 -0
  324. package/src/services/session-manager/session-manager.service.ts +405 -0
  325. package/src/utils/get-user-subscription.ts +84 -0
  326. package/src/utils/index.ts +1 -0
  327. package/tsconfig.json +16 -0
  328. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,153 @@
1
+ /* eslint-disable turbo/no-undeclared-env-vars -- test */
2
+ import z from 'zod';
3
+ import { EnvService } from './env.service.js';
4
+
5
+ describe('EnvService', () => {
6
+ // Store original process.env
7
+ const originalEnv = process.env;
8
+
9
+ beforeEach(() => {
10
+ // Reset process.env before each test
11
+ process.env = { ...originalEnv };
12
+ // Reset the singleton instance
13
+ // @ts-expect-error accessing private static for testing
14
+ EnvService.instance = null;
15
+ });
16
+
17
+ afterAll(() => {
18
+ // Restore original process.env
19
+ process.env = originalEnv;
20
+ });
21
+
22
+ describe('initialization', () => {
23
+ it('should initialize with valid environment variables', () => {
24
+ // Arrange
25
+ const schema = z.object({
26
+ TEST_VAR: z.string(),
27
+ TEST_NUMBER: z.coerce.number(),
28
+ });
29
+ process.env.TEST_VAR = 'test';
30
+ process.env.TEST_NUMBER = '123';
31
+
32
+ // Act
33
+ const envService = EnvService.initialize(schema);
34
+
35
+ // Assert
36
+ expect(envService.get('TEST_VAR')).toBe('test');
37
+ expect(envService.get('TEST_NUMBER')).toBe(123);
38
+ });
39
+
40
+ it('should throw error when required environment variables are missing', () => {
41
+ // Arrange
42
+ const schema = z.object({
43
+ MISSING_VAR: z.string(),
44
+ });
45
+
46
+ // Act & Assert
47
+ expect(() => EnvService.initialize(schema)).toThrow();
48
+ });
49
+
50
+ it('should maintain singleton instance', () => {
51
+ // Arrange
52
+ const schema = z.object({
53
+ TEST_VAR: z.string(),
54
+ });
55
+ process.env.TEST_VAR = 'test';
56
+
57
+ // Act
58
+ const instance1 = EnvService.initialize(schema);
59
+ const instance2 = EnvService.initialize(schema);
60
+
61
+ // Assert
62
+ expect(instance1).toBe(instance2);
63
+ });
64
+ });
65
+
66
+ describe('getInstance', () => {
67
+ it('should throw error when accessing getInstance before initialization', () => {
68
+ // Act & Assert
69
+ expect(() => EnvService.getInstance()).toThrow(
70
+ 'EnvService must be initialized with a schema first',
71
+ );
72
+ });
73
+
74
+ it('should return initialized instance', () => {
75
+ // Arrange
76
+ const schema = z.object({
77
+ TEST_VAR: z.string(),
78
+ });
79
+ process.env.TEST_VAR = 'test';
80
+ const initializedInstance = EnvService.initialize(schema);
81
+
82
+ // Act
83
+ const instance = EnvService.getInstance();
84
+
85
+ // Assert
86
+ expect(instance).toBe(initializedInstance);
87
+ });
88
+ });
89
+
90
+ describe('environment access', () => {
91
+ it('should return all environment variables', () => {
92
+ // Arrange
93
+ const schema = z.object({
94
+ TEST_VAR1: z.string(),
95
+ TEST_VAR2: z.string(),
96
+ });
97
+ process.env.TEST_VAR1 = 'value1';
98
+ process.env.TEST_VAR2 = 'value2';
99
+ const envService = EnvService.initialize(schema);
100
+
101
+ // Act
102
+ const allEnv = envService.getAll();
103
+
104
+ // Assert
105
+ expect(allEnv).toEqual({
106
+ TEST_VAR1: 'value1',
107
+ TEST_VAR2: 'value2',
108
+ });
109
+ });
110
+
111
+ it('should handle transformed values correctly', () => {
112
+ // Arrange
113
+ const schema = z.object({
114
+ NUMBER: z.string().transform(Number),
115
+ BOOLEAN: z.string().transform((val) => val === 'true'),
116
+ });
117
+ process.env.NUMBER = '42';
118
+ process.env.BOOLEAN = 'true';
119
+ const envService = EnvService.initialize(schema);
120
+
121
+ // Act & Assert
122
+ expect(envService.get('NUMBER')).toBe(42);
123
+ expect(envService.get('BOOLEAN')).toBe(true);
124
+ });
125
+ });
126
+
127
+ describe('validation', () => {
128
+ it('should validate enum values', () => {
129
+ // Arrange
130
+ const schema = z.object({
131
+ NODE_ENV: z.enum(['development', 'production', 'test']),
132
+ });
133
+ process.env.NODE_ENV = 'development';
134
+
135
+ // Act
136
+ const envService = EnvService.initialize(schema);
137
+
138
+ // Assert
139
+ expect(envService.get('NODE_ENV')).toBe('development');
140
+ });
141
+
142
+ it('should throw on invalid enum values', () => {
143
+ // Arrange
144
+ const schema = z.object({
145
+ NODE_ENV: z.enum(['development', 'production', 'test']),
146
+ });
147
+ process.env.NODE_ENV = 'invalid';
148
+
149
+ // Act & Assert
150
+ expect(() => EnvService.initialize(schema)).toThrow();
151
+ });
152
+ });
153
+ });
@@ -0,0 +1,65 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-return -- f*/
2
+ import { Logger } from '@ixo/logger';
3
+ import { config } from 'dotenv';
4
+ import z from 'zod';
5
+
6
+ config();
7
+
8
+ export class EnvService<T extends z.ZodType> {
9
+ private static instance: EnvService<z.ZodType> | null = null;
10
+ private readonly validatedEnv: z.infer<T>;
11
+
12
+ private constructor(schema: T, onError?: (error: z.ZodError) => void) {
13
+ try {
14
+ // Parse and validate environment variables
15
+ this.validatedEnv = schema.parse(process.env) as z.infer<T>;
16
+ } catch (error) {
17
+ if (error instanceof z.ZodError) {
18
+ if (onError) {
19
+ onError(error);
20
+ return;
21
+ }
22
+ Logger.error('Environment validation failed:' + error.message);
23
+ }
24
+ throw error;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Initialize the environment service with a schema
30
+ * @param schema - Zod schema to validate environment variables
31
+ * @returns EnvService instance
32
+ */
33
+ public static initialize<S extends z.ZodType>(schema: S): EnvService<S> {
34
+ if (EnvService.instance === null) {
35
+ EnvService.instance = new EnvService(schema);
36
+ }
37
+ return EnvService.instance as EnvService<S>;
38
+ }
39
+
40
+ /**
41
+ * Get the singleton instance of EnvService
42
+ * @throws Error if service hasn't been initialized
43
+ */
44
+ public static getInstance<S extends z.ZodType>(): EnvService<S> {
45
+ if (EnvService.instance === null) {
46
+ throw new Error('EnvService must be initialized with a schema first');
47
+ }
48
+ return EnvService.instance as EnvService<S>;
49
+ }
50
+
51
+ /**
52
+ * Get all validated environment variables
53
+ */
54
+ public getAll(): z.infer<T> {
55
+ return this.validatedEnv;
56
+ }
57
+
58
+ /**
59
+ * Get a specific environment variable
60
+ * @param key - The key of the environment variable
61
+ */
62
+ public get<K extends keyof z.infer<T>>(key: K): z.infer<T>[K] {
63
+ return this.validatedEnv[key];
64
+ }
65
+ }
@@ -0,0 +1 @@
1
+ export { EnvService } from './env.service.js';
@@ -0,0 +1,4 @@
1
+ export * from './env/index.js';
2
+ export * from './memory-engine/memory-engine.service.js';
3
+ export * from './memory-engine/types.js';
4
+ export * from './session-manager/index.js';
@@ -0,0 +1,486 @@
1
+ import { Logger } from '@ixo/logger';
2
+ import type {
3
+ SearchEnhancedRequest,
4
+ SearchEnhancedResponse,
5
+ UserContextData,
6
+ } from './types.js';
7
+
8
+ export class MemoryEngineService {
9
+ private readonly QUERY_TIMEOUT_MS = 2500; // 2.5 seconds per query
10
+
11
+ constructor(
12
+ private readonly memoryEngineUrl: string,
13
+ private readonly memoryServiceApiKey: string,
14
+ ) {}
15
+
16
+ /**
17
+ * Wraps a promise with a timeout, returning fallback value if timeout is exceeded
18
+ */
19
+ private async withTimeout<T>(
20
+ promise: Promise<T>,
21
+ timeoutMs: number,
22
+ fallback: T,
23
+ ): Promise<T> {
24
+ return Promise.race([
25
+ promise,
26
+ new Promise<T>((resolve) =>
27
+ setTimeout(() => resolve(fallback), timeoutMs),
28
+ ),
29
+ ]);
30
+ }
31
+
32
+ /**
33
+ * Gather user context from Memory Engine by executing 6 parallel queries
34
+ */
35
+ async gatherUserContext(params: {
36
+ oracleDid: string;
37
+ userDid: string;
38
+ roomId: string;
39
+ }): Promise<UserContextData> {
40
+ const { oracleDid, userDid, roomId } = params;
41
+
42
+ Logger.info(
43
+ `[MemoryEngineService] Gathering user context for oracle: ${oracleDid}, room: ${roomId}`,
44
+ );
45
+
46
+ try {
47
+ // Execute all 6 queries in parallel with timeouts using Promise.allSettled
48
+ const results = await Promise.allSettled([
49
+ this.withTimeout(
50
+ this.queryIdentity(oracleDid, userDid, roomId),
51
+ this.QUERY_TIMEOUT_MS,
52
+ undefined,
53
+ ),
54
+ this.withTimeout(
55
+ this.queryWork(oracleDid, userDid, roomId),
56
+ this.QUERY_TIMEOUT_MS,
57
+ undefined,
58
+ ),
59
+ this.withTimeout(
60
+ this.queryGoals(oracleDid, userDid, roomId),
61
+ this.QUERY_TIMEOUT_MS,
62
+ undefined,
63
+ ),
64
+ this.withTimeout(
65
+ this.queryInterests(oracleDid, userDid, roomId),
66
+ this.QUERY_TIMEOUT_MS,
67
+ undefined,
68
+ ),
69
+ this.withTimeout(
70
+ this.queryRelationships(oracleDid, userDid, roomId),
71
+ this.QUERY_TIMEOUT_MS,
72
+ undefined,
73
+ ),
74
+ this.withTimeout(
75
+ this.queryRecent(oracleDid, userDid, roomId),
76
+ this.QUERY_TIMEOUT_MS,
77
+ undefined,
78
+ ),
79
+ ]);
80
+
81
+ // Extract results from Promise.allSettled outcomes
82
+ const identity =
83
+ results[0].status === 'fulfilled' ? results[0].value : undefined;
84
+ const work =
85
+ results[1].status === 'fulfilled' ? results[1].value : undefined;
86
+ const goals =
87
+ results[2].status === 'fulfilled' ? results[2].value : undefined;
88
+ const interests =
89
+ results[3].status === 'fulfilled' ? results[3].value : undefined;
90
+ const relationships =
91
+ results[4].status === 'fulfilled' ? results[4].value : undefined;
92
+ const recent =
93
+ results[5].status === 'fulfilled' ? results[5].value : undefined;
94
+
95
+ // Log any failures
96
+ results.forEach((result, index) => {
97
+ if (result.status === 'rejected') {
98
+ Logger.warn(
99
+ `[MemoryEngineService] Query ${index} failed:`,
100
+ result.reason,
101
+ );
102
+ }
103
+ });
104
+
105
+ return {
106
+ identity,
107
+ work,
108
+ goals,
109
+ interests,
110
+ relationships,
111
+ recent,
112
+ };
113
+ } catch (error) {
114
+ Logger.error(
115
+ '[MemoryEngineService] Failed to gather user context:',
116
+ error,
117
+ );
118
+ // Return empty context on error
119
+ return {};
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Query 1: User Identity & Attributes
125
+ */
126
+ private async queryIdentity(
127
+ oracleDid: string,
128
+ userDid: string,
129
+ roomId: string,
130
+ ): Promise<SearchEnhancedResponse | undefined> {
131
+ const request: SearchEnhancedRequest = {
132
+ oracle_dids: [oracleDid],
133
+ query:
134
+ 'username and nickname and age user identity traits values personality characteristics communication style beliefs preferences',
135
+ strategy: 'balanced',
136
+ max_facts: 10,
137
+ max_entities: 6,
138
+ max_episodes: 3,
139
+ max_communities: 2,
140
+ knowledge_level: 'both',
141
+ search_filters: {
142
+ node_labels: [
143
+ 'Person',
144
+ 'Trait',
145
+ 'Value',
146
+ 'Identity',
147
+ 'Attribute',
148
+ 'Emotion',
149
+ 'Belief',
150
+ 'CommunicationStyle',
151
+ ],
152
+ invalid_at: [[{ date: null, comparison_operator: 'IS NULL' }]],
153
+ },
154
+ };
155
+
156
+ return this.executeQuery(request, userDid, oracleDid, roomId);
157
+ }
158
+
159
+ /**
160
+ * Query 2: Work Context
161
+ */
162
+ private async queryWork(
163
+ oracleDid: string,
164
+ userDid: string,
165
+ roomId: string,
166
+ ): Promise<SearchEnhancedResponse | undefined> {
167
+ const request: SearchEnhancedRequest = {
168
+ oracle_dids: [oracleDid],
169
+ query:
170
+ 'work job career projects skills organization employment role responsibilities expertise',
171
+ strategy: 'balanced',
172
+ max_facts: 10,
173
+ max_entities: 6,
174
+ max_episodes: 3,
175
+ max_communities: 2,
176
+ knowledge_level: 'both',
177
+ search_filters: {
178
+ node_labels: [
179
+ 'Job',
180
+ 'Project',
181
+ 'Organization',
182
+ 'Skill',
183
+ 'Tool',
184
+ 'Expertise',
185
+ 'Task',
186
+ ],
187
+ edge_types: [
188
+ 'EmployedAt',
189
+ 'WorksOn',
190
+ 'Manages',
191
+ 'Uses',
192
+ 'ExpertiseIn',
193
+ 'WorksWith',
194
+ ],
195
+ invalid_at: [[{ date: null, comparison_operator: 'IS NULL' }]],
196
+ },
197
+ };
198
+
199
+ return this.executeQuery(request, userDid, oracleDid, roomId);
200
+ }
201
+
202
+ /**
203
+ * Query 3: Goals & Habits
204
+ */
205
+ private async queryGoals(
206
+ oracleDid: string,
207
+ userDid: string,
208
+ roomId: string,
209
+ ): Promise<SearchEnhancedResponse | undefined> {
210
+ const request: SearchEnhancedRequest = {
211
+ oracle_dids: [oracleDid],
212
+ query:
213
+ 'goals aspirations objectives milestones habits routines patterns achievements progress',
214
+ strategy: 'balanced',
215
+ max_facts: 8,
216
+ max_entities: 4,
217
+ max_episodes: 3,
218
+ max_communities: 1,
219
+ knowledge_level: 'both',
220
+ search_filters: {
221
+ node_labels: [
222
+ 'Goal',
223
+ 'Milestone',
224
+ 'Habit',
225
+ 'Routine',
226
+ 'Pattern',
227
+ 'LearningGoal',
228
+ ],
229
+ edge_types: ['Pursuing', 'Achieved', 'Practices', 'Motivates'],
230
+ invalid_at: [[{ date: null, comparison_operator: 'IS NULL' }]],
231
+ },
232
+ };
233
+
234
+ return this.executeQuery(request, userDid, oracleDid, roomId);
235
+ }
236
+
237
+ /**
238
+ * Query 4: Interests & Preferences
239
+ */
240
+ private async queryInterests(
241
+ oracleDid: string,
242
+ userDid: string,
243
+ roomId: string,
244
+ ): Promise<SearchEnhancedResponse | undefined> {
245
+ const request: SearchEnhancedRequest = {
246
+ oracle_dids: [oracleDid],
247
+ query:
248
+ 'interests hobbies passions preferences likes dislikes expertise topics content',
249
+ strategy: 'balanced',
250
+ max_facts: 8,
251
+ max_entities: 4,
252
+ max_episodes: 3,
253
+ max_communities: 1,
254
+ knowledge_level: 'both',
255
+ search_filters: {
256
+ node_labels: [
257
+ 'Interest',
258
+ 'Hobby',
259
+ 'Preference',
260
+ 'Product',
261
+ 'Content',
262
+ 'Expertise',
263
+ 'Resource',
264
+ ],
265
+ edge_types: [
266
+ 'Prefers',
267
+ 'Likes',
268
+ 'Dislikes',
269
+ 'InterestedIn',
270
+ 'ExpertiseIn',
271
+ ],
272
+ invalid_at: [[{ date: null, comparison_operator: 'IS NULL' }]],
273
+ },
274
+ };
275
+
276
+ return this.executeQuery(request, userDid, oracleDid, roomId);
277
+ }
278
+
279
+ /**
280
+ * Query 5: Relationships
281
+ */
282
+ private async queryRelationships(
283
+ oracleDid: string,
284
+ userDid: string,
285
+ roomId: string,
286
+ ): Promise<SearchEnhancedResponse | undefined> {
287
+ const request: SearchEnhancedRequest = {
288
+ oracle_dids: [oracleDid],
289
+ query:
290
+ 'relationships people connections social network colleagues friends family contacts',
291
+ strategy: 'balanced',
292
+ max_facts: 6,
293
+ max_entities: 6,
294
+ max_episodes: 2,
295
+ max_communities: 1,
296
+ knowledge_level: 'both',
297
+ search_filters: {
298
+ node_labels: ['Person', 'Group'],
299
+ edge_types: [
300
+ 'Knows',
301
+ 'WorksWith',
302
+ 'MemberOf',
303
+ 'Influences',
304
+ 'Supports',
305
+ 'RelatesTo',
306
+ ],
307
+ invalid_at: [[{ date: null, comparison_operator: 'IS NULL' }]],
308
+ },
309
+ };
310
+
311
+ return this.executeQuery(request, userDid, oracleDid, roomId);
312
+ }
313
+
314
+ /**
315
+ * Query 6: Recent Context
316
+ */
317
+ private async queryRecent(
318
+ oracleDid: string,
319
+ userDid: string,
320
+ roomId: string,
321
+ ): Promise<SearchEnhancedResponse | undefined> {
322
+ // Calculate date 90 days ago for recent context
323
+ const ninetyDaysAgo = new Date();
324
+ ninetyDaysAgo.setDate(ninetyDaysAgo.getDate() - 90);
325
+ const dateString = ninetyDaysAgo.toISOString();
326
+
327
+ const request: SearchEnhancedRequest = {
328
+ oracle_dids: [oracleDid],
329
+ query:
330
+ 'recent conversations messages discussions activities updates interactions',
331
+ strategy: 'recent_memory',
332
+ max_facts: 8,
333
+ max_entities: 4,
334
+ max_episodes: 6,
335
+ max_communities: 2,
336
+ knowledge_level: 'both',
337
+ search_filters: {
338
+ created_at: [[{ date: dateString, comparison_operator: '>=' }]],
339
+ },
340
+ };
341
+
342
+ return this.executeQuery(request, userDid, oracleDid, roomId);
343
+ }
344
+
345
+ /**
346
+ * Process conversation history by sending messages to the Memory Engine
347
+ */
348
+ async processConversationHistory({
349
+ messages,
350
+ userDid,
351
+ oracleDid,
352
+ roomId,
353
+ }: {
354
+ messages: Array<{
355
+ content: string;
356
+ role_type: 'user' | 'assistant' | 'system';
357
+ role?: string;
358
+ name?: string;
359
+ source_description?: string;
360
+ }>;
361
+ userDid: string;
362
+ oracleDid: string;
363
+ roomId: string;
364
+ }): Promise<{ success: boolean }> {
365
+ if (!userDid) {
366
+ Logger.warn(
367
+ `[MemoryEngineService] No user DID provided, skipping conversation processing`,
368
+ );
369
+ return { success: false };
370
+ }
371
+ if (!oracleDid) {
372
+ Logger.warn(
373
+ `[MemoryEngineService] No oracle did provided, skipping conversation processing`,
374
+ );
375
+ return { success: false };
376
+ }
377
+ if (!roomId) {
378
+ Logger.warn(
379
+ `[MemoryEngineService] No room id provided, skipping conversation processing`,
380
+ );
381
+ return { success: false };
382
+ }
383
+ if (!messages || messages.length === 0) {
384
+ Logger.info(
385
+ `[MemoryEngineService] No messages to process for room ${roomId}`,
386
+ );
387
+ return { success: true };
388
+ }
389
+
390
+ try {
391
+ const response = await fetch(`${this.memoryEngineUrl}/messages`, {
392
+ method: 'POST',
393
+ headers: {
394
+ 'x-user-did': userDid,
395
+ 'x-oracle-did': oracleDid,
396
+ 'x-room-id': roomId,
397
+ 'x-service-api-key': this.memoryServiceApiKey,
398
+ 'Content-Type': 'application/json',
399
+ },
400
+ body: JSON.stringify({ messages }),
401
+ });
402
+
403
+ if (!response.ok) {
404
+ const errorText = await response.text();
405
+ Logger.warn(
406
+ `[MemoryEngineService] Memory Engine conversation processing failed (${response.status}): ${errorText}`,
407
+ );
408
+ return { success: false };
409
+ }
410
+
411
+ Logger.info(
412
+ `[MemoryEngineService] Successfully processed ${messages.length} messages for room ${roomId}`,
413
+ );
414
+ return { success: true };
415
+ } catch (error) {
416
+ Logger.error(
417
+ `[MemoryEngineService] Failed to process conversation history for room ${roomId}:`,
418
+ error,
419
+ );
420
+ return { success: false };
421
+ }
422
+ }
423
+
424
+ /**
425
+ * Execute a search query against the Memory Engine API
426
+ */
427
+ private async executeQuery(
428
+ request: SearchEnhancedRequest,
429
+ userDid: string,
430
+ oracleDid: string,
431
+ roomId: string,
432
+ ): Promise<SearchEnhancedResponse | undefined> {
433
+ if (!userDid) {
434
+ Logger.warn(
435
+ `[MemoryEngineService] No user DID provided, skipping query "${request.query}"`,
436
+ );
437
+ return undefined;
438
+ }
439
+ if (!oracleDid) {
440
+ Logger.warn(
441
+ `[MemoryEngineService] No oracle did provided, skipping query "${request.query}"`,
442
+ );
443
+ return undefined;
444
+ }
445
+ if (!roomId) {
446
+ Logger.warn(
447
+ `[MemoryEngineService] No room id provided, skipping query "${request.query}"`,
448
+ );
449
+ return undefined;
450
+ }
451
+
452
+ try {
453
+ const response = await fetch(`${this.memoryEngineUrl}/search-enhanced`, {
454
+ method: 'POST',
455
+ headers: {
456
+ 'x-user-did': userDid,
457
+ 'x-oracle-did': oracleDid,
458
+ 'x-room-id': roomId,
459
+ 'x-service-api-key': this.memoryServiceApiKey,
460
+ 'Content-Type': 'application/json',
461
+ },
462
+ body: JSON.stringify(request),
463
+ });
464
+
465
+ if (!response.ok) {
466
+ const errorText = await response.text();
467
+ Logger.warn(
468
+ `[MemoryEngineService] Memory Engine query failed (${response.status}): ${errorText}`,
469
+ );
470
+ return undefined;
471
+ }
472
+
473
+ const result = (await response.json()) as SearchEnhancedResponse;
474
+ Logger.info(
475
+ `[MemoryEngineService] Query "${request.query}" returned ${result.total_results.facts} facts, ${result.total_results.entities} entities`,
476
+ );
477
+ return result;
478
+ } catch (error) {
479
+ Logger.error(
480
+ `[MemoryEngineService] Failed to execute query "${request.query}":`,
481
+ error,
482
+ );
483
+ return undefined;
484
+ }
485
+ }
486
+ }