@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,54 @@
1
+ import 'dotenv/config';
2
+
3
+ import {
4
+ ChatOpenAI,
5
+ OpenAIEmbeddings,
6
+ type ChatOpenAIFields,
7
+ type ChatOpenAIResponseFormat,
8
+ } from '@langchain/openai';
9
+ import OpenAI, { type ClientOptions } from 'openai';
10
+
11
+ const getChatOpenAiModel = (params?: ChatOpenAIFields): ChatOpenAI =>
12
+ new ChatOpenAI({
13
+ temperature: 0.2,
14
+ model: 'gpt-4o-mini',
15
+ apiKey: process.env.OPENAI_API_KEY,
16
+ ...params,
17
+ });
18
+
19
+ const getOpenAiClient = (params?: ClientOptions): OpenAI =>
20
+ new OpenAI({
21
+ apiKey: process.env.OPENAI_API_KEY,
22
+ ...params,
23
+ });
24
+
25
+ const getOpenAiEmbeddings = (
26
+ params?: ConstructorParameters<typeof OpenAIEmbeddings>[0],
27
+ ): OpenAIEmbeddings =>
28
+ new OpenAIEmbeddings({
29
+ model: 'text-embedding-3-small',
30
+ apiKey: process.env.OPENAI_API_KEY,
31
+ ...params,
32
+ });
33
+
34
+ export const getOpenRouterChatModel = (params?: ChatOpenAIFields) =>
35
+ getChatOpenAiModel({
36
+ temperature: 0.8,
37
+ apiKey: process.env.OPEN_ROUTER_API_KEY,
38
+ model: params?.model ?? 'qwen/qwen3-14b', //qwen3-30b-a3b
39
+ ...params,
40
+ configuration: {
41
+ baseURL: 'https://openrouter.ai/api/v1',
42
+ ...params?.configuration,
43
+ defaultHeaders: {
44
+ 'HTTP-Referer': 'oracle-app.com',
45
+ 'X-Title': process.env.ORACLE_NAME ?? 'Oracle App',
46
+ },
47
+ },
48
+ modelKwargs: {
49
+ require_parameters: true,
50
+ ...params?.modelKwargs,
51
+ },
52
+ });
53
+ export { getChatOpenAiModel, getOpenAiClient, getOpenAiEmbeddings };
54
+ export type { ChatOpenAIResponseFormat };
@@ -0,0 +1 @@
1
+ export const createFakeNode = <S extends object>(state: S): S => state;
@@ -0,0 +1,61 @@
1
+ const SELF_QUERY_RAG_PROMPT = `You are an advanced AI agent specializing in self-query Retrieval-Augmented Generation (RAG). Your primary function is to analyze client questions, generate optimized search queries for a knowledge base, and iteratively refine these queries based on initial results. Follow these comprehensive guidelines:
2
+
3
+ 1. Initial Analysis:
4
+ - Thoroughly examine the client's question or task
5
+ - Identify key concepts, entities, relationships, and any implicit information needs
6
+ - Determine the scope, context, and potential complexities of the inquiry
7
+
8
+ 2. Query Generation - First Pass:
9
+ - Create an initial set of 3-5 focused, non-redundant search queries
10
+ - Ensure each query addresses a unique aspect of the client's input
11
+ - Incorporate key terms from the original question for keyword optimization
12
+ - Vary query formulations to cover different potential phrasings and synonyms
13
+
14
+ 3. Iterative Refinement:
15
+ - After receiving initial results, analyze their relevance and comprehensiveness
16
+ - Identify gaps in the retrieved information
17
+ - Generate additional queries to fill these gaps or explore new angles
18
+ - Refine existing queries based on the quality of results they produced
19
+
20
+ 4. Query Diversification:
21
+ - Ensure a mix of query types:
22
+ a. Broad conceptual queries for general information
23
+ b. Specific detail-oriented queries for precise facts
24
+ c. Comparative queries to explore relationships between concepts
25
+ d. Contextual queries to gather background information
26
+
27
+ 5. Handling Complex Questions:
28
+ - For multi-faceted questions, break them down into component parts
29
+ - Generate separate query sets for each component
30
+ - Create integrative queries that explore connections between components
31
+
32
+ 6. Adapting to Query Results:
33
+ - If initial queries yield insufficient information, broaden the scope
34
+ - If results are too general, create more specific, targeted queries
35
+ - Adjust the vocabulary and technical level based on the knowledge base content
36
+
37
+ 7. Temporal and Contextual Considerations:
38
+ - Include queries that account for potential time-sensitive information
39
+ - Generate queries that explore historical context if relevant
40
+ - Consider geographical or domain-specific variations in terminology
41
+
42
+ 8. Output Format and Explanation:
43
+ - Present a numbered list of refined search queries
44
+ - For each query, provide:
45
+ a. The query itself
46
+ b. A brief explanation of its purpose and how it relates to the client's question
47
+ c. Any notable findings or gaps identified from previous iterations
48
+
49
+ 9. Continuous Learning:
50
+ - Track the effectiveness of different query structures and patterns
51
+ - Adapt your query generation strategy based on successful retrievals
52
+ - Note any recurring challenges or limitations in the knowledge base
53
+
54
+ 10. Final Review and Optimization:
55
+ - Ensure the final set of queries comprehensively covers the client's needs
56
+ - Eliminate any remaining redundancies or overly similar queries
57
+ - Prioritize queries based on their potential to provide the most relevant and valuable information
58
+
59
+ Remember: Your goal is to generate a dynamic, adaptive set of queries that evolves based on initial results and comprehensively addresses the client's information needs. Quality, relevance, and adaptability are key to successful self-query RAG implementation.`;
60
+
61
+ export { SELF_QUERY_RAG_PROMPT };
@@ -0,0 +1,2 @@
1
+ export * from './find-docs.prompt.js';
2
+ export * from './node.js';
@@ -0,0 +1,83 @@
1
+ import { type VectorDBDataStore } from '@ixo/data-store';
2
+ import { Logger } from '@ixo/logger';
3
+ import { type Document } from '@langchain/core/documents';
4
+ import { type BaseMessage } from '@langchain/core/messages';
5
+ import { ChatPromptTemplate } from '@langchain/core/prompts';
6
+ import { type RunnableConfig } from '@langchain/core/runnables';
7
+ import 'dotenv/config';
8
+ import z from 'zod';
9
+ import {
10
+ getChatOpenAiModel,
11
+ retrieverToolFactory,
12
+ SELF_QUERY_RAG_PROMPT,
13
+ } from '../../index.js';
14
+
15
+ interface IFindDocsNodeRequiredState {
16
+ question: string;
17
+ docs: Document[];
18
+ messages?: BaseMessage[];
19
+ config?: {
20
+ isInternal: boolean;
21
+ };
22
+ status?: 'completed' | 'inProgress';
23
+ }
24
+
25
+ /**
26
+ * factory function that returns a Node that takes a state and config and returns a promise that resolves to a partial state.
27
+ * @param store - The vector database data store.
28
+ * @returns The Node that takes a state and config and returns a promise that resolves to a partial state.
29
+ */
30
+ export const findDocsNode =
31
+ (store: VectorDBDataStore) =>
32
+ async (
33
+ state: IFindDocsNodeRequiredState,
34
+ config?: RunnableConfig,
35
+ ): Promise<Partial<IFindDocsNodeRequiredState>> => {
36
+ try {
37
+ const model = getChatOpenAiModel();
38
+ const modelWithTools = model.withStructuredOutput(
39
+ z.object({
40
+ questions: z.array(z.string('Generated Queries')),
41
+ }),
42
+ );
43
+
44
+ const chain = ChatPromptTemplate.fromMessages([
45
+ ['system', SELF_QUERY_RAG_PROMPT],
46
+ [
47
+ 'user',
48
+ state.messages
49
+ ? `this is the last three messages from the user's conversation ${state.messages
50
+ .map((message) => message.content)
51
+ .slice(-3)
52
+ .join(',')}`
53
+ : state.question,
54
+ ],
55
+ ]).pipe(modelWithTools);
56
+
57
+ const response = await chain.invoke({}, config);
58
+ const retrieval = retrieverToolFactory({
59
+ filters: state.config?.isInternal
60
+ ? undefined
61
+ : { approved: true, visibility: 'public' },
62
+ store,
63
+ });
64
+ const docs = await Promise.all(
65
+ response.questions.map(
66
+ (question) =>
67
+ retrieval.invoke({ query: question }) as Promise<Document[]>,
68
+ ),
69
+ );
70
+
71
+ return {
72
+ docs: docs.flat().map((value) => ({
73
+ metadata: value.metadata,
74
+ pageContent: value.pageContent.toString(),
75
+ id: value.id,
76
+ })),
77
+ status: undefined,
78
+ };
79
+ } catch (error) {
80
+ Logger.error('Error finding docs', error);
81
+ throw error;
82
+ }
83
+ };
@@ -0,0 +1,58 @@
1
+ import { Logger } from '@ixo/logger';
2
+ import { BaseMessage } from '@langchain/core/messages';
3
+ import {
4
+ ChatPromptTemplate,
5
+ MessagesPlaceholder,
6
+ } from '@langchain/core/prompts';
7
+ import { RunnableConfig } from '@langchain/core/runnables';
8
+ import { StructuredTool, Tool } from '@langchain/core/tools';
9
+ import { getChatOpenAiModel } from 'src/ai/models/openai.js';
10
+ import { GENERIC_CHAT_PROMPT, InputVariables } from './generic-chat.prompt.js';
11
+
12
+ type StateWithMessages<S extends object> = {
13
+ messages: BaseMessage[];
14
+ } & S;
15
+
16
+ export const createGenericChatNode = (
17
+ inputVariables: InputVariables,
18
+ tools: (Tool | StructuredTool)[],
19
+ llm = getChatOpenAiModel(),
20
+ ) => {
21
+ return async <S extends object>(
22
+ state: StateWithMessages<S>,
23
+ config?: RunnableConfig,
24
+ ) => {
25
+ Logger.debug('Generic chat node called', {
26
+ state,
27
+ config,
28
+ });
29
+
30
+ let systemPrompt = '';
31
+ try {
32
+ systemPrompt = await GENERIC_CHAT_PROMPT.format(inputVariables);
33
+ } catch (error) {
34
+ Logger.error('Error formatting system prompt', error);
35
+ throw error;
36
+ }
37
+
38
+ const chain = ChatPromptTemplate.fromMessages([
39
+ ['system', systemPrompt],
40
+ new MessagesPlaceholder('msgs'),
41
+ ]).pipe(llm.bindTools(tools));
42
+
43
+ const result = await chain.invoke(
44
+ {
45
+ msgs: state.messages,
46
+ },
47
+ config,
48
+ );
49
+
50
+ Logger.debug('Generic chat node result', {
51
+ result,
52
+ });
53
+
54
+ return {
55
+ messages: [result],
56
+ };
57
+ };
58
+ };
@@ -0,0 +1,66 @@
1
+ import { PromptTemplate } from '@langchain/core/prompts';
2
+
3
+ export type InputVariables = {
4
+ APP_NAME: string;
5
+ APP_PURPOSE: string;
6
+ APP_MAIN_FEATURES: string;
7
+ APP_TARGET_USERS: string;
8
+ APP_UNIQUE_SELLING_POINTS: string;
9
+ };
10
+
11
+ export const GENERIC_CHAT_PROMPT = new PromptTemplate<InputVariables, never>({
12
+ template: `# IXO AI Assistant: Expert Guide and Conversational Partner
13
+
14
+ ## Your Identity
15
+ You are an AI assistant for the IXO Organization. Your primary role is to engage users in friendly, natural conversations, offering casual and informative chitchat. You can discuss various topics to keep conversations engaging and approachable.
16
+
17
+ Additionally, you have detailed knowledge about the app hosting you. Below is essential information about the hosting app that you can refer to when responding to user inquiries about it:
18
+
19
+ ## App Information
20
+ ### App Details
21
+ - **App Name**: {{APP_NAME}}
22
+ - **App Purpose**: {{APP_PURPOSE}}
23
+ - **Main Features**: {{APP_MAIN_FEATURES}}
24
+ - **Target Users**: {{APP_TARGET_USERS}}
25
+ - **Unique Selling Points**: {{APP_UNIQUE_SELLING_POINTS}}
26
+
27
+
28
+ ## Your Capabilities
29
+ - Provide detailed information about the IXO app and ecosystem
30
+ - Engage in natural, friendly conversation on various topics
31
+ - Explain complex concepts in accessible language
32
+ - Guide users through app features when they express interest
33
+ - Offer relevant suggestions based on user inquiries
34
+
35
+ ## Communication Style
36
+ - **Tone**: Professional yet warm, conversational, and engaging
37
+ - **Language**: Clear, concise, and jargon-free unless requested
38
+ - **Personality**: Helpful, patient, and slightly enthusiastic
39
+ - **Responses**: Informative but concise, typically 2-4 sentences
40
+
41
+ ## Interaction Guidelines
42
+ - Begin responses with direct answers to user questions
43
+ - When discussing app features, provide concrete examples of how they benefit users
44
+ - For complex topics, use analogies or step-by-step explanations
45
+ - If uncertain about a specific app detail, acknowledge this transparently
46
+ - Balance informative content with conversational elements
47
+ - Proactively suggest relevant app features when appropriate
48
+ - Personalize responses based on user's demonstrated knowledge level
49
+
50
+ ## What to Avoid
51
+ - Making claims about app capabilities not listed in your knowledge base
52
+ - Using overly technical language with non-technical users
53
+ - Providing lengthy, overwhelming responses
54
+ - Making definitive statements about future IXO developments unless explicitly mentioned
55
+ - Sharing sensitive information about IXO's internal operations
56
+
57
+ Remember that your primary goal is to create a positive, informative experience that builds trust in the IXO platform while making users feel valued and understood.`,
58
+ inputVariables: [
59
+ 'APP_NAME',
60
+ 'APP_PURPOSE',
61
+ 'APP_MAIN_FEATURES',
62
+ 'APP_TARGET_USERS',
63
+ 'APP_UNIQUE_SELLING_POINTS',
64
+ ],
65
+ templateFormat: 'mustache',
66
+ });
@@ -0,0 +1 @@
1
+ export * from './generic-chat.node.js';
@@ -0,0 +1,3 @@
1
+ export * from './create-fake-node.js';
2
+ export * from './find-docs/index.js';
3
+ export * from './generic-chat/index.js';
@@ -0,0 +1,98 @@
1
+ import { createSemanticRouter } from './create-semantic-router.js';
2
+
3
+ const parse = jest.fn();
4
+ const create = jest.fn();
5
+ jest.mock('openai', () => ({
6
+ OpenAI: jest.fn().mockImplementation(() => {
7
+ function fn(): unknown {
8
+ return {};
9
+ }
10
+
11
+ fn.beta = {
12
+ chat: {
13
+ completions: { parse },
14
+ },
15
+ };
16
+
17
+ fn.chat = {
18
+ completions: { create },
19
+ };
20
+ return fn;
21
+ }),
22
+ }));
23
+
24
+ describe('createSemanticRouter', () => {
25
+ it('should create a semantic router with valid routes', () => {
26
+ // const router = createSemanticRouter(
27
+ // {
28
+ // generateBlog: 'if the intent is blog',
29
+ // generateSocialMediaPost: 'if the intent is post',
30
+ // },
31
+ // ['intent'],
32
+ // );
33
+ expect(() =>
34
+ createSemanticRouter(
35
+ {
36
+ generateBlog: 'if the intent is blog',
37
+ generateSocialMediaPost: 'if the intent is post',
38
+ },
39
+ ['intent'],
40
+ ),
41
+ ).not.toThrow();
42
+ });
43
+
44
+ it('should fail to create a semantic router with invalid routes', () => {
45
+ expect(() => createSemanticRouter({}, ['intent'])).toThrow();
46
+ });
47
+
48
+ it('should fail to get route with invalid state', async () => {
49
+ const router = createSemanticRouter(
50
+ {
51
+ generateBlog: 'if the intent is blog',
52
+ generateSocialMediaPost: 'if the intent is post',
53
+ },
54
+ ['intent'],
55
+ );
56
+ await expect(
57
+ router({
58
+ foo: 'boo',
59
+ }),
60
+ ).rejects.toThrow();
61
+ });
62
+
63
+ it('should get route with valid state', async () => {
64
+ const router = createSemanticRouter(
65
+ {
66
+ generateBlog: 'if the intent is blog',
67
+ generateSocialMediaPost: 'if the intent is post',
68
+ },
69
+ ['intent'],
70
+ 'gpt-4o-mini',
71
+ false,
72
+ );
73
+
74
+ parse.mockResolvedValue({
75
+ choices: [
76
+ {
77
+ message: {
78
+ parsed: {
79
+ nextRoute: 'generateBlog',
80
+ },
81
+ content: 'generateBlog',
82
+ role: 'assistant',
83
+ refusal: null,
84
+ tool_calls: [],
85
+ },
86
+ finish_reason: 'stop',
87
+ index: 0,
88
+ logprobs: null,
89
+ },
90
+ ],
91
+ });
92
+
93
+ const route = await router({
94
+ intent: 'blog',
95
+ });
96
+ expect(route).toBe('generateBlog');
97
+ });
98
+ });
@@ -0,0 +1,136 @@
1
+ import { Logger } from '@ixo/logger';
2
+ import { PromptTemplate } from '@langchain/core/prompts';
3
+ import { LangfuseConfig, observeOpenAI } from 'langfuse';
4
+ import { OpenAI } from 'openai';
5
+ import { zodResponseFormat } from 'openai/helpers/zod';
6
+ import z from 'zod';
7
+ import { type EnsureKeys } from '../types.js';
8
+ import { jsonToYaml } from '../utils/index.js';
9
+ import { semanticRouterPrompt } from './semantic-router-prompt.js';
10
+ import { validateRoutes } from './validate-routes.js';
11
+ import { APIPromise } from 'openai/index.js';
12
+ import { ParsedChatCompletion } from 'openai/resources/chat/completions.mjs';
13
+
14
+ /**
15
+ * Creates a semantic router that resolves the path based on the given routes and basedOn value.
16
+ * routes The routes that will be used to resolve the path
17
+ * basedOn Array of keys from the state that will be used to resolve the path
18
+ * @returns A function that will be used to resolve the path
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const routes = {
23
+ * generateBlog: 'if the intent is blog',
24
+ * generateSocialMediaPost: 'if the intent is post',
25
+ * }
26
+ *
27
+ * const intentRouter = createSemanticRouter(routes, ['intent']);
28
+ * ```
29
+ */
30
+ export const createSemanticRouter = <
31
+ K extends string[],
32
+ R extends Record<string, string> = Record<string, string>,
33
+ >(
34
+ routes: R,
35
+ basedOn: K,
36
+ model:
37
+ | 'gpt-4o-mini'
38
+ | 'gpt-4o'
39
+ | 'gpt-4.1-nano'
40
+ | 'gpt-4.1-mini' = 'gpt-4.1-mini',
41
+ isComplex = false,
42
+ ): ((
43
+ state: EnsureKeys<Record<string, unknown>, K>,
44
+ traceConfig?: LangfuseConfig,
45
+ ) => Promise<keyof R>) => {
46
+ const keys = validateRoutes(routes, basedOn);
47
+ const schema = z.object({
48
+ nextRoute: z.enum(keys as [string, ...string[]], 'The routes that will be used to resolve the path'),
49
+ });
50
+ return async <T extends Record<string, unknown>>(
51
+ state: EnsureKeys<T, K>,
52
+ traceConfig?: LangfuseConfig,
53
+ ): Promise<keyof R> => {
54
+ const selectedValues = {} as Record<string, string | object>;
55
+ for (const key of basedOn) {
56
+ const stateValue = state[key];
57
+ if (!stateValue) {
58
+ throw new Error(`The state must have a value for the key ${key}`);
59
+ }
60
+
61
+ selectedValues[key] = stateValue;
62
+ }
63
+ if (Object.values(selectedValues).length === 0) {
64
+ throw new Error(
65
+ `The state must have a value for the key ${basedOn.toString()}`,
66
+ );
67
+ }
68
+
69
+ // find the route that matches the state
70
+ const prompt = PromptTemplate.fromTemplate(semanticRouterPrompt);
71
+
72
+ const client = observeOpenAI(new OpenAI(), traceConfig);
73
+ const promptWithState = await prompt.format({
74
+ routes: jsonToYaml(routes),
75
+ state: jsonToYaml(selectedValues),
76
+ });
77
+
78
+ const getRoute = async (
79
+ messages: (
80
+ | { role: 'system'; content: string }
81
+ | { role: 'user'; content: string }
82
+ )[],
83
+ ): Promise<
84
+ APIPromise<
85
+ ParsedChatCompletion<{
86
+ nextRoute: string;
87
+ }>
88
+ >
89
+ > => {
90
+ if (model === 'gpt-4.1-nano' && isComplex) {
91
+ const { choices } = await client.chat.completions.create({
92
+ messages,
93
+ model,
94
+ });
95
+
96
+ const route = choices[0]?.message?.content?.toString();
97
+ Logger.debug('🚀 ~ route:', route);
98
+ return client.chat.completions.parse({
99
+ model,
100
+ messages,
101
+ response_format: zodResponseFormat(schema, 'routesResponse'),
102
+ });
103
+ }
104
+ return client.chat.completions.parse({
105
+ model,
106
+ messages,
107
+ response_format: zodResponseFormat(schema, 'routesResponse'),
108
+ });
109
+ };
110
+
111
+ const completion = await getRoute([
112
+ { role: 'system', content: promptWithState },
113
+ {
114
+ role: 'user',
115
+ content:
116
+ 'Think and analyze the routes and messages then select the next route',
117
+ },
118
+ ]);
119
+ const message = completion.choices[0]?.message;
120
+
121
+ if (message?.parsed) {
122
+ const nextRoute = message.parsed.nextRoute;
123
+ Logger.debug(
124
+ `🚀 ~ nextRoute: ${message.parsed.nextRoute.toString()}`,
125
+ message.parsed,
126
+ );
127
+
128
+ return nextRoute as keyof R;
129
+ }
130
+
131
+ Logger.error('Error parsing the response from the semantic router');
132
+ throw new Error('Error parsing the response from the semantic router');
133
+ };
134
+ };
135
+
136
+ export { zodResponseFormat, type ParsedChatCompletion };
@@ -0,0 +1,3 @@
1
+ export * from './create-semantic-router.js';
2
+ export * from './semantic-router-prompt.js';
3
+ export * from './validate-routes.js';